OSDN Git Service

Fixed a bug that portsreinstall-chroot failed to mount when some shared directories...
[portsreinstall/current.git] / lib / chroot / libfs.sh
1 #!/bin/sh -e
2 # ==============================================================================
3 # portsreinstall-chroot library script
4 # Overlay onto lib/libfs.sh for portsreinstall-chroot
5 # - File system operations -
6 # Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
7 # This software is distributed under the 2-Clause BSD License.
8 # ==============================================================================
9
10 FS_UNMOUNT_RETIAL_MAXNUM=5      # Number of retrial of unmounting
11 FS_UNMOUNT_RETIAL_WAIT=3        # Wait seconds in retrial of unmounting
12
13 # ============= Check the safety of the base directory of builder chroot environment =============
14 fs_chk_safety_basedir ()
15 {
16         local basedir
17         basedir=$1
18         [ -n "$basedir" ] || return
19         case "$basedir" in
20         /|/bin|/boot|/compat|/dev|/entropy|/etc|/home|/host|/lib|/libexec|/net|/proc|/rescue|/root|/sbin|/sys|/tmp|/usr|/var)
21                 return 1
22                 ;;
23         esac
24         expr "$basedir" : '^/boot/.*' > /dev/null && return 1
25         expr "$basedir" : '^/compat/.*' > /dev/null && return 1
26         expr "$basedir" : '^/dev/.*' > /dev/null && return 1
27         expr "$basedir" : '^/etc/.*' > /dev/null && return 1
28         expr "$basedir" : '^/lib/.*' > /dev/null && return 1
29         expr "$basedir" : '^/libexec/.*' > /dev/null && return 1
30         expr "$basedir" : '^/proc/.*' > /dev/null && return 1
31         expr "$basedir" : '^/sbin/.*' > /dev/null && return 1
32         :
33 }
34
35 # ============= Safeguard of the base directory of builder chroot environment =============
36 fs_safeguard_basedir ()
37 {
38         local basedir
39         basedir=$1
40         fs_chk_safety_basedir "$basedir" && return
41         message_echo "ERROR: The base directory [$opt_basedir] is not safe." >&2
42         exit 1
43 }
44
45 # ============= Save the system base observed currently =============
46 fs_save_current_systembase ()
47 {
48         local systembase 
49         systembase=$1
50         echo "$systembase" >  ${TMPDIR}/fs_save_current_systembase
51 }
52
53 # ============= Save the system base observed at the time of mounting =============
54 fs_save_mounttime_systembase ()
55 {
56         local systembase 
57         systembase=$1
58         echo "$systembase" >  ${DBDIR}/fs_systembase
59 }
60
61 # ============= Get the system base observed currently =============
62 fs_get_current_systembase ()
63 {
64         cat  "${TMPDIR}/fs_save_current_systembase" 2> /dev/null
65 }
66
67 # ============= Get the system base observed at the time of mounting =============
68 # Non-zero return means no file system was attempted to mount
69 fs_get_mounttime_systembase ()
70 {
71         cat "${DBDIR}/fs_systembase" 2> /dev/null
72 }
73
74 # ============= Get the system base in the scope of accessing =============
75 fs_system_base_in_mp_access ()
76 {
77         fs_get_current_systembase
78 }
79
80 # ============= Get the system base in the scope of creating mount points =============
81 fs_system_base_in_mp_creation ()
82 {
83         fs_get_current_systembase
84 }
85
86 # ============= Get the system base in the scope of referring to mount points =============
87 fs_system_base_in_mp_reference ()
88 {
89         str_regularize_df_path "`fs_get_current_systembase`/`fs_get_system_basedir`"
90 }
91
92 # ============= Get the system base in the scope of targets =============
93 # Non-zero return means no file system was attempted to mount
94 fs_system_base_in_target ()
95 {
96         fs_get_mounttime_systembase
97 }
98
99 # ============= Build the file systems for the builder chroot environment =============
100 fs_build_chroot ()
101 {
102         [ -e "${DBDIR}/mount_manifest" ] && return
103         message_echo "Building the file systems for builder chroot environment (if not yet)."
104         fs_safeguard_basedir "$opt_basedir"
105         fs_unmount || return
106         mkdir -p "$opt_basedir"
107         # Prescan the f file system of the original environment
108         cp /dev/null "${TMPDIR}/fs_build_chroot:directories"
109         (
110                 {
111                         echo bin compat etc lib libexec root sbin sys usr var | tr ' ' '\n'
112                         echo "$opt_extra_dirs" | tr "$opt_extra_dirs_delim" '\n'
113                 } | grep -v '^[[:space:]]*$' | sort -u > ${TMPDIR}/fs_build_chroot:sys_dirs
114                 sysdirs_ptn="^/*(`str_escape_regexp_filter < ${TMPDIR}/fs_build_chroot:sys_dirs | tr '\n' '|' | sed 's/\|$//'`)/+"
115                 while read directory
116                 do
117                         [ -e "/$directory" ] || continue
118                         if [ -L "/$directory" ]
119                         then
120                                 src_mountpoint_real=`realpath "/$directory"`
121                                         printf '%s\t%s\n' link "$directory" >> ${TMPDIR}/fs_build_chroot:directories
122                                 if ! echo "$src_mountpoint_real/" | grep -qE "$sysdirs_ptn"
123                                 then
124                                         printf '%s\t%s\n' real "$src_mountpoint_real" >> ${TMPDIR}/fs_build_chroot:directories
125                                         tmpdir_descendant=${TMPDIR}/fs_build_chroot:descendant/$src_mountpoint_real
126                                         mkdir -p "$tmpdir_descendant"
127                                         fs_get_descendant_mount_info "/$src_mountpoint_real" > $tmpdir_descendant/list
128                                 fi
129                         elif [ -d "/$directory" ]
130                         then
131                                 printf '%s\t%s\n' real $directory >> ${TMPDIR}/fs_build_chroot:directories
132                                 tmpdir_descendant=${TMPDIR}/fs_build_chroot:descendant/$directory
133                                 mkdir -p "$tmpdir_descendant"
134                                 fs_get_descendant_mount_info "/$directory" > $tmpdir_descendant/list
135                         fi
136                 done < ${TMPDIR}/fs_build_chroot:sys_dirs
137         )
138         # Prepare the grand base of the chroot environment
139         (
140                 cd "/$opt_basedir"
141                 for directory in builder mask store
142                 do
143                         [ -d $directory ] || mkdir $directory
144                 done
145         )
146         # Directories to share with the host environment by nullfs
147         if [ "x$opt_share_port_pkgs_dirs" = xyes ]
148         then
149                 echo "$PORTSDIR"
150                 echo "$PORTSNAP_WORKDIR"
151                 echo "$PKGNG_PKG_CACHEDIR"
152         fi | str_regularize_df_path_filter | grep -v '^[[:space:]]*$' | sort -u > ${DBDIR}/shared_dirs.lst
153         str_escape_regexp_filter < ${DBDIR}/shared_dirs.lst | sed 's|^|^|;s|$|\/|' > ${TMPDIR}/fs_build_chroot:shared_dirs.regexp.tmp
154         paste "${DBDIR}/shared_dirs.lst" "${TMPDIR}/fs_build_chroot:shared_dirs.regexp.tmp" > ${TMPDIR}/fs_build_chroot:shared_dirs.regexp
155         cp /dev/null "${TMPDIR}/fs_build_chroot:shared_dirs:added"
156         # Build target directories and the manifest for mounting
157         cp /dev/null "${DBDIR}/mount_manifest.tmp"
158         (
159                 cd "/$opt_basedir"/builder
160                 while read srcline
161                 do
162                         type=`echo "$srcline" | cut -f 1`
163                         directory=`echo "$srcline" | cut -f 2`
164                         case $type in
165                         link )
166                                 [ -e "$directory" -o -L "$directory" ] || cp -RpP "/$directory" .
167                                 ;;
168                         real )
169                                 mkdir -p "./$directory"
170                                 masktarget=/$opt_basedir/mask/$directory
171                                 mkdir -p "$masktarget"
172                                 printf '%s\t%s\t%s\t%s\n' nullfs "/$directory" "$directory" ro >> ${DBDIR}/mount_manifest.tmp
173                                 printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" "$directory" rw,noatime >> ${DBDIR}/mount_manifest.tmp
174                                 while read srcline
175                                 do
176                                         fs=`echo "$srcline" | cut -f 1`
177                                         mp=`echo "$srcline" | cut -f 2 | str_regularize_df_path_filter`
178                                         relative=`echo "$srcline" | cut -f 3 | str_regularize_df_path_filter`
179                                         fullpath=`str_regularize_df_path "/$directory/$relative"`
180                                         rm -f "${TMPDIR}/fs_build_chroot:shared_dirs:is_under"
181                                         rm -f "${TMPDIR}/fs_build_chroot:shared_dirs:is_itself"
182                                         while read -r shared_path shared_path_regexp
183                                         do
184                                                 echo "$fullpath/" | grep -qE "$shared_path_regexp" || continue
185                                                 echo "$shared_path"$'\n'"$fullpath" | while read mpath
186                                                 do
187                                                         if  ! grep -qFx "$mpath" "${TMPDIR}/fs_build_chroot:shared_dirs:added"
188                                                         then
189                                                                 echo "$mpath" >> ${TMPDIR}/fs_build_chroot:shared_dirs:added
190                                                                 mkdir -p "/$mpath"
191                                                                 mp_share=`realpath "/$mpath"`
192                                                                 printf '%s\t%s\t%s\t%s\n' nullfs "$mp_share" "$mpath" rw >> ${DBDIR}/mount_manifest.tmp
193                                                         fi
194                                                 done
195                                                 touch "${TMPDIR}/fs_build_chroot:shared_dirs:is_under"
196                                         done < ${TMPDIR}/fs_build_chroot:shared_dirs.regexp
197                                         [ -e "${TMPDIR}/fs_build_chroot:shared_dirs:is_under" ] && continue
198                                         case $fs in
199                                                 normal )
200                                                         masktarget=`str_regularize_df_path "/$opt_basedir/mask/$fullpath"`
201                                                         mkdir -p "$masktarget"
202                                                         printf '%s\t%s\t%s\t%s\n' nullfs "$mp" "$fullpath" ro >> ${DBDIR}/mount_manifest.tmp
203                                                         printf '%s\t%s\t%s\t%s\n' unionfs "$masktarget" "$fullpath" rw,noatime >> ${DBDIR}/mount_manifest.tmp
204                                                         ;;
205                                                 devfs )
206                                                         printf '%s\t%s\t%s\t%s\n' devfs devfs "$fullpath" rw >> ${DBDIR}/mount_manifest.tmp
207                                                         ;;
208                                                 fdescfs )
209                                                         printf '%s\t%s\t%s\t%s\n' fdescfs fdesc "$fullpath" rw >> ${DBDIR}/mount_manifest.tmp
210                                                         ;;
211                                                 procfs )
212                                                         printf '%s\t%s\t%s\t%s\n' procfs proc "$fullpath" rw >> ${DBDIR}/mount_manifest.tmp
213                                                         ;;
214                                                 linprocfs )
215                                                         printf '%s\t%s\t%s\t%s\n' linprocfs linproc "$fullpath" rw >> ${DBDIR}/mount_manifest.tmp
216                                                         ;;
217                                                 tmpfs )
218                                                         printf '%s\t%s\t%s\t%s\n' tmpfs tmpfs "$fullpath" rw,mode=1777 >> ${DBDIR}/mount_manifest.tmp
219                                                         ;;
220                                         esac
221                                 done < ${TMPDIR}/fs_build_chroot:descendant/$directory/list
222                                 ;;
223                         esac
224                 done < ${TMPDIR}/fs_build_chroot:directories
225                 grep -Ev -f "${TMPDIR}/fs_build_chroot:shared_dirs:added" "${DBDIR}/shared_dirs.lst" | while read shared_dir
226                 do
227                         mkdir -p "$shared_dir"
228                         mp_share=`realpath "$shared_dir"`
229                         printf '%s\t%s\t%s\t%s\n' nullfs "$mp_share" "/$shared_dir" rw >> ${DBDIR}/mount_manifest.tmp
230                 done
231                 for directory in dev proc tmp 
232                 do
233                         [ -e $directory ] || mkdir $directory
234                 done
235                 printf '%s\t%s\t%s\t%s\n' devfs devfs dev rw >> ${DBDIR}/mount_manifest.tmp
236                 printf '%s\t%s\t%s\t%s\n' fdescfs fdesc dev/fd rw >> ${DBDIR}/mount_manifest.tmp
237                 printf '%s\t%s\t%s\t%s\n' procfs proc proc rw >> ${DBDIR}/mount_manifest.tmp
238                 printf '%s\t%s\t%s\t%s\n' tmpfs tmpfs tmp rw,mode=1777 >> ${DBDIR}/mount_manifest.tmp
239                 mkdir -p ."${PROGRAM}"
240                 cd "/$opt_basedir/mask"
241                 if [ ! -e root/.cshrc ]
242                 then
243                         tmp_cshrc=${TMPDIR}/fs_build_chroot:.cshrc
244                         [ -d root ] || mkdir root
245                         if [ -e /root/.cshrc ]
246                         then
247                                 cp -p /root/.cshrc "$tmp_cshrc"
248                                 cp -p /root/.cshrc "root/.cshrc.bak-${APPNAME}"
249                         elif [ -e /usr/share/skel/dot.cshrc ]
250                         then
251                                 cp -p /usr/share/skel/dot.cshrc "$tmp_cshrc"
252                                 touch "root/.cshrc.bak-${APPNAME}"
253                         else
254                                 cp /dev/null "$tmp_cshrc"
255                         fi
256                         echo >> $tmp_cshrc
257                         echo 'set prompt="%N@[builder]%m:%~ %# "' >> $tmp_cshrc
258                         mv "$tmp_cshrc" root/.cshrc
259                 fi
260                 printf '%s\t%s\t%s\t%s\n' nullfs "/$opt_basedir"/store ".${PROGRAM}" rw >> ${DBDIR}/mount_manifest.tmp
261         )
262         mv "${DBDIR}/mount_manifest.tmp" "${DBDIR}/mount_manifest"
263 }
264
265 # ============= Check whether the file systems for the builder chroot environment are all mounted =============
266 fs_chk_mount ()
267 {
268         local systembase_target systembase_mp tmp_remains
269         [ -e "${DBDIR}/mount_manifest" ] || return
270         systembase_target=`fs_system_base_in_target` || return
271         systembase_mp=`fs_system_base_in_mp_reference`
272         tmp_remains=${TMPDIR}/fs_chk_mount:remains
273         rm -rf "$tmp_remains"
274         while read srcline
275         do
276                 type=`echo "$srcline" | cut -f 1`
277                 target=`echo "$srcline" | cut -f 2`
278                 [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=`str_regularize_df_path "$systembase_target/$target"`
279                 directory=`echo "$srcline" | cut -f 3`
280                 opt=`echo "$srcline" | cut -f 4`
281                 mp=`str_regularize_df_path "$systembase_mp/$opt_basedir/builder/$directory"`
282                 if ! fs_chk_mounted "$type" "$target" "$mp"
283                 then
284                         printf '%s\t%s\t%s\n' "$type" "$target" "$mp" >> $tmp_remains
285                 fi
286         done < ${DBDIR}/mount_manifest
287         ! cat "$tmp_remains" 2> /dev/null
288 }
289
290 # ============= Terminate when the file systems for the builder chroot environment cannot be mounted =============
291 fs_terminate_if_mount_unavailable ()
292 {
293         local systembase systembase_saved
294         systembase=`fs_get_current_systembase`
295         fs_chk_mount > /dev/null && return
296         if systembase_saved=`fs_get_mounttime_systembase`
297         then
298                 if [ "x$systembase" = "x$systembase_saved" ]
299                 then
300                         fs_chk_mount_privilege && return
301                 elif [ -n "$systembase" ]
302                 then
303                         temp_terminate_process ()
304                         {
305                                 message_echo "ERROR: Cannot mount because the current file systems are being mounted from inside the virtual (chroot or jail) environment."  >&2
306                                 message_echo "INFO: Instead of this command, mount from inside the virtual (chroot or jail) environment."
307                         }
308                         [ $TEMP_IN_TRAP = no ] || temp_terminate_process
309                         exit 1
310                 fi
311         elif fs_chk_mount_privilege
312         then
313                 fs_save_mounttime_systembase "`fs_get_current_systembase`"
314                 return
315         fi
316         temp_terminate_process ()
317         {
318                 local basedir
319                 [ $opt_batch_mode = yes ] && return
320                 message_echo
321                 message_echo "INFO: Terminated for mounting file systems because this utility was executed at a virtual (chroot or jail) environment."
322                 message_echo "Execute"
323                 basedir=`fs_get_system_basedir`
324                 if [ -n "$basedir" ]
325                 then
326                         message_echo "  $basedir${SHAREDIR}/bin/portsreinstall-chroot-mount"
327                         message_echo "at the grand host environment."
328                 else
329                         message_echo "  \$BASEDIR${SHAREDIR}/bin/portsreinstall-chroot-mount"
330                         message_echo "at the grand host environment, where \$BASEDIR denotes the base directory of this virtual environment."
331                 fi
332                 message_echo "After its successful execution, rerun"
333                 if [ -n "$COMMAND_RESTART" ]
334                 then
335                         message_echo "  ${APPNAME} $COMMAND_RESTART"
336                 else
337                         message_echo "  ${APPNAME}"
338                 fi
339         }
340         [ $TEMP_IN_TRAP = no ] || temp_terminate_process
341         exit 2
342 }
343
344 # ============= Generate a custom fstab file for the builder chroot environment =============
345 fs_gen_fstab ()
346 {
347         local stage systembase_target systembase_mp
348         stage=$1
349         systembase_target=`fs_system_base_in_target`
350         case $stage in
351         mount )
352                 systembase_mp=`fs_system_base_in_mp_creation`
353                 ;;
354         unmount )
355                 systembase_mp=`fs_system_base_in_mp_reference`
356                 ;;
357         esac
358         fs_safeguard_basedir "$opt_basedir"
359         while read srcline
360         do
361                 type=`echo "$srcline" | cut -f 1`
362                 target=`echo "$srcline" | cut -f 2`
363                 directory=`echo "$srcline" | cut -f 3`
364                 opt=`echo "$srcline" | cut -f 4`
365                 [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase_target/$target
366                 target=`str_regularize_df_path "$target"`
367                 mp=`str_regularize_df_path "$systembase_mp/$opt_basedir/builder/$directory"`
368                 opt=`echo "$opt" | sed 's/[[:space:]]/\\040/g'`
369                 echo "$target $mp $type $opt 0 0"
370         done < ${DBDIR}/mount_manifest > ${DBDIR}/fstab
371 }
372
373 # ============= Mount the file systems for the builder chroot environment if not yet =============
374 fs_mount ()
375 {
376         local remining
377         if fs_chk_mount > /dev/null
378         then
379                 message_echo "The builder chroot environment is already mounted."
380                 message_echo
381                 return
382         fi
383         fs_terminate_if_mount_unavailable
384         message_section_title "Mounting the file systems for builder chroot environment."
385         fs_gen_fstab mount
386         remining=
387         if ! mount -F "${DBDIR}/fstab" -a || ! remining=`fs_chk_mount`
388         then
389                 cp "${DBDIR}/fstab" "${DBDIR}/fstab-mount-err"
390                 message_echo "ERROR: Failed to mount the file systems. The followings remain unmounted:" >&2
391                 if [ $opt_batch_mode = no ]
392                 then
393                         [ -n "$remining" ] || remining=`fs_chk_mount` || :
394                         echo "$remining" >&2
395                 fi
396                 exit 1
397         fi
398         message_echo "Mounting done."
399         message_echo
400 }
401
402 # ============= Check whether the file systems for the builder chroot environment are all unmounted or destroyed =============
403 fs_chk_unmount ()
404 {
405         local systembase_target systembase_mp tmp_remains
406         [ -e "${DBDIR}/mount_manifest" ] || return 0
407         systembase_target=`fs_system_base_in_target` || return 0
408         systembase_mp=`fs_system_base_in_mp_reference`
409         tmp_remains=${TMPDIR}/fs_chk_unmount:remains
410         rm -rf "$tmp_remains"
411         tail -r "${DBDIR}/mount_manifest" | while read srcline
412         do
413                 type=`echo "$srcline" | cut -f 1`
414                 target=`echo "$srcline" | cut -f 2`
415                 [ "x$type" = xnullfs -o "x$type" = xunionfs ] && target=$systembase_target/$target
416                 directory=`echo "$srcline" | cut -f 3`
417                 opt=`echo "$srcline" | cut -f 4`
418                 mp=$systembase_mp/$opt_basedir/builder/$directory
419                 fs_chk_mounted "$type" "$target" "$mp" || continue
420                 str_regularize_df_path "$mp" >> $tmp_remains
421         done
422         ! cat "$tmp_remains" 2> /dev/null
423 }
424
425 # ============= Terminate when the file systems for the builder chroot environment cannot be unmounted =============
426 fs_terminate_if_unmount_unavailable ()
427 {
428         local systembase systembase_saved
429         systembase=`fs_get_current_systembase`
430         systembase_saved=`fs_get_mounttime_systembase` || return 0
431         fs_chk_unmount > /dev/null && return
432         if [ "x$systembase" = "x$systembase_saved" ]
433         then
434                 fs_chk_mount_privilege && return
435         elif [ -n "$systembase" ]
436         then
437                 temp_terminate_process ()
438                 {
439                         message_echo "ERROR: Cannot unmount because the current file systems were mounted from inside the virtual (chroot or jail) environment."  >&2
440                         message_echo "INFO: Instead of this command, unmount from inside the virtual (chroot or jail) environment."
441                 }
442                 [ $TEMP_IN_TRAP = no ] || temp_terminate_process
443                 exit 1
444         fi
445         temp_terminate_process ()
446         {
447                 local errno basedir
448                 errno=${1:-0}
449                 [ $opt_batch_mode = yes ] && return
450                 message_echo
451                 message_echo "INFO: Terminated for unmounting file systems because this utility was executed at a virtual (chroot or jail) environment."
452                 message_echo "Execute"
453                 basedir=`fs_get_system_basedir`
454                 if [ -n "$basedir" ]
455                 then
456                         message_echo "  $basedir${SHAREDIR}/bin/portsreinstall-chroot-mount unmount"
457                         message_echo "at the grand host environment."
458                 else
459                         message_echo "  \$BASEDIR${SHAREDIR}/bin/portsreinstall-chroot-mount unmount"
460                         message_echo "at the grand host environment, where \$BASEDIR denotes the base directory of this virtual environment."
461                 fi
462                 message_echo "After its successful execution, rerun"
463                 if [ -n "$COMMAND_RESTART" ]
464                 then
465                         message_echo "  ${APPNAME} $COMMAND_RESTART"
466                 else
467                         message_echo "  ${APPNAME}"
468                 fi
469         }
470         [ $TEMP_IN_TRAP = no ] || temp_terminate_process
471         exit 3
472 }
473
474 # ============= Unmount  file systems for the chroot environment =============
475 fs_unmount ()
476 {
477         local systembase_access systembase_saved remining
478         systembase_access=`fs_system_base_in_mp_access`
479         ! fs_get_mounttime_systembase > /dev/null && return
480         fs_terminate_if_unmount_unavailable
481         [ ! -d "$systembase_access/$opt_basedir"/builder ] && return
482         [ ! -e "${DBDIR}/mount_manifest" ] && return
483         if fs_chk_unmount > /dev/null
484         then
485                 if [ $TEMP_IN_TRAP = no ]
486                 then
487                         message_echo "The builder chroot environment is already unmounted."
488                         message_echo
489                 fi
490                 return
491         fi
492         if [ $TEMP_IN_TRAP = no ]
493         then
494                 message_section_title "Unmounting the file systems for builder chroot."
495         else
496                 message_echo
497                 message_echo "Unmounting the file systems for builder chroot."
498         fi
499         fs_gen_fstab unmount
500         umount -F "${DBDIR}/fstab" -af 2> /dev/null || :
501         itrial=${FS_UNMOUNT_RETIAL_MAXNUM}
502         while [ $itrial -gt 0 ]
503         do
504                 remining=`fs_chk_unmount` && break
505                 echo -n "$remining" | str_regularize_df_path_filter | while read remining_mp
506                 do
507                         umount -f "$remining_mp" || :
508                 done
509                 message_echo "(Retrying to unmount the file systems...)" >&2
510                 sleep ${FS_UNMOUNT_RETIAL_WAIT}
511                 umount -F "${DBDIR}/fstab" -af 2> /dev/null || :
512                 itrial=$(($itrial-1))
513         done
514         if [ $itrial -eq 0 ]
515         then
516                 message_echo "WARNING: Failed to unmount the file systems. Some of them remain mounted." >&2
517                 return 1
518         fi
519         rm -f "${DBDIR}/fs_systembase"
520         message_echo "Unmounting done."
521         message_echo
522 }
523
524 # ============= Destroy the chroot environment =============
525 fs_destroy ()
526 {
527         fs_chk_safety_basedir "$opt_basedir" || return 0
528         [ ! -d "$opt_basedir" ] && return
529         fs_unmount || return
530         chflags -R noschg "$opt_basedir"
531         rm -rf "$opt_basedir"
532 }