aboutsummaryrefslogtreecommitdiff
path: root/makemsi.c
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2017-05-18 08:26:44 +0100
committerSimon Tatham <anakin@pobox.com>2017-05-18 08:27:29 +0100
commita568db73a69a934c09ad5c95f5a218fb6b869298 (patch)
tree301b9b7c78e132bad0955c8c9cb9ccc49999abae /makemsi.c
parent7ca5ab5ef2eb8bb0f65aedf11eb74ad2ada78a19 (diff)
downloadwix-on-linux-a568db73a69a934c09ad5c95f5a218fb6b869298.tar.gz
wix-on-linux-a568db73a69a934c09ad5c95f5a218fb6b869298.tar.bz2
wix-on-linux-a568db73a69a934c09ad5c95f5a218fb6b869298.zip
Rename fake-msi.c to makemsi.c.
It's now a sensible source flie containing a set of routines that do something coherently connected to each other, so it doesn't deserve that 'fake-' prefix that I used for the previous monolithic files full of tangled-together stuff. While I'm here, I've also made up nicer (i.e. more distinguishable) random magic numbers for the structure-type disambiguation.
Diffstat (limited to 'makemsi.c')
-rw-r--r--makemsi.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/makemsi.c b/makemsi.c
new file mode 100644
index 0000000..8b78448
--- /dev/null
+++ b/makemsi.c
@@ -0,0 +1,220 @@
1#include <assert.h>
2#include <stdio.h>
3#include <stdint.h>
4#include <string.h>
5#include <limits.h>
6#include <uchar.h>
7
8#include <err.h>
9
10#include <fcntl.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <unistd.h>
14
15#include "memory.h"
16#include "dupstr.h"
17#include "subproc.h"
18#include "uchars.h"
19
20/*
21 * The same routine MsiCloseHandle is used by our client to dispose of
22 * three kinds of structure that _we_ think of as completely different
23 * types. So we must ensure all three start with distinct magic number
24 * fields, so as to know what kind we're being asked to close.
25 */
26typedef struct MsiTypePrefix {
27 enum {
28 MAIN = 0x2B7FB8B8,
29 VIEW = 0x1570B0E3,
30 RECORD = 0x62365065
31 } type;
32} MsiTypePrefix;
33
34typedef struct MsiMainCtx {
35 MsiTypePrefix t;
36
37 char *tempdir;
38 char *outfile;
39
40 char **args;
41 int nargs, argsize;
42} MsiMainCtx;
43
44
45uint32_t MsiOpenDatabaseW(const char16_t *filename,
46 const char16_t *persist,
47 MsiMainCtx **out_ctx)
48{
49 MsiMainCtx *ctx = snew(MsiMainCtx);
50 ctx->t.type = MAIN;
51 ctx->outfile = ascii(filename, true);
52 close(open(ctx->outfile, O_CREAT | O_WRONLY, 0666));
53 ctx->outfile = realpath(ctx->outfile, NULL);
54 unlink(ctx->outfile);
55 ctx->tempdir = dupcat(ctx->outfile, "-msiXXXXXX", cNULL);
56 if (!mkdtemp(ctx->tempdir))
57 err(1, "%s: mkdtemp", ctx->tempdir);
58 ctx->nargs = 0;
59 ctx->argsize = 16;
60 ctx->args = snewn(ctx->argsize, char *);
61 ctx->args[ctx->nargs++] = dupstr("sh");
62 ctx->args[ctx->nargs++] = dupstr("-c");
63 ctx->args[ctx->nargs++] = dupstr("cd \"$0\" && \"$@\"");
64 ctx->args[ctx->nargs++] = dupstr(ctx->tempdir);
65 ctx->args[ctx->nargs++] = dupstr("msibuild");
66 ctx->args[ctx->nargs++] = dupstr(ctx->outfile);
67 *out_ctx = ctx;
68 return 0;
69}
70
71uint32_t MsiDatabaseImportW(MsiMainCtx *ctx, const char16_t *folder,
72 const char16_t *file)
73{
74 assert(ctx->t.type == MAIN);
75 system_argv("sh", "-c", "cd \"$0\" && cp \"$1\" \"$2\"",
76 ascii(folder, true), ascii(file, true), ctx->tempdir, cNULL);
77 if (ctx->nargs + 2 >= ctx->argsize) {
78 ctx->argsize = ctx->nargs * 5 / 4 + 16;
79 ctx->args = sresize(ctx->args, ctx->argsize, char *);
80 }
81 ctx->args[ctx->nargs++] = dupstr("-i");
82 ctx->args[ctx->nargs++] = dupcat(ctx->tempdir, "/", ascii(file, true),
83 cNULL);
84 return 0;
85}
86
87typedef struct MsiView {
88 MsiTypePrefix t;
89
90 FILE *fp;
91 char *targetdir;
92 MsiMainCtx *ctx;
93} MsiView;
94
95uint32_t MsiDatabaseOpenViewW(MsiMainCtx *ctx, const char16_t *query,
96 MsiView **outview)
97{
98 assert(ctx->t.type == MAIN);
99 MsiView *view = snew(MsiView);
100 view->t.type = VIEW;
101 view->ctx = ctx;
102 char *cquery = ascii(query, false);
103 if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `_Streams`"))
104 view->fp = NULL; /* special case */
105 else {
106 if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Binary`")) {
107 view->fp = fopen(dupcat(ctx->tempdir, "/", "Binary.idt", cNULL),
108 "a");
109 view->targetdir = dupcat(ctx->tempdir, "/", "Binary", cNULL);
110 } else if (!strcmp(cquery, "SELECT `Name`, `Data` FROM `Icon`")) {
111 view->fp = fopen(dupcat(ctx->tempdir, "/", "Icon.idt", cNULL),
112 "a");
113 view->targetdir = dupcat(ctx->tempdir, "/", "Icon", cNULL);
114 } else
115 errx(1, "unrecognised query: %s", cquery);
116 if (!view->fp)
117 err(1, "open");
118 if (mkdir(view->targetdir, 0777) < 0)
119 err(1, "%s: mkdir", view->targetdir);
120 }
121 *outview = view;
122 return 0;
123}
124
125uint32_t MsiViewExecute(MsiView *view, void *params)
126{
127 assert(view->t.type == VIEW);
128 return 0;
129}
130
131typedef struct MsiRecord {
132 MsiTypePrefix t;
133
134 char *name, *data;
135} MsiRecord;
136
137MsiRecord *MsiCreateRecord(uint32_t nparams)
138{
139 MsiRecord *rec = snew(MsiRecord);
140 rec->t.type = RECORD;
141
142 if (nparams != 2)
143 errx(1, "bad MsiCreateRecord param count %u", (unsigned)nparams);
144 rec->name = rec->data = NULL;
145 return rec;
146}
147
148uint32_t MsiRecordSetStringW(MsiRecord *rec, uint32_t field, char16_t *value)
149{
150 assert(rec->t.type == RECORD);
151 if (field != 1)
152 errx(1, "bad MsiRecordSetString param index %u", (unsigned)field);
153 rec->name = ascii(value, false);
154 return 0;
155}
156
157uint32_t MsiRecordSetStreamW(MsiRecord *rec, uint32_t field, char16_t *path)
158{
159 assert(rec->t.type == RECORD);
160 if (field != 2)
161 errx(1, "bad MsiRecordSetStream param index %u", (unsigned)field);
162 rec->data = ascii(path, true);
163 return 0;
164}
165
166uint32_t MsiViewModify(MsiView *view, uint32_t mode, MsiRecord *rec)
167{
168 assert(view->t.type == VIEW);
169 assert(rec->t.type == RECORD);
170 if (view->fp) {
171 system_argv("sh", "-c", "cp \"$0\" \"$1\"/\"$2\"",
172 rec->data, view->targetdir, rec->name, cNULL);
173 fprintf(view->fp, "%s\t%s\r\n", rec->name, rec->name);
174 } else {
175 MsiMainCtx *ctx = view->ctx;
176 if (ctx->nargs + 3 >= ctx->argsize) {
177 ctx->argsize = ctx->nargs * 5 / 4 + 16;
178 ctx->args = sresize(ctx->args, ctx->argsize, char *);
179 }
180 ctx->args[ctx->nargs++] = dupstr("-a");
181 ctx->args[ctx->nargs++] = dupstr(rec->name);
182 ctx->args[ctx->nargs++] = dupstr(rec->data);
183 }
184 return 0;
185}
186
187uint32_t MsiCloseHandle(MsiTypePrefix *t)
188{
189 if (t->type == VIEW) {
190 MsiView *view = (MsiView *)t;
191 if (view->fp)
192 fclose(view->fp);
193 }
194 return 0;
195}
196
197uint32_t MsiDatabaseCommit(MsiMainCtx *ctx)
198{
199 assert(ctx->t.type == MAIN);
200 printf("commit:");
201 for (int i = 0; i < ctx->nargs; i++) {
202 printf(" '");
203 for (const char *p = ctx->args[i]; *p; p++) {
204 if (*p == '\'')
205 printf("'\\''");
206 else
207 putchar(*p);
208 }
209 printf("'");
210 }
211 printf("\n");
212
213 if (ctx->nargs + 1 >= ctx->argsize) {
214 ctx->argsize = ctx->nargs * 5 / 4 + 16;
215 ctx->args = sresize(ctx->args, ctx->argsize, char *);
216 }
217 ctx->args[ctx->nargs++] = NULL;
218 system_argv_array(ctx->args);
219 return 0;
220}