diff --git a/coverage.sh b/coverage.sh index 5ee6fb0..394dc7f 100755 --- a/coverage.sh +++ b/coverage.sh @@ -2581,21 +2581,28 @@ cat << END > shared/test.sh set -eu export LC_ALL=C.UTF-8 pkgs=base-files,base-passwd,busybox,debianutils,dpkg,libc-bin,mawk,tar +# busybox --install -s will install symbolic links into the rootfs, leaving +# existing files untouched. It has to run after extraction (otherwise there is +# no busybox binary) and before first configuration $CMD --mode=root --variant=custom \ --include=\$pkgs \ --setup-hook='mkdir -p "\$1/bin"' \ - --setup-hook='for p in awk cat chmod chown cp diff echo env grep less ln mkdir mount rm rmdir sed sh sleep sort touch uname; do ln -s busybox "\$1/bin/\$p"; done' \ --setup-hook='echo root:x:0:0:root:/root:/bin/sh > "\$1/etc/passwd"' \ --setup-hook='printf "root:x:0:\nmail:x:8:\nutmp:x:43:\n" > "\$1/etc/group"' \ + --extract-hook='chroot "\$1" busybox --install -s' \ $DEFAULT_DIST /tmp/debian-chroot $mirror echo "\$pkgs" | tr ',' '\n' > /tmp/expected chroot /tmp/debian-chroot dpkg-query -f '\${binary:Package}\n' -W \ | comm -12 - /tmp/expected \ | diff -u - /tmp/expected rm /tmp/expected -for cmd in echo cat sort sed grep; do +for cmd in echo cat sed grep; do test -L /tmp/debian-chroot/bin/\$cmd - test "\$(readlink /tmp/debian-chroot/bin/\$cmd)" = "busybox" + test "\$(readlink /tmp/debian-chroot/bin/\$cmd)" = "/bin/busybox" +done +for cmd in sort; do + test -L /tmp/debian-chroot/usr/bin/\$cmd + test "\$(readlink /tmp/debian-chroot/usr/bin/\$cmd)" = "/bin/busybox" done chroot /tmp/debian-chroot echo foobar \ | chroot /tmp/debian-chroot cat \ diff --git a/mmdebstrap b/mmdebstrap index 9200153..e8d396c 100755 --- a/mmdebstrap +++ b/mmdebstrap @@ -1868,6 +1868,8 @@ sub setup { print_progress "done"; } + run_hooks('extract', $options); + if ($options->{mode} eq 'chrootless') { if ($options->{dryrun}) { info "simulate installing packages..."; @@ -2481,7 +2483,7 @@ sub hookhelper { # owned by the root user. push @tarcmd, '--owner=0', '--group=0'; } - } elsif (any { $_ eq $hook } ('essential', 'customize')) { + } elsif (any { $_ eq $hook } ('extract', 'essential', 'customize')) { if ($mode eq 'fakechroot') { # Fakechroot requires tar to run inside the chroot or # otherwise absolute symlinks will include the path to the @@ -2517,7 +2519,10 @@ sub hookhelper { my $directory; if ($hook eq 'setup') { $directory = "$root/$outpath"; - } elsif (any { $_ eq $hook } ('essential', 'customize')) { + } elsif ( + any { $_ eq $hook } + ('extract', 'essential', 'customize') + ) { $directory = $outpath; } else { error "unknown hook: $hook"; @@ -2636,7 +2641,10 @@ sub hookhelper { my $directory; if ($hook eq 'setup') { $directory = "$root/$ARGV[$i]"; - } elsif (any { $_ eq $hook } ('essential', 'customize')) { + } elsif ( + any { $_ eq $hook } + ('extract', 'essential', 'customize') + ) { $directory = $ARGV[$i]; } else { error "unknown hook: $hook"; @@ -2818,6 +2826,7 @@ sub main() { apttrustedparts => $apttrustedparts, noop => [], setup_hook => [], + extract_hook => [], essential_hook => [], customize_hook => [], dryrun => 0, @@ -2872,6 +2881,7 @@ sub main() { sub { push @{ $options->{noop} }, 'force-check-gpg'; }, # hook options are hidden until I'm happy with them 'setup-hook=s@' => \$options->{setup_hook}, + 'extract-hook=s@' => \$options->{extract_hook}, 'essential-hook=s@' => \$options->{essential_hook}, 'customize-hook=s@' => \$options->{customize_hook}, # Sometimes --simulate fails even though non-simulate succeeds because @@ -2897,7 +2907,7 @@ sub main() { } if ($options->{dryrun}) { - foreach my $hook ('setup', 'essential', 'customize') { + foreach my $hook ('setup', 'extract', 'essential', 'customize') { if (scalar @{ $options->{"${hook}_hook"} } > 0) { warning "In dry-run mode, --$hook-hook options have no effect"; }