commit c0507cea20b8d3a6d23f84938f18ac237a428be0
Author: Cem Keylan <cem@ckyln.com>
Date: Mon, 15 Jun 2020 16:49:00 +0300
initial commit
Diffstat:
A | LICENSE | | | 21 | +++++++++++++++++++++ |
A | README | | | 14 | ++++++++++++++ |
A | genfstab | | | 145 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | genfstab.8 | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 225 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (C) 2020 Cem Keylan
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README b/README
@@ -0,0 +1,14 @@
+GENFSTAB
+--------------------------------------------------------------------------------
+
+Simplified POSIX sh implementation of the Arch Linux tool[1] with the same name.
+This implementation (with the exception of a single function) is pure shell,
+the only dependency is 'readlink' which can be found in most base utility
+implementations.
+
+Pseudo-filesystem identification is better on this implementation for complex
+environments. Other than this, syntax and output is identical. If you are
+using a simple PC, you will not notice any difference.
+
+
+[1]: https://github.com/archlinux/arch-install-scripts
diff --git a/genfstab b/genfstab
@@ -0,0 +1,145 @@
+#!/bin/sh
+# fstab generator similar in function to the Arch Linux tool that can be found
+# on arch-install-scripts.
+#
+# Copyright (C) 2020 Cem Keylan <cem@ckyln.com>
+
+out() { printf '%s\n' "$@" ;}
+msg() { out "$@" >&2 ;}
+die() { [ "$1" ] && msg "$@"; exit 1 ;}
+
+find_tag() {
+ # Function to find the tag of the given device. This eliminates the
+ # requirement for programs such as lsblk/blkid.
+ #
+ # usage: find_tag /dev/sdx1
+
+ # If no identifiers are given, return with the plain partition name.
+ [ "$ident" ] || { out "$1"; return 0 ;}
+
+ [ -d "${tagdir:=/dev/disk/by-$(printf "$ident" | tr '[:upper:]' '[:lower:]')}" ] ||
+ die "Directory '$dir' doesn't exist"
+
+ for file in "$tagdir/"*; do
+ [ "$(readlink -f "$file")" = "$1" ] || continue
+ tag="$ident=${file##*/}"
+ break
+ done
+
+ # If the tag couldn't be found for some reason, fallback to the default
+ # name instead of printing empty.
+ out "${tag:-$1}"
+}
+
+readlink_sh() (
+ # This function changes directory to the given path in order to find the
+ # real location of the given directory. We are doing this in a subshell
+ # so that we return to our previous location. Sadly, we cannot use this
+ # function on 'find_tag()' as this only works for resolving directory paths.
+ cd -P "$1" || return 1
+ printf '%s\n' "$PWD"
+)
+
+ispseudo() {
+ # This function checks for pseudo-filesystems and returns 0 if it is.
+ # There is no definitive way to know every single pseudo-filesystems,
+ # there might be some issues with this function.
+ #
+ # If the filesystem is not a directory or a tag, we will assume that
+ # it is a pseudofs. The only exception I have noticed so far are loop
+ # devices.
+ case "$fs" in /dev/loop*) return 0 ;; /*|*=*) ;; *) return 0; esac
+
+ # These are the most common types of pseudo filesystems.
+ case "$type" in squashfs|proc|sysfs|tmpfs|devtmpfs|devpts|debugfs) return 0; esac
+
+ # As for the last check, we will look up /proc/filesystems which are
+ # filesystems known by the running kernel.
+ while read -r ps filesystem; do
+ [ "$filesystem" = "$type" ] || continue
+ [ "$ps" ] && return 0
+ return 1
+ done < /proc/filesystems
+
+ # If we still haven't come up with an answer, let's assume that this is NOT
+ # a pseudo-filesystem.
+ return 1
+}
+
+usage() {
+ out "usage: ${0##*/} [-f filter] [-t tag] [-LpPU] [root]" "" \
+ " Options:" \
+ " -f <filter> Restrict output to mountpoints matching the prefix FILTER" \
+ " -L Use labels for source identifiers (Shortcut for -t LABEL)" \
+ " -p Exclude pseudofs mounts (default behaviour)" \
+ " -P Include pseudofs mounts" \
+ " -t <tag> Use tag for source identifiers (should be one of: LABEL," \
+ " UUID, PARTLABEL, PARTUUID)" \
+ " -U Use UUIDs for source identifiers (Shortcut for -t UUID)" "" \
+ " -h Print this help message" "" \
+ "${0##*/} generates output suitable for addition to an fstab file based on the" \
+ "devices mounted under the mountpoint specified by the given root." "" \
+ "This implementation of genfstab is from <https://git.ckyln.com/genfstab>"
+ exit 0
+}
+
+
+# Print help information
+case " $* " in *' --help '*|*' -h '*) usage; esac
+
+ident='' filter='' pseudo=0
+while getopts PpLUf:t: flag; do
+ case $flag in
+ h) usage ;;
+ P) pseudo=1 ;;
+ p) pseudo=0 ;;
+ L) ident=LABEL ;;
+ U) ident=UUID ;;
+ f) [ -d "$OPTARG" ] || die "Not a directory '$OPTARG'"
+ filter=$(readlink_sh "$OPTARG") ;;
+ t) case "$OPTARG" in
+ LABEL|UUID|PARTLABEL|PARTUUID) ident=$OPTARG ;;
+ *) die "Unknown identifier '$OPTARG'"; esac
+ ;;
+ ?) die
+ esac
+done
+shift $(( OPTIND - 1 ))
+
+[ "$1" ] && {
+ [ -d "$1" ] || die "Not a directory '$1'"
+ root="$(readlink_sh "$1")"
+}
+
+# It's a good thing that /proc/mounts and fstab share the same syntax. We will
+# always be defining dump and pass ourselves since they will always be '0 0' on
+# /proc/mounts.
+while read -r fs dir type options _; do
+ if ispseudo; then
+ pass=0
+ [ "$pseudo" != 1 ] && continue
+ [ "$ident" ] && out "# $fs"
+ else
+ case "$dir" in "${root:-/}"*) ;; *) continue; esac
+ [ "$ident" ] && out "# $fs"
+ fs="$(find_tag "$fs")"
+ [ "$root" ] && dir=/${dir#$root}
+
+ case "$dir" in /) pass=1 ;; *) pass=2; esac
+ fi
+ [ "$filter" ] && case "$dir" in ${filter%/}*) ;; *) continue; esac
+
+ printf '%-23s %-15s %-15s %-15s %s %s\n\n' "$fs" "${dir:-/}" "$type" "$options" "${dump:=0}" "$pass"
+done < /proc/mounts
+
+# Now print out mounted swaps. I am really not quite sure how swaps work as I
+# don't personally use them. If you have a better approach to this, please let
+# me know.
+while read -r file _; do
+ [ -f "/$file" ] || continue
+ [ "$root" ] && {
+ case "$file" in "$root/"*) ;; *) continue; esac
+ file=/${file#$root}
+ }
+ printf '%-23s %-15s %-15s %-15s %s %s\n\n' "$file" none swap sw 0 0
+done < /proc/swaps
diff --git a/genfstab.8 b/genfstab.8
@@ -0,0 +1,45 @@
+.TH GENFSTAB 8 "2020-06-15" "Cem Keylan" "System Administration"
+.SH NAME
+genfstab - generate fstab-compatible output
+.SH SYNOPSIS
+genfstab [-f filter] [-t tag] [-LpPU] [root]
+.SH DESCRIPTION
+genfstab is a utility that detects mounted filesystems and swaps, and outputs
+information that can be parsed by fstab(5). This is a POSIX sh implementation
+of the Arch Linux tool with the same name.
+.SH OPTIONS
+.PP
+\fB-f\fR <filter>
+.RS 4
+Restrict output to mountpoints matching the prefix FILTER
+.RE
+.PP
+\fB-L\fR
+.RS 4
+Use labels for source identifiers (shortcut for -t LABEL)
+.RE
+.PP
+\fB-p\fR
+.RS 4
+Exclude pseudofs mounts (default behaviour)
+.RE
+.PP
+\fB-P\fR
+.RS 4
+Include pseudofs mounts
+.RE
+.PP
+\fB-t\fR <tag>
+.RS 4
+Use tag for source identifiers (should be one of: LABEL, UUID, PARTLABEL, PARTUUID)
+.RE
+.PP
+\fB-U\fR
+.RS 4
+Use UUIDs for source identifiers (shortcut for \fI-t UUID\fR)
+.RE
+.SH AUTHOR
+Cem Keylan <cem@ckyln\&.com>
+.SH SEE ALSO
+.sp
+\fBfstab\fR(5)