diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-06 19:23:36 +0100 |
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-07 10:45:48 +0100 |
| commit | d4b3a4fcc4f74b35e145844ef4982372cb459764 (patch) | |
| tree | 1ec8c5a54ee8a6511d6c94fd20a94db1ffe8db13 /tools | |
| parent | 3bae43f78b9baf75395981f3225b741c150bec64 (diff) | |
msiinfo: add export to SQL
Still not that useful since there is no tool to read it back, but it
shows how to use the API.
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/msiinfo.c | 248 |
1 files changed, 246 insertions, 2 deletions
diff --git a/tools/msiinfo.c b/tools/msiinfo.c index f55906a..0aa04bd 100644 --- a/tools/msiinfo.c +++ b/tools/msiinfo.c @@ -22,6 +22,8 @@ #include "config.h" #include "libmsi.h" + +#include <glib.h> #include <stdio.h> #include <assert.h> #include <stdlib.h> @@ -416,10 +418,246 @@ static int cmd_extract(struct Command *cmd, int argc, char **argv) libmsi_unref(db); } +static unsigned export_create_table(const char *table, + LibmsiRecord *names, + LibmsiRecord *types, + LibmsiRecord *keys) +{ + int num_columns = libmsi_record_get_field_count(names); + int num_keys = libmsi_record_get_field_count(keys); + int i, len; + unsigned r; + char type[30], name[100], size[20], extra[30]; + unsigned sz; + + + printf("CREATE TABLE `%s` (", table); + for (i = 1; i <= num_columns; i++) + { + sz = sizeof(name); + r = libmsi_record_get_string(names, i, name, &sz); + if (r) { + return r; + } + + sz = sizeof(type); + r = libmsi_record_get_string(types, i, type, &sz); + if (r) { + return r; + } + + if (i > 1) { + printf(", "); + } + + extra[0] = '\0'; + if (islower(type[0])) { + strcat(extra, " NOT NULL"); + } + + switch (type[0]) + { + case 'l': case 'L': + strcat(extra, " LOCALIZABLE"); + /* fall through */ + case 's': case 'S': + strcpy(size, type+1); + sprintf(type, "CHAR(%s)", size); + break; + case 'i': case 'I': + len = atol(type + 1); + if (len <= 2) + strcpy(type, "INT"); + else if (len == 4) + strcpy(type, "LONG"); + else + abort(); + break; + case 'v': case 'V': + strcpy(type, "OBJECT"); + break; + default: + abort(); + } + + printf("`%s` %s%s", name, type, extra); + } + for (i = 1; i <= num_keys; i++) + { + sz = sizeof(name); + r = libmsi_record_get_string(names, i, name, &sz); + if (r) { + return r; + } + + printf("%s `%s`", (i > 1 ? "," : " PRIMARY KEY"), name); + } + printf(")\n"); + return r; +} + +static void print_quoted_string(const char *s) +{ + putchar('\''); + for (; *s; s++) { + switch (*s) { + case '\n': putchar('\\'); putchar('n'); break; + case '\r': putchar('\\'); putchar('r'); break; + case '\\': putchar('\\'); putchar('\\'); break; + case '\'': putchar('\\'); putchar('\''); break; + default: putchar(*s); + } + } + putchar('\''); +} + +static unsigned export_insert(const char *table, + LibmsiRecord *names, + LibmsiRecord *types, + LibmsiRecord *vals) +{ + int num_columns = libmsi_record_get_field_count(names); + int i; + unsigned r; + char type[30], name[100]; + unsigned sz; + char *s; + + printf("INSERT INTO `%s` (", table); + for (i = 1; i <= num_columns; i++) + { + sz = sizeof(name); + r = libmsi_record_get_string(names, i, name, &sz); + if (r) { + return r; + } + + if (i > 1) { + printf(", "); + } + + printf("`%s`", name); + } + printf(") VALUES ("); + for (i = 1; i <= num_columns; i++) + { + if (i > 1) { + printf(", "); + } + + if (libmsi_record_is_null(vals, i)) { + printf("NULL"); + continue; + } + + sz = sizeof(type); + r = libmsi_record_get_string(types, i, type, &sz); + if (r) { + return r; + } + + switch (type[0]) + { + case 'l': case 'L': + case 's': case 'S': + sz = INT_MAX; + r = libmsi_record_get_string(vals, i, NULL, &sz); + if (r) { + return r; + } + + s = g_malloc(++sz); + libmsi_record_get_string(vals, i, s, &sz); + print_quoted_string(s); + g_free(s); + break; + + case 'i': case 'I': + printf("%d", libmsi_record_get_integer(vals, i)); + break; + case 'v': case 'V': + printf("''", s); + break; + default: + abort(); + } + } + printf(")\n"); + return r; +} + +static unsigned export_sql( LibmsiDatabase *db, const char *table) +{ + LibmsiRecord *name = NULL; + LibmsiRecord *type = NULL; + LibmsiRecord *keys = NULL; + LibmsiRecord *rec = NULL; + LibmsiQuery *query = NULL; + unsigned r; + char *sql; + + sql = g_strdup_printf("select * from `%s`", table); + r = libmsi_database_open_query(db, sql, &query); + if (r) { + return r; + } + + /* write out row 1, the column names */ + r = libmsi_query_get_column_info(query, LIBMSI_COL_INFO_NAMES, &name); + if (r) { + goto done; + } + + /* write out row 2, the column types */ + r = libmsi_query_get_column_info(query, LIBMSI_COL_INFO_TYPES, &type); + if (r) { + goto done; + } + + /* write out row 3, the table name + keys */ + r = libmsi_database_get_primary_keys( db, table, &keys ); + if (r) { + goto done; + } + + r = export_create_table(table, name, type, keys); + if (r) { + goto done; + } + + /* write out row 4 onwards, the data */ + while ((r = libmsi_query_fetch(query, &rec)) == LIBMSI_RESULT_SUCCESS) { + unsigned size = PATH_MAX; + r = export_insert(table, name, type, rec); + libmsi_unref(rec); + if (r) { + break; + } + } + + if (r == LIBMSI_RESULT_NO_MORE_ITEMS) { + r = LIBMSI_RESULT_SUCCESS; + } + +done: + libmsi_unref(name); + libmsi_unref(type); + libmsi_unref(keys); + libmsi_unref(query); + return r; +} + static int cmd_export(struct Command *cmd, int argc, char **argv) { LibmsiDatabase *db = NULL; LibmsiResult r; + bool sql = false; + + if (!strcmp(argv[1], "-s")) { + sql = true; + argc--; + argv++; + } if (argc != 3) { cmd_usage(stderr, cmd); @@ -430,7 +668,12 @@ static int cmd_export(struct Command *cmd, int argc, char **argv) print_libmsi_error(r); } - r = libmsi_database_export(db, argv[2], STDOUT_FILENO); + if (sql) { + r = export_sql(db, argv[2]); + } else { + r = libmsi_database_export(db, argv[2], STDOUT_FILENO); + } + if (r) { print_libmsi_error(r); } @@ -483,7 +726,8 @@ static struct Command cmds[] = { }, { .cmd = "export", - .opts = "FILE TABLE", + .opts = "[-s] FILE TABLE\n\nOptions:\n" + " -s Format output as an SQL query", .desc = "Export a table in text form from an .msi file", .func = cmd_export, }, |
