From 62775e2d68b310725560b85da99c85632b525874 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Sat, 21 Aug 2021 18:48:47 -0400 Subject: initial --- forkroot | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100755 forkroot diff --git a/forkroot b/forkroot new file mode 100755 index 0000000..1ab4244 --- /dev/null +++ b/forkroot @@ -0,0 +1,120 @@ +#!/bin/bash +die() { printf 'Error: %s\n' "$*"; exit 1; } +if [ $UID != 0 ] +then + exec sudo -- "$0" "$@" || die 'You are not root.' +fi + +help() +{ + printf '%s\n' "Usage: $0 [-h|--help] [--] " +} + +unset force delete verbose +while [ $# -gt 0 ] +do + case "$1" in + -h|--help) help; exit;; + --force) force=y ;; + --delete-after) delete=y ;; + -v) verbose=y ;; + --) shift; break ;; + -*) die unknown option ;; + *) break; + esac + shift +done + +[ $# = 1 ] || die 'You must specify a target directory to create.' + +target=$1 +root=$target/root +mkdir "$target" || die 'creating target directory' + +btrfs subvolume snapshot / "$root" + +verbosely() +{ + ( + if [ "$verbose" ] + then set -x + fi + "$@" + ) +} + +bind_it() +{ + verbosely mount --bind "$mountpoint" "$root"/"$mountpoint" +} + +copy_mountpoint() +{ + [ "$1" -a "$2" ] || return + + [ -d "$2" ] && return + [ -d "${2%/*}" ] || copy_mountpoint "${1%/*}" "${2%/*}" + mkdir -p "$2" + chown --reference "$1" "$2" + chmod --reference "$1" "$2" +} + +mounts=$(tempfile) +cat /proc/mounts > "$mounts" + +while read mountdev mountpoint fstype fsoptions _ +do + case "$mountpoint" in + /sys |/proc |/dev |/usr | /usr/local) bind_it; continue ;; + /sys/*|/proc/*|/dev/* ) continue ;; + esac + case "$PWD" in + "$mountpoint"/*) bind_it; continue ;; + esac + + case "$fstype" in + tmpfs) + case "$mountpoint" in + /run/*) copy_mountpoint "$mountpoint" "$root"/"$mountpoint" ;; + esac + mount "$mountdev" -t "$fstype" -o "$fsoptions" "$root"/"$mountpoint" ;; + esac +done < "$mounts" + +tac "$mounts" | +while read mountdev mountpoint fstype fsoptions _ +do + case "$mountpoint" in "$root"/*) verbosely umount -l "$mountpoint";; esac +done + +chroot "$root" /bin/bash + +confirm() +{ + cat < " line + case "$line" in + [yY]) "$@"; return ;; + esac +} + +if [ "$delete" -a "$force" ] +then + btrfs subvolume delete "$target"/root + rmdir "$target" +elif [ "$delete" ] +then + confirm btrfs subvolume delete "$target"/root + rmdir "$target" +fi -- cgit v1.2.3