[Reproducible-commits] [dpkg] 43/63: dpkg-deb: Use the treewalk module to build the .deb data member

Jérémy Bobbio lunar at moszumanska.debian.org
Fri Mar 4 17:44:45 UTC 2016


This is an automated email from the git hooks/post-receive script.

lunar pushed a commit to branch pu/buildinfo
in repository dpkg.

commit 231ba4312b8b215a2e388461d19a2b0d1b7f53c1
Author: Guillem Jover <guillem at debian.org>
Date:   Fri Feb 26 10:51:04 2016 +0100

    dpkg-deb: Use the treewalk module to build the .deb data member
    
    We reduce external dependencies on commands, avoid a read syscall per
    byte on the pipe, reduce code substantially, and get sorted file lists.
---
 debian/changelog |  1 +
 dpkg-deb/build.c | 86 ++++++++++++++------------------------------------------
 2 files changed, 22 insertions(+), 65 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 476eeae..a684a14 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -38,6 +38,7 @@ dpkg (1.18.5) UNRELEASED; urgency=medium
   * Add a new treewalk module in libdpkg, with the nice properties of avoiding
     duplicate stat(2) calls, not calling find(1), and sorting the output w/o
     stalling on the entire input being slurped and sorted.
+    - Use it to build the .deb data member in dpkg-deb.
   * Portability:
     - Move DPKG_ADMINDIR environment variable name out from update-alternatives
       code, to make life easier for non-dpkg-based systems.
diff --git a/dpkg-deb/build.c b/dpkg-deb/build.c
index 2ddeec6..849f483 100644
--- a/dpkg-deb/build.c
+++ b/dpkg-deb/build.c
@@ -43,6 +43,7 @@
 #include <dpkg/dpkg.h>
 #include <dpkg/dpkg-db.h>
 #include <dpkg/path.h>
+#include <dpkg/treewalk.h>
 #include <dpkg/varbuf.h>
 #include <dpkg/fdio.h>
 #include <dpkg/buffer.h>
@@ -58,7 +59,6 @@
  */
 struct file_info {
   struct file_info *next;
-  struct stat st;
   char *fn;
 };
 
@@ -94,43 +94,6 @@ file_info_find_name(struct file_info *list, const char *filename)
 }
 
 /**
- * Read a filename from the file descriptor and create a file_info struct.
- *
- * @return A file_info struct or NULL if there is nothing to read.
- */
-static struct file_info *
-file_info_get(const char *root, int fd)
-{
-  static struct varbuf fn = VARBUF_INIT;
-  struct file_info *fi;
-  size_t root_len;
-
-  varbuf_reset(&fn);
-  root_len = varbuf_printf(&fn, "%s/", root);
-
-  while (1) {
-    int res;
-
-    varbuf_grow(&fn, 1);
-    res = fd_read(fd, (fn.buf + fn.used), 1);
-    if (res < 0)
-      return NULL;
-    if (res == 0) /* EOF -> parent died. */
-      return NULL;
-    if (fn.buf[fn.used] == '\0')
-      break;
-
-    varbuf_trunc(&fn, fn.used + 1);
-  }
-
-  fi = file_info_new(fn.buf + root_len);
-  if (lstat(fn.buf, &(fi->st)) != 0)
-    ohshite(_("unable to stat file name '%.250s'"), fn.buf);
-
-  return fi;
-}
-
-/**
  * Add a new file_info struct to a single linked list of file_info structs.
  *
  * We perform a slight optimization to work around a ‘feature’ in tar: tar
@@ -168,46 +131,39 @@ file_info_list_free(struct file_info *fi)
 static void
 file_treewalk_feed(const char *dir, int fd_out)
 {
-  int pipefd[2];
-  pid_t pid;
+  struct treeroot *tree;
+  struct treenode *node;
   struct file_info *fi;
   struct file_info *symlist = NULL;
   struct file_info *symlist_end = NULL;
 
-  m_pipe(pipefd);
+  tree = treewalk_open(dir, TREEWALK_NONE, NULL);
+  for (node = treewalk_node(tree); node ; node = treewalk_next(tree)) {
+    const char *virtname = treenode_get_virtname(node);
+    char *nodename;
 
-  pid = subproc_fork();
-  if (pid == 0) {
-    m_dup2(pipefd[1], 1);
-    close(pipefd[0]);
-    close(pipefd[1]);
+    if (strncmp(virtname, BUILDCONTROLDIR, strlen(BUILDCONTROLDIR)) == 0)
+      continue;
 
-    if (chdir(dir))
-      ohshite(_("failed to chdir to '%.255s'"), dir);
+    nodename = str_fmt("./%s", virtname);
 
-    execlp(FIND, "find", ".", "-path", "./" BUILDCONTROLDIR, "-prune", "-o",
-           "-print0", NULL);
-    ohshite(_("unable to execute %s (%s)"), "find", FIND);
-  }
-  close(pipefd[1]);
-
-  /* We need to reorder the files so we can make sure that symlinks
-   * will not appear before their target. */
-  while ((fi = file_info_get(dir, pipefd[0])) != NULL) {
-    if (strchr(fi->fn, '\n'))
-      ohshit(_("newline not allowed in pathname '%s'"), fi->fn);
-    if (S_ISLNK(fi->st.st_mode)) {
+    if (strchr(nodename, '\n'))
+      ohshit(_("newline not allowed in pathname '%s'"), nodename);
+
+    /* We need to reorder the files so we can make sure that symlinks
+     * will not appear before their target. */
+    if (S_ISLNK(treenode_get_mode(node))) {
+      fi = file_info_new(nodename);
       file_info_list_append(&symlist, &symlist_end, fi);
     } else {
-      if (fd_write(fd_out, fi->fn, strlen(fi->fn) + 1) < 0)
+      if (fd_write(fd_out, nodename, strlen(nodename) + 1) < 0)
         ohshite(_("failed to write filename to tar pipe (%s)"),
                 _("data member"));
-      file_info_free(fi);
     }
-  }
 
-  close(pipefd[0]);
-  subproc_reap(pid, "find", 0);
+    free(nodename);
+  }
+  treewalk_close(tree);
 
   for (fi = symlist; fi; fi = fi->next)
     if (fd_write(fd_out, fi->fn, strlen(fi->fn) + 1) < 0)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/dpkg.git



More information about the Reproducible-commits mailing list