summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-12-05 12:51:51 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2012-12-06 20:30:33 +0100
commit17c0629bbf711c06859a0e6dc46b4aa18e6449bb (patch)
treeff4ffcaab7ed7a31401a8686042b72f53d5e55d5 /tools
parent1f98157f966c42abcb31584eafba983f1b200c04 (diff)
downloadmsitools-17c0629bbf711c06859a0e6dc46b4aa18e6449bb.tar.gz
msitools-17c0629bbf711c06859a0e6dc46b4aa18e6449bb.tar.xz
msitools-17c0629bbf711c06859a0e6dc46b4aa18e6449bb.zip
msiinfo: add extract command
Diffstat (limited to 'tools')
-rw-r--r--tools/msiinfo.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/tools/msiinfo.c b/tools/msiinfo.c
index 8c36593..f55906a 100644
--- a/tools/msiinfo.c
+++ b/tools/msiinfo.c
@@ -23,9 +23,12 @@
#include "config.h"
#include "libmsi.h"
#include <stdio.h>
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
static const char *program_name;
@@ -336,6 +339,83 @@ static int cmd_suminfo(struct Command *cmd, int argc, char **argv)
libmsi_unref(si);
}
+static void full_write(int fd, char *buf, size_t sz)
+{
+ while (sz > 0) {
+ ssize_t rc = write(fd, buf, sz);
+ if (rc < 0) {
+ perror("write");
+ exit(1);
+ }
+ buf += rc;
+ sz -= rc;
+ }
+}
+
+static int cmd_extract(struct Command *cmd, int argc, char **argv)
+{
+ LibmsiDatabase *db = NULL;
+ LibmsiQuery *query = NULL;
+ LibmsiRecord *rec = NULL;
+ LibmsiResult r;
+ char *buf;
+ unsigned size, bufsize;
+
+ if (argc != 3) {
+ cmd_usage(stderr, cmd);
+ }
+
+ r = libmsi_database_open(argv[1], LIBMSI_DB_OPEN_READONLY, &db);
+ if (r) {
+ print_libmsi_error(r);
+ }
+
+ r = libmsi_database_open_query(db, "SELECT `Data` FROM `_Streams` WHERE `Name` = ?", &query);
+ if (r) {
+ print_libmsi_error(r);
+ }
+
+ rec = libmsi_record_create(1);
+ libmsi_record_set_string(rec, 1, argv[2]);
+ r = libmsi_query_execute(query, rec);
+ libmsi_unref(rec);
+ if (r) {
+ print_libmsi_error(r);
+ }
+
+ r = libmsi_query_fetch(query, &rec);
+ if (r) {
+ print_libmsi_error(r);
+ }
+
+ r = libmsi_record_save_stream(rec, 1, NULL, &size);
+ if (r) {
+ print_libmsi_error(r);
+ }
+
+ bufsize = (size > 1048576 ? 1048576 : size);
+ buf = malloc(bufsize);
+ if (!buf) {
+ perror("malloc");
+ exit(1);
+ }
+
+#if O_BINARY
+ _setmode(STDOUT_FILENO, O_BINARY);
+#endif
+
+ while (size > 0) {
+ r = libmsi_record_save_stream(rec, 1, buf, &bufsize);
+ assert(size >= bufsize);
+ full_write(STDOUT_FILENO, buf, bufsize);
+ size -= bufsize;
+ }
+
+ libmsi_unref(rec);
+ libmsi_unref(query);
+ libmsi_unref(db);
+}
+
static int cmd_export(struct Command *cmd, int argc, char **argv)
{
LibmsiDatabase *db = NULL;
@@ -396,6 +476,12 @@ static struct Command cmds[] = {
.func = cmd_tables,
},
{
+ .cmd = "extract",
+ .opts = "FILE STREAM",
+ .desc = "Extract a binary stream from an .msi file",
+ .func = cmd_extract,
+ },
+ {
.cmd = "export",
.opts = "FILE TABLE",
.desc = "Export a table in text form from an .msi file",