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