[Libguestfs] [PATCH] New API: cpio-out converts a directory to cpio format.

Richard W.M. Jones rjones at redhat.com
Sat May 3 16:01:07 UTC 2014


This is useful for generating Linux initramfses from other types of
filesystems.  For example:

 guestfish --ro -a disk.img -i cpio-out / - | gzip -9 > initrd.img
---
 daemon/Makefile.am   |   1 +
 daemon/cpio.c        | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++
 generator/actions.ml |  28 ++++++++++++
 gobject/Makefile.inc |   2 +
 po/POTFILES          |   2 +
 src/MAX_PROC_NR      |   2 +-
 6 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 daemon/cpio.c

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index b18f9ff..8ccf322 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -93,6 +93,7 @@ guestfsd_SOURCES = \
 	command.c \
 	compress.c \
 	copy.c \
+	cpio.c \
 	cpmv.c \
 	daemon.h \
 	dd.c \
diff --git a/daemon/cpio.c b/daemon/cpio.c
new file mode 100644
index 0000000..e33e47b
--- /dev/null
+++ b/daemon/cpio.c
@@ -0,0 +1,124 @@
+/* libguestfs - the guestfsd daemon
+ * Copyright (C) 2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "read-file.h"
+
+#include "guestfs_protocol.h"
+#include "daemon.h"
+#include "actions.h"
+#include "optgroups.h"
+
+GUESTFSD_EXT_CMD(str_cpio, cpio);
+
+/* Has one FileOut parameter. */
+/* Takes optional arguments, consult optargs_bitmask. */
+int
+do_cpio_out (const char *dir, const char *format)
+{
+  CLEANUP_FREE char *buf = NULL;
+  struct stat statbuf;
+  int r;
+  FILE *fp;
+  CLEANUP_FREE char *cmd = NULL;
+  char buffer[GUESTFS_MAX_CHUNK_SIZE];
+
+  /* Check the filename exists and is a directory (RHBZ#908322). */
+  buf = sysroot_path (dir);
+  if (buf == NULL) {
+    reply_with_perror ("malloc");
+    return -1;
+  }
+
+  if (stat (buf, &statbuf) == -1) {
+    reply_with_perror ("stat: %s", dir);
+    return -1;
+  }
+
+  if (! S_ISDIR (statbuf.st_mode)) {
+    reply_with_error ("%s: not a directory", dir);
+    return -1;
+  }
+
+  /* Check the format is one of the permitted ones. */
+  if ((optargs_bitmask & GUESTFS_CPIO_OUT_FORMAT_BITMASK)) {
+    if (STRNEQ (format, "newc") && STRNEQ (format, "crc")) {
+      reply_with_error ("%s: format must be 'newc' or 'crc'", format);
+      return -1;
+    }
+  }
+  else
+    format = "newc";
+
+  if (asprintf_nowarn (&cmd, "cd %Q && find -print0 | %s -0 -o -H %s --quiet",
+                       buf,
+                       str_cpio,
+                       format) == -1) {
+    reply_with_perror ("asprintf");
+    return -1;
+  }
+
+  if (verbose)
+    fprintf (stderr, "%s\n", cmd);
+
+  fp = popen (cmd, "r");
+  if (fp == NULL) {
+    reply_with_perror ("%s", cmd);
+    return -1;
+  }
+
+  /* Now we must send the reply message, before the file contents.  After
+   * this there is no opportunity in the protocol to send any error
+   * message back.  Instead we can only cancel the transfer.
+   */
+  reply (NULL, NULL);
+
+  while ((r = fread (buffer, 1, sizeof buffer, fp)) > 0) {
+    if (send_file_write (buffer, r) < 0) {
+      pclose (fp);
+      return -1;
+    }
+  }
+
+  if (ferror (fp)) {
+    fprintf (stderr, "fread: %s: %m\n", dir);
+    send_file_end (1);		/* Cancel. */
+    pclose (fp);
+    return -1;
+  }
+
+  if (pclose (fp) != 0) {
+    fprintf (stderr, "pclose: %s: %m\n", dir);
+    send_file_end (1);		/* Cancel. */
+    return -1;
+  }
+
+  if (send_file_end (0))	/* Normal end of file. */
+    return -1;
+
+  return 0;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index ef3f17e..aecc63b 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -11882,6 +11882,34 @@ blocks of zero bytes when read the next time.
 If it returns false, then it may be that discarded blocks are
 read as stale or random data." };
 
+  { defaults with
+    name = "cpio_out";
+    style = RErr, [String "directory"; FileOut "cpiofile"], [OString "format"];
+    proc_nr = Some 419;
+    cancellable = true;
+    shortdesc = "pack directory into cpio file";
+    longdesc = "\
+This command packs the contents of C<directory> and downloads
+it to local file C<cpiofile>.
+
+The optional C<format> parameter can be used to select the format.
+Only the following formats are currently permitted:
+
+=over 4
+
+=item C<newc>
+
+New (SVR4) portable format.  This format happens to be compatible
+with the cpio-like format used by the Linux kernel for initramfs.
+
+This is the default format.
+
+=item C<crc>
+
+New (SVR4) portable format with a checksum.
+
+=back" };
+
 ]
 
 (* Non-API meta-commands available only in guestfish.
diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc
index cfb6ed3..3b567a2 100644
--- a/gobject/Makefile.inc
+++ b/gobject/Makefile.inc
@@ -55,6 +55,7 @@ guestfs_gobject_headers= \
   include/guestfs-gobject/optargs-copy_device_to_file.h \
   include/guestfs-gobject/optargs-copy_file_to_device.h \
   include/guestfs-gobject/optargs-copy_file_to_file.h \
+  include/guestfs-gobject/optargs-cpio_out.h \
   include/guestfs-gobject/optargs-disk_create.h \
   include/guestfs-gobject/optargs-e2fsck.h \
   include/guestfs-gobject/optargs-fstrim.h \
@@ -131,6 +132,7 @@ guestfs_gobject_sources= \
   src/optargs-copy_device_to_file.c \
   src/optargs-copy_file_to_device.c \
   src/optargs-copy_file_to_file.c \
+  src/optargs-cpio_out.c \
   src/optargs-disk_create.c \
   src/optargs-e2fsck.c \
   src/optargs-fstrim.c \
diff --git a/po/POTFILES b/po/POTFILES
index 0fac8fe..ac12815 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -27,6 +27,7 @@ daemon/cmp.c
 daemon/command.c
 daemon/compress.c
 daemon/copy.c
+daemon/cpio.c
 daemon/cpmv.c
 daemon/dd.c
 daemon/debug.c
@@ -174,6 +175,7 @@ gobject/src/optargs-copy_device_to_device.c
 gobject/src/optargs-copy_device_to_file.c
 gobject/src/optargs-copy_file_to_device.c
 gobject/src/optargs-copy_file_to_file.c
+gobject/src/optargs-cpio_out.c
 gobject/src/optargs-disk_create.c
 gobject/src/optargs-e2fsck.c
 gobject/src/optargs-fstrim.c
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 29aae8e..7b53aa0 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-418
+419
-- 
1.9.0




More information about the Libguestfs mailing list