also re-exec under fakechroot if fakechroot is picked in 'auto' mode

This commit is contained in:
Johannes 'josch' Schauer 2019-03-25 14:35:38 +01:00
parent 3e8a251e1f
commit a69a2d39b8
Signed by untrusted user: josch
GPG key ID: F2CBA5C78FBD83E1

View file

@ -1785,15 +1785,46 @@ sub main() {
error "invalid mode. Choose from " . (join ', ', @valid_modes); error "invalid mode. Choose from " . (join ', ', @valid_modes);
} }
my $check_fakechroot_running = sub {
# test if we are inside fakechroot already
# We fork a child process because setting FAKECHROOT_DETECT seems to
# be an irreversible operation for fakechroot.
my $pid = open my $rfh, '-|' // error "failed to fork(): $!";
if ($pid == 0) {
# with the FAKECHROOT_DETECT environment variable set, any program
# execution will be replaced with the output "fakeroot [version]"
$ENV{FAKECHROOT_DETECT} = 0;
exec 'echo', 'If fakechroot is running, this will not be printed';
}
my $content = do { local $/; <$rfh> };
waitpid $pid, 0;
my $result = 0;
if ($? == 0 and $content =~ /^fakechroot \d\.\d+$/) {
$result = 1;
}
return $result;
};
# figure out the mode to use or test whether the chosen mode is legal # figure out the mode to use or test whether the chosen mode is legal
if ($options->{mode} eq 'auto') { if ($options->{mode} eq 'auto') {
if ($EFFECTIVE_USER_ID == 0) { if (&{$check_fakechroot_running}()) {
# if mmdebstrap is executed inside fakechroot, then we assume the
# user expects fakechroot mode
$options->{mode} = 'fakechroot';
} elsif ($EFFECTIVE_USER_ID == 0) {
# if mmdebstrap is executed as root, we assume the user wants root
# mode
$options->{mode} = 'root'; $options->{mode} = 'root';
} elsif (test_unshare(0)) { } elsif (test_unshare(0)) {
# otherwise, unshare mode is our best option if test_unshare()
# succeeds
$options->{mode} = 'unshare'; $options->{mode} = 'unshare';
} elsif (system('fakechroot --version>/dev/null') == 0) { } elsif (system('fakechroot --version>/dev/null') == 0) {
$options->{mode} = 'fakechroot'; # the next fallback is fakechroot
# exec ourselves again but within fakechroot
exec 'fakechroot', 'fakeroot', $PROGRAM_NAME, @ARGVORIG;
} elsif (system('proot --version>/dev/null') == 0) { } elsif (system('proot --version>/dev/null') == 0) {
# and lastly, proot
$options->{mode} = 'proot'; $options->{mode} = 'proot';
} else { } else {
error "unable to pick chroot mode automatically"; error "unable to pick chroot mode automatically";
@ -1808,19 +1839,7 @@ sub main() {
error "need working proot binary"; error "need working proot binary";
} }
} elsif ($options->{mode} eq 'fakechroot') { } elsif ($options->{mode} eq 'fakechroot') {
# test if we are inside fakechroot already if (&{$check_fakechroot_running}()) {
# We fork a child process because setting FAKECHROOT_DETECT seems to
# be an irreversible operation for fakechroot.
my $pid = open my $rfh, '-|' // error "failed to fork(): $!";
if ($pid == 0) {
# with the FAKECHROOT_DETECT environment variable set, any program
# execution will be replaced with the output "fakeroot [version]"
$ENV{FAKECHROOT_DETECT} = 0;
exec 'echo', 'If fakechroot is running, this will not be printed';
}
my $content = do { local $/; <$rfh> };
waitpid $pid, 0;
if ($? == 0 and $content =~ /^fakechroot \d\.\d+$/) {
# fakechroot is already running # fakechroot is already running
} elsif (system('fakechroot --version>/dev/null') != 0) { } elsif (system('fakechroot --version>/dev/null') != 0) {
error "need working fakechroot binary"; error "need working fakechroot binary";