[Libguestfs] [PATCH] filearch: support gzip/xz-compressed files

Pino Toscano ptoscano at redhat.com
Tue Apr 14 09:21:26 UTC 2015


Extract them to find out the architecture of the data they hold.
Useful to detect the architecture of e.g. compressed Linux modules.

Provide in the test.iso two samples (compressing existing test data) of
binaries compressed with gzip and xz.
---
 .gitignore             |  2 ++
 generator/actions.ml   |  4 ++++
 src/filearch.c         | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/data/Makefile.am | 12 ++++++++++
 4 files changed, 82 insertions(+)

diff --git a/.gitignore b/.gitignore
index 9c329a0..abfaaf3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -515,12 +515,14 @@ Makefile.in
 /tests/data/100krandom
 /tests/data/10klines
 /tests/data/abssymlink
+/tests/data/bin-x86_64-dynamic.gz
 /tests/data/blank-disk-*
 /tests/data/blank-disk-*
 /tests/data/hello.b64
 /tests/data/initrd
 /tests/data/initrd-x86_64.img
 /tests/data/initrd-x86_64.img.gz
+/tests/data/lib-i586.so.xz
 /tests/data/test-grep.txt.gz
 /tests/data/test.iso
 /tests/disks/test-qemu-drive-libvirt.xml
diff --git a/generator/actions.ml b/generator/actions.ml
index 11ea436..1a89869 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -813,6 +813,10 @@ to specify the QEMU interface emulation to use at run time." };
         [["file_architecture"; "/initrd-x86_64.img"]], "x86_64"), [];
       InitISOFS, Always, TestResultString (
         [["file_architecture"; "/initrd-x86_64.img.gz"]], "x86_64"), [];
+      InitISOFS, Always, TestResultString (
+        [["file_architecture"; "/bin-x86_64-dynamic.gz"]], "x86_64"), [];
+      InitISOFS, Always, TestResultString (
+        [["file_architecture"; "/lib-i586.so.xz"]], "i386"), [];
     ];
     shortdesc = "detect the architecture of a binary file";
     longdesc = "\
diff --git a/src/filearch.c b/src/filearch.c
index 219eaae..df65c98 100644
--- a/src/filearch.c
+++ b/src/filearch.c
@@ -250,6 +250,66 @@ cpio_arch (guestfs_h *g, const char *file, const char *path)
   return ret;
 }
 
+static char *
+compressed_file_arch (guestfs_h *g, const char *path, const char *method)
+{
+  CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g), *dir = NULL;
+  CLEANUP_FREE char *tempfile = NULL, *tempfile_extracted = NULL;
+  CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
+  char *ret = NULL;
+  int64_t size;
+  int r;
+  bool matched;
+
+  if (asprintf (&dir, "%s/libguestfsXXXXXX", tmpdir) == -1) {
+    perrorf (g, "asprintf");
+    return NULL;
+  }
+
+  /* Security: Refuse to download file if it is huge. */
+  size = guestfs_filesize (g, path);
+  if (size == -1 || size > 10000000) {
+    error (g, _("size of %s unreasonable (%" PRIi64 " bytes)"),
+           path, size);
+    goto out;
+  }
+
+  if (mkdtemp (dir) == NULL) {
+    perrorf (g, "mkdtemp");
+    goto out;
+  }
+
+  tempfile = safe_asprintf (g, "%s/file", dir);
+  if (guestfs_download (g, path, tempfile) == -1)
+    goto out;
+
+  tempfile_extracted = safe_asprintf (g, "%s/file_extracted", dir);
+
+  /* Construct a command to extract named binaries from the initrd file. */
+  guestfs_int_cmd_add_string_unquoted (cmd, method);
+  guestfs_int_cmd_add_string_unquoted (cmd, " ");
+  guestfs_int_cmd_add_string_quoted (cmd, tempfile);
+  guestfs_int_cmd_add_string_unquoted (cmd, " > ");
+  guestfs_int_cmd_add_string_quoted (cmd, tempfile_extracted);
+
+  r = guestfs_int_cmd_run (cmd);
+  if (r == -1)
+    goto out;
+  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
+    guestfs_int_external_command_failed (g, r, method, path);
+    goto out;
+  }
+
+  ret = magic_for_file (g, tempfile_extracted, NULL, &matched);
+  if (!matched)
+    error (g, "file_architecture: could not determine architecture of compressed file");
+
+ out:
+  guestfs_int_recursive_remove_dir (g, dir);
+
+  return ret;
+}
+
 char *
 guestfs_impl_file_architecture (guestfs_h *g, const char *path)
 {
@@ -272,6 +332,10 @@ guestfs_impl_file_architecture (guestfs_h *g, const char *path)
     ret = safe_strdup (g, "x86_64");
   else if (strstr (file, "cpio archive"))
     ret = cpio_arch (g, file, path);
+  else if (strstr (file, "gzip compressed data"))
+    ret = compressed_file_arch (g, path, "zcat");
+  else if (strstr (file, "XZ compressed data"))
+    ret = compressed_file_arch (g, path, "xzcat");
   else
     error (g, "file_architecture: unknown architecture: %s", path);
 
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index dd7c01a..b0bf58a 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -76,6 +76,7 @@ images_files_build = \
 	100kallspaces \
 	100krandom \
 	10klines \
+	bin-x86_64-dynamic.gz \
 	blank-disk-1s.raw \
 	blank-disk-1s.qcow2 \
 	blank-disk-1K.raw \
@@ -87,6 +88,7 @@ images_files_build = \
 	initrd \
 	initrd-x86_64.img \
 	initrd-x86_64.img.gz \
+	lib-i586.so.xz \
 	test-grep.txt.gz
 
 check_DATA = $(images_files_build) test.iso
@@ -193,3 +195,13 @@ test-grep.txt.gz: test-grep.txt
 	rm -f $@ $@-t
 	gzip --best -c $< > $@-t
 	mv $@-t $@
+
+bin-x86_64-dynamic.gz: bin-x86_64-dynamic
+	rm -f $@ $@-t
+	gzip --best -c $< > $@-t
+	mv $@-t $@
+
+lib-i586.so.xz: lib-i586.so
+	rm -f $@ $@-t
+	xz -c $< > $@-t
+	mv $@-t $@
-- 
2.1.0




More information about the Libguestfs mailing list