summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-11-30 19:11:21 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2012-12-06 20:30:31 +0100
commita10f8ef403ca688bdf506db1bed79734437ae75e (patch)
treea3be38dcc6e8d4a7fc105f8b977f43d47221b651 /tools
parent27ffbe6482ce7ab301e2764cd6e659eb95de68e1 (diff)
downloadmsitools-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.c178
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;
+}