Jonathan Nieder wrote:

> For reference when looking at other patches, I made a bunch of
> cosmetic changes to make this patch a little easier to read.  This
> does not address Guillem’s comments, nor even all of my own.  The
> changes have not been considered carefully.  But maybe it can be of
> some use nevertheless.
> 
> Changes from Sean’s original:
[...]

Here is the promised interdiff.

 src/conffiledb.c   |  253 +++++++++++++++++++++++++++++------------------------
 src/conffiledb.h   |  141 +++++++++++++++++------------
 lib/dpkg/subproc.c |   34 +++----
 lib/dpkg/subproc.h |    1 
 4 files changed, 243 insertions(+), 186 deletions(-)

diff -u b/src/conffiledb.c b/src/conffiledb.c
--- b/src/conffiledb.c
+++ b/src/conffiledb.c
@@ -12,95 +12,94 @@
 
 #include <dpkg/dpkg.h>
 #include <dpkg/i18n.h>
+#include <dpkg/varbuf.h>
 #include <dpkg/buffer.h>
 #include <dpkg/path.h>
+#include <dpkg/subproc.h>
 #include <dpkg/dpkg-db.h>
 #include "main.h"
 
 const char *conffiledb_base_dirs[] = { "current", "new", "resolved", "tmp" };
 
-char* 
-conffiledb_path(const char *pkg, const char *path, conffiledb_base base)
+/* Find a conffiledb entry, conffiledb, or conffiledb base dir. */
+char *
+conffiledb_path(const struct pkginfo *pkg, const char *path,
+               conffiledb_base base)
 {
-       char *full_path = NULL, *hash = NULL;
-       const char *basedir = NULL;
-       size_t basedir_sz = 0, conffiledb_sz = 0, full_path_sz = 0;
+       struct varbuf full_path = VARBUF_INIT;
+       const char *basedir;
 
-       /* sanity check for a valid base dir */
+       /* sanity check */
        if (base >= conffiledb_base_COUNT)
-               ohshit("conffiledb_path called with unsupported base %x", base);
+               ohshit(_("conffiledb_path called with unsupported base %x"),
+                       base);
 
        basedir = conffiledb_base_dirs[base];
+       varbufprintf(&full_path, "%s/%s%s/",
+               admindir, CONFFILEDBDIRROOT, basedir);
 
-       /* the root path is <admindir>/<#CONFFILEDBDIRROOT/><basedir>/
-        * (note that the '/' after #CONFFILEDBDIRROOT is implicitly included 
-        * in the #define'd string). The null byte is also accounted for
-        * at this point. */
-       basedir_sz = strlen(admindir) + 1 + strlen(CONFFILEDBDIRROOT) +
-                    strlen(basedir) + 2;
-       full_path_sz = conffiledb_sz = basedir_sz;
-       
-       /* we will add "<pkg>/" to the string later if <pkg> is not null */
-       if (pkg != NULL) 
-               full_path_sz = conffiledb_sz += strlen(pkg) + 1;
-
-       /* and if a conffile is being requested (not just the db root)... */
-       if (path != NULL)
-               full_path_sz += CONFFILEDB_MD5SUM_LEN;
-
-       /* this is the path to the conffile db for the given base/pkg */
-       full_path = m_malloc(full_path_sz);
-       snprintf(full_path, basedir_sz, "%s/%s%s/", admindir, 
-                CONFFILEDBDIRROOT, basedir);
-       
-       /* append "<pkg>/" if needed */
-       if (pkg != NULL)
-               sprintf(full_path + basedir_sz - 1, "%s/", pkg);
-
-       /* append the pathname's hash if relevant */
-       if (path != NULL) {
-               hash = full_path + conffiledb_sz - 1;
-               buffer_md5(path, hash, strlen(path));
-       }
-
-       debug(dbg_conffdetail, "confffiledb_path(%s, %s, %x) = %s\n", pkg, 
-             path, base, full_path);
-
-       return full_path;
+       if (pkg == NULL)
+               goto done;
+       varbufprintf(&full_path, "%s/", pkg->name);
+
+       if (path == NULL)
+               goto done;
+       varbuf_grow(&full_path, CONFFILEDB_MD5SUM_LEN + 1);
+       buffer_md5(path, full_path.buf + full_path.used,
+               strlen(path));
+       full_path.used += CONFFILEDB_MD5SUM_LEN;
+
+done:
+       debug(dbg_conffdetail, "confffiledb_path(%s, %s, %x) = %s\n",
+               pkg ? pkg->name : "(null)", path ? path : "(null)", base,
+               full_path.buf);
+       return full_path.buf;
 }
 
