Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
comparison sbin/fjail @ 177:9ffbe53dbc35
Flag for creating a separatate dataset for freebsd-update data.
By default this is not needed in jails.
| author | Franz Glasner <hg@dom66.de> |
|---|---|
| date | Tue, 16 Aug 2022 11:44:56 +0200 |
| parents | cf0a91fde79c |
| children | 00fbf2b4b44f |
comparison
equal
deleted
inserted
replaced
| 176:cf0a91fde79c | 177:9ffbe53dbc35 |
|---|---|
| 32 | 32 |
| 33 Create ZFS datasets to be used within a jail | 33 Create ZFS datasets to be used within a jail |
| 34 | 34 |
| 35 PARENT must exist already and CHILD must not exist. | 35 PARENT must exist already and CHILD must not exist. |
| 36 | 36 |
| 37 -s Also create a dataset for freebsd-update data files | |
| 37 -u Do not automatically mount newly created datasets | 38 -u Do not automatically mount newly created datasets |
| 38 | 39 |
| 39 privs MOUNTPOINT | 40 privs MOUNTPOINT |
| 40 | 41 |
| 41 Adjust some Unix privileges to mounted jail datasets | 42 Adjust some Unix privileges to mounted jail datasets |
| 119 local _pds _cds | 120 local _pds _cds |
| 120 # and its mount point | 121 # and its mount point |
| 121 local _pmp _get _dummy | 122 local _pmp _get _dummy |
| 122 # full name of the dataset | 123 # full name of the dataset |
| 123 local _ds | 124 local _ds |
| 125 # dynamic ZFS options -- create cache for freebsd-update | |
| 126 local _zfsopts _fbsdupdate | |
| 127 | |
| 128 _zfsopts="" | |
| 129 _fbsdupdate="" | |
| 130 while getopts "us" _opt ; do | |
| 131 case ${_opt} in | |
| 132 u) | |
| 133 # do not mount newly created datasets | |
| 134 _zfsopts="${_zfsopts} -u" | |
| 135 ;; | |
| 136 s) | |
| 137 # create also a dataset for freebsd-update data | |
| 138 _fbsdupdate="yes" | |
| 139 \?|:) | |
| 140 return 2; | |
| 141 ;; | |
| 142 esac | |
| 143 done | |
| 144 shift $((OPTIND-1)) | |
| 145 OPTIND=1 | |
| 146 | |
| 147 _pds="$1" | |
| 148 if [ -z "${_pds}" ]; then | |
| 149 echo "ERROR: no parent dataset given" >&2 | |
| 150 return 2 | |
| 151 fi | |
| 152 _get=$(zfs get -H mountpoint "${_pds}" 2>/dev/null) || { echo "ERROR: dataset \`${_pds}' does not exist" >&2; return 1; } | |
| 153 IFS=$'\t' read _dummy _dummy _pmp _dummy <<EOF | |
| 154 ${_get} | |
| 155 EOF | |
| 156 case "${_pmp}" in | |
| 157 none) | |
| 158 echo "ERROR: dataset \`${_pds}' has no mountpoint" >&2 | |
| 159 return 1 | |
| 160 ;; | |
| 161 legacy) | |
| 162 echo "ERROR: dataset \`${_pds}' has a \`${_mp}' mountpoint" >&2 | |
| 163 return 1 | |
| 164 ;; | |
| 165 *) | |
| 166 # VOID | |
| 167 ;; | |
| 168 esac | |
| 169 _cds="$2" | |
| 170 if [ -z "${_cds}" ]; then | |
| 171 echo "ERROR: no child dataset given" >&2 | |
| 172 return 2 | |
| 173 fi | |
| 174 _ds="${_pds}/${_cds}" | |
| 175 echo "Resulting new root dataset is \`${_ds}' at mountpoint \`${_pmp}/${_cds}'" | |
| 176 if zfs get -H mountpoint "${_ds}" >/dev/null 2>/dev/null; then | |
| 177 echo "ERROR: dataset \`${_ds}' does already exist" >&2 | |
| 178 return 1 | |
| 179 fi | |
| 180 zfs create ${_zfsopts} -o atime=off "${_ds}" | |
| 181 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/tmp" | |
| 182 zfs create ${_zfsopts} "${_ds}/usr" | |
| 183 zfs create ${_zfsopts} -o setuid=off "${_ds}/usr/home" | |
| 184 zfs create ${_zfsopts} "${_ds}/usr/local" | |
| 185 zfs create ${_zfsopts} "${_ds}/var" | |
| 186 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/audit" | |
| 187 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/cache" | |
| 188 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata -o compression=off "${_ds}/var/cache/pkg" | |
| 189 zfs create ${_zfsopts} -o exec=off -o setuid=off -o compression=off "${_ds}/var/crash" | |
| 190 if [ "$_fbsdupdate" = "yes" ]; then | |
| 191 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata -o compression=off "${_ds}/var/db/freebsd-update" | |
| 192 fi | |
| 193 zfs create ${_zfsopts} -o readonly=on -o exec=off -o setuid=off "${_ds}/var/empty" | |
| 194 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata "${_ds}/var/log" | |
| 195 zfs create ${_zfsopts} -o exec=off -o setuid=off -o atime=on "${_ds}/var/mail" | |
| 196 zfs create ${_zfsopts} -o sync=disabled -o exec=off -o setuid=off -o compression=off -o primarycache=all "${_ds}/var/run" | |
| 197 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/var/tmp" | |
| 198 } | |
| 199 | |
| 200 | |
| 201 # | |
| 202 # "populate" -- populate the datasets with content from a FreeBSD base.txz | |
| 203 # | |
| 204 # command_populate mountpoint basetxz | |
| 205 # | |
| 206 command_populate() { | |
| 207 # MOUNTPOINT -- base.txz | |
| 208 local _mp _basetxz | |
| 209 | |
| 210 _mp="$1" | |
| 211 _basetxz="$2" | |
| 212 | |
| 213 if [ -z "${_mp}" ]; then | |
| 214 echo "ERROR: no mountpoint given" >&2 | |
| 215 return 2 | |
| 216 fi | |
| 217 if [ -z "${_basetxz}" ]; then | |
| 218 echo "ERROR: no base.txz given" >&2 | |
| 219 return 2 | |
| 220 fi | |
| 221 if [ ! -d "${_mp}" ]; then | |
| 222 echo "ERROR: mountpoint \`${_mp}' does not exist" >&2 | |
| 223 return 1 | |
| 224 fi | |
| 225 if [ ! -r "${_basetxz}" ]; then | |
| 226 echo "ERROR: file \`${_basetxz}' is not readable" >&2 | |
| 227 return 1 | |
| 228 fi | |
| 229 | |
| 230 # | |
| 231 # Handle /var/empty separately later: could be already there and | |
| 232 # mounted read-only. | |
| 233 # | |
| 234 tar -C "${_mp}" --exclude=./var/empty -xJp -f "${_basetxz}" || { echo "ERROR: tar encountered errors" >&2; return 1; } | |
| 235 if [ -d "${_mp}/var/empty" ]; then | |
| 236 # | |
| 237 # If /var/empty exists already try to extract with changing the | |
| 238 # flags (e.g. `schg'). But be tolerant with errors here. | |
| 239 # | |
| 240 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty | |
| 241 else | |
| 242 # Just extract /var/empty normally | |
| 243 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty || { echo "ERROR: tar encountered errors" >&2; return 1; } | |
| 244 fi | |
| 245 | |
| 246 find "${_mp}/boot" -type f -delete | |
| 247 } | |
| 248 | |
| 249 | |
| 250 # | |
| 251 # "copy" -- ZFS copy of datasets | |
| 252 # | |
| 253 # command_copy source-dataset destination-dataset | |
| 254 # | |
| 255 command_copy() { | |
| 256 # source dataset -- destination dataset | |
| 257 local _source _dest | |
| 124 # dynamic ZFS options | 258 # dynamic ZFS options |
| 125 local _zfsopts | 259 local _zfsopts |
| 126 | 260 |
| 127 _zfsopts="" | 261 _zfsopts="" |
| 128 while getopts "u" _opt ; do | 262 while getopts "u" _opt ; do |
| 137 esac | 271 esac |
| 138 done | 272 done |
| 139 shift $((OPTIND-1)) | 273 shift $((OPTIND-1)) |
| 140 OPTIND=1 | 274 OPTIND=1 |
| 141 | 275 |
| 142 _pds="$1" | |
| 143 if [ -z "${_pds}" ]; then | |
| 144 echo "ERROR: no parent dataset given" >&2 | |
| 145 return 2 | |
| 146 fi | |
| 147 _get=$(zfs get -H mountpoint "${_pds}" 2>/dev/null) || { echo "ERROR: dataset \`${_pds}' does not exist" >&2; return 1; } | |
| 148 IFS=$'\t' read _dummy _dummy _pmp _dummy <<EOF | |
| 149 ${_get} | |
| 150 EOF | |
| 151 case "${_pmp}" in | |
| 152 none) | |
| 153 echo "ERROR: dataset \`${_pds}' has no mountpoint" >&2 | |
| 154 return 1 | |
| 155 ;; | |
| 156 legacy) | |
| 157 echo "ERROR: dataset \`${_pds}' has a \`${_mp}' mountpoint" >&2 | |
| 158 return 1 | |
| 159 ;; | |
| 160 *) | |
| 161 # VOID | |
| 162 ;; | |
| 163 esac | |
| 164 _cds="$2" | |
| 165 if [ -z "${_cds}" ]; then | |
| 166 echo "ERROR: no child dataset given" >&2 | |
| 167 return 2 | |
| 168 fi | |
| 169 _ds="${_pds}/${_cds}" | |
| 170 echo "Resulting new root dataset is \`${_ds}' at mountpoint \`${_pmp}/${_cds}'" | |
| 171 if zfs get -H mountpoint "${_ds}" >/dev/null 2>/dev/null; then | |
| 172 echo "ERROR: dataset \`${_ds}' does already exist" >&2 | |
| 173 return 1 | |
| 174 fi | |
| 175 zfs create ${_zfsopts} -o atime=off "${_ds}" | |
| 176 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/tmp" | |
| 177 zfs create ${_zfsopts} "${_ds}/usr" | |
| 178 zfs create ${_zfsopts} -o setuid=off "${_ds}/usr/home" | |
| 179 zfs create ${_zfsopts} "${_ds}/usr/local" | |
| 180 zfs create ${_zfsopts} "${_ds}/var" | |
| 181 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/audit" | |
| 182 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/cache" | |
| 183 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata -o compression=off "${_ds}/var/cache/pkg" | |
| 184 zfs create ${_zfsopts} -o exec=off -o setuid=off -o compression=off "${_ds}/var/crash" | |
| 185 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/db" | |
| 186 zfs create ${_zfsopts} -o readonly=on -o exec=off -o setuid=off "${_ds}/var/empty" | |
| 187 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata "${_ds}/var/log" | |
| 188 zfs create ${_zfsopts} -o exec=off -o setuid=off -o atime=on "${_ds}/var/mail" | |
| 189 zfs create ${_zfsopts} -o sync=disabled -o exec=off -o setuid=off -o compression=off -o primarycache=all "${_ds}/var/run" | |
| 190 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/var/tmp" | |
| 191 } | |
| 192 | |
| 193 | |
| 194 # | |
| 195 # "populate" -- populate the datasets with content from a FreeBSD base.txz | |
| 196 # | |
| 197 # command_populate mountpoint basetxz | |
| 198 # | |
| 199 command_populate() { | |
| 200 # MOUNTPOINT -- base.txz | |
| 201 local _mp _basetxz | |
| 202 | |
| 203 _mp="$1" | |
| 204 _basetxz="$2" | |
| 205 | |
| 206 if [ -z "${_mp}" ]; then | |
| 207 echo "ERROR: no mountpoint given" >&2 | |
| 208 return 2 | |
| 209 fi | |
| 210 if [ -z "${_basetxz}" ]; then | |
| 211 echo "ERROR: no base.txz given" >&2 | |
| 212 return 2 | |
| 213 fi | |
| 214 if [ ! -d "${_mp}" ]; then | |
| 215 echo "ERROR: mountpoint \`${_mp}' does not exist" >&2 | |
| 216 return 1 | |
| 217 fi | |
| 218 if [ ! -r "${_basetxz}" ]; then | |
| 219 echo "ERROR: file \`${_basetxz}' is not readable" >&2 | |
| 220 return 1 | |
| 221 fi | |
| 222 | |
| 223 # | |
| 224 # Handle /var/empty separately later: could be already there and | |
| 225 # mounted read-only. | |
| 226 # | |
| 227 tar -C "${_mp}" --exclude=./var/empty -xJp -f "${_basetxz}" || { echo "ERROR: tar encountered errors" >&2; return 1; } | |
| 228 if [ -d "${_mp}/var/empty" ]; then | |
| 229 # | |
| 230 # If /var/empty exists already try to extract with changing the | |
| 231 # flags (e.g. `schg'). But be tolerant with errors here. | |
| 232 # | |
| 233 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty | |
| 234 else | |
| 235 # Just extract /var/empty normally | |
| 236 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty || { echo "ERROR: tar encountered errors" >&2; return 1; } | |
| 237 fi | |
| 238 | |
| 239 find "${_mp}/boot" -type f -delete | |
| 240 } | |
| 241 | |
| 242 | |
| 243 # | |
| 244 # "copy" -- ZFS copy of datasets | |
| 245 # | |
| 246 # command_copy source-dataset destination-dataset | |
| 247 # | |
| 248 command_copy() { | |
| 249 # source dataset -- destination dataset | |
| 250 local _source _dest | |
| 251 # dynamic ZFS options | |
| 252 local _zfsopts | |
| 253 | |
| 254 _zfsopts="" | |
| 255 while getopts "u" _opt ; do | |
| 256 case ${_opt} in | |
| 257 u) | |
| 258 # do not mount newly created datasets | |
| 259 _zfsopts="${_zfsopts} -u" | |
| 260 ;; | |
| 261 \?|:) | |
| 262 return 2; | |
| 263 ;; | |
| 264 esac | |
| 265 done | |
| 266 shift $((OPTIND-1)) | |
| 267 OPTIND=1 | |
| 268 | |
| 269 _source="$1" | 276 _source="$1" |
| 270 if [ -z "${_source}" ]; then | 277 if [ -z "${_source}" ]; then |
| 271 echo "ERROR: no source dataset given" >&2 | 278 echo "ERROR: no source dataset given" >&2 |
| 272 return 2 | 279 return 2 |
| 273 fi | 280 fi |
