mrrl-containers

MRRL version of container scripts
git clone https://ccx.te2000.cz/git/mrrl-containers
Log | Files | Refs

confz_containers_init (64659B)


      1 #  vim: ft=zsh noet ts=4 sts=4 sw=4
      2 
      3 
      4 # find: ‘./event’: Permission denied
      5 # /	d	o0:0	m755
      6 # /flag-newpidns	cN		o0:0	m644
      7 # /data	d	o0:0	m755
      8 # /data/fstab
      9 # CN	/mnt/volumes/containers/alpine-xsession	/mnt/volumes/containers/user/ccx/xsession.6/root	none	bind,ro	0 0
     10 # 	/run/containers/xsession.6.ccx/run	/mnt/volumes/containers/user/ccx/xsession.6/root/run	none	bind	0 0
     11 # 	/run/containers/xsession.6.ccx/tmp	/mnt/volumes/containers/user/ccx/xsession.6/root/tmp	none	bind	0 0
     12 # 	/run/containers/xsession.6.ccx/home	/mnt/volumes/containers/user/ccx/xsession.6/root/home	none	bind	0 0
     13 # 	/run/containers/xsession.6.ccx/inbox	/mnt/volumes/containers/user/ccx/xsession.6/root/run/inbox	none	bind,ro	0 0
     14 # o0:0	m644
     15 # /data/root	l	/mnt/volumes/containers/user/ccx/xsession.6/root	o0:0	m777
     16 # /down	cN		o0:0	m644
     17 # /env	d	o0:0	m755
     18 # /env/CONTAINER_NAME	cN	xsession.6	o0:0	m644
     19 # /env/CONTAINER_USER	cN	ccx	o0:0	m644
     20 # /event	d	o0:100	m3730
     21 # /finish	l	/usr/local/bzr/containers/service_scripts/xsession/finish	o0:0	m777
     22 # /run	l	/usr/local/bzr/containers/service_scripts/xsession/run	o0:0	m777
     23 # /supervise	d	o0:0	m755
     24 # /supervise/control	p	o1000:0	m600
     25 # /supervise/death_tally	cN		o0:0	m644
     26 # /supervise/lock	cN		o1000:0	m644
     27 # /supervise/status	B	QAAAAF/8iBYvOSJcQAAAAF/8iBYvOSJcAAAAAAAAAAAAABQ=
     28 # o0:0	m644
     29 
     30 typeset -gA container_uid_cache container_gid_cache
     31 
     32 container_get_uid() {
     33 	if (($+container_uid_cache[$1])); then
     34 		printf '%s' $container_uid_cache[$1]
     35 		return 0
     36 	else
     37 		local uid
     38 		uid="${${(s.:.)"$(getent passwd $1)"}[3]}" || return $?
     39 		[[ -z $uid ]] && return 1
     40 		container_uid_cache[$1]=$uid
     41 		printf '%s' $uid
     42 		return 0
     43 	fi
     44 }
     45 
     46 container_get_gid() {
     47 	if (($+container_gid_cache[$1])); then
     48 		printf '%s' $container_gid_cache[$1]
     49 		return 0
     50 	else
     51 		local gid
     52 		gid="${${(s.:.)"$(getent group $1)"}[3]}" || return $?
     53 		[[ -z $gid ]] && return 1
     54 		container_gid_cache[$1]=$gid
     55 		printf '%s' $gid
     56 	fi
     57 }
     58 
     59 confz_container_uidgid_for_name_check() {
     60 	checkvars name
     61 	local uid gid
     62 	uid=$(container_get_uid $vars[name]) ||
     63 		die "Could not determine uid for user ${(qqq)vars[name]}"
     64 	gid=$(container_get_gid $vars[name]) ||
     65 		die "Could not determine gid for group ${(qqq)vars[name]}"
     66 	unify uid $uid
     67 	unify gid $gid
     68 }
     69 
     70 confz_container_service_check() {
     71 	checkvars svc_dir root_link run_link finish_link
     72 	defvar down true
     73 	defvar control_user root
     74 	defvar control_group root
     75 	defvar fstab_post ''
     76 
     77 	require fs_d flags=p filename=$vars[svc_dir]
     78 	require fs_m filename=$vars[svc_dir] mode=755
     79 
     80 	if $vars[down]; then
     81 		require fs_f filename=$vars[svc_dir]/down
     82 	else
     83 		require fs_r filename=$vars[svc_dir]/down
     84 	fi
     85 
     86 	require fs_f filename=$vars[svc_dir]/flag-newpidns
     87 
     88 	require fs_d filename=$vars[svc_dir]/data
     89 	require fs_m filename=$vars[svc_dir]/data mode=755
     90 
     91 	require fs_l filename=$vars[svc_dir]/data/root \
     92 		destination=$vars[root_link]
     93 
     94 	if (($+vars[fstab])); then
     95 		require fs_contentnl filename=$vars[svc_dir]/data/fstab \
     96 			content=$vars[fstab]
     97 		require fs_m filename=$vars[svc_dir]/data/fstab mode=644
     98 	else
     99 		require fs_r filename=$vars[svc_dir]/data/fstab
    100 	fi
    101 
    102 	if (($+vars[prepare_chroot])); then
    103 		require fs_contentnl filename=$vars[svc_dir]/data/prepare_chroot \
    104 			content=$vars[prepare_chroot]
    105 		require fs_m filename=$vars[svc_dir]/data/prepare_chroot mode=755
    106 	else
    107 		require fs_r filename=$vars[svc_dir]/data/prepare_chroot
    108 	fi
    109 
    110 	if (($+vars[pid1_exec])); then
    111 		require fs_contentnl filename=$vars[svc_dir]/data/pid1_exec \
    112 			content=$vars[pid1_exec]
    113 		require fs_m filename=$vars[svc_dir]/data/pid1_exec mode=755
    114 	else
    115 		require fs_r filename=$vars[svc_dir]/data/pid1_exec
    116 	fi
    117 
    118 	require fs_d filename=$vars[svc_dir]/env
    119 	if [[ -n $vars[fstab_post] ]]; then
    120 		require fs_contentnl filename=$vars[svc_dir]/env/NS_FSTAB \
    121 			content=$vars[svc_dir]/data/fstab_post
    122 		require fs_contentnl filename=$vars[svc_dir]/data/fstab_post \
    123 			content=$vars[fstab_post]
    124 	else
    125 		require fs_r filename=$vars[svc_dir]/env/NS_FSTAB
    126 		require fs_r filename=$vars[svc_dir]/data/fstab_post
    127 	fi
    128 
    129 	if (( $+container_ns_bin_dir )); then
    130 		require fs_contentnl filename=$vars[svc_dir]/env/NS_BIN \
    131 			content=$container_ns_bin_dir
    132 	else
    133 		require fs_r filename=$vars[svc_dir]/env/NS_BIN
    134 	fi
    135 
    136 	require fs_l filename=$vars[svc_dir]/run \
    137 		destination=$vars[run_link]
    138 	require fs_l filename=$vars[svc_dir]/finish \
    139 		destination=$vars[finish_link]
    140 
    141 	require fs_contentnl filename=$vars[svc_dir]/notification-fd \
    142 		content=3
    143 
    144 	require fs_d filename=$vars[svc_dir]/event
    145 	require fs_o filename=$vars[svc_dir]/event \
    146 		owner=0:$vars[control_group]
    147 	require fs_m filename=$vars[svc_dir]/event mode=3730
    148 
    149 	require fs_d filename=$vars[svc_dir]/supervise
    150 	require fs_o filename=$vars[svc_dir]/supervise \
    151 		owner=0:0
    152 	require fs_m filename=$vars[svc_dir]/supervise mode=755
    153 
    154 	require fs_pipe filename=$vars[svc_dir]/supervise/control
    155 	require fs_o filename=$vars[svc_dir]/supervise/control \
    156 		owner=$vars[control_user]:0
    157 	require fs_m filename=$vars[svc_dir]/supervise/control mode=600
    158 
    159 	require fs_f filename=$vars[svc_dir]/supervise/lock
    160 	require fs_o filename=$vars[svc_dir]/supervise/lock \
    161 		owner=$vars[control_user]:0
    162 	require fs_m filename=$vars[svc_dir]/supervise/lock mode=644
    163 
    164 	if (($+vars[log_dir])); then
    165 		require container_service_log :svc_dir :log_dir :log_uid :log_gid \
    166 			\?log_umask
    167 	else
    168 		[[ -e $vars[svc_dir]/log/supervise ]] && \
    169 			die "Should not have a logger but one might be running: ${(qqq)vars[svc_dir]}"
    170 		require fs_r flags=r filename=$vars[svc_dir]/log
    171 	fi
    172 }
    173 
    174 confz_container_service_log_check() {
    175 	checkvars svc_dir log_dir log_uid log_gid
    176 	defvar log_umask 027
    177 
    178 	local -a runscript=(
    179 		'#!/command/execlineb -P'
    180 		"if { mkdir -p ${(qqq)vars[log_dir]} }"
    181 		"if { chmod $(( [##8] 8#777 ^ 8#$vars[log_umask] )) ${(qqq)vars[log_dir]} }"
    182 		"umask $vars[log_umask]"
    183 		"if { chown -R $vars[log_uid]:$vars[log_gid] ${(qqq)vars[log_dir]} }"
    184 		"s6-setuidgid $vars[log_uid]:$vars[log_gid]"
    185 		"s6-log -b -- p${vars[svc_dir]:t} t ${(qqq)vars[log_dir]}"
    186 	)
    187 
    188 	require fs_d filename=$vars[svc_dir]/log
    189 	require fs_m filename=$vars[svc_dir]/log mode=755
    190 	require fs_contentnl filename=$vars[svc_dir]/log/run \
    191 		content="${(F)runscript}"
    192 	require fs_m filename=$vars[svc_dir]/log/run mode=755
    193 	require fs_o filename=$vars[svc_dir]/log/run owner=0:0
    194 }
    195 
    196 confz_container_service_preset_check() {
    197 	local preset_dir=$container_service_script_dir
    198 	checkvars svc_dir preset root_link
    199 	[[ -x $preset_dir/$vars[preset]/run ]] || die "not an executable file: $preset_dir/$vars[preset]/run"
    200 	[[ -x $preset_dir/$vars[preset]/finish ]] || die "not an executable file: $preset_dir/$vars[preset]/finish"
    201 	require container_service \
    202 		run_link=$preset_dir/$vars[preset]/run \
    203 		finish_link=$preset_dir/$vars[preset]/finish \
    204 		:svc_dir :root_link \?fstab \?down \?control_user \?control_group \?fstab_post \
    205 		\?log_dir \?log_uid \?log_gid \?prepare_chroot \?pid1_exec
    206 }
    207 () {
    208 	(($+container_service_script_dir)) && return
    209 	local d=$functions_source[confz_container_service_preset_check]:A:h:h/service_scripts
    210 	if [[ -d $d ]]; then
    211 		typeset -g container_service_script_dir=$d
    212 	fi
    213 }
    214 
    215 confz_container_group_check() {
    216 	checkvars group_name
    217 	local gid="${${(s.:.)"$(getent group $vars[group_name])"}[3]}"
    218 	if [[ -z $gid ]]; then
    219 		fail_reason="getent returns no GID for group ${(qqq)vars[group_name]}"
    220 		return 1
    221 	fi
    222 	unify gid "$gid"
    223 }
    224 confz_container_group_do() {
    225 	addgroup "$vars[group_name]" || return $?
    226 	local gid="${${(s.:.)"$(getent group $vars[group_name])"}[3]}"
    227 	if [[ -z $gid ]]; then
    228 		fail_reason="getent returns no GID for group ${(qqq)vars[group_name]}"
    229 		return 1
    230 	fi
    231 	unify gid "$gid"
    232 }
    233 
    234 confz_container_user_check() {
    235 	checkvars user_name gid homedir
    236 	local -A uids
    237 	local -a entry
    238 	local line name
    239 	</etc/passwd while IFS= read line; do
    240 		entry=( "${${(s.:.)line}[@]}" )
    241 		# name:password:UID:GID:GECOS:directory:shell
    242 		# 1   :2       :3  :4  :5    :6        :7
    243 		if [[ $entry[1] == $vars[user_name] ]]; then
    244 			unify uid "$entry[3]"
    245 			unify gid "$entry[4]"
    246 			unify homedir "$entry[6]"
    247 			return 0
    248 		fi
    249 		uids[${entry[3]}]=$entry[1]
    250 	done
    251 	# name not found
    252 	if (($+vars[uid])); then
    253 		if (($+uids[${vars[uid]}])); then
    254 			die "UID ${vars[uid]} already assigned to user ${(qqq)vars[user_name]}"
    255 		else
    256 			return 1
    257 		fi
    258 	fi
    259 	# UID not set, pick unused one
    260 	local n
    261 	for n in {1000..2000}; do
    262 		(($+uids[$n])) && continue
    263 		unify uid $n
    264 		return 1
    265 	done
    266 	die "Could not find unassigned UID for user ${(qqq)vars[user_name]}"
    267 }
    268 confz_container_user_do() {
    269 	printf >>/etc/passwd "%s:x:%s:%s:container root:%s:/bin/sh\n" \
    270 		"$vars[user_name]" "$vars[uid]" "$vars[gid]" "$vars[homedir]"
    271 }
    272 
    273 confz_container_sysroot_user_check() {
    274 	checkvars containers_dir image_name
    275 	unify sysroot_user container-$vars[image_name]
    276 	unify sysroot_group container-$vars[image_name]
    277 	require container_group group_name=$vars[sysroot_group] %gid
    278 	require container_user user_name=$vars[sysroot_user] %uid :gid \
    279 		homedir=$vars[containers_dir]/systems/root
    280 }
    281 
    282 confz_container_image_layout_check() {
    283 	checkvars containers_dir image_name
    284 
    285 	unify root $vars[containers_dir]/systems/$vars[image_name]
    286 
    287 	require container_sysroot_user :containers_dir :image_name \
    288 		%uid %gid %sysroot_user %sysroot_group
    289 }
    290 confz_container_image_layout_svc_check() {
    291 	checkvars containers_dir svscan_dir image_name
    292 	unify sysroot_svc $vars[svscan_dir]/container.$vars[image_name].sysroot
    293 	require container_image_layout :containers_dir :image_name \
    294 		%root %uid %gid %sysroot_user %sysroot_group
    295 }
    296 
    297 confz_container_image_owner_check() {
    298 	checkvars containers_dir image_name uid gid
    299 	do_command=(
    300 		chown -R $vars[uid]:$vars[gid] $vars[containers_dir]/systems/$vars[image_name]
    301 	)
    302 	local -A stat_info
    303 	zstat -H stat_info $vars[containers_dir]/systems/$vars[image_name] \
    304 		|| die "Could not stat container directory."
    305 	[[ $stat_info[uid] == $vars[uid] && $stat_info[gid] == $vars[gid] ]]
    306 }
    307 
    308 confz_container_image_user_uid_gid_check() {
    309 	checkvars containers_dir image_name uid gid
    310 	defvar user root
    311 	local user_bre=${vars[user]//(#b)([\[\]\\.*^$])/\\$match[1]}
    312 	do_command=(
    313 		sed -i "s/^$user_bre:\([^:]*\):[^:]*:[^:]*:/${vars[user]}:\1:${vars[uid]}:${vars[gid]}:/" $vars[containers_dir]/systems/$vars[image_name]/etc/passwd
    314 	)
    315 	grep -qe "^$user_bre:[^:]*:${vars[uid]}:${vars[gid]}:" $vars[containers_dir]/systems/$vars[image_name]/etc/passwd
    316 }
    317 
    318 confz_container_image_group_gid_check() {
    319 	checkvars containers_dir image_name gid
    320 	defvar group root
    321 	local -a entry
    322 	local line
    323 	<$vars[containers_dir]/systems/$vars[image_name]/etc/group while IFS= read line; do
    324 		entry=( "${${(s.:.)line}[@]}" )
    325 		# name:password:GID:user_list
    326 		# 1   :2       :3  :4
    327 		if [[ $entry[1] == $vars[group] ]]; then
    328 			if [[ $vars[gid] == $entry[3] ]]; then
    329 				return 0
    330 			fi
    331 			unify previous_gid $entry[3]
    332 			return 1
    333 		fi
    334 	done
    335 	# group not found
    336 	return 1
    337 }
    338 confz_container_image_group_gid_do() {
    339 	local group_bre=${vars[group]//(#b)([\[\]\\.*^$])/\\$match[1]}
    340 	if (($+vars[previous_gid])); then
    341 		sed -i 's|^\([^:]*:[^:]*:[^:]*\):'"${vars[previous_gid]}:|\1:${vars[gid]}:|" $vars[containers_dir]/systems/$vars[image_name]/etc/passwd || die
    342 		sed -i "s|^\\($group_bre:[^:]*\\):[^:]*:|\1:${vars[gid]}:|" $vars[containers_dir]/systems/$vars[image_name]/etc/group || die
    343 	else
    344 		printf '%s:x:%s:\n' $vars[group] $vars[gid] >>$vars[containers_dir]/systems/$vars[image_name]/etc/group || die
    345 	fi
    346 }
    347 
    348 confz_container_service_sysroot_check() {
    349 	local uid gid svc_dir container container_user_dir
    350 	local -a fstab
    351 	checkvars containers_dir svscan_dir image_name
    352 	defvar fstab_extra ''
    353 	defvar container_name "$vars[image_name]"
    354 	container=$vars[container_name]
    355 
    356 	require container_image_layout_svc \
    357 		:containers_dir :svscan_dir :image_name \
    358 		%uid %gid %sysroot_svc %root %sysroot_user %sysroot_group
    359 
    360 	require fs_d filename=$vars[containers_dir]/systems/$vars[image_name]
    361 	require container_image_owner :uid :gid :containers_dir :image_name
    362 
    363 	require fs_d filename=$vars[containers_dir]/user/sysroot
    364 	require fs_m filename=$vars[containers_dir]/user/sysroot mode=751
    365 	require fs_o filename=$vars[containers_dir]/user/sysroot owner=0:0
    366 
    367 	container_user_dir=$vars[containers_dir]/user/sysroot/$container
    368 	require fs_d filename=$container_user_dir
    369 	require fs_m filename=$container_user_dir mode=751
    370 	require fs_o filename=$container_user_dir owner=0:0
    371 
    372 	require fs_d filename=$container_user_dir/root
    373 
    374 	# require fs_d filename=$vars[containers_dir]/home/sysroot
    375 	# require fs_m filename=$vars[containers_dir]/home/sysroot mode=751
    376 	# require fs_o filename=$vars[containers_dir]/home/sysroot owner=0:$gid
    377 
    378 	# require fs_l filename=$vars[containers_dir]/home/sysroot/$container \
    379 	# 	destination=../../user/sysroot/$container/root/home/sysroot
    380 
    381 	fstab=(
    382 		$vars[containers_dir]/systems/$vars[image_name]$'\t'$container_user_dir/root$'\tnone\tbind,nosuid,nodev\t0 0'
    383 		# /run/containers/$container.sysroot/home$'\t'$container_user_dir/root/home$'\tnone\tbind,nosuid,nodev\t0 0'
    384 		/run/containers/$container.sysroot/run$'\t'$container_user_dir/root/run$'\tnone\tbind,nosuid,nodev\t0 0'
    385 		# /run/containers/$container.sysroot/tmp$'\t'$container_user_dir/root/tmp$'\tnone\tbind,nosuid,nodev\t0 0'
    386 		"${(f@)vars[fstab_extra]}"
    387 	)
    388 
    389 	require container_service_preset preset=sysroot \
    390 		svc_dir=$vars[sysroot_svc] control_user=$vars[uid] control_group=$vars[gid] \
    391 		root_link=$container_user_dir/root \
    392 		fstab=${(F)fstab} \?down \?fstab_post
    393 	require fs_d filename=$vars[sysroot_svc]/env
    394 	require fs_contentnl filename=$vars[sysroot_svc]/env/CONTAINER_USER \
    395 		content=container-$vars[image_name]
    396 	require fs_contentnl filename=$vars[sysroot_svc]/env/CONTAINER_NAME \
    397 		content=$container
    398 }
    399 
    400 confz_container_service_ephemeral_check() {
    401 	local uid gid container_user_dir svc_dir log_dir container
    402 	local -a fstab mnt_dirs
    403 	checkvars containers_dir svscan_dir image_name user
    404 	defvar seccomp_profile 'default'
    405 	defvar linux_caps ''
    406 	defvar fstab_extra ''
    407 	defvar mnt_dirs_extra ''
    408 	defvar container_name "$vars[image_name]"
    409 	container=$vars[container_name]
    410 
    411 	uid="${${(s.:.)"$(getent passwd $vars[user])"}[3]}" \
    412 	gid="${${(s.:.)"$(getent group $vars[user])"}[3]}" \
    413 
    414 	require fs_d filename=$vars[containers_dir]/user/$vars[user]
    415 	require fs_m filename=$vars[containers_dir]/user/$vars[user] mode=751
    416 	require fs_o filename=$vars[containers_dir]/user/$vars[user] owner=0:$gid
    417 
    418 	container_user_dir=$vars[containers_dir]/user/$vars[user]/$container
    419 	require fs_d filename=$container_user_dir
    420 	require fs_m filename=$container_user_dir mode=751
    421 	require fs_o filename=$container_user_dir owner=0:$gid
    422 
    423 	require fs_d filename=$container_user_dir/root
    424 
    425 	require fs_d filename=$vars[containers_dir]/home/$vars[user]
    426 	require fs_m filename=$vars[containers_dir]/home/$vars[user] mode=751
    427 	require fs_o filename=$vars[containers_dir]/home/$vars[user] owner=0:$gid
    428 
    429 	require fs_l filename=$vars[containers_dir]/home/$vars[user]/$container \
    430 		destination=../../user/$vars[user]/$container/home/$vars[user]
    431 
    432 	mnt_dirs=( ns $=vars[mnt_dirs_extra] )
    433 
    434 	local src dst rw
    435 	local -a bind_mounts pid1_el_lines
    436 	bind_mounts=(
    437 		$vars[containers_dir]/systems/$vars[image_name]
    438 		$container_user_dir/root
    439 		ro
    440 
    441 		/run/containers/$container.$vars[user]/home
    442 		$container_user_dir/root/home
    443 		rw
    444 
    445 		/run/containers/$container.$vars[user]/run
    446 		$container_user_dir/root/run
    447 		rw
    448 
    449 		/run/containers/$container.$vars[user]/tmp
    450 		$container_user_dir/root/tmp
    451 		rw
    452 
    453 		/run/containers/$container.$vars[user]/mnt
    454 		$container_user_dir/root/mnt
    455 		rw
    456 	)
    457 
    458 	pid1_el_lines=( "#!$(which execlineb) -S0" )
    459 	for src dst rw in "$bind_mounts[@]"; do
    460 		fstab+=( $src$'\t'$dst$'\tnone\tbind,'$rw$',nosuid,nodev,slave\t0 0' )
    461 		src_el=\"${${src//\\/\\\\}//\"/\\\"}\"
    462 		dst_el=\"${${dst//\\/\\\\}//\"/\\\"}\"
    463 		pid1_el_lines+=(
    464 			"if { s6-mount -o bind,$rw,nodev,nosuid,slave $src_el $dst_el }"
    465 			"if { s6-mount -o remount,bind,$rw,nodev,nosuid . $dst_el }"
    466 		)
    467 	done
    468 
    469 	fstab+=( "${(f@)vars[fstab_extra]}" )
    470 	(($+vars[pid1_el])) && pid1_el_lines+=( $vars[pid1_el] )
    471 	pid1_el_lines+=( '$@' )
    472 
    473 	svc_dir=$vars[svscan_dir]/container.$container.$vars[user]
    474 	require container_service_preset preset=generic \
    475 		svc_dir=$svc_dir control_user=$uid control_group=$gid \
    476 		log_dir=/run/container-logs/$container.$vars[user] \
    477 		log_uid=0 log_gid=$gid \
    478 		root_link=$container_user_dir/root \
    479 		fstab=${(F)fstab} \?down \?fstab_post \
    480 		\?prepare_chroot pid1_exec=${(F)pid1_el_lines}
    481 	require fs_d filename=$svc_dir/env
    482 	require fs_contentnl filename=$svc_dir/env/CONTAINER_USER \
    483 		content=$vars[user]
    484 	require fs_contentnl filename=$svc_dir/env/CONTAINER_NAME \
    485 		content=$container
    486 	require fs_contentnl filename=$svc_dir/env/CONTAINER_MNT_DIRS \
    487 		content="$mnt_dirs"
    488 	require fs_contentnl filename=$svc_dir/env/CONTAINER_CAPS \
    489 		content=$vars[linux_caps]
    490 	require fs_contentnl filename=$svc_dir/env/CONTAINER_SECCOMP_PROFILE \
    491 		content=$vars[seccomp_profile]
    492 }
    493 
    494 confz_container_service_generic_check() {
    495 	local uid gid container_user_dir svc_dir log_dir container
    496 	local -a fstab mnt_dirs
    497 	checkvars containers_dir svscan_dir image_name user
    498 	defvar seccomp_profile 'default'
    499 	defvar linux_caps ''
    500 	defvar fstab_extra ''
    501 	defvar mnt_dirs_extra ''
    502 	defvar container_name "$vars[image_name]"
    503 	container=$vars[container_name]
    504 
    505 	uid="${${(s.:.)"$(getent passwd $vars[user])"}[3]}" \
    506 	gid="${${(s.:.)"$(getent group $vars[user])"}[3]}" \
    507 
    508 	require fs_d filename=$vars[containers_dir]/user/$vars[user]
    509 	require fs_m filename=$vars[containers_dir]/user/$vars[user] mode=751
    510 	require fs_o filename=$vars[containers_dir]/user/$vars[user] owner=0:$gid
    511 
    512 	container_user_dir=$vars[containers_dir]/user/$vars[user]/$container
    513 	require fs_d filename=$container_user_dir
    514 	require fs_m filename=$container_user_dir mode=751
    515 	require fs_o filename=$container_user_dir owner=0:$gid
    516 
    517 	require fs_d filename=$container_user_dir/root
    518 
    519 	require fs_d filename=$container_user_dir/home
    520 	require fs_m filename=$container_user_dir/home mode=751
    521 	require fs_o filename=$container_user_dir/home owner=0:$gid
    522 
    523 	require fs_d filename=$container_user_dir/home/$vars[user]
    524 	require fs_o filename=$container_user_dir/home/$vars[user] owner=$uid:$gid
    525 
    526 	require fs_d filename=$vars[containers_dir]/home/$vars[user]
    527 	require fs_m filename=$vars[containers_dir]/home/$vars[user] mode=751
    528 	require fs_o filename=$vars[containers_dir]/home/$vars[user] owner=0:$gid
    529 
    530 	require fs_l filename=$vars[containers_dir]/home/$vars[user]/$container \
    531 		destination=../../user/$vars[user]/$container/home/$vars[user]
    532 
    533 	mnt_dirs=( ns $=vars[mnt_dirs_extra] )
    534 
    535 	local src dst rw
    536 	local -a bind_mounts pid1_el_lines
    537 	bind_mounts=(
    538 		$vars[containers_dir]/systems/$vars[image_name]
    539 		$container_user_dir/root
    540 		ro
    541 
    542 		$container_user_dir/home
    543 		$container_user_dir/root/home
    544 		rw
    545 
    546 		/run/containers/$container.$vars[user]/run
    547 		$container_user_dir/root/run
    548 		rw
    549 
    550 		/run/containers/$container.$vars[user]/tmp
    551 		$container_user_dir/root/tmp
    552 		rw
    553 
    554 		/run/containers/$container.$vars[user]/mnt
    555 		$container_user_dir/root/mnt
    556 		rw
    557 	)
    558 
    559 	pid1_el_lines=( "#!$(which execlineb) -S0" )
    560 	for src dst rw in "$bind_mounts[@]"; do
    561 		fstab+=( $src$'\t'$dst$'\tnone\tbind,'$rw$',nosuid,nodev,slave\t0 0' )
    562 		src_el=\"${${src//\\/\\\\}//\"/\\\"}\"
    563 		dst_el=\"${${dst//\\/\\\\}//\"/\\\"}\"
    564 		pid1_el_lines+=(
    565 			"if { s6-mount -o bind,$rw,nodev,nosuid,slave $src_el $dst_el }"
    566 			"if { s6-mount -o remount,bind,$rw,nodev,nosuid . $dst_el }"
    567 		)
    568 	done
    569 
    570 	fstab+=( "${(f@)vars[fstab_extra]}" )
    571 	(($+vars[pid1_el])) && pid1_el_lines+=( $vars[pid1_el] )
    572 	pid1_el_lines+=( '$@' )
    573 
    574 	svc_dir=$vars[svscan_dir]/container.$container.$vars[user]
    575 	require container_service_preset preset=generic \
    576 		svc_dir=$svc_dir control_user=$uid control_group=$gid \
    577 		log_dir=/run/container-logs/$container.$vars[user] \
    578 		log_uid=0 log_gid=$gid \
    579 		root_link=$container_user_dir/root \
    580 		fstab=${(F)fstab} \?down \?fstab_post \
    581 		\?prepare_chroot pid1_exec=${(F)pid1_el_lines}
    582 	require fs_d filename=$svc_dir/env
    583 	require fs_contentnl filename=$svc_dir/env/CONTAINER_USER \
    584 		content=$vars[user]
    585 	require fs_contentnl filename=$svc_dir/env/CONTAINER_NAME \
    586 		content=$container
    587 	require fs_contentnl filename=$svc_dir/env/CONTAINER_MNT_DIRS \
    588 		content="$mnt_dirs"
    589 	require fs_contentnl filename=$svc_dir/env/CONTAINER_CAPS \
    590 		content=$vars[linux_caps]
    591 	require fs_contentnl filename=$svc_dir/env/CONTAINER_SECCOMP_PROFILE \
    592 		content=$vars[seccomp_profile]
    593 }
    594 
    595 confz_container_service_alsa_check() {
    596 	local uid gid container_user_dir svc_dir container
    597 	local -a fstab
    598 	checkvars containers_dir svscan_dir image_name user
    599 	defvar fstab_extra ''
    600 	defvar container_name "$vars[image_name]"
    601 	container=$vars[container_name]
    602 
    603 	uid="${${(s.:.)"$(getent passwd $vars[user])"}[3]}" \
    604 	gid="${${(s.:.)"$(getent group $vars[user])"}[3]}" \
    605 
    606 	require fs_d filename=$vars[containers_dir]/user/$vars[user]
    607 	require fs_m filename=$vars[containers_dir]/user/$vars[user] mode=751
    608 	require fs_o filename=$vars[containers_dir]/user/$vars[user] owner=0:$gid
    609 
    610 	container_user_dir=$vars[containers_dir]/user/$vars[user]/$container
    611 	require fs_d filename=$container_user_dir
    612 	require fs_m filename=$container_user_dir mode=751
    613 	require fs_o filename=$container_user_dir owner=0:$gid
    614 
    615 	require fs_d filename=$container_user_dir/root
    616 
    617 	require fs_d filename=$container_user_dir/home
    618 	require fs_m filename=$container_user_dir/home mode=751
    619 	require fs_o filename=$container_user_dir/home owner=0:$gid
    620 
    621 	require fs_d filename=$container_user_dir/home/$vars[user]
    622 	require fs_o filename=$container_user_dir/home/$vars[user] owner=$uid:$gid
    623 
    624 	require fs_d filename=$vars[containers_dir]/home/$vars[user]
    625 	require fs_m filename=$vars[containers_dir]/home/$vars[user] mode=751
    626 	require fs_o filename=$vars[containers_dir]/home/$vars[user] owner=0:$gid
    627 
    628 	require fs_l filename=$vars[containers_dir]/home/$vars[user]/$container \
    629 		destination=../../user/$vars[user]/$container/home/$vars[user]
    630 
    631 	fstab=(
    632 		$vars[containers_dir]/systems/$vars[image_name]$'\t'$container_user_dir/root$'\tnone\tbind,ro,nosuid,nodev\t0 0'
    633 		$container_user_dir/home$'\t'$container_user_dir/root/home$'\tnone\tbind,nosuid,nodev\t0 0'
    634 		/run/containers/$container.$vars[user]/run$'\t'$container_user_dir/root/run$'\tnone\tbind,nosuid,nodev\t0 0'
    635 		/run/containers/$container.$vars[user]/tmp$'\t'$container_user_dir/root/tmp$'\tnone\tbind,nosuid,nodev\t0 0'
    636 		"${(f@)vars[fstab_extra]}"
    637 	)
    638 
    639 	svc_dir=$vars[svscan_dir]/container.$container.$vars[user]
    640 	require container_service_preset preset=alsa \
    641 		svc_dir=$svc_dir control_user=$uid control_group=$gid \
    642 		log_dir=/run/container-logs/$container.$vars[user] \
    643 		log_uid=0 log_gid=$gid \
    644 		root_link=$container_user_dir/root \
    645 		fstab=${(F)fstab} \?down \?fstab_post
    646 	require fs_d filename=$svc_dir/env
    647 	require fs_contentnl filename=$svc_dir/env/CONTAINER_USER \
    648 		content=$vars[user]
    649 	require fs_contentnl filename=$svc_dir/env/CONTAINER_NAME \
    650 		content=$container
    651 }
    652 
    653 confz_container_service_xsession_check() {
    654 	local uid gid container_user_dir svc_dir container
    655 	local -a fstab mnt_dirs
    656 	checkvars containers_dir svscan_dir image_name user display_number
    657 	defvar fstab_extra ''
    658 	defvar mnt_dirs_extra ''
    659 	container=xsession.$vars[display_number]
    660 
    661 	uid="${${(s.:.)"$(getent passwd $vars[user])"}[3]}" \
    662 	gid="${${(s.:.)"$(getent group $vars[user])"}[3]}" \
    663 
    664 	require fs_d filename=$vars[containers_dir]/user/$vars[user]
    665 	require fs_m filename=$vars[containers_dir]/user/$vars[user] mode=751
    666 	require fs_o filename=$vars[containers_dir]/user/$vars[user] owner=0:$gid
    667 
    668 	container_user_dir=$vars[containers_dir]/user/$vars[user]/$container
    669 	require fs_d filename=$container_user_dir
    670 	require fs_m filename=$container_user_dir mode=751
    671 	require fs_o filename=$container_user_dir owner=0:$gid
    672 
    673 	require fs_d filename=$container_user_dir/root
    674 
    675 	require fs_d filename=$vars[containers_dir]/home/$vars[user]
    676 	require fs_m filename=$vars[containers_dir]/home/$vars[user] mode=751
    677 	require fs_o filename=$vars[containers_dir]/home/$vars[user] owner=0:$gid
    678 
    679 	require fs_l filename=$vars[containers_dir]/home/$vars[user]/$container \
    680 		destination=../../user/$vars[user]/$container/root/home/$vars[user]
    681 
    682 	mnt_dirs=( ns container-logs $=vars[mnt_dirs_extra] )
    683 
    684 	fstab=(
    685 		$vars[containers_dir]/systems/$vars[image_name]$'\t'$container_user_dir/root$'\tnone\tbind,ro,nosuid,nodev\t0 0'
    686 		/run/containers/$container.$vars[user]/home$'\t'$container_user_dir/root/home$'\tnone\tbind,nosuid,nodev\t0 0'
    687 		/run/containers/$container.$vars[user]/run$'\t'$container_user_dir/root/run$'\tnone\tbind,nosuid,nodev\t0 0'
    688 		/run/containers/$container.$vars[user]/tmp$'\t'$container_user_dir/root/tmp$'\tnone\tbind,nosuid,nodev\t0 0'
    689 		/run/containers/$container.$vars[user]/mnt$'\t'$container_user_dir/root/mnt$'\tnone\tbind,ro,nosuid,nodev\t0 0'
    690 		/run/container-logs$'\t'$container_user_dir/root/mnt/container-logs$'\tnone\tbind,ro,nosuid,nodev\t0 0'
    691 		"${(f@)vars[fstab_extra]}"
    692 	)
    693 
    694 	svc_dir=$vars[svscan_dir]/container.xsession.$vars[display_number].$vars[user]
    695 	require container_service_preset preset=xsession \
    696 		svc_dir=$svc_dir control_user=$uid control_group=$gid \
    697 		log_dir=/run/container-logs/$container.$vars[user] \
    698 		log_uid=0 log_gid=$gid \
    699 		root_link=$container_user_dir/root \
    700 		fstab=${(F)fstab} \?down \?fstab_post
    701 	require fs_d filename=$svc_dir/env
    702 	require fs_contentnl filename=$svc_dir/env/CONTAINER_USER \
    703 		content=$vars[user]
    704 	require fs_contentnl filename=$svc_dir/env/CONTAINER_NAME \
    705 		content=$container
    706 	require fs_contentnl filename=$svc_dir/env/DISPLAY \
    707 		content=:$vars[display_number]
    708 	require fs_contentnl filename=$svc_dir/env/vtN \
    709 		content=$vars[display_number]
    710 	require fs_contentnl filename=$svc_dir/env/CONTAINER_MNT_DIRS \
    711 		content="$mnt_dirs"
    712 }
    713 
    714 confz_container_service_xorg_check() {
    715 	local uid gid container_user_dir svc_dir container
    716 	local -a fstab_post
    717 	checkvars containers_dir svscan_dir image_name vtN
    718 	defvar user xorg
    719 	defvar fstab_extra ''
    720 	defvar container_name "X$vars[vtN]"
    721 	container=$vars[container_name]
    722 
    723 	uid="${${(s.:.)"$(getent passwd $vars[user])"}[3]}" \
    724 	gid="${${(s.:.)"$(getent group $vars[user])"}[3]}" \
    725 
    726 	require fs_d filename=$vars[containers_dir]/user/$vars[user]
    727 	require fs_m filename=$vars[containers_dir]/user/$vars[user] mode=751
    728 	require fs_o filename=$vars[containers_dir]/user/$vars[user] owner=0:$gid
    729 
    730 	container_user_dir=$vars[containers_dir]/user/$vars[user]/$container
    731 	require fs_d filename=$container_user_dir
    732 	require fs_m filename=$container_user_dir mode=751
    733 	require fs_o filename=$container_user_dir owner=0:$gid
    734 
    735 	require fs_d filename=$container_user_dir/root
    736 
    737 	fstab_post=(
    738 		/run/containers/$container.$vars[user]/run$'\t/mnt/chroot/run\tnone\tbind,nosuid,nodev\t0 0'
    739 		/run/containers/$container.$vars[user]/tmp$'\t/mnt/chroot/tmp\tnone\tbind,nosuid,nodev\t0 0'
    740 	)
    741 
    742 	svc_dir=$vars[svscan_dir]/container.$container
    743 	require container_service_preset preset=xorg \
    744 		svc_dir=$svc_dir control_user=0 control_group=0 \
    745 		log_dir=/run/container-logs/$container \
    746 		log_uid=0 log_gid=0 \
    747 		root_link=$vars[containers_dir]/systems/$vars[image_name] \
    748 		fstab_post=${(F)fstab_post} \?down \?fstab=fstab_extra
    749 	require fs_d filename=$svc_dir/env
    750 	require fs_contentnl filename=$svc_dir/env/CONTAINER_USER \
    751 		content=$vars[user]
    752 	require fs_contentnl filename=$svc_dir/env/CONTAINER_NAME \
    753 		content=$container
    754 	require fs_contentnl filename=$svc_dir/env/vtN \
    755 		content=$vars[vtN]
    756 }
    757 
    758 # --- new image constructor
    759 
    760 () {
    761 	(($+container_template_dir)) && return
    762 	local f d
    763 	for f in $^fpath/confz_containers_init*(N); do
    764 		d=$f:A:h:h/container_template
    765 		if [[ -d $d ]]; then
    766 			typeset -g container_template_dir=$d
    767 			break
    768 		fi
    769 	done
    770 }
    771 
    772 confz_container_template_file_check() {
    773 	checkvars template name root
    774 	defvar uid 0
    775 	defvar gid 0
    776 	defvar mode 0644
    777 	defvar target $vars[name]
    778 
    779 	[[ -f $container_template_dir/$vars[template]/$vars[name] ]] \
    780 		|| die "Template file not found: $container_template_dir/$vars[template]/$vars[name]"
    781 
    782 	[[ -f $vars[root]/$vars[target] ]] || return 1
    783 
    784 	require fs_m :mode filename=$vars[root]/$vars[target]
    785 	require fs_o owner=$vars[uid]:$vars[gid] filename=$vars[root]/$vars[target]
    786 }
    787 confz_container_template_file_do() {
    788 	cp -va $container_template_dir/$vars[template]/$vars[name] \
    789 		$vars[root]/$vars[target] || die
    790 	chown $vars[uid]:$vars[gid] $vars[root]/$vars[target] || die
    791 	chmod $vars[mode] $vars[root]/$vars[target] || die
    792 }
    793 
    794 confz_container_download_and_verify_check() {
    795 	checkvars containers_dir url checksum checksum_algo
    796 	defvar filename ${vars[url]:t}
    797 
    798 	local download_dir=$vars[containers_dir]/download-cache
    799 	require fs_d filename=$download_dir
    800 
    801 	(cd $download_dir &&
    802 		$vars[checksum_algo]sum -s -c <<<"$vars[checksum]  $vars[filename]")
    803 }
    804 confz_container_download_and_verify_do() {
    805 	wget -O - -- $vars[url] \
    806 		>$vars[containers_dir]/download-cache/$vars[filename]
    807 }
    808 
    809 confz_container_generic_layout_check() {
    810 	checkvars root
    811 	defvar uid 0
    812 	defvar gid 0
    813 
    814 	require fs_d filename="$vars[root]"
    815 	require fs_m filename="$vars[root]" mode=0755
    816 	require fs_o filename="$vars[root]" owner=$vars[uid]:$vars[gid]
    817 
    818 	require fs_d filename="$vars[root]/etc"
    819 	require fs_m filename="$vars[root]/etc" mode=0755
    820 	require fs_o filename="$vars[root]/etc" owner=$vars[uid]:$vars[gid]
    821 
    822 	require fs_l filename="$vars[root]/etc/resolv.conf" \
    823 		flags=\! destination="../run/resolv.conf"
    824 
    825 	require fs_d filename="$vars[root]/dev"
    826 	require fs_m filename="$vars[root]/dev" mode=0755
    827 	require fs_o filename="$vars[root]/dev" owner=$vars[uid]:$vars[gid]
    828 
    829 	require fs_d filename="$vars[root]/dev/pts"
    830 	require fs_m filename="$vars[root]/dev/pts" mode=0755
    831 	require fs_o filename="$vars[root]/dev/pts" owner=$vars[uid]:$vars[gid]
    832 
    833 	require fs_d filename="$vars[root]/dev/shm"
    834 	require fs_m filename="$vars[root]/dev/shm" mode=0755
    835 	require fs_o filename="$vars[root]/dev/shm" owner=$vars[uid]:$vars[gid]
    836 
    837 	require fs_d filename="$vars[root]/home"
    838 	require fs_m filename="$vars[root]/home" mode=0755
    839 	require fs_o filename="$vars[root]/home" owner=$vars[uid]:$vars[gid]
    840 
    841 	require fs_d filename="$vars[root]/mnt"
    842 	require fs_m filename="$vars[root]/mnt" mode=0755
    843 	require fs_o filename="$vars[root]/mnt" owner=$vars[uid]:$vars[gid]
    844 
    845 	# This is not required for regular run, /mnt is on tmpfs there
    846 	# but sysroot currently doesn't do that.
    847 	require fs_d filename="$vars[root]/mnt/ns"
    848 	require fs_m filename="$vars[root]/mnt/ns" mode=0755
    849 	require fs_o filename="$vars[root]/mnt/ns" owner=$vars[uid]:$vars[gid]
    850 
    851 	require fs_d filename="$vars[root]/run"
    852 	require fs_m filename="$vars[root]/run" mode=0755
    853 	require fs_o filename="$vars[root]/run" owner=$vars[uid]:$vars[gid]
    854 
    855 	require fs_d filename="$vars[root]/tmp"
    856 	# require fs_m filename="$vars[root]/tmp" mode=0755
    857 	require fs_o filename="$vars[root]/tmp" owner=$vars[uid]:$vars[gid]
    858 }
    859 
    860 # --- mrrl via bind-mount ---
    861 confz_container_mrrl_base_layout_check() {
    862 	checkvars root
    863 	defvar uid 0
    864 	defvar gid 0
    865 
    866 	require container_generic_layout :root :uid :gid
    867 
    868 	require fs_l filename="$vars[root]/versions" destination="mnt/versions"
    869 	require fs_l filename="$vars[root]/sbin" destination="bin"
    870 	require fs_l filename="$vars[root]/usr" destination="."
    871 
    872 	require fs_d filename="$vars[root]/bin"
    873 	require fs_m filename="$vars[root]/bin" mode=0755
    874 	require fs_o filename="$vars[root]/bin" owner=$vars[uid]:$vars[gid]
    875 
    876 	require fs_l filename="$vars[root]/bin/awk" destination="argv0exec"
    877 	require fs_l filename="$vars[root]/bin/bash" destination="argv0exec"
    878 	require fs_l filename="$vars[root]/bin/env" destination="argv0exec"
    879 	require fs_l filename="$vars[root]/bin/execlineb" destination="argv0exec"
    880 	require fs_l filename="$vars[root]/bin/sh" destination="argv0exec"
    881 	require fs_l filename="$vars[root]/bin/zsh" destination="argv0exec"
    882 
    883 	require fs_d filename="$vars[root]/etc"
    884 	require fs_m filename="$vars[root]/etc" mode=0755
    885 	require fs_o filename="$vars[root]/etc" owner=$vars[uid]:$vars[gid]
    886 
    887 	require fs_l filename="$vars[root]/etc/mtab" destination="/proc/mounts"
    888 	# require fs_o filename="$vars[root]/etc/mtab" owner=$vars[uid]:$vars[gid]
    889 
    890 	require fs_f filename="$vars[root]/etc/group"
    891 	require fs_m filename="$vars[root]/etc/group" mode=0644
    892 	require fs_o filename="$vars[root]/etc/group" owner=$vars[uid]:$vars[gid]
    893 
    894 	require fs_f filename="$vars[root]/etc/passwd"
    895 	require fs_m filename="$vars[root]/etc/passwd" mode=0644
    896 	require fs_o filename="$vars[root]/etc/passwd" owner=$vars[uid]:$vars[gid]
    897 
    898 	require fs_d filename="$vars[root]/proc"
    899 	require fs_m filename="$vars[root]/proc" mode=0755
    900 	require fs_o filename="$vars[root]/proc" owner=$vars[uid]:$vars[gid]
    901 
    902 	require fs_d filename="$vars[root]/root"
    903 	require fs_m filename="$vars[root]/root" mode=0700
    904 	require fs_o filename="$vars[root]/root" owner=$vars[uid]:$vars[gid]
    905 
    906 	require fs_d filename="$vars[root]/sys"
    907 	require fs_m filename="$vars[root]/sys" mode=0755
    908 	require fs_o filename="$vars[root]/sys" owner=$vars[uid]:$vars[gid]
    909 
    910 	require fs_d filename="$vars[root]/var"
    911 	require fs_m filename="$vars[root]/var" mode=0755
    912 	require fs_o filename="$vars[root]/var" owner=$vars[uid]:$vars[gid]
    913 
    914 	require fs_d filename="$vars[root]/var/empty"
    915 	require fs_m filename="$vars[root]/var/empty" mode=0555
    916 	require fs_o filename="$vars[root]/var/empty" owner=$vars[uid]:$vars[gid]
    917 
    918 	require fs_l filename="$vars[root]/var/run" destination="../run"
    919 	# require fs_o filename="$vars[root]/var/run" owner=$vars[uid]:$vars[gid]
    920 }
    921 
    922 confz_container_mrrl_image_check() {
    923 	checkvars containers_dir image_name
    924 
    925 	require container_image_layout :containers_dir :image_name \
    926 		 %uid %gid %root %sysroot_user
    927 	require container_mrrl_base_layout :uid :gid :root
    928 }
    929 
    930 # --- Alpine ---
    931 
    932 confz_container_alpine_base_layout_check() {
    933 	checkvars root
    934 	defvar uid 0
    935 	defvar gid 0
    936 
    937 	require container_generic_layout :root :uid :gid
    938 
    939 	require fs_d filename="$vars[root]/etc"
    940 	require fs_m filename="$vars[root]/etc" mode=0755
    941 	require fs_o filename="$vars[root]/etc" owner=$vars[uid]:$vars[gid]
    942 
    943 	require fs_d filename="$vars[root]/etc/apk"
    944 	require fs_m filename="$vars[root]/etc/apk" mode=0755
    945 	require fs_o filename="$vars[root]/etc/apk" owner=$vars[uid]:$vars[gid]
    946 
    947 	require fs_l filename="$vars[root]/etc/mtab" destination="/proc/mounts"
    948 	# require fs_o filename="$vars[root]/etc/mtab" owner=$vars[uid]:$vars[gid]
    949 
    950 	require fs_d filename="$vars[root]/etc/profile.d"
    951 	require fs_m filename="$vars[root]/etc/profile.d" mode=0755
    952 	require fs_o filename="$vars[root]/etc/profile.d" owner=$vars[uid]:$vars[gid]
    953 
    954 	require fs_d filename="$vars[root]/lib"
    955 	require fs_m filename="$vars[root]/lib" mode=0755
    956 	require fs_o filename="$vars[root]/lib" owner=$vars[uid]:$vars[gid]
    957 
    958 	require fs_d filename="$vars[root]/lib/firmware"
    959 	require fs_m filename="$vars[root]/lib/firmware" mode=0755
    960 	require fs_o filename="$vars[root]/lib/firmware" owner=$vars[uid]:$vars[gid]
    961 
    962 	require fs_d filename="$vars[root]/lib/mdev"
    963 	require fs_m filename="$vars[root]/lib/mdev" mode=0755
    964 	require fs_o filename="$vars[root]/lib/mdev" owner=$vars[uid]:$vars[gid]
    965 
    966 	require fs_d filename="$vars[root]/opt"
    967 	require fs_m filename="$vars[root]/opt" mode=0755
    968 	require fs_o filename="$vars[root]/opt" owner=$vars[uid]:$vars[gid]
    969 
    970 	require fs_d filename="$vars[root]/proc"
    971 	require fs_m filename="$vars[root]/proc" mode=0755
    972 	require fs_o filename="$vars[root]/proc" owner=$vars[uid]:$vars[gid]
    973 
    974 	require fs_d filename="$vars[root]/root"
    975 	require fs_m filename="$vars[root]/root" mode=0700
    976 	require fs_o filename="$vars[root]/root" owner=$vars[uid]:$vars[gid]
    977 
    978 	require fs_d filename="$vars[root]/run"
    979 	require fs_m filename="$vars[root]/run" mode=0755
    980 	require fs_o filename="$vars[root]/run" owner=$vars[uid]:$vars[gid]
    981 
    982 	require fs_d filename="$vars[root]/sbin"
    983 	require fs_m filename="$vars[root]/sbin" mode=0755
    984 	require fs_o filename="$vars[root]/sbin" owner=$vars[uid]:$vars[gid]
    985 
    986 	require fs_d filename="$vars[root]/srv"
    987 	require fs_m filename="$vars[root]/srv" mode=0755
    988 	require fs_o filename="$vars[root]/srv" owner=$vars[uid]:$vars[gid]
    989 
    990 	require fs_d filename="$vars[root]/sys"
    991 	require fs_m filename="$vars[root]/sys" mode=0755
    992 	require fs_o filename="$vars[root]/sys" owner=$vars[uid]:$vars[gid]
    993 
    994 	require fs_d filename="$vars[root]/tmp"
    995 	require fs_m filename="$vars[root]/tmp" mode=1777
    996 	require fs_o filename="$vars[root]/tmp" owner=$vars[uid]:$vars[gid]
    997 
    998 	require fs_d filename="$vars[root]/usr"
    999 	require fs_m filename="$vars[root]/usr" mode=0755
   1000 	require fs_o filename="$vars[root]/usr" owner=$vars[uid]:$vars[gid]
   1001 
   1002 	require fs_d filename="$vars[root]/usr/lib"
   1003 	require fs_m filename="$vars[root]/usr/lib" mode=0755
   1004 	require fs_o filename="$vars[root]/usr/lib" owner=$vars[uid]:$vars[gid]
   1005 
   1006 	require fs_d filename="$vars[root]/usr/local"
   1007 	require fs_m filename="$vars[root]/usr/local" mode=0755
   1008 	require fs_o filename="$vars[root]/usr/local" owner=$vars[uid]:$vars[gid]
   1009 
   1010 	require fs_d filename="$vars[root]/usr/local/bin"
   1011 	require fs_m filename="$vars[root]/usr/local/bin" mode=0755
   1012 	require fs_o filename="$vars[root]/usr/local/bin" owner=$vars[uid]:$vars[gid]
   1013 
   1014 	require fs_d filename="$vars[root]/usr/local/lib"
   1015 	require fs_m filename="$vars[root]/usr/local/lib" mode=0755
   1016 	require fs_o filename="$vars[root]/usr/local/lib" owner=$vars[uid]:$vars[gid]
   1017 
   1018 	require fs_d filename="$vars[root]/usr/local/share"
   1019 	require fs_m filename="$vars[root]/usr/local/share" mode=0755
   1020 	require fs_o filename="$vars[root]/usr/local/share" owner=$vars[uid]:$vars[gid]
   1021 
   1022 	require fs_d filename="$vars[root]/usr/sbin"
   1023 	require fs_m filename="$vars[root]/usr/sbin" mode=0755
   1024 	require fs_o filename="$vars[root]/usr/sbin" owner=$vars[uid]:$vars[gid]
   1025 
   1026 	require fs_d filename="$vars[root]/usr/share"
   1027 	require fs_m filename="$vars[root]/usr/share" mode=0755
   1028 	require fs_o filename="$vars[root]/usr/share" owner=$vars[uid]:$vars[gid]
   1029 
   1030 	require fs_d filename="$vars[root]/usr/share/man"
   1031 	require fs_m filename="$vars[root]/usr/share/man" mode=0755
   1032 	require fs_o filename="$vars[root]/usr/share/man" owner=$vars[uid]:$vars[gid]
   1033 
   1034 	require fs_d filename="$vars[root]/usr/share/misc"
   1035 	require fs_m filename="$vars[root]/usr/share/misc" mode=0755
   1036 	require fs_o filename="$vars[root]/usr/share/misc" owner=$vars[uid]:$vars[gid]
   1037 
   1038 	require fs_d filename="$vars[root]/var"
   1039 	require fs_m filename="$vars[root]/var" mode=0755
   1040 	require fs_o filename="$vars[root]/var" owner=$vars[uid]:$vars[gid]
   1041 
   1042 	require fs_d filename="$vars[root]/var/cache"
   1043 	require fs_m filename="$vars[root]/var/cache" mode=0755
   1044 	require fs_o filename="$vars[root]/var/cache" owner=$vars[uid]:$vars[gid]
   1045 
   1046 	require fs_d filename="$vars[root]/var/cache/misc"
   1047 	require fs_m filename="$vars[root]/var/cache/misc" mode=0755
   1048 	require fs_o filename="$vars[root]/var/cache/misc" owner=$vars[uid]:$vars[gid]
   1049 
   1050 	require fs_d filename="$vars[root]/var/empty"
   1051 	require fs_m filename="$vars[root]/var/empty" mode=0555
   1052 	require fs_o filename="$vars[root]/var/empty" owner=$vars[uid]:$vars[gid]
   1053 
   1054 	require fs_d filename="$vars[root]/var/lib"
   1055 	require fs_m filename="$vars[root]/var/lib" mode=0755
   1056 	require fs_o filename="$vars[root]/var/lib" owner=$vars[uid]:$vars[gid]
   1057 
   1058 	require fs_d filename="$vars[root]/var/lib/misc"
   1059 	require fs_m filename="$vars[root]/var/lib/misc" mode=0755
   1060 	require fs_o filename="$vars[root]/var/lib/misc" owner=$vars[uid]:$vars[gid]
   1061 
   1062 	require fs_d filename="$vars[root]/var/local"
   1063 	require fs_m filename="$vars[root]/var/local" mode=0755
   1064 	require fs_o filename="$vars[root]/var/local" owner=$vars[uid]:$vars[gid]
   1065 
   1066 	require fs_d filename="$vars[root]/var/lock"
   1067 	require fs_m filename="$vars[root]/var/lock" mode=0755
   1068 	require fs_o filename="$vars[root]/var/lock" owner=$vars[uid]:$vars[gid]
   1069 
   1070 	require fs_d filename="$vars[root]/var/lock/subsys"
   1071 	require fs_m filename="$vars[root]/var/lock/subsys" mode=0755
   1072 	require fs_o filename="$vars[root]/var/lock/subsys" owner=$vars[uid]:$vars[gid]
   1073 
   1074 	require fs_d filename="$vars[root]/var/log"
   1075 	require fs_m filename="$vars[root]/var/log" mode=0755
   1076 	require fs_o filename="$vars[root]/var/log" owner=$vars[uid]:$vars[gid]
   1077 
   1078 	require fs_d filename="$vars[root]/var/mail"
   1079 	require fs_m filename="$vars[root]/var/mail" mode=0755
   1080 	require fs_o filename="$vars[root]/var/mail" owner=$vars[uid]:$vars[gid]
   1081 
   1082 	require fs_d filename="$vars[root]/var/opt"
   1083 	require fs_m filename="$vars[root]/var/opt" mode=0755
   1084 	require fs_o filename="$vars[root]/var/opt" owner=$vars[uid]:$vars[gid]
   1085 
   1086 	require fs_l filename="$vars[root]/var/run" destination="../run"
   1087 	# require fs_o filename="$vars[root]/var/run" owner=$vars[uid]:$vars[gid]
   1088 
   1089 	require fs_d filename="$vars[root]/var/spool"
   1090 	require fs_m filename="$vars[root]/var/spool" mode=0755
   1091 	require fs_o filename="$vars[root]/var/spool" owner=$vars[uid]:$vars[gid]
   1092 
   1093 	require fs_d filename="$vars[root]/var/tmp"
   1094 	require fs_m filename="$vars[root]/var/tmp" mode=1777
   1095 	require fs_o filename="$vars[root]/var/tmp" owner=$vars[uid]:$vars[gid]
   1096 
   1097 }
   1098 
   1099 confz_container_alpine_base_files_check() {
   1100 	checkvars root mirror release repositories hostname locale
   1101 	defvar uid 0
   1102 	defvar gid 0
   1103 
   1104 	local -a repositories=( $vars[mirror]/$vars[release]/${^=vars[repositories]} )
   1105 	require fs_contentnl filename="$vars[root]/etc/apk/repositories" \
   1106 		content="${(F)repositories}"
   1107 	require fs_m filename="$vars[root]/etc/apk/repositories" mode=0644
   1108 	require fs_o filename="$vars[root]/etc/apk/repositories" owner=$vars[uid]:$vars[gid]
   1109 
   1110 	require fs_contentnl filename="$vars[root]/etc/hostname" \
   1111 		content="$vars[hostname]"
   1112 	require fs_m filename="$vars[root]/etc/hostname" mode=0644
   1113 	require fs_o filename="$vars[root]/etc/hostname" owner=$vars[uid]:$vars[gid]
   1114 
   1115 	require container_template_file :root :uid :gid \
   1116 		template=alpine name=etc/hosts
   1117 
   1118 	# require fs_contentnl filename="$vars[root]/etc/hosts" \
   1119 	# 	content=$'127.0.0.1\tlocalhost localhost.localdomain\n::1\tlocalhost localhost.localdomain'
   1120 	# require fs_m filename="$vars[root]/etc/hosts" mode=0644
   1121 	# require fs_o filename="$vars[root]/etc/hosts" owner=$vars[uid]:$vars[gid]
   1122 
   1123 	require fs_contentnl filename="$vars[root]/etc/motd" \
   1124 		content="Welcome to container image at ${(qqq)vars[root]}"
   1125 	require fs_m filename="$vars[root]/etc/motd" mode=0644
   1126 	require fs_o filename="$vars[root]/etc/motd" owner=$vars[uid]:$vars[gid]
   1127 
   1128 	require container_template_file :root :uid :gid \
   1129 		template=alpine name=etc/profile
   1130 
   1131 	local -a locale_lines=(
   1132 		"export CHARSET=${(q)vars[locale]}"
   1133 		"export LANG=${(q)vars[locale]}"
   1134 		"export LC_COLLATE=C"
   1135 	)
   1136 	require fs_contentnl filename="$vars[root]/etc/profile.d/locale.sh" \
   1137 		content="${(F)locale_lines}"
   1138 	require fs_m filename="$vars[root]/etc/profile.d/locale.sh" mode=0644
   1139 	require fs_o filename="$vars[root]/etc/profile.d/locale.sh" owner=$vars[uid]:$vars[gid]
   1140 
   1141 	require container_template_file :root :uid :gid \
   1142 		template=alpine name=etc/protocols
   1143 
   1144 	require container_template_file :root :uid :gid \
   1145 		template=alpine name=etc/services
   1146 
   1147 	require container_template_file :root :uid :gid \
   1148 		template=alpine name=etc/shells
   1149 
   1150 	# require fs_contentnl filename="$vars[root]/etc/shells" \
   1151 	# 	content=$'# valid login shells\n/bin/sh\n/bin/ash\n/bin/zsh\n/bin/bash\n/bin/mksh'
   1152 	# require fs_m filename="$vars[root]/etc/shells" mode=0644
   1153 	# require fs_o filename="$vars[root]/etc/shells" owner=$vars[uid]:$vars[gid]
   1154 
   1155 	require fs_f filename="$vars[root]/etc/group"
   1156 	# require fs_c filename="$vars[root]/etc/group" \
   1157 	# 	content=""
   1158 	require fs_m filename="$vars[root]/etc/group" mode=0644
   1159 	require fs_o filename="$vars[root]/etc/group" owner=$vars[uid]:$vars[gid]
   1160 
   1161 	require fs_f filename="$vars[root]/etc/passwd"
   1162 	# require fs_c filename="$vars[root]/etc/passwd" \
   1163 	# 	content=""
   1164 	require fs_m filename="$vars[root]/etc/passwd" mode=0644
   1165 	require fs_o filename="$vars[root]/etc/passwd" owner=$vars[uid]:$vars[gid]
   1166 
   1167 	# require fs_c filename="$vars[root]/etc/shadow" \
   1168 	# 	content=""
   1169 	# require fs_m filename="$vars[root]/etc/shadow" mode=0640
   1170 	# require fs_o filename="$vars[root]/etc/shadow" owner=$vars[uid]:$vars[gid]
   1171 
   1172 }
   1173 
   1174 confz_container_alpine_apk_check() {
   1175 	checkvars sysroot_user root arch
   1176 	defvar keys_dir ${container_alpine_keys_dir:-/etc/apk/keys}
   1177 	defvar apk_executable ${container_apk_executable:-apk}
   1178 	do_command=(
   1179 		s6-setuidgid $vars[sysroot_user]
   1180 		$vars[apk_executable]
   1181 		--update-cache
   1182 		--initdb
   1183 		--arch $vars[arch]
   1184 		--root $vars[root]
   1185 		--keys-dir $vars[keys_dir]
   1186 		--no-scripts
   1187 		--no-chown
   1188 		add alpine-keys apk-tools busybox
   1189 	)
   1190 	[[ -f $vars[root]/sbin/apk ]]
   1191 }
   1192 
   1193 confz_container_alpine_image_check() {
   1194 	checkvars containers_dir image_name arch
   1195 	defvar mirror http://mirror.fel.cvut.cz/alpine
   1196 	defvar release edge
   1197 	defvar repositories main
   1198 	defvar hostname $vars[image_name]
   1199 	defvar locale C.UTF-8
   1200 
   1201 	require container_image_layout :containers_dir :image_name \
   1202 		 %uid %gid %root %sysroot_user
   1203 	require container_alpine_base_layout :uid :gid :root
   1204 	require container_alpine_base_files :uid :gid :root \
   1205 		:mirror :release :repositories :hostname :locale
   1206 	require container_alpine_apk :arch :root :sysroot_user
   1207 }
   1208 
   1209 container_run() {
   1210 	local svcdir=$1
   1211 	shift
   1212 	$commands[cd] $vars[sysroot_svc] container_sysroot_run "$@"
   1213 }
   1214 
   1215 confz_container_alpine_packages_installed_check() {
   1216 	checkvars containers_dir image_name packages svscan_dir
   1217 
   1218 	require container_service_sysroot \
   1219 		:containers_dir :svscan_dir :image_name \
   1220 		%sysroot_svc
   1221 
   1222 	local root=$vars[containers_dir]/systems/$vars[image_name]
   1223 	local -a world=( "${(@f)$(<$root/etc/apk/world)}" )
   1224 	local -a installed=( "${(@f)$(
   1225 		container_run $vars[sysroot_svc] /sbin/apk info -a </dev/null
   1226 	)}" )
   1227 	local -a missing
   1228 	local pkg
   1229 
   1230 	for pkg in $=vars[packages]; do
   1231 		(( $installed[(I)${pkg}] )) || missing+=( $pkg )
   1232 	done
   1233 	(( $#missing == 0 )) && return 0
   1234 
   1235 	typeset -ga container_alpine_packages_missing
   1236 	container_alpine_packages_missing=( $missing )
   1237 
   1238 	fail_reason="Following packages are not installed: $missing (req:${#$=vars[packages]} ins:$#installed)"
   1239 	return 1
   1240 }
   1241 confz_container_alpine_packages_installed_do() {
   1242 	$commands[cd] $vars[sysroot_svc] container_sysroot_run \
   1243 		/sbin/apk add --no-chown $container_alpine_packages_missing ||
   1244 		$commands[cd] $vars[sysroot_svc] container_sysroot_run \
   1245 		/sbin/apk add --no-chown $container_alpine_packages_missing
   1246 }
   1247 
   1248 # --- Void ---
   1249 
   1250 confz_container_void_base_files_check() {
   1251 	checkvars root
   1252 	# checkvars hostname locale
   1253 	defvar uid 0
   1254 	defvar gid 0
   1255 
   1256 	local d
   1257 	for d in $vars[root]{,/var{,/db{,/xbps{,/keys}}}}; do
   1258 		require fs_d filename="$d"
   1259 		require fs_m filename="$d" mode=0755
   1260 		require fs_o filename="$d" owner=$vars[uid]:$vars[gid]
   1261 	done
   1262 
   1263 	local f
   1264 	for f in $container_template_dir/void/**/*(.); do
   1265 		require container_template_file :root :uid :gid \
   1266 			template=void name=${f#${container_template_dir}/void/}
   1267 	done
   1268 
   1269 	# Alpine XBPS compatibility
   1270 	require fs_l filename="$vars[root]/var/lib/xbps/db" \
   1271 		flags=\!p destination="../../db"
   1272 }
   1273 
   1274 confz_container_void_xbps_check() {
   1275 	checkvars sysroot_user root arch mirror repository
   1276 	defvar xbps_install_executable ${container_xbps_install_executable:-xbps-install}
   1277 	do_command=(
   1278 		env XBPS_ARCH=$vars[arch]
   1279 		s6-setuidgid $vars[sysroot_user]
   1280 		$vars[xbps_install_executable]
   1281 		--sync
   1282 		--rootdir $vars[root]
   1283 		--repository ${vars[mirror]#/}/$vars[repository]
   1284 		--yes
   1285 		base-files xbps dash coreutils
   1286 	)
   1287 	[[ -f $vars[root]/usr/bin/xbps-install && -f $vars[root]/usr/bin/sh ]]
   1288 }
   1289 
   1290 confz_container_void_image_check() {
   1291 	checkvars containers_dir image_name arch
   1292 	defvar mirror https://repo-default.voidlinux.org/
   1293 	defvar repository current
   1294 	#defvar hostname $vars[image_name]
   1295 	#defvar locale C.UTF-8
   1296 
   1297 	require container_image_layout :containers_dir :image_name \
   1298 		%uid %gid %root %sysroot_user
   1299 	require container_generic_layout :uid :gid :root
   1300 	require container_void_base_files :uid :gid :root
   1301 	require container_void_xbps :arch :mirror :repository \
   1302 		:root :sysroot_user \?xbps_install_executable
   1303 }
   1304 
   1305 confz_container_void_packages_installed_check() {
   1306 	checkvars packages containers_dir image_name svscan_dir
   1307 
   1308 	require container_service_sysroot \
   1309 		:containers_dir :svscan_dir :image_name \
   1310 		%root %sysroot_svc
   1311 
   1312 	local -a missing
   1313 	local pkg
   1314 
   1315 	for pkg in $=vars[packages]; do
   1316 		[[ -f $vars[root]/var/db/xbps/.${pkg}-files.plist ]] \
   1317 			|| missing+=( $pkg )
   1318 	done
   1319 
   1320 	do_command=(
   1321 		$commands[cd] $vars[sysroot_svc] container_sysroot_run
   1322 		/usr/sbin/xbps-install --yes --sync -- $missing
   1323 	)
   1324 
   1325 	(( $#missing == 0 ))
   1326 }
   1327 
   1328 # --- Nix / NixOS ---
   1329 
   1330 confz_container_nix_base_files_check() {
   1331 	checkvars root hostname locale
   1332 	defvar uid 0
   1333 	defvar gid 0
   1334 
   1335 	require fs_contentnl filename="$vars[root]/etc/hostname" \
   1336 		content="$vars[hostname]"
   1337 	require fs_m filename="$vars[root]/etc/hostname" mode=0644
   1338 	require fs_o filename="$vars[root]/etc/hostname" owner=$vars[uid]:$vars[gid]
   1339 
   1340 	require container_template_file :root :uid :gid \
   1341 		template=alpine name=etc/hosts
   1342 
   1343 	require fs_contentnl filename="$vars[root]/etc/motd" \
   1344 		content="Welcome to container image at ${(qqq)vars[root]}"
   1345 	require fs_m filename="$vars[root]/etc/motd" mode=0644
   1346 	require fs_o filename="$vars[root]/etc/motd" owner=$vars[uid]:$vars[gid]
   1347 
   1348 	require container_template_file :root :uid :gid \
   1349 		template=alpine name=etc/profile
   1350 
   1351 	local -a locale_lines=(
   1352 		"export CHARSET=${(q)vars[locale]}"
   1353 		"export LANG=${(q)vars[locale]}"
   1354 		"export LC_COLLATE=C"
   1355 	)
   1356 	require fs_d filename="$vars[root]/etc/profile.d"
   1357 	require fs_m filename="$vars[root]/etc/profile.d" mode=0755
   1358 	require fs_o filename="$vars[root]/etc/profile.d" owner=$vars[uid]:$vars[gid]
   1359 
   1360 	require fs_contentnl filename="$vars[root]/etc/profile.d/locale.sh" \
   1361 		content="${(F)locale_lines}"
   1362 	require fs_m filename="$vars[root]/etc/profile.d/locale.sh" mode=0644
   1363 	require fs_o filename="$vars[root]/etc/profile.d/locale.sh" owner=$vars[uid]:$vars[gid]
   1364 
   1365 	require fs_l filename="$vars[root]/etc/profile.d/nix.sh" \
   1366 		destination="/nix/var/nix/profiles/default/etc/profile.d/nix.sh"
   1367 
   1368 	# TODO: source Nix stuff from profile
   1369 
   1370 	require container_template_file :root :uid :gid \
   1371 		template=alpine name=etc/protocols
   1372 
   1373 	require container_template_file :root :uid :gid \
   1374 		template=alpine name=etc/services
   1375 
   1376 	require container_template_file :root :uid :gid \
   1377 		template=alpine name=etc/shells
   1378 
   1379 	require fs_f filename="$vars[root]/etc/group"
   1380 	# require fs_c filename="$vars[root]/etc/group" \
   1381 	# 	content=""
   1382 	require fs_m filename="$vars[root]/etc/group" mode=0644
   1383 	require fs_o filename="$vars[root]/etc/group" owner=$vars[uid]:$vars[gid]
   1384 
   1385 	require fs_f filename="$vars[root]/etc/passwd"
   1386 	# require fs_c filename="$vars[root]/etc/passwd" \
   1387 	# 	content=""
   1388 	require fs_m filename="$vars[root]/etc/passwd" mode=0644
   1389 	require fs_o filename="$vars[root]/etc/passwd" owner=$vars[uid]:$vars[gid]
   1390 
   1391 	# symlink relevant executables for shebangs
   1392 	require fs_d filename="$vars[root]/bin"
   1393 	require fs_m filename="$vars[root]/bin" mode=0755
   1394 	require fs_o filename="$vars[root]/bin" owner=$vars[uid]:$vars[gid]
   1395 
   1396 	# require fs_l filename="$vars[root]/bin/execlineb" \
   1397 	# 	destination="/root/.nix-profile/bin/execlineb"
   1398 
   1399 	# require fs_l filename="$vars[root]/bin/zsh" \
   1400 	# 	destination="/root/.nix-profile/bin/zsh"
   1401 }
   1402 
   1403 confz_container_nix_image_from_release_check() {
   1404 	checkvars containers_dir svscan_dir image_name system
   1405 	defvar release 2.9.1
   1406 	defvar checksum_algo sha256
   1407 	defvar mirror https://releases.nixos.org/nix
   1408 
   1409 	case $vars[release] in
   1410 		(2.9.1) case $vars[system] in
   1411 			(x86_64-linux)
   1412 				defvar checksum ea7b94637b251cdaadf932cef41c681aa3d2a15928877d8319ae6f35a440977d
   1413 				;;
   1414 
   1415 			(i686-linux)
   1416 				defvar checksum 41e38706a26736aa42acd3dbd57db7e354e722e4bd5f6d9c8069d1c98b6081be
   1417 				;;
   1418 
   1419 			(aarch64-linux)
   1420 				defvar checksum d706c6b710548b9c3ed4a409df3a7293da14f726dcc59849abd709e574cabeed
   1421 				;;
   1422 
   1423 			(armv6l-linux)
   1424 				defvar checksum d8483f0747dce74685fcffa628908a96e6d0f7b1166a97f0eef231f5faa86c22
   1425 				;;
   1426 
   1427 			(armv7l-linux)
   1428 				defvar checksum 6f7f285d5de8b8d7686b6925869e25c2ff40f16492190c0b773ebd357bd4c956
   1429 				;;
   1430 		esac
   1431 		;;
   1432 	esac
   1433 
   1434 	defvar alpine_arch ${vars[system]%-*}
   1435 	unify url $vars[mirror]/nix-$vars[release]/nix-$vars[release]-$vars[system].tar.xz
   1436 
   1437 	(($+vars[checksum])) || die "No stored checksum for $url"
   1438 
   1439 	require container_nix_image :containers_dir :svscan_dir :image_name :url \
   1440 		:checksum :checksum_algo :alpine_arch \?hostname \?locale
   1441 }
   1442 
   1443 confz_container_nix_bootstrap_packages_check() {
   1444 	checkvars sysroot_user root arch uid gid
   1445 	defvar keys_dir ${container_alpine_keys_dir:-/etc/apk/keys}
   1446 	defvar apk_executable ${container_apk_executable:-apk}
   1447 	defvar mirror http://mirror.fel.cvut.cz/alpine
   1448 	defvar release edge
   1449 	defvar repositories main
   1450 
   1451 	local -a repositories=( $vars[mirror]/$vars[release]/${^=vars[repositories]} )
   1452 
   1453 	require fs_d filename="$vars[root]/etc/apk"
   1454 	require fs_m filename="$vars[root]/etc/apk" mode=0755
   1455 	require fs_o filename="$vars[root]/etc/apk" owner=$vars[uid]:$vars[gid]
   1456 
   1457 	require fs_contentnl filename="$vars[root]/etc/apk/repositories" \
   1458 		content="${(F)repositories}"
   1459 	require fs_m filename="$vars[root]/etc/apk/repositories" mode=0644
   1460 	require fs_o filename="$vars[root]/etc/apk/repositories" owner=$vars[uid]:$vars[gid]
   1461 
   1462 	do_command=(
   1463 		s6-setuidgid $vars[sysroot_user]
   1464 		$vars[apk_executable]
   1465 		--update-cache
   1466 		--initdb
   1467 		--arch $vars[arch]
   1468 		--root $vars[root]
   1469 		--keys-dir $vars[keys_dir]
   1470 		--no-scripts
   1471 		add alpine-keys busybox ca-certificates{,-bundle}
   1472 	)
   1473 	[[ -f $vars[root]/bin/busybox ]]
   1474 }
   1475 
   1476 confz_container_nix_bootstrap_check() {
   1477 	checkvars root sysroot_svc sysroot_user uid gid arch
   1478 
   1479 	require container_nix_bootstrap_packages \
   1480 		:root :arch :uid :gid :sysroot_user \
   1481 		\?keys_dir \?apk_executable \?mirror \?release \?repositories
   1482 
   1483 	do_command=(
   1484 		$commands[cd] $vars[sysroot_svc] container_sysroot_run
   1485 		/bin/busybox --install -s /bin
   1486 	)
   1487 
   1488 	[[ -f $vars[root]/bin/test ]]
   1489 }
   1490 
   1491 confz_container_nix_image_installed_check() {
   1492 	checkvars root filename uid gid
   1493 
   1494 	require fs_r flags=r filename=$vars[root]/${vars[filename]%.tar.*}
   1495 
   1496 	require fs_d filename="$vars[root]/nix"
   1497 	require fs_m filename="$vars[root]/nix" mode=0755
   1498 	require fs_o filename="$vars[root]/nix" owner=$vars[uid]:$vars[gid]
   1499 
   1500 	[[ -d $vars[root]/nix/store ]]
   1501 }
   1502 
   1503 confz_container_nix_image_installed_do() {
   1504 	local download_dir=$vars[containers_dir]/download-cache
   1505 	s6-setuidgid $vars[sysroot_user] \
   1506 		tar -xpC "$vars[root]" -f "$download_dir/$vars[filename]" \
   1507 		|| die "Unpacking ${(qqq)vars[filename]} failed"
   1508 
   1509 	$commands[cd] $vars[svscan_dir]/container.$vars[image_name].sysroot \
   1510 		container_sysroot_run \
   1511 		/${vars[filename]%.tar.*}/install \
   1512 		|| die "Nix installation script failed"
   1513 
   1514 	rm -rf $vars[root]/${vars[filename]%.tar.*} \
   1515 		|| die "Removing tarball directory failed"
   1516 }
   1517 
   1518 confz_container_nix_image_check() {
   1519 	checkvars containers_dir image_name url checksum svscan_dir alpine_arch
   1520 	defvar checksum_algo sha256
   1521 
   1522 	defvar hostname $vars[image_name]
   1523 	defvar locale C.UTF-8
   1524 	# TODO: test if these actually do something
   1525 
   1526 	require container_service_sysroot \
   1527 		:containers_dir :svscan_dir :image_name \
   1528 		%root %uid %gid %sysroot_user %sysroot_svc
   1529 
   1530 	require container_download_and_verify :containers_dir \
   1531 		:checksum :checksum_algo %filename :url
   1532 
   1533 	require container_generic_layout :uid :gid :root
   1534 	require container_nix_base_files :uid :gid :root :hostname :locale
   1535 
   1536 	require container_nix_bootstrap :sysroot_svc :root :uid :gid :sysroot_user
   1537 		\?arch=alpine_arch \
   1538 		\?keys_dir=alpine_keys_dir \
   1539 		\?mirror=alpine_mirrors \
   1540 		\?release=alpine_release \
   1541 		\?repositories=alpine_repositories \
   1542 		\?apk_executable
   1543 
   1544 	require container_nix_image_installed :filename :root :uid :gid
   1545 
   1546 	require fs_l filename="$vars[root]/nix/var/nix/profiles/default" \
   1547 		destination="per-user/root/profile"
   1548 	require fs_o filename="$vars[root]/nix/var/nix/profiles/default" \
   1549 		owner=$vars[uid]:$vars[gid]
   1550 }
   1551 
   1552 confz_container_nix_bin_linked_check() {
   1553 	checkvars containers_dir image_name
   1554 
   1555 	require container_image_layout :containers_dir :image_name %root
   1556 
   1557 	local profile_dir=$vars[root]/root/.nix-profile
   1558 	local -A stat_info
   1559 	zstat -L -H stat_info $profile_dir
   1560 	# while it's a symlink
   1561 	while (( $stat_info[mode] >> 12 == 10 )); do
   1562 		if [[ $stat_info[link] == /* ]]; then
   1563 			profile_dir=$vars[root]$stat_info[link]
   1564 		else
   1565 			profile_dir=${profile_dir:h}/$stat_info[link]
   1566 		fi
   1567 		zstat -L -H stat_info $profile_dir
   1568 	done
   1569 	[[ -d $profile_dir ]] || \
   1570 		die "Could not find profile directory: ${(qqq)profile_dir}"
   1571 
   1572 	local b
   1573 	for b in $profile_dir/bin/*; do
   1574 		[[ -e $vars[root]/bin/$b:t ]] || \
   1575 			require fs_l filename="$vars[root]/bin/${b:t}" \
   1576 				destination=../root/.nix-profile/bin/$b:t
   1577 	done
   1578 }
   1579 
   1580 confz_container_nix_packages_installed_check() {
   1581 	checkvars packages containers_dir image_name svscan_dir
   1582 
   1583 	require container_service_sysroot \
   1584 		:containers_dir :svscan_dir :image_name \
   1585 		%root %svscan_dir
   1586 
   1587 	local -A stat_info
   1588 
   1589 	# local profile_dir=$vars[root]/nix/var/nix/profiles/per-user/root/profile
   1590 	local profile_dir=$vars[root]/root/.nix-profile
   1591 	zstat -L -H stat_info $profile_dir
   1592 	# while it's a symlink
   1593 	while (( $stat_info[mode] >> 12 == 10 )); do
   1594 		if [[ $stat_info[link] == /* ]]; then
   1595 			profile_dir=$vars[root]$stat_info[link]
   1596 		else
   1597 			profile_dir=${profile_dir:h}/$stat_info[link]
   1598 		fi
   1599 		zstat -L -H stat_info $profile_dir
   1600 	done
   1601 	[[ -d $profile_dir ]] || \
   1602 		die "Could not find profile directory: ${(qqq)profile_dir}"
   1603 
   1604 	local manifest_file=$profile_dir/manifest.nix
   1605 	zstat -L -H stat_info $manifest_file
   1606 	# while it's a symlink
   1607 	while (( $stat_info[mode] >> 12 == 10 )); do
   1608 		if [[ $stat_info[link] == /* ]]; then
   1609 			manifest_file=$vars[root]$stat_info[link]
   1610 		else
   1611 			manifest_file=${manifest_file:h}/$stat_info[link]
   1612 		fi
   1613 		zstat -L -H stat_info $manifest_file
   1614 	done
   1615 	[[ -f $manifest_file ]] || \
   1616 		die "Could not find manifest.nix file: ${(qqq)manifest_file}"
   1617 
   1618 	local -a world world_noversion missing
   1619 	world=( "${(@f)$(
   1620 		grep -o 'outPath = "[^"]*"' $manifest_file \
   1621 		| uniq | sed 's|^outPath = "/nix/store/[^-]*-||;s|"$||'
   1622 	)}" )
   1623 	world_noversion=( "${world[@]%-bin}" )
   1624 	world_noversion=( "${world_noversion[@]/%-[-0-9.]#/}" )
   1625 
   1626 	local pkg
   1627 	for pkg in $=vars[packages]; do
   1628 		(( $world[(I)${pkg}] )) || \
   1629 			(( $world_noversion[(I)${pkg}] )) || \
   1630 			missing+=( $pkg )
   1631 	done
   1632 
   1633 	do_command=(
   1634 		$commands[cd] $vars[sysroot_svc] container_sysroot_run
   1635 		/root/.nix-profile/bin/nix-env --install $missing
   1636 		# /var/lib/nix/profiles/default/bin/nix-env --install $missing
   1637 	)
   1638 
   1639 	fail_reason="Following packages are not installed: $missing"
   1640 	(( $#missing == 0 ))
   1641 }
   1642 #typeset -f -t confz_container_nix_packages_installed_check
   1643 
   1644 # --- Gentoo ---
   1645 confz_container_gentoo_from_snapshot_check() {
   1646 	checkvars containers_dir svscan_dir image_name system
   1647 	defvar checksum_algo sha256
   1648 	#defvar mirror https://mirrors.gentoo.org/gentoo
   1649 	defvar mirror http://ftp.fi.muni.cz/pub/linux/gentoo/
   1650 
   1651 	case $vars[system] in
   1652 		(amd64-musl-hardened) defvar build 20241006T144834Z; case $vars[build] in
   1653 			(20241006T144834Z)
   1654 				defvar checksum 8d53c2d6df66f5e0559541b31c1f6587339cc26640a74372449afeaac4ecc2fc
   1655 				;;
   1656 			(20240312T171909Z)
   1657 				defvar checksum 2f3b224aeb231fec83652d9d9a5b9b80a28b46521bca7a0347a5ba212ae00e04
   1658 				;;
   1659 			(20240128T165521Z)
   1660 				defvar checksum ab0bcfe9001dc0fc612e92fb2ccbbf1e2c03fd5630712515b28a1362268e15f1
   1661 				;;
   1662 		esac
   1663 		;;
   1664 		(amd64-nomultilib-openrc) defvar build 20241110T170333Z; case $vars[build] in
   1665 			(20241110T170333Z)
   1666 				defvar checksum 3248000a2cc0f4df9fbc0bc4e4f2a2c1db7265b5c8c7cc116dcdc0fda5705f59
   1667 				;;
   1668 		esac
   1669 		;;
   1670 	esac
   1671 
   1672 	defvar alpine_arch ${vars[system]%-*}
   1673 	unify url $vars[mirror]/releases/${vars[system]%%-*}/autobuilds/$vars[build]/stage3-${vars[system]}-${vars[build]}.tar.xz
   1674 
   1675 	(($+vars[checksum])) || die "No stored checksum for $url"
   1676 
   1677 	require container_gentoo_image :containers_dir :svscan_dir :image_name :url \
   1678 		:checksum :checksum_algo :alpine_arch \?hostname \?locale
   1679 }
   1680 
   1681 confz_container_gentoo_image_check() {
   1682 	checkvars containers_dir image_name url checksum checksum_algo svscan_dir alpine_arch
   1683 
   1684 	defvar hostname $vars[image_name]
   1685 	defvar locale C.UTF-8
   1686 	# TODO:apply them to configuration files?
   1687 
   1688 	require container_service_sysroot \
   1689 		:containers_dir :svscan_dir :image_name \
   1690 		%root %uid %gid %sysroot_user %sysroot_svc
   1691 
   1692 	require container_download_and_verify :containers_dir \
   1693 		:checksum :checksum_algo %filename :url
   1694 
   1695 	require container_gentoo_stage3_installed \
   1696 		:sysroot_user :containers_dir :root :filename
   1697 
   1698 	require container_generic_layout :uid :gid :root
   1699 
   1700 	require container_image_user_uid_gid \
   1701 		:containers_dir :image_name :uid :gid user=root
   1702 	require container_image_group_gid \
   1703 		:containers_dir :image_name :gid group=root
   1704 
   1705 	require container_image_user_uid_gid \
   1706 		:containers_dir :image_name :uid :gid user=portage
   1707 	require container_image_group_gid \
   1708 		:containers_dir :image_name :gid group=portage
   1709 }
   1710 
   1711 confz_container_gentoo_stage3_installed_check() {
   1712 	[[ -f $vars[root]/.confz.containers.installed_from ]]
   1713 }
   1714 confz_container_gentoo_stage3_installed_do() {
   1715 	local download_dir=$vars[containers_dir]/download-cache
   1716 	s6-setuidgid $vars[sysroot_user] \
   1717 		tar -xpC "$vars[root]" --exclude ./dev/\* -f "$download_dir/$vars[filename]" \
   1718 		|| die "Unpacking ${(qqq)vars[filename]} failed"
   1719 
   1720 	s6-setuidgid $vars[sysroot_user] \
   1721 		rm -f "$vars[root]"/dev/**/*~*/(null|zero|full|ptmx|random|urandom)(DN%) \
   1722 		|| die "Failed to clean $vars[root]/dev"
   1723 
   1724 	printf '%s\n' $vars[filename] >$vars[root]/.confz.containers.installed_from || die
   1725 }
   1726 
   1727 # --- Debian ---
   1728 
   1729 confz_container_debian_image_check() {
   1730 	checkvars containers_dir image_name arch suite
   1731 	defvar mirror http://ftp.cvut.cz/debian/
   1732 
   1733 	require container_image_layout :containers_dir :image_name \
   1734 		%uid %gid %root %sysroot_user
   1735 	require container_debootstrap :root :arch :mirror :suite \
   1736 		:uid :gid
   1737 	require container_generic_layout :uid :gid :root
   1738 	#require container_debian_base_files :uid :gid :root
   1739 }
   1740 
   1741 confz_container_debootstrap_check() {
   1742 	checkvars root arch mirror suite uid gid
   1743 	defvar variant minbase
   1744 	defvar debootstrap_executable debootstrap
   1745 	[[ -f $vars[root]/usr/bin/apt-get && -f $vars[root]/usr/bin/sh ]]
   1746 }
   1747 confz_container_debootstrap_do() {
   1748 	local tmp_root=${vars[root]:h}/.debootstrap.${vars[root]:t}
   1749 	if [[ -e $tmp_root ]]; then
   1750 		rm -rf $tmp_root || return $?
   1751 	fi
   1752 	$vars[debootstrap_executable] --variant=$vars[variant] \
   1753 		--include=fakeroot \
   1754 		$vars[suite] $tmp_root $vars[mirror] || return $?
   1755 
   1756 	chown -R $vars[uid]:$vars[gid] $tmp_root || return $?
   1757 	s6-rename $tmp_root $vars[root] || return $?
   1758 }
   1759 typeset -f -t confz_container_debootstrap_do
   1760 
   1761 confz_container_debian_packages_installed_check() {
   1762 	checkvars containers_dir image_name packages svscan_dir
   1763 
   1764 	require container_service_sysroot \
   1765 		:containers_dir :svscan_dir :image_name \
   1766 		%uid %gid %root %sysroot_user %sysroot_svc
   1767 
   1768 	local root=$vars[containers_dir]/systems/$vars[image_name]
   1769 	local -a missing installed
   1770 	local pkg
   1771 
   1772 	installed=( ${(f)"$(
   1773 		awk '/^Package: /{p=$2} /^Status:.* installed/{print p}' $vars[root]/var/lib/dpkg/status
   1774 	)"} )
   1775 
   1776 	for pkg in $=vars[packages]; do
   1777 		(( $installed[(I)${pkg}] )) || missing+=( $pkg )
   1778 	done
   1779 
   1780 	do_command=(
   1781 		$commands[cd] $vars[sysroot_svc] container_sysroot_run
   1782 		# /usr/bin/apt-get install --trivial-only -- $missing
   1783 		/usr/bin/apt-get install --yes -- $missing
   1784 	)
   1785 
   1786 	fail_reason="Following packages are not installed: $missing"
   1787 	(( $#missing == 0 ))
   1788 }
   1789 
   1790 confz_container_debian_packages_installed_with_fakeroot_check() {
   1791 	checkvars containers_dir image_name packages svscan_dir
   1792 
   1793 	require container_service_sysroot \
   1794 		:containers_dir :svscan_dir :image_name \
   1795 		%uid %gid %root %sysroot_user %sysroot_svc
   1796 
   1797 	local root=$vars[containers_dir]/systems/$vars[image_name]
   1798 	local -a missing installed
   1799 	local pkg
   1800 
   1801 	installed=( ${(f)"$(
   1802 		awk '/^Package: /{p=$2} /^Status:.* installed/{print p}' $vars[root]/var/lib/dpkg/status
   1803 	)"} )
   1804 
   1805 	for pkg in $=vars[packages]; do
   1806 		(( $installed[(I)${pkg}] )) || missing+=( $pkg )
   1807 	done
   1808 
   1809 	do_command=(
   1810 		$commands[cd] $vars[sysroot_svc] container_sysroot_run
   1811 		/usr/bin/fakeroot-sysv /usr/bin/apt-get install --yes -- $missing
   1812 	)
   1813 
   1814 	fail_reason="Following packages are not installed: $missing"
   1815 	(( $#missing == 0 ))
   1816 }
   1817 
   1818 confz_container_puppet_apt_repo_check() {
   1819 	checkvars containers_dir svscan_dir image_name arch suite
   1820 	defvar puppet_version 7
   1821 
   1822 	require container_service_sysroot \
   1823 		:containers_dir :svscan_dir :image_name \
   1824 		%uid %gid %root %sysroot_user %sysroot_svc
   1825 
   1826 	[[ -f $vars[root]/etc/apt/trusted.gpg.d/puppet$vars[puppet_version]-keyring.gpg \
   1827 		&& -f $vars[root]/etc/apt/sources.list.d/puppet$vars[puppet_version].list \
   1828 		&& -f $vars[root]/var/lib/apt/lists/apt.puppetlabs.com_dists_$vars[suite]_InRelease ]]
   1829 }
   1830 confz_container_puppet_apt_repo_do() {
   1831 	local deb_file=puppet7-release-$vars[suite].deb
   1832 
   1833 	s6-setuidgid $vars[sysroot_user] \
   1834 		wget -O - >$vars[root]/root/$deb_file \
   1835 		https://apt.puppetlabs.com/$deb_file \
   1836 		|| return $?
   1837 	$commands[cd] $vars[sysroot_svc] container_sysroot_run \
   1838 		/usr/bin/dpkg --force-not-root -i /root/$deb_file \
   1839 		|| return $?
   1840 	$commands[cd] $vars[sysroot_svc] container_sysroot_run \
   1841 		/usr/bin/apt-get update \
   1842 		|| return $?
   1843 }
   1844