Compare commits

...

6 commits

5 changed files with 84 additions and 28 deletions

View file

@ -402,6 +402,7 @@ Test: error-if-stdout-is-tty
Test: variant-custom-timeout Test: variant-custom-timeout
Test: include-deb-file Test: include-deb-file
Modes: root unshare fakechroot
Needs-APT-Config: true Needs-APT-Config: true
Test: unshare-include-deb Test: unshare-include-deb

View file

@ -14,6 +14,10 @@ env APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get indextargets --no-release-info -
| sort -u \ | sort -u \
| while read -r path; do | while read -r path; do
mkdir -p "$rootdir/run/mmdebstrap" mkdir -p "$rootdir/run/mmdebstrap"
if [ ! -d "/$path" ]; then
echo "/$path is not an existing directory" >&2
continue
fi
case $MMDEBSTRAP_MODE in case $MMDEBSTRAP_MODE in
root|unshare) root|unshare)
echo "bind-mounting /$path into the chroot" >&2 echo "bind-mounting /$path into the chroot" >&2
@ -22,8 +26,8 @@ env APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get indextargets --no-release-info -
;; ;;
*) *)
echo "copying /$path into the chroot" >&2 echo "copying /$path into the chroot" >&2
mkdir -p "$rootdir/$(dirname "$path")" mkdir -p "$rootdir/$path"
cp -av "/$path" "$rootdir/$(dirname "$path")" "$MMDEBSTRAP_ARGV0" --hook-helper "$rootdir" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" env "$MMDEBSTRAP_VERBOSITY" sync-in "/$path" "/$path" <&"$MMDEBSTRAP_HOOKSOCK" >&"$MMDEBSTRAP_HOOKSOCK"
;; ;;
esac esac
printf '/%s\0' "$path" >> "$rootdir/run/mmdebstrap/file-mirror-automount" printf '/%s\0' "$path" >> "$rootdir/run/mmdebstrap/file-mirror-automount"
@ -47,6 +51,10 @@ for pkg in $MMDEBSTRAP_INCLUDE; do
fi fi
# make path absolute # make path absolute
pkg="$(realpath "$pkg")" pkg="$(realpath "$pkg")"
case "$pkg" in
/*) : ;;
*) echo "path for $pkg is not absolute" >&2; continue;;
esac
mkdir -p "$rootdir/run/mmdebstrap" mkdir -p "$rootdir/run/mmdebstrap"
mkdir -p "$rootdir/$(dirname "$pkg")" mkdir -p "$rootdir/$(dirname "$pkg")"
case $MMDEBSTRAP_MODE in case $MMDEBSTRAP_MODE in
@ -57,7 +65,7 @@ for pkg in $MMDEBSTRAP_INCLUDE; do
;; ;;
*) *)
echo "copying $pkg into the chroot" >&2 echo "copying $pkg into the chroot" >&2
cp -av "$pkg" "$rootdir/$pkg" "$MMDEBSTRAP_ARGV0" --hook-helper "$rootdir" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" env "$MMDEBSTRAP_VERBOSITY" upload "$pkg" "$pkg" <&"$MMDEBSTRAP_HOOKSOCK" >&"$MMDEBSTRAP_HOOKSOCK"
;; ;;
esac esac
printf '/%s\0' "$pkg" >> "$rootdir/run/mmdebstrap/file-mirror-automount" printf '/%s\0' "$pkg" >> "$rootdir/run/mmdebstrap/file-mirror-automount"

View file

@ -1613,6 +1613,9 @@ sub run_hooks {
if (length $ENV{APT_CONFIG}) { if (length $ENV{APT_CONFIG}) {
push @env_opts, "MMDEBSTRAP_APT_CONFIG=$ENV{APT_CONFIG}"; push @env_opts, "MMDEBSTRAP_APT_CONFIG=$ENV{APT_CONFIG}";
} }
# I hook script that wants to call mmdebstrap with --hook-helper needs to
# know how mmdebstrap was executed
push @env_opts, "MMDEBSTRAP_ARGV0=$PROGRAM_NAME";
# Storing the mode is important for hook scripts to potentially change # Storing the mode is important for hook scripts to potentially change
# their behavior depending on the mode. It's also important for when the # their behavior depending on the mode. It's also important for when the
# hook wants to use the mmdebstrap --hook-helper. # hook wants to use the mmdebstrap --hook-helper.
@ -1820,6 +1823,25 @@ sub setup {
run_hooks('setup', $options); run_hooks('setup', $options);
# apt runs dpkg from inside the chroot and directly passes the filename to
# dpkg. Hence, the included files on the outside must be present under the
# same path on the inside. If they are not, dpkg cannot find them.
if (scalar(grep { /^\// } @{ $options->{include} }) > 0) {
my $ret = 0;
foreach my $f (grep { /^\// } @{ $options->{include} }) {
next if -e "$options->{root}/$f";
warning
"path given via --include is not present inside the chroot: $f";
$ret = 1;
}
if ($ret != 0) {
warning("apt runs chrooted dpkg which needs access to the "
. "package paths given via --include inside the chroot.");
warning "maybe try running mmdebstrap with "
. "--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount";
}
}
if (any { $_ eq 'update' } @{ $options->{skip} }) { if (any { $_ eq 'update' } @{ $options->{skip} }) {
info "skipping update as requested"; info "skipping update as requested";
} else { } else {
@ -4442,10 +4464,8 @@ sub main() {
my ($opt_name, $opt_value) = @_; my ($opt_name, $opt_value) = @_;
my $sanitize_path = sub { my $sanitize_path = sub {
my $pkg = shift; my $pkg = shift;
$pkg = abs_path($pkg); $pkg = abs_path($pkg)
if (!defined $pkg) { // error "cannot resolve absolute path of $pkg: $!";
error "cannot resolve absolute path of $pkg: $!";
}
if ($pkg !~ /^\//) { if ($pkg !~ /^\//) {
error "absolute path of $pkg doesn't start with a slash"; error "absolute path of $pkg doesn't start with a slash";
} }
@ -5719,9 +5739,9 @@ sub main() {
); );
waitpid $pid, 0; waitpid $pid, 0;
if ($? != 0) { if ($? != 0) {
warning "no read access for some packages for the unshared user"; warning("apt on the outside is run as the unshared user and "
warning "maybe try running mmdebstrap with " . "needs read access to packages outside the chroot given "
. "--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount"; . "via --include");
} }
} }
@ -6457,8 +6477,9 @@ by this option will be the only ones that get either extracted or installed by
dpkg, respectively. For all other variants, apt is used to install the dpkg, respectively. For all other variants, apt is used to install the
additional packages. Package names are directly passed to apt and thus, you additional packages. Package names are directly passed to apt and thus, you
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
regex for C<pkg>, use apt patterns or pass a path to a .deb package file. See regex for C<pkg>, use apt patterns or pass a path to a .deb package file (see
apt(8) for the supported syntax. below for notes concerning passing the path to a .deb package file in
B<unshare> mode). See apt(8) for the supported syntax.
The option can be specified multiple times and the packages are concatenated in The option can be specified multiple times and the packages are concatenated in
the order in which they are given on the command line. If later list items are the order in which they are given on the command line. If later list items are
@ -6486,6 +6507,22 @@ apt. To add more packages, use multiple B<--include> options. To disable this
detection of patterns and paths, start the argument to B<--include> with a detection of patterns and paths, start the argument to B<--include> with a
comma or whitespace. comma or whitespace.
If you pass the path to a .deb package file using B<--include>, B<mmdebstrap>
will ensure that the path exists. If the path is a relative path, it will
internally by converted to an absolute path. Since apt (outside the chroot)
passes paths to dpkg (on the inside) verbatim, you have to make the .deb
package available under the same path inside the chroot as well or otherwise
dpkg inside the chroot will be unable to access it. This can be achieved using
a setup-hook. A hook that automatically makes the contents of C<file://>
mirrors as well as .deb packages given with B<--include> available inside the
chroot is provided by B<mmdebstrap> as
B<--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount>. This hook
takes care of copying all relevant file to their correct locations and cleans
up those files at the end. In B<unshare> mode, the .deb package paths have to
be accessible by the unshared user as well. This means that the package itself
likely must be made world-readable and all directory components on the path to
it world-executable.
=item B<--components>=I<comp1>[,I<comp2>,...] =item B<--components>=I<comp1>[,I<comp2>,...]
Comma or whitespace separated list of components like main, contrib, non-free Comma or whitespace separated list of components like main, contrib, non-free
@ -6942,11 +6979,13 @@ 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_HOOK> stores which hook is currently run (setup, B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
extract, essential, customize) and C<MMDEBSTRAP_VERBOSITY> stores the numerical extract, essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the
verbosity level (0 for no output, 1 for normal, 2 for verbose and 3 for debug binary with which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores
output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of packages, apt the numerical verbosity level (0 for no output, 1 for normal, 2 for verbose and
patterns or file paths given by the B<--include> option, separated by a comma 3 for debug output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of
and with commas and percent signs in the option values urlencoded. 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
urlencoded.
In special hooks, the paths inside the chroot are relative to the root In special hooks, the paths inside the chroot are relative to the root
directory of the chroot. The path on the outside is relative to current directory of the chroot. The path on the outside is relative to current

View file

@ -5,6 +5,18 @@ export LC_ALL=C.UTF-8
trap "rm -rf /tmp/dummypkg.deb /tmp/dummypkg" EXIT INT TERM trap "rm -rf /tmp/dummypkg.deb /tmp/dummypkg" 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
# instead of obtaining a .deb from our cache, we create a new package because # instead of obtaining a .deb from our cache, we create a new package because
# otherwise apt might decide to download the package with the same name and # otherwise apt might decide to download the package with the same name and
# version from the cache instead of using the local .deb # version from the cache instead of using the local .deb
@ -22,7 +34,7 @@ Description: dummypkg
END END
dpkg-deb --build "/tmp/dummypkg" "/tmp/dummypkg.deb" dpkg-deb --build "/tmp/dummypkg" "/tmp/dummypkg.deb"
{{ CMD }} --variant=apt --include="/tmp/dummypkg.deb" \ $prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include="/tmp/dummypkg.deb" \
--hook-dir=./hooks/file-mirror-automount \ --hook-dir=./hooks/file-mirror-automount \
--customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \ --customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \
{{ DIST }} /dev/null {{ MIRROR }} {{ DIST }} /dev/null {{ MIRROR }}

View file

@ -12,14 +12,10 @@ rm /tmp/debian-chroot/etc/timezone
rm -r /tmp/debian-chroot/usr/share/doc/tzdata rm -r /tmp/debian-chroot/usr/share/doc/tzdata
rm -r /tmp/debian-chroot/usr/share/zoneinfo rm -r /tmp/debian-chroot/usr/share/zoneinfo
rm /tmp/debian-chroot/var/lib/apt/extended_states rm /tmp/debian-chroot/var/lib/apt/extended_states
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.list for p in doc-debian tzdata; do
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.md5sums for f in list md5sums config postinst postrm templates preinst prerm; do
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.list [ -e "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f" ] || continue
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.md5sums rm "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f"
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.config done
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.postinst done
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.postrm
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.templates
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.preinst
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.prerm
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt - tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -