Package: base-files
Version: 9.6
Severity: wishlist
Tags: patch
User: helm...@debian.org
Usertags: rebootstrap

Hi Santiago,

In version 1.18.5, dpkg gained a new way for installing binary packages.
It now supports executing maintainer scripts outside the system it is
operating on. The feature is tracked at
https://wiki.debian.org/Teams/Dpkg/Spec/InstallBootstrap. This is
relevant in two ways:
 * When running debootstrap, ordering postinsts is tricky due to the
   number of dependency loops. By executing them outside the chroot,
   some loops can be broken as utilities of the outer system can be
   used.
 * When creating chroots for foreign architectures, the utilities
   inside such chroots usually cannot be executed at all.

To support this, dpkg now unconditionally exports an environment
variable called DPKG_ROOT. It will point to the installation root with
the trailing slash stripped. That means under normal conditions, it is
empty. Since scripts are normally run under chroot(2) even when passing
--root to dpkg, it is empty in that case as well. Only when explicitly
activating the new mode, the chroot call is skipped and DPKG_ROOT can be
non-empty. It is yet unclear under what conditions this mode should be
enabled, so for the time being the only way to do so is to use
--force-script-chrootless and I stress that this is only meant for
testing. Discussion on what maintainer scripts may assume in this mode
is still ongoing, but base-files' postinst only needs a tiny fraction so
it should be safe.

I prepared a patch that converts all filesystem accesses to prepend
DPKG_ROOT. After applying it, base-files can be installed fully
unprivileged using fakeroot[1] and in foreign chroots without access to
qemu. Is it acceptable for base-files?

Helmut

