diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2012-11-30 19:11:21 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2012-12-06 20:30:31 +0100 |
commit | a10f8ef403ca688bdf506db1bed79734437ae75e (patch) | |
tree | a3be38dcc6e8d4a7fc105f8b977f43d47221b651 /tools | |
parent | 27ffbe6482ce7ab301e2764cd6e659eb95de68e1 (diff) | |
download | msitools-a10f8ef403ca688bdf506db1bed79734437ae75e.tar.gz msitools-a10f8ef403ca688bdf506db1bed79734437ae75e.tar.xz msitools-a10f8ef403ca688bdf506db1bed79734437ae75e.zip |
msibuild: new tool
Converted from winemsibuilder, using the _Streams table instead of
the OLE storage API. The command-line is also a bit more powerful.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/msibuild.c | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/tools/msibuild.c b/tools/msibuild.c new file mode 100644 index 0000000..df14d90 --- /dev/null +++ b/tools/msibuild.c @@ -0,0 +1,178 @@ +/* + * winemsibuilder - tool to build MSI packages + * + * Copyright 2010 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/stat.h> +#include <libmsi.h> + +LibmsiDatabase *db; + +LibmsiResult open_database(const char *msifile, LibmsiDatabase **db) +{ + LibmsiResult r; + struct stat st; + + if (stat(msifile, &st) == -1) + { + r = libmsi_database_open(msifile, LIBMSI_DB_OPEN_CREATE, db); + if (r != LIBMSI_RESULT_SUCCESS) + { + fprintf(stderr, "failed to create package database %s (%u)\n", msifile, r); + return r; + } + r = libmsi_database_commit(*db); + if (r != LIBMSI_RESULT_SUCCESS) + { + fprintf(stderr, "failed to commit database (%u)\n", r); + libmsi_unref(*db); + return r; + } + } + else + { + r = libmsi_database_open(msifile, LIBMSI_DB_OPEN_TRANSACT, db); + if (r != LIBMSI_RESULT_SUCCESS) + { + fprintf(stderr, "failed to open package database %s (%u)\n", msifile, r); + return r; + } + } + + return r; +} + +static int import_table(char *table) +{ + LibmsiResult r; + char dir[PATH_MAX]; + + if (getcwd(dir, PATH_MAX) == NULL) + return 1; + + r = libmsi_database_import(db, dir, table); + if (r != LIBMSI_RESULT_SUCCESS) + { + fprintf(stderr, "failed to import table %s (%u)\n", table, r); + } + + return (r != LIBMSI_RESULT_SUCCESS); +} + +static int add_stream(const char *stream, const char *file) +{ + LibmsiResult r; + LibmsiRecord *rec; + LibmsiQuery *query; + + rec = libmsi_record_create(2); + libmsi_record_set_string(rec, 1, stream); + r = libmsi_record_load_stream(rec, 2, file); + if (r != LIBMSI_RESULT_SUCCESS) + fprintf(stderr, "failed to load stream (%u)\n", r); + + r = libmsi_database_open_query(db, + "INSERT INTO `_Streams` (`Name`, `Data`) VALUES (?, ?)", &query); + if (r != LIBMSI_RESULT_SUCCESS) + fprintf(stderr, "failed to open query (%u)\n", r); + + r = libmsi_query_execute(query, rec); + if (r != LIBMSI_RESULT_SUCCESS) + fprintf(stderr, "failed to execute query (%u)\n", r); + + libmsi_unref(rec); + libmsi_query_close(query); + libmsi_unref(query); + return 0; +} + +static void show_usage(void) +{ + printf( + "Usage: msibuild MSIFILE [OPTION]...\n" + "Options:\n" + " -i table1.idt Import one table into the database.\n" + " -a stream file Add 'stream' to storage with contents of 'file'.\n" + "\nExisting tables or streams will be overwritten. If package.msi does not exist a new file\n" + "will be created with an empty database.\n" + ); +} + +int main(int argc, char *argv[]) +{ + int r; + + if (argc <= 2 ) + { + show_usage(); + return 1; + } + + /* Accept package after first option for winemsibuilder compatibility. */ + if (argc >= 3 && argv[1][0] == '-') { + r = open_database(argv[2], &db); + argv[2] = argv[1]; + } else { + r = open_database(argv[1], &db); + } + if (r != LIBMSI_RESULT_SUCCESS) return 1; + + argc -= 2, argv += 2; + while (argc > 0) { + int ret; + if (argc < 2 || argv[0][0] != '-' || argv[0][2]) + { + show_usage(); + return 1; + } + + switch (argv[0][1]) + { + case 'i': + do { + ret = import_table(argv[1]); + argc--, argv++; + } while (argv[1] && argv[1][0] != '-'); + argc--, argv++; + break; + case 'a': + if (argc < 3) break; + ret = add_stream(argv[1], argv[2]); + argc -= 3, argv += 3; + break; + default: + fprintf(stdout, "unknown option\n"); + show_usage(); + break; + } + if (r != LIBMSI_RESULT_SUCCESS) { + break; + } + } + + if (r == LIBMSI_RESULT_SUCCESS) { + r = libmsi_database_commit(db); + if (r != LIBMSI_RESULT_SUCCESS) + fprintf(stderr, "failed to commit database (%u)\n", r); + } + libmsi_unref(db); + return r != LIBMSI_RESULT_SUCCESS; +} |