2 # ==============================================================================
3 # portsreinstall library script
4 # - File system operations -
5 # Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
6 # This software is distributed under the 2-Clause BSD License.
7 # ==============================================================================
9 # ============= Get the global path of a possibly not yet created file/directory =============
18 expr "$path_src" : '^/' > /dev/null || echo -n `realpath .`
23 # ============= Inspect the privilege of the current environment on file system operation =============
24 fs_inspect_fs_privilege ()
26 local tgv mp mp_regexp mount_privilege basedir
27 [ -d "${TMPDIR}"/fs_privilege ] && return
28 tgv=${TMPDIR}/fs_privilege/test_tg
29 mkdir -p "$tgv" "${TMPDIR}"/fs_privilege/test_mp
30 mp=`realpath "${TMPDIR}"/fs_privilege/test_mp`
31 mp_regexp=`str_escape_regexp "$mp"`
32 echo yes > ${TMPDIR}/fs_privilege/fs_privilege
33 cat > ${TMPDIR}/fs_privilege/fslist << eof
43 if mount -t $fs "$tgv" "$mp" 2> /dev/null && umount "$mp"
48 echo no > ${TMPDIR}/fs_privilege/fs_privilege
49 fi > ${TMPDIR}/fs_privilege/fs_privilege:$fs 2> /dev/null
50 umount -f "$mp" 2> /dev/null || :
51 [ -e "${TMPDIR}"/fs_privilege/basedir ] && continue
52 mount -t $fs "$tgv" "$mp" 2> /dev/null && \
53 df "$mp" > ${TMPDIR}/fs_privilege/df:$fs && \
55 real_mp=`sed 1d "${TMPDIR}"/fs_privilege/df:$fs | tail -n 1 | \
56 sed -E 's/^.*[[:space:]][0-9]+%[[:space:]]+//'`
57 echo "$real_mp" | sed -E "s/$mp_regexp$//" > ${TMPDIR}/fs_privilege/basedir
58 done < ${TMPDIR}/fs_privilege/fslist
59 mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege`
60 if [ "x$mount_privilege" = xyes ]
62 mount -t nullfs /bin "$mp" 2> /dev/null
63 if [ `ls "$mp" 2> /dev/null | wc -l` -gt 0 ]
68 fi > ${TMPDIR}/fs_privilege/nullfs_target_recognition
69 umount -f "$mp" 2> /dev/null || :
70 nullfs_target_recognition=`cat "${TMPDIR}"/fs_privilege/nullfs_target_recognition`
71 if [ "x$nullfs_target_recognition" = xyes ]
73 message_echo "INFO: The current environment has the full required privilege of mounting/unmounting file systems."
75 message_echo "INFO: The current environment formally has the full required privilege of mounting/unmounting file systems but the recognition of nullfs/unionfs targets is incorrect."
78 echo no > ${TMPDIR}/fs_privilege/nullfs_target_recognition
79 message_echo "INFO: The current environment does not have the privilege of mounting/unmounting for the following file system(s)."
82 mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege:$fs`
83 [ "x$mount_privilege" = xyes ] || echo ' '$fs
84 done < ${TMPDIR}/fs_privilege/fslist | message_cat
86 basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
89 message_echo "INFO: The current environment will be a chroot/jail guest whose base directory is \"$basedir\"."
91 if [ "x$opt_invalidate_mount_privilege" = xyes ]
93 message_echo "INFO: The privilege of mounting/unmounting in this environment is forcibly invalidated."
97 # ============= Check whether mounting file systems are available at the current environment =============
98 fs_chk_mount_privilege ()
100 local mount_privilege
101 fs_inspect_fs_privilege
102 [ "x$opt_invalidate_mount_privilege" = xno ] || return
103 mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege`
104 nullfs_target_recognition=`cat "${TMPDIR}"/fs_privilege/nullfs_target_recognition`
105 [ "x$nullfs_target_recognition" = xyes -a "x$mount_privilege" = xyes ]
108 # ============= Check whether mounting file systems are available at the current environment =============
109 fs_chk_unmount_privilege ()
111 local mount_privilege
112 fs_inspect_fs_privilege
113 [ "x$opt_invalidate_mount_privilege" = xno ] || return
114 mount_privilege=`cat "${TMPDIR}"/fs_privilege/fs_privilege`
115 [ "x$mount_privilege" = xyes ]
118 # ============= Get the base directory the current environment (applicable in case of a chroot guest) =============
119 fs_get_system_basedir ()
121 fs_inspect_fs_privilege
122 cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :
125 # ============= Get the regular expression pattern of the actual mount point =============
126 fs_get_actual_mount_point_pattern ()
128 local mountpoint basedir mountpoint_real
130 [ -e "$mountpoint" ] || return
131 fs_inspect_fs_privilege
132 basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
133 mountpoint_real=`realpath "$mountpoint"`
134 mountpoint_real_full=`echo "$basedir$mountpoint_real" | sed 's|//*|/|'`
135 str_escape_regexp "$mountpoint_real_full"
138 # ============= Get mount info at the descendant directory levels required for builder chroot environment =============
139 fs_get_descendant_mount_info ()
141 local mountpoint mountpoint_real_regexp basedir
143 mountpoint_real_regexp=`fs_get_actual_mount_point_pattern "$mountpoint"` || return
144 basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
145 basedir_ptn=`str_escape_regexp "$basedir"`
146 df | sed 1d | grep -E "%[[:space:]]+$mountpoint_real_regexp\/" | while read fs data
148 echo "$fs" | grep -q -e '^/' -e '^<above>:' && fs=normal
149 mp_abs=`echo "$data" | sed -E 's|.*%[[:space:]]+(/.+)$|\1|'`
150 mp=`echo "$mp_abs" | sed -E "s|^$basedir_ptn||"`
151 relative=`echo "$mp_abs" | sed -E "s|^$mountpoint_real_regexp||"`
152 printf '%s\t%s\t%s\n' "$fs" "$mp" "$relative"
156 # ============= Repair the unionfs image if applicable and hidden =============
157 # Use the side effect of find(1).
158 fs_fix_unionfs_image_if_hidden ()
160 local needlepath needlepath_cur needlepath_next
162 needlepath_cur=$needlepath
165 find -dx "$needlepath_cur" -maxdepth 0 > /dev/null 2>&1 || :
166 needlepath_next=`dirname "$needlepath_cur"`
167 [ "x$needlepath_cur" = "x$needlepath_next" ] && break
168 needlepath_cur=$needlepath_next
170 [ -e "$needlepath" ] && return
171 message_echo "ERROR: Lost mandatory file, probably due to the bug of unionfs: $needlepath" >&2
175 # ============= Check whether a directory is mounted properly =============
178 local type target mountpoint target_ptn mountpoint_real_regexp tmpsrc
182 target_ptn=`echo "$target" | sed 's|//*|/|g' | str_escape_regexp_filter`
183 mountpoint_real_regexp=`fs_get_actual_mount_point_pattern "$mountpoint"` || return
184 basedir=`cat "${TMPDIR}"/fs_privilege/basedir 2> /dev/null || :`
185 basedir_target_ptn=`echo "$basedir/$target" | sed 's|//*|/|g' | str_escape_regexp_filter`
186 tmpsrc=${TMPDIR}/fs_chk_mounted:src
187 df | sed 1d | grep -E "%[[:space:]]+$mountpoint_real_regexp$" > $tmpsrc
190 grep -qE "^${target_ptn}[[:space:]]" "$tmpsrc" || grep -qE "^${basedir_target_ptn}[[:space:]]" "$tmpsrc"
193 grep -qE "^<above>:${target_ptn}[[:space:]]" "$tmpsrc" || grep -qE "^<above>:${basedir_target_ptn}[[:space:]]" "$tmpsrc"
195 devfs | fdescfs | procfs | linprocfs | tmpfs )
196 grep -q "^$type" "$tmpsrc"
199 message_echo "ERROR: Unsupported fyle system [$type]" >&2