comparison sbin/ftjail @ 658:260a81d769a6

Implemented "ftjail check-freebsd-update": thorough check for preconditions to a successful run of "ftjail freebsd-update". All checks that "ftjail freebsd-update" does are replicated in "ftjail check-freebsd-update".
author Franz Glasner <fzglas.hg@dom66.de>
date Sat, 28 Sep 2024 19:12:05 +0200
parents db22766df6a4
children 82a98db83a13
comparison
equal deleted inserted replaced
657:db22766df6a4 658:260a81d769a6
59 59
60 60
61 _p_datadir='@@DATADIR@@' 61 _p_datadir='@@DATADIR@@'
62 [ "${_p_datadir#@@DATADIR}" = '@@' ] && _p_datadir="$(dirname "$0")"/../share/local-bsdtools 62 [ "${_p_datadir#@@DATADIR}" = '@@' ] && _p_datadir="$(dirname "$0")"/../share/local-bsdtools
63 . "${_p_datadir}/common.subr" 63 . "${_p_datadir}/common.subr"
64 . "${_p_datadir}/farray.sh"
64 65
65 66
66 # Reset to standard umask 67 # Reset to standard umask
67 umask 0022 68 umask 0022
68 69
856 } 857 }
857 } 858 }
858 859
859 860
860 #: 861 #:
862 #: Callback for _print_check_errors
863 #:
864 _print_check_error() {
865 printf '%s CHECK: %s\n' '-' "$3" 1>&2
866 return 0
867 }
868
869
870 #:
871 #: Print all the errors to stderr
872 #:
873 _print_check_errors() {
874 farray_istrue "$1" || return 0
875 echo "There are ERRORs to be resolved before \`freebsd-update' can be run:" 1>&2
876 farray_for_each "$1" _print_check_error
877 }
878
879
880 #:
881 #: Callback for _print_check_warnings
882 #:
883 _print_check_warning() {
884 printf '%s WARNING: %s\n' '-' "$3" 1>&2
885 return 0
886 }
887
888
889 #:
890 #: Print all the warnings to stderr
891 #:
892 _print_check_warnings() {
893 farray_istrue "$1" || return 0
894 echo "There are WARNINGs to be considered before \`freebsd-update' should be run:" 1>&2
895 farray_for_each "$1" _print_check_warning
896 }
897
898
899 #:
900 #: Implement the "check-freebsd-update" command for a thin jail
901 #:
902 command_check_freebsd_update() {
903 local _directory _new_origin _etcupdate_tarball
904 local _opt_keep _opt_old_origin
905
906 local _errors _warnings _rc
907 local _directory _new_origin _etcupdate_tarball
908 local _dir_basename _dir_mounts _jailname _tmp _line _log_sock
909 local _root_dataset _root_mountpoint _root_type _root_options
910 local _mnt_device _mnt_mountpoint _mnt_type _mnt_options
911
912 _rc=0
913
914 _warnings=''
915 farray_create _warnings XXX
916 _errors=''
917 farray_create _errors
918
919 _opt_keep="no"
920 _opt_old_origin=""
921 while getopts "ko:" _opt ; do
922 case "${_opt}" in
923 k)
924 _opt_keep="yes"
925 ;;
926 o)
927 _opt_old_origin="$OPTARG"
928 ;;
929 \?|:)
930 return 2;
931 ;;
932 esac
933 done
934 shift $((OPTIND-1))
935 OPTIND=1
936
937 _directory="${1-}"
938 _new_origin="${2-}"
939 _etcupdate_tarball="${3-}"
940
941 if [ -z "${_directory}" ]; then
942 farray_append _errors "no directory given"
943 else
944 [ -d "${_directory}" ] || farray_append _errors "directory \`${_directory}' does not exist"
945 fi
946 if [ -z "${_new_origin}" ]; then
947 farray_append _errors "no new origin given"
948 else
949 zfs list -H -o name -t snapshot "${_new_origin}" >/dev/null 2>/dev/null || farray_append _errors "ZFS dataset snapshot for the new origin \`${_new_origin}' does not exist"
950 fi
951 if [ -n "${_etcupdate_tarball}" ]; then
952 [ -r "${_etcupdate_tarball}" ] || farray_append _errors "given etcupdate tarball does not exist and/or is not readable"
953 fi
954
955 if [ -n "${_directory}" ]; then
956
957 _dir_basename="$(basename "${_directory}")"
958
959 set +e
960 _jailname="$(_get_jail_from_path "${_directory}")"
961 _tmp=$?
962 set -e
963 case ${_tmp} in
964 0)
965 farray_append _errors "Jail \`${_jailname}' is running. Please stop it."
966 ;;
967 1)
968 farray_append _errors "Cannot determine jail name"
969 ;;
970 3)
971 true
972 ;;
973 2)
974 farray_append _errors "Jail \`${_jailname}' is currently yet dying. Please wait."
975 ;;
976 *)
977 farray_append _errors "UNHANDLED RETURN VALUE from _get_jail_from_path()"
978 ;;
979 esac
980
981 #
982 # Check whether additional log sockets are opened at their default
983 # locations. Because they hinder proper unmounting of filesystems.
984 #
985 for _log_sock in /var/run/log /var/run/logpriv ; do
986 if [ -S "${_directory}${_log_sock}" ]; then
987 farray_append _errors "log socket is open at \`${_directory}${_log_sock}'"
988 fi
989 done
990
991 # Check whether there are any open files or VM mappings within the jail.
992 if ! _check_no_open_files_from_all_proc "${_directory}" ; then
993 farray_append _errors "There are open files or memory mappings within the jail"
994 fi
995
996 _dir_mounts="$(_get_mounts_at_directory "${_directory}")"
997
998 #
999 # Check preconditions thoroughly!
1000 #
1001 # Check that the first item/line is a read-only ZFS mount directly
1002 # at the given directory. This must also be its configured
1003 # mountpoint in ZFS.
1004 # Also check that it is a clone proper.
1005 #
1006 IFS=$'\t' read -r _root_dataset _root_mountpoint _root_type _root_options _line <<EOF4tHGCSSf5d7d9cf
1007 ${_dir_mounts}
1008 EOF4tHGCSSf5d7d9cf
1009 [ "${_root_mountpoint}" != "${_directory}" ] && farray_append _errors "found root mountpoint does not match given directory"
1010 [ "${_root_type}" != "zfs" ] && farray_append _errors "root mountpoint is not from a ZFS dataset"
1011 _root_readonly="$(zfs get -H -o value readonly "${_root_dataset}")"
1012 [ "${_root_readonly}" != "on" ] && farray_append _errors "the root dataset is not mounted read-only"
1013 _root_origin="$(zfs get -H -o value origin "${_root_dataset}")"
1014 if [ -n "${_opt_old_origin}" ]; then
1015 [ "${_opt_old_origin}" != "${_root_origin}" ] && farray_append _errors "origin mismatch"
1016 else
1017 [ "${_root_origin}" = '-' ] && farray_append _errors "the root dataset is not a ZFS clone"
1018 fi
1019 #
1020 # Check for open files on all the mounted filesystems
1021 #
1022 while IFS=$'\t' read -r _mnt_device _mnt_mountpoint _mnt_type _mnt_options _line; do
1023 if ! _check_no_open_files_on_filesystem "${_mnt_mountpoint}" ; then
1024 farray_append _errors "There are open files or memory mapping on file system \`${_mnt_mountpoint}'"
1025 fi
1026 done <<EOF4tHGCAASL775f9f320205
1027 ${_dir_mounts}
1028 EOF4tHGCAASL775f9f320205
1029 fi
1030
1031 if farray_istrue _errors; then
1032 _print_check_errors _errors
1033 _rc=1
1034 fi
1035 # Warnings do not influence the return code
1036 _print_check_warnings _warnings
1037
1038 farray_destroy _errors
1039 farray_destroy _warnings
1040 return ${_rc}
1041 }
1042
1043
1044 #:
861 #: Implement the "freebsd-update" command for a thin jail 1045 #: Implement the "freebsd-update" command for a thin jail
862 #: 1046 #:
863 #: .. note:: FreeBSD's :command:`etcupdate` also executes 1047 #: .. note:: FreeBSD's :command:`etcupdate` also executes
864 #: :command:`certctl rehash` if certs are to be added or removed! 1048 #: :command:`certctl rehash` if certs are to be added or removed!
865 #: 1049 #:
1158 ;; 1342 ;;
1159 configure) 1343 configure)
1160 echo "ERROR: use \`fjail configure' instead" 1>&2; 1344 echo "ERROR: use \`fjail configure' instead" 1>&2;
1161 exit 2 1345 exit 2
1162 ;; 1346 ;;
1347 check-freebsd-update)
1348 command_check_freebsd_update "$@"
1349 ;;
1163 freebsd-update) 1350 freebsd-update)
1164 command_freebsd_update "$@" 1351 command_freebsd_update "$@"
1165 ;; 1352 ;;
1166 *) 1353 *)
1167 echo "ERROR: unknown command \`${command}'" 1>&2 1354 fatal 2 "unknown command \`${command}'"
1168 exit 2
1169 ;; 1355 ;;
1170 esac 1356 esac