-/** Ensure that a particular conffiledb dir exists.
+/**
+ * Ensure that a particular conffiledb dir exists.
+ *
+ * mkdir -p $CONFFILEDBDIRROOT/$base/$pkg
  *
  * @param pkg The package owning the conffiledb dir.
  * @param base Which conffiledb basedir to use.
  */
 static void
-conffiledb_ensure_db(const char *pkg, conffiledb_base base)
+conffiledb_ensure_db(const struct pkginfo *pkg, conffiledb_base base)
 {
-       struct stat s; 
-       short i = 0;
-       char *dbdir = NULL;
-       char *separators[3];
+       struct stat s;
+       int i;
+       char *dbdir, *end, *separators[3];
 
        dbdir = conffiledb_path(pkg, NULL, base);
-       /* temporarily truncate the string to cheaply traverse up to the
+
+       /* sanity check */
+       if (*dbdir != '/')
+               ohshit(_("conffiledb_path returned a relative path"));
+
+       /*
+        * Temporarily truncate the string to cheaply traverse up to the
         * the parent and its parent. store the locations so we can cheaply
-        * get back to them later. */
+        * get back to them later.
+        */
+       end = dbdir + strlen(dbdir);
        for (i = 0; i < 3; i++) {
-               separators[i] = rindex(dbdir, '/');
-               *separators[i] = '\0';
+               while (*end != '/' && end != dbdir)
+                       end--;
+               *end = '\0';
+               separators[i] = end;
        }
 
-       /* now ensure each directory exists while reconstructing the path */
+       /* Now ensure each directory exists while reconstructing the path. */
        for (i = 2; i >= 0; i--) {
                if (stat(dbdir, &s)) {
-                       debug(dbg_conffdetail, 
+                       debug(dbg_conffdetail,
                              "conffiledb_ensure_db: creating %s\n", dbdir);
-                       if (errno != ENOENT) 
-                               ohshite("conffiledb_ensure_db: stat(%s)", 
+                       if (errno != ENOENT)
+                               ohshite("conffiledb_ensure_db: stat(%s)",
                                        dbdir);
-                       if (mkdir(dbdir, S_IRWXU)) 
-                               ohshite("conffiledb_ensure_db: mkdir(%s)", 
+                       if (mkdir(dbdir, S_IRWXU))
+                               ohshite("conffiledb_ensure_db: mkdir(%s)",
                                        dbdir);
                }
                *separators[i] = '/';
@@ -109,76 +108,93 @@
        free(dbdir);
 }
 
+/* Add a new entry to $CONFFILEDBDIRROOT/new/$pkg. */
 void
-conffiledb_register_new_conffile(const char *pkg, const char *path, int fd, 
-                                 size_t sz)
+conffiledb_register_new_conffile(const struct pkginfo *pkg,
+               const char *path, int fd, size_t sz)
 {
        int cfgfd;
-       /* get the path to where the registered file goes */
-       char *p = conffiledb_path(pkg, path, conffiledb_base_new);
-       char fnamebuf[256];
+       char *dest;
+       char msg_dest[256];
+
+       /* sanity check */
+       if (path == NULL || pkg == NULL)
+               ohshit(_("conffiledb_register_new_conffile called "
+                       "with NULL arguments"));
+
+       dest = conffiledb_path(pkg, path, conffiledb_base_new);
+       path_quote_filename(msg_dest, dest, sizeof(msg_dest));
+       debug(dbg_conff, "conffile_register_new_conffile: %s, %s, %s\n",
+               pkg->name, path, msg_dest);
 
        conffiledb_ensure_db(pkg, conffiledb_base_new);
-       debug(dbg_conff, "conffile_reg_fd: %s, %s, %s\n", pkg, path, p);
-       /* make a mode 600 copy of file to p */
-       cfgfd = open(p, (O_CREAT|O_EXCL|O_WRONLY), (S_IRUSR|S_IWUSR));
-       if (cfgfd < 0) 
-               ohshite(_("unable to create `%.255s'"),p);
-       fd_fd_copy(fd, cfgfd, sz, _("backend dpkg-deb during `%.255s'"),
-                  path_quote_filename(fnamebuf, p, 256));
-       if (close(cfgfd))
-               ohshite("can't close %s", p);
 
-       free(p);
+       cfgfd = open(dest, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
+       if (cfgfd < 0)
+               ohshite(_("unable to create `%.255s'"), msg_dest);
+       fd_fd_copy(fd, cfgfd, sz, _("new conffiledb entry '%.255s'"),
+                  msg_dest);
+
+       if (close(cfgfd))
+               ohshite("can't close %.255s", msg_dest);
+       free(dest);
 }
 
+/* Open a conffiledb entry for reading. */
 int
-conffiledb_get_conffile(const char *pkg, const char *path, conffiledb_base 
base)
+conffiledb_get_conffile(const struct pkginfo *pkg,
+               const char *path, conffiledb_base base)
 {
-       int fd = -1;
+       int fd;
        char *p = conffiledb_path(pkg, path, base);
 
        fd = open(p, O_RDONLY);
-       if (fd == -1)
-               ohshite("error opening conffile registered at %s", p);
+       if (fd == -1) {
+               char msg_p[256];
+               ohshite(_("error opening conffile registered at %.255s"),
+                       path_quote_filename(msg_p, p, sizeof(msg_p)));
+       }
 
        free(p);
        return fd;
 }
 
+/*
+ * Update the conffiles "db" dir.  This consists of the following steps:
+ * - nuke the tmp dir if it exists
+ * - rename to_base to the tmp dir
+ * - rename from_base to to_base
+ * - nuke the tmp dir
+ */
 void
-conffiledb_commit(const char *pkg, conffiledb_base from_base, 
+conffiledb_commit(const struct pkginfo *pkg, conffiledb_base from_base,
                   conffiledb_base to_base)
 {
-       /* update the conffiles "db" dir.  this consists of the following steps:
-        * - nuke the tmp dir if it exists
-        * - rename to_base to the tmp dir
-        * - rename from_base to to_base
-        * - nuke the tmp dir
-        */
        char *cfdb_to = NULL, *cfdb_from = NULL, *cfdb_tmp = NULL;
-       debug(dbg_conff, "conffiledb_commit(%s, %d, %d)", pkg, from_base, 
-             to_base);
+
+       /* sanity check */
+       if (pkg == NULL)
+               ohshit(_("conffiledb_commit called for NULL package"));
+
+       debug(dbg_conff, "conffiledb_commit(%s, %d, %d)",
+               pkg->name, from_base, to_base);
 
        cfdb_from = conffiledb_path(pkg, NULL, from_base);
        cfdb_to = conffiledb_path(pkg, NULL, to_base);
        cfdb_tmp = conffiledb_path(pkg, NULL, conffiledb_base_tmp);
 
-       /* Make sure all leading components of the tmp conffiledb exist */
        conffiledb_ensure_db(pkg, conffiledb_base_tmp);
-       /* Then nuke the tmp conffiledb if it exists */
        conffiledb_remove(pkg, conffiledb_base_tmp);
-       /* Make sure all leading components of the target conffiledb exist */
+
        conffiledb_ensure_db(pkg, to_base);
-       /* Rename the target conffiledb to the tmp one */
        if (rename(cfdb_to, cfdb_tmp))
-               ohshite("conffiledb_commit: rename(%s,%s)", cfdb_to, cfdb_tmp);
-       /* Make sure all leading components of the source conffiledb exist */
+               ohshite(_("conffiledb_commit: rename(%s, %s)"),
+                       cfdb_to, cfdb_tmp);
        conffiledb_ensure_db(pkg, from_base);
-       /* Rename from_base to to_base */
        if (rename(cfdb_from, cfdb_to))
-               ohshite("conffiledb_commit: rename(%s,%s)", cfdb_from, cfdb_to);
-       /* Nuke the tmp version if it exists */
+               ohshite(_("conffiledb_commit: rename(%s, %s)"),
+                       cfdb_from, cfdb_to);
+
        conffiledb_remove(pkg, conffiledb_base_tmp);
 
        free(cfdb_from);
@@ -188,31 +204,44 @@
 
+/* Remove a conffiledb with all of its entries. */
 void
-conffiledb_remove(const char *pkg, conffiledb_base base)
+conffiledb_remove(const struct pkginfo *pkg, conffiledb_base base)
 {
-       char *cfdb = conffiledb_path(pkg, NULL, base);
+       char *cfdb;
+
+       /* sanity check */
+       if (pkg == NULL)
+               ohshit(_("conffiledb_remove called for NULL package"));
 
-       debug(dbg_conff, "conffiledb_remove(%s): removing %s\n", pkg, cfdb);
+       cfdb = conffiledb_path(pkg, NULL, base);
+       debug(dbg_conff, "conffiledb_remove(%s): removing %s\n",
+               pkg->name, cfdb);
        ensure_pathname_nonexisting(cfdb);
 
        free(cfdb);
 }
 
+/* Spawn 'diff -u <conffiledb entry> <installed conffile>'. */
 int
-conffiledb_diff (const char *pkg, const char *path, conffiledb_base base)
+conffiledb_diff(const struct pkginfo *pkg, const char *path,
+               conffiledb_base base)
 {
-       int status;
-       char *src = conffiledb_path(pkg, path, base);
-       char *cmd = NULL;
-       const char *opts = "-u";
-       /* DIFF + ' ' + <opts> + ' ' + <srcfile> + ' ' + <dstfile> + '\0' */
-       size_t cmd_sz = strlen(DIFF) + 1 + strlen(opts) + 1 + strlen(src) +
-                       1 + strlen(path) + 1;
-
-       cmd = m_malloc(cmd_sz);
-       sprintf(cmd, "%s %s %s %s", DIFF, opts, src, path);
-       status = system(cmd);
+       int child, result;
+       char *src;
+
+       /* sanity check */
+       if (pkg == NULL || path == NULL)
+               ohshit(_("conffiledb_diff called for NULL conffile"));
+
+       src = conffiledb_path(pkg, path, base);
+
+       if (!(child = m_fork())) {
+               execlp(DIFF, "diff", "-u", src, path, NULL);
+               ohshite(_("failed to exec 'diff -u %s %s'"),
+                       src, path);
+       }
+
+       result = waitsubproc(child, "diff", PROCNOERR | PROCSAVESTATUS);
 
        free(src);
-       free(cmd);
-       return WEXITSTATUS(status);
+       return result;
 }
diff -u b/src/conffiledb.h b/src/conffiledb.h
--- b/src/conffiledb.h
+++ b/src/conffiledb.h
@@ -1,7 +1,7 @@
 /**
  * @file conffiledb.h
  *
- * Functions for tracking referencable versions of packages' conffiles.
+ * Functions for tracking referenceable versions of packages' conffiles.
  *
  * This library allows for tracking the pristine versions (and in some specific
  * cases a few other versions) of packages' conffiles.  This allows for a
@@ -15,19 +15,23 @@
  *     #CONFFILEDBDIRROOT/\<base\>/\<pkg\>/\<md5\>
  *
  * where:
- * - @b \<base\> is a short string which corresponds to the base reference
- *   type in question. See the documentation for conffiledb_base for the 
- *   enumerated values and conffiledb_base_dirs for the corresponding
- *   string values.
- * - @b \<pkg\> is the conffile database directory for an individual package.
- * - @b \<md5\> is the md5 hash of the location of a package's conffile.  A 
+ * - @b \<base\> is a short string describing which version of the conffile
+ *   this is. See enum #conffiledb_base for the enumerated values and
+ *   #conffiledb_base_dirs for the corresponding strings.
+ * - @b \<pkg\> is the package name.
+ * - @b \<md5\> is the md5 hash of the location of a package's conffile.  A
  *   hash is used to keep a flat and balanced directory structure, and has
  *   the added benefit of a simpler implementation.
  *
  * Some further terminology to keep things clear later on:
  *
- * - @b "conffiledb root" refers to the top-most directory containing
- *   all conffile databases, and is defined by #CONFFILEDBDIRROOT.
+ * - @b "conffiledb file" or @b "conffiledb entry" refers to a file whose
+ *   contents correspond to a particular conffiledb_base/package/conffile
+ *   triplet.
+ * - @anchor conffiledb @b "conffile database" or @b "conffiledb" refers
+ *   to a directory specific to a conffiledb_base + package tuple.  Such a
+ *   directory will contain copies of the conffiles named after the hash
+ *   of their respective installed locations.
  * - @b "conffiledb basedir" refers to the subdirectory directly
  *   underneath the conffiledb root directory, which divides the the
  *   different conffiledbs by different "reference types" (i.e. the
@@ -35,19 +39,17 @@
  *   a newly unpacked version). The available basedirs are defined in
  *   conffiledb_base_dirs, which is indexed on the respective enumerated
  *   values from conffiledb_base.
- * - @anchor conffiledb @b "conffile database" or @b "conffiledb" refers
- *   to a directory specific to a conffiledb_base + package tuple.  Such a
- *   directory will contain copies of the conffiles named after the hash
- *   of their respective installed locations.
- * - @b "conffiledb file" or @b "conffiledb entry" refers to a file whose 
- *   contents correspond to a particular conffiledb_base/package/conffile 
- *   triplet.
+ * - @b "conffiledb root" refers to the top-most directory containing
+ *   all conffile databases, and is defined by #CONFFILEDBDIRROOT.
  */
 #ifndef CONFFILES_H
 #define CONFFILES_H
 
 #include <sys/types.h>
 
+/* Defined in dpkg/dpkg-db.h. */
+struct pkginfo;
+
 /** The different base reference types underneath the conffile db. */
 typedef enum {
        conffiledb_base_current, /**< The currently installed version */
@@ -57,7 +59,7 @@
        conffiledb_base_COUNT /**< The count of possible values for this type */
 } conffiledb_base;
 
-/** 
+/**
  * The directory names of the conffiledb base dirs, indexed by the respective
  * conffiledb_base value.
  */
@@ -66,13 +68,14 @@
 /** Length of the MD5 string used in conffile path hashing (NULL not counted) 
*/
 #define CONFFILEDB_MD5SUM_LEN 32
 
-/** Return the canonical path for a conffiledb entry or other location.
+/**
+ * Determine the canonical path for a conffiledb entry.
  *
- * This is a helper function to resolve the full path to a specific location 
+ * This is a helper function to resolve the full path to a specific location
  * within the conffile database. The primary use is to find the location
  * of a conffiledb file, but it can also be used to find the location
  * of the @ref conffiledb for a particular conffiledb_base + package,
- * as well as the parent conffiledb basedir corresponding to a particular 
+ * as well as the parent conffiledb basedir corresponding to a particular
  * conffiledb_base.
  *
  * @param pkg The package name. If NULL, the returned value will be
@@ -81,75 +84,99 @@
  *        value will be the conffiledb directory which should contain all
  *        conffiledb files for the combination of pkg and base.
- * @param base Which conffiledb basedir is requested.
+ * @param base Which conffiledb base reference type is requested.
+ *
  * @return An allocated string with the path (your job to free it).
  */
-char* conffiledb_path(const char *pkg, const char *path, conffiledb_base base);
+char *conffiledb_path(const struct pkginfo *pkg, const char *path,
+       conffiledb_base base);
 
-/** Register a new conffiledb file for a package.
+/**
+ * Add a new conffiledb entry for a package.
  *
- * Create a conffiledb entry in the conffiledb dir for the::conffiledb_base_new
- * version of a particular package. The conffile will be later processed in the
- * package configuration stage, after which there should be a call to
- * conffiledb_commit_new before configuration can be considered successful.
- *
- * The use of a filedescriptor is due to the fact that the new conffile is
- * intercepted very early during the unpack phase, before it exists on disk.
- * Therefore this interface is designed to hook cleanly into what's available 
- * at that point, which is a filedescriptor generated from a struct TarInfo
- * (see tarobject in archives.c).
+ * For use when unpacking a package.  Create a conffiledb entry in the
+ * conffiledb dir for the #conffiledb_base_new version of a particular
+ * package. The conffile will be later processed in the package configuration
+ * stage, after which there should be a call to conffiledb_commit() before
+ * configuration can be considered successful.
+ *
+ * The use of a file descriptor allows the new entry to be written very early
+ * in the unpack phase, before it exists on disk.  This interface is designed
+ * to hook cleanly with what's available, which is filedescriptor representing
+ * output from tar extraction.
  *
  * @param pkg The package owning the conffile.
  * @param path The installed location of the conffile.
  * @param fd A file descriptor holding the contents of the conffile.
- * @param sz The size of the conffile.
+ * @param sz Size of the conffile in bytes.
+ *           (XXX why is this not off_t, -1 allowed?)
  */
-void conffiledb_register_new_conffile(const char *pkg, const char *path, int 
fd,
-                                      size_t sz);
+void conffiledb_register_new_conffile(const struct pkginfo *pkg,
+       const char *path, int fd, size_t sz);
 
-/** Get a readable filehandle to the contents of a conffiledb entry.
+/**
+ * Open a conffiledb entry for reading.
  *
  * @param pkg The package owning the conffile.
  * @param path The installed location of the conffile.
  * @param base Which conffiledb basedir to use.
- * @return A read-only file descriptor for the registered conffile.
+ *
+ * @return A read-only file descriptor for the registered conffile
+ *         (your job to close it).
  */
-int conffiledb_get_conffile(const char *pkg, const char *path, 
-                            conffiledb_base base);
+int conffiledb_get_conffile(const struct pkginfo *pkg,
+       const char *path, conffiledb_base base);
 
-/** Remove a conffiledb directory for a package.
+/**
+ * Remove a package’s conffiledb.
+ *
+ * Remove the indicated version of the specified package’s conffiledb.
  *
- * This is designed to be used in two use cases: 
- * - package removal and cleanup
- * - after one conffiledb directory has been replaced by another.
+ * This should be useful in two cases:
+ * - purging a package’s configuration files
+ * - replacing one conffiledb with another.
  *
  * @param pkg The package owning the conffile db to be removed.
  * @param base Which conffiledb basedir to use with respect to pkg.
  */
-void conffiledb_remove(const char *pkg, conffiledb_base base);
+void conffiledb_remove(const struct pkginfo *pkg, conffiledb_base base);
 
-/** Commit one conffiledb as another, replacing any existing one.
+/**
+ * Move a conffiledb from one base reference type to another.
  *
- * This function takes the conffiledb defined by pkg and from_base and
- * commits it as being defined by pkg and to_base. Any existing conffiledb
- * for pkg / to_base is first renamed as conffiledb_base_tmp and then
- * removed after the successful "commit" (to keep things as atomic as 
- * possible).
+ * This is a safer way to perform the operation
+ *  
+ *     rm -r $CONFFILEDBDIRROOT/$to_base/$pkg
+ *     mv $CONFFILEDBDIRROOT/$from_base/$pkg $CONFFILEDBDIRROOT/$to_base/
+ *
+ * The conffiledb corresponding to pkg and the tmp base reference type
+ * is used as a temporary location to hold the entries from to_base until
+ * the entries from from_base are put into place.
+ *
+ * Any entries already in the tmp/$pkg conffiledb will be removed.  The
+ * invoking program is responsible for putting things back in order upon
+ * failure.
  *
  * @param pkg The package owning the conffile database
  * @param from_base The current conffiledb basedir which should be renamed.
  * @param to_base The conffiledb basedir which should be replaced by the
  *        version in from_base.
  */
-void conffiledb_commit(const char *pkg, conffiledb_base from_base, 
-                       conffiledb_base to_base);
+void conffiledb_commit(const struct pkginfo *pkg,
+       conffiledb_base from_base, conffiledb_base to_base);
 
-/** Show the diff between a conffiledb entry and a corresponding conffile.
- * 
+/**
+ * Print a diff between a conffiledb entry and the installed version.
+ *
+ * Print a unified diff between a conffiledb entry and the corresponding
+ * installed conffile to stdout.
+ *
  * @param pkg The package that owns the conffile.
  * @param path The pathname to the installed version of the conffile.
  * @param base Which conffiledb basedir to use.
- * @return The exit status of the underlying call to diff(1).
+ *
+ * @return The exit status from diff(1).
  */
-int conffiledb_diff(const char *pkg, const char *path, conffiledb_base base);
+int conffiledb_diff(const struct pkginfo *pkg, const char *path,
+       conffiledb_base base);
 
 #endif /* CONFFILES_H */
only in patch2:
unchanged:
--- a/lib/dpkg/subproc.c
+++ b/lib/dpkg/subproc.c
@@ -73,22 +73,24 @@ cu_subproc_signals(int argc, void **argv)
 int
 checksubprocerr(int status, const char *description, int flags)
 {
-       int n;
+       if (flags & PROCWARN)
+               flags |= PROCNOERR;
 
        if (WIFEXITED(status)) {
-               n = WEXITSTATUS(status);
+               int n = WEXITSTATUS(status);
+
                if (!n)
                        return 0;
-               if (flags & PROCNOERR)
-                       return -1;
                if (flags & PROCWARN)
                        warning(_("%s returned error exit status %d"),
                                description, n);
-               else
-                       ohshit(_("subprocess %s returned error exit status %d"),
-                              description, n);
+               if (flags & PROCNOERR)
+                       return flags & PROCSAVESTATUS ? n : -1;
+               ohshit(_("subprocess %s returned error exit status %d"),
+                      description, n);
        } else if (WIFSIGNALED(status)) {
-               n = WTERMSIG(status);
+               int n = WTERMSIG(status);
+
                if (!n)
                        return 0;
                if ((flags & PROCPIPE) && n == SIGPIPE)
@@ -97,16 +99,14 @@ checksubprocerr(int status, const char *description, int 
flags)
                        warning(_("%s killed by signal (%s)%s"),
                                description, strsignal(n),
                                WCOREDUMP(status) ? _(", core dumped") : "");
-               else
-                       ohshit(_("subprocess %s killed by signal (%s)%s"),
-                              description, strsignal(n),
-                              WCOREDUMP(status) ? _(", core dumped") : "");
-       } else {
-               ohshit(_("subprocess %s failed with wait status code %d"),
-                      description, status);
+               if (flags & PROCNOERR)
+                       return -1;
+               ohshit(_("subprocess %s killed by signal (%s)%s"),
+                      description, strsignal(n),
+                      WCOREDUMP(status) ? _(", core dumped") : "");
        }
-
-       return -1;
+       ohshit(_("subprocess %s failed with wait status code %d"),
+              description, status);
 }
 
 int
only in patch2:
unchanged:
--- a/lib/dpkg/subproc.h
+++ b/lib/dpkg/subproc.h
@@ -34,6 +34,7 @@ void cu_subproc_signals(int argc, void **argv);
 #define PROCPIPE 1
 #define PROCWARN 2
 #define PROCNOERR 4
+#define PROCSAVESTATUS 8
 
 int checksubprocerr(int status, const char *desc, int flags);
 int waitsubproc(pid_t pid, const char *desc, int flags);


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to