diff options
Diffstat (limited to 'multistrap/selfstrap')
-rwxr-xr-x | multistrap/selfstrap | 116 |
1 files changed, 91 insertions, 25 deletions
diff --git a/multistrap/selfstrap b/multistrap/selfstrap index 88dc07e..c693a4e 100755 --- a/multistrap/selfstrap +++ b/multistrap/selfstrap | |||
@@ -43,6 +43,8 @@ apt_get() | |||
43 | [ "$rootfs" ] || die 'no $rootfs' | 43 | [ "$rootfs" ] || die 'no $rootfs' |
44 | [ "$APT_CONFIG" ] || die 'no $APT_CONFIG' | 44 | [ "$APT_CONFIG" ] || die 'no $APT_CONFIG' |
45 | 45 | ||
46 | visible_args="$*" | ||
47 | |||
46 | set -- -o Apt::Install-Recommends=false "$@" | 48 | set -- -o Apt::Install-Recommends=false "$@" |
47 | 49 | ||
48 | # Set various paths to within the created system. | 50 | # Set various paths to within the created system. |
@@ -59,7 +61,7 @@ apt_get() | |||
59 | # We must also set dpkg to use the created system. | 61 | # We must also set dpkg to use the created system. |
60 | # Dpkg::options requires undocumented apt CLI magic. | 62 | # Dpkg::options requires undocumented apt CLI magic. |
61 | if [ "$DEBUG_DPKG" ]; then | 63 | if [ "$DEBUG_DPKG" ]; then |
62 | [ "$DEBUG_DPKG" -gt 0 ] 2>/dev/null || DEBUG_DPKG=013 | 64 | [ "$DEBUG_DPKG" -gt 0 ] 2>/dev/null || DEBUG_DPKG=10013 |
63 | set -- -o DPkg::options::arg0=--debug="${DEBUG_DPKG}" "$@" | 65 | set -- -o DPkg::options::arg0=--debug="${DEBUG_DPKG}" "$@" |
64 | fi | 66 | fi |
65 | # This is the important one: | 67 | # This is the important one: |
@@ -75,9 +77,60 @@ apt_get() | |||
75 | # Avoid deleting lists on the calling system. | 77 | # Avoid deleting lists on the calling system. |
76 | set -- -o APT::Get::List-Cleanup=false "$@" | 78 | set -- -o APT::Get::List-Cleanup=false "$@" |
77 | 79 | ||
80 | [ "$VERBOSE" ] && printf '+ apt-get %s\n' "$visible_args" >&2 || true | ||
81 | |||
78 | apt-get "$@" | 82 | apt-get "$@" |
79 | } | 83 | } |
80 | 84 | ||
85 | idem() { if [ ! -e "${!#}" ]; then "$@"; fi; } | ||
86 | idem_mknod() { if [ ! -e "$3" ]; then mknod "$@"; fi; } | ||
87 | |||
88 | # This function is copied (with modifications) from debootstrap. | ||
89 | install_devices() | ||
90 | { | ||
91 | local TARGET="$rootfs" | ||
92 | [ "$TARGET" -a -d "$TARGET" ] || die 'no $TARGET' | ||
93 | idem mkdir "$TARGET"/dev | ||
94 | # The list of devices that can be created in a container comes from | ||
95 | # src/core/cgroup.c in the systemd source tree. | ||
96 | idem_mknod -m 666 "$TARGET"/dev/null c 1 3 | ||
97 | idem_mknod -m 666 "$TARGET"/dev/zero c 1 5 | ||
98 | idem_mknod -m 666 "$TARGET"/dev/full c 1 7 | ||
99 | idem_mknod -m 666 "$TARGET"/dev/random c 1 8 | ||
100 | idem_mknod -m 666 "$TARGET"/dev/urandom c 1 9 | ||
101 | idem_mknod -m 666 "$TARGET"/dev/tty c 5 0 | ||
102 | idem mkdir "$TARGET"/dev/pts/ | ||
103 | idem mkdir "$TARGET"/dev/shm/ | ||
104 | # Inside a container, we might not be allowed to create /dev/ptmx. | ||
105 | # If not, do the next best thing. | ||
106 | if ! idem_mknod -m 666 "$TARGET"/dev/ptmx c 5 2; then | ||
107 | idem ln -s pts/ptmx "$TARGET"/dev/ptmx | ||
108 | fi | ||
109 | idem ln -s /proc/self/fd "$TARGET"/dev/fd | ||
110 | idem ln -s /proc/self/fd/0 "$TARGET"/dev/stdin | ||
111 | idem ln -s /proc/self/fd/1 "$TARGET"/dev/stdout | ||
112 | idem ln -s /proc/self/fd/2 "$TARGET"/dev/stderr | ||
113 | } | ||
114 | |||
115 | mount_virtfs() | ||
116 | { | ||
117 | local TARGET="$1" | ||
118 | [ "$TARGET" ] || die 'no $TARGET' | ||
119 | [ -d "$TARGET"/proc ] || mkdir "$TARGET"/proc | ||
120 | [ -d "$TARGET"/sys ] || mkdir "$TARGET"/sys | ||
121 | mount -t proc proc "$TARGET"/proc | ||
122 | mount -t sysfs sysfs "$TARGET"/sys | ||
123 | } | ||
124 | |||
125 | umount_virtfs() | ||
126 | { | ||
127 | local TARGET="$1" fail= | ||
128 | [ "$TARGET" ] || die 'no $TARGET' | ||
129 | umount "$TARGET"/proc || fail=y | ||
130 | umount "$TARGET"/sys || fail=y | ||
131 | [ ! "$fail" ] | ||
132 | } | ||
133 | |||
81 | write_lines_once() | 134 | write_lines_once() |
82 | { | 135 | { |
83 | local output="$1" | 136 | local output="$1" |
@@ -100,6 +153,7 @@ populate_rootfs() | |||
100 | write_lines_once "$rootfs"/etc/apt/sources.list \ | 153 | write_lines_once "$rootfs"/etc/apt/sources.list \ |
101 | "deb $debian_mirror $release main contrib non-free" \ | 154 | "deb $debian_mirror $release main contrib non-free" \ |
102 | "deb http://security.debian.org $release/updates main contrib non-free" | 155 | "deb http://security.debian.org $release/updates main contrib non-free" |
156 | install_devices | ||
103 | } | 157 | } |
104 | 158 | ||
105 | parse_apt_noact_line() | 159 | parse_apt_noact_line() |
@@ -131,23 +185,33 @@ dpkg_extract_with_info() | |||
131 | PKG=${PKG%%_*} | 185 | PKG=${PKG%%_*} |
132 | PKG=$PKG$multiarch | 186 | PKG=$PKG$multiarch |
133 | 187 | ||
134 | command=' | 188 | command=$(cat <<'EOF' |
135 | [ "$TAR_FILENAME" = ./control ] && exit | 189 | if [ "$TAR_FILENAME" = ./control ]; then |
136 | f=$TARGET/var/lib/dpkg/info/$PKG.${TAR_FILENAME#./} | 190 | (sed "/^Package:/a Status: install ok installed"; echo) >> "$TARGET"/var/lib/dpkg/status |
137 | cat > "$f" | 191 | else |
138 | chmod $TAR_MODE "$f" | 192 | f=$TARGET/var/lib/dpkg/info/$PKG.${TAR_FILENAME#./} |
139 | ' | 193 | cat > "$f" |
194 | chmod $TAR_MODE "$f" | ||
195 | fi | ||
196 | EOF | ||
197 | ) | ||
140 | (export PKG TARGET; dpkg --ctrl-tarfile "$deb" | tar -x --to-command "$command") | 198 | (export PKG TARGET; dpkg --ctrl-tarfile "$deb" | tar -x --to-command "$command") |
141 | dpkg --fsys-tarfile "$deb" | | 199 | dpkg --fsys-tarfile "$deb" | |
142 | (cd "$TARGET" && tar -xv) | | 200 | (cd "$TARGET" && tar -xv) | |
143 | sed 's?^\.??; s?^/$?/.?; s?/$??' > "$TARGET/var/lib/dpkg/info/$PKG.list" | 201 | sed 's?^\.??; s?^/$?/.?; s?/$??' > "$TARGET/var/lib/dpkg/info/$PKG.list" |
144 | |||
145 | } | 202 | } |
146 | 203 | ||
147 | apt_run_inst() | 204 | apt_run_inst() |
148 | { | 205 | { |
149 | apt_get -s -yqq install "$@" | while read line; do | 206 | apt_get -s -yqq install "$@" | dpkg_inst_from_apt |
207 | } | ||
208 | |||
209 | dpkg_inst_from_apt() | ||
210 | { | ||
211 | while read line; do | ||
150 | parse_apt_noact_line "$line" || die "unexpected output from apt-get: $line" | 212 | parse_apt_noact_line "$line" || die "unexpected output from apt-get: $line" |
213 | export LC_ALL=C | ||
214 | export DEBIAN_FRONTEND=noninteractive | ||
151 | export DPKG_MAINTSCRIPT_PACKAGE="$package" DPKG_MAINTSCRIPT_ARCH="$arch" | 215 | export DPKG_MAINTSCRIPT_PACKAGE="$package" DPKG_MAINTSCRIPT_ARCH="$arch" |
152 | is_multiarch_same "$package" && multiarch=":$arch" || multiarch= | 216 | is_multiarch_same "$package" && multiarch=":$arch" || multiarch= |
153 | case "$action" in | 217 | case "$action" in |
@@ -174,7 +238,9 @@ apt_run_inst() | |||
174 | apt_extract() | 238 | apt_extract() |
175 | { | 239 | { |
176 | apt_get -d -yqq install "$@" | 240 | apt_get -d -yqq install "$@" |
177 | apt_get -s -yqq install "$@" | while read line; do | 241 | actions=$(mktemp) || die 'mktemp failed' |
242 | apt_get -s -yqq install "$@" | tee "$actions" | while read line; do | ||
243 | |||
178 | parse_apt_noact_line "$line" || die "unexpected output from apt-get: $line" | 244 | parse_apt_noact_line "$line" || die "unexpected output from apt-get: $line" |
179 | 245 | ||
180 | deb=/var/cache/apt/archives/${package}_${version//:/%3a}_${arch}.deb | 246 | deb=/var/cache/apt/archives/${package}_${version//:/%3a}_${arch}.deb |
@@ -194,18 +260,22 @@ apt_extract() | |||
194 | dpkg-deb --extract "$deb" "$rootfs" | 260 | dpkg-deb --extract "$deb" "$rootfs" |
195 | fi | 261 | fi |
196 | ;; | 262 | ;; |
197 | Conf) | 263 | Conf) ;; |
198 | ;; | ||
199 | Remv) ;; | 264 | Remv) ;; |
200 | *) die "impossible" ;; | 265 | *) die "impossible" ;; |
201 | esac | 266 | esac |
202 | done | 267 | done |
268 | if [ "$EXTRACT_DPKG_INFO" ]; then | ||
269 | install_etc_passwd | ||
270 | dpkg_inst_from_apt < "$actions" | ||
271 | fi | ||
272 | rm "$actions" | ||
203 | } | 273 | } |
204 | 274 | ||
205 | install_etc_passwd() | 275 | install_etc_passwd() |
206 | { | 276 | { |
207 | [ -e "$rootfs"/etc/passwd ] || cp "$rootfs"//usr/share/base-passwd/passwd.master "$rootfs"/etc/passwd | 277 | [ -e "$rootfs"/etc/passwd ] || cp "$rootfs"/usr/share/base-passwd/passwd.master "$rootfs"/etc/passwd |
208 | [ -e "$rootfs"/etc/group ] || cp "$rootfs"//usr/share/base-passwd/group.master "$rootfs"/etc/group | 278 | [ -e "$rootfs"/etc/group ] || cp "$rootfs"/usr/share/base-passwd/group.master "$rootfs"/etc/group |
209 | } | 279 | } |
210 | 280 | ||
211 | main_packages_file() | 281 | main_packages_file() |
@@ -273,8 +343,6 @@ packages=$(required_packages) && [ "$packages" ] || die 'failed to determine lis | |||
273 | extra_packages='apt debian-archive-keyring locales' | 343 | extra_packages='apt debian-archive-keyring locales' |
274 | 344 | ||
275 | 345 | ||
276 | # Extract files from downloaded packages. | ||
277 | # | ||
278 | # Some files need to be present before 'apt-get install' can install anything. | 346 | # Some files need to be present before 'apt-get install' can install anything. |
279 | # In particular: | 347 | # In particular: |
280 | # | 348 | # |
@@ -282,20 +350,18 @@ extra_packages='apt debian-archive-keyring locales' | |||
282 | # 2. /etc/passwd and /etc/group so that 'chown' works | 350 | # 2. /etc/passwd and /etc/group so that 'chown' works |
283 | 351 | ||
284 | # Rather than fuss about (1), extract everything from all packages. | 352 | # Rather than fuss about (1), extract everything from all packages. |
285 | apt_extract $packages | ||
286 | # This handles (2). | ||
287 | install_etc_passwd | ||
288 | 353 | ||
354 | # Note: apt_extract() runs preinst and postinst scripts itself when | ||
355 | # $EXTRACT_DPKG_INFO is true. | ||
356 | apt_extract $packages | ||
289 | 357 | ||
290 | # Finally we are ready to run apt-get install. | ||
291 | export LC_ALL=C | ||
292 | export DEBIAN_FRONTEND=noninteractive | ||
293 | if [ "$SKIP_INSTALL" ]; then | 358 | if [ "$SKIP_INSTALL" ]; then |
294 | apt_extract $extra_packages | 359 | apt_extract $extra_packages |
295 | if [ "$RUN_INST_SCRIPTS" ]; then | ||
296 | apt_run_inst $packages $extra_packages | ||
297 | fi | ||
298 | else | 360 | else |
361 | export LC_ALL=C | ||
362 | export DEBIAN_FRONTEND=noninteractive | ||
363 | |||
364 | install_etc_passwd # This handles (2). | ||
299 | if [ "$FIX_BROKEN" ]; then | 365 | if [ "$FIX_BROKEN" ]; then |
300 | dpkg --root="$rootfs" --configure -a | 366 | dpkg --root="$rootfs" --configure -a |
301 | fi | 367 | fi |