|  | #!/bin/bash -f | 
|  | # SPDX-License-Identifier: GPL-2.0 | 
|  | # | 
|  | # Copyright (c) 2024 Oracle.  All Rights Reserved. | 
|  | # Author: Darrick J. Wong <djwong@kernel.org> | 
|  | # | 
|  |  | 
|  | OPTS="" | 
|  | USAGE="Usage: xfs_property [-V] [mountpoint|device|file] [list [-v]|get name...|set name=value...|remove name...]" | 
|  |  | 
|  | # Try to find a loop device associated with a file.  We only want to return | 
|  | # one loopdev (multiple loop devices can attach to a single file) so we grab | 
|  | # the last line and return it if it's actually a block device. | 
|  | try_find_loop_dev_for_file() { | 
|  | local x="$(losetup -O NAME -j "$1" 2> /dev/null | tail -n 1)" | 
|  | test -b "${x}" && echo "${x}" | 
|  | } | 
|  |  | 
|  | while getopts "V" c | 
|  | do | 
|  | case $c in | 
|  | V)	xfs_io -p xfs_info -V | 
|  | status=$? | 
|  | exit ${status} | 
|  | ;; | 
|  | *)	echo "${USAGE}" 1>&2 | 
|  | exit 2 | 
|  | ;; | 
|  | esac | 
|  | done | 
|  | set -- extra "$@" | 
|  | shift $OPTIND | 
|  |  | 
|  | if [ $# -lt 2 ]; then | 
|  | echo "${USAGE}" 1>&2 | 
|  | exit 2 | 
|  | fi | 
|  |  | 
|  | target="$1" | 
|  | shift | 
|  | subcommand="$1" | 
|  | shift | 
|  |  | 
|  | db_args=() | 
|  | io_args=() | 
|  |  | 
|  | case "$subcommand" in | 
|  | "list") | 
|  | vparam= | 
|  | if [ $# -eq 1 ] && [ "$1" = "-v" ]; then | 
|  | vparam=" -v" | 
|  | fi | 
|  | db_args+=('-c' "attr_list -Z${vparam}") | 
|  | io_args+=('-c' "listfsprops${vparam}") | 
|  | ;; | 
|  | "get"|"remove"|"set") | 
|  | for arg in "$@"; do | 
|  | db_args+=('-c' "attr_${subcommand} -Z ${arg/=/ }") | 
|  | io_args+=('-c' "${subcommand}fsprops ${arg}") | 
|  | done | 
|  | ;; | 
|  | *) | 
|  | echo "${USAGE}" 1>&2 | 
|  | exit 2 | 
|  | esac | 
|  |  | 
|  | # See if we can map the arg to a loop device | 
|  | loopdev="$(try_find_loop_dev_for_file "${target}")" | 
|  | test -n "${loopdev}" && target="${loopdev}" | 
|  |  | 
|  | # If we find a mountpoint for the device, do a live query; otherwise try | 
|  | # reading the fs with xfs_db. | 
|  | if mountpt="$(findmnt -t xfs -f -n -o TARGET "${target}" 2> /dev/null)"; then | 
|  | exec xfs_io -p xfs_property "${io_args[@]}" "${mountpt}" | 
|  | else | 
|  | exec xfs_db -p xfs_property -x -c 'path /' "${db_args[@]}" "${target}" | 
|  | fi |