Compare commits
13 commits
3fcb125e3c
...
7d7d757f00
Author | SHA1 | Date | |
---|---|---|---|
7d7d757f00 | |||
902bc55c4d | |||
226f86fea9 | |||
df2226fb25 | |||
3fb97753ea | |||
89a7e4c6ee | |||
f1d847e4ae | |||
c95632f963 | |||
5533b25255 | |||
34a9de929d | |||
b385eb548a | |||
d82afec5de | |||
117a1591c5 |
13 changed files with 223 additions and 180 deletions
|
@ -88,12 +88,14 @@ def main():
|
|||
)
|
||||
parser.add_argument("--mode", metavar="mode", help="only run tests with this mode")
|
||||
parser.add_argument("--dist", metavar="dist", help="only run tests with this dist")
|
||||
parser.add_argument(
|
||||
"--variant", metavar="variant", help="only run tests with this variant"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# copy over files from git or as distributed
|
||||
for (git, dist, target) in [
|
||||
("./mmdebstrap", "/usr/bin/mmdebstrap", "mmdebstrap"),
|
||||
("./taridshift", "/usr/bin/mmtaridshift", "taridshift"),
|
||||
("./tarfilter", "/usr/bin/mmtarfilter", "tarfilter"),
|
||||
(
|
||||
"./proxysolver",
|
||||
|
@ -223,7 +225,7 @@ def main():
|
|||
)
|
||||
print("time left: %s" % timeleft, file=sys.stderr)
|
||||
if failed:
|
||||
print("failed: %d" % len(failed))
|
||||
print("failed: %d" % len(failed), file=sys.stderr)
|
||||
num_finished += 1
|
||||
with open("tests/" + name) as fin, open("shared/test.sh", "w") as fout:
|
||||
for line in fin:
|
||||
|
@ -257,6 +259,9 @@ def main():
|
|||
if args.mode and args.mode != mode:
|
||||
print(f"skipping because of --mode={args.mode}", file=sys.stderr)
|
||||
continue
|
||||
if args.variant and args.variant != variant:
|
||||
print(f"skipping because of --variant={args.variant}", file=sys.stderr)
|
||||
continue
|
||||
proc = subprocess.Popen(argv)
|
||||
try:
|
||||
proc.wait()
|
||||
|
|
|
@ -52,7 +52,7 @@ Skip-If:
|
|||
fmt == "squashfs" and dist == "oldstable" # squashfs-tools-ng is not available
|
||||
fmt == "ext2" and dist == "oldstable" # genext2fs does not support SOURCE_DATE_EPOCH
|
||||
|
||||
Test: taridshift-utility
|
||||
Test: tarfilter-idshift
|
||||
Needs-QEMU: true
|
||||
Skip-If: dist == "oldstable" # python3 tarfile module does not preserve xattrs
|
||||
|
||||
|
@ -286,11 +286,10 @@ Test: install-doc-debian
|
|||
Modes: chrootless
|
||||
Variants: custom
|
||||
|
||||
Test: install-known-good-from-essential-yes
|
||||
Test: chrootless-essential
|
||||
Variants: custom
|
||||
Modes: chrootless
|
||||
Skip-If:
|
||||
True # #1006692
|
||||
dist in ["oldstable", "stable"]
|
||||
|
||||
Test: install-doc-debian-and-output-tarball
|
||||
|
@ -322,3 +321,7 @@ Modes: fakechroot
|
|||
Test: dev-ptmx
|
||||
Modes: root unshare
|
||||
Needs-QEMU: true
|
||||
|
||||
Test: error-if-stdout-is-tty
|
||||
|
||||
Test: variant-custom-timeout
|
||||
|
|
52
mmdebstrap
52
mmdebstrap
|
@ -37,7 +37,8 @@ use Cwd qw(abs_path getcwd);
|
|||
require "syscall.ph"; ## no critic (Modules::RequireBarewordIncludes)
|
||||
use Fcntl qw(S_IFCHR S_IFBLK FD_CLOEXEC F_GETFD F_SETFD);
|
||||
use List::Util qw(any none);
|
||||
use POSIX qw(SIGINT SIGHUP SIGPIPE SIGTERM SIG_BLOCK SIG_UNBLOCK strftime);
|
||||
use POSIX
|
||||
qw(SIGINT SIGHUP SIGPIPE SIGTERM SIG_BLOCK SIG_UNBLOCK strftime isatty);
|
||||
use Carp;
|
||||
use Term::ANSIColor;
|
||||
use Socket;
|
||||
|
@ -978,19 +979,24 @@ sub run_apt_download_progress {
|
|||
my $flags = fcntl($wfh, F_GETFD, 0) or error "fcntl F_GETFD: $!";
|
||||
fcntl($wfh, F_SETFD, $flags & ~FD_CLOEXEC) or error "fcntl F_SETFD: $!";
|
||||
my $fd = fileno $wfh;
|
||||
# run_apt_progress() can raise an exception which would leave this function
|
||||
# without cleaning up the other thread we started, making mmdebstrap hang
|
||||
# in case run_apt_progress() fails -- so wrap this in eval() instead
|
||||
eval {
|
||||
# 2022-05-02, #debian-apt on OFTC, times in UTC+2
|
||||
# 16:57 < josch> DonKult: how is -oDebug::pkgDpkgPm=1 -oDir::Log=/dev/null
|
||||
# a "fancy no-op"?
|
||||
# 11:52 < DonKult> josch: "fancy no-op" in sofar as it does nothing to the
|
||||
# system even through its not in a special mode ala
|
||||
# simulation or download-only. It does all the things it
|
||||
# normally does, except that it just prints the dpkg calls
|
||||
# instead of execv() them which in practice amounts means
|
||||
# it does nothing (the Dir::Log just prevents libapt from
|
||||
# creating the /var/log/apt directories. As the code
|
||||
# creates them even if no logs will be placed there…). As
|
||||
# said, midterm an apt --print-install-packages or
|
||||
# something would be nice to avoid running everything.
|
||||
# 16:57 < josch> DonKult: how is -oDebug::pkgDpkgPm=1
|
||||
# -oDir::Log=/dev/null a "fancy no-op"?
|
||||
# 11:52 < DonKult> josch: "fancy no-op" in sofar as it does nothing to
|
||||
# the system even through its not in a special mode
|
||||
# ala simulation or download-only. It does all the
|
||||
# things it normally does, except that it just prints
|
||||
# the dpkg calls instead of execv() them which in
|
||||
# practice amounts means it does nothing (the Dir::Log
|
||||
# just prevents libapt from creating the /var/log/apt
|
||||
# directories. As the code creates them even if no
|
||||
# logs will be placed there…). As said, midterm an apt
|
||||
# --print-install-packages or something would be nice
|
||||
# to avoid running everything.
|
||||
run_apt_progress({
|
||||
ARGV => [
|
||||
'apt-get',
|
||||
|
@ -1011,13 +1017,21 @@ sub run_apt_download_progress {
|
|||
@{ $options->{APT_ARGV} },
|
||||
],
|
||||
});
|
||||
};
|
||||
my $err = '';
|
||||
if ($@) {
|
||||
$err = "apt download failed: $@";
|
||||
}
|
||||
# signal the child process that we are done
|
||||
close $wfh;
|
||||
# and then read from it what it got
|
||||
my @listofdebs = <$fh>;
|
||||
close $fh;
|
||||
if ($? != 0) {
|
||||
error "status child failed";
|
||||
$err = "status child failed";
|
||||
}
|
||||
if ($err) {
|
||||
error $err;
|
||||
}
|
||||
# remove trailing newlines
|
||||
chomp @listofdebs;
|
||||
|
@ -4149,7 +4163,7 @@ sub main() {
|
|||
# this is like:
|
||||
# lxc-usernsexec -- lxc-unshare -s 'MOUNT|PID|UTSNAME|IPC' ...
|
||||
# but without needing lxc
|
||||
if ($ARGV[0] eq "--unshare-helper") {
|
||||
if (scalar @ARGV >= 1 && $ARGV[0] eq "--unshare-helper") {
|
||||
if ($EFFECTIVE_USER_ID != 0 && !test_unshare_userns(1)) {
|
||||
exit 1;
|
||||
}
|
||||
|
@ -4451,7 +4465,7 @@ sub main() {
|
|||
);
|
||||
close $fh;
|
||||
if ( $? == 0
|
||||
and $content =~ /^apt ([0-9]+\.[0-9]+\.[0-9]+)[a-z0-9]* \([a-z0-9-]+\)$/m) {
|
||||
and $content =~ /^apt (\d+\.\d+\.\d+)\w* \(\S+\)$/am) {
|
||||
$aptversion = version->new($1);
|
||||
}
|
||||
if ($aptversion < "2.3.14") {
|
||||
|
@ -5126,7 +5140,11 @@ sub main() {
|
|||
$options->{sourceslists} = $sourceslists;
|
||||
}
|
||||
|
||||
if ($options->{target} ne '-') {
|
||||
if ($options->{target} eq '-') {
|
||||
if (POSIX::isatty STDOUT) {
|
||||
error "stdout is a an interactive tty";
|
||||
}
|
||||
} else {
|
||||
my $abs_path = abs_path($options->{target});
|
||||
if (!defined $abs_path) {
|
||||
error "unable to get absolute path of target directory"
|
||||
|
|
98
tarfilter
98
tarfilter
|
@ -43,17 +43,53 @@ class PaxFilterAction(argparse.Action):
|
|||
setattr(namespace, "paxfilter", items)
|
||||
|
||||
|
||||
class TransformAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
items = getattr(namespace, "trans", [])
|
||||
# This function mimics what src/transform.c from tar does
|
||||
if not values.startswith("s"):
|
||||
raise ValueError("regex must start with an 's'")
|
||||
if len(values) <= 4:
|
||||
# minimum regex: s/x//
|
||||
raise ValueError("invalid regex (too short)")
|
||||
d = values[1]
|
||||
if values.startswith(f"s{d}{d}"):
|
||||
raise ValueError("empty regex")
|
||||
values = values.removeprefix(f"s{d}")
|
||||
flags = 0
|
||||
if values.endswith(f"{d}i"):
|
||||
# trailing flags
|
||||
flags = re.IGNORECASE
|
||||
values = values.removesuffix(f"{d}i")
|
||||
# This regex only finds non-empty tokens.
|
||||
# Finding empty tokens would require a variable length look-behind
|
||||
# or \K in order to find escaped delimiters which is not supported by
|
||||
# the python re module.
|
||||
tokens = re.findall(rf"(?:\\[\\{d}]|[^{d}])+", values)
|
||||
match len(tokens):
|
||||
case 0:
|
||||
raise ValueError("invalid regex: not enough terms")
|
||||
case 1:
|
||||
repl = ""
|
||||
case 2:
|
||||
repl = tokens[1]
|
||||
case _:
|
||||
raise ValueError("invalid regex: too many terms: %s" % tokens)
|
||||
items.append((re.compile(tokens[0], flags), repl))
|
||||
setattr(namespace, "trans", items)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description="""\
|
||||
Filters a tarball on standard input by the same rules as the dpkg --path-exclude
|
||||
and --path-include options and writes resulting tarball to standard output. See
|
||||
dpkg(1) for information on how these two options work in detail. Since this is
|
||||
meant for filtering tarballs storing a rootfs, notice that paths must be given
|
||||
as /path and not as ./path even though they might be stored as such in the
|
||||
tarball.
|
||||
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
|
||||
./path even though they might be stored as such in the tarball.
|
||||
|
||||
Similarly, filter out unwanted pax extended headers. This is useful in cases
|
||||
Secondly, filter out unwanted pax extended headers. This is useful in cases
|
||||
where a tool only accepts certain xattr prefixes. For example tar2sqfs only
|
||||
supports SCHILY.xattr.user.*, SCHILY.xattr.trusted.* and
|
||||
SCHILY.xattr.security.* but not SCHILY.xattr.system.posix_acl_default.*.
|
||||
|
@ -65,41 +101,65 @@ Both types of options use Unix shell-style wildcards:
|
|||
[seq] matches any character in seq
|
||||
[!seq] matches any character not in seq
|
||||
|
||||
Thirdly, strip leading directory components off of tar members. Just as with
|
||||
Thirdly, transform the path of tar members using a sed expression just as with
|
||||
GNU tar --transform.
|
||||
|
||||
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
|
||||
their path are not passed through.
|
||||
"""
|
||||
|
||||
Lastly, shift user id and group id of each entry by the value given by the
|
||||
--idshift argument. The resulting uid or gid must not be negative.
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--path-exclude",
|
||||
metavar="pattern",
|
||||
action=PathFilterAction,
|
||||
help="Exclude path matching the given shell pattern.",
|
||||
help="Exclude path matching the given shell pattern. "
|
||||
"This option can be specified multiple times.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--path-include",
|
||||
metavar="pattern",
|
||||
action=PathFilterAction,
|
||||
help="Re-include a pattern after a previous exclusion.",
|
||||
help="Re-include a pattern after a previous exclusion. "
|
||||
"This option can be specified multiple times.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pax-exclude",
|
||||
metavar="pattern",
|
||||
action=PaxFilterAction,
|
||||
help="Exclude pax header matching the given globbing pattern.",
|
||||
help="Exclude pax header matching the given globbing pattern. "
|
||||
"This option can be specified multiple times.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pax-include",
|
||||
metavar="pattern",
|
||||
action=PaxFilterAction,
|
||||
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.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--transform",
|
||||
"--xform",
|
||||
metavar="EXPRESSION",
|
||||
action=TransformAction,
|
||||
help="Use sed replace EXPRESSION to transform file names. "
|
||||
"This option can be specified multiple times.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--strip-components",
|
||||
metavar="number",
|
||||
metavar="NUMBER",
|
||||
type=int,
|
||||
help="Strip NUMBER leading components from file names",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--idshift",
|
||||
metavar="NUM",
|
||||
type=int,
|
||||
help="Integer value by which to shift the uid and gid of each entry",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if (
|
||||
not hasattr(args, "pathfilter")
|
||||
|
@ -157,6 +217,8 @@ their path are not passed through.
|
|||
continue
|
||||
if args.strip_components:
|
||||
comps = member.name.split("/")
|
||||
# just as with GNU tar, archive members with less or equal
|
||||
# number of components are not passed through at all
|
||||
if len(comps) <= args.strip_components:
|
||||
continue
|
||||
member.name = "/".join(comps[args.strip_components :])
|
||||
|
@ -165,6 +227,18 @@ their path are not passed through.
|
|||
for k, v in member.pax_headers.items()
|
||||
if not pax_filter_should_skip(k)
|
||||
}
|
||||
if args.idshift:
|
||||
if args.idshift < 0 and -args.idshift > member.uid:
|
||||
print("uid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
if args.idshift < 0 and -args.idshift > member.gid:
|
||||
print("gid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
member.uid += args.idshift
|
||||
member.gid += args.idshift
|
||||
if hasattr(args, "trans"):
|
||||
for r, s in args.trans:
|
||||
member.name = r.sub(s, member.name)
|
||||
if member.isfile():
|
||||
with in_tar.extractfile(member) as file:
|
||||
out_tar.addfile(member, file)
|
||||
|
|
67
taridshift
67
taridshift
|
@ -1,67 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# This script is in the public domain
|
||||
#
|
||||
# Author: Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
|
||||
#
|
||||
# This script accepts a tarball on standard input and prints a tarball on
|
||||
# standard output with the same contents but all uid and gid ownership
|
||||
# information shifted by the value given as first command line argument.
|
||||
#
|
||||
# A tool like this should be written in C but libarchive has issues:
|
||||
# https://github.com/libarchive/libarchive/issues/587
|
||||
# https://github.com/libarchive/libarchive/pull/1288/ (needs 3.4.1)
|
||||
# Should these issues get fixed, then a good template is tarfilter.c in the
|
||||
# examples directory of libarchive.
|
||||
#
|
||||
# We are not using Perl either, because Archive::Tar slurps the whole tarball
|
||||
# into memory.
|
||||
#
|
||||
# We could also use Go but meh...
|
||||
# https://stackoverflow.com/a/59542307/784669
|
||||
|
||||
import tarfile
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="""\
|
||||
Accepts a tarball on standard input and prints a tarball on standard output
|
||||
with the same contents but all uid and gid ownership information shifted by the
|
||||
value given as first command line argument.
|
||||
"""
|
||||
)
|
||||
parser.add_argument(
|
||||
"idshift",
|
||||
metavar="NUM",
|
||||
type=int,
|
||||
help="Integer value by which to shift the uid and gid of each entry",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# starting with Python 3.8, the default format became PAX_FORMAT, so this
|
||||
# is only for compatibility with older versions of Python 3
|
||||
with tarfile.open(fileobj=sys.stdin.buffer, mode="r|*") as in_tar, tarfile.open(
|
||||
fileobj=sys.stdout.buffer, mode="w|", format=tarfile.PAX_FORMAT
|
||||
) as out_tar:
|
||||
for member in in_tar:
|
||||
if args.idshift < 0 and -args.idshift > member.uid:
|
||||
print("uid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
if args.idshift < 0 and -args.idshift > member.gid:
|
||||
print("gid cannot be negative", file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
member.uid += args.idshift
|
||||
member.gid += args.idshift
|
||||
if member.isfile():
|
||||
with in_tar.extractfile(member) as file:
|
||||
out_tar.addfile(member, file)
|
||||
else:
|
||||
out_tar.addfile(member)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -16,7 +16,7 @@ echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
|
|||
# mmdebstrap, resulting in different gid values
|
||||
{{ CMD }} --variant={{ VARIANT }} --mode={{ MODE }} \
|
||||
--essential-hook='if [ {{ VARIANT }} = - ]; then echo _apt:*:100:65534::/nonexistent:/usr/sbin/nologin >> "$1"/etc/passwd; fi' \
|
||||
--essential-hook='if [ {{ VARIANT }} = - ] && [ {{ DIST }} = unstable -o {{ DIST }} = testing ]; then printf "systemd-journal:x:101:\nsystemd-network:x:102:\nsystemd-resolve:x:103:\ncrontab:x:104:" >> "$1"/etc/group; fi' \
|
||||
--essential-hook='if [ {{ VARIANT }} = - ] && [ {{ DIST }} = unstable -o {{ DIST }} = testing ]; then printf "systemd-journal:x:999:\nsystemd-network:x:998:\ncrontab:x:101:" >> "$1"/etc/group; fi' \
|
||||
$(case {{ DIST }} in oldstable|stable) : ;; *) echo --hook-dir=./hooks/merged-usr ;; esac) \
|
||||
{{ DIST }} /tmp/debian-{{ DIST }}-mm.tar {{ MIRROR }}
|
||||
|
||||
|
@ -32,7 +32,7 @@ tar --xattrs --xattrs-include='*' -C /tmp/debian-{{ DIST }}-debootstrap -xf "cac
|
|||
tar -C /tmp/debian-{{ DIST }}-debootstrap -cf dev1.tar ./dev
|
||||
tar -C /tmp/debian-{{ DIST }}-mm -cf dev2.tar ./dev
|
||||
ret=0
|
||||
cmp dev1.tar dev2.tar || ret=$?
|
||||
cmp dev1.tar dev2.tar >&2 || ret=$?
|
||||
if [ "$ret" -ne 0 ]; then
|
||||
if type diffoscope >/dev/null; then
|
||||
diffoscope dev1.tar dev2.tar
|
||||
|
@ -144,7 +144,7 @@ for f in "/var/lib/dpkg/triggers/File" "/etc/shells"; do
|
|||
continue
|
||||
fi
|
||||
# the file must be different
|
||||
if cmp "$f1" "$f2"; then
|
||||
if cmp "$f1" "$f2" >&2; then
|
||||
continue
|
||||
fi
|
||||
# then sort both
|
||||
|
@ -162,15 +162,27 @@ for f in shadow shadow-; do
|
|||
done
|
||||
# same as above but for cron and systemd groups
|
||||
for f in gshadow gshadow-; do
|
||||
for group in systemd-journal systemd-network systemd-resolve crontab; do
|
||||
if grep -q '^'"$group"':!:' /tmp/debian-{{ DIST }}-debootstrap/etc/$f; then
|
||||
sed -i 's/^'"$group"':x::/'"$group"':!::/' /tmp/debian-{{ DIST }}-mm/etc/$f
|
||||
for group in systemd-journal systemd-network crontab; do
|
||||
for password in "!" "!\\*"; do
|
||||
if grep -q '^'"$group"':'"$password"':' /tmp/debian-{{ DIST }}-debootstrap/etc/$f; then
|
||||
sed -i 's/^'"$group"':x::/'"$group"':'"$password"'::/' /tmp/debian-{{ DIST }}-mm/etc/$f
|
||||
fi
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
for log in faillog lastlog; do
|
||||
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /tmp/debian-{{ DIST }}-mm/var/log/$log >&2;then
|
||||
# if the files differ, make sure they are all zeroes
|
||||
cmp -n $(stat -c %s /tmp/debian-{{ DIST }}-debootstrap/var/log/$log) /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /dev/zero >&2
|
||||
cmp -n $(stat -c %s /tmp/debian-{{ DIST }}-mm/var/log/$log) /tmp/debian-{{ DIST }}-mm/var/log/$log /dev/zero >&2
|
||||
# then delete them
|
||||
rm /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /tmp/debian-{{ DIST }}-mm/var/log/$log
|
||||
fi
|
||||
done
|
||||
|
||||
# workaround for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=917773
|
||||
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/etc/shadow /tmp/debian-{{ DIST }}-mm/etc/shadow; then
|
||||
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/etc/shadow /tmp/debian-{{ DIST }}-mm/etc/shadow >&2; then
|
||||
echo patching /etc/shadow on {{ DIST }} {{ VARIANT }} >&2
|
||||
awk -v FS=: -v OFS=: -v SDE={{ SOURCE_DATE_EPOCH }} '{ print $1,$2,int(SDE/60/60/24),$4,$5,$6,$7,$8,$9 }' < /tmp/debian-{{ DIST }}-mm/etc/shadow > /tmp/debian-{{ DIST }}-mm/etc/shadow.bak
|
||||
cat /tmp/debian-{{ DIST }}-mm/etc/shadow.bak > /tmp/debian-{{ DIST }}-mm/etc/shadow
|
||||
|
@ -178,7 +190,7 @@ if ! cmp /tmp/debian-{{ DIST }}-debootstrap/etc/shadow /tmp/debian-{{ DIST }}-mm
|
|||
else
|
||||
echo no difference for /etc/shadow on {{ DIST }} {{ VARIANT }} >&2
|
||||
fi
|
||||
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/etc/shadow- /tmp/debian-{{ DIST }}-mm/etc/shadow-; then
|
||||
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/etc/shadow- /tmp/debian-{{ DIST }}-mm/etc/shadow- >&2; then
|
||||
echo patching /etc/shadow- on {{ DIST }} {{ VARIANT }} >&2
|
||||
awk -v FS=: -v OFS=: -v SDE={{ SOURCE_DATE_EPOCH }} '{ print $1,$2,int(SDE/60/60/24),$4,$5,$6,$7,$8,$9 }' < /tmp/debian-{{ DIST }}-mm/etc/shadow- > /tmp/debian-{{ DIST }}-mm/etc/shadow-.bak
|
||||
cat /tmp/debian-{{ DIST }}-mm/etc/shadow-.bak > /tmp/debian-{{ DIST }}-mm/etc/shadow-
|
||||
|
|
13
tests/chrootless-essential
Normal file
13
tests/chrootless-essential
Normal file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
export LC_ALL=C.UTF-8
|
||||
if [ "$(id -u)" -eq 0 ] && ! id -u 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
|
||||
adduser --gecos user --disabled-password user
|
||||
fi
|
||||
prefix=
|
||||
[ "$(id -u)" -eq 0 ] && prefix="runuser -u user --"
|
||||
$prefix fakechroot fakeroot {{ CMD }} --mode=chrootless --variant=essential {{ DIST }} /dev/null {{ MIRROR }}
|
|
@ -13,6 +13,10 @@ homedir=$(runuser -u user -- sh -c 'cd && pwd')
|
|||
# apt:test/integration/test-apt-key
|
||||
TMPDIR_ADD="This is fü\$\$ing cràzy, \$(apt -v)\$!"
|
||||
runuser -u user -- mkdir "$homedir/$TMPDIR_ADD"
|
||||
# make sure the unshared user can traverse into the TMPDIR
|
||||
chmod 711 "$homedir"
|
||||
# set permissions and sticky bit like the real /tmp
|
||||
chmod 1777 "$homedir/$TMPDIR_ADD"
|
||||
runuser -u user -- env TMPDIR="$homedir/$TMPDIR_ADD" {{ CMD }} --mode=unshare --variant=apt \
|
||||
--setup-hook='case "$1" in '"$(quote "$homedir/$TMPDIR_ADD/mmdebstrap.")"'??????????) exit 0;; *) echo "$1"; exit 1;; esac' \
|
||||
{{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
||||
|
|
|
@ -132,6 +132,7 @@ script -qfc "$prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
|
|||
{{ DIST }} /dev/null {{ MIRROR }}" /dev/null
|
||||
|
||||
fail=0
|
||||
[ -r /tmp/log ] || fail=1
|
||||
grep '^E:' /tmp/log && fail=1
|
||||
grep 'Can not write log' /tmp/log && fail=1
|
||||
grep 'posix_openpt' /tmp/log && fail=1
|
||||
|
|
12
tests/error-if-stdout-is-tty
Normal file
12
tests/error-if-stdout-is-tty
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
ret=0
|
||||
script -qfec "{{ CMD }} --mode={{ MODE }} --variant=apt {{ DIST }} - {{ MIRROR }}" /dev/null || ret=$?
|
||||
if [ "$ret" = 0 ]; then
|
||||
echo expected failure but got exit $ret >&2
|
||||
exit 1
|
||||
fi
|
|
@ -1,43 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# regularly check whether more packages work with chrootless:
|
||||
# for p in $(grep-aptavail -F Essential yes -s Package -n | sort -u); do ./mmdebstrap -- mode=chrootless --variant=custom --include=bsdutils,coreutils,debianutils,diffutils,dpkg, findutils,grep,gzip,hostname,init-system-helpers,ncurses-base,ncurses-bin,perl-base,sed, sysvinit-utils,tar,$p unstable /dev/null; done
|
||||
#
|
||||
# see https://bugs.debian.org/cgi-bin/pkgreport.cgi?users=debian-dpkg@lists.debian.org;tag=dpkg- root-support
|
||||
#
|
||||
# base-files: #824594
|
||||
# base-passwd: debconf
|
||||
# bash: depends base-files
|
||||
# bsdutils: ok
|
||||
# coreutils: ok
|
||||
# dash: debconf
|
||||
# debianutils: ok
|
||||
# diffutils: ok
|
||||
# dpkg: ok
|
||||
# findutils: ok
|
||||
# grep: ok
|
||||
# gzip: ok
|
||||
# hostname: ok
|
||||
# init-system-helpers: ok
|
||||
# libc-bin: #983412
|
||||
# login: debconf
|
||||
# ncurses-base: ok
|
||||
# ncurses-bin: ok
|
||||
# perl-base: ok
|
||||
# sed: ok
|
||||
# sysvinit-utils: ok
|
||||
# tar: ok
|
||||
# util-linux: debconf
|
||||
|
||||
set -eu
|
||||
export LC_ALL=C.UTF-8
|
||||
if [ "$(id -u)" -eq 0 ] && ! id -u 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
|
||||
adduser --gecos user --disabled-password user
|
||||
fi
|
||||
prefix=
|
||||
[ "$(id -u)" -eq 0 ] && prefix="runuser -u user --"
|
||||
$prefix {{ CMD }} --mode=chrootless --variant=custom --include=bsdutils,coreutils,debianutils,diffutils,dpkg,findutils,grep,gzip,hostname,init-system-helpers,ncurses-base,ncurses-bin,perl-base,sed,sysvinit-utils,tar {{ DIST }} /dev/null {{ MIRROR }}
|
|
@ -10,12 +10,12 @@ adduser --gecos user --disabled-password user
|
|||
echo user:100000:65536 | cmp /etc/subuid -
|
||||
echo user:100000:65536 | cmp /etc/subgid -
|
||||
sysctl -w kernel.unprivileged_userns_clone=1
|
||||
# include iputils-ping so that we can verify that taridshift does not remove
|
||||
# include iputils-ping so that we can verify that tarfilter does not remove
|
||||
# extended attributes
|
||||
# run through tarshift no-op to create a tarball that should be bit-by-bit
|
||||
# identical to a round trip through "taridshift X" and "taridshift -X"
|
||||
# identical to a round trip through "tarfilter --idshift X" and "tarfilter --idshift -X"
|
||||
runuser -u user -- {{ CMD }} --mode=unshare --variant=apt --include=iputils-ping {{ DIST }} - {{ MIRROR }} \
|
||||
| ./taridshift 0 > /tmp/debian-chroot.tar
|
||||
| ./tarfilter --idshift 0 > /tmp/debian-chroot.tar
|
||||
# make sure that xattrs are set in the original tarball
|
||||
mkdir /tmp/debian-chroot
|
||||
tar --xattrs --xattrs-include='*' --directory /tmp/debian-chroot -xf /tmp/debian-chroot.tar ./bin/ping
|
||||
|
@ -25,9 +25,9 @@ rm /tmp/debian-chroot/bin/ping
|
|||
rmdir /tmp/debian-chroot/bin
|
||||
rmdir /tmp/debian-chroot
|
||||
# shift the uid/gid forward by 100000 and backward by 100000
|
||||
./taridshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
|
||||
./taridshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
|
||||
# the tarball before and after the roundtrip through taridshift should be bit
|
||||
./tarfilter --idshift 100000 < /tmp/debian-chroot.tar > /tmp/debian-chroot-shifted.tar
|
||||
./tarfilter --idshift -100000 < /tmp/debian-chroot-shifted.tar > /tmp/debian-chroot-shiftedback.tar
|
||||
# the tarball before and after the roundtrip through tarfilter should be bit
|
||||
# by bit identical
|
||||
cmp /tmp/debian-chroot.tar /tmp/debian-chroot-shiftedback.tar
|
||||
# manually adjust uid/gid and compare "tar -t" output
|
11
tests/variant-custom-timeout
Normal file
11
tests/variant-custom-timeout
Normal file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
# mmdebstrap used to hang forever if apt in custom mode failed to resolve
|
||||
# dependencies because a process died without cleaning up its children.
|
||||
# https://bugs.debian.org/1017795
|
||||
ret=0
|
||||
{{ CMD }} --mode={{ MODE }} --variant=custom \
|
||||
--include=this-package-does-not-exist {{ DIST }} /dev/null {{ MIRROR }} || ret=1
|
||||
[ $ret -eq 1 ]
|
Loading…
Reference in a new issue