diff options
-rw-r--r-- | makemsi.c | 103 |
1 files changed, 81 insertions, 22 deletions
@@ -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 | */ | ||
49 | typedef uint32_t MsiHandle; | ||
50 | static void **msi_handles = NULL; | ||
51 | static size_t n_msi_handles = 0, msi_handles_size = 0; | ||
52 | |||
53 | static 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 | |||
71 | static 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 | |||
82 | static 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 | ||
45 | uint32_t MsiOpenDatabaseW(const char16_t *filename, | 89 | uint32_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 | ||
71 | uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder, | 115 | uint32_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 | ||
95 | uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query, | 139 | static 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 | |||
146 | uint32_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 | ||
125 | uint32_t MsiViewExecute(MsiView *view, void *params) | 176 | uint32_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 | ||
137 | MsiRecord *MsiCreateRecord(uint32_t nparams) | 188 | static MsiRecord *lookup_handle_record(MsiHandle handle) |
189 | { | ||
190 | MsiRecord *toret = lookup_handle(handle); | ||
191 | assert(toret->t.type == RECORD); | ||
192 | return toret; | ||
193 | } | ||
194 | |||
195 | MsiHandle 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 | ||
148 | uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value) | 206 | uint32_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 | ||
157 | uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path) | 215 | uint32_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 | ||
166 | uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec) | 224 | uint32_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 | ||
187 | uint32_t MsiCloseHandle(MsiTypePrefix *t) | 245 | uint32_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 | ||
197 | uint32_t MsiDatabaseCommit(MsiMainCtx *ctx) | 256 | uint32_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(" '"); |