[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH 1/3] Refactor dpkg-deb do_build() in multiple smaller functions



---
 dpkg-deb/build.c |  346 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 207 insertions(+), 139 deletions(-)

diff --git a/dpkg-deb/build.c b/dpkg-deb/build.c
index 348e01e..703136a 100644
--- a/dpkg-deb/build.c
+++ b/dpkg-deb/build.c
@@ -382,79 +382,39 @@ pkg_get_pathname(const char *dir, struct pkginfo *pkg)
   return path;
 }
 
-/**
- * Overly complex function that builds a .deb file.
- */
-int
-do_build(const char *const *argv)
+static void
+compress_control_tar(int input_fd, int gzfd)
 {
-  struct dpkg_error err;
-  const char *debar, *dir;
-  bool subdir;
-  char *tfbuf;
-  int arfd;
-  int p1[2], p2[2], p3[2], gzfd;
-  pid_t c1,c2,c3;
-  struct file_info *fi;
-  struct file_info *symlist = NULL;
-  struct file_info *symlist_end = NULL;
+  pid_t c;
 
-  /* Decode our arguments. */
-  dir = *argv++;
-  if (!dir)
-    badusage(_("--%s needs a <directory> argument"), cipaction->olong);
-  subdir = false;
-  debar = *argv++;
-  if (debar != NULL) {
-    struct stat debarstab;
-
-    if (*argv)
-      badusage(_("--%s takes at most two arguments"), cipaction->olong);
+  /* And run gzip to compress our control archive. */
+  c = subproc_fork();
+  if (!c) {
+    struct compress_params params;
 
-    if (stat(debar, &debarstab)) {
-      if (errno != ENOENT)
-        ohshite(_("unable to check for existence of archive `%.250s'"), debar);
-    } else if (S_ISDIR(debarstab.st_mode)) {
-      subdir = true;
-    }
-  } else {
-    char *m;
+    params.type = compressor_type_gzip;
+    params.strategy = compressor_strategy_none;
+    params.level = 9;
 
-    m= m_malloc(strlen(dir) + sizeof(DEBEXT));
-    strcpy(m, dir);
-    path_trim_slash_slashdot(m);
-    strcat(m, DEBEXT);
-    debar= m;
+    compress_filter(&params, input_fd, gzfd, _("compressing control member"));
+    exit(0);
   }
+  close(input_fd);
+  subproc_wait_check(c, "gzip -9c", 0);
+}
 
-  /* Perform some sanity checks on the to-be-build package. */
-  if (nocheckflag) {
-    if (subdir)
-      ohshit(_("target is directory - cannot skip control file check"));
-    warning(_("not checking contents of control area"));
-    printf(_("dpkg-deb: building an unknown package in '%s'.\n"), debar);
-  } else {
-    struct pkginfo *pkg;
-
-    pkg = check_new_pkg(dir);
-    if (subdir)
-      debar = pkg_get_pathname(debar, pkg);
-    printf(_("dpkg-deb: building package `%s' in `%s'.\n"),
-           pkg->set->name, debar);
-  }
-  m_output(stdout, _("<standard output>"));
+static void
+create_control_tar(const char *dir, int gzfd)
+{
+  int p[2];
+  pid_t c;
 
-  /* Now that we have verified everything its time to actually
-   * build something. Let's start by making the ar-wrapper. */
-  arfd = creat(debar, 0644);
-  if (arfd < 0)
-    ohshite(_("unable to create `%.255s'"), debar);
   /* Fork a tar to package the control-section of the package. */
   unsetenv("TAR_OPTIONS");
-  m_pipe(p1);
-  c1 = subproc_fork();
-  if (!c1) {
-    m_dup2(p1[1],1); close(p1[0]); close(p1[1]);
+  m_pipe(p);
+  c = subproc_fork();
+  if (!c) {
+    m_dup2(p[1], 1); close(p[0]); close(p[1]);
     if (chdir(dir))
       ohshite(_("failed to chdir to `%.255s'"), dir);
     if (chdir(BUILDCONTROLDIR))
@@ -462,88 +422,85 @@ do_build(const char *const *argv)
     execlp(TAR, "tar", "-cf", "-", "--format=gnu", ".", NULL);
     ohshite(_("unable to execute %s (%s)"), "tar -cf", TAR);
   }
-  close(p1[1]);
+  close(p[1]);
+
+  compress_control_tar(p[0], gzfd);
+  subproc_wait_check(c, "tar -cf", 0);
+}
+
+static void
+write_format_zero_deb_header(const char *debar, int arfd, int gzfd)
+{
+  struct dpkg_error err;
+  struct stat controlstab;
+  char versionbuf[40];
+
+  if (fstat(gzfd, &controlstab))
+    ohshite(_("failed to stat temporary file (%s)"), _("control member"));
+  sprintf(versionbuf, "%-8s\n%jd\n", OLDARCHIVEVERSION,
+          (intmax_t)controlstab.st_size);
+  if (fd_write(arfd, versionbuf, strlen(versionbuf)) < 0)
+    ohshite(_("error writing `%s'"), debar);
+  if (fd_fd_copy(gzfd, arfd, -1, &err) < 0)
+    ohshit(_("cannot copy '%s' into archive '%s': %s"), _("control member"),
+           debar, err.str);
+}
+
+static void
+write_deb_header(const char *debar, int arfd, int gzfd)
+{
+  const char deb_magic[] = ARCHIVEVERSION "\n";
+
+  /* Ensure that we start at the beginning */
+  if (lseek(gzfd, 0, SEEK_SET))
+    ohshite(_("failed to rewind temporary file (%s)"), _("control member"));
+
+  if (deb_format.major == 0) {
+    write_format_zero_deb_header(debar, arfd, gzfd);
+    return;
+  }
+
+  dpkg_ar_put_magic(debar, arfd);
+  dpkg_ar_member_put_mem(debar, arfd, DEBMAGIC, deb_magic, strlen(deb_magic));
+  dpkg_ar_member_put_file(debar, arfd, ADMINMEMBER, gzfd, -1);
+}
+
+static int
+setup_temp_gz(char const * target_name)
+{
+  char *tfbuf;
+  int gzfd;
+
   /* Create a temporary file to store the control data in. Immediately
    * unlink our temporary file so others can't mess with it. */
   tfbuf = path_make_temp_template("dpkg-deb");
   gzfd = mkstemp(tfbuf);
   if (gzfd == -1)
-    ohshite(_("failed to make temporary file (%s)"), _("control member"));
+    ohshite(_("failed to make temporary file (%s)"), target_name);
   /* Make sure it's gone, the fd will remain until we close it. */
   if (unlink(tfbuf))
-    ohshit(_("failed to unlink temporary file (%s), %s"), _("control member"),
+    ohshit(_("failed to unlink temporary file (%s), %s"), target_name,
            tfbuf);
   free(tfbuf);
+  return gzfd;
+}
 
-  /* And run gzip to compress our control archive. */
-  c2 = subproc_fork();
-  if (!c2) {
-    struct compress_params params;
-
-    params.type = compressor_type_gzip;
-    params.strategy = compressor_strategy_none;
-    params.level = 9;
-
-    compress_filter(&params, p1[0], gzfd, _("compressing control member"));
-    exit(0);
-  }
-  close(p1[0]);
-  subproc_wait_check(c2, "gzip -9c", 0);
-  subproc_wait_check(c1, "tar -cf", 0);
-
-  if (lseek(gzfd, 0, SEEK_SET))
-    ohshite(_("failed to rewind temporary file (%s)"), _("control member"));
-
-  /* We have our first file for the ar-archive. Write a header for it
-   * to the package and insert it. */
-  if (deb_format.major == 0) {
-    struct stat controlstab;
-    char versionbuf[40];
-
-    if (fstat(gzfd, &controlstab))
-      ohshite(_("failed to stat temporary file (%s)"), _("control member"));
-    sprintf(versionbuf, "%-8s\n%jd\n", OLDARCHIVEVERSION,
-            (intmax_t)controlstab.st_size);
-    if (fd_write(arfd, versionbuf, strlen(versionbuf)) < 0)
-      ohshite(_("error writing `%s'"), debar);
-    if (fd_fd_copy(gzfd, arfd, -1, &err) < 0)
-      ohshit(_("cannot copy '%s' into archive '%s': %s"), _("control member"),
-             debar, err.str);
-  } else {
-    const char deb_magic[] = ARCHIVEVERSION "\n";
-
-    dpkg_ar_put_magic(debar, arfd);
-    dpkg_ar_member_put_mem(debar, arfd, DEBMAGIC, deb_magic, strlen(deb_magic));
-    dpkg_ar_member_put_file(debar, arfd, ADMINMEMBER, gzfd, -1);
-  }
-  close(gzfd);
+static void
+create_data_tar(const char *dir, int gzfd)
+{
+  int p1[2], p2[2], p3[2];
+  pid_t c1, c2, c3;
+  struct file_info *fi;
+  struct file_info *symlist = NULL;
+  struct file_info *symlist_end = NULL;
 
-  /* Control is done, now we need to archive the data. */
-  if (deb_format.major == 0) {
-    /* In old format, the data member is just concatenated after the
-     * control member, so we do not need a temporary file and can use
-     * the compression file descriptor. */
-    gzfd = arfd;
-  } else {
-    /* Start by creating a new temporary file. Immediately unlink the
-     * temporary file so others can't mess with it. */
-    tfbuf = path_make_temp_template("dpkg-deb");
-    gzfd = mkstemp(tfbuf);
-    if (gzfd == -1)
-      ohshite(_("failed to make temporary file (%s)"), _("data member"));
-    /* Make sure it's gone, the fd will remain until we close it. */
-    if (unlink(tfbuf))
-      ohshit(_("failed to unlink temporary file (%s), %s"), _("data member"),
-             tfbuf);
-    free(tfbuf);
-  }
   /* Fork off a tar. We will feed it a list of filenames on stdin later. */
   m_pipe(p1);
   m_pipe(p2);
   c1 = subproc_fork();
   if (!c1) {
-    m_dup2(p1[0],0); close(p1[0]); close(p1[1]);
-    m_dup2(p2[1],1); close(p2[0]); close(p2[1]);
+    m_dup2(p1[0], 0); close(p1[0]); close(p1[1]);
+    m_dup2(p2[1], 1); close(p2[0]); close(p2[1]);
     if (chdir(dir))
       ohshite(_("failed to chdir to `%.255s'"), dir);
     execlp(TAR, "tar", "-cf", "-", "--format=gnu", "--null", "-T", "-", "--no-recursion", NULL);
@@ -565,7 +522,7 @@ do_build(const char *const *argv)
   m_pipe(p3);
   c3 = subproc_fork();
   if (!c3) {
-    m_dup2(p3[1],1); close(p3[0]); close(p3[1]);
+    m_dup2(p3[1], 1); close(p3[0]); close(p3[1]);
     if (chdir(dir))
       ohshite(_("failed to chdir to `%.255s'"), dir);
     execlp(FIND, "find", ".", "-path", "./" BUILDCONTROLDIR, "-prune", "-o",
@@ -595,17 +552,128 @@ do_build(const char *const *argv)
   file_info_list_free(symlist);
   subproc_wait_check(c2, _("<compress> from tar -cf"), 0);
   subproc_wait_check(c1, "tar -cf", 0);
-  /* Okay, we have data.tar as well now, add it to the ar wrapper. */
-  if (deb_format.major == 2) {
-    char datamember[16 + 1];
+}
 
-    sprintf(datamember, "%s%s", DATAMEMBER,
-            compressor_get_extension(compress_params.type));
+static void
+write_data_tar(const char *debar, int arfd, int gzfd)
+{
+  char datamember[16 + 1];
+
+  sprintf(datamember, "%s%s", DATAMEMBER,
+          compressor_get_extension(compress_params.type));
+
+  if (lseek(gzfd, 0, SEEK_SET))
+    ohshite(_("failed to rewind temporary file (%s)"), _("data member"));
 
-    if (lseek(gzfd, 0, SEEK_SET))
-      ohshite(_("failed to rewind temporary file (%s)"), _("data member"));
+  dpkg_ar_member_put_file(debar, arfd, datamember, gzfd, -1);
+}
 
-    dpkg_ar_member_put_file(debar, arfd, datamember, gzfd, -1);
+static void
+decode_arguments(const char *const *argv, const char **dir, bool *subdir, const char **debar)
+{
+  *dir = *argv++;
+  if (!*dir)
+    badusage(_("--%s needs a <directory> argument"), cipaction->olong);
+  *subdir = false;
+  *debar = *argv++;
+  if (*debar != NULL) {
+    struct stat debarstab;
+
+    if (*argv)
+      badusage(_("--%s takes at most two arguments"), cipaction->olong);
+
+    if (stat(*debar, &debarstab)) {
+      if (errno != ENOENT)
+        ohshite(_("unable to check for existence of archive `%.250s'"), *debar);
+    } else if (S_ISDIR(debarstab.st_mode)) {
+      *subdir = true;
+    }
+  } else {
+    char *m;
+
+    m = m_malloc(strlen(*dir) + sizeof(DEBEXT));
+    strcpy(m, *dir);
+    path_trim_slash_slashdot(m);
+    strcat(m, DEBEXT);
+    *debar = m;
+  }
+}
+
+static void
+check_build_sanity(const char *dir, bool subdir, const char **debar)
+{
+  if (nocheckflag) {
+    if (subdir)
+      ohshit(_("target is directory - cannot skip control file check"));
+    warning(_("not checking contents of control area"));
+    printf(_("dpkg-deb: building an unknown package in '%s'.\n"), *debar);
+  } else {
+    struct pkginfo *pkg;
+
+    pkg = check_new_pkg(dir);
+    if (subdir)
+      *debar = pkg_get_pathname(*debar, pkg);
+    printf(_("dpkg-deb: building package `%s' in `%s'.\n"),
+           pkg->set->name, *debar);
+  }
+  m_output(stdout, _("<standard output>")); // XXX-lunar: what is this for?
+}
+
+static int
+initialize_ar(const char *debar)
+{
+  int arfd;
+
+  arfd = creat(debar, 0644);
+  if (arfd < 0)
+    ohshite(_("unable to create `%.255s'"), debar);
+  return arfd;
+}
+
+/**
+ * Overly complex function that builds a .deb file.
+ */
+int
+do_build(const char *const *argv)
+{
+  const char *debar, *dir;
+  bool subdir;
+  int arfd;
+  int gzfd;
+
+  /* Decode our arguments. */
+  decode_arguments(argv, &dir, &subdir, &debar);
+
+  /* Perform some sanity checks on the to-be-build package. */
+  check_build_sanity(dir, subdir, &debar);
+
+  /* Now that we have verified everything its time to actually
+   * build something. Let's start by making the ar-wrapper. */
+  arfd = initialize_ar(debar);
+
+  gzfd = setup_temp_gz(_("control member"));
+
+  create_control_tar(dir, gzfd);
+
+  /* We have our first file for the ar-archive. Write a header for it
+   * to the package and insert it. */
+  write_deb_header(debar, arfd, gzfd);
+
+  close(gzfd);
+
+  /* Control is done, now we need to archive the data. */
+  if (deb_format.major == 0) {
+    /* In old format, the data member is just concatenated after the
+     * control member, so we do not need a temporary file and can use
+     * the compression file descriptor. */
+    gzfd = arfd;
+  } else {
+    gzfd = setup_temp_gz(_("data member"));
+  }
+  create_data_tar(dir, gzfd);
+  /* Okay, we have data.tar as well now, add it to the ar wrapper. */
+  if (deb_format.major == 2) {
+    write_data_tar(debar, arfd, gzfd);
   }
   if (fsync(arfd))
     ohshite(_("unable to sync file '%s'"), debar);
-- 
Lunar                                .''`. 
lunar@debian.org                    : :Ⓐ  :  # apt-get install anarchism
                                    `. `'` 
                                      `-   

Attachment: signature.asc
Description: Digital signature


Reply to: