1 78a779a3 2008-07-20 rsc #include <u.h>
2 78a779a3 2008-07-20 rsc #include <libc.h>
3 78a779a3 2008-07-20 rsc #include <auth.h>
4 78a779a3 2008-07-20 rsc #include <fcall.h>
5 78a779a3 2008-07-20 rsc #include "dat.h"
6 78a779a3 2008-07-20 rsc #include "fns.h"
7 78a779a3 2008-07-20 rsc #include "iso9660.h"
9 78a779a3 2008-07-20 rsc static void ireset(void);
10 78a779a3 2008-07-20 rsc static int iattach(Xfile*);
11 78a779a3 2008-07-20 rsc static void iclone(Xfile*, Xfile*);
12 78a779a3 2008-07-20 rsc static void iwalkup(Xfile*);
13 78a779a3 2008-07-20 rsc static void iwalk(Xfile*, char*);
14 78a779a3 2008-07-20 rsc static void iopen(Xfile*, int);
15 78a779a3 2008-07-20 rsc static void icreate(Xfile*, char*, long, int);
16 78a779a3 2008-07-20 rsc static long ireaddir(Xfile*, uchar*, long, long);
17 78a779a3 2008-07-20 rsc static long iread(Xfile*, char*, vlong, long);
18 78a779a3 2008-07-20 rsc static long iwrite(Xfile*, char*, vlong, long);
19 78a779a3 2008-07-20 rsc static void iclunk(Xfile*);
20 78a779a3 2008-07-20 rsc static void iremove(Xfile*);
21 78a779a3 2008-07-20 rsc static void istat(Xfile*, Dir*);
22 78a779a3 2008-07-20 rsc static void iwstat(Xfile*, Dir*);
24 78a779a3 2008-07-20 rsc static char* nstr(uchar*, int);
25 78a779a3 2008-07-20 rsc static char* rdate(uchar*, int);
26 78a779a3 2008-07-20 rsc static int getcontin(Xdata*, uchar*, uchar**);
27 78a779a3 2008-07-20 rsc static int getdrec(Xfile*, void*);
28 78a779a3 2008-07-20 rsc static void ungetdrec(Xfile*);
29 78a779a3 2008-07-20 rsc static int opendotdot(Xfile*, Xfile*);
30 78a779a3 2008-07-20 rsc static int showdrec(int, int, void*);
31 78a779a3 2008-07-20 rsc static long gtime(uchar*);
32 78a779a3 2008-07-20 rsc static long l16(void*);
33 78a779a3 2008-07-20 rsc static long l32(void*);
34 78a779a3 2008-07-20 rsc static void newdrec(Xfile*, Drec*);
35 78a779a3 2008-07-20 rsc static int rzdir(Xfs*, Dir*, int, Drec*);
37 78a779a3 2008-07-20 rsc Xfsub isosub =
39 78a779a3 2008-07-20 rsc ireset, iattach, iclone, iwalkup, iwalk, iopen, icreate,
40 78a779a3 2008-07-20 rsc ireaddir, iread, iwrite, iclunk, iremove, istat, iwstat
48 78a779a3 2008-07-20 rsc iattach(Xfile *root)
50 78a779a3 2008-07-20 rsc Xfs *cd = root->xf;
51 78a779a3 2008-07-20 rsc Iobuf *p; Voldesc *v; Isofile *fp; Drec *dp;
52 78a779a3 2008-07-20 rsc int fmt, blksize, i, n, l, haveplan9;
54 78a779a3 2008-07-20 rsc uchar dbuf[256];
55 78a779a3 2008-07-20 rsc Drec *rd = (Drec *)dbuf;
56 78a779a3 2008-07-20 rsc uchar *q, *s;
62 78a779a3 2008-07-20 rsc haveplan9 = 0;
63 78a779a3 2008-07-20 rsc for(i=VOLDESC;i<VOLDESC+100; i++){ /* +100 for sanity */
64 78a779a3 2008-07-20 rsc p = getbuf(cd->d, i);
65 78a779a3 2008-07-20 rsc v = (Voldesc*)(p->iobuf);
66 78a779a3 2008-07-20 rsc if(memcmp(v->byte, "\01CD001\01", 7) == 0){ /* iso */
68 78a779a3 2008-07-20 rsc putbuf(dirp);
71 78a779a3 2008-07-20 rsc dp = (Drec*)v->z.desc.rootdir;
72 78a779a3 2008-07-20 rsc blksize = l16(v->z.desc.blksize);
73 78a779a3 2008-07-20 rsc chat("iso, blksize=%d...", blksize);
75 78a779a3 2008-07-20 rsc v = (Voldesc*)(dirp->iobuf);
76 78a779a3 2008-07-20 rsc haveplan9 = (strncmp((char*)v->z.boot.sysid, "PLAN 9", 6)==0);
77 78a779a3 2008-07-20 rsc if(haveplan9){
78 78a779a3 2008-07-20 rsc if(noplan9) {
79 78a779a3 2008-07-20 rsc chat("ignoring plan9");
80 78a779a3 2008-07-20 rsc haveplan9 = 0;
83 78a779a3 2008-07-20 rsc chat("plan9 iso...");
89 78a779a3 2008-07-20 rsc if(memcmp(&v->byte[8], "\01CDROM\01", 7) == 0){ /* high sierra */
91 78a779a3 2008-07-20 rsc putbuf(dirp);
94 78a779a3 2008-07-20 rsc dp = (Drec*)v->r.desc.rootdir;
95 78a779a3 2008-07-20 rsc blksize = l16(v->r.desc.blksize);
96 78a779a3 2008-07-20 rsc chat("high sierra, blksize=%d...", blksize);
100 78a779a3 2008-07-20 rsc if(haveplan9==0 && !nojoliet
101 78a779a3 2008-07-20 rsc && memcmp(v->byte, "\02CD001\01", 7) == 0){
102 78a779a3 2008-07-20 rsc chat("%d %d\n", haveplan9, nojoliet);
104 78a779a3 2008-07-20 rsc * The right thing to do is walk the escape sequences looking
105 78a779a3 2008-07-20 rsc * for one of 25 2F 4[035], but Microsoft seems to not honor
106 78a779a3 2008-07-20 rsc * the format, which makes it hard to walk over.
108 78a779a3 2008-07-20 rsc q = v->z.desc.escapes;
109 78a779a3 2008-07-20 rsc if(q[0] == 0x25 && q[1] == 0x2F && (q[2] == 0x40 || q[2] == 0x43 || q[2] == 0x45)){ /* Joliet, it appears */
111 78a779a3 2008-07-20 rsc putbuf(dirp);
114 78a779a3 2008-07-20 rsc dp = (Drec*)v->z.desc.rootdir;
115 78a779a3 2008-07-20 rsc if(blksize != l16(v->z.desc.blksize))
116 78a779a3 2008-07-20 rsc fprint(2, "warning: suspicious Joliet blocksize\n");
117 78a779a3 2008-07-20 rsc chat("joliet...");
122 78a779a3 2008-07-20 rsc if(v->byte[0] == 0xFF)
126 78a779a3 2008-07-20 rsc if(fmt == 0){
128 78a779a3 2008-07-20 rsc putbuf(dirp);
131 78a779a3 2008-07-20 rsc assert(dirp != nil);
134 78a779a3 2008-07-20 rsc showdrec(2, fmt, dp);
135 78a779a3 2008-07-20 rsc if(blksize > Sectorsize){
136 78a779a3 2008-07-20 rsc chat("blksize too big...");
137 78a779a3 2008-07-20 rsc putbuf(dirp);
140 78a779a3 2008-07-20 rsc if(waserror()){
141 78a779a3 2008-07-20 rsc putbuf(dirp);
142 78a779a3 2008-07-20 rsc nexterror();
144 13c28c2c 2008-12-02 trisk root->len = sizeof(Isofile) - sizeof(Drec) + dp->z.reclen;
145 78a779a3 2008-07-20 rsc root->ptr = fp = ealloc(root->len);
147 78a779a3 2008-07-20 rsc if(haveplan9)
148 78a779a3 2008-07-20 rsc root->xf->isplan9 = 1;
150 78a779a3 2008-07-20 rsc fp->fmt = fmt;
151 78a779a3 2008-07-20 rsc fp->blksize = blksize;
152 78a779a3 2008-07-20 rsc fp->offset = 0;
153 78a779a3 2008-07-20 rsc fp->doffset = 0;
154 13c28c2c 2008-12-02 trisk memmove(&fp->d, dp, dp->z.reclen);
155 13c28c2c 2008-12-02 trisk root->qid.path = l32(dp->z.addr);
156 78a779a3 2008-07-20 rsc root->qid.type = QTDIR;
157 78a779a3 2008-07-20 rsc putbuf(dirp);
159 78a779a3 2008-07-20 rsc if(getdrec(root, rd) >= 0){
160 13c28c2c 2008-12-02 trisk n = rd->z.reclen-(34+rd->z.namelen);
161 13c28c2c 2008-12-02 trisk s = (uchar*)rd->z.name + rd->z.namelen;
162 78a779a3 2008-07-20 rsc if((uintptr)s & 1){
166 78a779a3 2008-07-20 rsc if(n >= 7 && s[0] == 'S' && s[1] == 'P' && s[2] == 7 &&
167 78a779a3 2008-07-20 rsc s[3] == 1 && s[4] == 0xBE && s[5] == 0xEF){
168 78a779a3 2008-07-20 rsc root->xf->issusp = 1;
169 78a779a3 2008-07-20 rsc root->xf->suspoff = s[6];
170 78a779a3 2008-07-20 rsc n -= root->xf->suspoff;
171 78a779a3 2008-07-20 rsc s += root->xf->suspoff;
172 78a779a3 2008-07-20 rsc for(; n >= 4; s += l, n -= l){
174 78a779a3 2008-07-20 rsc if(s[0] == 'E' && s[1] == 'R'){
175 78a779a3 2008-07-20 rsc if(!norock && s[4] == 10 && memcmp(s+8, "RRIP_1991A", 10) == 0)
176 78a779a3 2008-07-20 rsc root->xf->isrock = 1;
178 78a779a3 2008-07-20 rsc } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){
179 78a779a3 2008-07-20 rsc n = getcontin(root->xf->d, s, &s);
181 78a779a3 2008-07-20 rsc } else if(s[0] == 'R' && s[1] == 'R'){
183 78a779a3 2008-07-20 rsc root->xf->isrock = 1;
185 78a779a3 2008-07-20 rsc } else if(s[0] == 'S' && s[1] == 'T')
190 78a779a3 2008-07-20 rsc if(root->xf->isrock)
191 78a779a3 2008-07-20 rsc chat("Rock Ridge...");
192 78a779a3 2008-07-20 rsc fp->offset = 0;
193 78a779a3 2008-07-20 rsc fp->doffset = 0;
198 78a779a3 2008-07-20 rsc iclone(Xfile *of, Xfile *nf)
205 78a779a3 2008-07-20 rsc iwalkup(Xfile *f)
208 78a779a3 2008-07-20 rsc uchar dbuf[256];
209 78a779a3 2008-07-20 rsc Drec *d = (Drec *)dbuf;
210 78a779a3 2008-07-20 rsc Xfile pf, ppf;
211 78a779a3 2008-07-20 rsc Isofile piso, ppiso;
213 78a779a3 2008-07-20 rsc memset(&pf, 0, sizeof pf);
214 78a779a3 2008-07-20 rsc memset(&ppf, 0, sizeof ppf);
215 78a779a3 2008-07-20 rsc pf.ptr = &piso;
216 78a779a3 2008-07-20 rsc ppf.ptr = &ppiso;
217 78a779a3 2008-07-20 rsc if(opendotdot(f, &pf) < 0)
218 78a779a3 2008-07-20 rsc error("can't open pf");
219 13c28c2c 2008-12-02 trisk paddr = l32(pf.ptr->d.z.addr);
220 13c28c2c 2008-12-02 trisk if(l32(f->ptr->d.z.addr) == paddr)
222 78a779a3 2008-07-20 rsc if(opendotdot(&pf, &ppf) < 0)
223 78a779a3 2008-07-20 rsc error("can't open ppf");
224 78a779a3 2008-07-20 rsc while(getdrec(&ppf, d) >= 0){
225 13c28c2c 2008-12-02 trisk if(l32(d->z.addr) == paddr){
226 78a779a3 2008-07-20 rsc newdrec(f, d);
227 78a779a3 2008-07-20 rsc f->qid.path = paddr;
228 78a779a3 2008-07-20 rsc f->qid.type = QTDIR;
232 78a779a3 2008-07-20 rsc error("can't find addr of ..");
236 78a779a3 2008-07-20 rsc casestrcmp(int isplan9, char *a, char *b)
241 78a779a3 2008-07-20 rsc return strcmp(a, b);
245 78a779a3 2008-07-20 rsc if(ca >= 'A' && ca <= 'Z')
246 78a779a3 2008-07-20 rsc ca += 'a' - 'A';
247 78a779a3 2008-07-20 rsc if(cb >= 'A' && cb <= 'Z')
248 78a779a3 2008-07-20 rsc cb += 'a' - 'A';
249 78a779a3 2008-07-20 rsc if(ca != cb) {
260 78a779a3 2008-07-20 rsc iwalk(Xfile *f, char *name)
262 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr;
263 78a779a3 2008-07-20 rsc uchar dbuf[256];
264 78a779a3 2008-07-20 rsc char nbuf[4*Maxname];
265 78a779a3 2008-07-20 rsc Drec *d = (Drec*)dbuf;
268 78a779a3 2008-07-20 rsc int len, vers, dvers;
271 78a779a3 2008-07-20 rsc if(p = strchr(name, ';')) { /* assign = */
272 78a779a3 2008-07-20 rsc len = p-name;
273 78a779a3 2008-07-20 rsc if(len >= Maxname)
274 78a779a3 2008-07-20 rsc len = Maxname-1;
275 78a779a3 2008-07-20 rsc memmove(nbuf, name, len);
276 78a779a3 2008-07-20 rsc vers = strtoul(p+1, 0, 10);
277 78a779a3 2008-07-20 rsc name = nbuf;
280 78a779a3 2008-07-20 rsc len = strlen(name);
281 78a779a3 2008-07-20 rsc if(len >= Maxname){
282 78a779a3 2008-07-20 rsc len = Maxname-1;
283 78a779a3 2008-07-20 rsc if(name != nbuf){
284 78a779a3 2008-07-20 rsc memmove(nbuf, name, len);
285 78a779a3 2008-07-20 rsc name = nbuf;
287 78a779a3 2008-07-20 rsc name[len] = 0;
291 78a779a3 2008-07-20 rsc chat("%d \"%s\"...", strlen(name), name);
292 78a779a3 2008-07-20 rsc ip->offset = 0;
293 78a779a3 2008-07-20 rsc setnames(&dir, nbuf);
294 78a779a3 2008-07-20 rsc while(getdrec(f, d) >= 0) {
295 78a779a3 2008-07-20 rsc dvers = rzdir(f->xf, &dir, ip->fmt, d);
296 78a779a3 2008-07-20 rsc if(casestrcmp(f->xf->isplan9||f->xf->isrock, name, dir.name) != 0)
298 78a779a3 2008-07-20 rsc newdrec(f, d);
299 78a779a3 2008-07-20 rsc f->qid.path = dir.qid.path;
300 78a779a3 2008-07-20 rsc f->qid.type = dir.qid.type;
301 78a779a3 2008-07-20 rsc USED(dvers);
305 78a779a3 2008-07-20 rsc error(Enonexist);
309 78a779a3 2008-07-20 rsc iopen(Xfile *f, int mode)
311 78a779a3 2008-07-20 rsc mode &= ~OCEXEC;
312 78a779a3 2008-07-20 rsc if(mode != OREAD && mode != OEXEC)
313 78a779a3 2008-07-20 rsc error(Eperm);
314 78a779a3 2008-07-20 rsc f->ptr->offset = 0;
315 78a779a3 2008-07-20 rsc f->ptr->doffset = 0;
319 78a779a3 2008-07-20 rsc icreate(Xfile *f, char *name, long perm, int mode)
325 78a779a3 2008-07-20 rsc error(Eperm);
329 78a779a3 2008-07-20 rsc ireaddir(Xfile *f, uchar *buf, long offset, long count)
331 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr;
333 78a779a3 2008-07-20 rsc char names[4*Maxname];
334 78a779a3 2008-07-20 rsc uchar dbuf[256];
335 78a779a3 2008-07-20 rsc Drec *drec = (Drec *)dbuf;
336 78a779a3 2008-07-20 rsc int n, rcnt;
338 78a779a3 2008-07-20 rsc if(offset==0){
339 78a779a3 2008-07-20 rsc ip->offset = 0;
340 78a779a3 2008-07-20 rsc ip->doffset = 0;
341 78a779a3 2008-07-20 rsc }else if(offset != ip->doffset)
342 78a779a3 2008-07-20 rsc error("seek in directory not allowed");
345 78a779a3 2008-07-20 rsc setnames(&d, names);
346 78a779a3 2008-07-20 rsc while(rcnt < count && getdrec(f, drec) >= 0){
347 13c28c2c 2008-12-02 trisk if(drec->z.namelen == 1){
348 13c28c2c 2008-12-02 trisk if(drec->z.name[0] == 0)
350 13c28c2c 2008-12-02 trisk if(drec->z.name[0] == 1)
353 78a779a3 2008-07-20 rsc rzdir(f->xf, &d, ip->fmt, drec);
354 78a779a3 2008-07-20 rsc d.qid.vers = f->qid.vers;
355 78a779a3 2008-07-20 rsc if((n = convD2M(&d, buf+rcnt, count-rcnt)) <= BIT16SZ){
356 78a779a3 2008-07-20 rsc ungetdrec(f);
361 78a779a3 2008-07-20 rsc ip->doffset += rcnt;
362 78a779a3 2008-07-20 rsc return rcnt;
366 78a779a3 2008-07-20 rsc iread(Xfile *f, char *buf, vlong offset, long count)
368 78a779a3 2008-07-20 rsc int n, o, rcnt = 0;
371 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr;
374 13c28c2c 2008-12-02 trisk size = l32(ip->d.z.size);
375 78a779a3 2008-07-20 rsc if(offset >= size)
377 78a779a3 2008-07-20 rsc if(offset+count > size)
378 78a779a3 2008-07-20 rsc count = size - offset;
379 13c28c2c 2008-12-02 trisk addr = ((vlong)l32(ip->d.z.addr) + ip->d.z.attrlen)*ip->blksize + offset;
380 78a779a3 2008-07-20 rsc o = addr % Sectorsize;
381 78a779a3 2008-07-20 rsc addr /= Sectorsize;
382 13c28c2c 2008-12-02 trisk /*chat("d.addr=%ld, addr=%lld, o=%d...", l32(ip->d.z.addr), addr, o);*/
383 78a779a3 2008-07-20 rsc n = Sectorsize - o;
385 78a779a3 2008-07-20 rsc while(count > 0){
386 78a779a3 2008-07-20 rsc if(n > count)
388 78a779a3 2008-07-20 rsc p = getbuf(f->xf->d, addr);
389 78a779a3 2008-07-20 rsc memmove(&buf[rcnt], &p->iobuf[o], n);
395 78a779a3 2008-07-20 rsc n = Sectorsize;
397 78a779a3 2008-07-20 rsc return rcnt;
401 78a779a3 2008-07-20 rsc iwrite(Xfile *f, char *buf, vlong offset, long count)
405 78a779a3 2008-07-20 rsc USED(offset);
406 78a779a3 2008-07-20 rsc USED(count);
407 78a779a3 2008-07-20 rsc error(Eperm);
412 78a779a3 2008-07-20 rsc iclunk(Xfile *f)
418 78a779a3 2008-07-20 rsc iremove(Xfile *f)
421 78a779a3 2008-07-20 rsc error(Eperm);
425 78a779a3 2008-07-20 rsc istat(Xfile *f, Dir *d)
427 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr;
429 78a779a3 2008-07-20 rsc rzdir(f->xf, d, ip->fmt, &ip->d);
430 78a779a3 2008-07-20 rsc d->qid.vers = f->qid.vers;
431 78a779a3 2008-07-20 rsc if(d->qid.path==f->xf->rootqid.path){
432 78a779a3 2008-07-20 rsc d->qid.path = 0;
433 78a779a3 2008-07-20 rsc d->qid.type = QTDIR;
438 78a779a3 2008-07-20 rsc iwstat(Xfile *f, Dir *d)
442 78a779a3 2008-07-20 rsc error(Eperm);
446 78a779a3 2008-07-20 rsc showdrec(int fd, int fmt, void *x)
448 78a779a3 2008-07-20 rsc Drec *d = (Drec *)x;
449 78a779a3 2008-07-20 rsc int namelen;
452 13c28c2c 2008-12-02 trisk if(d->z.reclen == 0)
454 78a779a3 2008-07-20 rsc fprint(fd, "%d %d %ld %ld ",
455 13c28c2c 2008-12-02 trisk d->z.reclen, d->z.attrlen, l32(d->z.addr), l32(d->z.size));
456 78a779a3 2008-07-20 rsc fprint(fd, "%s 0x%2.2x %d %d %ld ",
457 13c28c2c 2008-12-02 trisk rdate(d->z.date, fmt), (fmt=='z' ? d->z.flags : d->r.flags),
458 13c28c2c 2008-12-02 trisk d->z.unitsize, d->z.gapsize, l16(d->z.vseqno));
459 13c28c2c 2008-12-02 trisk fprint(fd, "%d %s", d->z.namelen, nstr(d->z.name, d->z.namelen));
460 78a779a3 2008-07-20 rsc if(fmt != 'J'){
461 13c28c2c 2008-12-02 trisk namelen = d->z.namelen + (1-(d->z.namelen&1));
462 13c28c2c 2008-12-02 trisk syslen = d->z.reclen - 33 - namelen;
463 78a779a3 2008-07-20 rsc if(syslen != 0)
464 13c28c2c 2008-12-02 trisk fprint(fd, " %s", nstr(&d->z.name[namelen], syslen));
466 78a779a3 2008-07-20 rsc fprint(fd, "\n");
467 13c28c2c 2008-12-02 trisk return d->z.reclen + (d->z.reclen&1);
471 78a779a3 2008-07-20 rsc newdrec(Xfile *f, Drec *dp)
473 78a779a3 2008-07-20 rsc Isofile *x = f->ptr;
477 13c28c2c 2008-12-02 trisk len = sizeof(Isofile) - sizeof(Drec) + dp->z.reclen;
478 78a779a3 2008-07-20 rsc n = ealloc(len);
479 78a779a3 2008-07-20 rsc n->fmt = x->fmt;
480 78a779a3 2008-07-20 rsc n->blksize = x->blksize;
481 78a779a3 2008-07-20 rsc n->offset = 0;
482 78a779a3 2008-07-20 rsc n->doffset = 0;
483 13c28c2c 2008-12-02 trisk memmove(&n->d, dp, dp->z.reclen);
486 78a779a3 2008-07-20 rsc f->len = len;
490 78a779a3 2008-07-20 rsc ungetdrec(Xfile *f)
492 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr;
494 78a779a3 2008-07-20 rsc if(ip->offset >= ip->odelta){
495 78a779a3 2008-07-20 rsc ip->offset -= ip->odelta;
496 78a779a3 2008-07-20 rsc ip->odelta = 0;
501 78a779a3 2008-07-20 rsc getdrec(Xfile *f, void *buf)
503 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr;
504 78a779a3 2008-07-20 rsc int len = 0, boff = 0;
507 78a779a3 2008-07-20 rsc Iobuf *p = 0;
511 13c28c2c 2008-12-02 trisk size = l32(ip->d.z.size);
512 78a779a3 2008-07-20 rsc while(ip->offset < size){
513 13c28c2c 2008-12-02 trisk addr = (l32(ip->d.z.addr)+ip->d.z.attrlen)*ip->blksize + ip->offset;
514 78a779a3 2008-07-20 rsc boff = addr % Sectorsize;
515 78a779a3 2008-07-20 rsc if(boff > Sectorsize-34){
516 78a779a3 2008-07-20 rsc ip->offset += Sectorsize-boff;
519 78a779a3 2008-07-20 rsc p = getbuf(f->xf->d, addr/Sectorsize);
520 78a779a3 2008-07-20 rsc len = p->iobuf[boff];
521 78a779a3 2008-07-20 rsc if(len >= 34)
525 78a779a3 2008-07-20 rsc ip->offset += Sectorsize-boff;
528 78a779a3 2008-07-20 rsc memmove(buf, &p->iobuf[boff], len);
530 78a779a3 2008-07-20 rsc ip->odelta = len + (len&1);
531 78a779a3 2008-07-20 rsc ip->offset += ip->odelta;
538 78a779a3 2008-07-20 rsc opendotdot(Xfile *f, Xfile *pf)
540 78a779a3 2008-07-20 rsc uchar dbuf[256];
541 78a779a3 2008-07-20 rsc Drec *d = (Drec *)dbuf;
542 78a779a3 2008-07-20 rsc Isofile *ip = f->ptr, *pip = pf->ptr;
544 78a779a3 2008-07-20 rsc ip->offset = 0;
545 78a779a3 2008-07-20 rsc if(getdrec(f, d) < 0){
546 78a779a3 2008-07-20 rsc chat("opendotdot: getdrec(.) failed...");
549 13c28c2c 2008-12-02 trisk if(d->z.namelen != 1 || d->z.name[0] != 0){
550 78a779a3 2008-07-20 rsc chat("opendotdot: no . entry...");
553 13c28c2c 2008-12-02 trisk if(l32(d->z.addr) != l32(ip->d.z.addr)){
554 78a779a3 2008-07-20 rsc chat("opendotdot: bad . address...");
557 78a779a3 2008-07-20 rsc if(getdrec(f, d) < 0){
558 78a779a3 2008-07-20 rsc chat("opendotdot: getdrec(..) failed...");
561 13c28c2c 2008-12-02 trisk if(d->z.namelen != 1 || d->z.name[0] != 1){
562 78a779a3 2008-07-20 rsc chat("opendotdot: no .. entry...");
566 78a779a3 2008-07-20 rsc pf->xf = f->xf;
567 78a779a3 2008-07-20 rsc pip->fmt = ip->fmt;
568 78a779a3 2008-07-20 rsc pip->blksize = ip->blksize;
569 78a779a3 2008-07-20 rsc pip->offset = 0;
570 78a779a3 2008-07-20 rsc pip->doffset = 0;
571 78a779a3 2008-07-20 rsc pip->d = *d;
581 78a779a3 2008-07-20 rsc rzdir(Xfs *fs, Dir *d, int fmt, Drec *dp)
583 78a779a3 2008-07-20 rsc int n, flags, i, j, lj, nl, vers, sysl, mode, l, have;
586 78a779a3 2008-07-20 rsc char buf[Maxname+UTFmax+1];
589 78a779a3 2008-07-20 rsc enum { ONAMELEN = 28 }; /* old Plan 9 directory name length */
594 13c28c2c 2008-12-02 trisk d->qid.path = l32(dp->z.addr);
595 78a779a3 2008-07-20 rsc d->qid.type = 0;
596 78a779a3 2008-07-20 rsc d->qid.vers = 0;
597 13c28c2c 2008-12-02 trisk n = dp->z.namelen;
598 78a779a3 2008-07-20 rsc memset(d->name, 0, Maxname);
599 78a779a3 2008-07-20 rsc if(n == 1) {
600 13c28c2c 2008-12-02 trisk switch(dp->z.name[0]){
602 78a779a3 2008-07-20 rsc d->name[1] = '.';
603 78a779a3 2008-07-20 rsc /* fall through */
605 78a779a3 2008-07-20 rsc d->name[0] = '.';
606 78a779a3 2008-07-20 rsc have = Hname;
609 13c28c2c 2008-12-02 trisk d->name[0] = tolower(dp->z.name[0]);
612 78a779a3 2008-07-20 rsc if(fmt == 'J'){ /* Joliet, 16-bit Unicode */
613 13c28c2c 2008-12-02 trisk q = (uchar*)dp->z.name;
614 78a779a3 2008-07-20 rsc for(i=j=lj=0; i<n && j<Maxname; i+=2){
616 78a779a3 2008-07-20 rsc r = (q[i]<<8)|q[i+1];
617 78a779a3 2008-07-20 rsc j += runetochar(buf+j, &r);
619 78a779a3 2008-07-20 rsc if(j >= Maxname)
621 78a779a3 2008-07-20 rsc memmove(d->name, buf, j);
623 78a779a3 2008-07-20 rsc if(n >= Maxname)
624 78a779a3 2008-07-20 rsc n = Maxname-1;
625 78a779a3 2008-07-20 rsc for(i=0; i<n; i++)
626 13c28c2c 2008-12-02 trisk d->name[i] = tolower(dp->z.name[i]);
630 13c28c2c 2008-12-02 trisk sysl = dp->z.reclen-(34+dp->z.namelen);
631 13c28c2c 2008-12-02 trisk s = (uchar*)dp->z.name + dp->z.namelen;
632 78a779a3 2008-07-20 rsc if(((uintptr)s) & 1) {
636 78a779a3 2008-07-20 rsc if(fs->isplan9 && sysl > 0) {
638 78a779a3 2008-07-20 rsc * get gid, uid, mode and possibly name
639 78a779a3 2008-07-20 rsc * from plan9 directory extension
642 78a779a3 2008-07-20 rsc if(nl >= ONAMELEN)
643 78a779a3 2008-07-20 rsc nl = ONAMELEN-1;
645 78a779a3 2008-07-20 rsc memset(d->name, 0, ONAMELEN);
646 78a779a3 2008-07-20 rsc memmove(d->name, s+1, nl);
648 78a779a3 2008-07-20 rsc s += 1 + *s;
650 78a779a3 2008-07-20 rsc if(nl >= ONAMELEN)
651 78a779a3 2008-07-20 rsc nl = ONAMELEN-1;
652 78a779a3 2008-07-20 rsc memset(d->uid, 0, ONAMELEN);
653 78a779a3 2008-07-20 rsc memmove(d->uid, s+1, nl);
654 78a779a3 2008-07-20 rsc s += 1 + *s;
656 78a779a3 2008-07-20 rsc if(nl >= ONAMELEN)
657 78a779a3 2008-07-20 rsc nl = ONAMELEN-1;
658 78a779a3 2008-07-20 rsc memset(d->gid, 0, ONAMELEN);
659 78a779a3 2008-07-20 rsc memmove(d->gid, s+1, nl);
660 78a779a3 2008-07-20 rsc s += 1 + *s;
661 78a779a3 2008-07-20 rsc if(((uintptr)s) & 1)
663 78a779a3 2008-07-20 rsc d->mode = l32(s);
664 78a779a3 2008-07-20 rsc if(d->mode & DMDIR)
665 78a779a3 2008-07-20 rsc d->qid.type |= QTDIR;
667 78a779a3 2008-07-20 rsc d->mode = 0444;
668 78a779a3 2008-07-20 rsc switch(fmt) {
670 78a779a3 2008-07-20 rsc if(fs->isrock)
671 78a779a3 2008-07-20 rsc strcpy(d->gid, "ridge");
673 78a779a3 2008-07-20 rsc strcpy(d->gid, "iso9660");
674 13c28c2c 2008-12-02 trisk flags = dp->z.flags;
677 78a779a3 2008-07-20 rsc strcpy(d->gid, "sierra");
678 13c28c2c 2008-12-02 trisk flags = dp->r.flags;
681 78a779a3 2008-07-20 rsc strcpy(d->gid, "joliet");
682 13c28c2c 2008-12-02 trisk flags = dp->z.flags;
685 78a779a3 2008-07-20 rsc strcpy(d->gid, "plan9");
686 13c28c2c 2008-12-02 trisk flags = dp->z.flags;
689 78a779a3 2008-07-20 rsc if(flags & 0x02){
690 78a779a3 2008-07-20 rsc d->qid.type |= QTDIR;
691 78a779a3 2008-07-20 rsc d->mode |= DMDIR|0111;
693 78a779a3 2008-07-20 rsc strcpy(d->uid, "cdrom");
694 78a779a3 2008-07-20 rsc if(fmt!='9' && !(d->mode&DMDIR)){
696 78a779a3 2008-07-20 rsc * ISO 9660 actually requires that you always have a . and a ;,
697 78a779a3 2008-07-20 rsc * even if there is no version and no extension. Very few writers
698 78a779a3 2008-07-20 rsc * do this. If the version is present, we use it for qid.vers.
699 78a779a3 2008-07-20 rsc * If there is no extension but there is a dot, we strip it off.
700 78a779a3 2008-07-20 rsc * (VMS heads couldn't comprehend the dot as a file name character
701 78a779a3 2008-07-20 rsc * rather than as just a separator between name and extension.)
703 78a779a3 2008-07-20 rsc * We don't do this for directory names because directories are
704 78a779a3 2008-07-20 rsc * not allowed to have extensions and versions.
706 78a779a3 2008-07-20 rsc if((p=strchr(d->name, ';')) != nil){
707 78a779a3 2008-07-20 rsc vers = strtoul(p+1, 0, 0);
708 78a779a3 2008-07-20 rsc d->qid.vers = vers;
711 78a779a3 2008-07-20 rsc if((p=strchr(d->name, '.')) != nil && *(p+1)=='\0')
714 78a779a3 2008-07-20 rsc if(fs->issusp){
716 78a779a3 2008-07-20 rsc s += fs->suspoff;
717 78a779a3 2008-07-20 rsc sysl -= fs->suspoff;
718 78a779a3 2008-07-20 rsc for(; sysl >= 4 && have != (Hname|Hmode); sysl -= l, s += l){
719 78a779a3 2008-07-20 rsc if(s[0] == 0 && ((uintptr)s & 1)){
720 78a779a3 2008-07-20 rsc /* MacOS pads individual entries, contrary to spec */
725 78a779a3 2008-07-20 rsc if(s[0] == 'P' && s[1] == 'X' && s[3] == 1){
726 78a779a3 2008-07-20 rsc /* posix file attributes */
727 78a779a3 2008-07-20 rsc mode = l32(s+4);
728 78a779a3 2008-07-20 rsc d->mode = mode & 0777;
729 78a779a3 2008-07-20 rsc if((mode & 0170000) == 040000){
730 78a779a3 2008-07-20 rsc d->mode |= DMDIR;
731 78a779a3 2008-07-20 rsc d->qid.type |= QTDIR;
733 78a779a3 2008-07-20 rsc have |= Hmode;
734 78a779a3 2008-07-20 rsc } else if(s[0] == 'N' && s[1] == 'M' && s[3] == 1){
735 78a779a3 2008-07-20 rsc /* alternative name */
736 78a779a3 2008-07-20 rsc if((s[4] & ~1) == 0){
738 78a779a3 2008-07-20 rsc if(i >= Maxname)
739 78a779a3 2008-07-20 rsc i = Maxname-1;
740 78a779a3 2008-07-20 rsc if((i -= nl) > 0){
741 78a779a3 2008-07-20 rsc memmove(d->name+nl, s+5, i);
744 78a779a3 2008-07-20 rsc if(s[4] == 0)
745 78a779a3 2008-07-20 rsc have |= Hname;
747 78a779a3 2008-07-20 rsc } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){
748 78a779a3 2008-07-20 rsc sysl = getcontin(fs->d, s, &s);
750 78a779a3 2008-07-20 rsc } else if(s[0] == 'S' && s[1] == 'T')
755 78a779a3 2008-07-20 rsc d->length = 0;
756 78a779a3 2008-07-20 rsc if((d->mode & DMDIR) == 0)
757 13c28c2c 2008-12-02 trisk d->length = l32(dp->z.size);
758 78a779a3 2008-07-20 rsc d->type = 0;
760 13c28c2c 2008-12-02 trisk d->atime = gtime(dp->z.date);
761 78a779a3 2008-07-20 rsc d->mtime = d->atime;
762 78a779a3 2008-07-20 rsc return vers;
766 78a779a3 2008-07-20 rsc getcontin(Xdata *dev, uchar *p, uchar **s)
768 78a779a3 2008-07-20 rsc long bn, off, len;
771 78a779a3 2008-07-20 rsc bn = l32(p+4);
772 78a779a3 2008-07-20 rsc off = l32(p+12);
773 78a779a3 2008-07-20 rsc len = l32(p+20);
774 78a779a3 2008-07-20 rsc chat("getcontin %d...", bn);
775 78a779a3 2008-07-20 rsc b = getbuf(dev, bn);
780 78a779a3 2008-07-20 rsc *s = b->iobuf+off;
785 78a779a3 2008-07-20 rsc static char *
786 78a779a3 2008-07-20 rsc nstr(uchar *p, int n)
788 78a779a3 2008-07-20 rsc static char buf[132];
789 78a779a3 2008-07-20 rsc char *q = buf;
791 78a779a3 2008-07-20 rsc while(--n >= 0){
792 78a779a3 2008-07-20 rsc if(*p == '\\')
793 78a779a3 2008-07-20 rsc *q++ = '\\';
794 78a779a3 2008-07-20 rsc if(' ' <= *p && *p <= '~')
795 78a779a3 2008-07-20 rsc *q++ = *p++;
797 78a779a3 2008-07-20 rsc q += sprint(q, "\\%2.2ux", *p++);
803 78a779a3 2008-07-20 rsc static char *
804 78a779a3 2008-07-20 rsc rdate(uchar *p, int fmt)
806 78a779a3 2008-07-20 rsc static char buf[64];
807 78a779a3 2008-07-20 rsc int htz, s, n;
809 78a779a3 2008-07-20 rsc n = sprint(buf, "%2.2d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d",
810 78a779a3 2008-07-20 rsc p[0], p[1], p[2], p[3], p[4], p[5]);
811 78a779a3 2008-07-20 rsc if(fmt == 'z'){
813 78a779a3 2008-07-20 rsc if(htz >= 128){
814 78a779a3 2008-07-20 rsc htz = 256-htz;
818 78a779a3 2008-07-20 rsc sprint(&buf[n], " (%c%.1f)", s, (float)htz/2);
824 78a779a3 2008-07-20 rsc dmsize[12] =
826 78a779a3 2008-07-20 rsc 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
829 78a779a3 2008-07-20 rsc #define dysize mydysize
832 78a779a3 2008-07-20 rsc dysize(int y)
835 78a779a3 2008-07-20 rsc if((y%4) == 0)
841 78a779a3 2008-07-20 rsc gtime(uchar *p) /* yMdhmsz */
844 78a779a3 2008-07-20 rsc int i, y, M, d, h, m, s, tz;
846 78a779a3 2008-07-20 rsc y=p[0]; M=p[1]; d=p[2];
847 78a779a3 2008-07-20 rsc h=p[3]; m=p[4]; s=p[5]; tz=p[6];
850 78a779a3 2008-07-20 rsc if (y < 1970)
852 78a779a3 2008-07-20 rsc if (M < 1 || M > 12)
854 78a779a3 2008-07-20 rsc if (d < 1 || d > dmsize[M-1])
855 78a779a3 2008-07-20 rsc if (!(M == 2 && d == 29 && dysize(y) == 366))
864 78a779a3 2008-07-20 rsc for(i=1970; i<y; i++)
865 78a779a3 2008-07-20 rsc t += dysize(i);
866 78a779a3 2008-07-20 rsc if (dysize(y)==366 && M >= 3)
869 78a779a3 2008-07-20 rsc t += dmsize[M-1];
871 78a779a3 2008-07-20 rsc t = 24*t + h;
872 78a779a3 2008-07-20 rsc t = 60*t + m;
873 78a779a3 2008-07-20 rsc t = 60*t + s;
877 78a779a3 2008-07-20 rsc #define p ((uchar*)arg)
880 78a779a3 2008-07-20 rsc l16(void *arg)
884 78a779a3 2008-07-20 rsc v = ((long)p[1]<<8)|p[0];
885 78a779a3 2008-07-20 rsc if (v >= 0x8000L)
886 78a779a3 2008-07-20 rsc v -= 0x10000L;
891 78a779a3 2008-07-20 rsc l32(void *arg)
893 78a779a3 2008-07-20 rsc return ((((((long)p[3]<<8)|p[2])<<8)|p[1])<<8)|p[0];