add support for generating squashfs images using tar2sqfs
This commit is contained in:
parent
51fab612ed
commit
dbdf3f34c6
3 changed files with 96 additions and 35 deletions
25
coverage.sh
25
coverage.sh
|
@ -49,7 +49,7 @@ if [ ! -e shared/mmdebstrap ] || [ mmdebstrap -nt shared/mmdebstrap ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
starttime=
|
starttime=
|
||||||
total=122
|
total=123
|
||||||
skipped=0
|
skipped=0
|
||||||
runtests=0
|
runtests=0
|
||||||
i=1
|
i=1
|
||||||
|
@ -547,6 +547,29 @@ else
|
||||||
runtests=$((runtests+1))
|
runtests=$((runtests+1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
print_header "mode=$defaultmode,variant=apt: test squashfs image"
|
||||||
|
cat << END > shared/test.sh
|
||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
export LC_ALL=C.UTF-8
|
||||||
|
$CMD --mode=$defaultmode --variant=apt $DEFAULT_DIST /tmp/debian-chroot.squashfs $mirror
|
||||||
|
printf 'hsqs' | cmp --bytes=4 /tmp/debian-chroot.squashfs -
|
||||||
|
# workaround for https://github.com/AgentD/squashfs-tools-ng/issues/37
|
||||||
|
sed 's#\\([^.]\\)/\$#\\1#' tar1.txt | sort > /tmp/tar1noslash.txt
|
||||||
|
sqfs2tar --no-skip --root-becomes . /tmp/debian-chroot.squashfs | tar -t | sort | diff -u /tmp/tar1noslash.txt -
|
||||||
|
rm /tmp/debian-chroot.squashfs /tmp/tar1noslash.txt
|
||||||
|
END
|
||||||
|
if [ "$HAVE_QEMU" = "yes" ]; then
|
||||||
|
./run_qemu.sh
|
||||||
|
runtests=$((runtests+1))
|
||||||
|
elif [ "$defaultmode" = "root" ]; then
|
||||||
|
./run_null.sh SUDO
|
||||||
|
runtests=$((runtests+1))
|
||||||
|
else
|
||||||
|
./run_null.sh
|
||||||
|
runtests=$((runtests+1))
|
||||||
|
fi
|
||||||
|
|
||||||
print_header "mode=auto,variant=apt: test auto-mode without unshare capabilities"
|
print_header "mode=auto,variant=apt: test auto-mode without unshare capabilities"
|
||||||
cat << END > shared/test.sh
|
cat << END > shared/test.sh
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
|
@ -407,7 +407,7 @@ if [ "$HAVE_QEMU" = "yes" ]; then
|
||||||
tmpdir="$(mktemp -d)"
|
tmpdir="$(mktemp -d)"
|
||||||
trap "cleanuptmpdir; cleanup_newcachedir" EXIT INT TERM
|
trap "cleanuptmpdir; cleanup_newcachedir" EXIT INT TERM
|
||||||
|
|
||||||
pkgs=perl-doc,linux-image-amd64,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,proot,qemu-user-static,binfmt-support,qemu-user,dpkg-dev,mini-httpd,libdevel-cover-perl,debootstrap,procps,apt-cudf,aspcud
|
pkgs=perl-doc,linux-image-amd64,systemd-sysv,perl,arch-test,fakechroot,fakeroot,mount,uidmap,proot,qemu-user-static,binfmt-support,qemu-user,dpkg-dev,mini-httpd,libdevel-cover-perl,debootstrap,procps,apt-cudf,aspcud,squashfs-tools-ng
|
||||||
if [ "$HOSTARCH" = amd64 ] && [ "$RUN_MA_SAME_TESTS" = "yes" ]; then
|
if [ "$HOSTARCH" = amd64 ] && [ "$RUN_MA_SAME_TESTS" = "yes" ]; then
|
||||||
arches=amd64,armhf
|
arches=amd64,armhf
|
||||||
pkgs="$pkgs,libfakechroot:armhf,libfakeroot:armhf"
|
pkgs="$pkgs,libfakechroot:armhf,libfakeroot:armhf"
|
||||||
|
|
102
mmdebstrap
102
mmdebstrap
|
@ -2707,16 +2707,9 @@ sub main() {
|
||||||
|
|
||||||
# figure out whether a tarball has to be created in the end
|
# figure out whether a tarball has to be created in the end
|
||||||
$options->{maketar} = 0;
|
$options->{maketar} = 0;
|
||||||
|
$options->{makesqfs} = 0;
|
||||||
if (defined $tar_compressor or $options->{target} =~ /\.tar$/ or $options->{target} eq '-') {
|
if (defined $tar_compressor or $options->{target} =~ /\.tar$/ or $options->{target} eq '-') {
|
||||||
$options->{maketar} = 1;
|
$options->{maketar} = 1;
|
||||||
if (any { $_ eq $options->{variant} } ('extract', 'custom') and any { $_ eq $options->{mode} } ('fakechroot', 'proot')) {
|
|
||||||
info "creating a tarball in fakechroot mode or proot mode might fail in extract and custom variants because there might be no tar inside the chroot";
|
|
||||||
}
|
|
||||||
# try to fail early if target tarball cannot be opened for writing
|
|
||||||
if ($options->{target} ne '-') {
|
|
||||||
open my $fh, '>', $options->{target} or error "cannot open $options->{target} for writing: $!";
|
|
||||||
close $fh;
|
|
||||||
}
|
|
||||||
# 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: $!";
|
||||||
|
@ -2730,9 +2723,31 @@ sub main() {
|
||||||
error ("failed to start " . (join " ", @{$tar_compressor}));
|
error ("failed to start " . (join " ", @{$tar_compressor}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elsif ($options->{target} =~ /\.(squashfs|sqfs)$/) {
|
||||||
|
$options->{makesqfs} = 1;
|
||||||
|
# check if tar2sqfs is installed
|
||||||
|
my $pid = fork() // error "fork() failed: $!";
|
||||||
|
if ($pid == 0) {
|
||||||
|
open(STDOUT, '>', '/dev/null') or error "cannot open /dev/null for writing: $!";
|
||||||
|
open(STDIN, '<', '/dev/null') or error "cannot open /dev/null for reading: $!";
|
||||||
|
exec ('tar2sqfs', '--version') or error ("cannot exec tar2sqfs --version: $!");
|
||||||
|
}
|
||||||
|
waitpid $pid, 0;
|
||||||
|
if ($? != 0) {
|
||||||
|
error ("failed to start tar2sqfs --version");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($options->{maketar}) {
|
if ($options->{maketar} or $options->{makesqfs}) {
|
||||||
|
if (any { $_ eq $options->{variant} } ('extract', 'custom') and any { $_ eq $options->{mode} } ('fakechroot', 'proot')) {
|
||||||
|
info "creating a tarball or squashfs image in fakechroot mode or proot mode might fail in extract and custom variants because there might be no tar inside the chroot";
|
||||||
|
}
|
||||||
|
# try to fail early if target tarball or squashfs image cannot be
|
||||||
|
# opened for writing
|
||||||
|
if ($options->{target} ne '-') {
|
||||||
|
open my $fh, '>', $options->{target} or error "cannot open $options->{target} for writing: $!";
|
||||||
|
close $fh;
|
||||||
|
}
|
||||||
# since the output is a tarball, we create the rootfs in a temporary
|
# since the output is a tarball, we create the rootfs in a temporary
|
||||||
# directory
|
# directory
|
||||||
$options->{root} = tempdir(
|
$options->{root} = tempdir(
|
||||||
|
@ -2837,7 +2852,7 @@ sub main() {
|
||||||
|
|
||||||
my $devtar = '';
|
my $devtar = '';
|
||||||
# We always craft the /dev entries ourselves if a tarball is to be created
|
# We always craft the /dev entries ourselves if a tarball is to be created
|
||||||
if ($options->{maketar}) {
|
if ($options->{maketar} or $options->{makesqfs}) {
|
||||||
foreach my $file (@devfiles) {
|
foreach my $file (@devfiles) {
|
||||||
my ($fname, $mode, $type, $linkname, $devmajor, $devminor) = @{$file};
|
my ($fname, $mode, $type, $linkname, $devmajor, $devminor) = @{$file};
|
||||||
my $entry = pack('a100 a8 a8 a8 a12 a12 A8 a1 a100 a8 a32 a32 a8 a8 a155 x12',
|
my $entry = pack('a100 a8 a8 a8 a12 a12 A8 a1 a100 a8 a32 a32 a8 a8 a155 x12',
|
||||||
|
@ -2901,7 +2916,7 @@ sub main() {
|
||||||
|
|
||||||
close $childsock;
|
close $childsock;
|
||||||
|
|
||||||
if ($options->{maketar}) {
|
if ($options->{maketar} or $options->{makesqfs}) {
|
||||||
info "creating tarball...";
|
info "creating tarball...";
|
||||||
|
|
||||||
# redirect tar output to the writing end of the pipe so that the
|
# redirect tar output to the writing end of the pipe so that the
|
||||||
|
@ -2943,7 +2958,7 @@ sub main() {
|
||||||
|
|
||||||
close $childsock;
|
close $childsock;
|
||||||
|
|
||||||
if ($options->{maketar}) {
|
if ($options->{maketar} or $options->{makesqfs}) {
|
||||||
info "creating tarball...";
|
info "creating tarball...";
|
||||||
|
|
||||||
# redirect tar output to the writing end of the pipe so that the
|
# redirect tar output to the writing end of the pipe so that the
|
||||||
|
@ -3306,7 +3321,7 @@ sub main() {
|
||||||
|
|
||||||
close $parentsock;
|
close $parentsock;
|
||||||
|
|
||||||
if ($options->{maketar}) {
|
if ($options->{maketar} or $options->{makesqfs}) {
|
||||||
# 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 {
|
||||||
|
@ -3315,7 +3330,17 @@ sub main() {
|
||||||
error "cannot copy to standard output: $!";
|
error "cannot copy to standard output: $!";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (defined $tar_compressor) {
|
if ($options->{makesqfs} or defined $tar_compressor) {
|
||||||
|
my @argv = ();
|
||||||
|
if ($options->{makesqfs}) {
|
||||||
|
push @argv, 'tar2sqfs',
|
||||||
|
'--quiet', '--no-skip', '--force', '--exportable',
|
||||||
|
'--compressor', 'xz',
|
||||||
|
'--block-size', '1048576',
|
||||||
|
$options->{target};
|
||||||
|
} else {
|
||||||
|
push @argv, @{$tar_compressor};
|
||||||
|
}
|
||||||
POSIX::sigprocmask(SIG_BLOCK, $sigset) or error "Can't block signals: $!";
|
POSIX::sigprocmask(SIG_BLOCK, $sigset) or error "Can't block signals: $!";
|
||||||
my $cpid = fork() // error "fork() failed: $!";
|
my $cpid = fork() // error "fork() failed: $!";
|
||||||
if ($cpid == 0) {
|
if ($cpid == 0) {
|
||||||
|
@ -3327,14 +3352,19 @@ sub main() {
|
||||||
|
|
||||||
# unblock all delayed signals (and possibly handle them)
|
# unblock all delayed signals (and possibly handle them)
|
||||||
POSIX::sigprocmask(SIG_UNBLOCK, $sigset) or error "Can't unblock signals: $!";
|
POSIX::sigprocmask(SIG_UNBLOCK, $sigset) or error "Can't unblock signals: $!";
|
||||||
|
|
||||||
|
if ($options->{makesqfs}) {
|
||||||
|
open(STDOUT, '>', '/dev/null') or error "cannot open /dev/null for writing: $!";
|
||||||
|
} else {
|
||||||
open(STDOUT, '>', $options->{target}) or error "cannot open $options->{target} for writing: $!";
|
open(STDOUT, '>', $options->{target}) or error "cannot open $options->{target} for writing: $!";
|
||||||
|
}
|
||||||
open(STDIN, '<&', $rfh) or error "cannot open file handle for reading: $!";
|
open(STDIN, '<&', $rfh) or error "cannot open file handle for reading: $!";
|
||||||
exec { $tar_compressor->[0] } @{$tar_compressor} or error ("cannot exec " . (join " ", @{$tar_compressor}) . ": $!");
|
exec { $argv[0] } @argv or error ("cannot exec " . (join " ", @argv) . ": $!");
|
||||||
}
|
}
|
||||||
POSIX::sigprocmask(SIG_UNBLOCK, $sigset) or error "Can't unblock signals: $!";
|
POSIX::sigprocmask(SIG_UNBLOCK, $sigset) or error "Can't unblock signals: $!";
|
||||||
waitpid $cpid, 0;
|
waitpid $cpid, 0;
|
||||||
if ($? != 0) {
|
if ($? != 0) {
|
||||||
error ("failed to start " . (join " ", @{$tar_compressor}));
|
error ("failed to start " . (join " ", @argv));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!copy($rfh, $options->{target})) {
|
if(!copy($rfh, $options->{target})) {
|
||||||
|
@ -3359,7 +3389,7 @@ sub main() {
|
||||||
# change signal handler message
|
# change signal handler message
|
||||||
$waiting_for = "cleanup";
|
$waiting_for = "cleanup";
|
||||||
|
|
||||||
if ($options->{maketar} and -e $options->{root}) {
|
if (($options->{maketar} or $options->{makesqfs}) and -e $options->{root}) {
|
||||||
info "removing tempdir $options->{root}...";
|
info "removing tempdir $options->{root}...";
|
||||||
if ($options->{mode} eq 'unshare') {
|
if ($options->{mode} eq 'unshare') {
|
||||||
# We don't have permissions to remove the directory outside
|
# We don't have permissions to remove the directory outside
|
||||||
|
@ -3447,25 +3477,29 @@ installed inside the chroot. If any mirror contains a tor+xxx URI, then the
|
||||||
apt-transport-tor package will be installed inside the chroot.
|
apt-transport-tor package will be installed inside the chroot.
|
||||||
|
|
||||||
The optional I<TARGET> argument can either be the path to a directory, the
|
The optional I<TARGET> argument can either be the path to a directory, the
|
||||||
path to a tarball filename or C<->. If I<TARGET> ends with C<.tar>, or with
|
path to a tarball filename, the path to a squashfs image or C<->. If I<TARGET>
|
||||||
any of the filename extensions listed in the section B<COMPRESSION>, then
|
ends with C<.tar>, or with any of the filename extensions listed in the
|
||||||
I<TARGET> will be interpreted as a path to a tarball filename. If I<TARGET> is
|
section B<COMPRESSION>, then I<TARGET> will be interpreted as a path to a
|
||||||
the path to a tarball filename or if I<TARGET> is C<-> or if no I<TARGET> was
|
tarball filename. If I<TARGET> ends with C<.squashfs> or C<.sqfs>, then
|
||||||
specified, B<mmdebstrap> will create a temporary chroot directory in
|
I<TARGET> will be interpreted as a path to a squashfs image. If I<TARGET> is
|
||||||
C<$TMPDIR> or F</tmp>. If I<TARGET> is the path to a tarball filename,
|
the path to a tarball filename or a squashfs image or if I<TARGET> is C<-> or
|
||||||
B<mmdebstrap> will create a tarball of that directory and store it as
|
if no I<TARGET> was specified, B<mmdebstrap> will create a temporary chroot
|
||||||
I<TARGET>, optionally applying a compression algorithm as indicated by its
|
directory in C<$TMPDIR> or F</tmp>. If I<TARGET> is the path to a tarball
|
||||||
|
filename, B<mmdebstrap> will create a tarball of that directory and store it
|
||||||
|
as I<TARGET>, optionally applying a compression algorithm as indicated by its
|
||||||
filename extension. If I<TARGET> is C<-> or if no I<TARGET> was specified,
|
filename extension. If I<TARGET> is C<-> or if no I<TARGET> was specified,
|
||||||
then an uncompressed tarball of that directory will be sent to standard
|
then an uncompressed tarball of that directory will be sent to standard
|
||||||
output. When B<mmdebstrap> creates a tarball it also stores extended
|
output. When B<mmdebstrap> creates a tarball it also stores extended
|
||||||
attributes. To preserve the extended attributes, you have to pass B<--xattrs
|
attributes. To preserve the extended attributes, you have to pass B<--xattrs
|
||||||
--xattrs-include='*'> to tar when extracting the tarball. If I<TARGET> does
|
--xattrs-include='*'> to tar when extracting the tarball. If I<TARGET> is the
|
||||||
not end in C<.tar> or with any of the filename extensions listed in the
|
path to a squashfs image, B<mmdebstrap> will create an xz compressed image
|
||||||
section B<COMPRESSION>, then I<TARGET> will be interpreted as the path to a
|
with a blocksize of 1048576 bytes. If I<TARGET> does neither end with C<.tar>
|
||||||
directory. If the directory already exists, it must either be empty or only
|
nor with any of the filename extensions listed in the section B<COMPRESSION>,
|
||||||
contain an empty C<lost+found> directory. If a directory is chosen as output
|
nor with C<.squashfs> or C<.sqfs>, then I<TARGET> will be interpreted as the
|
||||||
in any other mode than B<sudo>, then its contents will have wrong ownership
|
path to a directory. If the directory already exists, it must either be empty
|
||||||
information and special device files will be missing.
|
or only contain an empty C<lost+found> directory. If a directory is chosen as
|
||||||
|
output in any other mode than B<sudo>, then its contents will have wrong
|
||||||
|
ownership information and special device files will be missing.
|
||||||
|
|
||||||
The I<SUITE> may be a valid release code name (eg, sid, stretch, jessie) or a
|
The I<SUITE> may be a valid release code name (eg, sid, stretch, jessie) or a
|
||||||
symbolic name (eg, unstable, testing, stable, oldstable). Any suite name that
|
symbolic name (eg, unstable, testing, stable, oldstable). Any suite name that
|
||||||
|
@ -3938,6 +3972,10 @@ create device nodes:
|
||||||
|
|
||||||
$ mmdebstrap unstable | tar --delete ./dev > unstable-chroot.tar
|
$ mmdebstrap unstable | tar --delete ./dev > unstable-chroot.tar
|
||||||
|
|
||||||
|
Instead of a tarball, a squashfs image can be created:
|
||||||
|
|
||||||
|
$ mmdebstrap unstable unstable-chroot.squashfs
|
||||||
|
|
||||||
By default, debootstrapping a stable distribution will add mirrors for security
|
By default, debootstrapping a stable distribution will add mirrors for security
|
||||||
and updates to the sources.list.
|
and updates to the sources.list.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue