13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <auth.h>
43e12c5d1SDavid du Colombier #include <fcall.h>
53e12c5d1SDavid du Colombier #include "dat.h"
63e12c5d1SDavid du Colombier #include "fns.h"
73e12c5d1SDavid du Colombier #include "iso9660.h"
83e12c5d1SDavid du Colombier
93e12c5d1SDavid du Colombier static void ireset(void);
103e12c5d1SDavid du Colombier static int iattach(Xfile*);
113e12c5d1SDavid du Colombier static void iclone(Xfile*, Xfile*);
123e12c5d1SDavid du Colombier static void iwalkup(Xfile*);
133e12c5d1SDavid du Colombier static void iwalk(Xfile*, char*);
143e12c5d1SDavid du Colombier static void iopen(Xfile*, int);
153e12c5d1SDavid du Colombier static void icreate(Xfile*, char*, long, int);
169a747e4fSDavid du Colombier static long ireaddir(Xfile*, uchar*, long, long);
1731919746SDavid du Colombier static long iread(Xfile*, char*, vlong, long);
1831919746SDavid du Colombier static long iwrite(Xfile*, char*, vlong, long);
193e12c5d1SDavid du Colombier static void iclunk(Xfile*);
203e12c5d1SDavid du Colombier static void iremove(Xfile*);
213e12c5d1SDavid du Colombier static void istat(Xfile*, Dir*);
223e12c5d1SDavid du Colombier static void iwstat(Xfile*, Dir*);
233e12c5d1SDavid du Colombier
247dd7cddfSDavid du Colombier static char* nstr(uchar*, int);
257dd7cddfSDavid du Colombier static char* rdate(uchar*, int);
2659cc4ca5SDavid du Colombier static int getcontin(Xdata*, uchar*, uchar**);
273e12c5d1SDavid du Colombier static int getdrec(Xfile*, void*);
289a747e4fSDavid du Colombier static void ungetdrec(Xfile*);
293e12c5d1SDavid du Colombier static int opendotdot(Xfile*, Xfile*);
303e12c5d1SDavid du Colombier static int showdrec(int, int, void*);
317dd7cddfSDavid du Colombier static long gtime(uchar*);
323e12c5d1SDavid du Colombier static long l16(void*);
333e12c5d1SDavid du Colombier static long l32(void*);
34*3e33a36fSDavid du Colombier static vlong l64(void *);
353e12c5d1SDavid du Colombier static void newdrec(Xfile*, Drec*);
3659cc4ca5SDavid du Colombier static int rzdir(Xfs*, Dir*, int, Drec*);
373e12c5d1SDavid du Colombier
38bd389b36SDavid du Colombier Xfsub isosub =
39bd389b36SDavid du Colombier {
403e12c5d1SDavid du Colombier ireset, iattach, iclone, iwalkup, iwalk, iopen, icreate,
413e12c5d1SDavid du Colombier ireaddir, iread, iwrite, iclunk, iremove, istat, iwstat
423e12c5d1SDavid du Colombier };
433e12c5d1SDavid du Colombier
443b86f2f8SDavid du Colombier static vlong
fakemax(vlong len)453b86f2f8SDavid du Colombier fakemax(vlong len)
463b86f2f8SDavid du Colombier {
473b86f2f8SDavid du Colombier if(len == (1UL << 31) - 1) /* max. 9660 size? */
483b86f2f8SDavid du Colombier len = (1ULL << 63) - 1; /* pretend it's vast */
493b86f2f8SDavid du Colombier return len;
503b86f2f8SDavid du Colombier }
513b86f2f8SDavid du Colombier
523e12c5d1SDavid du Colombier static void
ireset(void)533e12c5d1SDavid du Colombier ireset(void)
543e12c5d1SDavid du Colombier {}
553e12c5d1SDavid du Colombier
563e12c5d1SDavid du Colombier static int
iattach(Xfile * root)573e12c5d1SDavid du Colombier iattach(Xfile *root)
583e12c5d1SDavid du Colombier {
593e12c5d1SDavid du Colombier Xfs *cd = root->xf;
603e12c5d1SDavid du Colombier Iobuf *p; Voldesc *v; Isofile *fp; Drec *dp;
6159cc4ca5SDavid du Colombier int fmt, blksize, i, n, l, haveplan9;
627dd7cddfSDavid du Colombier Iobuf *dirp;
6359cc4ca5SDavid du Colombier uchar dbuf[256];
6459cc4ca5SDavid du Colombier Drec *rd = (Drec *)dbuf;
6559cc4ca5SDavid du Colombier uchar *q, *s;
663e12c5d1SDavid du Colombier
677dd7cddfSDavid du Colombier dirp = nil;
687dd7cddfSDavid du Colombier blksize = 0;
697dd7cddfSDavid du Colombier fmt = 0;
707dd7cddfSDavid du Colombier dp = nil;
717dd7cddfSDavid du Colombier haveplan9 = 0;
727dd7cddfSDavid du Colombier for(i=VOLDESC;i<VOLDESC+100; i++){ /* +100 for sanity */
737dd7cddfSDavid du Colombier p = getbuf(cd->d, i);
743e12c5d1SDavid du Colombier v = (Voldesc*)(p->iobuf);
753e12c5d1SDavid du Colombier if(memcmp(v->byte, "\01CD001\01", 7) == 0){ /* iso */
767dd7cddfSDavid du Colombier if(dirp)
777dd7cddfSDavid du Colombier putbuf(dirp);
787dd7cddfSDavid du Colombier dirp = p;
793e12c5d1SDavid du Colombier fmt = 'z';
803e12c5d1SDavid du Colombier dp = (Drec*)v->z.desc.rootdir;
813e12c5d1SDavid du Colombier blksize = l16(v->z.desc.blksize);
823e12c5d1SDavid du Colombier chat("iso, blksize=%d...", blksize);
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier v = (Voldesc*)(dirp->iobuf);
857dd7cddfSDavid du Colombier haveplan9 = (strncmp((char*)v->z.boot.sysid, "PLAN 9", 6)==0);
8659cc4ca5SDavid du Colombier if(haveplan9){
877dd7cddfSDavid du Colombier if(noplan9) {
8859cc4ca5SDavid du Colombier chat("ignoring plan9");
897dd7cddfSDavid du Colombier haveplan9 = 0;
907dd7cddfSDavid du Colombier } else {
917dd7cddfSDavid du Colombier fmt = '9';
927dd7cddfSDavid du Colombier chat("plan9 iso...");
937dd7cddfSDavid du Colombier }
9459cc4ca5SDavid du Colombier }
957dd7cddfSDavid du Colombier continue;
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier
987dd7cddfSDavid du Colombier if(memcmp(&v->byte[8], "\01CDROM\01", 7) == 0){ /* high sierra */
997dd7cddfSDavid du Colombier if(dirp)
1007dd7cddfSDavid du Colombier putbuf(dirp);
1017dd7cddfSDavid du Colombier dirp = p;
1023e12c5d1SDavid du Colombier fmt = 'r';
1033e12c5d1SDavid du Colombier dp = (Drec*)v->r.desc.rootdir;
1043e12c5d1SDavid du Colombier blksize = l16(v->r.desc.blksize);
1053e12c5d1SDavid du Colombier chat("high sierra, blksize=%d...", blksize);
1067dd7cddfSDavid du Colombier continue;
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier if(haveplan9==0 && !nojoliet
1107dd7cddfSDavid du Colombier && memcmp(v->byte, "\02CD001\01", 7) == 0){
1117dd7cddfSDavid du Colombier chat("%d %d\n", haveplan9, nojoliet);
1127dd7cddfSDavid du Colombier /*
1137dd7cddfSDavid du Colombier * The right thing to do is walk the escape sequences looking
1147dd7cddfSDavid du Colombier * for one of 25 2F 4[035], but Microsoft seems to not honor
1157dd7cddfSDavid du Colombier * the format, which makes it hard to walk over.
1167dd7cddfSDavid du Colombier */
1177dd7cddfSDavid du Colombier q = v->z.desc.escapes;
1187dd7cddfSDavid du Colombier if(q[0] == 0x25 && q[1] == 0x2F && (q[2] == 0x40 || q[2] == 0x43 || q[2] == 0x45)){ /* Joliet, it appears */
1197dd7cddfSDavid du Colombier if(dirp)
1207dd7cddfSDavid du Colombier putbuf(dirp);
1217dd7cddfSDavid du Colombier dirp = p;
1227dd7cddfSDavid du Colombier fmt = 'J';
1237dd7cddfSDavid du Colombier dp = (Drec*)v->z.desc.rootdir;
1247dd7cddfSDavid du Colombier if(blksize != l16(v->z.desc.blksize))
1257dd7cddfSDavid du Colombier fprint(2, "warning: suspicious Joliet blocksize\n");
1267dd7cddfSDavid du Colombier chat("joliet...");
1277dd7cddfSDavid du Colombier continue;
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier }
1303e12c5d1SDavid du Colombier putbuf(p);
1317dd7cddfSDavid du Colombier if(v->byte[0] == 0xFF)
1327dd7cddfSDavid du Colombier break;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier if(fmt == 0){
1367dd7cddfSDavid du Colombier if(dirp)
1377dd7cddfSDavid du Colombier putbuf(dirp);
1383e12c5d1SDavid du Colombier return -1;
1393e12c5d1SDavid du Colombier }
1407dd7cddfSDavid du Colombier assert(dirp != nil);
1417dd7cddfSDavid du Colombier
1423e12c5d1SDavid du Colombier if(chatty)
1433e12c5d1SDavid du Colombier showdrec(2, fmt, dp);
1443e12c5d1SDavid du Colombier if(blksize > Sectorsize){
1453e12c5d1SDavid du Colombier chat("blksize too big...");
1467dd7cddfSDavid du Colombier putbuf(dirp);
1473e12c5d1SDavid du Colombier return -1;
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier if(waserror()){
1507dd7cddfSDavid du Colombier putbuf(dirp);
1513e12c5d1SDavid du Colombier nexterror();
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier root->len = sizeof(Isofile) - sizeof(Drec) + dp->reclen;
1543e12c5d1SDavid du Colombier root->ptr = fp = ealloc(root->len);
1557dd7cddfSDavid du Colombier
1567dd7cddfSDavid du Colombier if(haveplan9)
1577dd7cddfSDavid du Colombier root->xf->isplan9 = 1;
1587dd7cddfSDavid du Colombier
1593e12c5d1SDavid du Colombier fp->fmt = fmt;
1603e12c5d1SDavid du Colombier fp->blksize = blksize;
1613e12c5d1SDavid du Colombier fp->offset = 0;
1623e12c5d1SDavid du Colombier fp->doffset = 0;
1633e12c5d1SDavid du Colombier memmove(&fp->d, dp, dp->reclen);
1649a747e4fSDavid du Colombier root->qid.path = l32(dp->addr);
1659a747e4fSDavid du Colombier root->qid.type = QTDIR;
1667dd7cddfSDavid du Colombier putbuf(dirp);
1673e12c5d1SDavid du Colombier poperror();
16859cc4ca5SDavid du Colombier if(getdrec(root, rd) >= 0){
16959cc4ca5SDavid du Colombier n = rd->reclen-(34+rd->namelen);
17059cc4ca5SDavid du Colombier s = (uchar*)rd->name + rd->namelen;
17173e742d7SDavid du Colombier if((uintptr)s & 1){
17259cc4ca5SDavid du Colombier s++;
17359cc4ca5SDavid du Colombier n--;
17459cc4ca5SDavid du Colombier }
17559cc4ca5SDavid du Colombier if(n >= 7 && s[0] == 'S' && s[1] == 'P' && s[2] == 7 &&
17659cc4ca5SDavid du Colombier s[3] == 1 && s[4] == 0xBE && s[5] == 0xEF){
17759cc4ca5SDavid du Colombier root->xf->issusp = 1;
17859cc4ca5SDavid du Colombier root->xf->suspoff = s[6];
17959cc4ca5SDavid du Colombier n -= root->xf->suspoff;
18059cc4ca5SDavid du Colombier s += root->xf->suspoff;
18159cc4ca5SDavid du Colombier for(; n >= 4; s += l, n -= l){
18259cc4ca5SDavid du Colombier l = s[2];
18359cc4ca5SDavid du Colombier if(s[0] == 'E' && s[1] == 'R'){
18459cc4ca5SDavid du Colombier if(!norock && s[4] == 10 && memcmp(s+8, "RRIP_1991A", 10) == 0)
18559cc4ca5SDavid du Colombier root->xf->isrock = 1;
18659cc4ca5SDavid du Colombier break;
18759cc4ca5SDavid du Colombier } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){
18859cc4ca5SDavid du Colombier n = getcontin(root->xf->d, s, &s);
18959cc4ca5SDavid du Colombier continue;
19059cc4ca5SDavid du Colombier } else if(s[0] == 'R' && s[1] == 'R'){
19159cc4ca5SDavid du Colombier if(!norock)
19259cc4ca5SDavid du Colombier root->xf->isrock = 1;
19359cc4ca5SDavid du Colombier break;
19459cc4ca5SDavid du Colombier } else if(s[0] == 'S' && s[1] == 'T')
19559cc4ca5SDavid du Colombier break;
19659cc4ca5SDavid du Colombier }
19759cc4ca5SDavid du Colombier }
19859cc4ca5SDavid du Colombier }
19959cc4ca5SDavid du Colombier if(root->xf->isrock)
20059cc4ca5SDavid du Colombier chat("Rock Ridge...");
20159cc4ca5SDavid du Colombier fp->offset = 0;
20259cc4ca5SDavid du Colombier fp->doffset = 0;
2033e12c5d1SDavid du Colombier return 0;
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier
2063e12c5d1SDavid du Colombier static void
iclone(Xfile * of,Xfile * nf)2073e12c5d1SDavid du Colombier iclone(Xfile *of, Xfile *nf)
2083e12c5d1SDavid du Colombier {
2093e12c5d1SDavid du Colombier USED(of, nf);
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier
2123e12c5d1SDavid du Colombier static void
iwalkup(Xfile * f)2133e12c5d1SDavid du Colombier iwalkup(Xfile *f)
2143e12c5d1SDavid du Colombier {
215*3e33a36fSDavid du Colombier vlong paddr;
2163e12c5d1SDavid du Colombier uchar dbuf[256];
2173e12c5d1SDavid du Colombier Drec *d = (Drec *)dbuf;
2183e12c5d1SDavid du Colombier Xfile pf, ppf;
2193e12c5d1SDavid du Colombier Isofile piso, ppiso;
2203e12c5d1SDavid du Colombier
2213e12c5d1SDavid du Colombier memset(&pf, 0, sizeof pf);
2223e12c5d1SDavid du Colombier memset(&ppf, 0, sizeof ppf);
2233e12c5d1SDavid du Colombier pf.ptr = &piso;
2243e12c5d1SDavid du Colombier ppf.ptr = &ppiso;
2253e12c5d1SDavid du Colombier if(opendotdot(f, &pf) < 0)
2263e12c5d1SDavid du Colombier error("can't open pf");
2279a747e4fSDavid du Colombier paddr = l32(pf.ptr->d.addr);
2289a747e4fSDavid du Colombier if(l32(f->ptr->d.addr) == paddr)
2293e12c5d1SDavid du Colombier return;
2303e12c5d1SDavid du Colombier if(opendotdot(&pf, &ppf) < 0)
2313e12c5d1SDavid du Colombier error("can't open ppf");
2323e12c5d1SDavid du Colombier while(getdrec(&ppf, d) >= 0){
2333e12c5d1SDavid du Colombier if(l32(d->addr) == paddr){
2343e12c5d1SDavid du Colombier newdrec(f, d);
2359a747e4fSDavid du Colombier f->qid.path = paddr;
2369a747e4fSDavid du Colombier f->qid.type = QTDIR;
2373e12c5d1SDavid du Colombier return;
2383e12c5d1SDavid du Colombier }
2393e12c5d1SDavid du Colombier }
2403e12c5d1SDavid du Colombier error("can't find addr of ..");
2413e12c5d1SDavid du Colombier }
2423e12c5d1SDavid du Colombier
2437dd7cddfSDavid du Colombier static int
casestrcmp(int isplan9,char * a,char * b)2447dd7cddfSDavid du Colombier casestrcmp(int isplan9, char *a, char *b)
2457dd7cddfSDavid du Colombier {
2467dd7cddfSDavid du Colombier if(isplan9)
2477dd7cddfSDavid du Colombier return strcmp(a, b);
24807c70eb6SDavid du Colombier return cistrcmp(a, b);
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier
2513e12c5d1SDavid du Colombier static void
iwalk(Xfile * f,char * name)2523e12c5d1SDavid du Colombier iwalk(Xfile *f, char *name)
2533e12c5d1SDavid du Colombier {
2543e12c5d1SDavid du Colombier Isofile *ip = f->ptr;
2553e12c5d1SDavid du Colombier uchar dbuf[256];
2569a747e4fSDavid du Colombier char nbuf[4*Maxname];
2573e12c5d1SDavid du Colombier Drec *d = (Drec*)dbuf;
2583e12c5d1SDavid du Colombier Dir dir;
2593e12c5d1SDavid du Colombier char *p;
260bd389b36SDavid du Colombier int len, vers, dvers;
2613e12c5d1SDavid du Colombier
262bd389b36SDavid du Colombier vers = -1;
263bd389b36SDavid du Colombier if(p = strchr(name, ';')) { /* assign = */
264bd389b36SDavid du Colombier len = p-name;
2659a747e4fSDavid du Colombier if(len >= Maxname)
2669a747e4fSDavid du Colombier len = Maxname-1;
267bd389b36SDavid du Colombier memmove(nbuf, name, len);
268bd389b36SDavid du Colombier vers = strtoul(p+1, 0, 10);
2693e12c5d1SDavid du Colombier name = nbuf;
2703e12c5d1SDavid du Colombier }
2719a747e4fSDavid du Colombier /*
272bd389b36SDavid du Colombier len = strlen(name);
2739a747e4fSDavid du Colombier if(len >= Maxname){
2749a747e4fSDavid du Colombier len = Maxname-1;
2759a747e4fSDavid du Colombier if(name != nbuf){
2769a747e4fSDavid du Colombier memmove(nbuf, name, len);
2779a747e4fSDavid du Colombier name = nbuf;
2789a747e4fSDavid du Colombier }
279bd389b36SDavid du Colombier name[len] = 0;
2809a747e4fSDavid du Colombier }
2819a747e4fSDavid du Colombier */
282bd389b36SDavid du Colombier
2839a747e4fSDavid du Colombier chat("%d \"%s\"...", strlen(name), name);
2843e12c5d1SDavid du Colombier ip->offset = 0;
2859a747e4fSDavid du Colombier setnames(&dir, nbuf);
286bd389b36SDavid du Colombier while(getdrec(f, d) >= 0) {
28759cc4ca5SDavid du Colombier dvers = rzdir(f->xf, &dir, ip->fmt, d);
28859cc4ca5SDavid du Colombier if(casestrcmp(f->xf->isplan9||f->xf->isrock, name, dir.name) != 0)
2893e12c5d1SDavid du Colombier continue;
2903e12c5d1SDavid du Colombier newdrec(f, d);
2913e12c5d1SDavid du Colombier f->qid.path = dir.qid.path;
2929a747e4fSDavid du Colombier f->qid.type = dir.qid.type;
293bd389b36SDavid du Colombier USED(dvers);
2943e12c5d1SDavid du Colombier return;
2953e12c5d1SDavid du Colombier }
296bd389b36SDavid du Colombier USED(vers);
2973e12c5d1SDavid du Colombier error(Enonexist);
2983e12c5d1SDavid du Colombier }
2993e12c5d1SDavid du Colombier
3003e12c5d1SDavid du Colombier static void
iopen(Xfile * f,int mode)3013e12c5d1SDavid du Colombier iopen(Xfile *f, int mode)
3023e12c5d1SDavid du Colombier {
3033e12c5d1SDavid du Colombier mode &= ~OCEXEC;
3043e12c5d1SDavid du Colombier if(mode != OREAD && mode != OEXEC)
3053e12c5d1SDavid du Colombier error(Eperm);
3069a747e4fSDavid du Colombier f->ptr->offset = 0;
3079a747e4fSDavid du Colombier f->ptr->doffset = 0;
3083e12c5d1SDavid du Colombier }
3093e12c5d1SDavid du Colombier
3103e12c5d1SDavid du Colombier static void
icreate(Xfile * f,char * name,long perm,int mode)3113e12c5d1SDavid du Colombier icreate(Xfile *f, char *name, long perm, int mode)
3123e12c5d1SDavid du Colombier {
3133e12c5d1SDavid du Colombier USED(f, name, perm, mode);
3143e12c5d1SDavid du Colombier error(Eperm);
3153e12c5d1SDavid du Colombier }
3163e12c5d1SDavid du Colombier
3173e12c5d1SDavid du Colombier static long
ireaddir(Xfile * f,uchar * buf,long offset,long count)3189a747e4fSDavid du Colombier ireaddir(Xfile *f, uchar *buf, long offset, long count)
3193e12c5d1SDavid du Colombier {
3203e12c5d1SDavid du Colombier Isofile *ip = f->ptr;
3213e12c5d1SDavid du Colombier Dir d;
3229a747e4fSDavid du Colombier char names[4*Maxname];
3233e12c5d1SDavid du Colombier uchar dbuf[256];
3243e12c5d1SDavid du Colombier Drec *drec = (Drec *)dbuf;
3259a747e4fSDavid du Colombier int n, rcnt;
3263e12c5d1SDavid du Colombier
3279a747e4fSDavid du Colombier if(offset==0){
3283e12c5d1SDavid du Colombier ip->offset = 0;
3293e12c5d1SDavid du Colombier ip->doffset = 0;
3309a747e4fSDavid du Colombier }else if(offset != ip->doffset)
3319a747e4fSDavid du Colombier error("seek in directory not allowed");
3329a747e4fSDavid du Colombier
3339a747e4fSDavid du Colombier rcnt = 0;
3349a747e4fSDavid du Colombier setnames(&d, names);
3353e12c5d1SDavid du Colombier while(rcnt < count && getdrec(f, drec) >= 0){
3363e12c5d1SDavid du Colombier if(drec->namelen == 1){
3373e12c5d1SDavid du Colombier if(drec->name[0] == 0)
3383e12c5d1SDavid du Colombier continue;
3393e12c5d1SDavid du Colombier if(drec->name[0] == 1)
3403e12c5d1SDavid du Colombier continue;
3413e12c5d1SDavid du Colombier }
34259cc4ca5SDavid du Colombier rzdir(f->xf, &d, ip->fmt, drec);
3433e12c5d1SDavid du Colombier d.qid.vers = f->qid.vers;
3449a747e4fSDavid du Colombier if((n = convD2M(&d, buf+rcnt, count-rcnt)) <= BIT16SZ){
3459a747e4fSDavid du Colombier ungetdrec(f);
3469a747e4fSDavid du Colombier break;
3479a747e4fSDavid du Colombier }
3489a747e4fSDavid du Colombier rcnt += n;
3493e12c5d1SDavid du Colombier }
3503e12c5d1SDavid du Colombier ip->doffset += rcnt;
3513e12c5d1SDavid du Colombier return rcnt;
3523e12c5d1SDavid du Colombier }
3533e12c5d1SDavid du Colombier
3543e12c5d1SDavid du Colombier static long
iread(Xfile * f,char * buf,vlong offset,long count)35531919746SDavid du Colombier iread(Xfile *f, char *buf, vlong offset, long count)
3563e12c5d1SDavid du Colombier {
35731919746SDavid du Colombier int n, o, rcnt = 0;
3583b86f2f8SDavid du Colombier vlong size, addr;
3593e12c5d1SDavid du Colombier Isofile *ip = f->ptr;
3603e12c5d1SDavid du Colombier Iobuf *p;
3613e12c5d1SDavid du Colombier
3623b86f2f8SDavid du Colombier size = fakemax(l32(ip->d.size));
3633e12c5d1SDavid du Colombier if(offset >= size)
3643e12c5d1SDavid du Colombier return 0;
3653e12c5d1SDavid du Colombier if(offset+count > size)
3663e12c5d1SDavid du Colombier count = size - offset;
36731919746SDavid du Colombier addr = ((vlong)l32(ip->d.addr) + ip->d.attrlen)*ip->blksize + offset;
36831919746SDavid du Colombier o = addr % Sectorsize;
36931919746SDavid du Colombier addr /= Sectorsize;
37031919746SDavid du Colombier /*chat("d.addr=%ld, addr=%lld, o=%d...", l32(ip->d.addr), addr, o);*/
3713e12c5d1SDavid du Colombier n = Sectorsize - o;
3723e12c5d1SDavid du Colombier
3733e12c5d1SDavid du Colombier while(count > 0){
3743e12c5d1SDavid du Colombier if(n > count)
3753e12c5d1SDavid du Colombier n = count;
3763e12c5d1SDavid du Colombier p = getbuf(f->xf->d, addr);
3773e12c5d1SDavid du Colombier memmove(&buf[rcnt], &p->iobuf[o], n);
3783e12c5d1SDavid du Colombier putbuf(p);
3793e12c5d1SDavid du Colombier count -= n;
3803e12c5d1SDavid du Colombier rcnt += n;
3813e12c5d1SDavid du Colombier ++addr;
3823e12c5d1SDavid du Colombier o = 0;
3833e12c5d1SDavid du Colombier n = Sectorsize;
3843e12c5d1SDavid du Colombier }
3853e12c5d1SDavid du Colombier return rcnt;
3863e12c5d1SDavid du Colombier }
3873e12c5d1SDavid du Colombier
3883e12c5d1SDavid du Colombier static long
iwrite(Xfile * f,char * buf,vlong offset,long count)38931919746SDavid du Colombier iwrite(Xfile *f, char *buf, vlong offset, long count)
3903e12c5d1SDavid du Colombier {
3913e12c5d1SDavid du Colombier USED(f, buf, offset, count);
3923e12c5d1SDavid du Colombier error(Eperm);
3933e12c5d1SDavid du Colombier return 0;
3943e12c5d1SDavid du Colombier }
3953e12c5d1SDavid du Colombier
3963e12c5d1SDavid du Colombier static void
iclunk(Xfile * f)3973e12c5d1SDavid du Colombier iclunk(Xfile *f)
3983e12c5d1SDavid du Colombier {
3993e12c5d1SDavid du Colombier USED(f);
4003e12c5d1SDavid du Colombier }
4013e12c5d1SDavid du Colombier
4023e12c5d1SDavid du Colombier static void
iremove(Xfile * f)4033e12c5d1SDavid du Colombier iremove(Xfile *f)
4043e12c5d1SDavid du Colombier {
4053e12c5d1SDavid du Colombier USED(f);
4063e12c5d1SDavid du Colombier error(Eperm);
4073e12c5d1SDavid du Colombier }
4083e12c5d1SDavid du Colombier
4093e12c5d1SDavid du Colombier static void
istat(Xfile * f,Dir * d)4103e12c5d1SDavid du Colombier istat(Xfile *f, Dir *d)
4113e12c5d1SDavid du Colombier {
4123e12c5d1SDavid du Colombier Isofile *ip = f->ptr;
4133e12c5d1SDavid du Colombier
41459cc4ca5SDavid du Colombier rzdir(f->xf, d, ip->fmt, &ip->d);
4153e12c5d1SDavid du Colombier d->qid.vers = f->qid.vers;
4169a747e4fSDavid du Colombier if(d->qid.path==f->xf->rootqid.path){
4179a747e4fSDavid du Colombier d->qid.path = 0;
4189a747e4fSDavid du Colombier d->qid.type = QTDIR;
4199a747e4fSDavid du Colombier }
4203e12c5d1SDavid du Colombier }
4213e12c5d1SDavid du Colombier
4223e12c5d1SDavid du Colombier static void
iwstat(Xfile * f,Dir * d)4233e12c5d1SDavid du Colombier iwstat(Xfile *f, Dir *d)
4243e12c5d1SDavid du Colombier {
4253e12c5d1SDavid du Colombier USED(f, d);
4263e12c5d1SDavid du Colombier error(Eperm);
4273e12c5d1SDavid du Colombier }
4283e12c5d1SDavid du Colombier
4293e12c5d1SDavid du Colombier static int
showdrec(int fd,int fmt,void * x)4303e12c5d1SDavid du Colombier showdrec(int fd, int fmt, void *x)
4313e12c5d1SDavid du Colombier {
4323e12c5d1SDavid du Colombier Drec *d = (Drec *)x;
4337dd7cddfSDavid du Colombier int namelen;
4347dd7cddfSDavid du Colombier int syslen;
4353e12c5d1SDavid du Colombier
4363e12c5d1SDavid du Colombier if(d->reclen == 0)
4373e12c5d1SDavid du Colombier return 0;
4387dd7cddfSDavid du Colombier fprint(fd, "%d %d %ld %ld ",
4393e12c5d1SDavid du Colombier d->reclen, d->attrlen, l32(d->addr), l32(d->size));
4407dd7cddfSDavid du Colombier fprint(fd, "%s 0x%2.2x %d %d %ld ",
4413e12c5d1SDavid du Colombier rdate(d->date, fmt), (fmt=='z' ? d->flags : d->r_flags),
4423e12c5d1SDavid du Colombier d->unitsize, d->gapsize, l16(d->vseqno));
4433e12c5d1SDavid du Colombier fprint(fd, "%d %s", d->namelen, nstr(d->name, d->namelen));
4447dd7cddfSDavid du Colombier if(fmt != 'J'){
4453e12c5d1SDavid du Colombier namelen = d->namelen + (1-(d->namelen&1));
4463e12c5d1SDavid du Colombier syslen = d->reclen - 33 - namelen;
4473e12c5d1SDavid du Colombier if(syslen != 0)
4483e12c5d1SDavid du Colombier fprint(fd, " %s", nstr(&d->name[namelen], syslen));
4497dd7cddfSDavid du Colombier }
4503e12c5d1SDavid du Colombier fprint(fd, "\n");
4513e12c5d1SDavid du Colombier return d->reclen + (d->reclen&1);
4523e12c5d1SDavid du Colombier }
4533e12c5d1SDavid du Colombier
4543e12c5d1SDavid du Colombier static void
newdrec(Xfile * f,Drec * dp)4553e12c5d1SDavid du Colombier newdrec(Xfile *f, Drec *dp)
4563e12c5d1SDavid du Colombier {
4573e12c5d1SDavid du Colombier Isofile *x = f->ptr;
4583e12c5d1SDavid du Colombier Isofile *n;
4593e12c5d1SDavid du Colombier int len;
4603e12c5d1SDavid du Colombier
4613e12c5d1SDavid du Colombier len = sizeof(Isofile) - sizeof(Drec) + dp->reclen;
4623e12c5d1SDavid du Colombier n = ealloc(len);
4633e12c5d1SDavid du Colombier n->fmt = x->fmt;
4643e12c5d1SDavid du Colombier n->blksize = x->blksize;
4653e12c5d1SDavid du Colombier n->offset = 0;
4663e12c5d1SDavid du Colombier n->doffset = 0;
4673e12c5d1SDavid du Colombier memmove(&n->d, dp, dp->reclen);
4683e12c5d1SDavid du Colombier free(x);
4693e12c5d1SDavid du Colombier f->ptr = n;
4703e12c5d1SDavid du Colombier f->len = len;
4713e12c5d1SDavid du Colombier }
4723e12c5d1SDavid du Colombier
4739a747e4fSDavid du Colombier static void
ungetdrec(Xfile * f)4749a747e4fSDavid du Colombier ungetdrec(Xfile *f)
4759a747e4fSDavid du Colombier {
4769a747e4fSDavid du Colombier Isofile *ip = f->ptr;
4779a747e4fSDavid du Colombier
4789a747e4fSDavid du Colombier if(ip->offset >= ip->odelta){
4799a747e4fSDavid du Colombier ip->offset -= ip->odelta;
4809a747e4fSDavid du Colombier ip->odelta = 0;
4819a747e4fSDavid du Colombier }
4829a747e4fSDavid du Colombier }
4839a747e4fSDavid du Colombier
4843e12c5d1SDavid du Colombier static int
getdrec(Xfile * f,void * buf)4853e12c5d1SDavid du Colombier getdrec(Xfile *f, void *buf)
4863e12c5d1SDavid du Colombier {
4873e12c5d1SDavid du Colombier Isofile *ip = f->ptr;
4883e12c5d1SDavid du Colombier int len = 0, boff = 0;
48931919746SDavid du Colombier vlong addr;
4903b86f2f8SDavid du Colombier uvlong size;
4913e12c5d1SDavid du Colombier Iobuf *p = 0;
4923e12c5d1SDavid du Colombier
4933e12c5d1SDavid du Colombier if(!ip)
4943e12c5d1SDavid du Colombier return -1;
4953b86f2f8SDavid du Colombier size = fakemax(l32(ip->d.size));
4963e12c5d1SDavid du Colombier while(ip->offset < size){
497*3e33a36fSDavid du Colombier addr = ((vlong)l32(ip->d.addr)+ip->d.attrlen)*ip->blksize + ip->offset;
49831919746SDavid du Colombier boff = addr % Sectorsize;
4993e12c5d1SDavid du Colombier if(boff > Sectorsize-34){
5003e12c5d1SDavid du Colombier ip->offset += Sectorsize-boff;
5013e12c5d1SDavid du Colombier continue;
5023e12c5d1SDavid du Colombier }
50331919746SDavid du Colombier p = getbuf(f->xf->d, addr/Sectorsize);
5043e12c5d1SDavid du Colombier len = p->iobuf[boff];
5053e12c5d1SDavid du Colombier if(len >= 34)
5063e12c5d1SDavid du Colombier break;
5073e12c5d1SDavid du Colombier putbuf(p);
5083e12c5d1SDavid du Colombier p = 0;
5093e12c5d1SDavid du Colombier ip->offset += Sectorsize-boff;
5103e12c5d1SDavid du Colombier }
5113e12c5d1SDavid du Colombier if(p) {
5123e12c5d1SDavid du Colombier memmove(buf, &p->iobuf[boff], len);
5133e12c5d1SDavid du Colombier putbuf(p);
5149a747e4fSDavid du Colombier ip->odelta = len + (len&1);
5159a747e4fSDavid du Colombier ip->offset += ip->odelta;
516bd389b36SDavid du Colombier return 0;
51731919746SDavid du Colombier }
518bd389b36SDavid du Colombier return -1;
5193e12c5d1SDavid du Colombier }
5203e12c5d1SDavid du Colombier
5213e12c5d1SDavid du Colombier static int
opendotdot(Xfile * f,Xfile * pf)5223e12c5d1SDavid du Colombier opendotdot(Xfile *f, Xfile *pf)
5233e12c5d1SDavid du Colombier {
5243e12c5d1SDavid du Colombier uchar dbuf[256];
5253e12c5d1SDavid du Colombier Drec *d = (Drec *)dbuf;
5263e12c5d1SDavid du Colombier Isofile *ip = f->ptr, *pip = pf->ptr;
5273e12c5d1SDavid du Colombier
5283e12c5d1SDavid du Colombier ip->offset = 0;
5293e12c5d1SDavid du Colombier if(getdrec(f, d) < 0){
5303e12c5d1SDavid du Colombier chat("opendotdot: getdrec(.) failed...");
5313e12c5d1SDavid du Colombier return -1;
5323e12c5d1SDavid du Colombier }
5333e12c5d1SDavid du Colombier if(d->namelen != 1 || d->name[0] != 0){
5343e12c5d1SDavid du Colombier chat("opendotdot: no . entry...");
5353e12c5d1SDavid du Colombier return -1;
5363e12c5d1SDavid du Colombier }
5373e12c5d1SDavid du Colombier if(l32(d->addr) != l32(ip->d.addr)){
5383e12c5d1SDavid du Colombier chat("opendotdot: bad . address...");
5393e12c5d1SDavid du Colombier return -1;
5403e12c5d1SDavid du Colombier }
5413e12c5d1SDavid du Colombier if(getdrec(f, d) < 0){
5423e12c5d1SDavid du Colombier chat("opendotdot: getdrec(..) failed...");
5433e12c5d1SDavid du Colombier return -1;
5443e12c5d1SDavid du Colombier }
5453e12c5d1SDavid du Colombier if(d->namelen != 1 || d->name[0] != 1){
5463e12c5d1SDavid du Colombier chat("opendotdot: no .. entry...");
5473e12c5d1SDavid du Colombier return -1;
5483e12c5d1SDavid du Colombier }
5493e12c5d1SDavid du Colombier
5503e12c5d1SDavid du Colombier pf->xf = f->xf;
5513e12c5d1SDavid du Colombier pip->fmt = ip->fmt;
5523e12c5d1SDavid du Colombier pip->blksize = ip->blksize;
5533e12c5d1SDavid du Colombier pip->offset = 0;
5543e12c5d1SDavid du Colombier pip->doffset = 0;
5553e12c5d1SDavid du Colombier pip->d = *d;
5563e12c5d1SDavid du Colombier return 0;
5573e12c5d1SDavid du Colombier }
5583e12c5d1SDavid du Colombier
55959cc4ca5SDavid du Colombier enum {
56059cc4ca5SDavid du Colombier Hname = 1,
56159cc4ca5SDavid du Colombier Hmode = 2,
56259cc4ca5SDavid du Colombier };
56359cc4ca5SDavid du Colombier
564bd389b36SDavid du Colombier static int
rzdir(Xfs * fs,Dir * d,int fmt,Drec * dp)56559cc4ca5SDavid du Colombier rzdir(Xfs *fs, Dir *d, int fmt, Drec *dp)
5663e12c5d1SDavid du Colombier {
56759cc4ca5SDavid du Colombier int n, flags, i, j, lj, nl, vers, sysl, mode, l, have;
5683e12c5d1SDavid du Colombier uchar *s;
569bd389b36SDavid du Colombier char *p;
5709a747e4fSDavid du Colombier char buf[Maxname+UTFmax+1];
5717dd7cddfSDavid du Colombier uchar *q;
5727dd7cddfSDavid du Colombier Rune r;
5739a747e4fSDavid du Colombier enum { ONAMELEN = 28 }; /* old Plan 9 directory name length */
5743e12c5d1SDavid du Colombier
57559cc4ca5SDavid du Colombier have = 0;
576bd389b36SDavid du Colombier flags = 0;
577bd389b36SDavid du Colombier vers = -1;
5783e12c5d1SDavid du Colombier d->qid.path = l32(dp->addr);
5799a747e4fSDavid du Colombier d->qid.type = 0;
5803e12c5d1SDavid du Colombier d->qid.vers = 0;
581bd389b36SDavid du Colombier n = dp->namelen;
5829a747e4fSDavid du Colombier memset(d->name, 0, Maxname);
5833e12c5d1SDavid du Colombier if(n == 1) {
5843e12c5d1SDavid du Colombier switch(dp->name[0]){
5853e12c5d1SDavid du Colombier case 1:
5863e12c5d1SDavid du Colombier d->name[1] = '.';
5873e12c5d1SDavid du Colombier /* fall through */
5883e12c5d1SDavid du Colombier case 0:
5893e12c5d1SDavid du Colombier d->name[0] = '.';
59059cc4ca5SDavid du Colombier have = Hname;
5913e12c5d1SDavid du Colombier break;
5923e12c5d1SDavid du Colombier default:
5933e12c5d1SDavid du Colombier d->name[0] = tolower(dp->name[0]);
5943e12c5d1SDavid du Colombier }
5953e12c5d1SDavid du Colombier } else {
5967dd7cddfSDavid du Colombier if(fmt == 'J'){ /* Joliet, 16-bit Unicode */
5977dd7cddfSDavid du Colombier q = (uchar*)dp->name;
5989a747e4fSDavid du Colombier for(i=j=lj=0; i<n && j<Maxname; i+=2){
5997dd7cddfSDavid du Colombier lj = j;
6007dd7cddfSDavid du Colombier r = (q[i]<<8)|q[i+1];
6017dd7cddfSDavid du Colombier j += runetochar(buf+j, &r);
6027dd7cddfSDavid du Colombier }
6039a747e4fSDavid du Colombier if(j >= Maxname)
6047dd7cddfSDavid du Colombier j = lj;
6057dd7cddfSDavid du Colombier memmove(d->name, buf, j);
6067dd7cddfSDavid du Colombier }else{
6079a747e4fSDavid du Colombier if(n >= Maxname)
6089a747e4fSDavid du Colombier n = Maxname-1;
6093e12c5d1SDavid du Colombier for(i=0; i<n; i++)
6103e12c5d1SDavid du Colombier d->name[i] = tolower(dp->name[i]);
6113e12c5d1SDavid du Colombier }
6127dd7cddfSDavid du Colombier }
6133e12c5d1SDavid du Colombier
61459cc4ca5SDavid du Colombier sysl = dp->reclen-(34+dp->namelen);
61559cc4ca5SDavid du Colombier s = (uchar*)dp->name + dp->namelen;
61673e742d7SDavid du Colombier if(((uintptr)s) & 1) {
61759cc4ca5SDavid du Colombier s++;
61859cc4ca5SDavid du Colombier sysl--;
61959cc4ca5SDavid du Colombier }
62059cc4ca5SDavid du Colombier if(fs->isplan9 && sysl > 0) {
621bd389b36SDavid du Colombier /*
622bd389b36SDavid du Colombier * get gid, uid, mode and possibly name
623bd389b36SDavid du Colombier * from plan9 directory extension
624bd389b36SDavid du Colombier */
6253e12c5d1SDavid du Colombier nl = *s;
6269a747e4fSDavid du Colombier if(nl >= ONAMELEN)
6279a747e4fSDavid du Colombier nl = ONAMELEN-1;
6283e12c5d1SDavid du Colombier if(nl) {
6299a747e4fSDavid du Colombier memset(d->name, 0, ONAMELEN);
6303e12c5d1SDavid du Colombier memmove(d->name, s+1, nl);
6313e12c5d1SDavid du Colombier }
6323e12c5d1SDavid du Colombier s += 1 + *s;
6333e12c5d1SDavid du Colombier nl = *s;
6349a747e4fSDavid du Colombier if(nl >= ONAMELEN)
6359a747e4fSDavid du Colombier nl = ONAMELEN-1;
6369a747e4fSDavid du Colombier memset(d->uid, 0, ONAMELEN);
6373e12c5d1SDavid du Colombier memmove(d->uid, s+1, nl);
6383e12c5d1SDavid du Colombier s += 1 + *s;
6393e12c5d1SDavid du Colombier nl = *s;
6409a747e4fSDavid du Colombier if(nl >= ONAMELEN)
6419a747e4fSDavid du Colombier nl = ONAMELEN-1;
6429a747e4fSDavid du Colombier memset(d->gid, 0, ONAMELEN);
6433e12c5d1SDavid du Colombier memmove(d->gid, s+1, nl);
6443e12c5d1SDavid du Colombier s += 1 + *s;
64573e742d7SDavid du Colombier if(((uintptr)s) & 1)
6463e12c5d1SDavid du Colombier s++;
6473e12c5d1SDavid du Colombier d->mode = l32(s);
6489a747e4fSDavid du Colombier if(d->mode & DMDIR)
6499a747e4fSDavid du Colombier d->qid.type |= QTDIR;
6503e12c5d1SDavid du Colombier } else {
6513e12c5d1SDavid du Colombier d->mode = 0444;
6523e12c5d1SDavid du Colombier switch(fmt) {
6533e12c5d1SDavid du Colombier case 'z':
65459cc4ca5SDavid du Colombier if(fs->isrock)
65559cc4ca5SDavid du Colombier strcpy(d->gid, "ridge");
65659cc4ca5SDavid du Colombier else
6577dd7cddfSDavid du Colombier strcpy(d->gid, "iso9660");
6583e12c5d1SDavid du Colombier flags = dp->flags;
6593e12c5d1SDavid du Colombier break;
6603e12c5d1SDavid du Colombier case 'r':
6613e12c5d1SDavid du Colombier strcpy(d->gid, "sierra");
6623e12c5d1SDavid du Colombier flags = dp->r_flags;
6633e12c5d1SDavid du Colombier break;
6647dd7cddfSDavid du Colombier case 'J':
6657dd7cddfSDavid du Colombier strcpy(d->gid, "joliet");
6667dd7cddfSDavid du Colombier flags = dp->flags;
6677dd7cddfSDavid du Colombier break;
6687dd7cddfSDavid du Colombier case '9':
6697dd7cddfSDavid du Colombier strcpy(d->gid, "plan9");
6707dd7cddfSDavid du Colombier flags = dp->flags;
6717dd7cddfSDavid du Colombier break;
6723e12c5d1SDavid du Colombier }
6733e12c5d1SDavid du Colombier if(flags & 0x02){
6749a747e4fSDavid du Colombier d->qid.type |= QTDIR;
6759a747e4fSDavid du Colombier d->mode |= DMDIR|0111;
6763e12c5d1SDavid du Colombier }
6773e12c5d1SDavid du Colombier strcpy(d->uid, "cdrom");
6789a747e4fSDavid du Colombier if(fmt!='9' && !(d->mode&DMDIR)){
6799a747e4fSDavid du Colombier /*
6809a747e4fSDavid du Colombier * ISO 9660 actually requires that you always have a . and a ;,
6819a747e4fSDavid du Colombier * even if there is no version and no extension. Very few writers
6829a747e4fSDavid du Colombier * do this. If the version is present, we use it for qid.vers.
6839a747e4fSDavid du Colombier * If there is no extension but there is a dot, we strip it off.
6849a747e4fSDavid du Colombier * (VMS heads couldn't comprehend the dot as a file name character
6859a747e4fSDavid du Colombier * rather than as just a separator between name and extension.)
6869a747e4fSDavid du Colombier *
6879a747e4fSDavid du Colombier * We don't do this for directory names because directories are
6889a747e4fSDavid du Colombier * not allowed to have extensions and versions.
6899a747e4fSDavid du Colombier */
6909a747e4fSDavid du Colombier if((p=strchr(d->name, ';')) != nil){
6919a747e4fSDavid du Colombier vers = strtoul(p+1, 0, 0);
6929a747e4fSDavid du Colombier d->qid.vers = vers;
6939a747e4fSDavid du Colombier *p = '\0';
6949a747e4fSDavid du Colombier }
6959a747e4fSDavid du Colombier if((p=strchr(d->name, '.')) != nil && *(p+1)=='\0')
6969a747e4fSDavid du Colombier *p = '\0';
697bd389b36SDavid du Colombier }
69859cc4ca5SDavid du Colombier if(fs->issusp){
69959cc4ca5SDavid du Colombier nl = 0;
70059cc4ca5SDavid du Colombier s += fs->suspoff;
70159cc4ca5SDavid du Colombier sysl -= fs->suspoff;
70259cc4ca5SDavid du Colombier for(; sysl >= 4 && have != (Hname|Hmode); sysl -= l, s += l){
70373e742d7SDavid du Colombier if(s[0] == 0 && ((uintptr)s & 1)){
7041f3c807eSDavid du Colombier /* MacOS pads individual entries, contrary to spec */
7051f3c807eSDavid du Colombier s++;
7061f3c807eSDavid du Colombier sysl--;
7071f3c807eSDavid du Colombier }
70859cc4ca5SDavid du Colombier l = s[2];
70959cc4ca5SDavid du Colombier if(s[0] == 'P' && s[1] == 'X' && s[3] == 1){
71059cc4ca5SDavid du Colombier /* posix file attributes */
71159cc4ca5SDavid du Colombier mode = l32(s+4);
71259cc4ca5SDavid du Colombier d->mode = mode & 0777;
71359cc4ca5SDavid du Colombier if((mode & 0170000) == 040000){
7149a747e4fSDavid du Colombier d->mode |= DMDIR;
7159a747e4fSDavid du Colombier d->qid.type |= QTDIR;
71659cc4ca5SDavid du Colombier }
71759cc4ca5SDavid du Colombier have |= Hmode;
71859cc4ca5SDavid du Colombier } else if(s[0] == 'N' && s[1] == 'M' && s[3] == 1){
71959cc4ca5SDavid du Colombier /* alternative name */
72059cc4ca5SDavid du Colombier if((s[4] & ~1) == 0){
72159cc4ca5SDavid du Colombier i = nl+l-5;
7229a747e4fSDavid du Colombier if(i >= Maxname)
7239a747e4fSDavid du Colombier i = Maxname-1;
72459cc4ca5SDavid du Colombier if((i -= nl) > 0){
72559cc4ca5SDavid du Colombier memmove(d->name+nl, s+5, i);
72659cc4ca5SDavid du Colombier nl += i;
72759cc4ca5SDavid du Colombier }
72859cc4ca5SDavid du Colombier if(s[4] == 0)
72959cc4ca5SDavid du Colombier have |= Hname;
73059cc4ca5SDavid du Colombier }
73159cc4ca5SDavid du Colombier } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){
73259cc4ca5SDavid du Colombier sysl = getcontin(fs->d, s, &s);
73359cc4ca5SDavid du Colombier continue;
73459cc4ca5SDavid du Colombier } else if(s[0] == 'S' && s[1] == 'T')
73559cc4ca5SDavid du Colombier break;
73659cc4ca5SDavid du Colombier }
73759cc4ca5SDavid du Colombier }
7383e12c5d1SDavid du Colombier }
7393e12c5d1SDavid du Colombier d->length = 0;
7409a747e4fSDavid du Colombier if((d->mode & DMDIR) == 0)
7413b86f2f8SDavid du Colombier d->length = fakemax(l32(dp->size));
7423e12c5d1SDavid du Colombier d->type = 0;
7433e12c5d1SDavid du Colombier d->dev = 0;
7443e12c5d1SDavid du Colombier d->atime = gtime(dp->date);
7453e12c5d1SDavid du Colombier d->mtime = d->atime;
746bd389b36SDavid du Colombier return vers;
7473e12c5d1SDavid du Colombier }
7483e12c5d1SDavid du Colombier
74959cc4ca5SDavid du Colombier static int
getcontin(Xdata * dev,uchar * p,uchar ** s)75059cc4ca5SDavid du Colombier getcontin(Xdata *dev, uchar *p, uchar **s)
75159cc4ca5SDavid du Colombier {
752*3e33a36fSDavid du Colombier vlong bn, off, len;
75359cc4ca5SDavid du Colombier Iobuf *b;
75459cc4ca5SDavid du Colombier
75559cc4ca5SDavid du Colombier bn = l32(p+4);
75659cc4ca5SDavid du Colombier off = l32(p+12);
75759cc4ca5SDavid du Colombier len = l32(p+20);
758*3e33a36fSDavid du Colombier chat("getcontin %lld...", bn);
75959cc4ca5SDavid du Colombier b = getbuf(dev, bn);
76059cc4ca5SDavid du Colombier if(b == 0){
76159cc4ca5SDavid du Colombier *s = 0;
76259cc4ca5SDavid du Colombier return 0;
76359cc4ca5SDavid du Colombier }
76459cc4ca5SDavid du Colombier *s = b->iobuf+off;
76559cc4ca5SDavid du Colombier putbuf(b);
76659cc4ca5SDavid du Colombier return len;
76759cc4ca5SDavid du Colombier }
76859cc4ca5SDavid du Colombier
7693e12c5d1SDavid du Colombier static char *
nstr(uchar * p,int n)7703e12c5d1SDavid du Colombier nstr(uchar *p, int n)
7713e12c5d1SDavid du Colombier {
7723e12c5d1SDavid du Colombier static char buf[132];
7733e12c5d1SDavid du Colombier char *q = buf;
774bd389b36SDavid du Colombier
7753e12c5d1SDavid du Colombier while(--n >= 0){
7763e12c5d1SDavid du Colombier if(*p == '\\')
7773e12c5d1SDavid du Colombier *q++ = '\\';
7783e12c5d1SDavid du Colombier if(' ' <= *p && *p <= '~')
7793e12c5d1SDavid du Colombier *q++ = *p++;
7803e12c5d1SDavid du Colombier else
7813e12c5d1SDavid du Colombier q += sprint(q, "\\%2.2ux", *p++);
7823e12c5d1SDavid du Colombier }
7833e12c5d1SDavid du Colombier *q = 0;
7843e12c5d1SDavid du Colombier return buf;
7853e12c5d1SDavid du Colombier }
7863e12c5d1SDavid du Colombier
7873e12c5d1SDavid du Colombier static char *
rdate(uchar * p,int fmt)7883e12c5d1SDavid du Colombier rdate(uchar *p, int fmt)
7893e12c5d1SDavid du Colombier {
7903e12c5d1SDavid du Colombier static char buf[64];
7913e12c5d1SDavid du Colombier int htz, s, n;
7923e12c5d1SDavid du Colombier
7933e12c5d1SDavid du Colombier n = sprint(buf, "%2.2d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d",
7943e12c5d1SDavid du Colombier p[0], p[1], p[2], p[3], p[4], p[5]);
7953e12c5d1SDavid du Colombier if(fmt == 'z'){
7963e12c5d1SDavid du Colombier htz = p[6];
7973e12c5d1SDavid du Colombier if(htz >= 128){
7983e12c5d1SDavid du Colombier htz = 256-htz;
7993e12c5d1SDavid du Colombier s = '-';
8003e12c5d1SDavid du Colombier }else
8013e12c5d1SDavid du Colombier s = '+';
8023e12c5d1SDavid du Colombier sprint(&buf[n], " (%c%.1f)", s, (float)htz/2);
8033e12c5d1SDavid du Colombier }
8043e12c5d1SDavid du Colombier return buf;
8053e12c5d1SDavid du Colombier }
8063e12c5d1SDavid du Colombier
807bd389b36SDavid du Colombier static char
808bd389b36SDavid du Colombier dmsize[12] =
809bd389b36SDavid du Colombier {
8103e12c5d1SDavid du Colombier 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
8113e12c5d1SDavid du Colombier };
812bd389b36SDavid du Colombier
8133e12c5d1SDavid du Colombier static int
dysize(int y)8143e12c5d1SDavid du Colombier dysize(int y)
8153e12c5d1SDavid du Colombier {
8163e12c5d1SDavid du Colombier
8173e12c5d1SDavid du Colombier if((y%4) == 0)
8183e12c5d1SDavid du Colombier return 366;
8193e12c5d1SDavid du Colombier return 365;
8203e12c5d1SDavid du Colombier }
821bd389b36SDavid du Colombier
8223e12c5d1SDavid du Colombier static long
gtime(uchar * p)8233e12c5d1SDavid du Colombier gtime(uchar *p) /* yMdhmsz */
8243e12c5d1SDavid du Colombier {
8253e12c5d1SDavid du Colombier long t;
8263e12c5d1SDavid du Colombier int i, y, M, d, h, m, s, tz;
82745d5944cSDavid du Colombier
8283e12c5d1SDavid du Colombier y=p[0]; M=p[1]; d=p[2];
8293e12c5d1SDavid du Colombier h=p[3]; m=p[4]; s=p[5]; tz=p[6];
8303e12c5d1SDavid du Colombier USED(tz);
83145d5944cSDavid du Colombier y += 1900;
83245d5944cSDavid du Colombier if (y < 1970)
8333e12c5d1SDavid du Colombier return 0;
8343e12c5d1SDavid du Colombier if (M < 1 || M > 12)
8353e12c5d1SDavid du Colombier return 0;
8363e12c5d1SDavid du Colombier if (d < 1 || d > dmsize[M-1])
83745d5944cSDavid du Colombier if (!(M == 2 && d == 29 && dysize(y) == 366))
8383e12c5d1SDavid du Colombier return 0;
8393e12c5d1SDavid du Colombier if (h > 23)
8403e12c5d1SDavid du Colombier return 0;
8413e12c5d1SDavid du Colombier if (m > 59)
8423e12c5d1SDavid du Colombier return 0;
8433e12c5d1SDavid du Colombier if (s > 59)
8443e12c5d1SDavid du Colombier return 0;
8453e12c5d1SDavid du Colombier t = 0;
8463e12c5d1SDavid du Colombier for(i=1970; i<y; i++)
8473e12c5d1SDavid du Colombier t += dysize(i);
8483e12c5d1SDavid du Colombier if (dysize(y)==366 && M >= 3)
8493e12c5d1SDavid du Colombier t++;
8503e12c5d1SDavid du Colombier while(--M)
8513e12c5d1SDavid du Colombier t += dmsize[M-1];
8523e12c5d1SDavid du Colombier t += d-1;
8533e12c5d1SDavid du Colombier t = 24*t + h;
8543e12c5d1SDavid du Colombier t = 60*t + m;
8553e12c5d1SDavid du Colombier t = 60*t + s;
8563e12c5d1SDavid du Colombier return t;
8573e12c5d1SDavid du Colombier }
8583e12c5d1SDavid du Colombier
8593e12c5d1SDavid du Colombier #define p ((uchar*)arg)
8603e12c5d1SDavid du Colombier
8613e12c5d1SDavid du Colombier static long
l16(void * arg)8623e12c5d1SDavid du Colombier l16(void *arg)
8633e12c5d1SDavid du Colombier {
8643e12c5d1SDavid du Colombier long v;
8653e12c5d1SDavid du Colombier
8663e12c5d1SDavid du Colombier v = ((long)p[1]<<8)|p[0];
8673e12c5d1SDavid du Colombier if (v >= 0x8000L)
8683e12c5d1SDavid du Colombier v -= 0x10000L;
8693e12c5d1SDavid du Colombier return v;
8703e12c5d1SDavid du Colombier }
8713e12c5d1SDavid du Colombier
8723e12c5d1SDavid du Colombier static long
l32(void * arg)8733e12c5d1SDavid du Colombier l32(void *arg)
8743e12c5d1SDavid du Colombier {
875*3e33a36fSDavid du Colombier return (((long)p[3]<<8 | p[2])<<8 | p[1])<<8 | p[0];
8763e12c5d1SDavid du Colombier }
8773e12c5d1SDavid du Colombier
8783e12c5d1SDavid du Colombier #undef p
879*3e33a36fSDavid du Colombier
880*3e33a36fSDavid du Colombier static vlong
l64(void * arg)881*3e33a36fSDavid du Colombier l64(void *arg)
882*3e33a36fSDavid du Colombier {
883*3e33a36fSDavid du Colombier uchar *p;
884*3e33a36fSDavid du Colombier
885*3e33a36fSDavid du Colombier p = arg;
886*3e33a36fSDavid du Colombier return (vlong)l32(p+4) << 32 | (ulong)l32(p);
887*3e33a36fSDavid du Colombier }
888