aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makemsi.c103
1 files changed, 81 insertions, 22 deletions
diff --git a/makemsi.c b/makemsi.c
index 8b78448..a301319 100644
--- a/makemsi.c
+++ b/makemsi.c
@@ -41,10 +41,54 @@ typedef struct MsiMainCtx {
41 int nargs, argsize; 41 int nargs, argsize;
42} MsiMainCtx; 42} MsiMainCtx;
43 43
44/*
45 * The Msi functions will expect to identify things by 32-bit handles,
46 * not machine-word sized pointers. So we must keep a list of handles
47 * we've allocated.
48 */
49typedef uint32_t MsiHandle;
50static void **msi_handles = NULL;
51static size_t n_msi_handles = 0, msi_handles_size = 0;
52
53static MsiHandle make_handle(void *ptr)
54{
55 size_t index;
56
57 if (n_msi_handles >= msi_handles_size) {
58 msi_handles_size = n_msi_handles * 5 / 4 + 512;
59 msi_handles = sresize(msi_handles, msi_handles_size, void *);
60 }
61
62 index = n_msi_handles++;
63 msi_handles[index] = ptr;
64
65 /*
66 * A mild error-correcting code, to ensure our handles make sense.
67 */
68 return index * 59 + 17;
69}
70
71static void *lookup_handle(MsiHandle h)
72{
73 size_t index;
74
75 assert(h % 59 == 17);
76 index = h / 59;
77
78 assert(index < n_msi_handles);
79 return msi_handles[index];
80}
81
82static MsiMainCtx *lookup_handle_main(MsiHandle handle)
83{
84 MsiMainCtx *toret = lookup_handle(handle);
85 assert(toret->t.type == MAIN);
86 return toret;
87}
44 88
45uint32_t MsiOpenDatabaseW(const char16_t *filename, 89uint32_t MsiOpenDatabaseW(const char16_t *filename,
46 const char16_t *persist, 90 const char16_t *persist,
47 MsiMainCtx **out_ctx) 91 MsiHandle *out_handle)
48{ 92{
49 MsiMainCtx *ctx = snew(MsiMainCtx); 93 MsiMainCtx *ctx = snew(MsiMainCtx);
50 ctx->t.type = MAIN; 94 ctx->t.type = MAIN;
@@ -64,14 +108,14 @@ uint32_t MsiOpenDatabaseW(const char16_t *filename,
64 ctx->args[ctx->nargs++] = dupstr(ctx->tempdir); 108 ctx->args[ctx->nargs++] = dupstr(ctx->tempdir);
65 ctx->args[ctx->nargs++] = dupstr("msibuild"); 109 ctx->args[ctx->nargs++] = dupstr("msibuild");
66 ctx->args[ctx->nargs++] = dupstr(ctx->outfile); 110 ctx->args[ctx->nargs++] = dupstr(ctx->outfile);
67 *out_ctx = ctx; 111 *out_handle = make_handle(ctx);
68 return 0; 112 return 0;
69} 113}
70 114
71uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, 115uint32_t MsiDatabaseImportW(MsiHandle handle, const char16_t *folder,
72 const char16_t *file) 116 const char16_t *file)
73{ 117{
74 assert(ctx->t.type == MAIN); 118 MsiMainCtx *ctx = lookup_handle_main(handle);
75 system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"", 119 system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"",
76 ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL); 120 ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL);
77 if (ctx->nargs + 2 >= ctx->argsize) { 121 if (ctx->nargs + 2 >= ctx->argsize) {
@@ -92,10 +136,17 @@ typedef struct MsiView {
92 MsiMainCtx *ctx; 136 MsiMainCtx *ctx;
93} MsiView; 137} MsiView;
94 138
95uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, 139static MsiView *lookup_handle_view(MsiHandle handle)
96 MsiView **outview)
97{ 140{
98 assert(ctx->t.type == MAIN); 141 MsiView *toret = lookup_handle(handle);
142 assert(toret->t.type == VIEW);
143 return toret;
144}
145
146uint32_t MsiDatabaseOpenViewW(MsiHandle handle, const char16_t *query,
147 MsiHandle *outhandle)
148{
149 MsiMainCtx *ctx = lookup_handle_main(handle);
99 MsiView *view = snew(MsiView); 150 MsiView *view = snew(MsiView);
100 view->t.type = VIEW; 151 view->t.type = VIEW;
101 view->ctx = ctx; 152 view->ctx = ctx;
@@ -118,13 +169,13 @@ uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query,
118 if (mkdir(view->targetdir, 0777) < 0) 169 if (mkdir(view->targetdir, 0777) < 0)
119 err(1, "%s: mkdir", view->targetdir); 170 err(1, "%s: mkdir", view->targetdir);
120 } 171 }
121 *outview = view; 172 *outhandle = make_handle(view);
122 return 0; 173 return 0;
123} 174}
124 175
125uint32_t MsiViewExecute(MsiView *view, void *params) 176uint32_t MsiViewExecute(MsiHandle handle, void *params)
126{ 177{
127 assert(view->t.type == VIEW); 178 lookup_handle_view(handle);
128 return 0; 179 return 0;
129} 180}
130 181
@@ -134,7 +185,14 @@ typedef struct MsiRecord {
134 char *name, *data; 185 char *name, *data;
135} MsiRecord; 186} MsiRecord;
136 187
137MsiRecord *MsiCreateRecord(uint32_t nparams) 188static MsiRecord *lookup_handle_record(MsiHandle handle)
189{
190 MsiRecord *toret = lookup_handle(handle);
191 assert(toret->t.type == RECORD);
192 return toret;
193}
194
195MsiHandle MsiCreateRecord(uint32_t nparams)
138{ 196{
139 MsiRecord *rec = snew(MsiRecord); 197 MsiRecord *rec = snew(MsiRecord);
140 rec->t.type = RECORD; 198 rec->t.type = RECORD;
@@ -142,31 +200,31 @@ MsiRecord *MsiCreateRecord(uint32_t nparams)
142 if (nparams != 2) 200 if (nparams != 2)
143 errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams); 201 errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams);
144 rec->name = rec->data = NULL; 202 rec->name = rec->data = NULL;
145 return rec; 203 return make_handle(rec);
146} 204}
147 205
148uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) 206uint32_t MsiRecordSetStringW(MsiHandle handle, uint32_t field, char16_t *value)
149{ 207{
150 assert(rec->t.type == RECORD); 208 MsiRecord *rec = lookup_handle_record(handle);
151 if (field != 1) 209 if (field != 1)
152 errx(1, "bad MsiRecordSetString param index %u", (unsigned)field); 210 errx(1, "bad MsiRecordSetString param index %u", (unsigned)field);
153 rec->name = ascii(value, false); 211 rec->name = ascii(value, false);
154 return 0; 212 return 0;
155} 213}
156 214
157uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) 215uint32_t MsiRecordSetStreamW(MsiHandle handle, uint32_t field, char16_t *path)
158{ 216{
159 assert(rec->t.type == RECORD); 217 MsiRecord *rec = lookup_handle_record(handle);
160 if (field != 2) 218 if (field != 2)
161 errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field); 219 errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field);
162 rec->data = ascii(path, true); 220 rec->data = ascii(path, true);
163 return 0; 221 return 0;
164} 222}
165 223
166uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) 224uint32_t MsiViewModify(MsiHandle viewhandle, uint32_t mode, MsiHandle rechandle)
167{ 225{
168 assert(view->t.type == VIEW); 226 MsiView *view = lookup_handle_view(viewhandle);
169 assert(rec->t.type == RECORD); 227 MsiRecord *rec = lookup_handle_record(rechandle);
170 if (view->fp) { 228 if (view->fp) {
171 system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"", 229 system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"",
172 rec->data, view->targetdir, rec->name, cNULL); 230 rec->data, view->targetdir, rec->name, cNULL);
@@ -184,8 +242,9 @@ uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec)
184 return 0; 242 return 0;
185} 243}
186 244
187uint32_t MsiCloseHandle(MsiTypePrefix *t) 245uint32_t MsiCloseHandle(MsiHandle handle)
188{ 246{
247 MsiTypePrefix *t = lookup_handle(handle);
189 if (t->type == VIEW) { 248 if (t->type == VIEW) {
190 MsiView *view = (MsiView *)t; 249 MsiView *view = (MsiView *)t;
191 if (view->fp) 250 if (view->fp)
@@ -194,9 +253,9 @@ uint32_t MsiCloseHandle(MsiTypePrefix *t)
194 return 0; 253 return 0;
195} 254}
196 255
197uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) 256uint32_t MsiDatabaseCommit(MsiHandle handle)
198{ 257{
199 assert(ctx->t.type == MAIN); 258 MsiMainCtx *ctx = lookup_handle_main(handle);
200 printf("commit:"); 259 printf("commit:");
201 for (int i = 0; i < ctx->nargs; i++) { 260 for (int i = 0; i < ctx->nargs; i++) {
202 printf(" '"); 261 printf(" '");