comparison sbin/ftjail @ 334:fdbb78c54ffb

Begin the "ftjail freebsd-update" command
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 02 Dec 2022 09:36:57 +0100
parents 8dbd11726ee5
children a423bc0e2a3f
comparison
equal deleted inserted replaced
333:ebf6c8863d9b 334:fdbb78c54ffb
98 return 0 98 return 0
99 fi 99 fi
100 done 100 done
101 return 1 101 return 1
102 } 102 }
103 }
104
105
106 #:
107 #: Search for a running jail where it's "path" points to a given location
108 #:
109 #: Args:
110 #: $1: the location to search for
111 #:
112 #: Output (stdout):
113 #: The name if the jail with a "path" that is equal to the input param.
114 #: Nothing if a jail is not found.
115 #:
116 #: Return:
117 #: - 0: if a running jail is found
118 #: - 1: error
119 #: - 2: no running jail found
120 #: - 3: jail found but currently dying
121 #:
122 _get_jail_from_path() {
123 local _location
124
125 local _name _path _dying
126
127 _location="${1-}"
128 [ -z "${_location}" ] && { echo "ERROR: no mountpoint given" 1>&2; return 1; }
129
130
131 jls -d name path dying \
132 | {
133 while IFS=' '$'\t' read -r _name _path _dying ; do
134 if [ "${_path}" = "${_location}" ]; then
135 if [ "${_dying}" != "false" ]; then
136 echo "Jail \`${_name}' is currently dying" 1>&2
137 return 3
138 fi
139 echo "${_name}"
140 return 0
141 fi
142 done
143 return 2
144 }
145 }
146
147
148 #:
149 #: Search for mounts and sub-mounts at a given directory.
150 #:
151 #: The output is sorted by the mountpoint.
152 #:
153 #: Args:
154 #: $1: the directory where to start for mounts and sub-mounts
155 #:
156 #: Output (stdout):
157 #: The sorted list (lines) of mounts in :manpage:`fstab(5)` format.
158 #: This list may be empty.
159 #:
160 #: Exit:
161 #: 1: on fatal errors (usage et al.)
162 #:
163 #: Important:
164 #: The input directory **must** be an absolute path.
165 #:
166 _get_mounts_at_directory() {
167 local _directory
168
169 local _fstab
170
171 _directory=${1-}
172 case "${_directory}" in
173 /*)
174 :
175 ;;
176 '')
177 echo "ERROR: no directory given" 1>&2;
178 exit 1;
179 ;;
180 *)
181 echo "ERROR: directory must be an absolute path" 1>&2;
182 exit 1;
183 ;;
184 esac
185 _fstab="$(mount -p | grep -E '\s'"${_directory}" | sort -k3)"
186 echo "${_fstab}"
103 } 187 }
104 188
105 189
106 # 190 #
107 # PARENT-BASE NAME DRY-RUN 191 # PARENT-BASE NAME DRY-RUN
785 return 1 869 return 1
786 fi 870 fi
787 } 871 }
788 872
789 873
874 #:
875 #: Implement the "freebsd-update" command for a thin jail
876 #:
877 command_freebsd_update() {
878 local _directory
879
880 local _res _jailname _dir_mounts _dir_fn_fstab _dir_basename
881 local _root_dataset _root_mountpoint _root_type _root_options
882 local _dummy
883 local _root_readonly
884
885 _directory="${1-}"
886
887 [ -z "${_directory}" ] && { echo "ERROR: no directory given" 1>&2; return 2; }
888 [ -d "${_directory}" ] || { echo "ERROR: directory \`${_directory}' does not exist" 1>&2; exit 1; }
889
890 _dir_basename="$(basename ${_directory})"
891
892 set +e
893 _jailname=$(_get_jail_from_path "${_directory}")ยด
894 _res=$?
895 set -e
896 if [ ${_res} -ne 2 ] ; then
897 if [ ${_res} -ne 0 ] ; then
898 exit ${_res}
899 else
900 echo "ERROR: Please stop the \`${_jailname}' jail" >&2
901 exit 1
902 fi
903 fi
904 _dir_mounts="$(_get_mounts_at_directory "${_directory}")"
905
906 #
907 # Check preconditions thoroughly!
908 #
909 # Check that the first item/line is a read-only ZFS mount directly
910 # at the given directory.
911 # Also check that it is a clone proper.
912 #
913 IFS=' '$'\t' read -r _root_dataset _root_mountpoint _root_type _root_options _dummy <<EOF4tHGCSS
914 ${_dir_mounts}
915 EOF4tHGCSS
916 [ "${_root_mountpoint}" != "${_directory}" ] && { echo "ERROR: found root mountpoint does not match given directory" 1>&2; exit 1; }
917 [ "${_root_type}" != "zfs" ] && { echo "ERROR: root mountpoint is not from a ZFS dataset" 1>&2; exit 1; }
918 _root_readonly="$(zfs list -H -o readonly "${_root_dataset}")"
919 [ "${_root_readonly}" != "on" ] && { echo "ERROR: the root dataset is not mounted read-only" 1>&2; exit 1; }
920 # XXX TBD: Check that it is a proper clone
921
922 #
923 # XXX FIXME: should we check that _root_options equals "ro" or
924 # start with "ro,"
925 #
926 _dir_fn_fstab="$(env TMPDIR=/var/tmp mktemp -t ftjail-fstab.${_dir_basename})"
927 echo -n "${_dir_mounts}" >>"${_dir_fn_fstab}"
928
929 # Unmount in reverse order: unmount can do it for us
930 umount -a -F "${_dir_fn_fstab}" -v || exit 1
931
932 #
933 # XXX TBD: Hooks to create some new top-level dirs (/srv /proc et
934 # al.) if needed: clone RW, mount, make the dirs,
935 # umount, make the clone RO and continue "normally" by
936 # completely mounting the stored fstab.
937 #
938 }
939
940
790 # 941 #
791 # Global option handling 942 # Global option handling
792 # 943 #
793 while getopts "Vh" _opt ; do 944 while getopts "Vh" _opt ; do
794 case ${_opt} in 945 case ${_opt} in
849 ;; 1000 ;;
850 configure) 1001 configure)
851 echo "ERROR: use \`fjail configure' instead" 1>&2; 1002 echo "ERROR: use \`fjail configure' instead" 1>&2;
852 exit 2 1003 exit 2
853 ;; 1004 ;;
1005 freebsd-update)
1006 command_freebsd_update "$@"
1007 ;;
854 *) 1008 *)
855 echo "ERROR: unknown command \`${command}'" 1>&2 1009 echo "ERROR: unknown command \`${command}'" 1>&2
856 exit 2 1010 exit 2
857 ;; 1011 ;;
858 esac 1012 esac