mmdebstrap/mmdebstrap

9069 lines
391 KiB
Perl
Executable file

#!/usr/bin/perl
#
# © 2018 - 2023 Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# The software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising
# from, out of or in connection with the software or the use or other dealings
# in the software.
use strict;
use warnings;
our $VERSION = '1.5.3';
use English;
use Getopt::Long;
use Pod::Usage;
use File::Copy;
use File::Path qw(make_path);
use File::Temp qw(tempfile tempdir);
use File::Basename;
use File::Find;
use Cwd qw(abs_path getcwd);
require "syscall.ph"; ## no critic (Modules::RequireBarewordIncludes)
require "sys/ioctl.ph"; ## no critic (Modules::RequireBarewordIncludes)
use Fcntl
qw(S_IFCHR S_IFBLK FD_CLOEXEC F_GETFD F_SETFD LOCK_EX O_RDONLY O_DIRECTORY);
use List::Util qw(any none);
use POSIX
qw(SIGINT SIGHUP SIGPIPE SIGTERM SIG_BLOCK SIG_UNBLOCK strftime isatty);
use Carp;
use Term::ANSIColor;
use Socket;
use Time::HiRes;
use Math::BigInt;
use Text::ParseWords;
use Digest::SHA;
use version;
## no critic (InputOutput::RequireBriefOpen)
# from sched.h
# use typeglob constants because "use constant" has several drawback as
# explained in the documentation for the Readonly CPAN module
*CLONE_NEWNS = \0x20000; # mount namespace
*CLONE_NEWUTS = \0x4000000; # utsname
*CLONE_NEWIPC = \0x8000000; # ipc
*CLONE_NEWUSER = \0x10000000; # user
*CLONE_NEWPID = \0x20000000; # pid
*CLONE_NEWNET = \0x40000000; # net
*_LINUX_CAPABILITY_VERSION_3 = \0x20080522;
*CAP_SYS_ADMIN = \21;
*PR_CAPBSET_READ = \23;
# from sys/mount.h
*MS_BIND = \0x1000;
*MS_REC = \0x4000;
*MNT_DETACH = \2;
# uuid_t NameSpace_DNS in rfc4122
*UUID_NS_DNS = \'6ba7b810-9dad-11d1-80b4-00c04fd430c8';
our (
$CLONE_NEWNS, $CLONE_NEWUTS,
$CLONE_NEWIPC, $CLONE_NEWUSER,
$CLONE_NEWPID, $CLONE_NEWNET,
$_LINUX_CAPABILITY_VERSION_3, $CAP_SYS_ADMIN,
$PR_CAPBSET_READ, $MS_BIND,
$MS_REC, $MNT_DETACH,
$UUID_NS_DNS
);
#<<<
# type codes:
# 0 -> normal file
# 1 -> hardlink
# 2 -> symlink
# 3 -> character special
# 4 -> block special
# 5 -> directory
my @linuxdevfiles = (
# file name mode type link target major minor transl.
["./dev/", oct(755), '5', undef, undef, undef, undef],
["./dev/console", oct(666), '3', undef, 5, 1, undef],
["./dev/fd", oct(777), '2', '/proc/self/fd', undef, undef, undef],
["./dev/full", oct(666), '3', undef, 1, 7, undef],
["./dev/null", oct(666), '3', undef, 1, 3, undef],
["./dev/ptmx", oct(666), '3', undef, 5, 2, undef],
["./dev/pts/", oct(755), '5', undef, undef, undef, undef],
["./dev/random", oct(666), '3', undef, 1, 8, undef],
["./dev/shm/", oct(755), '5', undef, undef, undef, undef],
["./dev/stderr", oct(777), '2', '/proc/self/fd/2', undef, undef, undef],
["./dev/stdin", oct(777), '2', '/proc/self/fd/0', undef, undef, undef],
["./dev/stdout", oct(777), '2', '/proc/self/fd/1', undef, undef, undef],
["./dev/tty", oct(666), '3', undef, 5, 0, undef],
["./dev/urandom", oct(666), '3', undef, 1, 9, undef],
["./dev/zero", oct(666), '3', undef, 1, 5, undef],
);
my @hurdfiles = (
# file name mode type link target major minor transl.
['./dev/', oct(755), '5', undef, undef, undef, undef],
['./dev/MAKEDEV', oct(755), '2', '/sbin/MAKEDEV', undef, undef, undef],
['./dev/cd0', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:cd0\0"],
['./dev/cd1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:cd1\0"],
['./dev/com0', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/com0\0device\0com0\0"],
['./dev/com1', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/com1\0device\0com1\0"],
['./dev/com2', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/com2\0device\0com2\0"],
['./dev/com3', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/com3\0device\0com3\0"],
['./dev/cons', oct(600), '0', undef, undef, undef, undef],
['./dev/console', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/console\0device\0console\0"],
['./dev/disk', oct(755), '2', 'rumpdisk', undef, undef, undef],
['./dev/eth0', oct(660), '0', undef, undef, undef,
"/hurd/devnode\0-M\0/dev/net\0eth0\0"],
['./dev/eth1', oct(660), '0', undef, undef, undef,
"/hurd/devnode\0-M\0/dev/net\0eth1\0"],
['./dev/eth2', oct(660), '0', undef, undef, undef,
"/hurd/devnode\0-M\0/dev/net\0eth2\0"],
['./dev/eth3', oct(660), '0', undef, undef, undef,
"/hurd/devnode\0-M\0/dev/net\0eth3\0"],
['./dev/fd', oct(666), '0', undef, undef, undef,
"/hurd/magic\0--directory\0fd\0"],
['./dev/fd0', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0fd0\0"],
['./dev/fd1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0fd1\0"],
['./dev/full', oct(666), '0', undef, undef, undef,
"/hurd/null\0--full\0"],
['./dev/hd0', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0\0"],
['./dev/hd0s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s1\0"],
['./dev/hd0s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s10\0"],
['./dev/hd0s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s11\0"],
['./dev/hd0s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s12\0"],
['./dev/hd0s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s13\0"],
['./dev/hd0s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s14\0"],
['./dev/hd0s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s15\0"],
['./dev/hd0s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s16\0"],
['./dev/hd0s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s2\0"],
['./dev/hd0s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s3\0"],
['./dev/hd0s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s4\0"],
['./dev/hd0s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s5\0"],
['./dev/hd0s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s6\0"],
['./dev/hd0s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s7\0"],
['./dev/hd0s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s8\0"],
['./dev/hd0s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd0s9\0"],
['./dev/hd1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1\0"],
['./dev/hd1s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s1\0"],
['./dev/hd1s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s10\0"],
['./dev/hd1s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s11\0"],
['./dev/hd1s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s12\0"],
['./dev/hd1s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s13\0"],
['./dev/hd1s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s14\0"],
['./dev/hd1s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s15\0"],
['./dev/hd1s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s16\0"],
['./dev/hd1s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s2\0"],
['./dev/hd1s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s3\0"],
['./dev/hd1s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s4\0"],
['./dev/hd1s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s5\0"],
['./dev/hd1s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s6\0"],
['./dev/hd1s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s7\0"],
['./dev/hd1s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s8\0"],
['./dev/hd1s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd1s9\0"],
['./dev/hd2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2\0"],
['./dev/hd2s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s1\0"],
['./dev/hd2s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s10\0"],
['./dev/hd2s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s11\0"],
['./dev/hd2s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s12\0"],
['./dev/hd2s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s13\0"],
['./dev/hd2s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s14\0"],
['./dev/hd2s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s15\0"],
['./dev/hd2s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s16\0"],
['./dev/hd2s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s2\0"],
['./dev/hd2s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s3\0"],
['./dev/hd2s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s4\0"],
['./dev/hd2s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s5\0"],
['./dev/hd2s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s6\0"],
['./dev/hd2s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s7\0"],
['./dev/hd2s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s8\0"],
['./dev/hd2s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd2s9\0"],
['./dev/hd3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3\0"],
['./dev/hd3s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s1\0"],
['./dev/hd3s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s10\0"],
['./dev/hd3s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s11\0"],
['./dev/hd3s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s12\0"],
['./dev/hd3s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s13\0"],
['./dev/hd3s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s14\0"],
['./dev/hd3s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s15\0"],
['./dev/hd3s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s16\0"],
['./dev/hd3s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s2\0"],
['./dev/hd3s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s3\0"],
['./dev/hd3s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s4\0"],
['./dev/hd3s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s5\0"],
['./dev/hd3s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s6\0"],
['./dev/hd3s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s7\0"],
['./dev/hd3s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s8\0"],
['./dev/hd3s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd3s9\0"],
['./dev/hd4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4\0"],
['./dev/hd4s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s1\0"],
['./dev/hd4s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s10\0"],
['./dev/hd4s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s11\0"],
['./dev/hd4s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s12\0"],
['./dev/hd4s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s13\0"],
['./dev/hd4s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s14\0"],
['./dev/hd4s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s15\0"],
['./dev/hd4s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s16\0"],
['./dev/hd4s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s2\0"],
['./dev/hd4s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s3\0"],
['./dev/hd4s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s4\0"],
['./dev/hd4s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s5\0"],
['./dev/hd4s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s6\0"],
['./dev/hd4s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s7\0"],
['./dev/hd4s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s8\0"],
['./dev/hd4s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd4s9\0"],
['./dev/hd5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5\0"],
['./dev/hd5s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s1\0"],
['./dev/hd5s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s10\0"],
['./dev/hd5s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s11\0"],
['./dev/hd5s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s12\0"],
['./dev/hd5s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s13\0"],
['./dev/hd5s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s14\0"],
['./dev/hd5s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s15\0"],
['./dev/hd5s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s16\0"],
['./dev/hd5s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s2\0"],
['./dev/hd5s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s3\0"],
['./dev/hd5s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s4\0"],
['./dev/hd5s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s5\0"],
['./dev/hd5s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s6\0"],
['./dev/hd5s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s7\0"],
['./dev/hd5s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s8\0"],
['./dev/hd5s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0hd5s9\0"],
['./dev/kbd', oct(644), '2', 'cons/kbd', undef, undef, undef],
['./dev/klog', oct(660), '0', undef, undef, undef,
"/hurd/streamio\0kmsg\0"],
['./dev/loop0', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop1', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop2', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop3', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop4', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop5', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop6', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/loop7', oct(640), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/lpr0', oct(660), '0', undef, undef, undef,
"/hurd/streamio\0lpr0\0"],
['./dev/lpr1', oct(660), '0', undef, undef, undef,
"/hurd/streamio\0lpr1\0"],
['./dev/lpr2', oct(660), '0', undef, undef, undef,
"/hurd/streamio\0lpr2\0"],
['./dev/mem', oct(660), '0', undef, undef, undef,
"/hurd/storeio\0--no-cache\0mem\0"],
['./dev/mouse', oct(644), '2', 'cons/mouse', undef, undef, undef],
['./dev/net', oct(755), '2', 'netdde', undef, undef, undef],
['./dev/netdde', oct(660), '0', undef, undef, undef,
"/hurd/netdde\0"],
['./dev/null', oct(666), '0', undef, undef, undef,
"/hurd/null\0"],
['./dev/pseudo-root', oct(640), '4', undef, 0, 0,
"/hurd/storeio\0pseudo-root\0"],
['./dev/ptyp0', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp0\0pty-master\0/dev/ttyp0\0"],
['./dev/ptyp1', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp1\0pty-master\0/dev/ttyp1\0"],
['./dev/ptyp2', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp2\0pty-master\0/dev/ttyp2\0"],
['./dev/ptyp3', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp3\0pty-master\0/dev/ttyp3\0"],
['./dev/ptyp4', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp4\0pty-master\0/dev/ttyp4\0"],
['./dev/ptyp5', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp5\0pty-master\0/dev/ttyp5\0"],
['./dev/ptyp6', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp6\0pty-master\0/dev/ttyp6\0"],
['./dev/ptyp7', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp7\0pty-master\0/dev/ttyp7\0"],
['./dev/ptyp8', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp8\0pty-master\0/dev/ttyp8\0"],
['./dev/ptyp9', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyp9\0pty-master\0/dev/ttyp9\0"],
['./dev/ptypa', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypa\0pty-master\0/dev/ttypa\0"],
['./dev/ptypb', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypb\0pty-master\0/dev/ttypb\0"],
['./dev/ptypc', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypc\0pty-master\0/dev/ttypc\0"],
['./dev/ptypd', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypd\0pty-master\0/dev/ttypd\0"],
['./dev/ptype', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptype\0pty-master\0/dev/ttype\0"],
['./dev/ptypf', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypf\0pty-master\0/dev/ttypf\0"],
['./dev/ptypg', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypg\0pty-master\0/dev/ttypg\0"],
['./dev/ptyph', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyph\0pty-master\0/dev/ttyph\0"],
['./dev/ptypi', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypi\0pty-master\0/dev/ttypi\0"],
['./dev/ptypj', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypj\0pty-master\0/dev/ttypj\0"],
['./dev/ptypk', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypk\0pty-master\0/dev/ttypk\0"],
['./dev/ptypl', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypl\0pty-master\0/dev/ttypl\0"],
['./dev/ptypm', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypm\0pty-master\0/dev/ttypm\0"],
['./dev/ptypn', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypn\0pty-master\0/dev/ttypn\0"],
['./dev/ptypo', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypo\0pty-master\0/dev/ttypo\0"],
['./dev/ptypp', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypp\0pty-master\0/dev/ttypp\0"],
['./dev/ptypq', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypq\0pty-master\0/dev/ttypq\0"],
['./dev/ptypr', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypr\0pty-master\0/dev/ttypr\0"],
['./dev/ptyps', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyps\0pty-master\0/dev/ttyps\0"],
['./dev/ptypt', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypt\0pty-master\0/dev/ttypt\0"],
['./dev/ptypu', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypu\0pty-master\0/dev/ttypu\0"],
['./dev/ptypv', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptypv\0pty-master\0/dev/ttypv\0"],
['./dev/ptyq0', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq0\0pty-master\0/dev/ttyq0\0"],
['./dev/ptyq1', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq1\0pty-master\0/dev/ttyq1\0"],
['./dev/ptyq2', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq2\0pty-master\0/dev/ttyq2\0"],
['./dev/ptyq3', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq3\0pty-master\0/dev/ttyq3\0"],
['./dev/ptyq4', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq4\0pty-master\0/dev/ttyq4\0"],
['./dev/ptyq5', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq5\0pty-master\0/dev/ttyq5\0"],
['./dev/ptyq6', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq6\0pty-master\0/dev/ttyq6\0"],
['./dev/ptyq7', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq7\0pty-master\0/dev/ttyq7\0"],
['./dev/ptyq8', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq8\0pty-master\0/dev/ttyq8\0"],
['./dev/ptyq9', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyq9\0pty-master\0/dev/ttyq9\0"],
['./dev/ptyqa', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqa\0pty-master\0/dev/ttyqa\0"],
['./dev/ptyqb', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqb\0pty-master\0/dev/ttyqb\0"],
['./dev/ptyqc', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqc\0pty-master\0/dev/ttyqc\0"],
['./dev/ptyqd', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqd\0pty-master\0/dev/ttyqd\0"],
['./dev/ptyqe', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqe\0pty-master\0/dev/ttyqe\0"],
['./dev/ptyqf', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqf\0pty-master\0/dev/ttyqf\0"],
['./dev/ptyqg', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqg\0pty-master\0/dev/ttyqg\0"],
['./dev/ptyqh', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqh\0pty-master\0/dev/ttyqh\0"],
['./dev/ptyqi', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqi\0pty-master\0/dev/ttyqi\0"],
['./dev/ptyqj', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqj\0pty-master\0/dev/ttyqj\0"],
['./dev/ptyqk', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqk\0pty-master\0/dev/ttyqk\0"],
['./dev/ptyql', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyql\0pty-master\0/dev/ttyql\0"],
['./dev/ptyqm', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqm\0pty-master\0/dev/ttyqm\0"],
['./dev/ptyqn', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqn\0pty-master\0/dev/ttyqn\0"],
['./dev/ptyqo', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqo\0pty-master\0/dev/ttyqo\0"],
['./dev/ptyqp', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqp\0pty-master\0/dev/ttyqp\0"],
['./dev/ptyqq', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqq\0pty-master\0/dev/ttyqq\0"],
['./dev/ptyqr', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqr\0pty-master\0/dev/ttyqr\0"],
['./dev/ptyqs', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqs\0pty-master\0/dev/ttyqs\0"],
['./dev/ptyqt', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqt\0pty-master\0/dev/ttyqt\0"],
['./dev/ptyqu', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqu\0pty-master\0/dev/ttyqu\0"],
['./dev/ptyqv', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ptyqv\0pty-master\0/dev/ttyqv\0"],
['./dev/random', oct(644), '0', undef, undef, undef,
"/hurd/random\0--seed-file\0/var/lib/random-seed\0"],
['./dev/rumpdisk', oct(660), '0', undef, undef, undef,
"/hurd/rumpdisk\0"],
['./dev/sd0', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0\0"],
['./dev/sd0s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s1\0"],
['./dev/sd0s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s10\0"],
['./dev/sd0s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s11\0"],
['./dev/sd0s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s12\0"],
['./dev/sd0s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s13\0"],
['./dev/sd0s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s14\0"],
['./dev/sd0s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s15\0"],
['./dev/sd0s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s16\0"],
['./dev/sd0s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s2\0"],
['./dev/sd0s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s3\0"],
['./dev/sd0s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s4\0"],
['./dev/sd0s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s5\0"],
['./dev/sd0s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s6\0"],
['./dev/sd0s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s7\0"],
['./dev/sd0s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s8\0"],
['./dev/sd0s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd0s9\0"],
['./dev/sd1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1\0"],
['./dev/sd1s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s1\0"],
['./dev/sd1s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s10\0"],
['./dev/sd1s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s11\0"],
['./dev/sd1s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s12\0"],
['./dev/sd1s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s13\0"],
['./dev/sd1s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s14\0"],
['./dev/sd1s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s15\0"],
['./dev/sd1s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s16\0"],
['./dev/sd1s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s2\0"],
['./dev/sd1s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s3\0"],
['./dev/sd1s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s4\0"],
['./dev/sd1s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s5\0"],
['./dev/sd1s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s6\0"],
['./dev/sd1s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s7\0"],
['./dev/sd1s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s8\0"],
['./dev/sd1s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd1s9\0"],
['./dev/sd2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2\0"],
['./dev/sd2s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s1\0"],
['./dev/sd2s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s10\0"],
['./dev/sd2s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s11\0"],
['./dev/sd2s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s12\0"],
['./dev/sd2s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s13\0"],
['./dev/sd2s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s14\0"],
['./dev/sd2s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s15\0"],
['./dev/sd2s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s16\0"],
['./dev/sd2s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s2\0"],
['./dev/sd2s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s3\0"],
['./dev/sd2s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s4\0"],
['./dev/sd2s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s5\0"],
['./dev/sd2s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s6\0"],
['./dev/sd2s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s7\0"],
['./dev/sd2s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s8\0"],
['./dev/sd2s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd2s9\0"],
['./dev/sd3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3\0"],
['./dev/sd3s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s1\0"],
['./dev/sd3s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s10\0"],
['./dev/sd3s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s11\0"],
['./dev/sd3s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s12\0"],
['./dev/sd3s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s13\0"],
['./dev/sd3s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s14\0"],
['./dev/sd3s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s15\0"],
['./dev/sd3s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s16\0"],
['./dev/sd3s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s2\0"],
['./dev/sd3s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s3\0"],
['./dev/sd3s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s4\0"],
['./dev/sd3s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s5\0"],
['./dev/sd3s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s6\0"],
['./dev/sd3s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s7\0"],
['./dev/sd3s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s8\0"],
['./dev/sd3s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd3s9\0"],
['./dev/sd4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4\0"],
['./dev/sd4s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s1\0"],
['./dev/sd4s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s10\0"],
['./dev/sd4s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s11\0"],
['./dev/sd4s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s12\0"],
['./dev/sd4s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s13\0"],
['./dev/sd4s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s14\0"],
['./dev/sd4s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s15\0"],
['./dev/sd4s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s16\0"],
['./dev/sd4s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s2\0"],
['./dev/sd4s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s3\0"],
['./dev/sd4s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s4\0"],
['./dev/sd4s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s5\0"],
['./dev/sd4s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s6\0"],
['./dev/sd4s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s7\0"],
['./dev/sd4s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s8\0"],
['./dev/sd4s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd4s9\0"],
['./dev/sd5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5\0"],
['./dev/sd5s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s1\0"],
['./dev/sd5s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s10\0"],
['./dev/sd5s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s11\0"],
['./dev/sd5s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s12\0"],
['./dev/sd5s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s13\0"],
['./dev/sd5s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s14\0"],
['./dev/sd5s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s15\0"],
['./dev/sd5s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s16\0"],
['./dev/sd5s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s2\0"],
['./dev/sd5s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s3\0"],
['./dev/sd5s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s4\0"],
['./dev/sd5s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s5\0"],
['./dev/sd5s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s6\0"],
['./dev/sd5s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s7\0"],
['./dev/sd5s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s8\0"],
['./dev/sd5s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0sd5s9\0"],
['./dev/shm', oct(644), '2', '/tmp', undef, undef, undef],
['./dev/stderr', oct(755), '2', 'fd/2', undef, undef, undef],
['./dev/stdin', oct(755), '2', 'fd/0', undef, undef, undef],
['./dev/stdout', oct(755), '2', 'fd/1', undef, undef, undef],
['./dev/time', oct(644), '0', undef, undef, undef,
"/hurd/storeio\0--no-cache\0time\0"],
['./dev/tty', oct(666), '0', undef, undef, undef,
"/hurd/magic\0tty\0"],
['./dev/tty1', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/tty1\0hurdio\0/dev/vcs/1/console\0"],
['./dev/tty2', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/tty2\0hurdio\0/dev/vcs/2/console\0"],
['./dev/tty3', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/tty3\0hurdio\0/dev/vcs/3/console\0"],
['./dev/tty4', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/tty4\0hurdio\0/dev/vcs/4/console\0"],
['./dev/tty5', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/tty5\0hurdio\0/dev/vcs/5/console\0"],
['./dev/tty6', oct(600), '0', undef, undef, undef,
"/hurd/term\0/dev/tty6\0hurdio\0/dev/vcs/6/console\0"],
['./dev/ttyp0', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp0\0pty-slave\0/dev/ptyp0\0"],
['./dev/ttyp1', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp1\0pty-slave\0/dev/ptyp1\0"],
['./dev/ttyp2', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp2\0pty-slave\0/dev/ptyp2\0"],
['./dev/ttyp3', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp3\0pty-slave\0/dev/ptyp3\0"],
['./dev/ttyp4', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp4\0pty-slave\0/dev/ptyp4\0"],
['./dev/ttyp5', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp5\0pty-slave\0/dev/ptyp5\0"],
['./dev/ttyp6', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp6\0pty-slave\0/dev/ptyp6\0"],
['./dev/ttyp7', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp7\0pty-slave\0/dev/ptyp7\0"],
['./dev/ttyp8', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp8\0pty-slave\0/dev/ptyp8\0"],
['./dev/ttyp9', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyp9\0pty-slave\0/dev/ptyp9\0"],
['./dev/ttypa', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypa\0pty-slave\0/dev/ptypa\0"],
['./dev/ttypb', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypb\0pty-slave\0/dev/ptypb\0"],
['./dev/ttypc', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypc\0pty-slave\0/dev/ptypc\0"],
['./dev/ttypd', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypd\0pty-slave\0/dev/ptypd\0"],
['./dev/ttype', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttype\0pty-slave\0/dev/ptype\0"],
['./dev/ttypf', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypf\0pty-slave\0/dev/ptypf\0"],
['./dev/ttypg', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypg\0pty-slave\0/dev/ptypg\0"],
['./dev/ttyph', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyph\0pty-slave\0/dev/ptyph\0"],
['./dev/ttypi', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypi\0pty-slave\0/dev/ptypi\0"],
['./dev/ttypj', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypj\0pty-slave\0/dev/ptypj\0"],
['./dev/ttypk', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypk\0pty-slave\0/dev/ptypk\0"],
['./dev/ttypl', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypl\0pty-slave\0/dev/ptypl\0"],
['./dev/ttypm', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypm\0pty-slave\0/dev/ptypm\0"],
['./dev/ttypn', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypn\0pty-slave\0/dev/ptypn\0"],
['./dev/ttypo', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypo\0pty-slave\0/dev/ptypo\0"],
['./dev/ttypp', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypp\0pty-slave\0/dev/ptypp\0"],
['./dev/ttypq', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypq\0pty-slave\0/dev/ptypq\0"],
['./dev/ttypr', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypr\0pty-slave\0/dev/ptypr\0"],
['./dev/ttyps', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyps\0pty-slave\0/dev/ptyps\0"],
['./dev/ttypt', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypt\0pty-slave\0/dev/ptypt\0"],
['./dev/ttypu', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypu\0pty-slave\0/dev/ptypu\0"],
['./dev/ttypv', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttypv\0pty-slave\0/dev/ptypv\0"],
['./dev/ttyq0', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq0\0pty-slave\0/dev/ptyq0\0"],
['./dev/ttyq1', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq1\0pty-slave\0/dev/ptyq1\0"],
['./dev/ttyq2', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq2\0pty-slave\0/dev/ptyq2\0"],
['./dev/ttyq3', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq3\0pty-slave\0/dev/ptyq3\0"],
['./dev/ttyq4', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq4\0pty-slave\0/dev/ptyq4\0"],
['./dev/ttyq5', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq5\0pty-slave\0/dev/ptyq5\0"],
['./dev/ttyq6', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq6\0pty-slave\0/dev/ptyq6\0"],
['./dev/ttyq7', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq7\0pty-slave\0/dev/ptyq7\0"],
['./dev/ttyq8', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq8\0pty-slave\0/dev/ptyq8\0"],
['./dev/ttyq9', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyq9\0pty-slave\0/dev/ptyq9\0"],
['./dev/ttyqa', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqa\0pty-slave\0/dev/ptyqa\0"],
['./dev/ttyqb', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqb\0pty-slave\0/dev/ptyqb\0"],
['./dev/ttyqc', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqc\0pty-slave\0/dev/ptyqc\0"],
['./dev/ttyqd', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqd\0pty-slave\0/dev/ptyqd\0"],
['./dev/ttyqe', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqe\0pty-slave\0/dev/ptyqe\0"],
['./dev/ttyqf', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqf\0pty-slave\0/dev/ptyqf\0"],
['./dev/ttyqg', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqg\0pty-slave\0/dev/ptyqg\0"],
['./dev/ttyqh', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqh\0pty-slave\0/dev/ptyqh\0"],
['./dev/ttyqi', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqi\0pty-slave\0/dev/ptyqi\0"],
['./dev/ttyqj', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqj\0pty-slave\0/dev/ptyqj\0"],
['./dev/ttyqk', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqk\0pty-slave\0/dev/ptyqk\0"],
['./dev/ttyql', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyql\0pty-slave\0/dev/ptyql\0"],
['./dev/ttyqm', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqm\0pty-slave\0/dev/ptyqm\0"],
['./dev/ttyqn', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqn\0pty-slave\0/dev/ptyqn\0"],
['./dev/ttyqo', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqo\0pty-slave\0/dev/ptyqo\0"],
['./dev/ttyqp', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqp\0pty-slave\0/dev/ptyqp\0"],
['./dev/ttyqq', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqq\0pty-slave\0/dev/ptyqq\0"],
['./dev/ttyqr', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqr\0pty-slave\0/dev/ptyqr\0"],
['./dev/ttyqs', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqs\0pty-slave\0/dev/ptyqs\0"],
['./dev/ttyqt', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqt\0pty-slave\0/dev/ptyqt\0"],
['./dev/ttyqu', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqu\0pty-slave\0/dev/ptyqu\0"],
['./dev/ttyqv', oct(666), '0', undef, undef, undef,
"/hurd/term\0/dev/ttyqv\0pty-slave\0/dev/ptyqv\0"],
['./dev/urandom', oct(755), '2', 'random', undef, undef,
"/hurd/random\0--seed-file\0/var/lib/random-seed\0--fast\0"],
['./dev/vcs', oct(600), '0', undef, undef, undef,
"/hurd/console\0"],
['./dev/wd0', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:wd0\0"],
['./dev/wd0s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:1:device:@/dev/disk:wd0\0"],
['./dev/wd0s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:10:device:@/dev/disk:wd0\0"],
['./dev/wd0s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:11:device:@/dev/disk:wd0\0"],
['./dev/wd0s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:12:device:@/dev/disk:wd0\0"],
['./dev/wd0s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:13:device:@/dev/disk:wd0\0"],
['./dev/wd0s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:14:device:@/dev/disk:wd0\0"],
['./dev/wd0s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:15:device:@/dev/disk:wd0\0"],
['./dev/wd0s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:16:device:@/dev/disk:wd0\0"],
['./dev/wd0s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:2:device:@/dev/disk:wd0\0"],
['./dev/wd0s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:3:device:@/dev/disk:wd0\0"],
['./dev/wd0s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:4:device:@/dev/disk:wd0\0"],
['./dev/wd0s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:5:device:@/dev/disk:wd0\0"],
['./dev/wd0s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:6:device:@/dev/disk:wd0\0"],
['./dev/wd0s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:7:device:@/dev/disk:wd0\0"],
['./dev/wd0s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:8:device:@/dev/disk:wd0\0"],
['./dev/wd0s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:9:device:@/dev/disk:wd0\0"],
['./dev/wd1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:wd1\0"],
['./dev/wd1s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:1:device:@/dev/disk:wd1\0"],
['./dev/wd1s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:10:device:@/dev/disk:wd1\0"],
['./dev/wd1s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:11:device:@/dev/disk:wd1\0"],
['./dev/wd1s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:12:device:@/dev/disk:wd1\0"],
['./dev/wd1s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:13:device:@/dev/disk:wd1\0"],
['./dev/wd1s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:14:device:@/dev/disk:wd1\0"],
['./dev/wd1s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:15:device:@/dev/disk:wd1\0"],
['./dev/wd1s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:16:device:@/dev/disk:wd1\0"],
['./dev/wd1s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:2:device:@/dev/disk:wd1\0"],
['./dev/wd1s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:3:device:@/dev/disk:wd1\0"],
['./dev/wd1s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:4:device:@/dev/disk:wd1\0"],
['./dev/wd1s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:5:device:@/dev/disk:wd1\0"],
['./dev/wd1s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:6:device:@/dev/disk:wd1\0"],
['./dev/wd1s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:7:device:@/dev/disk:wd1\0"],
['./dev/wd1s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:8:device:@/dev/disk:wd1\0"],
['./dev/wd1s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:9:device:@/dev/disk:wd1\0"],
['./dev/wd2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:wd2\0"],
['./dev/wd2s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:1:device:@/dev/disk:wd2\0"],
['./dev/wd2s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:10:device:@/dev/disk:wd2\0"],
['./dev/wd2s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:11:device:@/dev/disk:wd2\0"],
['./dev/wd2s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:12:device:@/dev/disk:wd2\0"],
['./dev/wd2s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:13:device:@/dev/disk:wd2\0"],
['./dev/wd2s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:14:device:@/dev/disk:wd2\0"],
['./dev/wd2s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:15:device:@/dev/disk:wd2\0"],
['./dev/wd2s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:16:device:@/dev/disk:wd2\0"],
['./dev/wd2s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:2:device:@/dev/disk:wd2\0"],
['./dev/wd2s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:3:device:@/dev/disk:wd2\0"],
['./dev/wd2s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:4:device:@/dev/disk:wd2\0"],
['./dev/wd2s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:5:device:@/dev/disk:wd2\0"],
['./dev/wd2s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:6:device:@/dev/disk:wd2\0"],
['./dev/wd2s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:7:device:@/dev/disk:wd2\0"],
['./dev/wd2s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:8:device:@/dev/disk:wd2\0"],
['./dev/wd2s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:9:device:@/dev/disk:wd2\0"],
['./dev/wd3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:wd3\0"],
['./dev/wd3s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:1:device:@/dev/disk:wd3\0"],
['./dev/wd3s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:10:device:@/dev/disk:wd3\0"],
['./dev/wd3s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:11:device:@/dev/disk:wd3\0"],
['./dev/wd3s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:12:device:@/dev/disk:wd3\0"],
['./dev/wd3s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:13:device:@/dev/disk:wd3\0"],
['./dev/wd3s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:14:device:@/dev/disk:wd3\0"],
['./dev/wd3s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:15:device:@/dev/disk:wd3\0"],
['./dev/wd3s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:16:device:@/dev/disk:wd3\0"],
['./dev/wd3s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:2:device:@/dev/disk:wd3\0"],
['./dev/wd3s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:3:device:@/dev/disk:wd3\0"],
['./dev/wd3s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:4:device:@/dev/disk:wd3\0"],
['./dev/wd3s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:5:device:@/dev/disk:wd3\0"],
['./dev/wd3s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:6:device:@/dev/disk:wd3\0"],
['./dev/wd3s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:7:device:@/dev/disk:wd3\0"],
['./dev/wd3s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:8:device:@/dev/disk:wd3\0"],
['./dev/wd3s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:9:device:@/dev/disk:wd3\0"],
['./dev/wd4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:wd4\0"],
['./dev/wd4s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:1:device:@/dev/disk:wd4\0"],
['./dev/wd4s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:10:device:@/dev/disk:wd4\0"],
['./dev/wd4s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:11:device:@/dev/disk:wd4\0"],
['./dev/wd4s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:12:device:@/dev/disk:wd4\0"],
['./dev/wd4s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:13:device:@/dev/disk:wd4\0"],
['./dev/wd4s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:14:device:@/dev/disk:wd4\0"],
['./dev/wd4s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:15:device:@/dev/disk:wd4\0"],
['./dev/wd4s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:16:device:@/dev/disk:wd4\0"],
['./dev/wd4s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:2:device:@/dev/disk:wd4\0"],
['./dev/wd4s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:3:device:@/dev/disk:wd4\0"],
['./dev/wd4s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:4:device:@/dev/disk:wd4\0"],
['./dev/wd4s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:5:device:@/dev/disk:wd4\0"],
['./dev/wd4s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:6:device:@/dev/disk:wd4\0"],
['./dev/wd4s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:7:device:@/dev/disk:wd4\0"],
['./dev/wd4s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:8:device:@/dev/disk:wd4\0"],
['./dev/wd4s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:9:device:@/dev/disk:wd4\0"],
['./dev/wd5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0@/dev/disk:wd5\0"],
['./dev/wd5s1', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:1:device:@/dev/disk:wd5\0"],
['./dev/wd5s10', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:10:device:@/dev/disk:wd5\0"],
['./dev/wd5s11', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:11:device:@/dev/disk:wd5\0"],
['./dev/wd5s12', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:12:device:@/dev/disk:wd5\0"],
['./dev/wd5s13', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:13:device:@/dev/disk:wd5\0"],
['./dev/wd5s14', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:14:device:@/dev/disk:wd5\0"],
['./dev/wd5s15', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:15:device:@/dev/disk:wd5\0"],
['./dev/wd5s16', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:16:device:@/dev/disk:wd5\0"],
['./dev/wd5s2', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:2:device:@/dev/disk:wd5\0"],
['./dev/wd5s3', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:3:device:@/dev/disk:wd5\0"],
['./dev/wd5s4', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:4:device:@/dev/disk:wd5\0"],
['./dev/wd5s5', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:5:device:@/dev/disk:wd5\0"],
['./dev/wd5s6', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:6:device:@/dev/disk:wd5\0"],
['./dev/wd5s7', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:7:device:@/dev/disk:wd5\0"],
['./dev/wd5s8', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:8:device:@/dev/disk:wd5\0"],
['./dev/wd5s9', oct(640), '0', undef, undef, undef,
"/hurd/storeio\0-T\0typed\0part:9:device:@/dev/disk:wd5\0"],
['./dev/xconsole', oct(755), '2', '/run/xconsole', undef, undef, undef],
['./dev/zero', oct(666), '0', undef, undef, undef,
"/bin/nullauth\0--\0/hurd/storeio\0-Tzero\0"],
# file name mode type link tgt major minor transl.
['./servers/', oct(755), '5', undef, undef, undef, undef],
['./servers/acpi', oct(644), '0', undef, undef, undef,
"/hurd/acpi\0"],
['./servers/bus/', oct(755), '5', undef, undef, undef, undef],
['./servers/bus/pci/', oct(755), '5', undef, undef, undef,
"/hurd/pci-arbiter\0"],
['./servers/crash', oct(644), '2', 'crash-dump-core', undef, undef,
undef],
['./servers/crash-dump-core', oct(644), '0', undef, undef, undef,
"/hurd/crash\0--dump-core\0"],
['./servers/crash-kill', oct(644), '0', undef, undef, undef,
"/hurd/crash\0--kill\0"],
['./servers/crash-suspend', oct(644), '0', undef, undef, undef,
"/hurd/crash\0--suspend\0"],
['./servers/default-pager', oct(755), '0', undef, undef, undef,
"/hurd/proxy-defpager\0"],
['./servers/exec', oct(644), '0', undef, undef, undef,
"/hurd/exec\0"],
['./servers/password', oct(644), '0', undef, undef, undef,
"/hurd/password\0"],
['./servers/shutdown', oct(644), '0', undef, undef, undef,
"/hurd/shutdown\0"],
['./servers/socket/', oct(755), '5', undef, undef, undef, undef],
['./servers/socket/1', oct(644), '0', undef, undef, undef,
"/hurd/pflocal\0"],
['./servers/socket/2', oct(644), '0', undef, undef, undef,
"/hurd/pfinet\0-6\0/servers/socket/26\0"],
['./servers/socket/26', oct(644), '0', undef, undef, undef,
"/hurd/pfinet\0-4\0/servers/socket/2\0"],
['./servers/socket/inet', oct(644), '2', "2", undef, undef, undef],
['./servers/socket/inet6', oct(644), '2', "26", undef, undef, undef],
['./servers/socket/local', oct(644), '2', "1", undef, undef, undef],
['./servers/startup', oct(644), '0', undef, undef, undef, undef]
);
#>>>
# verbosity levels:
# 0 -> print nothing
# 1 -> normal output and progress bars
# 2 -> verbose output
# 3 -> debug output
my $verbosity_level = 1;
my $is_covering = 0;
{
# make $@ local, so we don't print "Undefined subroutine called"
# in other parts where we evaluate $@
local $@ = '';
$is_covering = !!(eval { Devel::Cover::get_coverage() });
}
# the reason why Perl::Critic warns about this is, that it suspects that the
# programmer wants to implement a test whether the terminal is interactive or
# not, in which case, complex interactions with the magic *ARGV indeed make it
# advisable to use IO::Interactive. In our case, we do not want to create an
# interactivity check but just want to check whether STDERR is opened to a tty,
# so our use of -t is fine and not "fragile and complicated" as is written in
# the description of InputOutput::ProhibitInteractiveTest. Also see
# https://github.com/Perl-Critic/Perl-Critic/issues/918
sub stderr_is_tty() {
## no critic (InputOutput::ProhibitInteractiveTest)
if (-t STDERR) {
return 1;
} else {
return 0;
}
}
sub debug {
if ($verbosity_level < 3) {
return;
}
my $msg = shift;
my ($package, $filename, $line) = caller;
$msg = "D: $PID $line $msg";
if (stderr_is_tty()) {
$msg = colored($msg, 'clear');
}
print STDERR "$msg\n";
return;
}
sub info {
if ($verbosity_level == 0) {
return;
}
my $msg = shift;
if ($verbosity_level >= 3) {
my ($package, $filename, $line) = caller;
$msg = "$PID $line $msg";
}
$msg = "I: $msg";
if (stderr_is_tty()) {
$msg = colored($msg, 'green');
}
print STDERR "$msg\n";
return;
}
sub warning {
if ($verbosity_level == 0) {
return;
}
my $msg = shift;
$msg = "W: $msg";
if (stderr_is_tty()) {
$msg = colored($msg, 'bold yellow');
}
print STDERR "$msg\n";
return;
}
sub error {
# if error() is called with the string from a previous error() that was
# caught inside an eval(), then the string will have a newline which we
# are stripping here
chomp(my $msg = shift);
$msg = "E: $msg";
if (stderr_is_tty()) {
$msg = colored($msg, 'bold red');
}
if ($verbosity_level == 3) {
croak $msg; # produces a backtrace
} else {
die "$msg\n";
}
}
# The encoding of dev_t is MMMM Mmmm mmmM MMmm, where M is a hex digit of
# the major number and m is a hex digit of the minor number.
sub major {
my $rdev = shift;
my $right
= Math::BigInt->from_hex("0x00000000000fff00")->band($rdev)->brsft(8);
my $left
= Math::BigInt->from_hex("0xfffff00000000000")->band($rdev)->brsft(32);
return $right->bior($left);
}
sub minor {
my $rdev = shift;
my $right = Math::BigInt->from_hex("0x00000000000000ff")->band($rdev);
my $left
= Math::BigInt->from_hex("0x00000ffffff00000")->band($rdev)->brsft(12);
return $right->bior($left);
}
sub can_execute {
my $tool = shift;
my $verbose = shift // '--version';
my $pid = open my $fh, '-|' // return 0;
if ($pid == 0) {
open(STDERR, '>&', STDOUT) or die;
exec {$tool} $tool, $verbose or die;
}
chomp(
my $content = do { local $/; <$fh> }
);
close $fh;
if ($? != 0) {
return 0;
}
if (length $content == 0) {
return 0;
}
return 1;
}
# check whether a directory is mounted by comparing the device number of the
# directory itself with its parent
sub is_mountpoint {
my $dir = shift;
if (!-e $dir) {
return 0;
}
my @a = stat "$dir/.";
my @b = stat "$dir/..";
# if the device number is different, then the directory must be mounted
if ($a[0] != $b[0]) {
return 1;
}
# if the inode number is the same, then the directory must be mounted
if ($a[1] == $b[1]) {
return 1;
}
return 0;
}
# tar cannot figure out the decompression program when receiving data on
# standard input, thus we do it ourselves. This is copied from tar's
# src/suffix.c
sub get_tar_compressor {
my $filename = shift;
if ($filename eq '-') {
return;
} elsif ($filename =~ /\.tar$/) {
return;
} elsif ($filename =~ /\.(gz|tgz|taz)$/) {
return ['gzip'];
} elsif ($filename =~ /\.(Z|taZ)$/) {
return ['compress'];
} elsif ($filename =~ /\.(bz2|tbz|tbz2|tz2)$/) {
return ['bzip2'];
} elsif ($filename =~ /\.lz$/) {
return ['lzip'];
} elsif ($filename =~ /\.(lzma|tlz)$/) {
return ['lzma'];
} elsif ($filename =~ /\.lzo$/) {
return ['lzop'];
} elsif ($filename =~ /\.lz4$/) {
return ['lz4'];
} elsif ($filename =~ /\.(xz|txz)$/) {
return ['xz'];
} elsif ($filename =~ /\.zst$/) {
return ['zstd'];
}
return;
}
# avoid dependency on String::ShellQuote by implementing the mechanism
# from python's shlex.quote function
sub shellescape {
my $string = shift;
if (length $string == 0) {
return "''";
}
# search for occurrences of characters that are not safe
# the 'a' regex modifier makes sure that \w only matches ASCII
if ($string !~ m/[^\w@\%+=:,.\/-]/a) {
return $string;
}
# wrap the string in single quotes and handle existing single quotes by
# putting them outside of the single-quoted string
$string =~ s/'/'"'"'/g;
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 {
my $verbose = shift;
local *maybe_error = sub {
my $msg = shift;
if ($verbose) {
error $msg;
} else {
debug $msg;
}
};
if ($EFFECTIVE_USER_ID == 0) {
maybe_error("cannot unshare user namespace when executing as root");
return 0;
}
# arguments to syscalls have to be stored in their own variable or
# otherwise we will get "Modification of a read-only value attempted"
my $unshare_flags = $CLONE_NEWUSER;
# we spawn a new per process because if unshare succeeds, we would
# otherwise have unshared the mmdebstrap process itself which we don't want
my $pid = fork() // error "fork() failed: $!";
if ($pid == 0) {
my $ret = syscall(&SYS_unshare, $unshare_flags);
if ($ret == 0) {
exit 0;
} else {
maybe_error("unshare syscall failed: $!");
exit 1;
}
}
waitpid($pid, 0);
if (($? >> 8) != 0) {
return 0;
}
# if newuidmap and newgidmap exist, the exit status will be 1 when
# executed without parameters
system "newuidmap 2>/dev/null";
if (($? >> 8) != 1) {
if (($? >> 8) == 127) {
maybe_error("cannot find newuidmap");
} else {
maybe_error("newuidmap returned unknown exit status: $?");
}
return 0;
}
system "newgidmap 2>/dev/null";
if (($? >> 8) != 1) {
if (($? >> 8) == 127) {
maybe_error("cannot find newgidmap");
} else {
maybe_error("newgidmap returned unknown exit status: $?");
}
return 0;
}
my @idmap = read_subuid_subgid($verbose);
if (scalar @idmap == 0) {
maybe_error("failed to parse /etc/subuid and /etc/subgid");
return 0;
}
# too much can go wrong when doing the dance required to unsharing the user
# namespace, so instead of adding more complexity to support maybe_error()
# to a function that is already too complex, we use eval()
eval {
$pid = get_unshare_cmd(
sub {
if ($EFFECTIVE_USER_ID == 0) {
exit 0;
} else {
exit 1;
}
},
\@idmap
);
waitpid $pid, 0;
if ($? != 0) {
maybe_error("failed to unshare the user namespace");
return 0;
}
};
if ($@) {
maybe_error($@);
return 0;
}
return 1;
}
sub read_subuid_subgid {
my $verbose = shift;
my @result = ();
my $username = getpwuid $REAL_USER_ID;
my ($subid, $num_subid, $fh, $n);
local *maybe_warn = sub {
my $msg = shift;
if ($verbose) {
warning $msg;
} else {
debug $msg;
}
};
if (!-e "/etc/subuid") {
maybe_warn("/etc/subuid doesn't exist");
return;
}
if (!-r "/etc/subuid") {
maybe_warn("/etc/subuid is not readable");
return;
}
open $fh, "<", "/etc/subuid"
or maybe_warn("cannot open /etc/subuid for reading: $!");
if (!$fh) {
return;
}
while (my $line = <$fh>) {
($n, $subid, $num_subid) = split(/:/, $line, 3);
last if ($n eq $username);
}
close $fh;
if (!length $subid) {
maybe_warn("/etc/subuid is empty");
return;
}
if ($n ne $username) {
maybe_warn("no entry in /etc/subuid for $username");
return;
}
push @result, ["u", 0, $subid, $num_subid];
if (scalar(@result) < 1) {
maybe_warn("/etc/subuid does not contain an entry for $username");
return;
}
if (scalar(@result) > 1) {
maybe_warn("/etc/subuid contains multiple entries for $username");
return;
}
if (!-e "/etc/subgid") {
maybe_warn("/etc/subgid doesn't exist");
return;
}
if (!-r "/etc/subgid") {
maybe_warn("/etc/subgid is not readable");
return;
}
open $fh, "<", "/etc/subgid"
or maybe_warn("cannot open /etc/subgid for reading: $!");
if (!$fh) {
return;
}
while (my $line = <$fh>) {
($n, $subid, $num_subid) = split(/:/, $line, 3);
last if ($n eq $username);
}
close $fh;
if (!length $subid) {
maybe_warn("/etc/subgid is empty");
return;
}
if ($n ne $username) {
maybe_warn("no entry in /etc/subgid for $username");
return;
}
push @result, ["g", 0, $subid, $num_subid];
if (scalar(@result) < 2) {
maybe_warn("/etc/subgid does not contain an entry for $username");
return;
}
if (scalar(@result) > 2) {
maybe_warn("/etc/subgid contains multiple entries for $username");
return;
}
return @result;
}
# This function spawns two child processes forming the following process tree
#
# A
# |
# fork()
# | \
# B C
# | |
# | fork()
# | | \
# | D E
# | | |
# |unshare()
# | close()
# | | |
# | | read()
# | | newuidmap(D)
# | | newgidmap(D)
# | | /
# | waitpid()
# | |
# | fork()
# | | \
# | F G
# | | |
# | | exec()
# | | /
# | waitpid()
# | /
# waitpid()
#
# To better refer to each individual part, we give each process a new
# identifier after calling fork(). Process A is the main process. After
# executing fork() we call the parent and child B and C, respectively. This
# first fork() is done because we do not want to modify A. B then remains
# waiting for its child C to finish. C calls fork() again, splitting into
# the parent D and its child E. In the parent D we call unshare() and close a
# pipe shared by D and E to signal to E that D is done with calling unshare().
# E notices this by using read() and follows up with executing the tools
# new[ug]idmap on D. E finishes and D continues with doing another fork().
# This is because when unsharing the PID namespace, we need a PID 1 to be kept
# alive or otherwise any child processes cannot fork() anymore themselves. So
# we keep F as PID 1 and finally call exec() in G.
sub get_unshare_cmd {
my $cmd = shift;
my $idmap = shift;
# unsharing the mount namespace (NEWNS) requires CAP_SYS_ADMIN
my $unshare_flags
= $CLONE_NEWNS | $CLONE_NEWPID | $CLONE_NEWUTS | $CLONE_NEWIPC;
# we only need to add CLONE_NEWUSER if we are not yet root
if ($EFFECTIVE_USER_ID != 0) {
$unshare_flags |= $CLONE_NEWUSER;
}
if (0) {
$unshare_flags |= $CLONE_NEWNET;
}
# fork a new process and let the child get unshare()ed
# we don't want to unshare the parent process
my $gcpid = fork() // error "fork() failed: $!";
if ($gcpid == 0) {
# Create a pipe for the parent process to signal the child process that
# it is done with calling unshare() so that the child can go ahead
# setting up uid_map and gid_map.
pipe my $rfh, my $wfh;
# We have to do this dance with forking a process and then modifying
# the parent from the child because:
# - new[ug]idmap can only be called on a process id after that process
# has unshared the user namespace
# - a process looses its capabilities if it performs an execve() with
# nonzero user ids see the capabilities(7) man page for details.
# - a process that unshared the user namespace by default does not
# have the privileges to call new[ug]idmap on itself
#
# this also works the other way around (the child setting up a user
# namespace and being modified from the parent) but that way, the
# parent would have to stay around until the child exited (so a pid
# would be wasted). Additionally, that variant would require an
# additional pipe to let the parent signal the child that it is done
# with calling new[ug]idmap. The way it is done here, this signaling
# can instead be done by wait()-ing for the exit of the child.
my $ppid = $$;
my $cpid = fork() // error "fork() failed: $!";
if ($cpid == 0) {
# child
# Close the writing descriptor at our end of the pipe so that we
# see EOF when parent closes its descriptor.
close $wfh;
# Wait for the parent process to finish its unshare() call by
# waiting for an EOF.
0 == sysread $rfh, my $c, 1 or error "read() did not receive EOF";
# the process is already root, so no need for newuidmap/newgidmap
if ($EFFECTIVE_USER_ID == 0) {
exit 0;
}
# The program's new[ug]idmap have to be used because they are
# setuid root. These privileges are needed to map the ids from
# /etc/sub[ug]id to the user namespace set up by the parent.
# Without these privileges, only the id of the user itself can be
# mapped into the new namespace.
#
# Since new[ug]idmap is setuid root we also don't need to write
# "deny" to /proc/$$/setgroups beforehand (this is otherwise
# required for unprivileged processes trying to write to
# /proc/$$/gid_map since kernel version 3.19 for security reasons)
# and therefore the parent process keeps its ability to change its
# own group here.
#
# Since /proc/$ppid/[ug]id_map can only be written to once,
# respectively, instead of making multiple calls to new[ug]idmap,
# we assemble a command line that makes one call each.
my $uidmapcmd = "";
my $gidmapcmd = "";
foreach (@{$idmap}) {
my ($t, $hostid, $nsid, $range) = @{$_};
if ($t ne "u" and $t ne "g" and $t ne "b") {
error "invalid idmap type: $t";
}
if ($t eq "u" or $t eq "b") {
$uidmapcmd .= " $hostid $nsid $range";
}
if ($t eq "g" or $t eq "b") {
$gidmapcmd .= " $hostid $nsid $range";
}
}
my $idmapcmd = '';
if ($uidmapcmd ne "") {
0 == system "newuidmap $ppid $uidmapcmd"
or error "newuidmap $ppid $uidmapcmd failed: $!";
}
if ($gidmapcmd ne "") {
0 == system "newgidmap $ppid $gidmapcmd"
or error "newgidmap $ppid $gidmapcmd failed: $!";
}
exit 0;
}
# parent
# After fork()-ing, the parent immediately calls unshare...
0 == syscall &SYS_unshare, $unshare_flags
or error "unshare() failed: $!";
# .. and then signals the child process that we are done with the
# unshare() call by sending an EOF.
close $wfh;
# Wait for the child process to finish its setup by waiting for its
# exit.
$cpid == waitpid $cpid, 0 or error "waitpid() failed: $!";
my $exit = $? >> 8;
if ($exit != 0) {
error "child had a non-zero exit status: $exit";
}
# Currently we are nobody (uid and gid are 65534). So we become root
# user and group instead.
#
# We are using direct syscalls instead of setting $(, $), $< and $>
# because then perl would do additional stuff which we don't need or
# want here, like checking /proc/sys/kernel/ngroups_max (which might
# not exist). It would also also call setgroups() in a way that makes
# the root user be part of the group unknown.
if ($EFFECTIVE_USER_ID != 0) {
0 == syscall &SYS_setgid, 0 or error "setgid failed: $!";
0 == syscall &SYS_setuid, 0 or error "setuid failed: $!";
0 == syscall &SYS_setgroups, 0, 0 or error "setgroups failed: $!";
}
if (1) {
# When the pid namespace is also unshared, then processes expect a
# master pid to always be alive within the namespace. To achieve
# this, we fork() here instead of exec() to always have one dummy
# process running as pid 1 inside the namespace. This is also what
# the unshare tool does when used with the --fork option.
#
# Otherwise, without a pid 1, new processes cannot be forked
# anymore after pid 1 finished.
my $cpid = fork() // error "fork() failed: $!";
if ($cpid != 0) {
# The parent process will stay alive as pid 1 in this
# namespace until the child finishes executing. This is
# important because pid 1 must never die or otherwise nothing
# new can be forked.
$cpid == waitpid $cpid, 0 or error "waitpid() failed: $!";
exit($? >> 8);
}
}
&{$cmd}();
exit 0;
}
# parent
return $gcpid;
}
sub havemknod {
my $root = shift;
my $havemknod = 0;
if (-e "$root/test-dev-null") {
error "/test-dev-null already exists";
}
TEST: {
# we fork so that we can read STDERR
my $pid = open my $fh, '-|' // error "failed to fork(): $!";
if ($pid == 0) {
open(STDERR, '>&', STDOUT) or error "cannot open STDERR: $!";
# we use mknod(1) instead of the system call because creating the
# right dev_t argument requires makedev(3)
exec 'mknod', "$root/test-dev-null", 'c', '1', '3';
}
chomp(
my $content = do { local $/; <$fh> }
);
close $fh;
{
last TEST unless $? == 0 and $content eq '';
last TEST unless -c "$root/test-dev-null";
last TEST unless open my $fh, '>', "$root/test-dev-null";
last TEST unless print $fh 'test';
}
$havemknod = 1;
}
if (-e "$root/test-dev-null") {
unlink "$root/test-dev-null"
or error "cannot unlink /test-dev-null: $!";
}
return $havemknod;
}
# inspired by /usr/share/perl/5.34/pod/perlfaq8.pod
sub terminal_width {
if (!stderr_is_tty()) {
return -1;
}
if (!defined &TIOCGWINSZ) {
return -1;
}
if (!-e "/dev/tty") {
return -1;
}
my $tty_fh;
if (!open($tty_fh, "+<", "/dev/tty")) {
return -1;
}
my $winsize = '';
if (!ioctl($tty_fh, &TIOCGWINSZ, $winsize)) {
return -1;
}
my (undef, $col, undef, undef) = unpack('S4', $winsize);
return $col;
}
# Prints the current status, the percentage and a progress bar on STDERR if
# it is an interactive tty and if verbosity is set to 1.
#
# * first 12 chars: status
# * following 7 chars: percentage
# * progress bar until 79 chars are filled
sub print_progress {
if ($verbosity_level != 1) {
return;
}
if (!stderr_is_tty()) {
return;
}
my $perc = shift;
my $status = shift;
my $len_status = 12;
my $len_perc = 7;
my $len_prog_min = 10;
my $len_prog_max = 60;
my $twidth = terminal_width();
if ($twidth <= $len_status) {
return;
}
# \e[2K clears everything on the current line (i.e. the progress bar)
print STDERR "\e[2K";
if ($perc eq "done") {
print STDERR "done\n";
return;
}
if (defined $status) {
printf STDERR "%*s", -$len_status, "$status:";
} else {
print STDERR (" " x $len_status);
}
if ($twidth <= $len_status + $len_perc) {
print STDERR "\r";
return;
}
if ($perc >= 100) {
$perc = 100;
}
printf STDERR "%*.2f", $len_perc, $perc;
if ($twidth <= $len_status + $len_perc + $len_prog_min) {
print STDERR "\r";
return;
}
my $len_prog = $twidth - $len_perc - $len_status;
if ($len_prog > $len_prog_max) {
$len_prog = $len_prog_max;
}
my $num_x = int($perc * ($len_prog - 3) / 100);
my $bar = '=' x $num_x;
if ($num_x != ($len_prog - 3)) {
$bar .= '>';
$bar .= ' ' x ($len_prog - $num_x - 4);
}
print STDERR " [$bar]\r";
return;
}
sub run_progress {
my ($get_exec, $line_handler, $line_has_error, $chdir) = @_;
pipe my $rfh, my $wfh;
my $got_signal = 0;
my $ignore = sub {
info "run_progress() received signal $_[0]: waiting for child...";
};
debug("run_progress: exec " . (join ' ', ($get_exec->('${FD}'))));
# delay signals so that we can fork and change behaviour of the signal
# handler in parent and child without getting interrupted
my $sigset = POSIX::SigSet->new(SIGINT, SIGHUP, SIGPIPE, SIGTERM);
POSIX::sigprocmask(SIG_BLOCK, $sigset) or error "Can't block signals: $!";
my $pid1 = open(my $pipe, '-|') // error "failed to fork(): $!";
if ($pid1 == 0) {
# child: default signal handlers
local $SIG{'INT'} = 'DEFAULT';
local $SIG{'HUP'} = 'DEFAULT';
local $SIG{'PIPE'} = 'DEFAULT';
local $SIG{'TERM'} = 'DEFAULT';
# unblock all delayed signals (and possibly handle them)
POSIX::sigprocmask(SIG_UNBLOCK, $sigset)
or error "Can't unblock signals: $!";
close $rfh;
# Unset the close-on-exec flag, so that the file descriptor does not
# get closed when we exec
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;
# redirect stderr to stdout so that we can capture it
open(STDERR, '>&', STDOUT) or error "cannot open STDOUT: $!";
my @execargs = $get_exec->($fd);
# before apt 1.5, "apt-get update" attempted to chdir() into the
# working directory. This will fail if the current working directory
# is not accessible by the user (for example in unshare mode). See
# Debian bug #860738
if (defined $chdir) {
chdir $chdir or error "failed chdir() to $chdir: $!";
}
eval { Devel::Cover::set_coverage("none") } if $is_covering;
exec { $execargs[0] } @execargs
or error 'cannot exec() ' . (join ' ', @execargs);
}
close $wfh;
# spawn two processes:
# parent will parse stdout to look for errors
# child will parse $rfh for the progress meter
my $pid2 = fork() // error "failed to fork(): $!";
if ($pid2 == 0) {
# child: default signal handlers
local $SIG{'INT'} = 'IGNORE';
local $SIG{'HUP'} = 'IGNORE';
local $SIG{'PIPE'} = 'IGNORE';
local $SIG{'TERM'} = 'IGNORE';
# unblock all delayed signals (and possibly handle them)
POSIX::sigprocmask(SIG_UNBLOCK, $sigset)
or error "Can't unblock signals: $!";
if ($verbosity_level != 1 || !stderr_is_tty()) {
# no need to print any progress
# we still need to consume everything from $rfh or otherwise apt
# will block forever if there is too much output
local $/;
<$rfh>;
close $rfh;
exit 0;
}
my $progress = 0.0;
my $status = undef;
print_progress($progress);
while (my $line = <$rfh>) {
my ($newprogress, $newstatus) = $line_handler->($line);
next unless $newprogress;
# start a new line if the new progress value is less than the
# previous one
if ($newprogress < $progress) {
print_progress("done");
}
if (defined $newstatus) {
$status = $newstatus;
}
print_progress($newprogress, $status);
$progress = $newprogress;
}
print_progress("done");
exit 0;
}
# parent: ignore signals
# by using "local", the original is automatically restored once the
# function returns
local $SIG{'INT'} = $ignore;
local $SIG{'HUP'} = $ignore;
local $SIG{'PIPE'} = $ignore;
local $SIG{'TERM'} = $ignore;
# unblock all delayed signals (and possibly handle them)
POSIX::sigprocmask(SIG_UNBLOCK, $sigset)
or error "Can't unblock signals: $!";
my $output = '';
my $has_error = 0;
while (my $line = <$pipe>) {
$has_error = $line_has_error->($line);
if ($verbosity_level >= 2) {
print STDERR $line;
} else {
# forward captured apt output
$output .= $line;
}
}
close($pipe);
my $fail = 0;
if ($? != 0 or $has_error) {
$fail = 1;
}
waitpid $pid2, 0;
$? == 0 or error "progress parsing failed";
if ($got_signal) {
error "run_progress() received signal: $got_signal";
}
# only print failure after progress output finished or otherwise it
# might interfere with the remaining output
if ($fail) {
if ($verbosity_level >= 1) {
print STDERR $output;
}
error((join ' ', $get_exec->('<$fd>')) . ' failed');
}
return;
}
sub run_dpkg_progress {
my $options = shift;
my @debs = @{ $options->{PKGS} // [] };
my $get_exec
= sub { return @{ $options->{ARGV} }, "--status-fd=$_[0]", @debs; };
my $line_has_error = sub { return 0; };
my $num = 0;
# each package has one install and one configure step, thus the total
# number is twice the number of packages
my $total = (scalar @debs) * 2;
my $line_handler = sub {
my $status = undef;
if ($_[0] =~ /^processing: (install|configure): /) {
if ($1 eq 'install') {
$status = 'installing';
} elsif ($1 eq 'configure') {
$status = 'configuring';
} else {
error "unknown status: $1";
}
$num += 1;
}
if ($total == 0) {
return 0, $status;
} else {
return $num / $total * 100, $status;
}
};
run_progress $get_exec, $line_handler, $line_has_error;
return;
}
sub run_apt_progress {
my $options = shift;
my @debs = @{ $options->{PKGS} // [] };
if ($verbosity_level >= 3) {
my @apt_debug_opts = qw(
-oDebug::pkgProblemResolver=true
-oDebug::pkgDepCache::Marker=1
-oDebug::pkgDepCache::AutoInstall=1
);
push @{ $options->{ARGV} }, @apt_debug_opts;
}
my $get_exec = sub {
my @prefix = ();
my @opts = ();
return (
@prefix,
@{ $options->{ARGV} },
@opts,
"-oAPT::Status-Fd=$_[0]",
# prevent apt from messing up the terminal and allow dpkg to
# receive SIGINT and quit immediately without waiting for
# maintainer script to finish
'-oDpkg::Use-Pty=false',
@debs
);
};
my $line_has_error = sub { return 0; };
if ($options->{FIND_APT_WARNINGS}) {
$line_has_error = sub {
# apt-get doesn't report a non-zero exit if the update failed.
# Thus, we have to parse its output. See #778357, #776152, #696335
# and #745735 for the parsing bugs as well as #594813, #696335,
# #776152, #778357 and #953726 for non-zero exit on transient
# network errors.
#
# For example, we want to fail with the following warning:
# W: Some index files failed to download. They have been ignored,
# or old ones used instead.
# But since this message is meant for human consumption it is not
# guaranteed to be stable across different apt versions and may
# change arbitrarily in the future. Thus, we error out on any W:
# lines as well. The downside is, that apt also unconditionally
# and by design prints a warning for unsigned repositories, even
# if they were allowed with Acquire::AllowInsecureRepositories "1"
# or with trusted=yes.
#
# A workaround was introduced by apt 2.1.16 with the --error-on=any
# option to apt-get update.
if ($_[0] =~ /^(W: |Err:)/) {
return 1;
}
return 0;
};
}
my $line_handler = sub {
if ($_[0] =~ /(pmstatus|dlstatus):[^:]+:(\d+\.\d+):.*/) {
my $status = undef;
if ($1 eq 'pmstatus') {
$status = "installing";
} elsif ($1 eq 'dlstatus') {
$status = "downloading";
} else {
error "unknown status: $1";
}
return $2, $status;
}
};
run_progress $get_exec, $line_handler, $line_has_error, $options->{CHDIR};
return;
}
sub run_apt_download_progress {
my $options = shift;
if ($options->{dryrun}) {
info "simulate downloading packages with apt...";
} else {
info "downloading packages with apt...";
}
pipe my $rfh, my $wfh;
my $pid = open my $fh, '-|' // error "fork() failed: $!";
if ($pid == 0) {
close $wfh;
# read until parent process closes $wfh
my $content = do { local $/; <$rfh> };
close $rfh;
# the parent is done -- pass what we read back to it
print $content;
exit 0;
}
close $rfh;
# Unset the close-on-exec flag, so that the file descriptor does not
# get closed when we exec
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.
run_apt_progress({
ARGV => [
'apt-get',
'--yes',
'-oDebug::pkgDpkgPm=1',
'-oDir::Log=/dev/null',
$options->{dryrun}
? '-oAPT::Get::Simulate=true'
: (
"-oAPT::Keep-Fds::=$fd",
"-oDPkg::Tools::options::'cat >&$fd'::InfoFD=$fd",
"-oDpkg::Pre-Install-Pkgs::=cat >&$fd",
# no need to lock the database if we are just downloading
"-oDebug::NoLocking=1",
# no need for pty magic if we write no log
"-oDpkg::Use-Pty=0",
# unset this or otherwise "cat >&$fd" will fail
"-oDPkg::Chroot-Directory=",
),
@{ $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) {
$err = "status child failed";
}
if ($err) {
error $err;
}
# remove trailing newlines
chomp @listofdebs;
return @listofdebs;
}
sub setup_mounts {
my $options = shift;
my @cleanup_tasks = ();
eval {
if (any { $_ eq $options->{mode} } ('root', 'unshare')) {
0 == system('mount', "--make-rprivate", "/")
or warning("mount --make-rprivate / failed: $?");
# if more than essential should be installed, make the system look
# more like a real one by creating or bind-mounting the device
# nodes
foreach my $file (@linuxdevfiles) {
my ($fname, $mode, $type, $linkname, $devmajor, $devminor,
undef)
= @{$file};
next if $fname eq './dev/';
if ($type eq '0') { # normal file
error "type 0 not implemented";
} elsif ($type eq '1') { # hardlink
error "type 1 not implemented";
} elsif ($type eq '2') { # symlink
if (!$options->{havemknod}) {
# If we had mknod, then the symlink was already created
# in the run_setup function.
if (!-d "$options->{root}/dev") {
warning(
"skipping creation of $fname because the"
. " /dev directory is missing in the target"
);
next;
}
if (-e "$options->{root}/$fname") {
warning(
"skipping creation of $fname because it"
. " already exists in the target");
next;
}
push @cleanup_tasks, sub {
unlink "$options->{root}/$fname"
or warning("cannot unlink ./dev/$fname: $!");
};
symlink $linkname, "$options->{root}/$fname"
or warning
"cannot create symlink $fname -> $linkname";
}
} elsif ($type eq '3' or $type eq '4') {
# character/block special
if (any { $_ =~ '^chroot/mount(?:/dev)?$' }
@{ $options->{skip} }) {
info "skipping chroot/mount/dev as requested";
} elsif (!$options->{canmount}) {
warning "skipping bind-mounting $fname";
} elsif (!$options->{havemknod}) {
if (!-d "$options->{root}/dev") {
warning(
"skipping creation of $fname because the"
. " /dev directory is missing in the target"
);
next;
}
if ($fname eq "./dev/ptmx") {
# We must not bind-mount ptmx from the outside or
# otherwise posix_openpt() will fail. Instead
# /dev/ptmx must refer to /dev/pts/ptmx either by
# symlink or by bind-mounting. We choose a symlink.
symlink '/dev/pts/ptmx',
"$options->{root}/dev/ptmx"
or error "cannot create /dev/pts/ptmx symlink";
push @cleanup_tasks, sub {
unlink "$options->{root}/dev/ptmx"
or warning "unlink /dev/ptmx";
};
next;
}
if (!-e "/$fname") {
warning("skipping creation of $fname because"
. " $fname does not exist"
. " on the outside");
next;
}
if (!-c "/$fname") {
warning("skipping creation of $fname because"
. " $fname on the outside is not a"
. " character special file");
next;
}
open my $fh, '>', "$options->{root}/$fname"
or error "cannot open $options->{root}/$fname: $!";
close $fh;
my @umountopts = ();
if ($options->{mode} eq 'unshare') {
push @umountopts, '--no-mtab';
}
push @cleanup_tasks, sub {
0 == system('umount', @umountopts,
"$options->{root}/$fname")
or warning("umount $fname failed: $?");
unlink "$options->{root}/$fname"
or warning("cannot unlink $fname: $!");
};
0 == system('mount', '-o', 'bind', "/$fname",
"$options->{root}/$fname")
or error "mount $fname failed: $?";
}
} elsif ($type eq '5') {
# directory
if (any { $_ =~ '^chroot/mount(?:/dev)?$' }
@{ $options->{skip} }) {
info "skipping chroot/mount/dev as requested";
} elsif (!$options->{canmount}) {
warning "skipping bind-mounting $fname";
} else {
if (!-d "$options->{root}/dev") {
warning(
"skipping creation of $fname because the"
. " /dev directory is missing in the target"
);
next;
}
if (!-e "/$fname" && $fname ne "./dev/pts/") {
warning("skipping creation of $fname because"
. " $fname does not exist"
. " on the outside");
next;
}
if (!-d "/$fname" && $fname ne "./dev/pts/") {
warning("skipping creation of $fname because"
. " $fname on the outside is not a"
. " directory");
next;
}
if (!$options->{havemknod}) {
# If had mknod, then the directory to bind-mount
# into was already created in the run_setup
# function.
push @cleanup_tasks, sub {
rmdir "$options->{root}/$fname"
or warning("cannot rmdir $fname: $!");
};
if (-e "$options->{root}/$fname") {
if (!-d "$options->{root}/$fname") {
error "$fname already exists but is not"
. " a directory";
}
} else {
my $num_created
= make_path "$options->{root}/$fname",
{ error => \my $err };
if ($err && @$err) {
error(
join "; ",
(
map {
"cannot create "
. (join ": ", %{$_})
} @$err
));
} elsif ($num_created == 0) {
error( "cannot create $options->{root}"
. "$fname");
}
}
chmod $mode, "$options->{root}/$fname"
or error "cannot chmod $fname: $!";
}
my @umountopts = ();
if ($options->{mode} eq 'unshare') {
push @umountopts, '--no-mtab';
}
push @cleanup_tasks, sub {
0 == system('umount', @umountopts,
"$options->{root}/$fname")
or warning("umount $fname failed: $?");
};
if ($fname eq "./dev/pts/") {
# We cannot just bind-mount /dev/pts from the host