1e44fe4caSDavid du Colombier /*
2e44fe4caSDavid du Colombier * Initialize a fossil file system from an ISO9660 image already in the
3e44fe4caSDavid du Colombier * file system. This is a fairly bizarre thing to do, but it lets us generate
4e44fe4caSDavid du Colombier * installation CDs that double as valid Plan 9 disk partitions.
5e44fe4caSDavid du Colombier * People having trouble booting the CD can just copy it into a disk
6e44fe4caSDavid du Colombier * partition and you've got a working Plan 9 system.
7e44fe4caSDavid du Colombier *
8e44fe4caSDavid du Colombier * I've tried hard to keep all the associated cruft in this file.
9e44fe4caSDavid du Colombier * If you deleted this file and cut out the three calls into it from flfmt.c,
10e44fe4caSDavid du Colombier * no traces would remain.
11e44fe4caSDavid du Colombier */
12e44fe4caSDavid du Colombier
13e44fe4caSDavid du Colombier #include "stdinc.h"
14e44fe4caSDavid du Colombier #include "dat.h"
15e44fe4caSDavid du Colombier #include "fns.h"
16e44fe4caSDavid du Colombier #include "flfmt9660.h"
17e44fe4caSDavid du Colombier #include <bio.h>
18e44fe4caSDavid du Colombier #include <ctype.h>
19e44fe4caSDavid du Colombier
20e44fe4caSDavid du Colombier static Biobuf *b;
21e44fe4caSDavid du Colombier
22e44fe4caSDavid du Colombier enum{
23e44fe4caSDavid du Colombier Tag = 0x96609660,
24e44fe4caSDavid du Colombier Blocksize = 2048,
25e44fe4caSDavid du Colombier };
26e44fe4caSDavid du Colombier
27e44fe4caSDavid du Colombier #pragma varargck type "s" uchar*
28e44fe4caSDavid du Colombier #pragma varargck type "L" uchar*
29e44fe4caSDavid du Colombier #pragma varargck type "B" uchar*
30e44fe4caSDavid du Colombier #pragma varargck type "N" uchar*
31e44fe4caSDavid du Colombier #pragma varargck type "T" uchar*
32e44fe4caSDavid du Colombier #pragma varargck type "D" uchar*
33e44fe4caSDavid du Colombier
34e44fe4caSDavid du Colombier typedef struct Voldesc Voldesc;
35e44fe4caSDavid du Colombier struct Voldesc {
36e44fe4caSDavid du Colombier uchar magic[8]; /* 0x01, "CD001", 0x01, 0x00 */
37e44fe4caSDavid du Colombier uchar systemid[32]; /* system identifier */
38e44fe4caSDavid du Colombier uchar volumeid[32]; /* volume identifier */
39e44fe4caSDavid du Colombier uchar unused[8]; /* character set in secondary desc */
40e44fe4caSDavid du Colombier uchar volsize[8]; /* volume size */
41e44fe4caSDavid du Colombier uchar charset[32];
42e44fe4caSDavid du Colombier uchar volsetsize[4]; /* volume set size = 1 */
43e44fe4caSDavid du Colombier uchar volseqnum[4]; /* volume sequence number = 1 */
44e44fe4caSDavid du Colombier uchar blocksize[4]; /* logical block size */
45e44fe4caSDavid du Colombier uchar pathsize[8]; /* path table size */
46e44fe4caSDavid du Colombier uchar lpathloc[4]; /* Lpath */
47e44fe4caSDavid du Colombier uchar olpathloc[4]; /* optional Lpath */
48e44fe4caSDavid du Colombier uchar mpathloc[4]; /* Mpath */
49e44fe4caSDavid du Colombier uchar ompathloc[4]; /* optional Mpath */
50e44fe4caSDavid du Colombier uchar rootdir[34]; /* root directory */
51e44fe4caSDavid du Colombier uchar volsetid[128]; /* volume set identifier */
52e44fe4caSDavid du Colombier uchar publisher[128];
53e44fe4caSDavid du Colombier uchar prepid[128]; /* data preparer identifier */
54e44fe4caSDavid du Colombier uchar applid[128]; /* application identifier */
55e44fe4caSDavid du Colombier uchar notice[37]; /* copyright notice file */
56e44fe4caSDavid du Colombier uchar abstract[37]; /* abstract file */
57e44fe4caSDavid du Colombier uchar biblio[37]; /* bibliographic file */
58e44fe4caSDavid du Colombier uchar cdate[17]; /* creation date */
59e44fe4caSDavid du Colombier uchar mdate[17]; /* modification date */
60e44fe4caSDavid du Colombier uchar xdate[17]; /* expiration date */
61e44fe4caSDavid du Colombier uchar edate[17]; /* effective date */
62e44fe4caSDavid du Colombier uchar fsvers; /* file system version = 1 */
63e44fe4caSDavid du Colombier };
64e44fe4caSDavid du Colombier
65e44fe4caSDavid du Colombier static void
dumpbootvol(void * a)66e44fe4caSDavid du Colombier dumpbootvol(void *a)
67e44fe4caSDavid du Colombier {
68e44fe4caSDavid du Colombier Voldesc *v;
69e44fe4caSDavid du Colombier
70e44fe4caSDavid du Colombier v = a;
71e44fe4caSDavid du Colombier print("magic %.2ux %.5s %.2ux %2ux\n",
72e44fe4caSDavid du Colombier v->magic[0], v->magic+1, v->magic[6], v->magic[7]);
73e44fe4caSDavid du Colombier if(v->magic[0] == 0xFF)
74e44fe4caSDavid du Colombier return;
75e44fe4caSDavid du Colombier
76e44fe4caSDavid du Colombier print("system %.32T\n", v->systemid);
77e44fe4caSDavid du Colombier print("volume %.32T\n", v->volumeid);
78e44fe4caSDavid du Colombier print("volume size %.4N\n", v->volsize);
79e44fe4caSDavid du Colombier print("charset %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n",
80e44fe4caSDavid du Colombier v->charset[0], v->charset[1], v->charset[2], v->charset[3],
81e44fe4caSDavid du Colombier v->charset[4], v->charset[5], v->charset[6], v->charset[7]);
82e44fe4caSDavid du Colombier print("volume set size %.2N\n", v->volsetsize);
83e44fe4caSDavid du Colombier print("volume sequence number %.2N\n", v->volseqnum);
84e44fe4caSDavid du Colombier print("logical block size %.2N\n", v->blocksize);
85e44fe4caSDavid du Colombier print("path size %.4L\n", v->pathsize);
86e44fe4caSDavid du Colombier print("lpath loc %.4L\n", v->lpathloc);
87e44fe4caSDavid du Colombier print("opt lpath loc %.4L\n", v->olpathloc);
88e44fe4caSDavid du Colombier print("mpath loc %.4B\n", v->mpathloc);
89e44fe4caSDavid du Colombier print("opt mpath loc %.4B\n", v->ompathloc);
90e44fe4caSDavid du Colombier print("rootdir %D\n", v->rootdir);
91e44fe4caSDavid du Colombier print("volume set identifier %.128T\n", v->volsetid);
92e44fe4caSDavid du Colombier print("publisher %.128T\n", v->publisher);
93e44fe4caSDavid du Colombier print("preparer %.128T\n", v->prepid);
94e44fe4caSDavid du Colombier print("application %.128T\n", v->applid);
95e44fe4caSDavid du Colombier print("notice %.37T\n", v->notice);
96e44fe4caSDavid du Colombier print("abstract %.37T\n", v->abstract);
97e44fe4caSDavid du Colombier print("biblio %.37T\n", v->biblio);
98e44fe4caSDavid du Colombier print("creation date %.17s\n", v->cdate);
99e44fe4caSDavid du Colombier print("modification date %.17s\n", v->mdate);
100e44fe4caSDavid du Colombier print("expiration date %.17s\n", v->xdate);
101e44fe4caSDavid du Colombier print("effective date %.17s\n", v->edate);
102e44fe4caSDavid du Colombier print("fs version %d\n", v->fsvers);
103e44fe4caSDavid du Colombier }
104e44fe4caSDavid du Colombier
105e44fe4caSDavid du Colombier typedef struct Cdir Cdir;
106e44fe4caSDavid du Colombier struct Cdir {
107e44fe4caSDavid du Colombier uchar len;
108e44fe4caSDavid du Colombier uchar xlen;
109e44fe4caSDavid du Colombier uchar dloc[8];
110e44fe4caSDavid du Colombier uchar dlen[8];
111e44fe4caSDavid du Colombier uchar date[7];
112e44fe4caSDavid du Colombier uchar flags;
113e44fe4caSDavid du Colombier uchar unitsize;
114e44fe4caSDavid du Colombier uchar gapsize;
115e44fe4caSDavid du Colombier uchar volseqnum[4];
116e44fe4caSDavid du Colombier uchar namelen;
117e44fe4caSDavid du Colombier uchar name[1]; /* chumminess */
118e44fe4caSDavid du Colombier };
119e44fe4caSDavid du Colombier #pragma varargck type "D" Cdir*
120e44fe4caSDavid du Colombier
121e44fe4caSDavid du Colombier static int
Dfmt(Fmt * fmt)122e44fe4caSDavid du Colombier Dfmt(Fmt *fmt)
123e44fe4caSDavid du Colombier {
124e44fe4caSDavid du Colombier char buf[128];
125e44fe4caSDavid du Colombier Cdir *c;
126e44fe4caSDavid du Colombier
127e44fe4caSDavid du Colombier c = va_arg(fmt->args, Cdir*);
128e44fe4caSDavid du Colombier if(c->namelen == 1 && c->name[0] == '\0' || c->name[0] == '\001') {
129e44fe4caSDavid du Colombier snprint(buf, sizeof buf, ".%s dloc %.4N dlen %.4N",
130e44fe4caSDavid du Colombier c->name[0] ? "." : "", c->dloc, c->dlen);
131e44fe4caSDavid du Colombier } else {
132e44fe4caSDavid du Colombier snprint(buf, sizeof buf, "%.*T dloc %.4N dlen %.4N", c->namelen, c->name,
133e44fe4caSDavid du Colombier c->dloc, c->dlen);
134e44fe4caSDavid du Colombier }
135e44fe4caSDavid du Colombier fmtstrcpy(fmt, buf);
136e44fe4caSDavid du Colombier return 0;
137e44fe4caSDavid du Colombier }
138e44fe4caSDavid du Colombier
139e44fe4caSDavid du Colombier char longc, shortc;
140e44fe4caSDavid du Colombier static void
bigend(void)141e44fe4caSDavid du Colombier bigend(void)
142e44fe4caSDavid du Colombier {
143e44fe4caSDavid du Colombier longc = 'B';
144e44fe4caSDavid du Colombier }
145e44fe4caSDavid du Colombier
146e44fe4caSDavid du Colombier static void
littleend(void)147e44fe4caSDavid du Colombier littleend(void)
148e44fe4caSDavid du Colombier {
149e44fe4caSDavid du Colombier longc = 'L';
150e44fe4caSDavid du Colombier }
151e44fe4caSDavid du Colombier
152e44fe4caSDavid du Colombier static ulong
big(void * a,int n)153e44fe4caSDavid du Colombier big(void *a, int n)
154e44fe4caSDavid du Colombier {
155e44fe4caSDavid du Colombier uchar *p;
156e44fe4caSDavid du Colombier ulong v;
157e44fe4caSDavid du Colombier int i;
158e44fe4caSDavid du Colombier
159e44fe4caSDavid du Colombier p = a;
160e44fe4caSDavid du Colombier v = 0;
161e44fe4caSDavid du Colombier for(i=0; i<n; i++)
162e44fe4caSDavid du Colombier v = (v<<8) | *p++;
163e44fe4caSDavid du Colombier return v;
164e44fe4caSDavid du Colombier }
165e44fe4caSDavid du Colombier
166e44fe4caSDavid du Colombier static ulong
little(void * a,int n)167e44fe4caSDavid du Colombier little(void *a, int n)
168e44fe4caSDavid du Colombier {
169e44fe4caSDavid du Colombier uchar *p;
170e44fe4caSDavid du Colombier ulong v;
171e44fe4caSDavid du Colombier int i;
172e44fe4caSDavid du Colombier
173e44fe4caSDavid du Colombier p = a;
174e44fe4caSDavid du Colombier v = 0;
175e44fe4caSDavid du Colombier for(i=0; i<n; i++)
176e44fe4caSDavid du Colombier v |= (*p++<<(i*8));
177e44fe4caSDavid du Colombier return v;
178e44fe4caSDavid du Colombier }
179e44fe4caSDavid du Colombier
180e44fe4caSDavid du Colombier /* numbers in big or little endian. */
181e44fe4caSDavid du Colombier static int
BLfmt(Fmt * fmt)182e44fe4caSDavid du Colombier BLfmt(Fmt *fmt)
183e44fe4caSDavid du Colombier {
184e44fe4caSDavid du Colombier ulong v;
185e44fe4caSDavid du Colombier uchar *p;
186e44fe4caSDavid du Colombier char buf[20];
187e44fe4caSDavid du Colombier
188e44fe4caSDavid du Colombier p = va_arg(fmt->args, uchar*);
189e44fe4caSDavid du Colombier
190e44fe4caSDavid du Colombier if(!(fmt->flags&FmtPrec)) {
191e44fe4caSDavid du Colombier fmtstrcpy(fmt, "*BL*");
192e44fe4caSDavid du Colombier return 0;
193e44fe4caSDavid du Colombier }
194e44fe4caSDavid du Colombier
195e44fe4caSDavid du Colombier if(fmt->r == 'B')
196e44fe4caSDavid du Colombier v = big(p, fmt->prec);
197e44fe4caSDavid du Colombier else
198e44fe4caSDavid du Colombier v = little(p, fmt->prec);
199e44fe4caSDavid du Colombier
200e44fe4caSDavid du Colombier sprint(buf, "0x%.*lux", fmt->prec*2, v);
201e44fe4caSDavid du Colombier fmt->flags &= ~FmtPrec;
202e44fe4caSDavid du Colombier fmtstrcpy(fmt, buf);
203e44fe4caSDavid du Colombier return 0;
204e44fe4caSDavid du Colombier }
205e44fe4caSDavid du Colombier
206e44fe4caSDavid du Colombier /* numbers in both little and big endian */
207e44fe4caSDavid du Colombier static int
Nfmt(Fmt * fmt)208e44fe4caSDavid du Colombier Nfmt(Fmt *fmt)
209e44fe4caSDavid du Colombier {
210e44fe4caSDavid du Colombier char buf[100];
211e44fe4caSDavid du Colombier uchar *p;
212e44fe4caSDavid du Colombier
213e44fe4caSDavid du Colombier p = va_arg(fmt->args, uchar*);
214e44fe4caSDavid du Colombier
215e44fe4caSDavid du Colombier sprint(buf, "%.*L %.*B", fmt->prec, p, fmt->prec, p+fmt->prec);
216e44fe4caSDavid du Colombier fmt->flags &= ~FmtPrec;
217e44fe4caSDavid du Colombier fmtstrcpy(fmt, buf);
218e44fe4caSDavid du Colombier return 0;
219e44fe4caSDavid du Colombier }
220e44fe4caSDavid du Colombier
221e44fe4caSDavid du Colombier static int
asciiTfmt(Fmt * fmt)222e44fe4caSDavid du Colombier asciiTfmt(Fmt *fmt)
223e44fe4caSDavid du Colombier {
224e44fe4caSDavid du Colombier char *p, buf[256];
225e44fe4caSDavid du Colombier int i;
226e44fe4caSDavid du Colombier
227e44fe4caSDavid du Colombier p = va_arg(fmt->args, char*);
228e44fe4caSDavid du Colombier for(i=0; i<fmt->prec; i++)
229e44fe4caSDavid du Colombier buf[i] = *p++;
230e44fe4caSDavid du Colombier buf[i] = '\0';
231e44fe4caSDavid du Colombier for(p=buf+strlen(buf); p>buf && p[-1]==' '; p--)
232e44fe4caSDavid du Colombier ;
233e44fe4caSDavid du Colombier p[0] = '\0';
234e44fe4caSDavid du Colombier fmt->flags &= ~FmtPrec;
235e44fe4caSDavid du Colombier fmtstrcpy(fmt, buf);
236e44fe4caSDavid du Colombier return 0;
237e44fe4caSDavid du Colombier }
238e44fe4caSDavid du Colombier
239e44fe4caSDavid du Colombier static void
ascii(void)240e44fe4caSDavid du Colombier ascii(void)
241e44fe4caSDavid du Colombier {
242e44fe4caSDavid du Colombier fmtinstall('T', asciiTfmt);
243e44fe4caSDavid du Colombier }
244e44fe4caSDavid du Colombier
245e44fe4caSDavid du Colombier static int
runeTfmt(Fmt * fmt)246e44fe4caSDavid du Colombier runeTfmt(Fmt *fmt)
247e44fe4caSDavid du Colombier {
248e44fe4caSDavid du Colombier Rune buf[256], *r;
249e44fe4caSDavid du Colombier int i;
250e44fe4caSDavid du Colombier uchar *p;
251e44fe4caSDavid du Colombier
252e44fe4caSDavid du Colombier p = va_arg(fmt->args, uchar*);
253e44fe4caSDavid du Colombier for(i=0; i*2+2<=fmt->prec; i++, p+=2)
254e44fe4caSDavid du Colombier buf[i] = (p[0]<<8)|p[1];
255e44fe4caSDavid du Colombier buf[i] = L'\0';
256e44fe4caSDavid du Colombier for(r=buf+i; r>buf && r[-1]==L' '; r--)
257e44fe4caSDavid du Colombier ;
258e44fe4caSDavid du Colombier r[0] = L'\0';
259e44fe4caSDavid du Colombier fmt->flags &= ~FmtPrec;
260e44fe4caSDavid du Colombier return fmtprint(fmt, "%S", buf);
261e44fe4caSDavid du Colombier }
262e44fe4caSDavid du Colombier
263e44fe4caSDavid du Colombier static void
getsect(uchar * buf,int n)264e44fe4caSDavid du Colombier getsect(uchar *buf, int n)
265e44fe4caSDavid du Colombier {
266e44fe4caSDavid du Colombier if(Bseek(b, n*2048, 0) != n*2048 || Bread(b, buf, 2048) != 2048)
267e44fe4caSDavid du Colombier {
268e44fe4caSDavid du Colombier abort();
269*14cc0f53SDavid du Colombier sysfatal("reading block at %,d: %r", n*2048);
270e44fe4caSDavid du Colombier }
271e44fe4caSDavid du Colombier }
272e44fe4caSDavid du Colombier
273e44fe4caSDavid du Colombier static Header *h;
274e44fe4caSDavid du Colombier static int fd;
275e44fe4caSDavid du Colombier static char *file9660;
276e44fe4caSDavid du Colombier static int off9660;
277e44fe4caSDavid du Colombier static ulong startoff;
278e44fe4caSDavid du Colombier static ulong endoff;
279e44fe4caSDavid du Colombier static ulong fsoff;
280e44fe4caSDavid du Colombier static uchar root[2048];
281e44fe4caSDavid du Colombier static Voldesc *v;
282e44fe4caSDavid du Colombier static ulong iso9660start(Cdir*);
283e44fe4caSDavid du Colombier static void iso9660copydir(Fs*, File*, Cdir*);
284e44fe4caSDavid du Colombier static void iso9660copyfile(Fs*, File*, Cdir*);
285e44fe4caSDavid du Colombier
286e44fe4caSDavid du Colombier void
iso9660init(int xfd,Header * xh,char * xfile9660,int xoff9660)287e44fe4caSDavid du Colombier iso9660init(int xfd, Header *xh, char *xfile9660, int xoff9660)
288e44fe4caSDavid du Colombier {
289e44fe4caSDavid du Colombier uchar sect[2048], sect2[2048];
290e44fe4caSDavid du Colombier
291e44fe4caSDavid du Colombier fmtinstall('L', BLfmt);
292e44fe4caSDavid du Colombier fmtinstall('B', BLfmt);
293e44fe4caSDavid du Colombier fmtinstall('N', Nfmt);
294e44fe4caSDavid du Colombier fmtinstall('D', Dfmt);
295e44fe4caSDavid du Colombier
296e44fe4caSDavid du Colombier fd = xfd;
297e44fe4caSDavid du Colombier h = xh;
298e44fe4caSDavid du Colombier file9660 = xfile9660;
299e44fe4caSDavid du Colombier off9660 = xoff9660;
300e44fe4caSDavid du Colombier
301e44fe4caSDavid du Colombier if((b = Bopen(file9660, OREAD)) == nil)
302e44fe4caSDavid du Colombier vtFatal("Bopen %s: %r", file9660);
303e44fe4caSDavid du Colombier
304e44fe4caSDavid du Colombier getsect(root, 16);
305e44fe4caSDavid du Colombier ascii();
306e44fe4caSDavid du Colombier
307e44fe4caSDavid du Colombier v = (Voldesc*)root;
308e44fe4caSDavid du Colombier if(memcmp(v->magic, "\x01CD001\x01\x00", 8) != 0)
309e44fe4caSDavid du Colombier vtFatal("%s not a cd image", file9660);
310e44fe4caSDavid du Colombier
311e44fe4caSDavid du Colombier startoff = iso9660start((Cdir*)v->rootdir)*Blocksize;
312e44fe4caSDavid du Colombier endoff = little(v->volsize, 4); /* already in bytes */
313e44fe4caSDavid du Colombier
314e44fe4caSDavid du Colombier fsoff = off9660 + h->data*h->blockSize;
315e44fe4caSDavid du Colombier if(fsoff > startoff)
316e44fe4caSDavid du Colombier vtFatal("fossil data starts after cd data");
317e44fe4caSDavid du Colombier if(off9660 + (vlong)h->end*h->blockSize < endoff)
318e44fe4caSDavid du Colombier vtFatal("fossil data ends before cd data");
319e44fe4caSDavid du Colombier if(fsoff%h->blockSize)
320e44fe4caSDavid du Colombier vtFatal("cd offset not a multiple of fossil block size");
321e44fe4caSDavid du Colombier
322e44fe4caSDavid du Colombier /* Read "same" block via CD image and via Fossil image */
323e44fe4caSDavid du Colombier getsect(sect, startoff/Blocksize);
324e44fe4caSDavid du Colombier if(seek(fd, startoff-off9660, 0) < 0)
325e44fe4caSDavid du Colombier vtFatal("cannot seek to first data sector on cd via fossil");
326e44fe4caSDavid du Colombier fprint(2, "look for %lud at %lud\n", startoff, startoff-off9660);
327e44fe4caSDavid du Colombier if(readn(fd, sect2, Blocksize) != Blocksize)
328e44fe4caSDavid du Colombier vtFatal("cannot read first data sector on cd via fossil");
329e44fe4caSDavid du Colombier if(memcmp(sect, sect2, Blocksize) != 0)
330e44fe4caSDavid du Colombier vtFatal("iso9660 offset is a lie %08ux %08ux", *(long*)sect, *(long*)sect2);
331e44fe4caSDavid du Colombier }
332e44fe4caSDavid du Colombier
333e44fe4caSDavid du Colombier void
iso9660labels(Disk * disk,uchar * buf,void (* write)(int,u32int))334e44fe4caSDavid du Colombier iso9660labels(Disk *disk, uchar *buf, void (*write)(int, u32int))
335e44fe4caSDavid du Colombier {
336e44fe4caSDavid du Colombier ulong sb, eb, bn, lb, llb;
337e44fe4caSDavid du Colombier Label l;
338e44fe4caSDavid du Colombier int lpb;
339e44fe4caSDavid du Colombier uchar sect[Blocksize];
340e44fe4caSDavid du Colombier
341e44fe4caSDavid du Colombier if(!diskReadRaw(disk, PartData, (startoff-fsoff)/h->blockSize, buf))
342e44fe4caSDavid du Colombier vtFatal("disk read failed: %r");
343e44fe4caSDavid du Colombier getsect(sect, startoff/Blocksize);
344e44fe4caSDavid du Colombier if(memcmp(buf, sect, Blocksize) != 0)
345e44fe4caSDavid du Colombier vtFatal("fsoff is wrong");
346e44fe4caSDavid du Colombier
347e44fe4caSDavid du Colombier sb = (startoff-fsoff)/h->blockSize;
348e44fe4caSDavid du Colombier eb = (endoff-fsoff+h->blockSize-1)/h->blockSize;
349e44fe4caSDavid du Colombier
350e44fe4caSDavid du Colombier lpb = h->blockSize/LabelSize;
351e44fe4caSDavid du Colombier
352e44fe4caSDavid du Colombier /* for each reserved block, mark label */
353e44fe4caSDavid du Colombier llb = ~0;
354e44fe4caSDavid du Colombier l.type = BtData;
355e44fe4caSDavid du Colombier l.state = BsAlloc;
356e44fe4caSDavid du Colombier l.tag = Tag;
357e44fe4caSDavid du Colombier l.epoch = 1;
358e44fe4caSDavid du Colombier l.epochClose = ~(u32int)0;
359e44fe4caSDavid du Colombier for(bn=sb; bn<eb; bn++){
360e44fe4caSDavid du Colombier lb = bn/lpb;
361e44fe4caSDavid du Colombier if(lb != llb){
362e44fe4caSDavid du Colombier if(llb != ~0)
363e44fe4caSDavid du Colombier (*write)(PartLabel, llb);
364e44fe4caSDavid du Colombier memset(buf, 0, h->blockSize);
365e44fe4caSDavid du Colombier }
366e44fe4caSDavid du Colombier llb = lb;
367e44fe4caSDavid du Colombier labelPack(&l, buf, bn%lpb);
368e44fe4caSDavid du Colombier }
369e44fe4caSDavid du Colombier if(llb != ~0)
370e44fe4caSDavid du Colombier (*write)(PartLabel, llb);
371e44fe4caSDavid du Colombier }
372e44fe4caSDavid du Colombier
373e44fe4caSDavid du Colombier void
iso9660copy(Fs * fs)374e44fe4caSDavid du Colombier iso9660copy(Fs *fs)
375e44fe4caSDavid du Colombier {
376e44fe4caSDavid du Colombier File *root;
377e44fe4caSDavid du Colombier
378e44fe4caSDavid du Colombier root = fileOpen(fs, "/active");
379e44fe4caSDavid du Colombier iso9660copydir(fs, root, (Cdir*)v->rootdir);
380e44fe4caSDavid du Colombier fileDecRef(root);
381e44fe4caSDavid du Colombier vtRUnlock(fs->elk);
382c3c4501eSDavid du Colombier if(!fsSnapshot(fs, nil, nil, 0))
383e44fe4caSDavid du Colombier vtFatal("snapshot failed: %R");
384e44fe4caSDavid du Colombier vtRLock(fs->elk);
385e44fe4caSDavid du Colombier }
386e44fe4caSDavid du Colombier
387e44fe4caSDavid du Colombier /*
388e44fe4caSDavid du Colombier * The first block used is the first data block of the leftmost file in the tree.
389e44fe4caSDavid du Colombier * (Just an artifact of how mk9660 works.)
390e44fe4caSDavid du Colombier */
391e44fe4caSDavid du Colombier static ulong
iso9660start(Cdir * c)392e44fe4caSDavid du Colombier iso9660start(Cdir *c)
393e44fe4caSDavid du Colombier {
394e44fe4caSDavid du Colombier uchar sect[Blocksize];
395e44fe4caSDavid du Colombier
396e44fe4caSDavid du Colombier while(c->flags&2){
397e44fe4caSDavid du Colombier getsect(sect, little(c->dloc, 4));
398e44fe4caSDavid du Colombier c = (Cdir*)sect;
399e44fe4caSDavid du Colombier c = (Cdir*)((uchar*)c+c->len); /* skip dot */
400e44fe4caSDavid du Colombier c = (Cdir*)((uchar*)c+c->len); /* skip dotdot */
401e44fe4caSDavid du Colombier /* oops: might happen if leftmost directory is empty or leftmost file is zero length! */
402e44fe4caSDavid du Colombier if(little(c->dloc, 4) == 0)
403e44fe4caSDavid du Colombier vtFatal("error parsing cd image or unfortunate cd image");
404e44fe4caSDavid du Colombier }
405e44fe4caSDavid du Colombier return little(c->dloc, 4);
406e44fe4caSDavid du Colombier }
407e44fe4caSDavid du Colombier
408e44fe4caSDavid du Colombier static void
iso9660copydir(Fs * fs,File * dir,Cdir * cd)409e44fe4caSDavid du Colombier iso9660copydir(Fs *fs, File *dir, Cdir *cd)
410e44fe4caSDavid du Colombier {
411e44fe4caSDavid du Colombier ulong off, end, len;
412e44fe4caSDavid du Colombier uchar sect[Blocksize], *esect, *p;
413e44fe4caSDavid du Colombier Cdir *c;
414e44fe4caSDavid du Colombier
415e44fe4caSDavid du Colombier len = little(cd->dlen, 4);
416e44fe4caSDavid du Colombier off = little(cd->dloc, 4)*Blocksize;
417e44fe4caSDavid du Colombier end = off+len;
418e44fe4caSDavid du Colombier esect = sect+Blocksize;
419e44fe4caSDavid du Colombier
420e44fe4caSDavid du Colombier for(; off<end; off+=Blocksize){
421e44fe4caSDavid du Colombier getsect(sect, off/Blocksize);
422e44fe4caSDavid du Colombier p = sect;
423e44fe4caSDavid du Colombier while(p < esect){
424e44fe4caSDavid du Colombier c = (Cdir*)p;
425e44fe4caSDavid du Colombier if(c->len <= 0)
426e44fe4caSDavid du Colombier break;
427e44fe4caSDavid du Colombier if(c->namelen!=1 || c->name[0]>1)
428e44fe4caSDavid du Colombier iso9660copyfile(fs, dir, c);
429e44fe4caSDavid du Colombier p += c->len;
430e44fe4caSDavid du Colombier }
431e44fe4caSDavid du Colombier }
432e44fe4caSDavid du Colombier }
433e44fe4caSDavid du Colombier
434e44fe4caSDavid du Colombier static char*
getname(uchar ** pp)435e44fe4caSDavid du Colombier getname(uchar **pp)
436e44fe4caSDavid du Colombier {
437e44fe4caSDavid du Colombier uchar *p;
438e44fe4caSDavid du Colombier int l;
439e44fe4caSDavid du Colombier
440e44fe4caSDavid du Colombier p = *pp;
441e44fe4caSDavid du Colombier l = *p;
442e44fe4caSDavid du Colombier *pp = p+1+l;
443e44fe4caSDavid du Colombier if(l == 0)
444e44fe4caSDavid du Colombier return "";
445e44fe4caSDavid du Colombier memmove(p, p+1, l);
446e44fe4caSDavid du Colombier p[l] = 0;
447e44fe4caSDavid du Colombier return (char*)p;
448e44fe4caSDavid du Colombier }
449e44fe4caSDavid du Colombier
450e44fe4caSDavid du Colombier static char*
getcname(Cdir * c)451e44fe4caSDavid du Colombier getcname(Cdir *c)
452e44fe4caSDavid du Colombier {
453e44fe4caSDavid du Colombier uchar *up;
454e44fe4caSDavid du Colombier char *p, *q;
455e44fe4caSDavid du Colombier
456e44fe4caSDavid du Colombier up = &c->namelen;
457e44fe4caSDavid du Colombier p = getname(&up);
458e44fe4caSDavid du Colombier for(q=p; *q; q++)
459e44fe4caSDavid du Colombier *q = tolower(*q);
460e44fe4caSDavid du Colombier return p;
461e44fe4caSDavid du Colombier }
462e44fe4caSDavid du Colombier
463e44fe4caSDavid du Colombier static char
464e44fe4caSDavid du Colombier dmsize[12] =
465e44fe4caSDavid du Colombier {
466e44fe4caSDavid du Colombier 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
467e44fe4caSDavid du Colombier };
468e44fe4caSDavid du Colombier
469e44fe4caSDavid du Colombier static ulong
getcdate(uchar * p)470e44fe4caSDavid du Colombier getcdate(uchar *p) /* yMdhmsz */
471e44fe4caSDavid du Colombier {
472e44fe4caSDavid du Colombier Tm tm;
473e44fe4caSDavid du Colombier int y, M, d, h, m, s, tz;
474e44fe4caSDavid du Colombier
475e44fe4caSDavid du Colombier y=p[0]; M=p[1]; d=p[2];
476e44fe4caSDavid du Colombier h=p[3]; m=p[4]; s=p[5]; tz=p[6];
477e44fe4caSDavid du Colombier USED(tz);
478e44fe4caSDavid du Colombier if (y < 70)
479e44fe4caSDavid du Colombier return 0;
480e44fe4caSDavid du Colombier if (M < 1 || M > 12)
481e44fe4caSDavid du Colombier return 0;
482e44fe4caSDavid du Colombier if (d < 1 || d > dmsize[M-1])
483e44fe4caSDavid du Colombier return 0;
484e44fe4caSDavid du Colombier if (h > 23)
485e44fe4caSDavid du Colombier return 0;
486e44fe4caSDavid du Colombier if (m > 59)
487e44fe4caSDavid du Colombier return 0;
488e44fe4caSDavid du Colombier if (s > 59)
489e44fe4caSDavid du Colombier return 0;
490e44fe4caSDavid du Colombier
491e44fe4caSDavid du Colombier memset(&tm, 0, sizeof tm);
492e44fe4caSDavid du Colombier tm.sec = s;
493e44fe4caSDavid du Colombier tm.min = m;
494e44fe4caSDavid du Colombier tm.hour = h;
495e44fe4caSDavid du Colombier tm.mday = d;
496e44fe4caSDavid du Colombier tm.mon = M-1;
497e44fe4caSDavid du Colombier tm.year = 1900+y;
498e44fe4caSDavid du Colombier tm.zone[0] = 0;
499e44fe4caSDavid du Colombier return tm2sec(&tm);
500e44fe4caSDavid du Colombier }
501e44fe4caSDavid du Colombier
502e44fe4caSDavid du Colombier static int ind;
503e44fe4caSDavid du Colombier
504e44fe4caSDavid du Colombier static void
iso9660copyfile(Fs * fs,File * dir,Cdir * c)505e44fe4caSDavid du Colombier iso9660copyfile(Fs *fs, File *dir, Cdir *c)
506e44fe4caSDavid du Colombier {
507e44fe4caSDavid du Colombier Dir d;
508e44fe4caSDavid du Colombier DirEntry de;
509e44fe4caSDavid du Colombier int sysl;
510e44fe4caSDavid du Colombier uchar score[VtScoreSize];
511e44fe4caSDavid du Colombier ulong off, foff, len, mode;
512e44fe4caSDavid du Colombier uchar *p;
513e44fe4caSDavid du Colombier File *f;
514e44fe4caSDavid du Colombier
515e44fe4caSDavid du Colombier ind++;
516e44fe4caSDavid du Colombier memset(&d, 0, sizeof d);
517e44fe4caSDavid du Colombier p = c->name + c->namelen;
51873e742d7SDavid du Colombier if(((uintptr)p) & 1)
519e44fe4caSDavid du Colombier p++;
520e44fe4caSDavid du Colombier sysl = (uchar*)c + c->len - p;
521e44fe4caSDavid du Colombier if(sysl <= 0)
522e44fe4caSDavid du Colombier vtFatal("missing plan9 directory entry on %d/%d/%.*s", c->namelen, c->name[0], c->namelen, c->name);
523e44fe4caSDavid du Colombier d.name = getname(&p);
524e44fe4caSDavid du Colombier d.uid = getname(&p);
525e44fe4caSDavid du Colombier d.gid = getname(&p);
52673e742d7SDavid du Colombier if((uintptr)p & 1)
527e44fe4caSDavid du Colombier p++;
528e44fe4caSDavid du Colombier d.mode = little(p, 4);
529e44fe4caSDavid du Colombier if(d.name[0] == 0)
530e44fe4caSDavid du Colombier d.name = getcname(c);
531e44fe4caSDavid du Colombier d.mtime = getcdate(c->date);
532e44fe4caSDavid du Colombier d.atime = d.mtime;
533e44fe4caSDavid du Colombier
534e44fe4caSDavid du Colombier if(d.mode&DMDIR) print("%*scopy %s %s %s %luo\n", ind*2, "", d.name, d.uid, d.gid, d.mode);
535e44fe4caSDavid du Colombier
536e44fe4caSDavid du Colombier mode = d.mode&0777;
537e44fe4caSDavid du Colombier if(d.mode&DMDIR)
538e44fe4caSDavid du Colombier mode |= ModeDir;
539e44fe4caSDavid du Colombier if((f = fileCreate(dir, d.name, mode, d.uid)) == nil)
540e44fe4caSDavid du Colombier vtFatal("could not create file '%s': %r", d.name);
541e44fe4caSDavid du Colombier if(d.mode&DMDIR)
542e44fe4caSDavid du Colombier iso9660copydir(fs, f, c);
543e44fe4caSDavid du Colombier else{
544e44fe4caSDavid du Colombier len = little(c->dlen, 4);
545e44fe4caSDavid du Colombier off = little(c->dloc, 4)*Blocksize;
546e44fe4caSDavid du Colombier for(foff=0; foff<len; foff+=h->blockSize){
547e44fe4caSDavid du Colombier localToGlobal((off+foff-fsoff)/h->blockSize, score);
548e44fe4caSDavid du Colombier if(!fileMapBlock(f, foff/h->blockSize, score, Tag))
549e44fe4caSDavid du Colombier vtFatal("fileMapBlock: %R");
550e44fe4caSDavid du Colombier }
551e44fe4caSDavid du Colombier if(!fileSetSize(f, len))
552e44fe4caSDavid du Colombier vtFatal("fileSetSize: %R");
553e44fe4caSDavid du Colombier }
554e44fe4caSDavid du Colombier if(!fileGetDir(f, &de))
555e44fe4caSDavid du Colombier vtFatal("fileGetDir: %R");
556e44fe4caSDavid du Colombier de.uid = d.uid;
557e44fe4caSDavid du Colombier de.gid = d.gid;
558e44fe4caSDavid du Colombier de.mtime = d.mtime;
559e44fe4caSDavid du Colombier de.atime = d.atime;
560e44fe4caSDavid du Colombier de.mode = d.mode&0777;
561e44fe4caSDavid du Colombier if(!fileSetDir(f, &de, "sys"))
562e44fe4caSDavid du Colombier vtFatal("fileSetDir: %R");
563e44fe4caSDavid du Colombier fileDecRef(f);
564e44fe4caSDavid du Colombier ind--;
565e44fe4caSDavid du Colombier }
566