exit 1
}
+# ============= Save the system base observed currently =============
+fs_save_current_systembase ()
+{
+ local systembase
+ systembase=$1
+ echo "$systembase" > ${TMPDIR}/fs_save_current_systembase
+}
+
+# ============= Save the system base observed at the time of mounting =============
+fs_save_mounttime_systembase ()
+{
+ local systembase
+ systembase=$1
+ echo "$systembase" > ${DBDIR}/fs_systembase
+}
+
+# ============= Get the system base observed currently =============
+fs_get_current_systembase ()
+{
+ cat "${TMPDIR}/fs_save_current_systembase" 2> /dev/null
+}
+
+# ============= Get the system base observed at the time of mounting =============
+# Non-zero return means no file system was attempted to mount
+fs_get_mounttime_systembase ()
+{
+ cat "${DBDIR}/fs_systembase" 2> /dev/null
+}
+
+# ============= Get the system base in the scope of accessing =============
+fs_system_base_in_mp_access ()
+{
+ fs_get_current_systembase
+}
+
+# ============= Get the system base in the scope of creating mount points =============
+fs_system_base_in_mp_creation ()
+{
+ fs_get_current_systembase
+}
+
+# ============= Get the system base in the scope of referring to mount points =============
+fs_system_base_in_mp_reference ()
+{
+ str_regularize_df_path "`fs_get_current_systembase`/`fs_get_system_basedir`"
+}
+
+# ============= Get the system base in the scope of targets =============
+# Non-zero return means no file system was attempted to mount
+fs_system_base_in_target ()
+{
+ fs_get_mounttime_systembase
+}
+
# ============= Build the file systems for the builder chroot environment =============
fs_build_chroot ()
{
- local systembase
- systembase=$1
[ -e "${DBDIR}/mount_manifest" ] && return
message_echo "Building the file systems for builder chroot environment (if not yet)."
fs_safeguard_basedir "$opt_basedir"
- fs_unmount "$systembase" || return
- mkdir -p "$systembase/$opt_basedir"
+ fs_unmount || return
+ mkdir -p "$opt_basedir"
# Prescan the f file system of the original environment
cp /dev/null "${TMPDIR}/fs_build_chroot:directories"
(
sysdirs_ptn="^/*(`str_escape_regexp_filter < ${TMPDIR}/fs_build_chroot:sys_dirs | tr '\n' '|' | sed 's/\|$//'`)/+"
while read directory
do
- [ -e "$systembase"/$directory ] || continue
- if [ -L "$systembase"/$directory ]
+ [ -e "/$directory" ] || continue
+ if [ -L "/$directory" ]
then
- src_mountpoint_real=`realpath "$systembase"/$directory`
- printf '%s\t%s\n' link $directory >> ${TMPDIR}/fs_build_chroot:directories
+ src_mountpoint_real=`realpath "/$directory"`
+ printf '%s\t%s\n' link "$directory" >> ${TMPDIR}/fs_build_chroot:directories
if ! echo "$src_mountpoint_real/" | grep -qE "$sysdirs_ptn"
then
printf '%s\t%s\n' real "$src_mountpoint_real" >> ${TMPDIR}/fs_build_chroot:directories
tmpdir_descendant=${TMPDIR}/fs_build_chroot:descendant/$src_mountpoint_real
mkdir -p "$tmpdir_descendant"
- fs_get_descendant_mount_info "$systembase/$src_mountpoint_real" > $tmpdir_descendant/list
+ fs_get_descendant_mount_info "/$src_mountpoint_real" > $tmpdir_descendant/list
fi
- elif [ -d "$systembase"/$directory ]
+ elif [ -d "/$directory" ]
then
printf '%s\t%s\n' real $directory >> ${TMPDIR}/fs_build_chroot:directories
tmpdir_descendant=${TMPDIR}/fs_build_chroot:descendant/$directory
mkdir -p "$tmpdir_descendant"
- fs_get_descendant_mount_info "$systembase/$directory" > $tmpdir_descendant/list
+ fs_get_descendant_mount_info "/$directory" > $tmpdir_descendant/list
fi
done < ${TMPDIR}/fs_build_chroot:sys_dirs
)
# Prepare the grand base of the chroot environment
(
- cd "$systembase/$opt_basedir"
+ cd "/$opt_basedir"
for directory in builder mask store
do
[ -d $directory ] || mkdir $directory
# Build target directories and the manifest for mounting
cp /dev/null "${DBDIR}/mount_manifest.tmp"
(
- cd "$systembase/$opt_basedir"/builder
+ cd "/$opt_basedir"/builder
while read srcline
do
type=`echo "$srcline" | cut -f 1`
directory=`echo "$srcline" | cut -f 2`
case $type in
link )
- [ -e "$directory" -o -L "$directory" ] || cp -RpP "$systembase/$directory" .
+ [ -e "$directory" -o -L "$directory" ] || cp -RpP "/$directory" .
;;
real )
mkdir -p "./$directory"
- masktarget=$systembase/$opt_basedir/mask/$directory
+ masktarget=/$opt_basedir/mask/$directory
mkdir -p "$masktarget"
- printf '%s\t%s\t%s\t%s\n' nullfs "$systembase"/$directory $directory ro >> ${DBDIR}/mount_manifest.tmp
- printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" $directory rw,noatime >> ${DBDIR}/mount_manifest.tmp
+ printf '%s\t%s\t%s\t%s\n' nullfs "/$directory" "$directory" ro >> ${DBDIR}/mount_manifest.tmp
+ printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" "$directory" rw,noatime >> ${DBDIR}/mount_manifest.tmp
while read srcline
do
fs=`echo "$srcline" | cut -f 1`
if ! grep -qFx "$mpath" "${TMPDIR}/fs_build_chroot:shared_dirs:added"
then
echo "$mpath" >> ${TMPDIR}/fs_build_chroot:shared_dirs:added
- mp_share=`realpath "$systembase/$mpath"`
+ mp_share=`realpath "/$mpath"`
printf '%s\t%s\t%s\t%s\n' nullfs "$mp_share" "$mpath" rw >> ${DBDIR}/mount_manifest.tmp
fi
done
[ -e "${TMPDIR}/fs_build_chroot:shared_dirs:is_under" ] && continue
case $fs in
normal )
- masktarget=`str_regularize_df_path "$systembase/$opt_basedir/mask/$fullpath"`
+ masktarget=`str_regularize_df_path "/$opt_basedir/mask/$fullpath"`
mkdir -p "$masktarget"
printf '%s\t%s\t%s\t%s\n' nullfs "$mp" "$fullpath" ro >> ${DBDIR}/mount_manifest.tmp
printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" "$fullpath" rw,noatime >> ${DBDIR}/mount_manifest.tmp
done < ${TMPDIR}/fs_build_chroot:directories
grep -Ev -f "${TMPDIR}/fs_build_chroot:shared_dirs:added" "${DBDIR}/shared_dirs.lst" | while read shared_dir
do
- mp_share=`realpath "$systembase$shared_dir"`
+ mp_share=`realpath "$shared_dir"`
printf '%s\t%s\t%s\t%s\n' nullfs "$mp_share" "/$shared_dir" rw >> ${DBDIR}/mount_manifest.tmp
done
for directory in dev proc tmp
printf '%s\t%s\t%s\t%s\n' procfs proc proc rw >> ${DBDIR}/mount_manifest.tmp
printf '%s\t%s\t%s\t%s\n' tmpfs tmpfs tmp rw,mode=1777 >> ${DBDIR}/mount_manifest.tmp
mkdir -p ."${PROGRAM}"
- cd "$systembase/$opt_basedir/mask"
+ cd "/$opt_basedir/mask"
if [ ! -e root/.cshrc ]
then
tmp_cshrc=${TMPDIR}/fs_build_chroot:.cshrc
[ -d root ] || mkdir root
- if [ -e "$systembase"/root/.cshrc ]
+ if [ -e /root/.cshrc ]
then
- cp -p "$systembase"/root/.cshrc "$tmp_cshrc"
- cp -p "$systembase"/root/.cshrc "root/.cshrc.bak-${APPNAME}"
- elif [ -e "$systembase"/usr/share/skel/dot.cshrc ]
+ cp -p /root/.cshrc "$tmp_cshrc"
+ cp -p /root/.cshrc "root/.cshrc.bak-${APPNAME}"
+ elif [ -e /usr/share/skel/dot.cshrc ]
then
- cp -p "$systembase"/usr/share/skel/dot.cshrc "$tmp_cshrc"
+ cp -p /usr/share/skel/dot.cshrc "$tmp_cshrc"
touch "root/.cshrc.bak-${APPNAME}"
else
cp /dev/null "$tmp_cshrc"
echo 'set prompt="%N@[builder]%m:%~ %# "' >> $tmp_cshrc
mv "$tmp_cshrc" root/.cshrc
fi
- printf '%s\t%s\t%s\t%s\n' nullfs "$systembase/$opt_basedir"/store ".${PROGRAM}" rw >> ${DBDIR}/mount_manifest.tmp
+ printf '%s\t%s\t%s\t%s\n' nullfs "/$opt_basedir"/store ".${PROGRAM}" rw >> ${DBDIR}/mount_manifest.tmp
)
mv "${DBDIR}/mount_manifest.tmp" "${DBDIR}/mount_manifest"
}
# ============= Check whether the file systems for the builder chroot environment are all mounted =============
fs_chk_mount ()
{
- local systembase
- systembase=$1
+ local systembase_target systembase_mp tmp_remains
[ -e "${DBDIR}/mount_manifest" ] || return
- rm -rf ${TMPDIR}/fs_chk_mount:remains
+ systembase_target=`fs_system_base_in_target` || return
+ systembase_mp=`fs_system_base_in_mp_reference`
+ tmp_remains=${TMPDIR}/fs_chk_mount:remains
+ rm -rf "$tmp_remains"
while read srcline
do
type=`echo "$srcline" | cut -f 1`
target=`echo "$srcline" | cut -f 2`
- [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+ [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase_target/$target
directory=`echo "$srcline" | cut -f 3`
opt=`echo "$srcline" | cut -f 4`
- if ! fs_chk_mounted "$type" "$target" "$systembase/$opt_basedir/builder/$directory"
+ mp=$systembase_mp/$opt_basedir/builder/$directory
+ if ! fs_chk_mounted "$type" "$target" "$mp"
then
- touch "${TMPDIR}"/fs_chk_mount:remains
- break
+ printf '%s\t%s\t%s\n' "$type" "$target" "$mp" >> $tmp_remains
fi
done < ${DBDIR}/mount_manifest
- [ ! -e "${TMPDIR}"/fs_chk_mount:remains ]
+ ! cat "$tmp_remains" 2> /dev/null
}
# ============= Terminate when the file systems for the builder chroot environment cannot be mounted =============
fs_terminate_if_mount_unavailable ()
{
- local systembase
- systembase=$1
- fs_chk_mount "$systembase" && return
- fs_chk_mount_privilege && return
+ local systembase systembase_saved
+ systembase=`fs_get_current_systembase`
+ fs_chk_mount > /dev/null && return
+ if systembase_saved=`fs_get_mounttime_systembase`
+ then
+ if [ "x$systembase" = "x$systembase_saved" ]
+ then
+ fs_chk_mount_privilege && return
+ elif [ -n "$systembase" ]
+ then
+ temp_terminate_process ()
+ {
+ message_echo "ERROR: Cannot mount because the current file systems are being mounted from inside the virtual (chroot or jail) environment." >&2
+ message_echo "INFO: Instead of this command, mount from inside the virtual (chroot or jail) environment."
+ }
+ exit 1
+ fi
+ elif fs_chk_mount_privilege
+ then
+ fs_save_mounttime_systembase "`fs_get_current_systembase`"
+ return
+ fi
temp_terminate_process ()
{
- local errno basedir
- errno=${1:-0}
+ local basedir
[ $opt_batch_mode = yes ] && return
- if [ $errno -ne 2 ]
- then
- message_echo "Aborted by unexpected error" >&2
- exit
- fi
message_echo
message_echo "INFO: Terminated for mounting file systems because this utility was executed at a virtual (chroot or jail) environment."
message_echo "Execute"
# ============= Generate a custom fstab file for the builder chroot environment =============
fs_gen_fstab ()
{
- local systembase
- systembase=$1
- [ "${DBDIR}/fstab" -nt "${DBDIR}/mount_manifest" ] && return
+ local stage systembase_target systembase_mp
+ stage=$1
+ systembase_target=`fs_system_base_in_target`
+ case $stage in
+ mount )
+ systembase_mp=`fs_system_base_in_mp_creation`
+ ;;
+ unmount )
+ systembase_mp=`fs_system_base_in_mp_reference`
+ ;;
+ esac
fs_safeguard_basedir "$opt_basedir"
while read srcline
do
target=`echo "$srcline" | cut -f 2`
directory=`echo "$srcline" | cut -f 3`
opt=`echo "$srcline" | cut -f 4`
- [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+ [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase_target/$target
target=`str_regularize_df_path "$target"`
- mp=`str_regularize_df_path "$systembase/$opt_basedir/builder/$directory"`
+ mp=`str_regularize_df_path "$systembase_mp/$opt_basedir/builder/$directory"`
opt=`echo "$opt" | sed 's/[[:space:]]/\\040/g'`
echo "$target $mp $type $opt 0 0"
done < ${DBDIR}/mount_manifest > ${DBDIR}/fstab
# ============= Mount the file systems for the builder chroot environment if not yet =============
fs_mount ()
{
- local systembase
- systembase=$1
+ local remining
+ if fs_chk_mount > /dev/null
+ then
+ message_echo "The builder chroot environment is already mounted."
+ return
+ fi
+ fs_terminate_if_mount_unavailable
message_echo "Mounting the file systems for builder chroot environment."
- fs_gen_fstab
- if ! mount -F "${DBDIR}/fstab" -a || ! fs_chk_mount "$systembase"
+ fs_gen_fstab mount
+ if ! mount -F "${DBDIR}/fstab" -a || ! remining=`fs_chk_mount`
then
- message_echo "Error: Failed to mount the file systems. Some of them remain unmounted." >&2
+ message_echo "ERROR: Failed to mount the file systems. The followings remain unmounted:" >&2
+ [ $opt_batch_mode = yes ] || echo "$remining" >&2
+ cp "${DBDIR}/fstab" "${DBDIR}/fstab-mount-err"
exit 1
fi
message_echo "Mounting done."
# ============= Check whether the file systems for the builder chroot environment are all unmounted or destroyed =============
fs_chk_unmount ()
{
- local systembase
- systembase=$1
+ local systembase_target systembase_mp tmp_remains
[ -e "${DBDIR}/mount_manifest" ] || return 0
- rm -rf ${TMPDIR}/fs_chk_unmount:remains
+ systembase_target=`fs_system_base_in_target` || return 0
+ systembase_mp=`fs_system_base_in_mp_reference`
+ tmp_remains=${TMPDIR}/fs_chk_unmount:remains
+ rm -rf "$tmp_remains"
tail -r "${DBDIR}/mount_manifest" | while read srcline
do
type=`echo "$srcline" | cut -f 1`
target=`echo "$srcline" | cut -f 2`
- [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase/$target
+ [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase_target/$target
directory=`echo "$srcline" | cut -f 3`
opt=`echo "$srcline" | cut -f 4`
- if fs_chk_mounted "$type" "$target" "$systembase/$opt_basedir/builder/$directory"
- then
- touch "${TMPDIR}"/fs_chk_unmount:remains
- break
- fi
+ mp=$systembase_mp/$opt_basedir/builder/$directory
+ fs_chk_mounted "$type" "$target" "$mp" || continue
+ echo "$mp" >> $tmp_remains
done
- [ ! -e "${TMPDIR}"/fs_chk_unmount:remains ]
+ ! cat "$tmp_remains" 2> /dev/null
}
# ============= Terminate when the file systems for the builder chroot environment cannot be unmounted =============
fs_terminate_if_unmount_unavailable ()
{
- local systembase
- systembase=$1
- fs_chk_unmount "$systembase" && return
- fs_chk_unmount_privilege && return
+ local systembase systembase_saved
+ systembase=`fs_get_current_systembase`
+ systembase_saved=`fs_get_mounttime_systembase` || return 0
+ fs_chk_unmount > /dev/null && return
+ if [ "x$systembase" = "x$systembase_saved" ]
+ then
+ fs_chk_mount_privilege && return
+ elif [ -n "$systembase" ]
+ then
+ temp_terminate_process ()
+ {
+ message_echo "ERROR: Cannot unmount because the current file systems were mounted from inside the virtual (chroot or jail) environment." >&2
+ message_echo "INFO: Instead of this command, unmount from inside the virtual (chroot or jail) environment."
+ }
+ exit 1
+ fi
temp_terminate_process ()
{
local errno basedir
errno=${1:-0}
[ $opt_batch_mode = yes ] && return
- if [ $errno -ne 3 ]
- then
- message_echo "Aborted by unexpected error" >&2
- exit
- fi
message_echo
message_echo "INFO: Terminated for unmounting file systems because this utility was executed at a virtual (chroot or jail) environment."
message_echo "Execute"
# ============= Unmount file systems for the chroot environment =============
fs_unmount ()
{
- local systembase
- systembase=$1
- [ ! -d "$systembase/$opt_basedir"/builder ] && return
- [ -e "${DBDIR}/mount_manifest" ] || return 0
+ local systembase_access systembase_saved remining
+ systembase_access=`fs_system_base_in_mp_access`
+ ! fs_get_mounttime_systembase > /dev/null && return
+ fs_terminate_if_unmount_unavailable
+ [ ! -d "$systembase_access/$opt_basedir"/builder ] && return
+ [ ! -e "${DBDIR}/mount_manifest" ] && return
+ if fs_chk_unmount > /dev/null
+ then
+ message_echo "The builder chroot environment is already unmounted."
+ return
+ fi
message_echo "Unmounting the file systems for builder chroot."
- fs_gen_fstab
+ fs_gen_fstab unmount
umount -F "${DBDIR}/fstab" -af 2> /dev/null || :
itrial=${FS_UNMOUNT_RETIAL_MAXNUM}
while [ $itrial -gt 0 ]
do
- fs_chk_unmount "$systembase" && break
+ remining=`fs_chk_unmount` && break
+ echo -n "$remining" | str_regularize_df_path_filter | while read remining_mp
+ do
+ umount -f "$remining_mp" || :
+ done
message_echo "(Retrying to unmount the file systems...)" >&2
sleep ${FS_UNMOUNT_RETIAL_WAIT}
umount -F "${DBDIR}/fstab" -af 2> /dev/null || :
message_echo "WARNING: Failed to unmount the file systems. Some of them remain mounted." >&2
return 1
fi
+ rm -f "${DBDIR}/fs_systembase"
message_echo "Unmounting done."
}
# ============= Destroy the chroot environment =============
fs_destroy ()
{
- local systembase
- systembase=$1
fs_chk_safety_basedir "$opt_basedir" || return 0
[ ! -d "$opt_basedir" ] && return
- fs_terminate_if_unmount_unavailable "$systembase"
- fs_unmount "$systembase" || return
+ fs_unmount || return
chflags -R noschg "$opt_basedir"
rm -rf "$opt_basedir"
}