From f27fa0d05bc7744234693a41f7cd04f76f35c0ed Mon Sep 17 00:00:00 2001 From: CyberLeo Date: Mon, 11 Jun 2012 09:01:02 -0500 Subject: [PATCH] j: add fstab maintenance hooks Hooks to mount and umount mountpoints within chroot based on the contents of an fstab file; and maintain an mtab file. --- j | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- mount | 1 + umount | 1 + 3 files changed, 84 insertions(+), 7 deletions(-) create mode 120000 mount create mode 120000 umount diff --git a/j b/j index e69559d..9014e18 100755 --- a/j +++ b/j @@ -31,6 +31,10 @@ Usage: eval evaluate a shell command line within the chroot + mount mount chroot filesystems according to chroot fstab + + umount umount chroot filesystems that were mounted with 'mount' + EOF exit 1 } @@ -136,6 +140,9 @@ j_params() { return 1 fi + # Does this have a valid fstab file? + [ -f "${jdir}/fstab" ] && jfstab="${jdir}/fstab" + # Where is the shell? jshell="" for shell in /bin/bash /usr/bin/bash /usr/local/bin/bash /bin/sh @@ -152,7 +159,7 @@ j_params() { return 1 fi - printf "jerror='' jname='%s' jdir='%s' jroot='%s' jshell='%s'\n" "${jname}" "${jdir}" "${jroot}" "${jshell}" + printf "jerror='' jname='%s' jdir='%s' jroot='%s' jfstab='%s' jshell='%s'\n" "${jname}" "${jdir}" "${jroot}" "${jfstab}" "${jshell}" ) } @@ -284,14 +291,64 @@ j_status() { done } -# Mount /dev/pts and /proc in the chroot +# Copy a mount from the host (for things like /dev, /proc, /sys, et alia) +j_fstab_copy_mount() { + grep -Eq "${1}[[:space:]]" "${tmp_fstab}" || grep -E \ + "[[:space:]]${1}[[:space:]]" /proc/mounts | head -n 1 >> "${tmp_fstab}" +} + +# Prepare fstab for use: +# * Strip comments +# * Make sure certain required mounts exist (/dev/pts, /proc) +# * Sort by mountpoint, to ensure mounts are performed in the correct order +j_fstab_synthesize() { + local tmp_fstab="$(mktemp "${jdir}/.fstab.XXXXXXXX")" + [ -f "${jfstab}" ] && sed -e 's/#.*$//; /^\W*$/d' "${jfstab}" > "${tmp_fstab}" + j_fstab_copy_mount "/dev/pts" + j_fstab_copy_mount "/proc" + sort -k2 "${tmp_fstab}" + rm -f "${tmp_fstab}" +} + +# Process fstab file and mount the filesystems therein; if no fstab file (or if +# excludes certain critical filesystems) then augment it. This will also maintain +# an mtab file so they can be unmounted later (and so df works inside chroot). +# +# All mountpoints listed in this file will be prepended with ${jroot} prior to +# their being mounted or umounted! Make sure the fstab mountpoints are relative +# to the chroot root! +j_fstab_mount() { + echo "rootfs / rootfs rw 0 0" > "${jdir}/mtab" + j_fstab_synthesize | while read src dir type opts fsck dump + do + mkdir -p "${dir}" || break + mount -t "${type}" -o "${opts}" "${src}" "${jroot}/${dir}" || break + printf "%s %s %s %s 0 0\n" "${src}" "/${dir##/}" "${type}" "${opts}" >> "${jdir}/mtab" + done +} + +# Process fstab and mtab files and unmount the filesystems therein (opposite j_fstab_mount) +j_fstab_umount() { + [ -s "${jdir}/mtab" ] || j_fstab_synthesize > "${jdir}/mtab" + tac "${jdir}/mtab" | while read src dir unused + do + # Mounted? + grep -Eq "[[:space:]]${jroot}${dir%%/}[[:space:]]" /proc/mounts || continue + umount -f "${jroot}/${dir}" || umount -l "${jroot}/${dir}" || break + done + :>"${jdir}/mtab" +} + +# Start up chroot j_start() { jname="${1:-${jname}}" j_up "${jname}" && return 0 eval "$(j_params "${jname}")" meh "starting ${jname} ..." - mount -t devpts devpts "${jroot}/dev/pts" - mount -t proc proc "${jroot}/proc" + + # Mount filesystems and copy in /etc/mtab + j_fstab_mount + cp "${jdir}/mtab" "${jroot}/etc/mtab" # Copy in ipcc and launch ipcd j_ipc_setup @@ -319,13 +376,14 @@ j_eval() { env -i ${jenv} /usr/bin/chroot "${jroot}" /bin/su "${juser:-${USER}}" -c "${*}" } +# Invoke a shell within the chroot j_shell() { jname="${1:-${jname}}" eval "$(j_params "${jname}")" j_eval "${jname}" "cd; exec ${jshell} -l" } -# Unmount /dev/pts and /proc in the chroot +# Shut down chroot j_stop() { jname="${1:-${jname}}" eval "$(j_params "${jname}")" @@ -338,8 +396,8 @@ j_stop() { # Terminate ipcd j_ipc_stop - umount "${jroot}/proc" - umount "${jroot}/dev/pts" + # Unmount filesystems + j_fstab_umount } # Send a signal to all processes inside a chroot, if possible @@ -358,6 +416,7 @@ j_signal() { fi } +# Kill all processes inside chroot (TERM, then KILL) j_kill() { jname="${1:-${jname}}" eval "$(j_params "${jname}")" @@ -368,6 +427,20 @@ j_kill() { j_signal "KILL" "${jname}" } +# Hook to allow mounting chroot mounts from command line +j_mount() { + jname="${1:-${jname}}" + eval "$(j_params "${jname}")" + j_fstab_mount +} + +# Hook to allow unmounting chroot mounts from command line +j_umount() { + jname="${1:-${jname}}" + eval "$(j_params "${jname}")" + j_fstab_umount +} + case "${cmd}" in init|create) j_init "${jname}" "${@}" ;; ls|list) j_ls ;; @@ -377,5 +450,7 @@ shell|enter) j_shell "${jname}" ;; eval) j_eval "${jname}" "${*}" ;; stop) j_stop "${jname}" ;; kill) j_kill "${jname}" ;; +mount) j_mount "${jname}" ;; +umount) j_umount "${jname}" ;; *) pebkac ;; esac diff --git a/mount b/mount new file mode 120000 index 0000000..0fe2fa5 --- /dev/null +++ b/mount @@ -0,0 +1 @@ +j \ No newline at end of file diff --git a/umount b/umount new file mode 120000 index 0000000..0fe2fa5 --- /dev/null +++ b/umount @@ -0,0 +1 @@ +j \ No newline at end of file -- 2.42.0