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: include-deb-file
Modes: root unshare fakechroot
Needs-APT-Config: true
Test: unshare-include-deb

View file

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

View file

@ -1613,6 +1613,9 @@ sub run_hooks {
if (length $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
# their behavior depending on the mode. It's also important for when the
# hook wants to use the mmdebstrap --hook-helper.
@ -1820,6 +1823,25 @@ sub setup {
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} }) {
info "skipping update as requested";
} else {
@ -4442,10 +4464,8 @@ sub main() {
my ($opt_name, $opt_value) = @_;
my $sanitize_path = sub {
my $pkg = shift;
$pkg = abs_path($pkg);
if (!defined $pkg) {
error "cannot resolve absolute path of $pkg: $!";
}
$pkg = abs_path($pkg)
// error "cannot resolve absolute path of $pkg: $!";
if ($pkg !~ /^\//) {
error "absolute path of $pkg doesn't start with a slash";
}
@ -5719,9 +5739,9 @@ sub main() {
);
waitpid $pid, 0;
if ($? != 0) {
warning "no read access for some packages for the unshared user";
warning "maybe try running mmdebstrap with "
. "--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount";
warning("apt on the outside is run as the unshared user and "
. "needs read access to packages outside the chroot given "
. "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
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
regex for C<pkg>, use apt patterns or pass a path to a .deb package file. See
apt(8) for the supported syntax.
regex for C<pkg>, use apt patterns or pass a path to a .deb package file (see
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 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
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>,...]
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
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
extract, essential, customize) and C<MMDEBSTRAP_VERBOSITY> stores the numerical
verbosity level (0 for no output, 1 for normal, 2 for verbose and 3 for debug
output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of 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.
extract, essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the
binary with which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores
the numerical verbosity level (0 for no output, 1 for normal, 2 for verbose and
3 for debug output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of
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
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
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
# otherwise apt might decide to download the package with the same name and
# version from the cache instead of using the local .deb
@ -22,7 +34,7 @@ Description: dummypkg
END
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 \
--customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \
{{ 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/zoneinfo
rm /tmp/debian-chroot/var/lib/apt/extended_states
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.list
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.md5sums
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.list
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.md5sums
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.config
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.postinst
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
for p in doc-debian tzdata; do
for f in list md5sums config postinst postrm templates preinst prerm; do
[ -e "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f" ] || continue
rm "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f"
done
done
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -