[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