[1] fakeroot dpkg --root "$target" --log "$target/var/log/dpkg.log" 
--force-script-chrootless -i base-files_*.deb
diff --minimal -Nru base-files-9.6/debian/changelog 
base-files-9.6+nmu1/debian/changelog
--- base-files-9.6/debian/changelog     2016-03-04 17:33:57.000000000 +0100
+++ base-files-9.6+nmu1/debian/changelog        2016-05-17 21:45:06.000000000 
+0200
@@ -1,3 +1,10 @@
+base-files (9.6+nmu1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Support DPKG_ROOT in postinst. Closes: #-1.
+
+ -- Helmut Grohne <hel...@subdivi.de>  Tue, 17 May 2016 21:44:49 +0200
+
 base-files (9.6) unstable; urgency=low
 
   * Add lintian override for /etc/os-release.
diff --minimal -Nru base-files-9.6/debian/postinst.in 
base-files-9.6+nmu1/debian/postinst.in
--- base-files-9.6/debian/postinst.in   2015-08-18 12:03:09.000000000 +0200
+++ base-files-9.6+nmu1/debian/postinst.in      2016-05-17 22:12:34.000000000 
+0200
@@ -1,52 +1,75 @@
 #!/bin/sh
 set -e
 
+: "${DPKG_ROOT:=}"
+
+change_owner() {
+  local owner group
+  owner=${1%:*}
+  group=${1#*:}
+  owner=$(sed -n "s/^$owner:[^:]*:\\([0-9]*\\):.*/\\1/p" 
"$DPKG_ROOT/etc/passwd")
+  group=$(sed -n "s/^$group:[^:]*:\\([0-9]*\\):.*/\\1/p" 
"$DPKG_ROOT/etc/group")
+  chown "$owner:$group" "$DPKG_ROOT$2"
+}
+
+change_mode() {
+  chmod "$1" "$DPKG_ROOT$2"
+}
+
+ensure_file_owner_mode() {
+  if [ ! -f "$DPKG_ROOT$1" ]; then
+    : > "$DPKG_ROOT$1"
+  fi
+  change_owner "$2" "$1"
+  change_mode "$3" "$1"
+}
+
 install_local_dir() {
-  if [ ! -d $1 ]; then
-    mkdir -p $1
+  if [ ! -d "$DPKG_ROOT$1" ]; then
+    mkdir -p "$DPKG_ROOT$1"
   fi
-  if [ -f /etc/staff-group-for-usr-local ]; then
-    chown root:staff $1 2> /dev/null || true
-    chmod 2775 $1 2> /dev/null || true
+  if [ -f "$DPKG_ROOT/etc/staff-group-for-usr-local" ]; then
+    change_owner root:staff "$1" 2>/dev/null || true
+    change_mode 2775 "$1" 2> /dev/null || true
   fi
 }
 
 install_from_default() {
-  if [ ! -f $2 ]; then
-    cp -p /usr/share/base-files/$1 $2
+  if [ ! -f "$DPKG_ROOT$2" ]; then
+    cp -p "$DPKG_ROOT/usr/share/base-files/$1" "$DPKG_ROOT$2"
   fi
 }
 
 install_directory() {
-  if [ ! -d /$1 ]; then
-    mkdir /$1
-    chown root:$3 /$1
-    chmod $2 /$1
+  if [ ! -d "$DPKG_ROOT/$1" ]; then
+    mkdir "$DPKG_ROOT/$1"
+    change_owner "root:$3" "/$1"
+    change_mode "$2" "/$1"
   fi
 }
 
 migrate_directory() {
-  if [ ! -L $1 ]; then
-    rmdir $1
-    ln -s $2 $1
+  if [ ! -L "$DPKG_ROOT$1" ]; then
+    rmdir "$DPKG_ROOT$1"
+    ln -s "$2" "$DPKG_ROOT$1"
   fi
 }
 
 update_to_current_default() {
-  if [ -f $2 ]; then
-    md5=`md5sum $2 | cut -f 1 -d " "`
-    if grep -q "$md5" /usr/share/base-files/$1.md5sums; then
-      if ! cmp -s /usr/share/base-files/$1 $2; then
-        cp -p /usr/share/base-files/$1 $2
+  if [ -f "$DPKG_ROOT$2" ]; then
+    md5=`md5sum "$DPKG_ROOT$2" | cut -f 1 -d " "`
+    if grep -q "$md5" "$DPKG_ROOT/usr/share/base-files/$1.md5sums"; then
+      if ! cmp -s "$DPKG_ROOT/usr/share/base-files/$1" "$DPKG_ROOT$2"; then
+        cp -p "$DPKG_ROOT/usr/share/base-files/$1" "$DPKG_ROOT$2"
         echo Updating $2 to current default.
       fi
     fi
   fi
 }
 
-if [ ! -e /etc/dpkg/origins/default ]; then
-  if [ -e /etc/dpkg/origins/#VENDORFILE# ]; then
-    ln -sf #VENDORFILE# /etc/dpkg/origins/default
+if [ ! -e "$DPKG_ROOT/etc/dpkg/origins/default" ]; then
+  if [ -e "$DPKG_ROOT/etc/dpkg/origins/#VENDORFILE#" ]; then
+    ln -sf #VENDORFILE# "$DPKG_ROOT/etc/dpkg/origins/default"
   fi
 fi
 
@@ -65,8 +88,8 @@
   install_directory var/opt   755 root
   install_directory media     755 root
   install_directory var/mail 2775 mail
-  if [ ! -L /var/spool/mail ]; then
-    ln -s ../mail /var/spool/mail
+  if [ ! -L "$DPKG_ROOT/var/spool/mail" ]; then
+    ln -s ../mail "$DPKG_ROOT/var/spool/mail"
   fi
   install_directory run/lock 1777 root
   migrate_directory /var/run /run
@@ -82,38 +105,25 @@
   install_local_dir /usr/local/sbin
   install_local_dir /usr/local/src
   install_local_dir /usr/local/etc
-  ln -sf share/man /usr/local/man
+  ln -sf share/man "$DPKG_ROOT/usr/local/man"
 
-  if [ ! -f /var/log/wtmp ]; then
-    echo -n>/var/log/wtmp
-  fi
-  if [ ! -f /var/log/btmp ]; then
-    echo -n>/var/log/btmp
-  fi
-  if [ ! -f /var/log/lastlog ]; then
-    echo -n>/var/log/lastlog
-  fi
-  chown root:utmp /var/log/wtmp /var/log/btmp /var/log/lastlog
-  chmod 664 /var/log/wtmp /var/log/lastlog
-  chmod 660 /var/log/btmp
-  if [ ! -f /var/run/utmp ]; then
-    echo -n>/var/run/utmp
-  fi
-  chown root:utmp /var/run/utmp
-  chmod 664 /var/run/utmp
+  ensure_file_owner_mode /var/log/wtmp root:utmp 664
+  ensure_file_owner_mode /var/log/btmp root:utmp 660
+  ensure_file_owner_mode /var/log/lastlog root:utmp 664
+  ensure_file_owner_mode /var/log/utmp root:utmp 664
 fi
 
-if [ ! -d /var/lib/dpkg ]; then
-  mkdir -m 755 -p /var/lib/dpkg
+if [ ! -d "$DPKG_ROOT/var/lib/dpkg" ]; then
+  mkdir -m 755 -p "$DPKG_ROOT/var/lib/dpkg"
 fi
-if [ ! -f /var/lib/dpkg/status ]; then
-  echo > /var/lib/dpkg/status
-  chmod 644 /var/lib/dpkg/status
+if [ ! -f "$DPKG_ROOT/var/lib/dpkg/status" ]; then
+  echo > "$DPKG_ROOT/var/lib/dpkg/status"
+  change_mode 644 /var/lib/dpkg/status
 fi
 
-if [ ! -f /usr/info/dir ] && [ ! -f /usr/share/info/dir ]; then
+if [ ! -f "$DPKG_ROOT/usr/info/dir" ] && [ ! -f 
"$DPKG_ROOT/usr/share/info/dir" ]; then
   install_from_default info.dir /usr/share/info/dir
-  chmod 644 /usr/share/info/dir
+  change_mode 644 /usr/share/info/dir
 fi
 
 if [ "$1" = "configure" ] && [ "$2" != "" ]; then

Reply via email to