Compare commits
No commits in common. "abcfda04426996e12c1d7de0532030df2c6be90d" and "1f606f913da4285d5049535c6fc7eeb4dffc076f" have entirely different histories.
abcfda0442
...
1f606f913d
13 changed files with 230 additions and 656 deletions
|
@ -446,10 +446,6 @@ def main():
|
||||||
print("failed %d:" % len(failed), file=sys.stderr)
|
print("failed %d:" % len(failed), file=sys.stderr)
|
||||||
for f in failed:
|
for f in failed:
|
||||||
print(f, file=sys.stderr)
|
print(f, file=sys.stderr)
|
||||||
currenttime = time.time()
|
|
||||||
walltime = timedelta(seconds=int(currenttime - starttime))
|
|
||||||
print(f"total runtime: {walltime}", file=sys.stderr)
|
|
||||||
if failed:
|
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
11
coverage.txt
11
coverage.txt
|
@ -277,14 +277,12 @@ Variants: - standard
|
||||||
Skip-If:
|
Skip-If:
|
||||||
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
|
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
|
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
|
|
||||||
|
|
||||||
Test: debug
|
Test: debug
|
||||||
Variants: - standard
|
Variants: - standard
|
||||||
Skip-If:
|
Skip-If:
|
||||||
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
|
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
|
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
|
|
||||||
|
|
||||||
Test: quiet
|
Test: quiet
|
||||||
Needs-Root: true
|
Needs-Root: true
|
||||||
|
@ -422,12 +420,3 @@ Skip-If: hostarch in ["i386", "armel", "armhf", "mipsel"] # #1023286
|
||||||
|
|
||||||
Test: auto-mode-as-normal-user
|
Test: auto-mode-as-normal-user
|
||||||
Modes: auto
|
Modes: auto
|
||||||
|
|
||||||
Test: skip-output-dev
|
|
||||||
Modes: root unshare
|
|
||||||
|
|
||||||
Test: skip-output-mknod
|
|
||||||
Modes: root unshare
|
|
||||||
|
|
||||||
Test: skip-tar-in-mknod
|
|
||||||
Modes: unshare
|
|
||||||
|
|
|
@ -250,17 +250,6 @@ END
|
||||||
trap "-" EXIT INT TERM
|
trap "-" EXIT INT TERM
|
||||||
)
|
)
|
||||||
|
|
||||||
check_proxy_running() {
|
|
||||||
if timeout 1 bash -c 'exec 3<>/dev/tcp/127.0.0.1/8080 && printf "GET http://deb.debian.org/debian/dists/'"$DEFAULT_DIST"'/InRelease HTTP/1.1\nHost: deb.debian.org\n\n" >&3 && grep "Suite: '"$DEFAULT_DIST"'" <&3 >/dev/null' 2>/dev/null; then
|
|
||||||
return 0
|
|
||||||
elif timeout 1 env http_proxy="http://127.0.0.1:8080/" wget --quiet -O - "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" | grep "Suite: $DEFAULT_DIST" >/dev/null; then
|
|
||||||
return 0
|
|
||||||
elif timeout 1 curl --proxy "http://127.0.0.1:8080/" --silent "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" | grep "Suite: $DEFAULT_DIST" >/dev/null; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -e "./shared/cache.A" ] && [ -e "./shared/cache.B" ]; then
|
if [ -e "./shared/cache.A" ] && [ -e "./shared/cache.B" ]; then
|
||||||
echo "both ./shared/cache.A and ./shared/cache.B exist" >&2
|
echo "both ./shared/cache.A and ./shared/cache.B exist" >&2
|
||||||
echo "was a former run of the script aborted?" >&2
|
echo "was a former run of the script aborted?" >&2
|
||||||
|
@ -312,9 +301,8 @@ components=main
|
||||||
# by default, use the mmdebstrap executable in the current directory
|
# by default, use the mmdebstrap executable in the current directory
|
||||||
: "${CMD:=./mmdebstrap}"
|
: "${CMD:=./mmdebstrap}"
|
||||||
: "${USE_HOST_APT_CONFIG:=no}"
|
: "${USE_HOST_APT_CONFIG:=no}"
|
||||||
: "${FORCE_UPDATE:=no}"
|
|
||||||
|
|
||||||
if [ "$FORCE_UPDATE" != "yes" ] && [ -e "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
|
if [ -e "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
|
||||||
http_code=$(curl --output /dev/null --silent --location --head --time-cond "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" --write-out '%{http_code}' "$mirror/dists/$DEFAULT_DIST/InRelease")
|
http_code=$(curl --output /dev/null --silent --location --head --time-cond "$oldmirrordir/dists/$DEFAULT_DIST/InRelease" --write-out '%{http_code}' "$mirror/dists/$DEFAULT_DIST/InRelease")
|
||||||
case "$http_code" in
|
case "$http_code" in
|
||||||
200) ;; # need update
|
200) ;; # need update
|
||||||
|
@ -328,7 +316,7 @@ PROXYPID=$!
|
||||||
trap 'kill "$PROXYPID" || :' EXIT INT TERM
|
trap 'kill "$PROXYPID" || :' EXIT INT TERM
|
||||||
|
|
||||||
for i in $(seq 10); do
|
for i in $(seq 10); do
|
||||||
check_proxy_running && break
|
curl --proxy "http://127.0.0.1:8080/" --silent -o /dev/null "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" && break
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
|
if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
|
||||||
|
@ -437,7 +425,7 @@ if [ "$HAVE_QEMU" = "yes" ]; then
|
||||||
PROXYPID=$!
|
PROXYPID=$!
|
||||||
|
|
||||||
for i in $(seq 10); do
|
for i in $(seq 10); do
|
||||||
check_proxy_running && break
|
curl --proxy "http://127.0.0.1:8080/" --silent -o /dev/null "http://deb.debian.org/debian/dists/$DEFAULT_DIST/InRelease" && break
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
|
if [ ! -s "$newmirrordir/dists/$DEFAULT_DIST/InRelease" ]; then
|
||||||
|
@ -449,7 +437,7 @@ if [ "$HAVE_QEMU" = "yes" ]; then
|
||||||
tmpdir="$(mktemp -d)"
|
tmpdir="$(mktemp -d)"
|
||||||
trap 'kill "$PROXYPID" || :;cleanuptmpdir; cleanup_newcachedir' EXIT INT TERM
|
trap 'kill "$PROXYPID" || :;cleanuptmpdir; cleanup_newcachedir' EXIT INT TERM
|
||||||
|
|
||||||
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-static,qemu-user,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,squashfs-tools-ng,genext2fs,linux-image-generic
|
pkgs=perl-doc,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,qemu-user-static,qemu-user,dpkg-dev,mini-httpd,libdevel-cover-perl,libtemplate-perl,debootstrap,procps,apt-cudf,aspcud,python3,libcap2-bin,gpg,debootstrap,distro-info-data,iproute2,ubuntu-keyring,apt-utils,disorderfs,squashfs-tools-ng,genext2fs,linux-image-generic
|
||||||
if [ ! -e ./mmdebstrap ]; then
|
if [ ! -e ./mmdebstrap ]; then
|
||||||
pkgs="$pkgs,mmdebstrap"
|
pkgs="$pkgs,mmdebstrap"
|
||||||
fi
|
fi
|
||||||
|
@ -561,5 +549,3 @@ mv --no-target-directory ./shared/cache.tmp ./shared/cache
|
||||||
deletecache "$oldcachedir"
|
deletecache "$oldcachedir"
|
||||||
|
|
||||||
trap - EXIT INT TERM
|
trap - EXIT INT TERM
|
||||||
|
|
||||||
echo "$0 finished successfully" >&2
|
|
||||||
|
|
559
mmdebstrap
559
mmdebstrap
|
@ -1170,18 +1170,12 @@ sub setup_mounts {
|
||||||
);
|
);
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if (-e "$options->{root}/dev/$fname") {
|
|
||||||
warning(
|
|
||||||
"skipping creation of ./dev/$fname because it"
|
|
||||||
. " already exists in the target");
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
push @cleanup_tasks, sub {
|
push @cleanup_tasks, sub {
|
||||||
unlink "$options->{root}/dev/$fname"
|
unlink "$options->{root}/dev/$fname"
|
||||||
or warning("cannot unlink ./dev/$fname: $!");
|
or warning("cannot unlink ./dev/$fname: $!");
|
||||||
};
|
};
|
||||||
symlink $linkname, "$options->{root}/dev/$fname"
|
symlink $linkname, "$options->{root}/dev/$fname"
|
||||||
or warning
|
or error
|
||||||
"cannot create symlink ./dev/$fname -> $linkname";
|
"cannot create symlink ./dev/$fname -> $linkname";
|
||||||
}
|
}
|
||||||
} elsif ($type == 3 or $type == 4) {
|
} elsif ($type == 3 or $type == 4) {
|
||||||
|
@ -1272,9 +1266,8 @@ sub setup_mounts {
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
if (!$options->{havemknod}) {
|
if (!$options->{havemknod}) {
|
||||||
# If had mknod, then the directory to bind-mount
|
# If had mknod, then the directory to bind-mount into
|
||||||
# into was already created in the run_setup
|
# was already created in the run_setup function.
|
||||||
# function.
|
|
||||||
push @cleanup_tasks, sub {
|
push @cleanup_tasks, sub {
|
||||||
rmdir "$options->{root}/dev/$fname"
|
rmdir "$options->{root}/dev/$fname"
|
||||||
or warning("cannot rmdir ./dev/$fname: $!");
|
or warning("cannot rmdir ./dev/$fname: $!");
|
||||||
|
@ -1316,17 +1309,17 @@ sub setup_mounts {
|
||||||
or warning("umount ./dev/$fname failed: $?");
|
or warning("umount ./dev/$fname failed: $?");
|
||||||
};
|
};
|
||||||
if ($fname eq "pts/") {
|
if ($fname eq "pts/") {
|
||||||
# We cannot just bind-mount /dev/pts from the host
|
# We cannot just bind-mount /dev/pts from the host as
|
||||||
# as doing so will make posix_openpt() fail.
|
# doing so will make posix_openpt() fail. Instead, we
|
||||||
# Instead, we need to mount a new devpts.
|
# need to mount a new devpts.
|
||||||
# We need ptmxmode=666 because /dev/ptmx is a
|
# We need ptmxmode=666 because /dev/ptmx is a symlink
|
||||||
# symlink to /dev/pts/ptmx and without it
|
# to /dev/pts/ptmx and without it posix_openpt() will
|
||||||
# posix_openpt() will fail if we are not the root
|
# fail if we are not the root user.
|
||||||
# user. See also:
|
# See also:
|
||||||
# kernel.o/doc/Documentation/filesystems/devpts.txt
|
# kernel.org/doc/Documentation/filesystems/devpts.txt
|
||||||
# salsa.d.o/debian/schroot/-/merge_requests/2
|
# salsa.debian.org/debian/schroot/-/merge_requests/2
|
||||||
# https://bugs.debian.org/856877
|
# https://bugs.debian.org/856877
|
||||||
# https://bugs.debian.org/817236
|
# https://bugs.debian.org/817236
|
||||||
0 == system(
|
0 == system(
|
||||||
'mount',
|
'mount',
|
||||||
'-t',
|
'-t',
|
||||||
|
@ -1630,7 +1623,6 @@ sub run_hooks {
|
||||||
if (defined $options->{suite}) {
|
if (defined $options->{suite}) {
|
||||||
push @env_opts, "MMDEBSTRAP_SUITE=$options->{suite}";
|
push @env_opts, "MMDEBSTRAP_SUITE=$options->{suite}";
|
||||||
}
|
}
|
||||||
push @env_opts, "MMDEBSTRAP_FORMAT=$options->{format}";
|
|
||||||
# Storing the hook name is important for hook scripts to potentially change
|
# Storing the hook name is important for hook scripts to potentially change
|
||||||
# their behavior depending on the hook. It's also important for when the
|
# their behavior depending on the hook. It's also important for when the
|
||||||
# hook wants to use the mmdebstrap --hook-helper.
|
# hook wants to use the mmdebstrap --hook-helper.
|
||||||
|
@ -1661,9 +1653,6 @@ sub run_hooks {
|
||||||
push @env_opts,
|
push @env_opts,
|
||||||
("MMDEBSTRAP_ESSENTIAL=" . (join " ", @{$essential_pkgs}));
|
("MMDEBSTRAP_ESSENTIAL=" . (join " ", @{$essential_pkgs}));
|
||||||
}
|
}
|
||||||
if ($options->{mode} eq 'unshare') {
|
|
||||||
push @env_opts, "container=mmdebstrap-unshare";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Unset the close-on-exec flag, so that the file descriptor does not
|
# Unset the close-on-exec flag, so that the file descriptor does not
|
||||||
# get closed when we exec
|
# get closed when we exec
|
||||||
|
@ -1755,8 +1744,7 @@ sub run_hooks {
|
||||||
# does for python
|
# does for python
|
||||||
my @args = shellwords $script;
|
my @args = shellwords $script;
|
||||||
hookhelper($options->{root}, $options->{mode}, $name,
|
hookhelper($options->{root}, $options->{mode}, $name,
|
||||||
(join ',', @{ $options->{skip} }),
|
$options->{qemu}, $verbosity_level, @args);
|
||||||
$verbosity_level, @args);
|
|
||||||
exit 0;
|
exit 0;
|
||||||
}
|
}
|
||||||
waitpid($pid, 0);
|
waitpid($pid, 0);
|
||||||
|
@ -2601,8 +2589,6 @@ sub run_extract() {
|
||||||
}
|
}
|
||||||
# not using dpkg-deb --extract as that would replace the
|
# not using dpkg-deb --extract as that would replace the
|
||||||
# merged-usr symlinks with plain directories
|
# merged-usr symlinks with plain directories
|
||||||
# even after switching from pre-merging to post-merging, dpkg-deb
|
|
||||||
# will ignore filter rules from dpkg.cfg.d
|
|
||||||
# https://bugs.debian.org/989602
|
# https://bugs.debian.org/989602
|
||||||
# not using dpkg --unpack because that would try running preinst
|
# not using dpkg --unpack because that would try running preinst
|
||||||
# maintainer scripts
|
# maintainer scripts
|
||||||
|
@ -2782,49 +2768,90 @@ sub run_prepare {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
|
|
||||||
# foreign architecture setup for fakechroot mode
|
# copy qemu-user-static binary into chroot
|
||||||
if (defined $options->{qemu} && $options->{mode} eq 'fakechroot') {
|
if (defined $options->{qemu}) {
|
||||||
# Make sure that the fakeroot and fakechroot shared libraries exist for
|
if ($options->{mode} eq 'fakechroot') {
|
||||||
# the right architecture
|
# Make sure that the fakeroot and fakechroot shared
|
||||||
open my $fh, '-|', 'dpkg-architecture', '-a',
|
# libraries exist for the right architecture
|
||||||
$options->{nativearch},
|
open my $fh, '-|', 'dpkg-architecture', '-a',
|
||||||
'-qDEB_HOST_MULTIARCH' // error "failed to fork(): $!";
|
$options->{nativearch},
|
||||||
chomp(
|
'-qDEB_HOST_MULTIARCH' // error "failed to fork(): $!";
|
||||||
my $deb_host_multiarch = do { local $/; <$fh> }
|
chomp(
|
||||||
);
|
my $deb_host_multiarch = do { local $/; <$fh> }
|
||||||
close $fh;
|
);
|
||||||
if (($? != 0) or (!$deb_host_multiarch)) {
|
close $fh;
|
||||||
error "dpkg-architecture failed: $?";
|
if (($? != 0) or (!$deb_host_multiarch)) {
|
||||||
}
|
error "dpkg-architecture failed: $?";
|
||||||
my $fakechrootdir = "/usr/lib/$deb_host_multiarch/fakechroot";
|
}
|
||||||
if (!-e "$fakechrootdir/libfakechroot.so") {
|
my $fakechrootdir = "/usr/lib/$deb_host_multiarch/fakechroot";
|
||||||
error "$fakechrootdir/libfakechroot.so doesn't exist."
|
if (!-e "$fakechrootdir/libfakechroot.so") {
|
||||||
. " Install libfakechroot:$options->{nativearch}"
|
error "$fakechrootdir/libfakechroot.so doesn't exist."
|
||||||
. " outside the chroot";
|
. " Install libfakechroot:$options->{nativearch}"
|
||||||
}
|
. " outside the chroot";
|
||||||
my $fakerootdir = "/usr/lib/$deb_host_multiarch/libfakeroot";
|
}
|
||||||
if (!-e "$fakerootdir/libfakeroot-sysv.so") {
|
my $fakerootdir = "/usr/lib/$deb_host_multiarch/libfakeroot";
|
||||||
error "$fakerootdir/libfakeroot-sysv.so doesn't exist."
|
if (!-e "$fakerootdir/libfakeroot-sysv.so") {
|
||||||
. " Install libfakeroot:$options->{nativearch}"
|
error "$fakerootdir/libfakeroot-sysv.so doesn't exist."
|
||||||
. " outside the chroot";
|
. " Install libfakeroot:$options->{nativearch}"
|
||||||
}
|
. " outside the chroot";
|
||||||
|
}
|
||||||
# The rest of this block sets environment variables, so we have to add
|
# The rest of this block sets environment variables, so we
|
||||||
# the "no critic" statement to stop perlcritic from complaining about
|
# have to add the "no critic" statement to stop perlcritic
|
||||||
# setting global variables
|
# from complaining about setting global variables
|
||||||
## no critic (Variables::RequireLocalizedPunctuationVars)
|
## no critic (Variables::RequireLocalizedPunctuationVars)
|
||||||
# fakechroot only fills LD_LIBRARY_PATH with the directories of the
|
# fakechroot only fills LD_LIBRARY_PATH with the
|
||||||
# host's architecture. We append the directories of the chroot
|
# directories of the host's architecture. We append the
|
||||||
# architecture.
|
# directories of the chroot architecture.
|
||||||
$ENV{LD_LIBRARY_PATH}
|
$ENV{LD_LIBRARY_PATH}
|
||||||
= "$ENV{LD_LIBRARY_PATH}:$fakechrootdir:$fakerootdir";
|
= "$ENV{LD_LIBRARY_PATH}:$fakechrootdir:$fakerootdir";
|
||||||
# The binfmt support on the outside is used, so qemu needs to know
|
# The binfmt support on the outside is used, so qemu needs
|
||||||
# where it has to look for shared libraries
|
# to know where it has to look for shared libraries
|
||||||
if (defined $ENV{QEMU_LD_PREFIX}
|
if (defined $ENV{QEMU_LD_PREFIX}
|
||||||
&& $ENV{QEMU_LD_PREFIX} ne "") {
|
&& $ENV{QEMU_LD_PREFIX} ne "") {
|
||||||
$ENV{QEMU_LD_PREFIX} = "$ENV{QEMU_LD_PREFIX}:$options->{root}";
|
$ENV{QEMU_LD_PREFIX} = "$ENV{QEMU_LD_PREFIX}:$options->{root}";
|
||||||
|
} else {
|
||||||
|
$ENV{QEMU_LD_PREFIX} = $options->{root};
|
||||||
|
}
|
||||||
|
} elsif (any { $_ eq $options->{mode} } ('root', 'unshare')) {
|
||||||
|
my $require_qemu_static = 1;
|
||||||
|
# make $@ local, so we don't print an eventual error
|
||||||
|
# in other parts where we evaluate $@
|
||||||
|
local $@ = '';
|
||||||
|
eval {
|
||||||
|
# Check for the F flag which makes the kernel open the binfmt
|
||||||
|
# binary at configuration time instead of lazily at startup
|
||||||
|
# time. If the flag is set, then the qemu-static binary is not
|
||||||
|
# required inside the chroot.
|
||||||
|
if (-e "/proc/sys/fs/binfmt_misc/qemu-$options->{qemu}") {
|
||||||
|
open my $fh, '<',
|
||||||
|
"/proc/sys/fs/binfmt_misc/qemu-$options->{qemu}";
|
||||||
|
while (my $line = <$fh>) {
|
||||||
|
chomp($line);
|
||||||
|
if ($line =~ /^flags: [A-Z]*F[A-Z]*$/) {
|
||||||
|
$require_qemu_static = 0;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close $fh;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ($require_qemu_static) {
|
||||||
|
# other modes require a static qemu-user binary
|
||||||
|
my $qemubin = "/usr/bin/qemu-$options->{qemu}-static";
|
||||||
|
if (!-e $qemubin) {
|
||||||
|
error "cannot find $qemubin";
|
||||||
|
}
|
||||||
|
copy $qemubin, "$options->{root}/$qemubin"
|
||||||
|
or error "cannot copy $qemubin: $!";
|
||||||
|
# File::Copy does not retain permissions but on some
|
||||||
|
# platforms (like Travis CI) the binfmt interpreter must
|
||||||
|
# have the executable bit set or otherwise execve will
|
||||||
|
# fail with EACCES
|
||||||
|
chmod 0755, "$options->{root}/$qemubin"
|
||||||
|
or error "cannot chmod $qemubin: $!";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$ENV{QEMU_LD_PREFIX} = $options->{root};
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2965,15 +2992,15 @@ sub run_install() {
|
||||||
|
|
||||||
my @pkgs_to_install = (@{ $options->{include} });
|
my @pkgs_to_install = (@{ $options->{include} });
|
||||||
if ($options->{variant} eq 'buildd') {
|
if ($options->{variant} eq 'buildd') {
|
||||||
push @pkgs_to_install, 'build-essential', 'apt';
|
push @pkgs_to_install, 'build-essential';
|
||||||
}
|
}
|
||||||
if (any { $_ eq $options->{variant} }
|
if (any { $_ eq $options->{variant} }
|
||||||
('required', 'important', 'standard')) {
|
('required', 'important', 'standard', 'buildd')) {
|
||||||
# Many of the priority:required packages are also essential:yes. We
|
# Many of the priority:required packages are also essential:yes. We
|
||||||
# make sure not to select those here to avoid useless "xxx is already
|
# make sure not to select those here to avoid useless "xxx is already
|
||||||
# the newest version" messages.
|
# the newest version" messages.
|
||||||
my $priority;
|
my $priority;
|
||||||
if (any { $_ eq $options->{variant} } ('required')) {
|
if (any { $_ eq $options->{variant} } ('required', 'buildd')) {
|
||||||
$priority = '?and(?priority(required),?not(?essential))';
|
$priority = '?and(?priority(required),?not(?essential))';
|
||||||
} elsif ($options->{variant} eq 'important') {
|
} elsif ($options->{variant} eq 'important') {
|
||||||
$priority = '?and(?or(?priority(required),?priority(important)),'
|
$priority = '?and(?or(?priority(required),?priority(important)),'
|
||||||
|
@ -3142,7 +3169,7 @@ sub run_cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any { $_ eq 'cleanup/mmdebstrap/qemu' } @{ $options->{skip} }) {
|
if (any { $_ eq 'cleanup/mmdebstrap/qemu' } @{ $options->{skip} }) {
|
||||||
info "skipping cleanup/mmdebstrap/qemu as requested";
|
info "skipping cleanup/mmdebstrap/qume as requested";
|
||||||
} elsif (defined $options->{qemu}
|
} elsif (defined $options->{qemu}
|
||||||
and any { $_ eq $options->{mode} } ('root', 'unshare')
|
and any { $_ eq $options->{mode} } ('root', 'unshare')
|
||||||
and -e "$options->{root}/usr/bin/qemu-$options->{qemu}-static") {
|
and -e "$options->{root}/usr/bin/qemu-$options->{qemu}-static") {
|
||||||
|
@ -3231,52 +3258,6 @@ sub run_cleanup() {
|
||||||
closedir($dh);
|
closedir($dh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any { $_ eq 'cleanup/dev' } @{ $options->{skip} }) {
|
|
||||||
info "skipping cleanup/dev as requested";
|
|
||||||
} else {
|
|
||||||
|
|
||||||
# By default, tar is run with --exclude=./dev because we create the
|
|
||||||
# ./dev entries ourselves using @devfiles. But if --skip=output/dev is
|
|
||||||
# used, --exclude=./dev is not passed so that the chroot includes ./dev
|
|
||||||
# as created by base-files. But if mknod was available (for example
|
|
||||||
# when running as root) then ./dev will also include the @devfiles
|
|
||||||
# entries created by run_setup() and thus the resulting tarball will
|
|
||||||
# include things inside ./dev despite the user having supplied
|
|
||||||
# --skip=output/dev. So if --skip=output/dev was passed and if a
|
|
||||||
# tarball is to be created, we need to make sure to clean up the
|
|
||||||
# ./dev entries that were created in run_setup(). This is not done
|
|
||||||
# when creating a directory because in that case we want to do the
|
|
||||||
# same as debootstrap and create a directory including device nodes.
|
|
||||||
if ($options->{format} ne 'directory' && any { $_ eq 'output/dev' }
|
|
||||||
@{ $options->{skip} }) {
|
|
||||||
foreach my $file (@devfiles) {
|
|
||||||
my ($fname, $mode, $type, $linkname, $devmajor, $devminor)
|
|
||||||
= @{$file};
|
|
||||||
if (!-e "$options->{root}/dev/$fname") {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
# do not remove ./dev itself
|
|
||||||
if ($fname eq "") {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
if ($type == 0) { # normal file
|
|
||||||
error "type 0 not implemented";
|
|
||||||
} elsif ($type == 1) { # hardlink
|
|
||||||
error "type 1 not implemented";
|
|
||||||
} elsif (any { $_ eq $type } (2, 3, 4))
|
|
||||||
{ # symlink, char, block
|
|
||||||
unlink "$options->{root}/dev/$fname"
|
|
||||||
or error "failed to unlink ./dev/$fname: $!";
|
|
||||||
} elsif ($type == 5) { # directory
|
|
||||||
rmdir "$options->{root}/dev/$fname"
|
|
||||||
or error "failed to unlink ./dev/$fname: $!";
|
|
||||||
} else {
|
|
||||||
error "unsupported type: $type";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3359,20 +3340,8 @@ sub pivot_root {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hookhelper {
|
sub hookhelper {
|
||||||
my ($root, $mode, $hook, $skipopt, $verbosity, $command, @args) = @_;
|
my ($root, $mode, $hook, $qemu, $verbosity, $command, @args) = @_;
|
||||||
$verbosity_level = $verbosity;
|
$verbosity_level = $verbosity;
|
||||||
my @skipopts = ();
|
|
||||||
if (length $skipopt) {
|
|
||||||
for my $skip (split /[,\s]+/, $skipopt) {
|
|
||||||
# strip leading and trailing whitespace
|
|
||||||
$skip =~ s/^\s+|\s+$//g;
|
|
||||||
# skip if the remainder is an empty string
|
|
||||||
if ($skip eq '') {
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
push @skipopts, $skip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# we put everything in an eval block because that way we can easily handle
|
# we put everything in an eval block because that way we can easily handle
|
||||||
# errors without goto labels or much code duplication: the error handler
|
# errors without goto labels or much code duplication: the error handler
|
||||||
# has to send an "error" message to the other side
|
# has to send an "error" message to the other side
|
||||||
|
@ -3461,48 +3430,8 @@ sub hookhelper {
|
||||||
@cmdprefix, @tarcmd, '--xattrs-include=*',
|
@cmdprefix, @tarcmd, '--xattrs-include=*',
|
||||||
'--directory', $directory, '--extract', '--file', '-'
|
'--directory', $directory, '--extract', '--file', '-'
|
||||||
);
|
);
|
||||||
# go via mmtarfilter if copy-in/mknod, tar-in/mknod or
|
debug("helper: running " . (join " ", @cmd));
|
||||||
# sync-in/mknod were part of the skip options
|
open($fh, '|-', @cmd) // error "failed to fork(): $!";
|
||||||
if (any { $_ eq "$command/mknod" } @skipopts) {
|
|
||||||
info "skipping $command/mknod as requested";
|
|
||||||
my $tarfilter = "mmtarfilter";
|
|
||||||
if (-x "./tarfilter") {
|
|
||||||
$tarfilter = "./tarfilter";
|
|
||||||
}
|
|
||||||
pipe my $filter_reader, $fh or error "pipe failed: $!";
|
|
||||||
pipe my $tar_reader, my $filter_writer
|
|
||||||
or error "pipe failed: $!";
|
|
||||||
my $pid1 = fork() // error "fork() failed: $!";
|
|
||||||
if ($pid1 == 0) {
|
|
||||||
open(STDIN, '<&', $filter_reader)
|
|
||||||
or error "cannot open STDIN: $!";
|
|
||||||
open(STDOUT, '>&', $filter_writer)
|
|
||||||
or error "cannot open STDOUT: $!";
|
|
||||||
close($tar_reader)
|
|
||||||
or error "cannot close tar_reader: $!";
|
|
||||||
debug(
|
|
||||||
"helper: running $tarfilter --type-exclude=3 "
|
|
||||||
. "--type-exclude=4");
|
|
||||||
eval { Devel::Cover::set_coverage("none") }
|
|
||||||
if $is_covering;
|
|
||||||
exec $tarfilter, '--type-exclude=3',
|
|
||||||
'--type-exclude=4';
|
|
||||||
}
|
|
||||||
my $pid2 = fork() // error "fork() failed: $!";
|
|
||||||
if ($pid2 == 0) {
|
|
||||||
open(STDIN, '<&', $tar_reader)
|
|
||||||
or error "cannot open STDIN: $!";
|
|
||||||
close($filter_writer)
|
|
||||||
or error "cannot close filter_writer: $!";
|
|
||||||
debug("helper: running " . (join " ", @cmd));
|
|
||||||
eval { Devel::Cover::set_coverage("none") }
|
|
||||||
if $is_covering;
|
|
||||||
exec { $cmd[0] } @cmd;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug("helper: running " . (join " ", @cmd));
|
|
||||||
open($fh, '|-', @cmd) // error "failed to fork(): $!";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
error "unknown command: $command";
|
error "unknown command: $command";
|
||||||
}
|
}
|
||||||
|
@ -4022,15 +3951,13 @@ sub hooklistener {
|
||||||
if ($? != 0) {
|
if ($? != 0) {
|
||||||
error "tar failed";
|
error "tar failed";
|
||||||
}
|
}
|
||||||
} elsif ($msg eq "error") {
|
|
||||||
error "received error on socket";
|
|
||||||
} else {
|
} else {
|
||||||
error "unknown message: $msg";
|
error "unknown message: $msg";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
warning("hooklistener errored out: $@");
|
debug("hooklistener errored out: $@");
|
||||||
# inform the other side that something went wrong
|
# inform the other side that something went wrong
|
||||||
print STDOUT (pack("n", 0) . "error")
|
print STDOUT (pack("n", 0) . "error")
|
||||||
or error "cannot write to socket: $!";
|
or error "cannot write to socket: $!";
|
||||||
|
@ -4514,7 +4441,6 @@ sub main() {
|
||||||
include => [],
|
include => [],
|
||||||
architectures => [$hostarch],
|
architectures => [$hostarch],
|
||||||
mode => 'auto',
|
mode => 'auto',
|
||||||
format => 'auto',
|
|
||||||
dpkgopts => [],
|
dpkgopts => [],
|
||||||
aptopts => [],
|
aptopts => [],
|
||||||
apttrusted => $apttrusted,
|
apttrusted => $apttrusted,
|
||||||
|
@ -4528,6 +4454,7 @@ sub main() {
|
||||||
skip => [],
|
skip => [],
|
||||||
};
|
};
|
||||||
my $logfile = undef;
|
my $logfile = undef;
|
||||||
|
my $format = 'auto';
|
||||||
Getopt::Long::Configure('default', 'bundling', 'auto_abbrev',
|
Getopt::Long::Configure('default', 'bundling', 'auto_abbrev',
|
||||||
'ignore_case_always');
|
'ignore_case_always');
|
||||||
GetOptions(
|
GetOptions(
|
||||||
|
@ -4610,7 +4537,7 @@ sub main() {
|
||||||
'q|quiet' => sub { $verbosity_level = 0; },
|
'q|quiet' => sub { $verbosity_level = 0; },
|
||||||
'v|verbose' => sub { $verbosity_level = 2; },
|
'v|verbose' => sub { $verbosity_level = 2; },
|
||||||
'd|debug' => sub { $verbosity_level = 3; },
|
'd|debug' => sub { $verbosity_level = 3; },
|
||||||
'format=s' => \$options->{format},
|
'format=s' => \$format,
|
||||||
'logfile=s' => \$logfile,
|
'logfile=s' => \$logfile,
|
||||||
# no-op options so that mmdebstrap can be used with
|
# no-op options so that mmdebstrap can be used with
|
||||||
# sbuild-createchroot --debootstrap=mmdebstrap
|
# sbuild-createchroot --debootstrap=mmdebstrap
|
||||||
|
@ -4777,16 +4704,16 @@ sub main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# sqfs is an alias for squashfs
|
# sqfs is an alias for squashfs
|
||||||
if ($options->{format} eq 'sqfs') {
|
if ($format eq 'sqfs') {
|
||||||
$options->{format} = 'squashfs';
|
$format = 'squashfs';
|
||||||
}
|
}
|
||||||
# dir is an alias for directory
|
# dir is an alias for directory
|
||||||
if ($options->{format} eq 'dir') {
|
if ($format eq 'dir') {
|
||||||
$options->{format} = 'directory';
|
$format = 'directory';
|
||||||
}
|
}
|
||||||
my @valid_formats
|
my @valid_formats
|
||||||
= ('auto', 'directory', 'tar', 'squashfs', 'ext2', 'null');
|
= ('auto', 'directory', 'tar', 'squashfs', 'ext2', 'null');
|
||||||
if (none { $_ eq $options->{format} } @valid_formats) {
|
if (none { $_ eq $format } @valid_formats) {
|
||||||
error "invalid format. Choose from " . (join ', ', @valid_formats);
|
error "invalid format. Choose from " . (join ', ', @valid_formats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5553,7 +5480,7 @@ sub main() {
|
||||||
my $tar_compressor = get_tar_compressor($options->{target});
|
my $tar_compressor = get_tar_compressor($options->{target});
|
||||||
|
|
||||||
# figure out the right format
|
# figure out the right format
|
||||||
if ($options->{format} eq 'auto') {
|
if ($format eq 'auto') {
|
||||||
# (stat(...))[6] is the device identifier which contains the major and
|
# (stat(...))[6] is the device identifier which contains the major and
|
||||||
# minor numbers for character special files
|
# minor numbers for character special files
|
||||||
# major 1 and minor 3 is /dev/null on Linux
|
# major 1 and minor 3 is /dev/null on Linux
|
||||||
|
@ -5562,7 +5489,7 @@ sub main() {
|
||||||
and -c '/dev/null'
|
and -c '/dev/null'
|
||||||
and major((stat("/dev/null"))[6]) == 1
|
and major((stat("/dev/null"))[6]) == 1
|
||||||
and minor((stat("/dev/null"))[6]) == 3) {
|
and minor((stat("/dev/null"))[6]) == 3) {
|
||||||
$options->{format} = 'null';
|
$format = 'null';
|
||||||
} elsif ($options->{target} eq '-'
|
} elsif ($options->{target} eq '-'
|
||||||
and $OSNAME eq 'linux'
|
and $OSNAME eq 'linux'
|
||||||
and major((stat(STDOUT))[6]) == 1
|
and major((stat(STDOUT))[6]) == 1
|
||||||
|
@ -5570,9 +5497,9 @@ sub main() {
|
||||||
# by checking the major and minor number of the STDOUT fd we also
|
# by checking the major and minor number of the STDOUT fd we also
|
||||||
# can detect redirections to /dev/null and choose the null format
|
# can detect redirections to /dev/null and choose the null format
|
||||||
# accordingly
|
# accordingly
|
||||||
$options->{format} = 'null';
|
$format = 'null';
|
||||||
} elsif ($options->{target} ne '-' and -d $options->{target}) {
|
} elsif ($options->{target} ne '-' and -d $options->{target}) {
|
||||||
$options->{format} = 'directory';
|
$format = 'directory';
|
||||||
} elsif (
|
} elsif (
|
||||||
defined $tar_compressor
|
defined $tar_compressor
|
||||||
or $options->{target} =~ /\.tar$/
|
or $options->{target} =~ /\.tar$/
|
||||||
|
@ -5580,7 +5507,7 @@ sub main() {
|
||||||
or -p $options->{target} # named pipe (fifo)
|
or -p $options->{target} # named pipe (fifo)
|
||||||
or -c $options->{target} # character special like /dev/null
|
or -c $options->{target} # character special like /dev/null
|
||||||
) {
|
) {
|
||||||
$options->{format} = 'tar';
|
$format = 'tar';
|
||||||
# check if the compressor is installed
|
# check if the compressor is installed
|
||||||
if (defined $tar_compressor) {
|
if (defined $tar_compressor) {
|
||||||
my $pid = fork() // error "fork() failed: $!";
|
my $pid = fork() // error "fork() failed: $!";
|
||||||
|
@ -5600,7 +5527,7 @@ sub main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elsif ($options->{target} =~ /\.(squashfs|sqfs)$/) {
|
} elsif ($options->{target} =~ /\.(squashfs|sqfs)$/) {
|
||||||
$options->{format} = 'squashfs';
|
$format = 'squashfs';
|
||||||
# check if tar2sqfs is installed
|
# check if tar2sqfs is installed
|
||||||
my $pid = fork() // error "fork() failed: $!";
|
my $pid = fork() // error "fork() failed: $!";
|
||||||
if ($pid == 0) {
|
if ($pid == 0) {
|
||||||
|
@ -5616,7 +5543,7 @@ sub main() {
|
||||||
error("failed to start tar2sqfs --version");
|
error("failed to start tar2sqfs --version");
|
||||||
}
|
}
|
||||||
} elsif ($options->{target} =~ /\.ext2$/) {
|
} elsif ($options->{target} =~ /\.ext2$/) {
|
||||||
$options->{format} = 'ext2';
|
$format = 'ext2';
|
||||||
# check if the installed version of genext2fs supports tarballs on
|
# check if the installed version of genext2fs supports tarballs on
|
||||||
# stdin
|
# stdin
|
||||||
(undef, my $filename) = tempfile(
|
(undef, my $filename) = tempfile(
|
||||||
|
@ -5637,34 +5564,32 @@ sub main() {
|
||||||
error "genext2fs failed with exit status: $exitstatus";
|
error "genext2fs failed with exit status: $exitstatus";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$options->{format} = 'directory';
|
$format = 'directory';
|
||||||
}
|
}
|
||||||
info "automatically chosen format: $options->{format}";
|
info "automatically chosen format: $format";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $options->{target} eq '-'
|
if ($options->{target} eq '-' and $format ne 'tar' and $format ne 'null') {
|
||||||
and $options->{format} ne 'tar'
|
error "the $format format is unable to write to standard output";
|
||||||
and $options->{format} ne 'null') {
|
|
||||||
error "the $options->{format} format is unable to write to stdout";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($options->{format} eq 'null'
|
if ($format eq 'null'
|
||||||
and none { $_ eq $options->{target} } ('-', '/dev/null')) {
|
and none { $_ eq $options->{target} } ('-', '/dev/null')) {
|
||||||
info "ignoring target $options->{target} with null format";
|
info "ignoring target $options->{target} with null format";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($options->{format} eq 'ext2') {
|
if ($format eq 'ext2') {
|
||||||
if (!can_execute 'genext2fs') {
|
if (!can_execute 'genext2fs') {
|
||||||
error "need genext2fs for ext2 format";
|
error "need genext2fs for ext2 format";
|
||||||
}
|
}
|
||||||
} elsif ($options->{format} eq 'squashfs') {
|
} elsif ($format eq 'squashfs') {
|
||||||
if (!can_execute 'tar2sqfs') {
|
if (!can_execute 'tar2sqfs') {
|
||||||
error "need tar2sqfs binary from the squashfs-tools-ng package";
|
error "need tar2sqfs binary from the squashfs-tools-ng package";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2', 'null')) {
|
if (any { $_ eq $format } ('tar', 'squashfs', 'ext2', 'null')) {
|
||||||
if ($options->{format} ne 'null') {
|
if ($format ne 'null') {
|
||||||
if (any { $_ eq $options->{variant} } ('extract', 'custom')
|
if (any { $_ eq $options->{variant} } ('extract', 'custom')
|
||||||
and $options->{mode} eq 'fakechroot') {
|
and $options->{mode} eq 'fakechroot') {
|
||||||
info "creating a tarball or squashfs image or ext2 image in"
|
info "creating a tarball or squashfs image or ext2 image in"
|
||||||
|
@ -5701,7 +5626,7 @@ sub main() {
|
||||||
) {
|
) {
|
||||||
chmod 0755, $options->{root} or error "cannot chmod root: $!";
|
chmod 0755, $options->{root} or error "cannot chmod root: $!";
|
||||||
}
|
}
|
||||||
} elsif ($options->{format} eq 'directory') {
|
} elsif ($format eq 'directory') {
|
||||||
# user does not seem to have specified a tarball as output, thus work
|
# user does not seem to have specified a tarball as output, thus work
|
||||||
# directly in the supplied directory
|
# directly in the supplied directory
|
||||||
$options->{root} = $options->{target};
|
$options->{root} = $options->{target};
|
||||||
|
@ -5757,7 +5682,7 @@ sub main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
|
|
||||||
# check for double quotes because apt doesn't allow to escape them and
|
# check for double quotes because apt doesn't allow to escape them and
|
||||||
|
@ -5841,28 +5766,15 @@ sub main() {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
|
|
||||||
# If a tarball is to be created, we always (except if --skip=output/dev is
|
|
||||||
# passed) craft the /dev entries ourselves.
|
|
||||||
# Why do we put /dev entries in the final tarball?
|
|
||||||
# - because debootstrap does it
|
|
||||||
# - because schroot (#856877) and pbuilder rely on it and we care about
|
|
||||||
# Debian buildds (using schroot) and reproducible builds infra (using
|
|
||||||
# pbuilder)
|
|
||||||
# If both the above assertion change, we can stop creating /dev entries as
|
|
||||||
# well.
|
|
||||||
my $devtar = '';
|
my $devtar = '';
|
||||||
if (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2')) {
|
# We always craft the /dev entries ourselves if a tarball is to be created
|
||||||
|
if (any { $_ eq $format } ('tar', 'squashfs', 'ext2')) {
|
||||||
foreach my $file (@devfiles) {
|
foreach my $file (@devfiles) {
|
||||||
my ($fname, $mode, $type, $linkname, $devmajor, $devminor)
|
my ($fname, $mode, $type, $linkname, $devmajor, $devminor)
|
||||||
= @{$file};
|
= @{$file};
|
||||||
if (length "./dev/$fname" > 100) {
|
if (length "./dev/$fname" > 100) {
|
||||||
error "tar entry cannot exceed 100 characters";
|
error "tar entry cannot exceed 100 characters";
|
||||||
}
|
}
|
||||||
if ($type == 3
|
|
||||||
and any { $_ eq 'output/mknod' } @{ $options->{skip} }) {
|
|
||||||
info "skipping output/mknod as requested for ./dev/$fname";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
my $entry = pack(
|
my $entry = pack(
|
||||||
'a100 a8 a8 a8 a12 a12 A8 a1 a100 a8 a32 a32 a8 a8 a155 x12',
|
'a100 a8 a8 a8 a12 a12 A8 a1 a100 a8 a32 a32 a8 a8 a155 x12',
|
||||||
"./dev/$fname",
|
"./dev/$fname",
|
||||||
|
@ -5886,10 +5798,10 @@ sub main() {
|
||||||
= sprintf("%06o\0", unpack("%16C*", $entry));
|
= sprintf("%06o\0", unpack("%16C*", $entry));
|
||||||
$devtar .= $entry;
|
$devtar .= $entry;
|
||||||
}
|
}
|
||||||
} elsif (any { $_ eq $options->{format} } ('directory', 'null')) {
|
} elsif (any { $_ eq $format } ('directory', 'null')) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $exitstatus = 0;
|
my $exitstatus = 0;
|
||||||
|
@ -5902,14 +5814,11 @@ sub main() {
|
||||||
'--format=pax',
|
'--format=pax',
|
||||||
'--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime',
|
'--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime',
|
||||||
'-c',
|
'-c',
|
||||||
|
'--exclude=./dev',
|
||||||
'--exclude=./lost+found'
|
'--exclude=./lost+found'
|
||||||
);
|
);
|
||||||
# only exclude ./dev if device nodes are written out (the default)
|
|
||||||
if (none { $_ eq 'output/dev' } @{ $options->{skip} }) {
|
|
||||||
push @taropts, '--exclude=./dev';
|
|
||||||
}
|
|
||||||
# tar2sqfs and genext2fs do not support extended attributes
|
# tar2sqfs and genext2fs do not support extended attributes
|
||||||
if ($options->{format} eq "squashfs") {
|
if ($format eq "squashfs") {
|
||||||
# tar2sqfs supports user.*, trusted.* and security.* but not system.*
|
# tar2sqfs supports user.*, trusted.* and security.* but not system.*
|
||||||
# https://bugs.debian.org/988100
|
# https://bugs.debian.org/988100
|
||||||
# lib/sqfs/xattr/xattr.c of https://github.com/AgentD/squashfs-tools-ng
|
# lib/sqfs/xattr/xattr.c of https://github.com/AgentD/squashfs-tools-ng
|
||||||
|
@ -5918,7 +5827,7 @@ sub main() {
|
||||||
warning("tar2sqfs does not support extended attributes"
|
warning("tar2sqfs does not support extended attributes"
|
||||||
. " from the 'system' namespace");
|
. " from the 'system' namespace");
|
||||||
push @taropts, '--xattrs', '--xattrs-exclude=system.*';
|
push @taropts, '--xattrs', '--xattrs-exclude=system.*';
|
||||||
} elsif ($options->{format} eq "ext2") {
|
} elsif ($format eq "ext2") {
|
||||||
warning "genext2fs does not support extended attributes";
|
warning "genext2fs does not support extended attributes";
|
||||||
} else {
|
} else {
|
||||||
push @taropts, '--xattrs';
|
push @taropts, '--xattrs';
|
||||||
|
@ -5970,7 +5879,7 @@ sub main() {
|
||||||
close $childsock;
|
close $childsock;
|
||||||
|
|
||||||
close $nblkreader;
|
close $nblkreader;
|
||||||
if (!$options->{dryrun} && $options->{format} eq 'ext2') {
|
if (!$options->{dryrun} && $format eq 'ext2') {
|
||||||
my $numblocks = approx_disk_usage($options->{root});
|
my $numblocks = approx_disk_usage($options->{root});
|
||||||
print $nblkwriter "$numblocks\n";
|
print $nblkwriter "$numblocks\n";
|
||||||
$nblkwriter->flush();
|
$nblkwriter->flush();
|
||||||
|
@ -5979,8 +5888,7 @@ sub main() {
|
||||||
|
|
||||||
if ($options->{dryrun}) {
|
if ($options->{dryrun}) {
|
||||||
info "simulate creating tarball...";
|
info "simulate creating tarball...";
|
||||||
} elsif (any { $_ eq $options->{format} }
|
} elsif (any { $_ eq $format } ('tar', 'squashfs', 'ext2')) {
|
||||||
('tar', 'squashfs', 'ext2')) {
|
|
||||||
info "creating tarball...";
|
info "creating tarball...";
|
||||||
|
|
||||||
# redirect tar output to the writing end of the pipe so
|
# redirect tar output to the writing end of the pipe so
|
||||||
|
@ -6001,11 +5909,10 @@ sub main() {
|
||||||
or error "tar failed: $?";
|
or error "tar failed: $?";
|
||||||
|
|
||||||
info "done";
|
info "done";
|
||||||
} elsif (any { $_ eq $options->{format} }
|
} elsif (any { $_ eq $format } ('directory', 'null')) {
|
||||||
('directory', 'null')) {
|
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
|
|
||||||
exit 0;
|
exit 0;
|
||||||
|
@ -6037,7 +5944,7 @@ sub main() {
|
||||||
close $childsock;
|
close $childsock;
|
||||||
|
|
||||||
close $nblkreader;
|
close $nblkreader;
|
||||||
if (!$options->{dryrun} && $options->{format} eq 'ext2') {
|
if (!$options->{dryrun} && $format eq 'ext2') {
|
||||||
my $numblocks = approx_disk_usage($options->{root});
|
my $numblocks = approx_disk_usage($options->{root});
|
||||||
print $nblkwriter $numblocks;
|
print $nblkwriter $numblocks;
|
||||||
$nblkwriter->flush();
|
$nblkwriter->flush();
|
||||||
|
@ -6046,8 +5953,7 @@ sub main() {
|
||||||
|
|
||||||
if ($options->{dryrun}) {
|
if ($options->{dryrun}) {
|
||||||
info "simulate creating tarball...";
|
info "simulate creating tarball...";
|
||||||
} elsif (any { $_ eq $options->{format} }
|
} elsif (any { $_ eq $format } ('tar', 'squashfs', 'ext2')) {
|
||||||
('tar', 'squashfs', 'ext2')) {
|
|
||||||
info "creating tarball...";
|
info "creating tarball...";
|
||||||
|
|
||||||
# redirect tar output to the writing end of the pipe so that
|
# redirect tar output to the writing end of the pipe so that
|
||||||
|
@ -6095,10 +6001,10 @@ sub main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
info "done";
|
info "done";
|
||||||
} elsif (any { $_ eq $options->{format} } ('directory', 'null')) {
|
} elsif (any { $_ eq $format } ('directory', 'null')) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
|
|
||||||
exit 0;
|
exit 0;
|
||||||
|
@ -6156,7 +6062,7 @@ sub main() {
|
||||||
|
|
||||||
my $numblocks = 0;
|
my $numblocks = 0;
|
||||||
close $nblkwriter;
|
close $nblkwriter;
|
||||||
if (!$options->{dryrun} && $options->{format} eq 'ext2') {
|
if (!$options->{dryrun} && $format eq 'ext2') {
|
||||||
$numblocks = <$nblkreader>;
|
$numblocks = <$nblkreader>;
|
||||||
if (defined $numblocks) {
|
if (defined $numblocks) {
|
||||||
chomp $numblocks;
|
chomp $numblocks;
|
||||||
|
@ -6173,11 +6079,9 @@ sub main() {
|
||||||
|
|
||||||
if ($options->{dryrun}) {
|
if ($options->{dryrun}) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} elsif (any { $_ eq $options->{format} } ('directory', 'null')) {
|
} elsif (any { $_ eq $format } ('directory', 'null')) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} elsif ($options->{format} eq 'ext2' && $numblocks <= 0) {
|
} elsif (any { $_ eq $format } ('tar', 'squashfs', 'ext2')) {
|
||||||
# nothing to do because of invalid $numblocks
|
|
||||||
} elsif (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2')) {
|
|
||||||
# we use eval() so that error() doesn't take this process down and
|
# we use eval() so that error() doesn't take this process down and
|
||||||
# thus leaves the setup() process without a parent
|
# thus leaves the setup() process without a parent
|
||||||
eval {
|
eval {
|
||||||
|
@ -6186,27 +6090,27 @@ sub main() {
|
||||||
error "cannot copy to standard output: $!";
|
error "cannot copy to standard output: $!";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( $options->{format} eq 'squashfs'
|
if ( $format eq 'squashfs'
|
||||||
or $options->{format} eq 'ext2'
|
or $format eq 'ext2'
|
||||||
or defined $tar_compressor) {
|
or defined $tar_compressor) {
|
||||||
my @argv = ();
|
my @argv = ();
|
||||||
if ($options->{format} eq 'squashfs') {
|
if ($format eq 'squashfs') {
|
||||||
push @argv, 'tar2sqfs',
|
push @argv, 'tar2sqfs',
|
||||||
'--quiet', '--no-skip', '--force',
|
'--quiet', '--no-skip', '--force',
|
||||||
'--exportable',
|
'--exportable',
|
||||||
'--compressor', 'xz',
|
'--compressor', 'xz',
|
||||||
'--block-size', '1048576',
|
'--block-size', '1048576',
|
||||||
$options->{target};
|
$options->{target};
|
||||||
} elsif ($options->{format} eq 'ext2') {
|
} elsif ($format eq 'ext2') {
|
||||||
if ($numblocks <= 0) {
|
if ($numblocks <= 0) {
|
||||||
error "invalid number of blocks: $numblocks";
|
error "invalid number of blocks: $numblocks";
|
||||||
}
|
}
|
||||||
push @argv, 'genext2fs', '-B', 1024, '-b', $numblocks,
|
push @argv, 'genext2fs', '-B', 1024, '-b', $numblocks,
|
||||||
'-i', '16384', '-a', '-', $options->{target};
|
'-i', '16384', '-a', '-', $options->{target};
|
||||||
} elsif ($options->{format} eq 'tar') {
|
} elsif ($format eq 'tar') {
|
||||||
push @argv, @{$tar_compressor};
|
push @argv, @{$tar_compressor};
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
POSIX::sigprocmask(SIG_BLOCK, $sigset)
|
POSIX::sigprocmask(SIG_BLOCK, $sigset)
|
||||||
or error "Can't block signals: $!";
|
or error "Can't block signals: $!";
|
||||||
|
@ -6224,16 +6128,15 @@ sub main() {
|
||||||
or error "Can't unblock signals: $!";
|
or error "Can't unblock signals: $!";
|
||||||
|
|
||||||
# redirect stdout to file or /dev/null
|
# redirect stdout to file or /dev/null
|
||||||
if ( $options->{format} eq 'squashfs'
|
if ($format eq 'squashfs' or $format eq 'ext2') {
|
||||||
or $options->{format} eq 'ext2') {
|
|
||||||
open(STDOUT, '>', '/dev/null')
|
open(STDOUT, '>', '/dev/null')
|
||||||
or error "cannot open /dev/null for writing: $!";
|
or error "cannot open /dev/null for writing: $!";
|
||||||
} elsif ($options->{format} eq 'tar') {
|
} elsif ($format eq 'tar') {
|
||||||
open(STDOUT, '>', $options->{target})
|
open(STDOUT, '>', $options->{target})
|
||||||
or error
|
or error
|
||||||
"cannot open $options->{target} for writing: $!";
|
"cannot open $options->{target} for writing: $!";
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
open(STDIN, '<&', $rfh)
|
open(STDIN, '<&', $rfh)
|
||||||
or error "cannot open file handle for reading: $!";
|
or error "cannot open file handle for reading: $!";
|
||||||
|
@ -6265,34 +6168,12 @@ sub main() {
|
||||||
# running tar and this process itself) to reliably tear down
|
# running tar and this process itself) to reliably tear down
|
||||||
# all running child processes. The main process is not affected
|
# all running child processes. The main process is not affected
|
||||||
# because we are ignoring SIGHUP.
|
# because we are ignoring SIGHUP.
|
||||||
#
|
|
||||||
# FIXME: this codepath becomes dangerous in case mmdebstrap is not
|
|
||||||
# run in its own process group. When run from the terminal, the
|
|
||||||
# shell creates a new process group as part of its job control, so
|
|
||||||
# sending SIGHUP to all processes in our own process group should
|
|
||||||
# not be dangerous. But for example, on debci, lxc will run in the
|
|
||||||
# same process group as mmdebstrap and sending SIGHUP to the whole
|
|
||||||
# process group will also kill lxc. Creating a new process group
|
|
||||||
# for $pid will break things because only the foreground job is
|
|
||||||
# allowed to read from the terminal. If a background job does it,
|
|
||||||
# i will be suspended with SIGTTIN. Even though apt could be told
|
|
||||||
# to not read from the terminal by opening STDIN from /dev/null,
|
|
||||||
# this would make --chrooted-customize-hook=bash impossible.
|
|
||||||
# Making the $pid process group the foreground job will destroy all
|
|
||||||
# the signal handling we have set up for when the user presses
|
|
||||||
# ctrl+c in a terminal. Even if we fix the signal handling we now
|
|
||||||
# find ourselves in the opposite situation: the $pid process must
|
|
||||||
# now clean up the former main process tree reliably. And we cannot
|
|
||||||
# create a new process group for everything all-in-one because that
|
|
||||||
# would also destroy CTRL+C handling from the terminal.
|
|
||||||
warning "creating tarball failed: $@";
|
warning "creating tarball failed: $@";
|
||||||
my $pgroup = getpgrp();
|
kill HUP => -getpgrp();
|
||||||
warning "sending SIGHUP to all processes in process group $pgroup";
|
|
||||||
kill HUP => -$pgroup;
|
|
||||||
$exitstatus = 1;
|
$exitstatus = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
close($rfh);
|
close($rfh);
|
||||||
waitpid $pid, 0;
|
waitpid $pid, 0;
|
||||||
|
@ -6303,10 +6184,9 @@ sub main() {
|
||||||
# change signal handler message
|
# change signal handler message
|
||||||
$waiting_for = "cleanup";
|
$waiting_for = "cleanup";
|
||||||
|
|
||||||
if (any { $_ eq $options->{format} } ('directory')) {
|
if (any { $_ eq $format } ('directory')) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} elsif (any { $_ eq $options->{format} }
|
} elsif (any { $_ eq $format } ('tar', 'squashfs', 'ext2', 'null')) {
|
||||||
('tar', 'squashfs', 'ext2', 'null')) {
|
|
||||||
if (!-e $options->{root}) {
|
if (!-e $options->{root}) {
|
||||||
error "$options->{root} does not exist";
|
error "$options->{root} does not exist";
|
||||||
}
|
}
|
||||||
|
@ -6354,7 +6234,7 @@ sub main() {
|
||||||
error "unknown mode: $options->{mode}";
|
error "unknown mode: $options->{mode}";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error "unknown format: $options->{format}";
|
error "unknown format: $format";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($got_signal) {
|
if ($got_signal) {
|
||||||
|
@ -6392,24 +6272,24 @@ dependencies and is thus able to use more than one mirror and resolve more
|
||||||
complex dependencies. See section B<OPERATION> for an overview of how
|
complex dependencies. See section B<OPERATION> for an overview of how
|
||||||
B<mmdebstrap> works internally.
|
B<mmdebstrap> works internally.
|
||||||
|
|
||||||
If no I<MIRROR> option is provided and I<SUITE> is not a stable release name,
|
If no I<MIRROR> option is provided, L<http://deb.debian.org/debian> is used.
|
||||||
L<http://deb.debian.org/debian> is used. If I<SUITE> is a stable release name
|
If I<SUITE> is a stable release name and no I<MIRROR> is specified, then
|
||||||
and no I<MIRROR> is specified, then mirrors for updates and security are
|
mirrors for updates and security are automatically added. If a I<MIRROR>
|
||||||
automatically added. If a I<MIRROR> option starts with "deb " or "deb-src "
|
option starts with "deb " or "deb-src " then it is used as a one-line-style
|
||||||
then it is used as a one-line-style format entry for apt's sources.list inside
|
format entry for apt's sources.list inside the chroot. If a I<MIRROR> option
|
||||||
the chroot. If a I<MIRROR> option contains a "://" then it is interpreted as a
|
contains a "://" then it is interpreted as a mirror URI and the apt line
|
||||||
mirror URI and the apt line inside the chroot is assembled as "deb [arch=A] B C
|
inside the chroot is assembled as "deb [arch=A] B C D" where A is the host's
|
||||||
D" where A is the host's native architecture, B is the I<MIRROR>, C is the
|
native architecture, B is the I<MIRROR>, C is the given I<SUITE> and D is the
|
||||||
given I<SUITE> and D is the components given via B<--components> (defaults to
|
components given via B<--components> (defaults to "main"). If a I<MIRROR>
|
||||||
"main"). If a I<MIRROR> option happens to be an existing file, then its
|
option happens to be an existing file, then its contents are pasted into the
|
||||||
contents are pasted into the chroot's sources.list. This can be used to supply
|
chroot's sources.list. This can be used to supply a deb822 style
|
||||||
a deb822 style sources.list. If I<MIRROR> is C<-> then standard input is pasted
|
sources.list. If I<MIRROR> is C<-> then standard input is pasted into the
|
||||||
into the chroot's sources.list. More than one mirror can be specified and are
|
chroot's sources.list. More than one mirror can be specified and are appended
|
||||||
appended to the chroot's sources.list in the given order. If you specify a
|
to the chroot's sources.list in the given order. If you specify a https or tor
|
||||||
https or tor I<MIRROR> and you want the chroot to be able to update itself,
|
I<MIRROR> and you want the chroot to be able to update itself, don't forget to
|
||||||
don't forget to also install the ca-certificates package, the
|
also install the ca-certificates package, the apt-transport-https package for
|
||||||
apt-transport-https package for apt versions less than 1.5 and/or the
|
apt versions less than 1.5 and/or the apt-transport-tor package using the
|
||||||
apt-transport-tor package using the B<--include> option, as necessary.
|
B<--include> option, as necessary.
|
||||||
|
|
||||||
The optional I<TARGET> argument can either be the path to a directory, the path
|
The optional I<TARGET> argument can either be the path to a directory, the path
|
||||||
to a tarball filename, the path to a squashfs image, the path to an ext2 image,
|
to a tarball filename, the path to a squashfs image, the path to an ext2 image,
|
||||||
|
@ -6693,10 +6573,6 @@ installed. At that point, the chroot directory does not contain any
|
||||||
executables and thus cannot be chroot-ed into. See section B<HOOKS> for more
|
executables and thus cannot be chroot-ed into. See section B<HOOKS> for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
Example: add additional apt sources entries on top of the default ones:
|
|
||||||
|
|
||||||
--setup-hook='echo "deb http..." > "$1"/etc/apt/sources.list.d/custom.list'
|
|
||||||
|
|
||||||
Example: Setup chroot for installing a sub-essential busybox-based chroot
|
Example: Setup chroot for installing a sub-essential busybox-based chroot
|
||||||
with --variant=custom
|
with --variant=custom
|
||||||
--include=dpkg,busybox,libc-bin,base-files,base-passwd,debianutils
|
--include=dpkg,busybox,libc-bin,base-files,base-passwd,debianutils
|
||||||
|
@ -6747,23 +6623,15 @@ Execute arbitrary I<command>s after the chroot is set up and all packages got
|
||||||
installed but before final cleanup actions are carried out. See section
|
installed but before final cleanup actions are carried out. See section
|
||||||
B<HOOKS> for more information.
|
B<HOOKS> for more information.
|
||||||
|
|
||||||
Example: Add a user without a password
|
Example: Preparing a chroot for use with autopkgtest
|
||||||
|
|
||||||
|
--customize-hook='chroot "$1" passwd --delete root'
|
||||||
--customize-hook='chroot "$1" useradd --home-dir /home/user
|
--customize-hook='chroot "$1" useradd --home-dir /home/user
|
||||||
--create-home user'
|
--create-home user'
|
||||||
--customize-hook='chroot "$1" passwd --delete user'
|
--customize-hook='chroot "$1" passwd --delete user'
|
||||||
|
|
||||||
Example: set up F</etc/hostname> and F</etc/hosts>
|
|
||||||
|
|
||||||
--customize-hook='echo host > "$1/etc/hostname"'
|
--customize-hook='echo host > "$1/etc/hostname"'
|
||||||
--customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"'
|
--customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"'
|
||||||
|
--customize-hook=/usr/share/autopkgtest/setup-commands/setup-testbed
|
||||||
Example: to mimic B<debootstrap> behaviour, B<mmdebstrap> copies from the host.
|
|
||||||
Remove them in a B<--customize-hook> to make the chroot reproducible across
|
|
||||||
multiple hosts:
|
|
||||||
|
|
||||||
--customize-hook='rm "$1"/etc/resolv.conf'
|
|
||||||
--customize-hook='rm "$1"/etc/hostname'
|
|
||||||
|
|
||||||
=item B<--hook-directory>=I<directory>
|
=item B<--hook-directory>=I<directory>
|
||||||
|
|
||||||
|
@ -6858,7 +6726,7 @@ This mode directly executes chroot and is the same mode of operation as is
|
||||||
used by debootstrap. It is the only mode that can directly create a directory
|
used by debootstrap. It is the only mode that can directly create a directory
|
||||||
chroot with the right permissions. If the chroot directory is not accessible
|
chroot with the right permissions. If the chroot directory is not accessible
|
||||||
by the _apt user, then apt sandboxing will be automatically disabled. This mode
|
by the _apt user, then apt sandboxing will be automatically disabled. This mode
|
||||||
needs to be able to mount and thus requires C<CAP_SYS_ADMIN>.
|
needs to be able to mount and thus requires C<SYS_CAP_ADMIN>.
|
||||||
|
|
||||||
=item B<unshare>
|
=item B<unshare>
|
||||||
|
|
||||||
|
@ -7099,9 +6967,9 @@ to all four of them. Any information specific to each hook is documented under
|
||||||
the specific hook options in the section B<OPTIONS>.
|
the specific hook options in the section B<OPTIONS>.
|
||||||
|
|
||||||
The options can be specified multiple times and the commands are executed in
|
The options can be specified multiple times and the commands are executed in
|
||||||
the order in which they are given on the command line. There are four different
|
the order in which they are given on the command line. There are four
|
||||||
types of hook option arguments. If the argument passed to the hook option
|
different types of hook option arguments. If the argument passed to the hook
|
||||||
starts with C<copy-in>, C<copy-out>, C<tar-in>, C<tar-out>, C<upload> or
|
option starts with C<copy-in>, C<copy-out>, C<tar-in>, C<tar-out>, C<upload> or
|
||||||
C<download> followed by a space, then the hook is interpreted as a special
|
C<download> followed by a space, then the hook is interpreted as a special
|
||||||
hook. Otherwise, if I<command> is an existing executable file from C<$PATH> or
|
hook. Otherwise, if I<command> is an existing executable file from C<$PATH> or
|
||||||
if I<command> does not contain any shell metacharacters, then I<command> is
|
if I<command> does not contain any shell metacharacters, then I<command> is
|
||||||
|
@ -7114,12 +6982,11 @@ C<APT_CONFIG> as written by mmdebstrap it can be found in the
|
||||||
C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment variables set by
|
C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment variables set by
|
||||||
the user are preserved, except for C<TMPDIR> which is cleared. See section
|
the user are preserved, except for C<TMPDIR> which is cleared. See section
|
||||||
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
||||||
B<--mode>, C<MMDEBSTRAP_FORMAT> stores the format chosen by B<--format>,
|
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
|
||||||
C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup, extract,
|
extract, essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the
|
||||||
essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the binary with
|
binary with which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores
|
||||||
which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores the
|
the numerical verbosity level (0 for no output, 1 for normal, 2 for verbose and
|
||||||
numerical verbosity level (0 for no output, 1 for normal, 2 for verbose and 3
|
3 for debug output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of
|
||||||
for debug output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of
|
|
||||||
packages, apt patterns or file paths given by the B<--include> option,
|
packages, apt patterns or file paths given by the B<--include> option,
|
||||||
separated by a comma and with commas and percent signs in the option values
|
separated by a comma and with commas and percent signs in the option values
|
||||||
urlencoded. If I<SUITE> name was supplied, it's stored in C<MMDEBSTRAP_SUITE>.
|
urlencoded. If I<SUITE> name was supplied, it's stored in C<MMDEBSTRAP_SUITE>.
|
||||||
|
@ -7168,9 +7035,7 @@ only update the content of an existing directory.
|
||||||
=item B<tar-in> I<outside.tar> I<pathinside>
|
=item B<tar-in> I<outside.tar> I<pathinside>
|
||||||
|
|
||||||
Unpacks a tarball I<outside.tar> from outside the chroot into a certain
|
Unpacks a tarball I<outside.tar> from outside the chroot into a certain
|
||||||
location I<pathinside> inside the chroot. In B<unshare> mode, device nodes
|
location I<pathinside> inside the chroot.
|
||||||
cannot be created. To ignore device nodes in tarballs, use
|
|
||||||
B<--skip=tar-in/mknod>.
|
|
||||||
|
|
||||||
=item B<tar-out> I<pathinside> I<outside.tar>
|
=item B<tar-out> I<pathinside> I<outside.tar>
|
||||||
|
|
||||||
|
@ -7383,21 +7248,10 @@ Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=item B<output>
|
|
||||||
|
|
||||||
For formats other than B<directory>, pack up the temporary chroot directory
|
For formats other than B<directory>, pack up the temporary chroot directory
|
||||||
into a tarball, ext2 image or squashfs image and delete the temporary chroot
|
into a tarball, ext2 image or squashfs image and delete the temporary chroot
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
If B<--skip=output/dev> is added, the resulting chroot will not contain the
|
|
||||||
device nodes, directories and symlinks that B<debootstrap> creates but just
|
|
||||||
an empty /dev as created by B<base-files>.
|
|
||||||
|
|
||||||
If B<--skip=output/mknod> is added, the resulting chroot will not contain
|
|
||||||
device nodes (neither block nor character special devices). This is useful
|
|
||||||
if the chroot tarball is to be exatracted in environments where mknod does
|
|
||||||
not function like in unshared user namespaces.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 EXAMPLES
|
=head1 EXAMPLES
|
||||||
|
@ -7525,14 +7379,7 @@ sources on the current system:
|
||||||
--wildcards './usr/src/libdvd-pkg/libdvdcss2_*_*.deb'
|
--wildcards './usr/src/libdvd-pkg/libdvdcss2_*_*.deb'
|
||||||
$ ls libdvdcss2_*_*.deb
|
$ ls libdvdcss2_*_*.deb
|
||||||
|
|
||||||
Use as replacement for autopkgtest-build-qemu and vmdb2 for all architectures
|
Use as replacement for autopkgtest-build-qemu and vmdb2:
|
||||||
supporting EFI booting (amd64, arm64, armhf, i386, riscv64), use a convenience
|
|
||||||
wrapper around B<mmdebstrap>:
|
|
||||||
|
|
||||||
$ mmdebstrap-autopkgtest-build-qemu unstable ./autopkgtest.img
|
|
||||||
|
|
||||||
Use as replacement for autopkgtest-build-qemu and vmdb2 on architectures
|
|
||||||
supporting extlinux (amd64 and i386):
|
|
||||||
|
|
||||||
$ mmdebstrap --variant=important --include=linux-image-amd64 \
|
$ mmdebstrap --variant=important --include=linux-image-amd64 \
|
||||||
--customize-hook='chroot "$1" passwd --delete root' \
|
--customize-hook='chroot "$1" passwd --delete root' \
|
||||||
|
@ -7564,7 +7411,7 @@ As a debootstrap wrapper to run it without superuser privileges but using Linux
|
||||||
user namespaces instead. This fixes Debian bug #829134.
|
user namespaces instead. This fixes Debian bug #829134.
|
||||||
|
|
||||||
$ mmdebstrap --variant=custom --mode=unshare \
|
$ mmdebstrap --variant=custom --mode=unshare \
|
||||||
--setup-hook='debootstrap unstable "$1"' \
|
--setup-hook='env container=lxc debootstrap unstable "$1"' \
|
||||||
- debian-debootstrap.tar
|
- debian-debootstrap.tar
|
||||||
|
|
||||||
Build a non-Debian chroot like Ubuntu bionic:
|
Build a non-Debian chroot like Ubuntu bionic:
|
||||||
|
@ -7609,12 +7456,6 @@ Create a system that can be used with docker:
|
||||||
root
|
root
|
||||||
$ sudo docker rmi debian
|
$ sudo docker rmi debian
|
||||||
|
|
||||||
Create and boot a qemu virtual machine for an arbitrary architecture using
|
|
||||||
the B<debvm-create> wrapper script around B<mmdebstrap>:
|
|
||||||
|
|
||||||
$ debvm-create -r stable -- --architecture=riscv64
|
|
||||||
$ debvm-run
|
|
||||||
|
|
||||||
Create a system that can be used with podman:
|
Create a system that can be used with podman:
|
||||||
|
|
||||||
$ mmdebstrap unstable | podman import - debian
|
$ mmdebstrap unstable | podman import - debian
|
||||||
|
@ -7625,9 +7466,9 @@ Create a system that can be used with podman:
|
||||||
|
|
||||||
As a docker/podman replacement:
|
As a docker/podman replacement:
|
||||||
|
|
||||||
$ mmdebstrap unstable chroot.tar
|
$ mmdebstrap unstable | mmtarfilter --path-exclude='/dev/*' > chroot.tar
|
||||||
[...]
|
[...]
|
||||||
$ mmdebstrap --variant=custom --skip=update,tar-in/mknod \
|
$ mmdebstrap --variant=custom --skip=update \
|
||||||
--setup-hook='tar-in chroot.tar /' \
|
--setup-hook='tar-in chroot.tar /' \
|
||||||
--customize-hook='chroot "$1" whoami' unstable /dev/null
|
--customize-hook='chroot "$1" whoami' unstable /dev/null
|
||||||
[...]
|
[...]
|
||||||
|
@ -7640,8 +7481,8 @@ installed, then instead of downloading and installing the essential packages
|
||||||
twice you can instead build on top of the already present minimal chroot:
|
twice you can instead build on top of the already present minimal chroot:
|
||||||
|
|
||||||
$ mmdebstrap --variant=apt unstable chroot.tar
|
$ mmdebstrap --variant=apt unstable chroot.tar
|
||||||
$ mmdebstrap --variant=custom --skip=update,setup,cleanup,tar-in/mknod \
|
$ mmdebstrap --variant=custom --setup-hook \
|
||||||
--setup-hook='tar-in chroot.tar /' \
|
'mmtarfilter "--path-exclude=/dev/*" < chroot.tar | tar -C "$1" -x' \
|
||||||
--customize-hook='chroot "$1" apt-get install --yes pkg1 pkg2' \
|
--customize-hook='chroot "$1" apt-get install --yes pkg1 pkg2' \
|
||||||
'' chroot-full.tar
|
'' chroot-full.tar
|
||||||
|
|
||||||
|
|
109
mmdebstrap-autopkgtest-build-qemu
Executable file → Normal file
109
mmdebstrap-autopkgtest-build-qemu
Executable file → Normal file
|
@ -2,111 +2,16 @@
|
||||||
# Copyright 2023 Johannes Schauer Marin Rodrigues <josch@debian.org>
|
# Copyright 2023 Johannes Schauer Marin Rodrigues <josch@debian.org>
|
||||||
# Copyright 2023 Helmut Grohne <helmut@subdivi.de>
|
# Copyright 2023 Helmut Grohne <helmut@subdivi.de>
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# This script is mostly compatible with autopkgtest-build-qemu as shipped in
|
||||||
|
# autopkgtest. Main differences:
|
||||||
|
# * It does not support any value for --boot but efi.
|
||||||
|
# * It uses different tools, most importantly swaps out vmdb2.
|
||||||
|
# * It can be run as non-root via user namespaces.
|
||||||
|
|
||||||
# We generally use single quotes to avoid variable expansion:
|
# We generally use single quotes to avoid variable expansion:
|
||||||
# shellcheck disable=SC2016
|
# shellcheck disable=SC2016
|
||||||
|
|
||||||
# Replacement for autopkgtest-build-qemu and vmdb2 for all architectures
|
|
||||||
# supporting EFI booting (amd64, arm64, armhf, i386, riscv64).
|
|
||||||
# For use as replacement for autopkgtest-build-qemu and vmdb2 on ppc64el which
|
|
||||||
# neither supports extlinux nor efi booting there is an unmaintained script
|
|
||||||
# which uses grub instead to boot:
|
|
||||||
#
|
|
||||||
# https://gitlab.mister-muffin.de/josch/mmdebstrap/src/commit/
|
|
||||||
# e523741610a4ed8579642bfc755956f64c847ef3/mmdebstrap-autopkgtest-build-qemu
|
|
||||||
|
|
||||||
: <<'POD2MAN'
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
mmdebstrap-autopkgtest-build-qemu - autopkgtest-build-qemu without vmdb2 but mmdebstrap and EFI boot
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<mmdebstrap-autopkgtest-build-qemu> [I<OPTIONS>] B<--boot>=B<efi> I<RELEASE> I<IMAGE>
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<mmdebstrap-autopkgtest-build-qemu> is a mostly compatible drop-in replacement
|
|
||||||
for B<autopkgtest-build-qemu>(1) with two main differences: Firstly, it uses
|
|
||||||
B<mmdebstrap>(1) instead of B<vmdb2>(1) and thus is able to create QEMU disk
|
|
||||||
images without requiring superuser privileges. Secondly, it uses
|
|
||||||
B<systemd-boot>(7) and thus only supports booting via EFI.
|
|
||||||
|
|
||||||
=head1 POSITIONAL PARAMETERS
|
|
||||||
|
|
||||||
=over 8
|
|
||||||
|
|
||||||
=item I<RELEASE>
|
|
||||||
|
|
||||||
The release to download from the I<MIRROR>. This parameter is required.
|
|
||||||
|
|
||||||
=item I<IMAGE>
|
|
||||||
|
|
||||||
The file to write, in raw format. This parameter is required.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 8
|
|
||||||
|
|
||||||
=item B<--mirror>=I<MIRROR>
|
|
||||||
|
|
||||||
Specify which distribution to install. It defaults to
|
|
||||||
http://deb.debian.org/debian (i.e. Debian), but you can pass a mirror of any
|
|
||||||
Debian derivative.
|
|
||||||
|
|
||||||
=item B<--architecture>=I<ARCHITECTURE>
|
|
||||||
|
|
||||||
Set the architecture for the virtual machine image, specified as a B<dpkg>(1)
|
|
||||||
architecture. If omitted, the host architecture is assumed.
|
|
||||||
|
|
||||||
B<--arch>=I<ARCH> is an alias for this option.
|
|
||||||
|
|
||||||
=item B<--script>=I<SCRIPT>
|
|
||||||
|
|
||||||
Specifies a user script that will be called with the root filesystem of the
|
|
||||||
image as its first parameter. This script can them make any necesssary
|
|
||||||
modifications to the root filesystem.
|
|
||||||
|
|
||||||
The script must be a POSIX shell script, and should not depend on bash-specific
|
|
||||||
features. This script will be executed inside a B<chroot>(1) call in the
|
|
||||||
virtual machine root filesystem.
|
|
||||||
|
|
||||||
=item B<--size>=I<SIZE>
|
|
||||||
|
|
||||||
Specifies the image size for the virtual machine, defaulting to 25G.
|
|
||||||
|
|
||||||
=item B<--apt-proxy>=I<PROXY>
|
|
||||||
|
|
||||||
Specify an apt proxy to use in the virtual machine. By default, if you have
|
|
||||||
an apt proxy configured on the host, the virtual machine will automatically use
|
|
||||||
this, otherwise there is no default.
|
|
||||||
|
|
||||||
=item B<--boot>=B<efi>, B<--efi>
|
|
||||||
|
|
||||||
Select the way the generated image will expect to be booted. Unless you
|
|
||||||
explicitly select --boot=efi, operation will fail.
|
|
||||||
|
|
||||||
=item B<--keyring>=I<KEYRING>
|
|
||||||
|
|
||||||
Passes an additional B<--keyring> parameter to B<mmdebstrap>.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 EXAMPLES
|
|
||||||
|
|
||||||
$ mmdebstrap-autopkgtest-build-qemu --boot=efi stable /path/to/debian-stable-i386.img i386
|
|
||||||
|
|
||||||
$ mmdebstrap-autopkgtest-build-qemu --boot=efi unstable /path/to/debian-unstable.img
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
B<autopkgtest-build-qemu>(1), B<autopkgtest-virt-qemu>(1), B<mmdebstrap>(1), B<autopkgtest>(1)
|
|
||||||
|
|
||||||
=cut
|
|
||||||
POD2MAN
|
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
die() {
|
die() {
|
||||||
|
@ -114,7 +19,7 @@ die() {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
usage() {
|
usage() {
|
||||||
die "usage: $0 [--architecture=|--apt-proxy=|--keyring=|--mirror=|--script=|--size=] --boot=efi <RELEASE> <IMAGE>"
|
die "usage: $0 [--boot=|--architecture=|--apt-proxy=|--keyring=|--mirror=|--script=|--size=] <RELEASE> <IMAGE> [MIRROR] [ARCHITECTURE] [SCRIPT] [SIZE]"
|
||||||
}
|
}
|
||||||
usage_error() {
|
usage_error() {
|
||||||
echo "error: $*" 1>&2
|
echo "error: $*" 1>&2
|
||||||
|
|
66
tarfilter
66
tarfilter
|
@ -43,29 +43,6 @@ class PaxFilterAction(argparse.Action):
|
||||||
setattr(namespace, "paxfilter", items)
|
setattr(namespace, "paxfilter", items)
|
||||||
|
|
||||||
|
|
||||||
class TypeFilterAction(argparse.Action):
|
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
|
||||||
items = getattr(namespace, "typefilter", [])
|
|
||||||
match values:
|
|
||||||
case "REGTYPE" | "0":
|
|
||||||
items.append(tarfile.REGTYPE)
|
|
||||||
case "LNKTYPE" | "1":
|
|
||||||
items.append(tarfile.LNKTYPE)
|
|
||||||
case "SYMTYPE" | "2":
|
|
||||||
items.append(tarfile.SYMTYPE)
|
|
||||||
case "CHRTYPE" | "3":
|
|
||||||
items.append(tarfile.CHRTYPE)
|
|
||||||
case "BLKTYPE" | "4":
|
|
||||||
items.append(tarfile.BLKTYPE)
|
|
||||||
case "DIRTYPE" | "5":
|
|
||||||
items.append(tarfile.DIRTYPE)
|
|
||||||
case "FIFOTYPE" | "6":
|
|
||||||
items.append(tarfile.FIFOTYPE)
|
|
||||||
case _:
|
|
||||||
raise ValueError("invalid type: %s" % values)
|
|
||||||
setattr(namespace, "typefilter", items)
|
|
||||||
|
|
||||||
|
|
||||||
class TransformAction(argparse.Action):
|
class TransformAction(argparse.Action):
|
||||||
def __call__(self, parser, namespace, values, option_string=None):
|
def __call__(self, parser, namespace, values, option_string=None):
|
||||||
items = getattr(namespace, "trans", [])
|
items = getattr(namespace, "trans", [])
|
||||||
|
@ -112,11 +89,10 @@ dpkg(1) for information on how these two options work in detail. To reuse the
|
||||||
exact same semantics as used by dpkg, paths must be given as /path and not as
|
exact same semantics as used by dpkg, paths must be given as /path and not as
|
||||||
./path even though they might be stored as such in the tarball.
|
./path even though they might be stored as such in the tarball.
|
||||||
|
|
||||||
Secondly, filter out unwanted pax extended headers using --pax-exclude and
|
Secondly, filter out unwanted pax extended headers. This is useful in cases
|
||||||
--pax-include. This is useful in cases where a tool only accepts certain xattr
|
where a tool only accepts certain xattr prefixes. For example tar2sqfs only
|
||||||
prefixes. For example tar2sqfs only supports SCHILY.xattr.user.*,
|
supports SCHILY.xattr.user.*, SCHILY.xattr.trusted.* and
|
||||||
SCHILY.xattr.trusted.* and SCHILY.xattr.security.* but not
|
SCHILY.xattr.security.* but not SCHILY.xattr.system.posix_acl_default.*.
|
||||||
SCHILY.xattr.system.posix_acl_default.*.
|
|
||||||
|
|
||||||
Both types of options use Unix shell-style wildcards:
|
Both types of options use Unix shell-style wildcards:
|
||||||
|
|
||||||
|
@ -125,16 +101,10 @@ Both types of options use Unix shell-style wildcards:
|
||||||
[seq] matches any character in seq
|
[seq] matches any character in seq
|
||||||
[!seq] matches any character not in seq
|
[!seq] matches any character not in seq
|
||||||
|
|
||||||
Thirdly, filter out files matching a specific tar archive member type using
|
Thirdly, transform the path of tar members using a sed expression just as with
|
||||||
--type-exclude. Valid type names are REGTYPE (regular file), LNKTYPE
|
|
||||||
(hardlink), SYMTYPE (symlink), CHRTYPE (character special), BLKTYPE (block
|
|
||||||
special), DIRTYPE (directory), FIFOTYPE (fifo) or their tar format flag value
|
|
||||||
(0-6, respectively).
|
|
||||||
|
|
||||||
Fourthly, transform the path of tar members using a sed expression just as with
|
|
||||||
GNU tar --transform.
|
GNU tar --transform.
|
||||||
|
|
||||||
Fifthly, strip leading directory components off of tar members. Just as with
|
Fourthly, strip leading directory components off of tar members. Just as with
|
||||||
GNU tar --strip-components, tar members that have less or equal components in
|
GNU tar --strip-components, tar members that have less or equal components in
|
||||||
their path are not passed through.
|
their path are not passed through.
|
||||||
|
|
||||||
|
@ -170,15 +140,6 @@ Lastly, shift user id and group id of each entry by the value given by the
|
||||||
help="Re-include a pax header after a previous exclusion. "
|
help="Re-include a pax header after a previous exclusion. "
|
||||||
"This option can be specified multiple times.",
|
"This option can be specified multiple times.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--type-exclude",
|
|
||||||
metavar="type",
|
|
||||||
action=TypeFilterAction,
|
|
||||||
help="Exclude certain member types by their type. Choose types either "
|
|
||||||
"by their name (REGTYPE, LNKTYPE, SYMTYPE, CHRTYPE, BLKTYPE, DIRTYPE, "
|
|
||||||
"FIFOTYPE) or by their tar format flag values (0-6, respectively). "
|
|
||||||
"This option can be specified multiple times.",
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--transform",
|
"--transform",
|
||||||
"--xform",
|
"--xform",
|
||||||
|
@ -203,7 +164,6 @@ Lastly, shift user id and group id of each entry by the value given by the
|
||||||
if (
|
if (
|
||||||
not hasattr(args, "pathfilter")
|
not hasattr(args, "pathfilter")
|
||||||
and not hasattr(args, "paxfilter")
|
and not hasattr(args, "paxfilter")
|
||||||
and not hasattr(args, "typefilter")
|
|
||||||
and not hasattr(args, "strip_components")
|
and not hasattr(args, "strip_components")
|
||||||
):
|
):
|
||||||
from shutil import copyfileobj
|
from shutil import copyfileobj
|
||||||
|
@ -247,24 +207,14 @@ Lastly, shift user id and group id of each entry by the value given by the
|
||||||
skip = True
|
skip = True
|
||||||
return skip
|
return skip
|
||||||
|
|
||||||
def type_filter_should_skip(member):
|
# starting with Python 3.8, the default format became PAX_FORMAT, so this
|
||||||
if not hasattr(args, "typefilter"):
|
# is only for compatibility with older versions of Python 3
|
||||||
return False
|
|
||||||
for t in args.typefilter:
|
|
||||||
if member.type == t:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
# starting with Python 3.8, the default format became PAX_FORMAT but we
|
|
||||||
# are still explicit here in case of future changes.
|
|
||||||
with tarfile.open(fileobj=sys.stdin.buffer, mode="r|*") as in_tar, tarfile.open(
|
with tarfile.open(fileobj=sys.stdin.buffer, mode="r|*") as in_tar, tarfile.open(
|
||||||
fileobj=sys.stdout.buffer, mode="w|", format=tarfile.PAX_FORMAT
|
fileobj=sys.stdout.buffer, mode="w|", format=tarfile.PAX_FORMAT
|
||||||
) as out_tar:
|
) as out_tar:
|
||||||
for member in in_tar:
|
for member in in_tar:
|
||||||
if path_filter_should_skip(member):
|
if path_filter_should_skip(member):
|
||||||
continue
|
continue
|
||||||
if type_filter_should_skip(member):
|
|
||||||
continue
|
|
||||||
if args.strip_components:
|
if args.strip_components:
|
||||||
comps = member.name.split("/")
|
comps = member.name.split("/")
|
||||||
# just as with GNU tar, archive members with less or equal
|
# just as with GNU tar, archive members with less or equal
|
||||||
|
|
|
@ -35,8 +35,15 @@ if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ];
|
||||||
chmod 644 "$TMP_APT_CONFIG"
|
chmod 644 "$TMP_APT_CONFIG"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# debootstrap runs mount -t proc proc /proc which doesn't work in an unshared
|
||||||
|
# namespace on privileged docker (like salsaci), so mount /proc manually
|
||||||
|
# https://bugs.debian.org/1031222
|
||||||
|
# https://salsa.debian.org/installer-team/debootstrap/-/merge_requests/91
|
||||||
$prefix {{ CMD }} --variant=custom --mode={{ MODE }} \
|
$prefix {{ CMD }} --variant=custom --mode={{ MODE }} \
|
||||||
--setup-hook='env '"${AUTOPROXY:+APT_CONFIG='$TMP_APT_CONFIG'}"' debootstrap --variant={{ VARIANT }} unstable "$1" {{ MIRROR }}' \
|
--setup-hook='env '"${AUTOPROXY:+APT_CONFIG='$TMP_APT_CONFIG'}"' container=lxc debootstrap --variant={{ VARIANT }} unstable "$1" {{ MIRROR }}' \
|
||||||
|
--setup-hook='mount -o rbind /proc "$1/proc"' \
|
||||||
|
--setup-hook='chroot "$1" dpkg-reconfigure systemd || true' \
|
||||||
|
--setup-hook='umount --lazy "$1/proc"' \
|
||||||
- /tmp/debian-mm.tar {{ MIRROR }}
|
- /tmp/debian-mm.tar {{ MIRROR }}
|
||||||
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
|
if [ -n "$AUTOPROXY" ] && [ -x "$AUTOPROXY" ] && [ -e /tmp/.auto-apt-proxy-0 ]; then
|
||||||
rm "$TMP_APT_CONFIG"
|
rm "$TMP_APT_CONFIG"
|
||||||
|
|
|
@ -174,13 +174,6 @@ if [ "{{ VARIANT }}" = "-" ]; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# since debootstrap 1.0.133 there is no tzdata in the buildd variant and thus
|
|
||||||
# debootstrap creates its own /etc/localtime
|
|
||||||
if [ "{{ VARIANT }}" = "buildd" ]; then
|
|
||||||
[ "$(readlink /tmp/debian-{{ DIST }}-debootstrap/etc/localtime)" = /usr/share/zoneinfo/UTC ]
|
|
||||||
rm /tmp/debian-{{ DIST }}-debootstrap/etc/localtime
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check if the file content differs
|
# check if the file content differs
|
||||||
diff --unified --no-dereference --recursive /tmp/debian-{{ DIST }}-debootstrap /tmp/debian-{{ DIST }}-mm >&2
|
diff --unified --no-dereference --recursive /tmp/debian-{{ DIST }}-debootstrap /tmp/debian-{{ DIST }}-mm >&2
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
|
|
||||||
prefix=
|
|
||||||
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
|
|
||||||
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
|
||||||
if [ ! -e /mmdebstrap-testenv ]; then
|
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
|
||||||
fi
|
|
||||||
prefix="runuser -u ${SUDO_USER:-user} --"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test this for both unshare and root mode because the code paths creating
|
|
||||||
# entries in /dev are different depending on whether mknod is available or not
|
|
||||||
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --skip=output/dev {{ DIST }} - {{ MIRROR }} | {
|
|
||||||
tar -t;
|
|
||||||
echo ./dev/console;
|
|
||||||
echo ./dev/fd;
|
|
||||||
echo ./dev/full;
|
|
||||||
echo ./dev/null;
|
|
||||||
echo ./dev/ptmx;
|
|
||||||
echo ./dev/pts/;
|
|
||||||
echo ./dev/random;
|
|
||||||
echo ./dev/shm/;
|
|
||||||
echo ./dev/stderr;
|
|
||||||
echo ./dev/stdin;
|
|
||||||
echo ./dev/stdout;
|
|
||||||
echo ./dev/tty;
|
|
||||||
echo ./dev/urandom;
|
|
||||||
echo ./dev/zero;
|
|
||||||
} | sort | diff -u tar1.txt -
|
|
|
@ -1,30 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
|
|
||||||
prefix=
|
|
||||||
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
|
|
||||||
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
|
||||||
if [ ! -e /mmdebstrap-testenv ]; then
|
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
|
||||||
fi
|
|
||||||
prefix="runuser -u ${SUDO_USER:-user} --"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test this for both unshare and root mode because the code paths creating
|
|
||||||
# entries in /dev are different depending on whether mknod is available or not
|
|
||||||
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --skip=output/mknod \
|
|
||||||
{{ DIST }} - {{ MIRROR }} | {
|
|
||||||
tar -t;
|
|
||||||
echo ./dev/console;
|
|
||||||
echo ./dev/full;
|
|
||||||
echo ./dev/null;
|
|
||||||
echo ./dev/ptmx;
|
|
||||||
echo ./dev/random;
|
|
||||||
echo ./dev/tty;
|
|
||||||
echo ./dev/urandom;
|
|
||||||
echo ./dev/zero;
|
|
||||||
} | sort | diff -u tar1.txt -
|
|
|
@ -1,28 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -eu
|
|
||||||
export LC_ALL=C.UTF-8
|
|
||||||
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
|
||||||
|
|
||||||
[ {{ MODE }} = "unshare" ]
|
|
||||||
|
|
||||||
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
|
||||||
|
|
||||||
prefix=
|
|
||||||
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
|
|
||||||
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
|
||||||
if [ ! -e /mmdebstrap-testenv ]; then
|
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
|
||||||
fi
|
|
||||||
prefix="runuser -u ${SUDO_USER:-user} --"
|
|
||||||
fi
|
|
||||||
|
|
||||||
$prefix {{ CMD }} --mode={{ MODE }} --variant=custom \
|
|
||||||
--skip=update,setup,cleanup,tar-in/mknod \
|
|
||||||
--setup-hook='tar-in ./cache/mmdebstrap-{{ DIST }}-apt.tar /' \
|
|
||||||
'' /tmp/debian-chroot.tar
|
|
||||||
|
|
||||||
cmp ./cache/mmdebstrap-{{ DIST }}-apt.tar /tmp/debian-chroot.tar \
|
|
||||||
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-apt.tar /tmp/debian-chroot.tar
|
|
|
@ -8,7 +8,7 @@ mkdir /tmp/root/real
|
||||||
run_testA() {
|
run_testA() {
|
||||||
echo content > /tmp/foo
|
echo content > /tmp/foo
|
||||||
# shellcheck disable=SC2094
|
# shellcheck disable=SC2094
|
||||||
{ { { {{ CMD }} --hook-helper /tmp/root root setup '' 1 upload /tmp/foo "$1" < /tmp/myfifo 3>&-; echo $? >&3; printf "\\000\\000adios";
|
{ { { {{ CMD }} --hook-helper /tmp/root root setup env 1 upload /tmp/foo "$1" < /tmp/myfifo 3>&-; echo $? >&3; printf "\\000\\000adios";
|
||||||
} | {{ CMD }} --hook-listener 1 3>&- >/tmp/myfifo; echo $?; } 3>&1;
|
} | {{ CMD }} --hook-listener 1 3>&- >/tmp/myfifo; echo $?; } 3>&1;
|
||||||
} | { read -r xs1; [ "$xs1" -eq 0 ]; read -r xs2; [ "$xs2" -eq 0 ]; }
|
} | { read -r xs1; [ "$xs1" -eq 0 ]; read -r xs2; [ "$xs2" -eq 0 ]; }
|
||||||
echo content | diff -u - /tmp/root/real/foo
|
echo content | diff -u - /tmp/root/real/foo
|
||||||
|
|
|
@ -8,12 +8,12 @@ echo "MMDEBSTRAP_APT_CONFIG $MMDEBSTRAP_APT_CONFIG"
|
||||||
echo "$MMDEBSTRAP_HOOK" >> /tmp/hooks
|
echo "$MMDEBSTRAP_HOOK" >> /tmp/hooks
|
||||||
[ "$MMDEBSTRAP_MODE" = "root" ]
|
[ "$MMDEBSTRAP_MODE" = "root" ]
|
||||||
echo test-content $MMDEBSTRAP_HOOK > test
|
echo test-content $MMDEBSTRAP_HOOK > test
|
||||||
{{ CMD }} --hook-helper "$1" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" '' 1 upload test /test <&$MMDEBSTRAP_HOOKSOCK >&$MMDEBSTRAP_HOOKSOCK
|
{{ CMD }} --hook-helper "$1" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" env 1 upload test /test <&$MMDEBSTRAP_HOOKSOCK >&$MMDEBSTRAP_HOOKSOCK
|
||||||
rm test
|
rm test
|
||||||
echo "content inside chroot:"
|
echo "content inside chroot:"
|
||||||
cat "$1/test"
|
cat "$1/test"
|
||||||
[ "test-content $MMDEBSTRAP_HOOK" = "$(cat "$1/test")" ]
|
[ "test-content $MMDEBSTRAP_HOOK" = "$(cat "$1/test")" ]
|
||||||
{{ CMD }} --hook-helper "$1" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" '' 1 download /test test <&$MMDEBSTRAP_HOOKSOCK >&$MMDEBSTRAP_HOOKSOCK
|
{{ CMD }} --hook-helper "$1" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" env 1 download /test test <&$MMDEBSTRAP_HOOKSOCK >&$MMDEBSTRAP_HOOKSOCK
|
||||||
echo "content outside chroot:"
|
echo "content outside chroot:"
|
||||||
cat test
|
cat test
|
||||||
[ "test-content $MMDEBSTRAP_HOOK" = "$(cat test)" ]
|
[ "test-content $MMDEBSTRAP_HOOK" = "$(cat test)" ]
|
||||||
|
|
Loading…
Reference in a new issue