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); 177dd7cddfSDavid du Colombier static long iread(Xfile*, char*, long, long); 187dd7cddfSDavid du Colombier static long iwrite(Xfile*, char*, long, 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*); 343e12c5d1SDavid du Colombier static void newdrec(Xfile*, Drec*); 3559cc4ca5SDavid du Colombier static int rzdir(Xfs*, Dir*, int, Drec*); 363e12c5d1SDavid du Colombier 37bd389b36SDavid du Colombier Xfsub isosub = 38bd389b36SDavid du Colombier { 393e12c5d1SDavid du Colombier ireset, iattach, iclone, iwalkup, iwalk, iopen, icreate, 403e12c5d1SDavid du Colombier ireaddir, iread, iwrite, iclunk, iremove, istat, iwstat 413e12c5d1SDavid du Colombier }; 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier static void 443e12c5d1SDavid du Colombier ireset(void) 453e12c5d1SDavid du Colombier {} 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier static int 483e12c5d1SDavid du Colombier iattach(Xfile *root) 493e12c5d1SDavid du Colombier { 503e12c5d1SDavid du Colombier Xfs *cd = root->xf; 513e12c5d1SDavid du Colombier Iobuf *p; Voldesc *v; Isofile *fp; Drec *dp; 5259cc4ca5SDavid du Colombier int fmt, blksize, i, n, l, haveplan9; 537dd7cddfSDavid du Colombier Iobuf *dirp; 5459cc4ca5SDavid du Colombier uchar dbuf[256]; 5559cc4ca5SDavid du Colombier Drec *rd = (Drec *)dbuf; 5659cc4ca5SDavid du Colombier uchar *q, *s; 573e12c5d1SDavid du Colombier 587dd7cddfSDavid du Colombier dirp = nil; 597dd7cddfSDavid du Colombier blksize = 0; 607dd7cddfSDavid du Colombier fmt = 0; 617dd7cddfSDavid du Colombier dp = nil; 627dd7cddfSDavid du Colombier haveplan9 = 0; 637dd7cddfSDavid du Colombier for(i=VOLDESC;i<VOLDESC+100; i++){ /* +100 for sanity */ 647dd7cddfSDavid du Colombier p = getbuf(cd->d, i); 653e12c5d1SDavid du Colombier v = (Voldesc*)(p->iobuf); 663e12c5d1SDavid du Colombier if(memcmp(v->byte, "\01CD001\01", 7) == 0){ /* iso */ 677dd7cddfSDavid du Colombier if(dirp) 687dd7cddfSDavid du Colombier putbuf(dirp); 697dd7cddfSDavid du Colombier dirp = p; 703e12c5d1SDavid du Colombier fmt = 'z'; 713e12c5d1SDavid du Colombier dp = (Drec*)v->z.desc.rootdir; 723e12c5d1SDavid du Colombier blksize = l16(v->z.desc.blksize); 733e12c5d1SDavid du Colombier chat("iso, blksize=%d...", blksize); 747dd7cddfSDavid du Colombier 757dd7cddfSDavid du Colombier v = (Voldesc*)(dirp->iobuf); 767dd7cddfSDavid du Colombier haveplan9 = (strncmp((char*)v->z.boot.sysid, "PLAN 9", 6)==0); 7759cc4ca5SDavid du Colombier if(haveplan9){ 787dd7cddfSDavid du Colombier if(noplan9) { 7959cc4ca5SDavid du Colombier chat("ignoring plan9"); 807dd7cddfSDavid du Colombier haveplan9 = 0; 817dd7cddfSDavid du Colombier } else { 827dd7cddfSDavid du Colombier fmt = '9'; 837dd7cddfSDavid du Colombier chat("plan9 iso..."); 847dd7cddfSDavid du Colombier } 8559cc4ca5SDavid du Colombier } 867dd7cddfSDavid du Colombier continue; 877dd7cddfSDavid du Colombier } 887dd7cddfSDavid du Colombier 897dd7cddfSDavid du Colombier if(memcmp(&v->byte[8], "\01CDROM\01", 7) == 0){ /* high sierra */ 907dd7cddfSDavid du Colombier if(dirp) 917dd7cddfSDavid du Colombier putbuf(dirp); 927dd7cddfSDavid du Colombier dirp = p; 933e12c5d1SDavid du Colombier fmt = 'r'; 943e12c5d1SDavid du Colombier dp = (Drec*)v->r.desc.rootdir; 953e12c5d1SDavid du Colombier blksize = l16(v->r.desc.blksize); 963e12c5d1SDavid du Colombier chat("high sierra, blksize=%d...", blksize); 977dd7cddfSDavid du Colombier continue; 987dd7cddfSDavid du Colombier } 997dd7cddfSDavid du Colombier 1007dd7cddfSDavid du Colombier if(haveplan9==0 && !nojoliet 1017dd7cddfSDavid du Colombier && memcmp(v->byte, "\02CD001\01", 7) == 0){ 1027dd7cddfSDavid du Colombier chat("%d %d\n", haveplan9, nojoliet); 1037dd7cddfSDavid du Colombier /* 1047dd7cddfSDavid du Colombier * The right thing to do is walk the escape sequences looking 1057dd7cddfSDavid du Colombier * for one of 25 2F 4[035], but Microsoft seems to not honor 1067dd7cddfSDavid du Colombier * the format, which makes it hard to walk over. 1077dd7cddfSDavid du Colombier */ 1087dd7cddfSDavid du Colombier q = v->z.desc.escapes; 1097dd7cddfSDavid du Colombier if(q[0] == 0x25 && q[1] == 0x2F && (q[2] == 0x40 || q[2] == 0x43 || q[2] == 0x45)){ /* Joliet, it appears */ 1107dd7cddfSDavid du Colombier if(dirp) 1117dd7cddfSDavid du Colombier putbuf(dirp); 1127dd7cddfSDavid du Colombier dirp = p; 1137dd7cddfSDavid du Colombier fmt = 'J'; 1147dd7cddfSDavid du Colombier dp = (Drec*)v->z.desc.rootdir; 1157dd7cddfSDavid du Colombier if(blksize != l16(v->z.desc.blksize)) 1167dd7cddfSDavid du Colombier fprint(2, "warning: suspicious Joliet blocksize\n"); 1177dd7cddfSDavid du Colombier chat("joliet..."); 1187dd7cddfSDavid du Colombier continue; 1197dd7cddfSDavid du Colombier } 1207dd7cddfSDavid du Colombier } 1213e12c5d1SDavid du Colombier putbuf(p); 1227dd7cddfSDavid du Colombier if(v->byte[0] == 0xFF) 1237dd7cddfSDavid du Colombier break; 1247dd7cddfSDavid du Colombier } 1257dd7cddfSDavid du Colombier 1267dd7cddfSDavid du Colombier if(fmt == 0){ 1277dd7cddfSDavid du Colombier if(dirp) 1287dd7cddfSDavid du Colombier putbuf(dirp); 1293e12c5d1SDavid du Colombier return -1; 1303e12c5d1SDavid du Colombier } 1317dd7cddfSDavid du Colombier assert(dirp != nil); 1327dd7cddfSDavid du Colombier 1333e12c5d1SDavid du Colombier if(chatty) 1343e12c5d1SDavid du Colombier showdrec(2, fmt, dp); 1353e12c5d1SDavid du Colombier if(blksize > Sectorsize){ 1363e12c5d1SDavid du Colombier chat("blksize too big..."); 1377dd7cddfSDavid du Colombier putbuf(dirp); 1383e12c5d1SDavid du Colombier return -1; 1393e12c5d1SDavid du Colombier } 1403e12c5d1SDavid du Colombier if(waserror()){ 1417dd7cddfSDavid du Colombier putbuf(dirp); 1423e12c5d1SDavid du Colombier nexterror(); 1433e12c5d1SDavid du Colombier } 1443e12c5d1SDavid du Colombier root->len = sizeof(Isofile) - sizeof(Drec) + dp->reclen; 1453e12c5d1SDavid du Colombier root->ptr = fp = ealloc(root->len); 1467dd7cddfSDavid du Colombier 1477dd7cddfSDavid du Colombier if(haveplan9) 1487dd7cddfSDavid du Colombier root->xf->isplan9 = 1; 1497dd7cddfSDavid du Colombier 1503e12c5d1SDavid du Colombier fp->fmt = fmt; 1513e12c5d1SDavid du Colombier fp->blksize = blksize; 1523e12c5d1SDavid du Colombier fp->offset = 0; 1533e12c5d1SDavid du Colombier fp->doffset = 0; 1543e12c5d1SDavid du Colombier memmove(&fp->d, dp, dp->reclen); 1559a747e4fSDavid du Colombier root->qid.path = l32(dp->addr); 1569a747e4fSDavid du Colombier root->qid.type = QTDIR; 1577dd7cddfSDavid du Colombier putbuf(dirp); 1583e12c5d1SDavid du Colombier poperror(); 15959cc4ca5SDavid du Colombier if(getdrec(root, rd) >= 0){ 16059cc4ca5SDavid du Colombier n = rd->reclen-(34+rd->namelen); 16159cc4ca5SDavid du Colombier s = (uchar*)rd->name + rd->namelen; 16259cc4ca5SDavid du Colombier if((ulong)s & 1){ 16359cc4ca5SDavid du Colombier s++; 16459cc4ca5SDavid du Colombier n--; 16559cc4ca5SDavid du Colombier } 16659cc4ca5SDavid du Colombier if(n >= 7 && s[0] == 'S' && s[1] == 'P' && s[2] == 7 && 16759cc4ca5SDavid du Colombier s[3] == 1 && s[4] == 0xBE && s[5] == 0xEF){ 16859cc4ca5SDavid du Colombier root->xf->issusp = 1; 16959cc4ca5SDavid du Colombier root->xf->suspoff = s[6]; 17059cc4ca5SDavid du Colombier n -= root->xf->suspoff; 17159cc4ca5SDavid du Colombier s += root->xf->suspoff; 17259cc4ca5SDavid du Colombier for(; n >= 4; s += l, n -= l){ 17359cc4ca5SDavid du Colombier l = s[2]; 17459cc4ca5SDavid du Colombier if(s[0] == 'E' && s[1] == 'R'){ 17559cc4ca5SDavid du Colombier if(!norock && s[4] == 10 && memcmp(s+8, "RRIP_1991A", 10) == 0) 17659cc4ca5SDavid du Colombier root->xf->isrock = 1; 17759cc4ca5SDavid du Colombier break; 17859cc4ca5SDavid du Colombier } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){ 17959cc4ca5SDavid du Colombier n = getcontin(root->xf->d, s, &s); 18059cc4ca5SDavid du Colombier continue; 18159cc4ca5SDavid du Colombier } else if(s[0] == 'R' && s[1] == 'R'){ 18259cc4ca5SDavid du Colombier if(!norock) 18359cc4ca5SDavid du Colombier root->xf->isrock = 1; 18459cc4ca5SDavid du Colombier break; 18559cc4ca5SDavid du Colombier } else if(s[0] == 'S' && s[1] == 'T') 18659cc4ca5SDavid du Colombier break; 18759cc4ca5SDavid du Colombier } 18859cc4ca5SDavid du Colombier } 18959cc4ca5SDavid du Colombier } 19059cc4ca5SDavid du Colombier if(root->xf->isrock) 19159cc4ca5SDavid du Colombier chat("Rock Ridge..."); 19259cc4ca5SDavid du Colombier fp->offset = 0; 19359cc4ca5SDavid du Colombier fp->doffset = 0; 1943e12c5d1SDavid du Colombier return 0; 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier static void 1983e12c5d1SDavid du Colombier iclone(Xfile *of, Xfile *nf) 1993e12c5d1SDavid du Colombier { 2003e12c5d1SDavid du Colombier USED(of, nf); 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier 2033e12c5d1SDavid du Colombier static void 2043e12c5d1SDavid du Colombier iwalkup(Xfile *f) 2053e12c5d1SDavid du Colombier { 2063e12c5d1SDavid du Colombier long paddr; 2073e12c5d1SDavid du Colombier uchar dbuf[256]; 2083e12c5d1SDavid du Colombier Drec *d = (Drec *)dbuf; 2093e12c5d1SDavid du Colombier Xfile pf, ppf; 2103e12c5d1SDavid du Colombier Isofile piso, ppiso; 2113e12c5d1SDavid du Colombier 2123e12c5d1SDavid du Colombier memset(&pf, 0, sizeof pf); 2133e12c5d1SDavid du Colombier memset(&ppf, 0, sizeof ppf); 2143e12c5d1SDavid du Colombier pf.ptr = &piso; 2153e12c5d1SDavid du Colombier ppf.ptr = &ppiso; 2163e12c5d1SDavid du Colombier if(opendotdot(f, &pf) < 0) 2173e12c5d1SDavid du Colombier error("can't open pf"); 2189a747e4fSDavid du Colombier paddr = l32(pf.ptr->d.addr); 2199a747e4fSDavid du Colombier if(l32(f->ptr->d.addr) == paddr) 2203e12c5d1SDavid du Colombier return; 2213e12c5d1SDavid du Colombier if(opendotdot(&pf, &ppf) < 0) 2223e12c5d1SDavid du Colombier error("can't open ppf"); 2233e12c5d1SDavid du Colombier while(getdrec(&ppf, d) >= 0){ 2243e12c5d1SDavid du Colombier if(l32(d->addr) == paddr){ 2253e12c5d1SDavid du Colombier newdrec(f, d); 2269a747e4fSDavid du Colombier f->qid.path = paddr; 2279a747e4fSDavid du Colombier f->qid.type = QTDIR; 2283e12c5d1SDavid du Colombier return; 2293e12c5d1SDavid du Colombier } 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier error("can't find addr of .."); 2323e12c5d1SDavid du Colombier } 2333e12c5d1SDavid du Colombier 2347dd7cddfSDavid du Colombier static int 2357dd7cddfSDavid du Colombier casestrcmp(int isplan9, char *a, char *b) 2367dd7cddfSDavid du Colombier { 2377dd7cddfSDavid du Colombier int ca, cb; 2387dd7cddfSDavid du Colombier 2397dd7cddfSDavid du Colombier if(isplan9) 2407dd7cddfSDavid du Colombier return strcmp(a, b); 2417dd7cddfSDavid du Colombier for(;;) { 2427dd7cddfSDavid du Colombier ca = *a++; 2437dd7cddfSDavid du Colombier cb = *b++; 2447dd7cddfSDavid du Colombier if(ca >= 'A' && ca <= 'Z') 2457dd7cddfSDavid du Colombier ca += 'a' - 'A'; 2467dd7cddfSDavid du Colombier if(cb >= 'A' && cb <= 'Z') 2477dd7cddfSDavid du Colombier cb += 'a' - 'A'; 2487dd7cddfSDavid du Colombier if(ca != cb) { 2497dd7cddfSDavid du Colombier if(ca > cb) 2507dd7cddfSDavid du Colombier return 1; 2517dd7cddfSDavid du Colombier return -1; 2527dd7cddfSDavid du Colombier } 2537dd7cddfSDavid du Colombier if(ca == 0) 2547dd7cddfSDavid du Colombier return 0; 2557dd7cddfSDavid du Colombier } 2567dd7cddfSDavid du Colombier } 2577dd7cddfSDavid du Colombier 2583e12c5d1SDavid du Colombier static void 2593e12c5d1SDavid du Colombier iwalk(Xfile *f, char *name) 2603e12c5d1SDavid du Colombier { 2613e12c5d1SDavid du Colombier Isofile *ip = f->ptr; 2623e12c5d1SDavid du Colombier uchar dbuf[256]; 2639a747e4fSDavid du Colombier char nbuf[4*Maxname]; 2643e12c5d1SDavid du Colombier Drec *d = (Drec*)dbuf; 2653e12c5d1SDavid du Colombier Dir dir; 2663e12c5d1SDavid du Colombier char *p; 267bd389b36SDavid du Colombier int len, vers, dvers; 2683e12c5d1SDavid du Colombier 269bd389b36SDavid du Colombier vers = -1; 270bd389b36SDavid du Colombier if(p = strchr(name, ';')) { /* assign = */ 271bd389b36SDavid du Colombier len = p-name; 2729a747e4fSDavid du Colombier if(len >= Maxname) 2739a747e4fSDavid du Colombier len = Maxname-1; 274bd389b36SDavid du Colombier memmove(nbuf, name, len); 275bd389b36SDavid du Colombier vers = strtoul(p+1, 0, 10); 2763e12c5d1SDavid du Colombier name = nbuf; 2773e12c5d1SDavid du Colombier } 2789a747e4fSDavid du Colombier /* 279bd389b36SDavid du Colombier len = strlen(name); 2809a747e4fSDavid du Colombier if(len >= Maxname){ 2819a747e4fSDavid du Colombier len = Maxname-1; 2829a747e4fSDavid du Colombier if(name != nbuf){ 2839a747e4fSDavid du Colombier memmove(nbuf, name, len); 2849a747e4fSDavid du Colombier name = nbuf; 2859a747e4fSDavid du Colombier } 286bd389b36SDavid du Colombier name[len] = 0; 2879a747e4fSDavid du Colombier } 2889a747e4fSDavid du Colombier */ 289bd389b36SDavid du Colombier 2909a747e4fSDavid du Colombier chat("%d \"%s\"...", strlen(name), name); 2913e12c5d1SDavid du Colombier ip->offset = 0; 2929a747e4fSDavid du Colombier setnames(&dir, nbuf); 293bd389b36SDavid du Colombier while(getdrec(f, d) >= 0) { 29459cc4ca5SDavid du Colombier dvers = rzdir(f->xf, &dir, ip->fmt, d); 29559cc4ca5SDavid du Colombier if(casestrcmp(f->xf->isplan9||f->xf->isrock, name, dir.name) != 0) 2963e12c5d1SDavid du Colombier continue; 2973e12c5d1SDavid du Colombier newdrec(f, d); 2983e12c5d1SDavid du Colombier f->qid.path = dir.qid.path; 2999a747e4fSDavid du Colombier f->qid.type = dir.qid.type; 300bd389b36SDavid du Colombier USED(dvers); 3013e12c5d1SDavid du Colombier return; 3023e12c5d1SDavid du Colombier } 303bd389b36SDavid du Colombier USED(vers); 3043e12c5d1SDavid du Colombier error(Enonexist); 3053e12c5d1SDavid du Colombier } 3063e12c5d1SDavid du Colombier 3073e12c5d1SDavid du Colombier static void 3083e12c5d1SDavid du Colombier iopen(Xfile *f, int mode) 3093e12c5d1SDavid du Colombier { 3103e12c5d1SDavid du Colombier mode &= ~OCEXEC; 3113e12c5d1SDavid du Colombier if(mode != OREAD && mode != OEXEC) 3123e12c5d1SDavid du Colombier error(Eperm); 3139a747e4fSDavid du Colombier f->ptr->offset = 0; 3149a747e4fSDavid du Colombier f->ptr->doffset = 0; 3153e12c5d1SDavid du Colombier } 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier static void 3183e12c5d1SDavid du Colombier icreate(Xfile *f, char *name, long perm, int mode) 3193e12c5d1SDavid du Colombier { 3203e12c5d1SDavid du Colombier USED(f, name, perm, mode); 3213e12c5d1SDavid du Colombier error(Eperm); 3223e12c5d1SDavid du Colombier } 3233e12c5d1SDavid du Colombier 3243e12c5d1SDavid du Colombier static long 3259a747e4fSDavid du Colombier ireaddir(Xfile *f, uchar *buf, long offset, long count) 3263e12c5d1SDavid du Colombier { 3273e12c5d1SDavid du Colombier Isofile *ip = f->ptr; 3283e12c5d1SDavid du Colombier Dir d; 3299a747e4fSDavid du Colombier char names[4*Maxname]; 3303e12c5d1SDavid du Colombier uchar dbuf[256]; 3313e12c5d1SDavid du Colombier Drec *drec = (Drec *)dbuf; 3329a747e4fSDavid du Colombier int n, rcnt; 3333e12c5d1SDavid du Colombier 3349a747e4fSDavid du Colombier if(offset==0){ 3353e12c5d1SDavid du Colombier ip->offset = 0; 3363e12c5d1SDavid du Colombier ip->doffset = 0; 3379a747e4fSDavid du Colombier }else if(offset != ip->doffset) 3389a747e4fSDavid du Colombier error("seek in directory not allowed"); 3399a747e4fSDavid du Colombier 3409a747e4fSDavid du Colombier rcnt = 0; 3419a747e4fSDavid du Colombier setnames(&d, names); 3423e12c5d1SDavid du Colombier while(rcnt < count && getdrec(f, drec) >= 0){ 3433e12c5d1SDavid du Colombier if(drec->namelen == 1){ 3443e12c5d1SDavid du Colombier if(drec->name[0] == 0) 3453e12c5d1SDavid du Colombier continue; 3463e12c5d1SDavid du Colombier if(drec->name[0] == 1) 3473e12c5d1SDavid du Colombier continue; 3483e12c5d1SDavid du Colombier } 34959cc4ca5SDavid du Colombier rzdir(f->xf, &d, ip->fmt, drec); 3503e12c5d1SDavid du Colombier d.qid.vers = f->qid.vers; 3519a747e4fSDavid du Colombier if((n = convD2M(&d, buf+rcnt, count-rcnt)) <= BIT16SZ){ 3529a747e4fSDavid du Colombier ungetdrec(f); 3539a747e4fSDavid du Colombier break; 3549a747e4fSDavid du Colombier } 3559a747e4fSDavid du Colombier rcnt += n; 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier ip->doffset += rcnt; 3583e12c5d1SDavid du Colombier return rcnt; 3593e12c5d1SDavid du Colombier } 3603e12c5d1SDavid du Colombier 3613e12c5d1SDavid du Colombier static long 3623e12c5d1SDavid du Colombier iread(Xfile *f, char *buf, long offset, long count) 3633e12c5d1SDavid du Colombier { 3643e12c5d1SDavid du Colombier Isofile *ip = f->ptr; 3653e12c5d1SDavid du Colombier long size, addr, o, n; 3663e12c5d1SDavid du Colombier int rcnt = 0; 3673e12c5d1SDavid du Colombier Iobuf *p; 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier size = l32(ip->d.size); 3703e12c5d1SDavid du Colombier if(offset >= size) 3713e12c5d1SDavid du Colombier return 0; 3723e12c5d1SDavid du Colombier if(offset+count > size) 3733e12c5d1SDavid du Colombier count = size - offset; 3743e12c5d1SDavid du Colombier addr = (l32(ip->d.addr)+ip->d.attrlen)*ip->blksize + offset; 3757dd7cddfSDavid du Colombier o = (ulong)addr % Sectorsize; 3767dd7cddfSDavid du Colombier addr = (ulong)addr / Sectorsize; 3773e12c5d1SDavid du Colombier /*chat("d.addr=0x%x, addr=0x%x, o=0x%x...", l32(ip->d.addr), addr, o);*/ 3783e12c5d1SDavid du Colombier n = Sectorsize - o; 3793e12c5d1SDavid du Colombier 3803e12c5d1SDavid du Colombier while(count > 0){ 3813e12c5d1SDavid du Colombier if(n > count) 3823e12c5d1SDavid du Colombier n = count; 3833e12c5d1SDavid du Colombier p = getbuf(f->xf->d, addr); 3843e12c5d1SDavid du Colombier memmove(&buf[rcnt], &p->iobuf[o], n); 3853e12c5d1SDavid du Colombier putbuf(p); 3863e12c5d1SDavid du Colombier count -= n; 3873e12c5d1SDavid du Colombier rcnt += n; 3883e12c5d1SDavid du Colombier ++addr; 3893e12c5d1SDavid du Colombier o = 0; 3903e12c5d1SDavid du Colombier n = Sectorsize; 3913e12c5d1SDavid du Colombier } 3923e12c5d1SDavid du Colombier return rcnt; 3933e12c5d1SDavid du Colombier } 3943e12c5d1SDavid du Colombier 3953e12c5d1SDavid du Colombier static long 3967dd7cddfSDavid du Colombier iwrite(Xfile *f, char *buf, long offset, long count) 3973e12c5d1SDavid du Colombier { 3983e12c5d1SDavid du Colombier USED(f, buf, offset, count); 3993e12c5d1SDavid du Colombier error(Eperm); 4003e12c5d1SDavid du Colombier return 0; 4013e12c5d1SDavid du Colombier } 4023e12c5d1SDavid du Colombier 4033e12c5d1SDavid du Colombier static void 4043e12c5d1SDavid du Colombier iclunk(Xfile *f) 4053e12c5d1SDavid du Colombier { 4063e12c5d1SDavid du Colombier USED(f); 4073e12c5d1SDavid du Colombier } 4083e12c5d1SDavid du Colombier 4093e12c5d1SDavid du Colombier static void 4103e12c5d1SDavid du Colombier iremove(Xfile *f) 4113e12c5d1SDavid du Colombier { 4123e12c5d1SDavid du Colombier USED(f); 4133e12c5d1SDavid du Colombier error(Eperm); 4143e12c5d1SDavid du Colombier } 4153e12c5d1SDavid du Colombier 4163e12c5d1SDavid du Colombier static void 4173e12c5d1SDavid du Colombier istat(Xfile *f, Dir *d) 4183e12c5d1SDavid du Colombier { 4193e12c5d1SDavid du Colombier Isofile *ip = f->ptr; 4203e12c5d1SDavid du Colombier 42159cc4ca5SDavid du Colombier rzdir(f->xf, d, ip->fmt, &ip->d); 4223e12c5d1SDavid du Colombier d->qid.vers = f->qid.vers; 4239a747e4fSDavid du Colombier if(d->qid.path==f->xf->rootqid.path){ 4249a747e4fSDavid du Colombier d->qid.path = 0; 4259a747e4fSDavid du Colombier d->qid.type = QTDIR; 4269a747e4fSDavid du Colombier } 4273e12c5d1SDavid du Colombier } 4283e12c5d1SDavid du Colombier 4293e12c5d1SDavid du Colombier static void 4303e12c5d1SDavid du Colombier iwstat(Xfile *f, Dir *d) 4313e12c5d1SDavid du Colombier { 4323e12c5d1SDavid du Colombier USED(f, d); 4333e12c5d1SDavid du Colombier error(Eperm); 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier 4363e12c5d1SDavid du Colombier static int 4373e12c5d1SDavid du Colombier showdrec(int fd, int fmt, void *x) 4383e12c5d1SDavid du Colombier { 4393e12c5d1SDavid du Colombier Drec *d = (Drec *)x; 4407dd7cddfSDavid du Colombier int namelen; 4417dd7cddfSDavid du Colombier int syslen; 4423e12c5d1SDavid du Colombier 4433e12c5d1SDavid du Colombier if(d->reclen == 0) 4443e12c5d1SDavid du Colombier return 0; 4457dd7cddfSDavid du Colombier fprint(fd, "%d %d %ld %ld ", 4463e12c5d1SDavid du Colombier d->reclen, d->attrlen, l32(d->addr), l32(d->size)); 4477dd7cddfSDavid du Colombier fprint(fd, "%s 0x%2.2x %d %d %ld ", 4483e12c5d1SDavid du Colombier rdate(d->date, fmt), (fmt=='z' ? d->flags : d->r_flags), 4493e12c5d1SDavid du Colombier d->unitsize, d->gapsize, l16(d->vseqno)); 4503e12c5d1SDavid du Colombier fprint(fd, "%d %s", d->namelen, nstr(d->name, d->namelen)); 4517dd7cddfSDavid du Colombier if(fmt != 'J'){ 4523e12c5d1SDavid du Colombier namelen = d->namelen + (1-(d->namelen&1)); 4533e12c5d1SDavid du Colombier syslen = d->reclen - 33 - namelen; 4543e12c5d1SDavid du Colombier if(syslen != 0) 4553e12c5d1SDavid du Colombier fprint(fd, " %s", nstr(&d->name[namelen], syslen)); 4567dd7cddfSDavid du Colombier } 4573e12c5d1SDavid du Colombier fprint(fd, "\n"); 4583e12c5d1SDavid du Colombier return d->reclen + (d->reclen&1); 4593e12c5d1SDavid du Colombier } 4603e12c5d1SDavid du Colombier 4613e12c5d1SDavid du Colombier static void 4623e12c5d1SDavid du Colombier newdrec(Xfile *f, Drec *dp) 4633e12c5d1SDavid du Colombier { 4643e12c5d1SDavid du Colombier Isofile *x = f->ptr; 4653e12c5d1SDavid du Colombier Isofile *n; 4663e12c5d1SDavid du Colombier int len; 4673e12c5d1SDavid du Colombier 4683e12c5d1SDavid du Colombier len = sizeof(Isofile) - sizeof(Drec) + dp->reclen; 4693e12c5d1SDavid du Colombier n = ealloc(len); 4703e12c5d1SDavid du Colombier n->fmt = x->fmt; 4713e12c5d1SDavid du Colombier n->blksize = x->blksize; 4723e12c5d1SDavid du Colombier n->offset = 0; 4733e12c5d1SDavid du Colombier n->doffset = 0; 4743e12c5d1SDavid du Colombier memmove(&n->d, dp, dp->reclen); 4753e12c5d1SDavid du Colombier free(x); 4763e12c5d1SDavid du Colombier f->ptr = n; 4773e12c5d1SDavid du Colombier f->len = len; 4783e12c5d1SDavid du Colombier } 4793e12c5d1SDavid du Colombier 4809a747e4fSDavid du Colombier static void 4819a747e4fSDavid du Colombier ungetdrec(Xfile *f) 4829a747e4fSDavid du Colombier { 4839a747e4fSDavid du Colombier Isofile *ip = f->ptr; 4849a747e4fSDavid du Colombier 4859a747e4fSDavid du Colombier if(ip->offset >= ip->odelta){ 4869a747e4fSDavid du Colombier ip->offset -= ip->odelta; 4879a747e4fSDavid du Colombier ip->odelta = 0; 4889a747e4fSDavid du Colombier } 4899a747e4fSDavid du Colombier } 4909a747e4fSDavid du Colombier 4913e12c5d1SDavid du Colombier static int 4923e12c5d1SDavid du Colombier getdrec(Xfile *f, void *buf) 4933e12c5d1SDavid du Colombier { 4943e12c5d1SDavid du Colombier Isofile *ip = f->ptr; 4953e12c5d1SDavid du Colombier int len = 0, boff = 0; 4963e12c5d1SDavid du Colombier long size, addr; 4973e12c5d1SDavid du Colombier Iobuf *p = 0; 4983e12c5d1SDavid du Colombier 4993e12c5d1SDavid du Colombier if(!ip) 5003e12c5d1SDavid du Colombier return -1; 5013e12c5d1SDavid du Colombier size = l32(ip->d.size); 5023e12c5d1SDavid du Colombier while(ip->offset<size){ 5033e12c5d1SDavid du Colombier addr = (l32(ip->d.addr)+ip->d.attrlen)*ip->blksize + ip->offset; 5047dd7cddfSDavid du Colombier boff = (ulong)addr % Sectorsize; 5053e12c5d1SDavid du Colombier if(boff > Sectorsize-34){ 5063e12c5d1SDavid du Colombier ip->offset += Sectorsize-boff; 5073e12c5d1SDavid du Colombier continue; 5083e12c5d1SDavid du Colombier } 5097dd7cddfSDavid du Colombier p = getbuf(f->xf->d, (ulong)addr/Sectorsize); 5103e12c5d1SDavid du Colombier len = p->iobuf[boff]; 5113e12c5d1SDavid du Colombier if(len >= 34) 5123e12c5d1SDavid du Colombier break; 5133e12c5d1SDavid du Colombier putbuf(p); 5143e12c5d1SDavid du Colombier p = 0; 5153e12c5d1SDavid du Colombier ip->offset += Sectorsize-boff; 5163e12c5d1SDavid du Colombier } 5173e12c5d1SDavid du Colombier if(p) { 5183e12c5d1SDavid du Colombier memmove(buf, &p->iobuf[boff], len); 5193e12c5d1SDavid du Colombier putbuf(p); 5209a747e4fSDavid du Colombier ip->odelta = len + (len&1); 5219a747e4fSDavid du Colombier ip->offset += ip->odelta; 5223e12c5d1SDavid du Colombier } 523bd389b36SDavid du Colombier if(p) 524bd389b36SDavid du Colombier return 0; 525bd389b36SDavid du Colombier return -1; 5263e12c5d1SDavid du Colombier } 5273e12c5d1SDavid du Colombier 5283e12c5d1SDavid du Colombier static int 5293e12c5d1SDavid du Colombier opendotdot(Xfile *f, Xfile *pf) 5303e12c5d1SDavid du Colombier { 5313e12c5d1SDavid du Colombier uchar dbuf[256]; 5323e12c5d1SDavid du Colombier Drec *d = (Drec *)dbuf; 5333e12c5d1SDavid du Colombier Isofile *ip = f->ptr, *pip = pf->ptr; 5343e12c5d1SDavid du Colombier 5353e12c5d1SDavid du Colombier ip->offset = 0; 5363e12c5d1SDavid du Colombier if(getdrec(f, d) < 0){ 5373e12c5d1SDavid du Colombier chat("opendotdot: getdrec(.) failed..."); 5383e12c5d1SDavid du Colombier return -1; 5393e12c5d1SDavid du Colombier } 5403e12c5d1SDavid du Colombier if(d->namelen != 1 || d->name[0] != 0){ 5413e12c5d1SDavid du Colombier chat("opendotdot: no . entry..."); 5423e12c5d1SDavid du Colombier return -1; 5433e12c5d1SDavid du Colombier } 5443e12c5d1SDavid du Colombier if(l32(d->addr) != l32(ip->d.addr)){ 5453e12c5d1SDavid du Colombier chat("opendotdot: bad . address..."); 5463e12c5d1SDavid du Colombier return -1; 5473e12c5d1SDavid du Colombier } 5483e12c5d1SDavid du Colombier if(getdrec(f, d) < 0){ 5493e12c5d1SDavid du Colombier chat("opendotdot: getdrec(..) failed..."); 5503e12c5d1SDavid du Colombier return -1; 5513e12c5d1SDavid du Colombier } 5523e12c5d1SDavid du Colombier if(d->namelen != 1 || d->name[0] != 1){ 5533e12c5d1SDavid du Colombier chat("opendotdot: no .. entry..."); 5543e12c5d1SDavid du Colombier return -1; 5553e12c5d1SDavid du Colombier } 5563e12c5d1SDavid du Colombier 5573e12c5d1SDavid du Colombier pf->xf = f->xf; 5583e12c5d1SDavid du Colombier pip->fmt = ip->fmt; 5593e12c5d1SDavid du Colombier pip->blksize = ip->blksize; 5603e12c5d1SDavid du Colombier pip->offset = 0; 5613e12c5d1SDavid du Colombier pip->doffset = 0; 5623e12c5d1SDavid du Colombier pip->d = *d; 5633e12c5d1SDavid du Colombier return 0; 5643e12c5d1SDavid du Colombier } 5653e12c5d1SDavid du Colombier 56659cc4ca5SDavid du Colombier enum { 56759cc4ca5SDavid du Colombier Hname = 1, 56859cc4ca5SDavid du Colombier Hmode = 2, 56959cc4ca5SDavid du Colombier }; 57059cc4ca5SDavid du Colombier 571bd389b36SDavid du Colombier static int 57259cc4ca5SDavid du Colombier rzdir(Xfs *fs, Dir *d, int fmt, Drec *dp) 5733e12c5d1SDavid du Colombier { 57459cc4ca5SDavid du Colombier int n, flags, i, j, lj, nl, vers, sysl, mode, l, have; 5753e12c5d1SDavid du Colombier uchar *s; 576bd389b36SDavid du Colombier char *p; 5779a747e4fSDavid du Colombier char buf[Maxname+UTFmax+1]; 5787dd7cddfSDavid du Colombier uchar *q; 5797dd7cddfSDavid du Colombier Rune r; 5809a747e4fSDavid du Colombier enum { ONAMELEN = 28 }; /* old Plan 9 directory name length */ 5813e12c5d1SDavid du Colombier 58259cc4ca5SDavid du Colombier have = 0; 583bd389b36SDavid du Colombier flags = 0; 584bd389b36SDavid du Colombier vers = -1; 5853e12c5d1SDavid du Colombier d->qid.path = l32(dp->addr); 5869a747e4fSDavid du Colombier d->qid.type = 0; 5873e12c5d1SDavid du Colombier d->qid.vers = 0; 588bd389b36SDavid du Colombier n = dp->namelen; 5899a747e4fSDavid du Colombier memset(d->name, 0, Maxname); 5903e12c5d1SDavid du Colombier if(n == 1) { 5913e12c5d1SDavid du Colombier switch(dp->name[0]){ 5923e12c5d1SDavid du Colombier case 1: 5933e12c5d1SDavid du Colombier d->name[1] = '.'; 5943e12c5d1SDavid du Colombier /* fall through */ 5953e12c5d1SDavid du Colombier case 0: 5963e12c5d1SDavid du Colombier d->name[0] = '.'; 59759cc4ca5SDavid du Colombier have = Hname; 5983e12c5d1SDavid du Colombier break; 5993e12c5d1SDavid du Colombier default: 6003e12c5d1SDavid du Colombier d->name[0] = tolower(dp->name[0]); 6013e12c5d1SDavid du Colombier } 6023e12c5d1SDavid du Colombier } else { 6037dd7cddfSDavid du Colombier if(fmt == 'J'){ /* Joliet, 16-bit Unicode */ 6047dd7cddfSDavid du Colombier q = (uchar*)dp->name; 6059a747e4fSDavid du Colombier for(i=j=lj=0; i<n && j<Maxname; i+=2){ 6067dd7cddfSDavid du Colombier lj = j; 6077dd7cddfSDavid du Colombier r = (q[i]<<8)|q[i+1]; 6087dd7cddfSDavid du Colombier j += runetochar(buf+j, &r); 6097dd7cddfSDavid du Colombier } 6109a747e4fSDavid du Colombier if(j >= Maxname) 6117dd7cddfSDavid du Colombier j = lj; 6127dd7cddfSDavid du Colombier memmove(d->name, buf, j); 6137dd7cddfSDavid du Colombier }else{ 6149a747e4fSDavid du Colombier if(n >= Maxname) 6159a747e4fSDavid du Colombier n = Maxname-1; 6163e12c5d1SDavid du Colombier for(i=0; i<n; i++) 6173e12c5d1SDavid du Colombier d->name[i] = tolower(dp->name[i]); 6183e12c5d1SDavid du Colombier } 6197dd7cddfSDavid du Colombier } 6203e12c5d1SDavid du Colombier 62159cc4ca5SDavid du Colombier sysl = dp->reclen-(34+dp->namelen); 62259cc4ca5SDavid du Colombier s = (uchar*)dp->name + dp->namelen; 62359cc4ca5SDavid du Colombier if(((ulong)s) & 1) { 62459cc4ca5SDavid du Colombier s++; 62559cc4ca5SDavid du Colombier sysl--; 62659cc4ca5SDavid du Colombier } 62759cc4ca5SDavid du Colombier if(fs->isplan9 && sysl > 0) { 628bd389b36SDavid du Colombier /* 629bd389b36SDavid du Colombier * get gid, uid, mode and possibly name 630bd389b36SDavid du Colombier * from plan9 directory extension 631bd389b36SDavid du Colombier */ 6323e12c5d1SDavid du Colombier nl = *s; 6339a747e4fSDavid du Colombier if(nl >= ONAMELEN) 6349a747e4fSDavid du Colombier nl = ONAMELEN-1; 6353e12c5d1SDavid du Colombier if(nl) { 6369a747e4fSDavid du Colombier memset(d->name, 0, ONAMELEN); 6373e12c5d1SDavid du Colombier memmove(d->name, s+1, nl); 6383e12c5d1SDavid du Colombier } 6393e12c5d1SDavid du Colombier s += 1 + *s; 6403e12c5d1SDavid du Colombier nl = *s; 6419a747e4fSDavid du Colombier if(nl >= ONAMELEN) 6429a747e4fSDavid du Colombier nl = ONAMELEN-1; 6439a747e4fSDavid du Colombier memset(d->uid, 0, ONAMELEN); 6443e12c5d1SDavid du Colombier memmove(d->uid, s+1, nl); 6453e12c5d1SDavid du Colombier s += 1 + *s; 6463e12c5d1SDavid du Colombier nl = *s; 6479a747e4fSDavid du Colombier if(nl >= ONAMELEN) 6489a747e4fSDavid du Colombier nl = ONAMELEN-1; 6499a747e4fSDavid du Colombier memset(d->gid, 0, ONAMELEN); 6503e12c5d1SDavid du Colombier memmove(d->gid, s+1, nl); 6513e12c5d1SDavid du Colombier s += 1 + *s; 6523e12c5d1SDavid du Colombier if(((ulong)s) & 1) 6533e12c5d1SDavid du Colombier s++; 6543e12c5d1SDavid du Colombier d->mode = l32(s); 6559a747e4fSDavid du Colombier if(d->mode & DMDIR) 6569a747e4fSDavid du Colombier d->qid.type |= QTDIR; 6573e12c5d1SDavid du Colombier } else { 6583e12c5d1SDavid du Colombier d->mode = 0444; 6593e12c5d1SDavid du Colombier switch(fmt) { 6603e12c5d1SDavid du Colombier case 'z': 66159cc4ca5SDavid du Colombier if(fs->isrock) 66259cc4ca5SDavid du Colombier strcpy(d->gid, "ridge"); 66359cc4ca5SDavid du Colombier else 6647dd7cddfSDavid du Colombier strcpy(d->gid, "iso9660"); 6653e12c5d1SDavid du Colombier flags = dp->flags; 6663e12c5d1SDavid du Colombier break; 6673e12c5d1SDavid du Colombier case 'r': 6683e12c5d1SDavid du Colombier strcpy(d->gid, "sierra"); 6693e12c5d1SDavid du Colombier flags = dp->r_flags; 6703e12c5d1SDavid du Colombier break; 6717dd7cddfSDavid du Colombier case 'J': 6727dd7cddfSDavid du Colombier strcpy(d->gid, "joliet"); 6737dd7cddfSDavid du Colombier flags = dp->flags; 6747dd7cddfSDavid du Colombier break; 6757dd7cddfSDavid du Colombier case '9': 6767dd7cddfSDavid du Colombier strcpy(d->gid, "plan9"); 6777dd7cddfSDavid du Colombier flags = dp->flags; 6787dd7cddfSDavid du Colombier break; 6793e12c5d1SDavid du Colombier } 6803e12c5d1SDavid du Colombier if(flags & 0x02){ 6819a747e4fSDavid du Colombier d->qid.type |= QTDIR; 6829a747e4fSDavid du Colombier d->mode |= DMDIR|0111; 6833e12c5d1SDavid du Colombier } 6843e12c5d1SDavid du Colombier strcpy(d->uid, "cdrom"); 6859a747e4fSDavid du Colombier if(fmt!='9' && !(d->mode&DMDIR)){ 6869a747e4fSDavid du Colombier /* 6879a747e4fSDavid du Colombier * ISO 9660 actually requires that you always have a . and a ;, 6889a747e4fSDavid du Colombier * even if there is no version and no extension. Very few writers 6899a747e4fSDavid du Colombier * do this. If the version is present, we use it for qid.vers. 6909a747e4fSDavid du Colombier * If there is no extension but there is a dot, we strip it off. 6919a747e4fSDavid du Colombier * (VMS heads couldn't comprehend the dot as a file name character 6929a747e4fSDavid du Colombier * rather than as just a separator between name and extension.) 6939a747e4fSDavid du Colombier * 6949a747e4fSDavid du Colombier * We don't do this for directory names because directories are 6959a747e4fSDavid du Colombier * not allowed to have extensions and versions. 6969a747e4fSDavid du Colombier */ 6979a747e4fSDavid du Colombier if((p=strchr(d->name, ';')) != nil){ 6989a747e4fSDavid du Colombier vers = strtoul(p+1, 0, 0); 6999a747e4fSDavid du Colombier d->qid.vers = vers; 7009a747e4fSDavid du Colombier *p = '\0'; 7019a747e4fSDavid du Colombier } 7029a747e4fSDavid du Colombier if((p=strchr(d->name, '.')) != nil && *(p+1)=='\0') 7039a747e4fSDavid du Colombier *p = '\0'; 704bd389b36SDavid du Colombier } 70559cc4ca5SDavid du Colombier if(fs->issusp){ 70659cc4ca5SDavid du Colombier nl = 0; 70759cc4ca5SDavid du Colombier s += fs->suspoff; 70859cc4ca5SDavid du Colombier sysl -= fs->suspoff; 70959cc4ca5SDavid du Colombier for(; sysl >= 4 && have != (Hname|Hmode); sysl -= l, s += l){ 710*1f3c807eSDavid du Colombier if(s[0] == 0 && ((ulong)s & 1)){ 711*1f3c807eSDavid du Colombier /* MacOS pads individual entries, contrary to spec */ 712*1f3c807eSDavid du Colombier s++; 713*1f3c807eSDavid du Colombier sysl--; 714*1f3c807eSDavid du Colombier } 71559cc4ca5SDavid du Colombier l = s[2]; 71659cc4ca5SDavid du Colombier if(s[0] == 'P' && s[1] == 'X' && s[3] == 1){ 71759cc4ca5SDavid du Colombier /* posix file attributes */ 71859cc4ca5SDavid du Colombier mode = l32(s+4); 71959cc4ca5SDavid du Colombier d->mode = mode & 0777; 72059cc4ca5SDavid du Colombier if((mode & 0170000) == 040000){ 7219a747e4fSDavid du Colombier d->mode |= DMDIR; 7229a747e4fSDavid du Colombier d->qid.type |= QTDIR; 72359cc4ca5SDavid du Colombier } 72459cc4ca5SDavid du Colombier have |= Hmode; 72559cc4ca5SDavid du Colombier } else if(s[0] == 'N' && s[1] == 'M' && s[3] == 1){ 72659cc4ca5SDavid du Colombier /* alternative name */ 72759cc4ca5SDavid du Colombier if((s[4] & ~1) == 0){ 72859cc4ca5SDavid du Colombier i = nl+l-5; 7299a747e4fSDavid du Colombier if(i >= Maxname) 7309a747e4fSDavid du Colombier i = Maxname-1; 73159cc4ca5SDavid du Colombier if((i -= nl) > 0){ 73259cc4ca5SDavid du Colombier memmove(d->name+nl, s+5, i); 73359cc4ca5SDavid du Colombier nl += i; 73459cc4ca5SDavid du Colombier } 73559cc4ca5SDavid du Colombier if(s[4] == 0) 73659cc4ca5SDavid du Colombier have |= Hname; 73759cc4ca5SDavid du Colombier } 73859cc4ca5SDavid du Colombier } else if(s[0] == 'C' && s[1] == 'E' && s[2] >= 28){ 73959cc4ca5SDavid du Colombier sysl = getcontin(fs->d, s, &s); 74059cc4ca5SDavid du Colombier continue; 74159cc4ca5SDavid du Colombier } else if(s[0] == 'S' && s[1] == 'T') 74259cc4ca5SDavid du Colombier break; 74359cc4ca5SDavid du Colombier } 74459cc4ca5SDavid du Colombier } 7453e12c5d1SDavid du Colombier } 7463e12c5d1SDavid du Colombier d->length = 0; 7479a747e4fSDavid du Colombier if((d->mode & DMDIR) == 0) 7483e12c5d1SDavid du Colombier d->length = l32(dp->size); 7493e12c5d1SDavid du Colombier d->type = 0; 7503e12c5d1SDavid du Colombier d->dev = 0; 7513e12c5d1SDavid du Colombier d->atime = gtime(dp->date); 7523e12c5d1SDavid du Colombier d->mtime = d->atime; 753bd389b36SDavid du Colombier return vers; 7543e12c5d1SDavid du Colombier } 7553e12c5d1SDavid du Colombier 75659cc4ca5SDavid du Colombier static int 75759cc4ca5SDavid du Colombier getcontin(Xdata *dev, uchar *p, uchar **s) 75859cc4ca5SDavid du Colombier { 75959cc4ca5SDavid du Colombier long bn, off, len; 76059cc4ca5SDavid du Colombier Iobuf *b; 76159cc4ca5SDavid du Colombier 76259cc4ca5SDavid du Colombier bn = l32(p+4); 76359cc4ca5SDavid du Colombier off = l32(p+12); 76459cc4ca5SDavid du Colombier len = l32(p+20); 76559cc4ca5SDavid du Colombier chat("getcontin %d...", bn); 76659cc4ca5SDavid du Colombier b = getbuf(dev, bn); 76759cc4ca5SDavid du Colombier if(b == 0){ 76859cc4ca5SDavid du Colombier *s = 0; 76959cc4ca5SDavid du Colombier return 0; 77059cc4ca5SDavid du Colombier } 77159cc4ca5SDavid du Colombier *s = b->iobuf+off; 77259cc4ca5SDavid du Colombier putbuf(b); 77359cc4ca5SDavid du Colombier return len; 77459cc4ca5SDavid du Colombier } 77559cc4ca5SDavid du Colombier 7763e12c5d1SDavid du Colombier static char * 7773e12c5d1SDavid du Colombier nstr(uchar *p, int n) 7783e12c5d1SDavid du Colombier { 7793e12c5d1SDavid du Colombier static char buf[132]; 7803e12c5d1SDavid du Colombier char *q = buf; 781bd389b36SDavid du Colombier 7823e12c5d1SDavid du Colombier while(--n >= 0){ 7833e12c5d1SDavid du Colombier if(*p == '\\') 7843e12c5d1SDavid du Colombier *q++ = '\\'; 7853e12c5d1SDavid du Colombier if(' ' <= *p && *p <= '~') 7863e12c5d1SDavid du Colombier *q++ = *p++; 7873e12c5d1SDavid du Colombier else 7883e12c5d1SDavid du Colombier q += sprint(q, "\\%2.2ux", *p++); 7893e12c5d1SDavid du Colombier } 7903e12c5d1SDavid du Colombier *q = 0; 7913e12c5d1SDavid du Colombier return buf; 7923e12c5d1SDavid du Colombier } 7933e12c5d1SDavid du Colombier 7943e12c5d1SDavid du Colombier static char * 7953e12c5d1SDavid du Colombier rdate(uchar *p, int fmt) 7963e12c5d1SDavid du Colombier { 7973e12c5d1SDavid du Colombier static char buf[64]; 7983e12c5d1SDavid du Colombier int htz, s, n; 7993e12c5d1SDavid du Colombier 8003e12c5d1SDavid du Colombier n = sprint(buf, "%2.2d.%2.2d.%2.2d %2.2d:%2.2d:%2.2d", 8013e12c5d1SDavid du Colombier p[0], p[1], p[2], p[3], p[4], p[5]); 8023e12c5d1SDavid du Colombier if(fmt == 'z'){ 8033e12c5d1SDavid du Colombier htz = p[6]; 8043e12c5d1SDavid du Colombier if(htz >= 128){ 8053e12c5d1SDavid du Colombier htz = 256-htz; 8063e12c5d1SDavid du Colombier s = '-'; 8073e12c5d1SDavid du Colombier }else 8083e12c5d1SDavid du Colombier s = '+'; 8093e12c5d1SDavid du Colombier sprint(&buf[n], " (%c%.1f)", s, (float)htz/2); 8103e12c5d1SDavid du Colombier } 8113e12c5d1SDavid du Colombier return buf; 8123e12c5d1SDavid du Colombier } 8133e12c5d1SDavid du Colombier 814bd389b36SDavid du Colombier static char 815bd389b36SDavid du Colombier dmsize[12] = 816bd389b36SDavid du Colombier { 8173e12c5d1SDavid du Colombier 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 8183e12c5d1SDavid du Colombier }; 819bd389b36SDavid du Colombier 8203e12c5d1SDavid du Colombier static int 8213e12c5d1SDavid du Colombier dysize(int y) 8223e12c5d1SDavid du Colombier { 8233e12c5d1SDavid du Colombier 8243e12c5d1SDavid du Colombier if((y%4) == 0) 8253e12c5d1SDavid du Colombier return 366; 8263e12c5d1SDavid du Colombier return 365; 8273e12c5d1SDavid du Colombier } 828bd389b36SDavid du Colombier 8293e12c5d1SDavid du Colombier static long 8303e12c5d1SDavid du Colombier gtime(uchar *p) /* yMdhmsz */ 8313e12c5d1SDavid du Colombier { 8323e12c5d1SDavid du Colombier long t; 8333e12c5d1SDavid du Colombier int i, y, M, d, h, m, s, tz; 8343e12c5d1SDavid du Colombier y=p[0]; M=p[1]; d=p[2]; 8353e12c5d1SDavid du Colombier h=p[3]; m=p[4]; s=p[5]; tz=p[6]; 8363e12c5d1SDavid du Colombier USED(tz); 8373e12c5d1SDavid du Colombier if (y < 70) 8383e12c5d1SDavid du Colombier return 0; 8393e12c5d1SDavid du Colombier if (M < 1 || M > 12) 8403e12c5d1SDavid du Colombier return 0; 8413e12c5d1SDavid du Colombier if (d < 1 || d > dmsize[M-1]) 8423e12c5d1SDavid du Colombier return 0; 8433e12c5d1SDavid du Colombier if (h > 23) 8443e12c5d1SDavid du Colombier return 0; 8453e12c5d1SDavid du Colombier if (m > 59) 8463e12c5d1SDavid du Colombier return 0; 8473e12c5d1SDavid du Colombier if (s > 59) 8483e12c5d1SDavid du Colombier return 0; 8493e12c5d1SDavid du Colombier y += 1900; 8503e12c5d1SDavid du Colombier t = 0; 8513e12c5d1SDavid du Colombier for(i=1970; i<y; i++) 8523e12c5d1SDavid du Colombier t += dysize(i); 8533e12c5d1SDavid du Colombier if (dysize(y)==366 && M >= 3) 8543e12c5d1SDavid du Colombier t++; 8553e12c5d1SDavid du Colombier while(--M) 8563e12c5d1SDavid du Colombier t += dmsize[M-1]; 8573e12c5d1SDavid du Colombier t += d-1; 8583e12c5d1SDavid du Colombier t = 24*t + h; 8593e12c5d1SDavid du Colombier t = 60*t + m; 8603e12c5d1SDavid du Colombier t = 60*t + s; 8613e12c5d1SDavid du Colombier return t; 8623e12c5d1SDavid du Colombier } 8633e12c5d1SDavid du Colombier 8643e12c5d1SDavid du Colombier #define p ((uchar*)arg) 8653e12c5d1SDavid du Colombier 8663e12c5d1SDavid du Colombier static long 8673e12c5d1SDavid du Colombier l16(void *arg) 8683e12c5d1SDavid du Colombier { 8693e12c5d1SDavid du Colombier long v; 8703e12c5d1SDavid du Colombier 8713e12c5d1SDavid du Colombier v = ((long)p[1]<<8)|p[0]; 8723e12c5d1SDavid du Colombier if (v >= 0x8000L) 8733e12c5d1SDavid du Colombier v -= 0x10000L; 8743e12c5d1SDavid du Colombier return v; 8753e12c5d1SDavid du Colombier } 8763e12c5d1SDavid du Colombier 8773e12c5d1SDavid du Colombier static long 8783e12c5d1SDavid du Colombier l32(void *arg) 8793e12c5d1SDavid du Colombier { 8803e12c5d1SDavid du Colombier return ((((((long)p[3]<<8)|p[2])<<8)|p[1])<<8)|p[0]; 8813e12c5d1SDavid du Colombier } 8823e12c5d1SDavid du Colombier 8833e12c5d1SDavid du Colombier #undef p 884