15 static void addprotofile(char *new, char *old, Dir *d, void *a);
24 fprint(2, "usage: mk9660 [-D:] [-9cjr] [-b bootfile] [-p proto] [-s src] cdimage\n");
26 fprint(2, "usage: dump9660 [-D:] [-9cjr] [-m maxsize] [-n now] [-p proto] [-s src] cdimage\n");
31 main(int argc, char **argv)
34 char buf[256], *dumpname, *proto, *s, *src, *status;
35 ulong block, length, newnull, cblock, clength, maxsize;
39 Direc *iconform, idumproot, iroot, *jconform, jdumproot, jroot, *r;
44 memset(&info, 0, sizeof info);
45 proto = unsharp("#9/proto/allproto");
48 info.volumename = atom("9CD");
49 info.volumeset = atom("9VolumeSet");
50 info.publisher = atom("9Publisher");
51 info.preparer = atom("dump9660");
52 info.application = atom("dump9660");
56 fmtinstall('H', encodefmt);
64 argv0 = "disk/mk9660";
65 info.flags &= ~CDdump;
68 info.flags |= CDplan9;
79 info.flags |= CDbootable;
80 info.bootimage = EARGF(usage());
83 info.flags |= CDconform;
89 info.flags |= CDjoliet;
92 now = atoi(EARGF(usage()));
95 maxsize = strtoul(EARGF(usage()), 0, 0);
98 proto = EARGF(usage());
101 info.flags |= CDrockridge;
104 src = EARGF(usage());
107 info.volumename = atom(EARGF(usage()));
113 if(mk9660 && (fix || now || maxsize))
120 now = (ulong)time(0);
122 if((cd = createcd(argv[0], info)) == nil)
123 sysfatal("cannot create '%s': %r", argv[0]);
125 if((cd = opencd(argv[0], info)) == nil)
126 sysfatal("cannot open '%s': %r", argv[0]);
127 if(!(cd->flags & CDdump))
128 sysfatal("not a dump cd");
131 /* create ISO9660/Plan 9 tree in memory */
132 memset(&dir, 0, sizeof dir);
134 dir.uid = atom("sys");
135 dir.gid = atom("sys");
138 dir.mode = DMDIR | 0755;
143 mkdirec(&iroot, &dir);
147 * Read new files into memory
149 if(rdproto(proto, src, addprotofile, 0, &iroot) < 0)
150 sysfatal("rdproto: %r");
153 dump = emalloc(sizeof *dump);
157 * Read current dump tree and _conform.map.
159 idumproot = readdumpdirs(cd, &dir, isostring);
161 if(cd->flags & CDjoliet)
162 jdumproot = readdumpdirs(cd, &dir, jolietstring);
166 cd->nextblock = cd->nulldump+1;
168 Cwseek(cd, cd->nextblock*Blocksize);
172 dumpname = adddumpdir(&idumproot, now, &dir);
173 /* note that we assume all names are conforming and thus sorted */
174 if(cd->flags & CDjoliet) {
175 s = adddumpdir(&jdumproot, now, &dir);
177 sysfatal("dumpnames don't match %s %s\n", dumpname, s);
179 dump = dumpcd(cd, &idumproot);
180 cd->nextblock = cd->nulldump+1;
184 * Write new files, starting where the dump tree was.
185 * Must be done before creation of the Joliet tree so that
186 * blocks and lengths are correct.
188 Cwseek(cd, cd->nextblock*Blocksize);
189 writefiles(dump, cd, &iroot);
192 findbootimage(cd, &iroot);
196 /* create Joliet tree */
197 if(cd->flags & CDjoliet)
198 copydirec(&jroot, &iroot);
200 if(info.flags & CDconform) {
201 checknames(&iroot, isbadiso9660);
202 convertnames(&iroot, struprcpy);
204 convertnames(&iroot, (char* (*)(char*, char*))strcpy);
206 /* isoabstract = findconform(&iroot, abstract); */
207 /* isobiblio = findconform(&iroot, biblio); */
208 /* isonotice = findconform(&iroot, notice); */
210 dsort(&iroot, isocmp);
212 if(cd->flags & CDjoliet) {
213 /* jabstract = findconform(&jroot, abstract); */
214 /* jbiblio = findconform(&jroot, biblio); */
215 /* jnotice = findconform(&jroot, notice); */
217 checknames(&jroot, isbadjoliet);
218 convertnames(&jroot, (char* (*)(char*, char*))strcpy);
219 dsort(&jroot, jolietcmp);
225 writedirs(cd, &iroot, Cputisodir);
226 if(cd->flags & CDjoliet)
227 writedirs(cd, &jroot, Cputjolietdir);
235 * Write incremental _conform.map block.
237 wrconform(cd, cd->nconform, &cblock, &clength);
239 /* jump here if we're just fixing up the cd */
242 * Write null dump header block; everything after this will be
243 * overwritten at the next dump. Because of this, it needs to be
244 * reconstructable. We reconstruct the _conform.map and dump trees
245 * from the header blocks in dump.c, and we reconstruct the path
246 * tables by walking the cd.
248 newnull = Cputdumpblock(cd);
252 * Write _conform.map.
255 if(cd->flags & (CDconform|CDjoliet)) {
256 if(!mk9660 && cd->nconform == 0){
260 wrconform(cd, 0, &block, &length);
268 /* The ISO9660 name will get turned into uppercase when written. */
269 if((iconform = walkdirec(&idumproot, "_conform.map")) == nil)
270 iconform = adddirec(&idumproot, "_conform.map", &dir);
272 if(cd->flags & CDjoliet) {
273 if((jconform = walkdirec(&jdumproot, "_conform.map")) == nil)
274 jconform = adddirec(&jdumproot, "_conform.map", &dir);
276 iconform->block = block;
277 iconform->length = length;
278 if(cd->flags & CDjoliet) {
279 jconform->block = block;
280 jconform->length = length;
291 * Patch in root directories.
293 setroot(cd, cd->iso9660pvd, iroot.block, iroot.length);
294 setvolsize(cd, cd->iso9660pvd, cd->nextblock*Blocksize);
295 if(cd->flags & CDjoliet){
296 setroot(cd, cd->jolietsvd, jroot.block, jroot.length);
297 setvolsize(cd, cd->jolietsvd, cd->nextblock*Blocksize);
301 * Write dump tree at end. We assume the name characters
302 * are all conforming, so everything is already sorted properly.
304 convertnames(&idumproot, (info.flags & CDconform) ? struprcpy : (char* (*)(char*, char*)) strcpy);
306 r = walkdirec(&idumproot, dumpname);
308 copybutname(r, &iroot);
310 if(cd->flags & CDjoliet) {
311 convertnames(&jdumproot, (char* (*)(char*, char*))strcpy);
313 r = walkdirec(&jdumproot, dumpname);
315 copybutname(r, &jroot);
319 writedumpdirs(cd, &idumproot, Cputisodir);
320 if(cd->flags & CDjoliet)
321 writedumpdirs(cd, &jdumproot, Cputjolietdir);
324 * Patch in new root directory entry.
326 setroot(cd, cd->iso9660pvd, idumproot.block, idumproot.length);
327 setvolsize(cd, cd->iso9660pvd, cd->nextblock*Blocksize);
328 if(cd->flags & CDjoliet){
329 setroot(cd, cd->jolietsvd, jdumproot.block, jdumproot.length);
330 setvolsize(cd, cd->jolietsvd, cd->nextblock*Blocksize);
337 * If we've gotten too big, truncate back to what we started with,
338 * fix up the cd, and exit with a non-zero status.
341 if(cd->nulldump && maxsize && Cwoffset(cd) > maxsize){
342 fprint(2, "too big; writing old tree back\n");
343 status = "cd too big; aborted";
345 rmdumpdir(&idumproot, dumpname);
346 rmdumpdir(&jdumproot, dumpname);
348 cd->nextblock = cd->nulldump+1;
350 Cwseek(cd, cd->nextblock*Blocksize);
355 * Write old null header block; this commits all our changes.
358 Cwseek(cd, cd->nulldump*Blocksize);
359 sprint(buf, "plan 9 dump cd\n");
360 sprint(buf+strlen(buf), "%s %lud %lud %lud %lud %lud %lud",
361 dumpname, now, newnull, cblock, clength, iroot.block,
363 if(cd->flags & CDjoliet)
364 sprint(buf+strlen(buf), " %lud %lud",
365 jroot.block, jroot.length);
367 Cwrite(cd, buf, strlen(buf));
372 fdtruncate(cd->fd, cd->nextblock*Blocksize);
378 addprotofile(char *new, char *old, Dir *d, void *a)
386 if(docolon && strchr(new, ':')) {
387 name = emalloc(strlen(new)+1);
389 while((p=strchr(name, ':')))
393 if((direc = adddirec((Direc*)a, new, &xd))) {
394 direc->srcfile = atom(old);
396 /* BUG: abstract, biblio, notice */