forked from josch/mmdebstrap
add --format=ext4
This commit is contained in:
parent
4a294f05bd
commit
409686048b
5 changed files with 162 additions and 46 deletions
|
@ -34,7 +34,7 @@ all_variants = [
|
||||||
"standard",
|
"standard",
|
||||||
]
|
]
|
||||||
default_format = "auto"
|
default_format = "auto"
|
||||||
all_formats = ["auto", "directory", "tar", "squashfs", "ext2", "null"]
|
all_formats = ["auto", "directory", "tar", "squashfs", "ext2", "ext4", "null"]
|
||||||
|
|
||||||
mirror = os.getenv("mirror", "http://127.0.0.1/debian")
|
mirror = os.getenv("mirror", "http://127.0.0.1/debian")
|
||||||
hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip()
|
hostarch = subprocess.check_output(["dpkg", "--print-architecture"]).decode().strip()
|
||||||
|
|
|
@ -59,7 +59,7 @@ Needs-QEMU: true
|
||||||
Test: mmdebstrap
|
Test: mmdebstrap
|
||||||
Needs-Root: true
|
Needs-Root: true
|
||||||
Modes: root
|
Modes: root
|
||||||
Formats: tar squashfs ext2
|
Formats: tar squashfs ext2 ext4
|
||||||
Variants: essential apt minbase buildd - standard
|
Variants: essential apt minbase buildd - standard
|
||||||
Skip-If:
|
Skip-If:
|
||||||
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
|
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
|
||||||
|
@ -68,7 +68,7 @@ Skip-If:
|
||||||
|
|
||||||
Test: check-for-bit-by-bit-identical-format-output
|
Test: check-for-bit-by-bit-identical-format-output
|
||||||
Modes: unshare fakechroot
|
Modes: unshare fakechroot
|
||||||
Formats: tar squashfs ext2
|
Formats: tar squashfs ext2 ext4
|
||||||
Variants: essential apt minbase buildd - standard
|
Variants: essential apt minbase buildd - standard
|
||||||
Skip-If:
|
Skip-If:
|
||||||
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
|
variant == "standard" and dist == "oldstable" # #864082, #1004557, #1004558
|
||||||
|
|
|
@ -33,7 +33,7 @@ deletecache() {
|
||||||
done
|
done
|
||||||
# deleting artifacts from test "mmdebstrap"
|
# deleting artifacts from test "mmdebstrap"
|
||||||
for variant in essential apt minbase buildd - standard; do
|
for variant in essential apt minbase buildd - standard; do
|
||||||
for format in tar ext2 squashfs; do
|
for format in tar ext2 ext4 squashfs; do
|
||||||
if [ -e "$dir/mmdebstrap-$dist-$variant.$format" ]; then
|
if [ -e "$dir/mmdebstrap-$dist-$variant.$format" ]; then
|
||||||
# attempt to delete for all dists because DEFAULT_DIST might've been different the last time
|
# attempt to delete for all dists because DEFAULT_DIST might've been different the last time
|
||||||
rm "$dir/mmdebstrap-$dist-$variant.$format"
|
rm "$dir/mmdebstrap-$dist-$variant.$format"
|
||||||
|
@ -453,7 +453,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,passwd
|
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,passwd,e2fsprogs,uuid-runtime
|
||||||
if [ ! -e ./mmdebstrap ]; then
|
if [ ! -e ./mmdebstrap ]; then
|
||||||
pkgs="$pkgs,mmdebstrap"
|
pkgs="$pkgs,mmdebstrap"
|
||||||
fi
|
fi
|
||||||
|
|
175
mmdebstrap
175
mmdebstrap
|
@ -46,6 +46,7 @@ use Socket;
|
||||||
use Time::HiRes;
|
use Time::HiRes;
|
||||||
use Math::BigInt;
|
use Math::BigInt;
|
||||||
use Text::ParseWords;
|
use Text::ParseWords;
|
||||||
|
use Digest::SHA;
|
||||||
use version;
|
use version;
|
||||||
|
|
||||||
## no critic (InputOutput::RequireBriefOpen)
|
## no critic (InputOutput::RequireBriefOpen)
|
||||||
|
@ -66,13 +67,16 @@ use version;
|
||||||
*MS_BIND = \0x1000;
|
*MS_BIND = \0x1000;
|
||||||
*MS_REC = \0x4000;
|
*MS_REC = \0x4000;
|
||||||
*MNT_DETACH = \2;
|
*MNT_DETACH = \2;
|
||||||
|
# uuid_t NameSpace_DNS in rfc4122
|
||||||
|
*UUID_NS_DNS = \'6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
||||||
our (
|
our (
|
||||||
$CLONE_NEWNS, $CLONE_NEWUTS,
|
$CLONE_NEWNS, $CLONE_NEWUTS,
|
||||||
$CLONE_NEWIPC, $CLONE_NEWUSER,
|
$CLONE_NEWIPC, $CLONE_NEWUSER,
|
||||||
$CLONE_NEWPID, $CLONE_NEWNET,
|
$CLONE_NEWPID, $CLONE_NEWNET,
|
||||||
$_LINUX_CAPABILITY_VERSION_3, $CAP_SYS_ADMIN,
|
$_LINUX_CAPABILITY_VERSION_3, $CAP_SYS_ADMIN,
|
||||||
$PR_CAPBSET_READ, $MS_BIND,
|
$PR_CAPBSET_READ, $MS_BIND,
|
||||||
$MS_REC, $MNT_DETACH
|
$MS_REC, $MNT_DETACH,
|
||||||
|
$UUID_NS_DNS
|
||||||
);
|
);
|
||||||
|
|
||||||
#<<<
|
#<<<
|
||||||
|
@ -216,10 +220,11 @@ sub minor {
|
||||||
|
|
||||||
sub can_execute {
|
sub can_execute {
|
||||||
my $tool = shift;
|
my $tool = shift;
|
||||||
|
my $verbose = shift // '--version';
|
||||||
my $pid = open my $fh, '-|' // return 0;
|
my $pid = open my $fh, '-|' // return 0;
|
||||||
if ($pid == 0) {
|
if ($pid == 0) {
|
||||||
open(STDERR, '>&', STDOUT) or die;
|
open(STDERR, '>&', STDOUT) or die;
|
||||||
exec {$tool} $tool, '--version' or die;
|
exec {$tool} $tool, $verbose or die;
|
||||||
}
|
}
|
||||||
chomp(
|
chomp(
|
||||||
my $content = do { local $/; <$fh> }
|
my $content = do { local $/; <$fh> }
|
||||||
|
@ -303,6 +308,28 @@ sub shellescape {
|
||||||
return "'$string'";
|
return "'$string'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub create_v5_uuid {
|
||||||
|
use bytes;
|
||||||
|
my $ns_uuid = shift;
|
||||||
|
my $name = shift;
|
||||||
|
my $version = 0x50;
|
||||||
|
# convert the namespace uuid to binary
|
||||||
|
$ns_uuid =~ tr/-//d;
|
||||||
|
$ns_uuid = pack 'H*', $ns_uuid;
|
||||||
|
# concatenate namespace and name and take sha1
|
||||||
|
my $digest = Digest::SHA->new(1);
|
||||||
|
$digest->add($ns_uuid);
|
||||||
|
$digest->add($name);
|
||||||
|
# only the first 16 bytes matter
|
||||||
|
my $uuid = substr($digest->digest(), 0, 16);
|
||||||
|
# set the version
|
||||||
|
substr $uuid, 6, 1, chr(ord(substr($uuid, 6, 1)) & 0x0f | $version);
|
||||||
|
substr $uuid, 8, 1, chr(ord(substr $uuid, 8, 1) & 0x3f | 0x80);
|
||||||
|
# convert binary back to uuid formatting
|
||||||
|
return join '-', map { unpack 'H*', $_ }
|
||||||
|
map { substr $uuid, 0, $_, '' } (4, 2, 2, 2, 6);
|
||||||
|
}
|
||||||
|
|
||||||
sub test_unshare_userns {
|
sub test_unshare_userns {
|
||||||
my $verbose = shift;
|
my $verbose = shift;
|
||||||
|
|
||||||
|
@ -4381,14 +4408,15 @@ sub guess_sources_format {
|
||||||
|
|
||||||
sub approx_disk_usage {
|
sub approx_disk_usage {
|
||||||
my $directory = shift;
|
my $directory = shift;
|
||||||
|
my $block_size = shift;
|
||||||
info "approximating disk usage...";
|
info "approximating disk usage...";
|
||||||
# the "du" utility reports different results depending on the underlying
|
# the "du" utility reports different results depending on the underlying
|
||||||
# filesystem, see https://bugs.debian.org/650077 for a discussion
|
# filesystem, see https://bugs.debian.org/650077 for a discussion
|
||||||
#
|
#
|
||||||
# we use code similar to the one used by dpkg-gencontrol instead
|
# we use code similar to the one used by dpkg-gencontrol instead
|
||||||
#
|
#
|
||||||
# Regular files are measured in number of 1024 byte blocks. All other
|
# Regular files are measured in number of $block_size byte blocks. All
|
||||||
# entries are assumed to take one block of space.
|
# other entries are assumed to take one block of space.
|
||||||
#
|
#
|
||||||
# We ignore /dev because depending on the mode, the directory might be
|
# We ignore /dev because depending on the mode, the directory might be
|
||||||
# populated or not and we want consistent disk usage results independent
|
# populated or not and we want consistent disk usage results independent
|
||||||
|
@ -4412,8 +4440,8 @@ sub approx_disk_usage {
|
||||||
return if exists $hardlink{"$dev:$ino"};
|
return if exists $hardlink{"$dev:$ino"};
|
||||||
# Track hardlinks to avoid repeated additions.
|
# Track hardlinks to avoid repeated additions.
|
||||||
$hardlink{"$dev:$ino"} = 1 if $nlink > 1;
|
$hardlink{"$dev:$ino"} = 1 if $nlink > 1;
|
||||||
# add file size in 1024 byte blocks, rounded up
|
# add file size in $block_size byte blocks, rounded up
|
||||||
$installed_size += int(((-s _) + 1024) / 1024);
|
$installed_size += int(((-s _) + $block_size) / $block_size);
|
||||||
} else {
|
} else {
|
||||||
# all other entries are assumed to only take up one block
|
# all other entries are assumed to only take up one block
|
||||||
$installed_size += 1;
|
$installed_size += 1;
|
||||||
|
@ -4805,7 +4833,7 @@ sub main() {
|
||||||
$options->{format} = 'directory';
|
$options->{format} = 'directory';
|
||||||
}
|
}
|
||||||
my @valid_formats
|
my @valid_formats
|
||||||
= ('auto', 'directory', 'tar', 'squashfs', 'ext2', 'null');
|
= ('auto', 'directory', 'tar', 'squashfs', 'ext2', 'ext4', 'null');
|
||||||
if (none { $_ eq $options->{format} } @valid_formats) {
|
if (none { $_ eq $options->{format} } @valid_formats) {
|
||||||
error "invalid format. Choose from " . (join ', ', @valid_formats);
|
error "invalid format. Choose from " . (join ', ', @valid_formats);
|
||||||
}
|
}
|
||||||
|
@ -5670,6 +5698,30 @@ sub main() {
|
||||||
if ($exitstatus != 0) {
|
if ($exitstatus != 0) {
|
||||||
error "genext2fs failed with exit status: $exitstatus";
|
error "genext2fs failed with exit status: $exitstatus";
|
||||||
}
|
}
|
||||||
|
} elsif ($options->{target} =~ /\.ext4$/) {
|
||||||
|
$options->{format} = 'ext4';
|
||||||
|
# check if the installed version of e2fsprogs supports tarballs on
|
||||||
|
# stdin
|
||||||
|
(undef, my $filename) = tempfile(
|
||||||
|
"mmdebstrap.ext4.XXXXXXXXXXXX",
|
||||||
|
OPEN => 0,
|
||||||
|
TMPDIR => 1
|
||||||
|
);
|
||||||
|
# creating file to suppress message "Creating regular file ..."
|
||||||
|
{ open my $fh, '>', $filename; }
|
||||||
|
open my $fh, '|-', 'mke2fs', '-q', '-F', '-o', 'Linux', '-T',
|
||||||
|
'ext4', '-b', '4096', '-d', '-', $filename,
|
||||||
|
'16384' // error "failed to fork(): $!";
|
||||||
|
# write 10240 null-bytes to mke2fs -- this represents an empty
|
||||||
|
# tar archive
|
||||||
|
print $fh ("\0" x 10240)
|
||||||
|
or error "cannot write to mke2fs process";
|
||||||
|
close $fh;
|
||||||
|
my $exitstatus = $?;
|
||||||
|
unlink $filename // die "cannot unlink $filename";
|
||||||
|
if ($exitstatus != 0) {
|
||||||
|
error "mke2fs failed with exit status: $exitstatus";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$options->{format} = 'directory';
|
$options->{format} = 'directory';
|
||||||
}
|
}
|
||||||
|
@ -5687,21 +5739,30 @@ sub main() {
|
||||||
info "ignoring target $options->{target} with null format";
|
info "ignoring target $options->{target} with null format";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $blocksize = -1;
|
||||||
if ($options->{format} eq 'ext2') {
|
if ($options->{format} eq 'ext2') {
|
||||||
if (!can_execute 'genext2fs') {
|
if (!can_execute 'genext2fs') {
|
||||||
error "need genext2fs for ext2 format";
|
error "need genext2fs for ext2 format";
|
||||||
}
|
}
|
||||||
|
$blocksize = 1024;
|
||||||
|
} elsif ($options->{format} eq 'ext4') {
|
||||||
|
if (!can_execute 'mke2fs', '-V') {
|
||||||
|
error "need mke2fs for ext4 format";
|
||||||
|
}
|
||||||
|
$blocksize = 4096;
|
||||||
} elsif ($options->{format} eq 'squashfs') {
|
} elsif ($options->{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";
|
||||||
}
|
}
|
||||||
|
$blocksize = 1048576;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2', 'null')) {
|
if (any { $_ eq $options->{format} }
|
||||||
|
('tar', 'squashfs', 'ext2', 'ext4', 'null')) {
|
||||||
if ($options->{format} ne 'null') {
|
if ($options->{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, squashfs, ext2 or ext4 image in"
|
||||||
. " fakechroot mode might fail in extract and"
|
. " fakechroot mode might fail in extract and"
|
||||||
. " custom variants because there might be no tar inside the"
|
. " custom variants because there might be no tar inside the"
|
||||||
. " chroot";
|
. " chroot";
|
||||||
|
@ -5885,7 +5946,7 @@ sub main() {
|
||||||
# If both the above assertion change, we can stop creating /dev entries as
|
# If both the above assertion change, we can stop creating /dev entries as
|
||||||
# well.
|
# well.
|
||||||
my $devtar = '';
|
my $devtar = '';
|
||||||
if (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2')) {
|
if (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2', 'ext4')) {
|
||||||
foreach my $file (@devfiles) {
|
foreach my $file (@devfiles) {
|
||||||
my ($fname, $mode, $type, $linkname, $devmajor, $devminor)
|
my ($fname, $mode, $type, $linkname, $devmajor, $devminor)
|
||||||
= @{$file};
|
= @{$file};
|
||||||
|
@ -5954,6 +6015,9 @@ sub main() {
|
||||||
push @taropts, '--xattrs', '--xattrs-exclude=system.*';
|
push @taropts, '--xattrs', '--xattrs-exclude=system.*';
|
||||||
} elsif ($options->{format} eq "ext2") {
|
} elsif ($options->{format} eq "ext2") {
|
||||||
warning "genext2fs does not support extended attributes";
|
warning "genext2fs does not support extended attributes";
|
||||||
|
warning "ext2 does not support sub-second precision timestamps";
|
||||||
|
warning "ext2 does not support timestamps beyond 2038 January 18";
|
||||||
|
warning "ext2 inode size of 128 prevents removing these limitations";
|
||||||
} else {
|
} else {
|
||||||
push @taropts, '--xattrs';
|
push @taropts, '--xattrs';
|
||||||
}
|
}
|
||||||
|
@ -6001,8 +6065,9 @@ sub main() {
|
||||||
close $childsock;
|
close $childsock;
|
||||||
|
|
||||||
close $nblkreader;
|
close $nblkreader;
|
||||||
if (!$options->{dryrun} && $options->{format} eq 'ext2') {
|
if (!$options->{dryrun} && any { $_ eq $options->{format} }
|
||||||
my $numblocks = approx_disk_usage($options->{root});
|
('ext2', 'ext4')) {
|
||||||
|
my $numblocks = approx_disk_usage($options->{root}, $blocksize);
|
||||||
print $nblkwriter "$numblocks\n";
|
print $nblkwriter "$numblocks\n";
|
||||||
$nblkwriter->flush();
|
$nblkwriter->flush();
|
||||||
}
|
}
|
||||||
|
@ -6010,8 +6075,8 @@ sub main() {
|
||||||
|
|
||||||
if ($options->{dryrun}) {
|
if ($options->{dryrun}) {
|
||||||
info "simulate creating tarball...";
|
info "simulate creating tarball...";
|
||||||
} elsif (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2'))
|
} elsif (any { $_ eq $options->{format} }
|
||||||
{
|
('tar', 'squashfs', 'ext2', 'ext4')) {
|
||||||
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
|
||||||
|
@ -6132,7 +6197,8 @@ sub main() {
|
||||||
|
|
||||||
my $numblocks = 0;
|
my $numblocks = 0;
|
||||||
close $nblkwriter;
|
close $nblkwriter;
|
||||||
if (!$options->{dryrun} && $options->{format} eq 'ext2') {
|
if (!$options->{dryrun} && any { $_ eq $options->{format} }
|
||||||
|
('ext2', 'ext4')) {
|
||||||
$numblocks = <$nblkreader>;
|
$numblocks = <$nblkreader>;
|
||||||
if (defined $numblocks) {
|
if (defined $numblocks) {
|
||||||
chomp $numblocks;
|
chomp $numblocks;
|
||||||
|
@ -6151,9 +6217,11 @@ sub main() {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} elsif (any { $_ eq $options->{format} } ('directory', 'null')) {
|
} elsif (any { $_ eq $options->{format} } ('directory', 'null')) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} elsif ($options->{format} eq 'ext2' && $numblocks <= 0) {
|
} elsif ((any { $_ eq $options->{format} } ('ext2', 'ext4'))
|
||||||
|
&& $numblocks <= 0) {
|
||||||
# nothing to do because of invalid $numblocks
|
# nothing to do because of invalid $numblocks
|
||||||
} elsif (any { $_ eq $options->{format} } ('tar', 'squashfs', 'ext2')) {
|
} elsif (any { $_ eq $options->{format} }
|
||||||
|
('tar', 'squashfs', 'ext2', 'ext4')) {
|
||||||
# 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 {
|
||||||
|
@ -6162,8 +6230,8 @@ sub main() {
|
||||||
error "cannot copy to standard output: $!";
|
error "cannot copy to standard output: $!";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( $options->{format} eq 'squashfs'
|
if (any { $_ eq $options->{format} }
|
||||||
or $options->{format} eq 'ext2'
|
('squashfs', 'ext2', 'ext4')
|
||||||
or defined $tar_compressor) {
|
or defined $tar_compressor) {
|
||||||
my @argv = ();
|
my @argv = ();
|
||||||
if ($options->{format} eq 'squashfs') {
|
if ($options->{format} eq 'squashfs') {
|
||||||
|
@ -6171,7 +6239,7 @@ sub main() {
|
||||||
'--quiet', '--no-skip', '--force',
|
'--quiet', '--no-skip', '--force',
|
||||||
'--exportable',
|
'--exportable',
|
||||||
'--compressor', 'xz',
|
'--compressor', 'xz',
|
||||||
'--block-size', '1048576',
|
'--block-size', $blocksize,
|
||||||
$options->{target};
|
$options->{target};
|
||||||
} elsif ($options->{format} eq 'ext2') {
|
} elsif ($options->{format} eq 'ext2') {
|
||||||
if ($numblocks <= 0) {
|
if ($numblocks <= 0) {
|
||||||
|
@ -6179,6 +6247,26 @@ sub main() {
|
||||||
}
|
}
|
||||||
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 'ext4') {
|
||||||
|
if ($numblocks <= 0) {
|
||||||
|
error "invalid number of blocks: $numblocks";
|
||||||
|
}
|
||||||
|
push @argv, 'mke2fs', '-q', '-F', '-o', 'Linux', '-T',
|
||||||
|
'ext4';
|
||||||
|
if (exists $ENV{SOURCE_DATE_EPOCH}) {
|
||||||
|
# if SOURCE_DATE_EPOCH was set, make the image
|
||||||
|
# reproducible by setting a fixed uuid and
|
||||||
|
# hash_seed
|
||||||
|
my $uuid = create_v5_uuid(
|
||||||
|
create_v5_uuid(
|
||||||
|
$UUID_NS_DNS, "mister-muffin.de"
|
||||||
|
),
|
||||||
|
$mtime
|
||||||
|
);
|
||||||
|
push @argv, '-U', $uuid, '-E', "hash_seed=$uuid";
|
||||||
|
}
|
||||||
|
push @argv, '-b', $blocksize, '-d', '-',
|
||||||
|
$options->{target}, $numblocks;
|
||||||
} elsif ($options->{format} eq 'tar') {
|
} elsif ($options->{format} eq 'tar') {
|
||||||
push @argv, @{$tar_compressor};
|
push @argv, @{$tar_compressor};
|
||||||
} else {
|
} else {
|
||||||
|
@ -6200,8 +6288,8 @@ 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 (any { $_ eq $options->{format} }
|
||||||
or $options->{format} eq 'ext2') {
|
('squashfs', 'ext2', 'ext4')) {
|
||||||
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 ($options->{format} eq 'tar') {
|
||||||
|
@ -6282,7 +6370,7 @@ sub main() {
|
||||||
if (any { $_ eq $options->{format} } ('directory')) {
|
if (any { $_ eq $options->{format} } ('directory')) {
|
||||||
# nothing to do
|
# nothing to do
|
||||||
} elsif (any { $_ eq $options->{format} }
|
} elsif (any { $_ eq $options->{format} }
|
||||||
('tar', 'squashfs', 'ext2', 'null')) {
|
('tar', 'squashfs', 'ext2', 'ext4', 'null')) {
|
||||||
if (!-e $options->{root}) {
|
if (!-e $options->{root}) {
|
||||||
error "$options->{root} does not exist";
|
error "$options->{root} does not exist";
|
||||||
}
|
}
|
||||||
|
@ -6381,12 +6469,12 @@ can be disabled by choosing the empty string for I<SUITE>. See the section
|
||||||
B<VARIANTS> for more information.
|
B<VARIANTS> for more information.
|
||||||
|
|
||||||
The I<TARGET> option may either be the path to a directory, the path to a
|
The I<TARGET> option may 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, a
|
tarball filename, the path to a squashfs image, the path to an ext2 or ext4
|
||||||
FIFO, a character special device, or C<->. The I<TARGET> option is optional if
|
image, a FIFO, a character special device, or C<->. The I<TARGET> option is
|
||||||
no I<MIRROR> option is provided. If I<TARGET> is missing or if I<TARGET> is
|
optional if no I<MIRROR> option is provided. If I<TARGET> is missing or if
|
||||||
C<->, an uncompressed tarball will be sent to standard output. Without the
|
I<TARGET> is C<->, an uncompressed tarball will be sent to standard output.
|
||||||
B<--format> option, I<TARGET> will be used to choose the format. See the
|
Without the B<--format> option, I<TARGET> will be used to choose the format.
|
||||||
section B<FORMATS> for more information.
|
See the section B<FORMATS> for more information.
|
||||||
|
|
||||||
The I<MIRROR> option may either be provided as a URI, in apt one-line format,
|
The I<MIRROR> option may either be provided as a URI, in apt one-line format,
|
||||||
as a path to a file in apt's one-line or deb822-format, or C<->. If no
|
as a path to a file in apt's one-line or deb822-format, or C<->. If no
|
||||||
|
@ -6463,8 +6551,8 @@ information.
|
||||||
=item B<--format>=I<name>
|
=item B<--format>=I<name>
|
||||||
|
|
||||||
Choose the output format. Valid format I<name>s are B<auto>, B<directory>,
|
Choose the output format. Valid format I<name>s are B<auto>, B<directory>,
|
||||||
B<tar>, B<squashfs>, B<ext2> and B<null>. The default format is B<auto>. See
|
B<tar>, B<squashfs>, B<ext2>, B<ext4> and B<null>. The default format is
|
||||||
the section B<FORMATS> for more information.
|
B<auto>. See the section B<FORMATS> for more information.
|
||||||
|
|
||||||
=item B<--aptopt>=I<option>|I<file>
|
=item B<--aptopt>=I<option>|I<file>
|
||||||
|
|
||||||
|
@ -7043,6 +7131,7 @@ I<TARGET> equals C<->, or if I<TARGET> is a named pipe (fifo) or if I<TARGET>
|
||||||
is a character special file, then the B<tar> format will be chosen. If
|
is a character special file, then the B<tar> format will be chosen. If
|
||||||
I<TARGET> ends with C<.squashfs> or C<.sqfs>, then the B<squashfs> format will
|
I<TARGET> ends with C<.squashfs> or C<.sqfs>, then the B<squashfs> format will
|
||||||
be chosen. If I<TARGET> ends with C<.ext2> then the B<ext2> format will be
|
be chosen. If I<TARGET> ends with C<.ext2> then the B<ext2> format will be
|
||||||
|
chosen. If I<TARGET> ends with C<.ext4> then the B<ext4> format will be
|
||||||
chosen. If none of these conditions apply, the B<directory> format will be
|
chosen. If none of these conditions apply, the B<directory> format will be
|
||||||
chosen.
|
chosen.
|
||||||
|
|
||||||
|
@ -7092,8 +7181,24 @@ with this format because C<genext2fs> can only write to a regular file. If you
|
||||||
need your ext2 image be named C<->, then just explicitly pass the relative path
|
need your ext2 image be named C<->, then just explicitly pass the relative path
|
||||||
to it like F<./->. To convert the result to an ext3 image, use C<tune2fs -O
|
to it like F<./->. To convert the result to an ext3 image, use C<tune2fs -O
|
||||||
has_journal TARGET> and to convert it to ext4, use C<tune2fs -O
|
has_journal TARGET> and to convert it to ext4, use C<tune2fs -O
|
||||||
extents,uninit_bg,dir_index,has_journal TARGET>. Since C<genext2fs> does not
|
extents,uninit_bg,dir_index,has_journal TARGET>.
|
||||||
support extended attributes, the resulting image will not contain them.
|
|
||||||
|
B<CAUTION>: the ext2 format does not support timestamps beyond 2038 January 19,
|
||||||
|
does not support sub-second precision timestamps and does not support extended
|
||||||
|
attributes. Its inode size of 128 prevents adding these features with tune2fs
|
||||||
|
later on.
|
||||||
|
|
||||||
|
=item B<ext4>
|
||||||
|
|
||||||
|
A temporary chroot directory will be created in C<$TMPDIR> or F</tmp> if
|
||||||
|
C<$TMPDIR> is not set. A tarball of that directory will be piped to the
|
||||||
|
C<mke2fs> utility, which will create an ext4 image that will be approximately
|
||||||
|
90% full in I<TARGET>. The special I<TARGET> C<-> does not work with this
|
||||||
|
format because C<mke2fs> can only write to a regular file. If you need your
|
||||||
|
ext4 image be named C<->, then just explicitly pass the relative path to it
|
||||||
|
like F<./->. If C<SOURCE_DATE_EPOCH> is set, the filesystem UUID and hash_seed
|
||||||
|
will be set to a UUID derived from SOURCE_DATE_EPOCH to create reproducible
|
||||||
|
images.
|
||||||
|
|
||||||
=item B<null>
|
=item B<null>
|
||||||
|
|
||||||
|
@ -7402,8 +7507,8 @@ Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
||||||
=item B<output>
|
=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, ext4 image or squashfs image and delete the
|
||||||
directory.
|
temporary chroot directory.
|
||||||
|
|
||||||
If B<--skip=output/dev> is added, the resulting chroot will not contain the
|
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
|
device nodes, directories and symlinks that B<debootstrap> creates but just
|
||||||
|
|
|
@ -5,15 +5,26 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||||
|
|
||||||
[ "$(id -u)" -eq 0 ]
|
[ "$(id -u)" -eq 0 ]
|
||||||
[ {{ MODE }} = "root" ]
|
[ {{ MODE }} = "root" ]
|
||||||
case {{ FORMAT }} in tar|squashfs|ext2) : ;; *) exit 1;; esac
|
case {{ FORMAT }} in tar|squashfs|ext2|ext4) : ;; *) exit 1;; esac
|
||||||
|
|
||||||
{{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }}
|
{{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} {{ MIRROR }}
|
||||||
|
# creating an ext4 image on a 9p filesystem produces different results compared
|
||||||
|
# to creating it on a tmpfs or ext4 fs because 9p does not support discards and
|
||||||
|
# even when running with -E nodiscard, the number of written bytes will differ
|
||||||
|
# https://lore.kernel.org/linux-ext4/171484520952.2626447.2160419274451668597@localhost/T/#t
|
||||||
|
mv /tmp/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }}
|
||||||
if [ "{{ FORMAT }}" = tar ]; then
|
if [ "{{ FORMAT }}" = tar ]; then
|
||||||
printf 'ustar ' | cmp --bytes=6 --ignore-initial=257:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar -
|
printf 'ustar ' | cmp --bytes=6 --ignore-initial=257:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar -
|
||||||
elif [ "{{ FORMAT }}" = squashfs ]; then
|
elif [ "{{ FORMAT }}" = squashfs ]; then
|
||||||
printf 'hsqs' | cmp --bytes=4 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.squashfs -
|
printf 'hsqs' | cmp --bytes=4 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.squashfs -
|
||||||
elif [ "{{ FORMAT }}" = ext2 ]; then
|
elif [ "{{ FORMAT }}" = ext2 ]; then
|
||||||
printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext2 -
|
printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext2 -
|
||||||
|
printf '\000\000\000\000\000\000\000\000\000\000\000\000' | cmp --bytes=12 --ignore-initial=1116:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext2 -
|
||||||
|
elif [ "{{ FORMAT }}" = ext4 ]; then
|
||||||
|
printf '\123\357' | cmp --bytes=2 --ignore-initial=1080:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4 -
|
||||||
|
printf '\074\020\000\000\302\042\000\000\153\004\000\000' | cmp --bytes=12 --ignore-initial=1116:0 ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4 -
|
||||||
|
|
||||||
|
[ "$(/sbin/blkid --match-tag UUID --output value ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.ext4)" = "$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name $SOURCE_DATE_EPOCH)" ]
|
||||||
else
|
else
|
||||||
echo "unknown format: {{ FORMAT }}" >&2
|
echo "unknown format: {{ FORMAT }}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|
Loading…
Reference in a new issue