commit 50f83ab8012a9ecd9cf0a5a42433ca9871e00d7f
parent a4ad9820efb3a0bab75bb5a7591baedda069f3b4
Author: Jan Pobrislo <ccx@webprojekty.cz>
Date: Tue, 26 Jul 2022 02:31:45 +0200
WIP postintstall.fileset application using rsync to dedicated workdir
Diffstat:
5 files changed, 126 insertions(+), 11 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
.PHONY: all clean
-ALL_TARGETS:= s6-rc.fileset postinstall.fileset static/etc/fstab
+ALL_TARGETS:= s6-rc.fileset postinstall.fileset postinstall.rsfilter static/etc/fstab
all: $(ALL_TARGETS)
clean:
@@ -16,6 +16,10 @@ build/%.awk: %.aat
query.awk "$<" >"$@.new"
mv "$@.new" "$@"
+%.rsfilter: %.fileset
+ RSFILTER="$@.new" fileset "$<" >/dev/null
+ mv "$@.new" "$@"
+
build/s6-rc-mount.awk: s6-rc-mount.aat parse_fs.include.awk
build/fstab.awk: fstab.aat parse_fs.include.awk
diff --git a/postinstall b/postinstall
@@ -69,16 +69,18 @@ link_changed() {
[[ "${(P)preinstall_links:-}" != "${(P)postinstall_links:-}" ]]
}
-postinstall() {
- local diff_ret
- cd $ALL_DIR || exit $?
-
- ensure_symlink /command current/command || return $?
+setup_static_symlinks() {
symlink_static_file /etc/hostname || return $?
symlink_static_file /etc/fstab || return $?
symlink_static_file /etc/profile.d/slashcommand.sh || return $?
symlink_static_file /etc/mkinitfs/mkinitfs.conf || return $?
+}
+setup_storage() {
+}
+
+setup_rc() {
+ local diff_ret
if [[ -d /run/s6-rc/ ]]; then
diff -Ru $preinstall_current/s6-rc-source ./s6-rc-source; diff_ret=$?
(( $diff_ret == 0 || $diff_ret == 1 )) || \
@@ -105,15 +107,46 @@ postinstall() {
fi
fi
+}
+
+setup_fileset() {
+ local -a rsync=(
+ rsync
+ -aA
+ --delete
+ --log-format=$'%i\t%B\t%U:%G\t%M\t%l\t%n'
+ --filter="merge postinstall.rsfilter"
+ )
+ $rsync --delete-excluded --log-file $SETUP_DIR/rsync.log.get / $SETUP_DIR/files.pre || return $?
+ cp -a --reflink=auto $SETUP_DIR/files.pre $SETUP_DIR/files.post || return $?
+ ./command/fsapply $SETUP_DIR/files.post $PWD/conf/postinstall.fileset || exit $?
+ $rsync ---log-file $SETUP_DIR/rsync.log.put $SETUP_DIR/files.post / --backup --backup-dir=$SETUP_DIR/files.bak || return $?
+}
+
+postinstall() {
+ typeset -g SETUP_DIR=/versions/postinstall/$EPOCHSECONDS.$ALL_DIR:t
+ cd $ALL_DIR || exit $?
+ mkdir -p $SETUP_DIR
+
+ ensure_symlink /command current/command || return $?
+
+ setup_static_symlinks || return $?
+ if [[ -d /run/s6-rc/ ]]; then
+ # TODO: determine mountpoint changes
+ setup_storage || return $?
+ mount -a || return $?
+ fi
+ setup_fileset || return $?
+ setup_rc || return $?
exit 0
}
typeset -ft postinstall
typeset -g ALL_DIR=$0:h:h
-if [[ $ALL_DIR == /versions/all.* ]]; then
- path=( $ALL_DIR/command "$path[@]" )
- #fpath=( $ALL_DIR/zsh-functions "$fpath[@]" )
- postinstall || exit $?
-else
+if [[ $ALL_DIR != /versions/all.* ]]; then
die100 "Fatal: ${(qqq)0}: This script needs to be run from versioned directory as a part of installation procedure."
fi
+
+path=( $ALL_DIR/command "$path[@]" )
+#fpath=( $ALL_DIR/zsh-functions "$fpath[@]" )
+postinstall || exit $?
diff --git a/postinstall.aat b/postinstall.aat
@@ -0,0 +1,68 @@
+|function passwd_user(line) {
+/etc/passwd f +
+!f awk 'BEGIN { FS=OFS=":"; seen=0; line="{{line}}"; split(line, a) }
+ { uids[$3] = $0 }
+ $1 == a[1] {
+ for(n in a) {
+ if(a[n] != $n) {
+ print "error: differing present and requested lines" >>"/dev/stderr"
+ print "requested: " line >>"/dev/stderr"
+ print "present: " $0 >>"/dev/stderr"
+ exit 1
+ }
+ }
+ seen = 1
+ }
+ { print $0 }
+ END {
+ if(seen == 0) {
+ if(a[3] in uids) {
+ print "error: user record with requested UID already present" >>"/dev/stderr"
+ print "requested: " line >>"/dev/stderr"
+ print "present: " uids[a[3]] >>"/dev/stderr"
+ exit 1
+ }
+ print line
+ }
+ }'
+|}
+|function shadow_user(line) {
+/etc/shadow f +
+!f awk 'BEGIN { FS=OFS=":"; seen=0; line="{{line}}"; split(line, a) }
+ $1 == a[1] {
+ for(n in a) {
+ if(a[n] != $n) {
+ print "error: differing present and requested lines" >>"/dev/stderr"
+ print "requested: " line >>"/dev/stderr"
+ print "present: " $0 >>"/dev/stderr"
+ exit 1
+ }
+ }
+ seen = 1
+ }
+ { print $0 }
+ END {
+ if(seen == 0) {
+ print line
+ }
+ }'
+|}
+|function line_append_file(pre, match_str, post, pre_re, post_re, regex, grep1) {
+| regex = match_str
+| grep = pre match_str post
+| gsub(/[][)(\\\/*+?]/, "\\\\&", regex)
+| gsub(/[][)(\\\/*+?]/, "\\\\&", grep1)
+? grep -qEe '^{{grep1}}$' $fname
+! if grep -qEe '{{pre_re regex post_re}}' $fname; then
+ sed -ire 's|{{pre_re regex post_re}}|{{pre match_str post}}|' $fname
+ else
+ printf '%s\n' '{{pre match_str post}}' >> $fname
+ fi
+|}
+|END{
+/boot +
+/boot/extlinux.conf +
+/etc +
+/etc/passwd +
+/etc/group +
+|}
diff --git a/postinstall.fileset b/postinstall.fileset
@@ -0,0 +1,5 @@
+/boot +
+/boot/extlinux.conf +
+/etc +
+/etc/passwd +
+/etc/group +
diff --git a/postinstall.rsfilter b/postinstall.rsfilter
@@ -0,0 +1,5 @@
++ /boot
++ /boot/extlinux.conf
++ /etc
++ /etc/passwd
++ /etc/group