114 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
| #!/bin/sh
 | |
| # Copyright (C) 2023  Umorpha Systems
 | |
| # SPDX-License-Identifier: AGPL-3.0-or-later
 | |
| 
 | |
| # This script is intended to work both in an initramfs and as a
 | |
| # developer-friendly tool on a real OS.  Therefore, it has very few
 | |
| # dependencies and must be tolerant of different implementations:
 | |
| #
 | |
| #  - sh     (bash or busybox)
 | |
| #  - getopt (busybox or util-linux)
 | |
| #  - mkdir  (busybox or coreutils)
 | |
| #  - mount  (util-linux)
 | |
| 
 | |
| set -eu
 | |
| 
 | |
| usage() {
 | |
| 	echo "Usage: $0 OPTIONS"
 | |
| 	echo "Mount devices using the Umorpha overlay-partition scheme."
 | |
| 	echo
 | |
| 	echo "OPTIONS:"
 | |
| 	echo "  -h, --help                             Show this help text"
 | |
| 	echo "      --root SPEC             (required) The read-only root device ant its mount arguments"
 | |
| 	echo "      --overlay SPEC          (required) The writable overlay device ant its mount arguments"
 | |
| 	echo "      --boot SPEC             (optional) The device to mount at /boot"
 | |
| 	echo "      --basedir DIR           (required) Scratch directory to mount the root device and the overlay device"
 | |
| 	echo "      --final-mountpoint DIR  (optional) Where to mount the overlayfs (default: \${basedir}/mnt"
 | |
| 	echo
 | |
| 	echo "A SPEC is of the form"
 | |
| 	echo "    DEVICE[:[FSTYPE][:OPTS]]"
 | |
| 	echo "If FSTYPE value isn't present, or is empty, then \`auto\` is used."
 | |
| }
 | |
| 
 | |
| main() {
 | |
| 	mode=run
 | |
| 	if O=$(getopt -n "${0##*/}" -l help,root:,overlay:,boot:,basedir:,final-mountpoint: -o h -- "$@"); then
 | |
| 		eval "set -- $O"
 | |
| 		while true; do
 | |
| 			case "$1" in
 | |
| 				--help|-h) usage; exit 0;;
 | |
| 				--root) root_all=$2; shift 2;;
 | |
| 				--overlay) overlay_all=$2; shift 2;;
 | |
| 				--boot) boot_all=$2; shift 2;;
 | |
| 				--basedir) basedir=$2; shift 2;;
 | |
| 				--final-mountpoint) union_mnt=$2; shift 2;;
 | |
| 				--) shift; break;;
 | |
| 			esac
 | |
| 		done
 | |
| 		if [[ "$#" -gt 0 ]]; then
 | |
| 			echo >&2 "${0##*/}: unexpected positional arguments: $*"
 | |
| 			mode=error
 | |
| 		fi
 | |
| 		if [[ -z "${root_all:-}" ]]; then
 | |
| 			echo >&2 "${0##*/}: missing required --root flag"
 | |
| 			mode=error
 | |
| 		fi
 | |
| 		if [[ -z "${overlay_all:-}" ]]; then
 | |
| 			echo >&2 "${0##*/}: missing required --overlay flag"
 | |
| 			mode=error
 | |
| 		fi
 | |
| 		if [[ -z "${basedir:-}" ]]; then
 | |
| 			echo >&2 "${0##*/}: missing required --basedir flag"
 | |
| 			mode=error
 | |
| 		fi
 | |
| 	else
 | |
| 		mode=error
 | |
| 	fi
 | |
| 	if [[ $mode == error ]]; then
 | |
| 		echo "Try '${0##*/} --help' for more information."
 | |
| 		exit 2
 | |
| 	fi
 | |
| 
 | |
| 	IFS=: read -r root_dev root_typ root_opt < <(echo "$root_all")
 | |
| 	root_mnt=$basedir/root
 | |
| 
 | |
| 	IFS=: read -r overlay_dev overlay_typ overlay_opt < <(echo "$overlay_all")
 | |
| 	overlay_mnt=$basedir/overlay
 | |
| 
 | |
| 	union_dev=umorpha-rootfs
 | |
| 	union_typ=overlay
 | |
| 	# BusyBox ash supports weird Bash-isms like "<(process
 | |
| 	# substitution)" and the special "[[" syntax, but supporting
 | |
| 	# "+=" to append to a variable is too much bloat!??
 | |
| 	union_opt=''
 | |
| 	union_opt="${union_opt:+${union_opt},}lowerdir=${root_mnt}"
 | |
| 	union_opt="${union_opt:+${union_opt},}upperdir=${overlay_mnt}/upperdir"
 | |
| 	union_opt="${union_opt:+${union_opt},}workdir=${overlay_mnt}/workdir"
 | |
| 	# > Offline changes to the lower tree are only allowed if the
 | |
| 	# > "metadata only copy up", "inode index", "xino" and
 | |
| 	# > "redirect_dir" features have not been used.
 | |
| 	#
 | |
| 	# -- https://www.kernel.org/doc/html/v6.6/filesystems/overlayfs.html#changes-to-underlying-filesystems
 | |
| 	union_opt="${union_opt:+${union_opt},}metacopy=off"
 | |
| 	union_opt="${union_opt:+${union_opt},}index=off"
 | |
| 	union_opt="${union_opt:+${union_opt},}xino=off"
 | |
| 	union_opt="${union_opt:+${union_opt},}redirect_dir=off"
 | |
| 	union_mnt=${union_mnt:-${basedir:-}/mnt}
 | |
| 
 | |
| 	if [[ -n "${boot_all:-}" ]]; then
 | |
| 		IFS=: read -r boot_dev boot_typ boot_opt < <(echo "$boot_all")
 | |
| 		boot_mnt=$union_mnt/boot
 | |
| 	fi
 | |
| 
 | |
| 	set -x
 | |
| 	mount --mkdir -t "${root_typ:-auto}" -o "$root_opt" "$root_dev" "$root_mnt"
 | |
| 	mount --mkdir -t "${overlay_typ:-auto}" -o "$overlay_opt" "$overlay_dev" "$overlay_mnt"
 | |
| 	mkdir -p -- "$overlay_mnt/upperdir" "$overlay_mnt/workdir"
 | |
| 	mount --mkdir -t "${union_typ:-auto}" -o "$union_opt" "$union_dev" "$union_mnt"
 | |
| 	if [[ -n "${boot_all:-}" ]]; then
 | |
| 		mount --mkdir -t "${boot_typ:-auto}" -o "$boot_opt" "$boot_dev" "$boot_mnt"
 | |
| 	fi
 | |
| }
 | |
| 
 | |
| main "$@"
 |