026f54428d
1f03775f4f
introduced arbitrary tag identification which removed the
variables this conditional checks.
193 lines
4.5 KiB
Bash
193 lines
4.5 KiB
Bash
#!/bin/bash
|
|
|
|
shopt -s extglob
|
|
|
|
m4_include(common)
|
|
|
|
write_source() {
|
|
local src=$1 spec= label= uuid= comment=()
|
|
|
|
label=$(lsblk -rno LABEL "$1" 2>/dev/null)
|
|
uuid=$(lsblk -rno UUID "$1" 2>/dev/null)
|
|
|
|
# bind mounts do not have a UUID!
|
|
|
|
case $bytag in
|
|
'')
|
|
[[ $uuid ]] && comment=("UUID=$uuid")
|
|
[[ $label ]] && comment+=("LABEL=$label")
|
|
;;
|
|
LABEL)
|
|
spec=$label
|
|
[[ $uuid ]] && comment=("$src" "UUID=$uuid")
|
|
;;
|
|
UUID)
|
|
spec=$uuid
|
|
comment=("$src")
|
|
[[ $label ]] && comment+=("LABEL=$label")
|
|
;;
|
|
*)
|
|
[[ $uuid ]] && comment=("$1" "UUID=$uuid")
|
|
[[ $label ]] && comment+=("LABEL=$label")
|
|
[[ $bytag ]] && spec=$(lsblk -rno "$bytag" "$1" 2>/dev/null)
|
|
;;
|
|
esac
|
|
|
|
[[ $comment ]] && printf '# %s\n' "${comment[*]}"
|
|
|
|
if [[ $spec ]]; then
|
|
printf '%-20s' "$bytag=$spec"
|
|
else
|
|
printf '%-20s' "$(mangle "$src")"
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
usage: ${0##*/} [options] root
|
|
|
|
Options:
|
|
-L Use labels for source identifiers (shortcut for -t LABEL)
|
|
-p Avoid printing pseudofs mounts
|
|
-t TAG Use TAG for source identifiers
|
|
-U Use UUIDs for source identifiers (shortcut for -t UUID)
|
|
|
|
-h Print this help message
|
|
|
|
genfstab generates output suitable for addition to an fstab file based on the
|
|
devices mounted under the mountpoint specified by the given root.
|
|
|
|
EOF
|
|
}
|
|
|
|
if [[ -z $1 || $1 = @(-h|--help) ]]; then
|
|
usage
|
|
exit $(( $# ? 0 : 1 ))
|
|
fi
|
|
|
|
while getopts ':Lpt:U' flag; do
|
|
case $flag in
|
|
L)
|
|
bytag=LABEL
|
|
;;
|
|
U)
|
|
bytag=UUID
|
|
;;
|
|
p)
|
|
nopseudofs=1
|
|
;;
|
|
t)
|
|
bytag=${OPTARG^^}
|
|
;;
|
|
:)
|
|
die '%s: option requires an argument -- '\''%s'\' "${0##*/}" "$OPTARG"
|
|
;;
|
|
?)
|
|
die '%s: invalid option -- '\''%s'\' "${0##*/}" "$OPTARG"
|
|
;;
|
|
esac
|
|
done
|
|
shift $(( OPTIND - 1 ))
|
|
|
|
(( $# )) || die "No root directory specified"
|
|
root=$1; shift
|
|
|
|
if ! mountpoint -q "$root"; then
|
|
die "$root is not a mountpoint"
|
|
fi
|
|
|
|
# handle block devices
|
|
findmnt -Recvruno SOURCE,TARGET,FSTYPE,OPTIONS,FSROOT "$root" |
|
|
while read -r src target fstype opts fsroot; do
|
|
# default 5th and 6th columns
|
|
dump=0 pass=2
|
|
|
|
src=$(unmangle "$src")
|
|
target=$(unmangle "$target")
|
|
target=${target#$root}
|
|
|
|
if (( !foundroot )) && findmnt "$src" "$root" >/dev/null; then
|
|
# this is root. we can't possibly have more than one...
|
|
pass=1 foundroot=1
|
|
fi
|
|
|
|
if fstype_is_pseudofs "$fstype" && (( nopseudofs )); then
|
|
continue
|
|
fi
|
|
|
|
# if there's no fsck tool available, then only pass=0 makes sense.
|
|
if ! fstype_has_fsck "$fstype"; then
|
|
pass=0
|
|
fi
|
|
|
|
if [[ $fsroot != / ]]; then
|
|
if [[ $fstype = btrfs ]]; then
|
|
opts+=,subvol=${fsroot#/}
|
|
else
|
|
# it's a bind mount
|
|
src=$(findmnt -funcevo TARGET "$src")$fsroot
|
|
if [[ $src -ef $target ]]; then
|
|
# hrmm, this is weird. we're probably looking at a file or directory
|
|
# that was bound into a chroot from the host machine. Ignore it,
|
|
# because this won't actually be a valid mount. Worst case, the user
|
|
# just re-adds it.
|
|
continue
|
|
fi
|
|
fstype=none
|
|
opts+=,bind
|
|
pass=0
|
|
fi
|
|
fi
|
|
|
|
# filesystem quirks
|
|
case $fstype in
|
|
fuseblk)
|
|
# well-behaved FUSE filesystems will report themselves as fuse.$fstype.
|
|
# this is probably NTFS-3g, but let's just make sure.
|
|
if ! newtype=$(lsblk -no FSTYPE "$src") || [[ -z $newtype ]]; then
|
|
# avoid blanking out fstype, leading to an invalid fstab
|
|
error 'Failed to derive real filesystem type for FUSE device on %s' "$target"
|
|
else
|
|
fstype=$newtype
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# write one line
|
|
write_source "$src"
|
|
printf '\t%-10s' "/$(mangle "${target#/}")" "$fstype" "$opts"
|
|
printf '\t%s %s' "$dump" "$pass"
|
|
printf '\n\n'
|
|
done
|
|
|
|
# handle swaps devices
|
|
{
|
|
# ignore header
|
|
read
|
|
|
|
while read -r device type _ _ prio; do
|
|
options=defaults
|
|
if [[ $prio != -1 ]]; then
|
|
options+=,pri=$prio
|
|
fi
|
|
|
|
# skip files marked deleted by the kernel
|
|
[[ $device = *'\\040(deleted)' ]] && continue
|
|
|
|
if [[ $type = file ]]; then
|
|
printf '%-20s' "$device"
|
|
elif [[ $device = /dev/dm-+([0-9]) ]]; then
|
|
# device mapper doesn't allow characters we need to worry
|
|
# about being mangled, and it does the escaping of dashes
|
|
# for us in sysfs.
|
|
write_source "$(dm_name_for_devnode "$device")"
|
|
else
|
|
write_source "$(unmangle "$device")"
|
|
fi
|
|
|
|
printf '\t%-10s\t%-10s\t%-10s\t0 0\n\n' 'none' 'swap' "$options"
|
|
done
|
|
} </proc/swaps
|
|
|
|
# vim: et ts=2 sw=2 ft=sh:
|