13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include <auth.h>
53e12c5d1SDavid du Colombier #include <fcall.h>
63e12c5d1SDavid du Colombier #include "iotrack.h"
73e12c5d1SDavid du Colombier #include "dat.h"
83e12c5d1SDavid du Colombier #include "fns.h"
93e12c5d1SDavid du Colombier
107dd7cddfSDavid du Colombier static uchar isdos[256];
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier int
isdosfs(uchar * buf)137dd7cddfSDavid du Colombier isdosfs(uchar *buf)
147dd7cddfSDavid du Colombier {
157dd7cddfSDavid du Colombier /*
167dd7cddfSDavid du Colombier * When dynamic disc managers move the disc partition,
177dd7cddfSDavid du Colombier * they make it start with 0xE9.
187dd7cddfSDavid du Colombier */
197dd7cddfSDavid du Colombier if(buf[0] == 0xE9)
207dd7cddfSDavid du Colombier return 1;
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier /*
237dd7cddfSDavid du Colombier * Check if the jump displacement (magic[1]) is too short for a FAT.
24*efb32250SDavid du Colombier *
25*efb32250SDavid du Colombier * check now omitted due to digital cameras that use a 0 jump.
26*efb32250SDavid du Colombier * the ecma-107 standard says this is okay and that interoperable fat
27*efb32250SDavid du Colombier * implementations shouldn't assume this:
28*efb32250SDavid du Colombier * http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-107.pdf,
29*efb32250SDavid du Colombier * page 11.
307dd7cddfSDavid du Colombier */
31*efb32250SDavid du Colombier if(buf[0] == 0xEB && buf[2] == 0x90 /* && buf[1] >= 0x30 */)
327dd7cddfSDavid du Colombier return 1;
33*efb32250SDavid du Colombier if(chatty)
34*efb32250SDavid du Colombier fprint(2, "bad sig %.2ux %.2ux %.2uxn", buf[0], buf[1], buf[2]);
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier return 0;
377dd7cddfSDavid du Colombier }
387dd7cddfSDavid du Colombier
393e12c5d1SDavid du Colombier int
dosfs(Xfs * xf)403e12c5d1SDavid du Colombier dosfs(Xfs *xf)
413e12c5d1SDavid du Colombier {
427dd7cddfSDavid du Colombier Iosect *p, *p1;
437dd7cddfSDavid du Colombier Dosboot *b;
447dd7cddfSDavid du Colombier Fatinfo *fi;
457dd7cddfSDavid du Colombier Dosboot32 *b32;
463e12c5d1SDavid du Colombier Dosbpb *bp;
477dd7cddfSDavid du Colombier long fisec, extflags;
489a747e4fSDavid du Colombier int i;
493e12c5d1SDavid du Colombier
507dd7cddfSDavid du Colombier if(!isdos['a']){
517dd7cddfSDavid du Colombier for(i = 'a'; i <= 'z'; i++)
527dd7cddfSDavid du Colombier isdos[i] = 1;
537dd7cddfSDavid du Colombier for(i = 'A'; i <= 'Z'; i++)
547dd7cddfSDavid du Colombier isdos[i] = 1;
557dd7cddfSDavid du Colombier for(i = '0'; i <= '9'; i++)
567dd7cddfSDavid du Colombier isdos[i] = 1;
577dd7cddfSDavid du Colombier isdos['$'] = 1;
587dd7cddfSDavid du Colombier isdos['%'] = 1;
597dd7cddfSDavid du Colombier isdos['''] = 1;
607dd7cddfSDavid du Colombier isdos['-'] = 1;
617dd7cddfSDavid du Colombier isdos['_'] = 1;
627dd7cddfSDavid du Colombier isdos['@'] = 1;
637dd7cddfSDavid du Colombier isdos['~'] = 1;
647dd7cddfSDavid du Colombier isdos['`'] = 1;
657dd7cddfSDavid du Colombier isdos['!'] = 1;
667dd7cddfSDavid du Colombier isdos['('] = 1;
677dd7cddfSDavid du Colombier isdos[')'] = 1;
687dd7cddfSDavid du Colombier isdos['{'] = 1;
697dd7cddfSDavid du Colombier isdos['}'] = 1;
707dd7cddfSDavid du Colombier isdos['^'] = 1;
717dd7cddfSDavid du Colombier isdos['#'] = 1;
727dd7cddfSDavid du Colombier isdos['&'] = 1;
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier
753e12c5d1SDavid du Colombier p = getsect(xf, 0);
763e12c5d1SDavid du Colombier if(p == 0)
773e12c5d1SDavid du Colombier return -1;
787dd7cddfSDavid du Colombier
793e12c5d1SDavid du Colombier b = (Dosboot*)p->iobuf;
80d9306527SDavid du Colombier if(b->clustsize == 0 || isdosfs(p->iobuf) == 0){
81219b2ee8SDavid du Colombier putsect(p);
82219b2ee8SDavid du Colombier return -1;
83219b2ee8SDavid du Colombier }
843e12c5d1SDavid du Colombier
853e12c5d1SDavid du Colombier bp = malloc(sizeof(Dosbpb));
867dd7cddfSDavid du Colombier memset(bp, 0, sizeof(Dosbpb)); /* clear lock */
873e12c5d1SDavid du Colombier xf->ptr = bp;
883e12c5d1SDavid du Colombier xf->fmt = 1;
893e12c5d1SDavid du Colombier
903e12c5d1SDavid du Colombier bp->sectsize = GSHORT(b->sectsize);
913e12c5d1SDavid du Colombier bp->clustsize = b->clustsize;
923e12c5d1SDavid du Colombier bp->nresrv = GSHORT(b->nresrv);
933e12c5d1SDavid du Colombier bp->nfats = b->nfats;
943e12c5d1SDavid du Colombier bp->rootsize = GSHORT(b->rootsize);
953e12c5d1SDavid du Colombier bp->volsize = GSHORT(b->volsize);
963e12c5d1SDavid du Colombier if(bp->volsize == 0)
973e12c5d1SDavid du Colombier bp->volsize = GLONG(b->bigvolsize);
983e12c5d1SDavid du Colombier bp->mediadesc = b->mediadesc;
993e12c5d1SDavid du Colombier bp->fatsize = GSHORT(b->fatsize);
1007dd7cddfSDavid du Colombier bp->fataddr = GSHORT(b->nresrv);
1013e12c5d1SDavid du Colombier
1027dd7cddfSDavid du Colombier bp->fatinfo = 0;
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier if(bp->fatsize == 0){ /* is FAT32 */
1057dd7cddfSDavid du Colombier if(chatty)
1067dd7cddfSDavid du Colombier bootsecdump32(2, xf, (Dosboot32*)b);
1077dd7cddfSDavid du Colombier xf->isfat32 = 1;
1087dd7cddfSDavid du Colombier b32 = (Dosboot32*)b;
1097dd7cddfSDavid du Colombier bp->fatsize = GLONG(b32->fatsize32);
1107dd7cddfSDavid du Colombier if(bp->fatsize == 0){
1117dd7cddfSDavid du Colombier putsect(p);
112*efb32250SDavid du Colombier if(chatty)
113*efb32250SDavid du Colombier fprint(2, "fatsize 0\n");
1147dd7cddfSDavid du Colombier return -1;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier bp->dataaddr = bp->fataddr + bp->nfats*bp->fatsize;
1177dd7cddfSDavid du Colombier bp->rootaddr = 0;
1187dd7cddfSDavid du Colombier bp->rootstart = GLONG(b32->rootstart);
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier /*
1217dd7cddfSDavid du Colombier * disable fat mirroring?
1227dd7cddfSDavid du Colombier */
1237dd7cddfSDavid du Colombier extflags = GSHORT(b32->extflags);
1247dd7cddfSDavid du Colombier if(extflags & 0x0080){
1257dd7cddfSDavid du Colombier for(i = 0; i < 4; i++){
1267dd7cddfSDavid du Colombier if(extflags & (1 << i)){
1277dd7cddfSDavid du Colombier bp->fataddr += i * bp->fatsize;
1287dd7cddfSDavid du Colombier bp->nfats = 1;
1297dd7cddfSDavid du Colombier break;
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier
1347dd7cddfSDavid du Colombier /*
1357dd7cddfSDavid du Colombier * fat free list info
1367dd7cddfSDavid du Colombier */
1377dd7cddfSDavid du Colombier bp->freeptr = FATRESRV;
1387dd7cddfSDavid du Colombier fisec = GSHORT(b32->infospec);
1397dd7cddfSDavid du Colombier if(fisec != 0 && fisec < GSHORT(b32->nresrv)){
1407dd7cddfSDavid du Colombier p1 = getsect(xf, fisec);
1417dd7cddfSDavid du Colombier if(p1 != nil){
1427dd7cddfSDavid du Colombier fi = (Fatinfo*)p1->iobuf;
1437dd7cddfSDavid du Colombier if(GLONG(fi->sig1) == FATINFOSIG1 && GLONG(fi->sig) == FATINFOSIG){
1447dd7cddfSDavid du Colombier bp->fatinfo = fisec;
1457dd7cddfSDavid du Colombier bp->freeptr = GLONG(fi->nextfree);
1467dd7cddfSDavid du Colombier bp->freeclusters = GLONG(fi->freeclust);
1477dd7cddfSDavid du Colombier chat("fat info: %ld free clusters, next free %ld\n", bp->freeclusters, bp->freeptr);
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier putsect(p1);
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier }else{
1537dd7cddfSDavid du Colombier if(chatty)
1547dd7cddfSDavid du Colombier bootdump(2, b);
1553e12c5d1SDavid du Colombier bp->rootaddr = bp->fataddr + bp->nfats*bp->fatsize;
1567dd7cddfSDavid du Colombier bp->rootstart = 0;
1577dd7cddfSDavid du Colombier i = bp->rootsize*DOSDIRSIZE + bp->sectsize-1;
1583e12c5d1SDavid du Colombier i /= bp->sectsize;
1593e12c5d1SDavid du Colombier bp->dataaddr = bp->rootaddr + i;
1607dd7cddfSDavid du Colombier bp->freeptr = FATRESRV;
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier bp->fatclusters = FATRESRV+(bp->volsize - bp->dataaddr)/bp->clustsize;
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier if(xf->isfat32)
1657dd7cddfSDavid du Colombier bp->fatbits = 32;
1667dd7cddfSDavid du Colombier else if(bp->fatclusters < 4087)
1673e12c5d1SDavid du Colombier bp->fatbits = 12;
1683e12c5d1SDavid du Colombier else
1693e12c5d1SDavid du Colombier bp->fatbits = 16;
1707dd7cddfSDavid du Colombier
1713e12c5d1SDavid du Colombier chat("fatbits=%d (%d clusters)...", bp->fatbits, bp->fatclusters);
1723e12c5d1SDavid du Colombier for(i=0; i<b->nfats; i++)
1739a747e4fSDavid du Colombier chat("fat %d: %ld...", i, bp->fataddr+i*bp->fatsize);
1749a747e4fSDavid du Colombier chat("root: %ld...", bp->rootaddr);
1759a747e4fSDavid du Colombier chat("data: %ld...", bp->dataaddr);
1763e12c5d1SDavid du Colombier putsect(p);
1773e12c5d1SDavid du Colombier return 0;
1783e12c5d1SDavid du Colombier }
1793e12c5d1SDavid du Colombier
1807dd7cddfSDavid du Colombier /*
1817dd7cddfSDavid du Colombier * initialize f to the root directory
1827dd7cddfSDavid du Colombier * this file has no Dosdir entry,
1837dd7cddfSDavid du Colombier * so we special case it all over.
1847dd7cddfSDavid du Colombier */
1857dd7cddfSDavid du Colombier void
1867dd7cddfSDavid du Colombier rootfile(Xfile *f)
1877dd7cddfSDavid du Colombier {
1887dd7cddfSDavid du Colombier Dosptr *dp;
1897dd7cddfSDavid du Colombier
1907dd7cddfSDavid du Colombier dp = f->ptr;
1917dd7cddfSDavid du Colombier memset(dp, 0, sizeof(Dosptr));
1927dd7cddfSDavid du Colombier dp->prevaddr = -1;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier
1957dd7cddfSDavid du Colombier int
1967dd7cddfSDavid du Colombier isroot(ulong addr)
1977dd7cddfSDavid du Colombier {
1987dd7cddfSDavid du Colombier return addr == 0;
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier
2013e12c5d1SDavid du Colombier int
2023e12c5d1SDavid du Colombier getfile(Xfile *f)
2033e12c5d1SDavid du Colombier {
2047dd7cddfSDavid du Colombier Dosptr *dp;
2053e12c5d1SDavid du Colombier Iosect *p;
2063e12c5d1SDavid du Colombier
2077dd7cddfSDavid du Colombier dp = f->ptr;
2083e12c5d1SDavid du Colombier if(dp->p)
2093e12c5d1SDavid du Colombier panic("getfile");
2103e12c5d1SDavid du Colombier p = getsect(f->xf, dp->addr);
2117dd7cddfSDavid du Colombier if(p == nil)
2123e12c5d1SDavid du Colombier return -1;
2137dd7cddfSDavid du Colombier
2147dd7cddfSDavid du Colombier /*
2157dd7cddfSDavid du Colombier * we could also make up a Dosdir for the root
2167dd7cddfSDavid du Colombier */
2177dd7cddfSDavid du Colombier dp->d = nil;
2187dd7cddfSDavid du Colombier if(!isroot(dp->addr)){
2199a747e4fSDavid du Colombier if(f->qid.path != QIDPATH(dp)){
2209a747e4fSDavid du Colombier chat("qid mismatch f=%#llux d=%#lux...", f->qid.path, QIDPATH(dp));
2213e12c5d1SDavid du Colombier putsect(p);
2223e12c5d1SDavid du Colombier errno = Enonexist;
2233e12c5d1SDavid du Colombier return -1;
2243e12c5d1SDavid du Colombier }
2257dd7cddfSDavid du Colombier dp->d = (Dosdir *)&p->iobuf[dp->offset];
2263e12c5d1SDavid du Colombier }
2273e12c5d1SDavid du Colombier dp->p = p;
2283e12c5d1SDavid du Colombier return 0;
2293e12c5d1SDavid du Colombier }
2303e12c5d1SDavid du Colombier
2313e12c5d1SDavid du Colombier void
2323e12c5d1SDavid du Colombier putfile(Xfile *f)
2333e12c5d1SDavid du Colombier {
2347dd7cddfSDavid du Colombier Dosptr *dp;
2353e12c5d1SDavid du Colombier
2367dd7cddfSDavid du Colombier dp = f->ptr;
2373e12c5d1SDavid du Colombier if(!dp->p)
2383e12c5d1SDavid du Colombier panic("putfile");
2393e12c5d1SDavid du Colombier putsect(dp->p);
2407dd7cddfSDavid du Colombier dp->p = nil;
2417dd7cddfSDavid du Colombier dp->d = nil;
2423e12c5d1SDavid du Colombier }
2433e12c5d1SDavid du Colombier
2447dd7cddfSDavid du Colombier long
2457dd7cddfSDavid du Colombier getstart(Xfs *xf, Dosdir *d)
2463e12c5d1SDavid du Colombier {
2477dd7cddfSDavid du Colombier long start;
2483e12c5d1SDavid du Colombier
2497dd7cddfSDavid du Colombier start = GSHORT(d->start);
2507dd7cddfSDavid du Colombier if(xf->isfat32)
2517dd7cddfSDavid du Colombier start |= GSHORT(d->hstart)<<16;
2527dd7cddfSDavid du Colombier return start;
2533e12c5d1SDavid du Colombier }
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier void
2567dd7cddfSDavid du Colombier putstart(Xfs *xf, Dosdir *d, long start)
2577dd7cddfSDavid du Colombier {
2589a747e4fSDavid du Colombier PSHORT(d->start, start);
2599a747e4fSDavid du Colombier if(xf->isfat32)
2609a747e4fSDavid du Colombier PSHORT(d->hstart, start>>16);
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier
2637dd7cddfSDavid du Colombier /*
2647dd7cddfSDavid du Colombier * return the disk cluster for the iclust cluster in f
2657dd7cddfSDavid du Colombier */
2669a747e4fSDavid du Colombier long
2679a747e4fSDavid du Colombier fileclust(Xfile *f, long iclust, int cflag)
2687dd7cddfSDavid du Colombier {
2697dd7cddfSDavid du Colombier Dosbpb *bp;
2707dd7cddfSDavid du Colombier Dosptr *dp;
2717dd7cddfSDavid du Colombier Dosdir *d;
2729a747e4fSDavid du Colombier long start, clust, nskip, next;
2737dd7cddfSDavid du Colombier
2747dd7cddfSDavid du Colombier bp = f->xf->ptr;
2757dd7cddfSDavid du Colombier dp = f->ptr;
2767dd7cddfSDavid du Colombier d = dp->d;
2777dd7cddfSDavid du Colombier next = 0;
2787dd7cddfSDavid du Colombier
2797dd7cddfSDavid du Colombier /*
2807dd7cddfSDavid du Colombier * asking for the cluster of the root directory
2817dd7cddfSDavid du Colombier * is not a well-formed question, since the root directory
2827dd7cddfSDavid du Colombier * does not begin on a cluster boundary.
2837dd7cddfSDavid du Colombier */
2847dd7cddfSDavid du Colombier if(!f->xf->isfat32 && isroot(dp->addr))
2857dd7cddfSDavid du Colombier return -1;
2867dd7cddfSDavid du Colombier
2877dd7cddfSDavid du Colombier if(f->xf->isfat32 && isroot(dp->addr)){
2887dd7cddfSDavid du Colombier start = bp->rootstart;
2897dd7cddfSDavid du Colombier }else{
2907dd7cddfSDavid du Colombier start = getstart(f->xf, d);
2917dd7cddfSDavid du Colombier if(start == 0){
2927dd7cddfSDavid du Colombier if(!cflag)
2937dd7cddfSDavid du Colombier return -1;
2947dd7cddfSDavid du Colombier mlock(bp);
2957dd7cddfSDavid du Colombier start = falloc(f->xf);
2967dd7cddfSDavid du Colombier unmlock(bp);
2977dd7cddfSDavid du Colombier if(start <= 0)
2987dd7cddfSDavid du Colombier return -1;
2997dd7cddfSDavid du Colombier puttime(d, 0);
3007dd7cddfSDavid du Colombier putstart(f->xf, d, start);
3017dd7cddfSDavid du Colombier dp->p->flags |= BMOD;
3027dd7cddfSDavid du Colombier dp->clust = 0;
3037dd7cddfSDavid du Colombier }
3047dd7cddfSDavid du Colombier }
3053e12c5d1SDavid du Colombier if(dp->clust == 0 || iclust < dp->iclust){
3067dd7cddfSDavid du Colombier clust = start;
3073e12c5d1SDavid du Colombier nskip = iclust;
3083e12c5d1SDavid du Colombier }else{
3093e12c5d1SDavid du Colombier clust = dp->clust;
3103e12c5d1SDavid du Colombier nskip = iclust - dp->iclust;
3113e12c5d1SDavid du Colombier }
312219b2ee8SDavid du Colombier if(chatty > 1 && nskip > 0)
3139a747e4fSDavid du Colombier chat("clust %#lx, skip %ld...", clust, nskip);
3143e12c5d1SDavid du Colombier if(clust <= 0)
3153e12c5d1SDavid du Colombier return -1;
3163e12c5d1SDavid du Colombier if(nskip > 0){
3177dd7cddfSDavid du Colombier mlock(bp);
3183e12c5d1SDavid du Colombier while(--nskip >= 0){
3193e12c5d1SDavid du Colombier next = getfat(f->xf, clust);
320219b2ee8SDavid du Colombier if(chatty > 1)
3219a747e4fSDavid du Colombier chat("->%#lx", next);
3223e12c5d1SDavid du Colombier if(next > 0){
3233e12c5d1SDavid du Colombier clust = next;
3243e12c5d1SDavid du Colombier continue;
3253e12c5d1SDavid du Colombier }else if(!cflag)
3263e12c5d1SDavid du Colombier break;
3279a747e4fSDavid du Colombier if(d && (d->attr&DSYSTEM)){
3287dd7cddfSDavid du Colombier next = cfalloc(f);
3297dd7cddfSDavid du Colombier if(next < 0)
3307dd7cddfSDavid du Colombier break;
3317dd7cddfSDavid du Colombier /* cfalloc will call putfat for us, since clust may change */
3327dd7cddfSDavid du Colombier } else {
3333e12c5d1SDavid du Colombier next = falloc(f->xf);
3343e12c5d1SDavid du Colombier if(next < 0)
3353e12c5d1SDavid du Colombier break;
3363e12c5d1SDavid du Colombier putfat(f->xf, clust, next);
3377dd7cddfSDavid du Colombier }
3383e12c5d1SDavid du Colombier clust = next;
3393e12c5d1SDavid du Colombier }
3407dd7cddfSDavid du Colombier unmlock(bp);
3413e12c5d1SDavid du Colombier if(next <= 0)
3423e12c5d1SDavid du Colombier return -1;
3433e12c5d1SDavid du Colombier dp->clust = clust;
3443e12c5d1SDavid du Colombier dp->iclust = iclust;
3453e12c5d1SDavid du Colombier }
3463e12c5d1SDavid du Colombier if(chatty > 1)
3479a747e4fSDavid du Colombier chat(" clust(%#lx)=%#lx...", iclust, clust);
3487dd7cddfSDavid du Colombier return clust;
3493e12c5d1SDavid du Colombier }
3503e12c5d1SDavid du Colombier
3517dd7cddfSDavid du Colombier /*
3527dd7cddfSDavid du Colombier * return the disk sector for the isect disk sector in f
3537dd7cddfSDavid du Colombier */
3549a747e4fSDavid du Colombier long
3559a747e4fSDavid du Colombier fileaddr(Xfile *f, long isect, int cflag)
3563e12c5d1SDavid du Colombier {
3577dd7cddfSDavid du Colombier Dosbpb *bp;
3587dd7cddfSDavid du Colombier Dosptr *dp;
3599a747e4fSDavid du Colombier long clust;
3603e12c5d1SDavid du Colombier
3617dd7cddfSDavid du Colombier bp = f->xf->ptr;
3627dd7cddfSDavid du Colombier dp = f->ptr;
3637dd7cddfSDavid du Colombier if(!f->xf->isfat32 && isroot(dp->addr)){
3647dd7cddfSDavid du Colombier if(isect*bp->sectsize >= bp->rootsize*DOSDIRSIZE)
3657dd7cddfSDavid du Colombier return -1;
3667dd7cddfSDavid du Colombier return bp->rootaddr + isect;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier clust = fileclust(f, isect/bp->clustsize, cflag);
3697dd7cddfSDavid du Colombier if(clust < 0)
3707dd7cddfSDavid du Colombier return -1;
3717dd7cddfSDavid du Colombier
3727dd7cddfSDavid du Colombier return clust2sect(bp, clust) + isect%bp->clustsize;
3737dd7cddfSDavid du Colombier }
3747dd7cddfSDavid du Colombier
3757dd7cddfSDavid du Colombier /*
3769a747e4fSDavid du Colombier * translate names
3777dd7cddfSDavid du Colombier */
3789a747e4fSDavid du Colombier void
3797dd7cddfSDavid du Colombier fixname(char *buf)
3807dd7cddfSDavid du Colombier {
3819a747e4fSDavid du Colombier int c;
3827dd7cddfSDavid du Colombier char *p;
3837dd7cddfSDavid du Colombier
3847dd7cddfSDavid du Colombier p = buf;
3857dd7cddfSDavid du Colombier while(c = *p){
3869a747e4fSDavid du Colombier if(c == ':' && trspaces)
3879a747e4fSDavid du Colombier *p = ' ';
3887dd7cddfSDavid du Colombier p++;
3897dd7cddfSDavid du Colombier }
3907dd7cddfSDavid du Colombier }
3917dd7cddfSDavid du Colombier
3927dd7cddfSDavid du Colombier /*
3939a747e4fSDavid du Colombier * classify the file name as one of
3949a747e4fSDavid du Colombier * Invalid - contains a bad character
3959a747e4fSDavid du Colombier * Short - short valid 8.3 name, no lowercase letters
3969a747e4fSDavid du Colombier * ShortLower - short valid 8.3 name except for lowercase letters
3979a747e4fSDavid du Colombier * Long - long name
3987dd7cddfSDavid du Colombier */
3999a747e4fSDavid du Colombier int
4009a747e4fSDavid du Colombier classifyname(char *buf)
4019a747e4fSDavid du Colombier {
4029a747e4fSDavid du Colombier char *p, *dot;
4039a747e4fSDavid du Colombier int c, isextended, is8dot3, islower, ndot;
4049a747e4fSDavid du Colombier
4059a747e4fSDavid du Colombier p = buf;
4069a747e4fSDavid du Colombier isextended = 0;
4079a747e4fSDavid du Colombier islower = 0;
4089a747e4fSDavid du Colombier dot = nil;
4099a747e4fSDavid du Colombier ndot = 0;
4109a747e4fSDavid du Colombier while(c = (uchar)*p){
4119a747e4fSDavid du Colombier if(c&0x80) /* UTF8 */
4129a747e4fSDavid du Colombier isextended = 1;
4139a747e4fSDavid du Colombier else if(c == '.'){
4149a747e4fSDavid du Colombier dot = p;
4159a747e4fSDavid du Colombier ndot++;
4169a747e4fSDavid du Colombier }else if(strchr("+,:;=[] ", c))
4179a747e4fSDavid du Colombier isextended = 1;
4189a747e4fSDavid du Colombier else if(!isdos[c])
4199a747e4fSDavid du Colombier return Invalid;
4209a747e4fSDavid du Colombier if('a' <= c && c <= 'z')
4219a747e4fSDavid du Colombier islower = 1;
4229a747e4fSDavid du Colombier p++;
4237dd7cddfSDavid du Colombier }
4247dd7cddfSDavid du Colombier
4259a747e4fSDavid du Colombier is8dot3 = (ndot==0 && p-buf <= 8) || (ndot==1 && dot-buf <= 8 && p-(dot+1) <= 3);
4267dd7cddfSDavid du Colombier
4279a747e4fSDavid du Colombier if(!isextended && is8dot3){
4289a747e4fSDavid du Colombier if(islower)
4299a747e4fSDavid du Colombier return ShortLower;
4309a747e4fSDavid du Colombier return Short;
4319a747e4fSDavid du Colombier }
4329a747e4fSDavid du Colombier return Long;
4337dd7cddfSDavid du Colombier }
4347dd7cddfSDavid du Colombier
4357dd7cddfSDavid du Colombier /*
4367dd7cddfSDavid du Colombier * make an alias for a valid long file name
4377dd7cddfSDavid du Colombier */
4387dd7cddfSDavid du Colombier void
4397dd7cddfSDavid du Colombier mkalias(char *name, char *sname, int id)
4407dd7cddfSDavid du Colombier {
4417dd7cddfSDavid du Colombier Rune r;
4427dd7cddfSDavid du Colombier char *s, *e, sid[10];
4437dd7cddfSDavid du Colombier int i, esuf, v;
4447dd7cddfSDavid du Colombier
4457dd7cddfSDavid du Colombier e = strrchr(name, '.');
4467dd7cddfSDavid du Colombier if(e == nil)
4477dd7cddfSDavid du Colombier e = strchr(name, '\0');
4487dd7cddfSDavid du Colombier
4497dd7cddfSDavid du Colombier s = name;
4507dd7cddfSDavid du Colombier i = 0;
4517dd7cddfSDavid du Colombier while(s < e && i < 6){
4529a747e4fSDavid du Colombier if(isdos[(uchar)*s])
4537dd7cddfSDavid du Colombier sname[i++] = *s++;
4547dd7cddfSDavid du Colombier else
4557dd7cddfSDavid du Colombier s += chartorune(&r, s);
4567dd7cddfSDavid du Colombier }
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier v = snprint(sid, 10, "%d", id);
4597dd7cddfSDavid du Colombier if(i + 1 + v > 8)
4607dd7cddfSDavid du Colombier i = 8 - 1 - v;
4617dd7cddfSDavid du Colombier sname[i++] = '~';
4627dd7cddfSDavid du Colombier strcpy(&sname[i], sid);
4637dd7cddfSDavid du Colombier i += v;
4647dd7cddfSDavid du Colombier
4657dd7cddfSDavid du Colombier sname[i++] = '.';
4667dd7cddfSDavid du Colombier esuf = i + 3;
4677dd7cddfSDavid du Colombier if(esuf > 12)
4687dd7cddfSDavid du Colombier panic("bad mkalias");
4697dd7cddfSDavid du Colombier while(*e && i < esuf){
4709a747e4fSDavid du Colombier if(isdos[(uchar)*e])
4717dd7cddfSDavid du Colombier sname[i++] = *e++;
4727dd7cddfSDavid du Colombier else
4737dd7cddfSDavid du Colombier e += chartorune(&r, e);
4747dd7cddfSDavid du Colombier }
4757dd7cddfSDavid du Colombier if(sname[i-1] == '.')
4767dd7cddfSDavid du Colombier i--;
4777dd7cddfSDavid du Colombier sname[i] = '\0';
4787dd7cddfSDavid du Colombier }
4797dd7cddfSDavid du Colombier
4807dd7cddfSDavid du Colombier /*
4817dd7cddfSDavid du Colombier * check for valid plan 9 names,
4827dd7cddfSDavid du Colombier * rewrite ' ' to ':'
4837dd7cddfSDavid du Colombier */
4847dd7cddfSDavid du Colombier char isfrog[256]={
4857dd7cddfSDavid du Colombier /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1,
4867dd7cddfSDavid du Colombier /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1,
4877dd7cddfSDavid du Colombier /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1,
4887dd7cddfSDavid du Colombier /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1,
4899a747e4fSDavid du Colombier /* [' '] 1, let's try this -rsc */
4907dd7cddfSDavid du Colombier ['/'] 1,
4917dd7cddfSDavid du Colombier [0x7f] 1,
4927dd7cddfSDavid du Colombier };
4937dd7cddfSDavid du Colombier
4947dd7cddfSDavid du Colombier int
4957dd7cddfSDavid du Colombier nameok(char *elem)
4967dd7cddfSDavid du Colombier {
4977dd7cddfSDavid du Colombier while(*elem) {
4989a747e4fSDavid du Colombier if(*elem == ' ' && trspaces)
4997dd7cddfSDavid du Colombier *elem = ':';
5007dd7cddfSDavid du Colombier if(isfrog[*(uchar*)elem])
5017dd7cddfSDavid du Colombier return 0;
5027dd7cddfSDavid du Colombier elem++;
5037dd7cddfSDavid du Colombier }
5047dd7cddfSDavid du Colombier return 1;
5057dd7cddfSDavid du Colombier }
5067dd7cddfSDavid du Colombier
5077dd7cddfSDavid du Colombier /*
5087dd7cddfSDavid du Colombier * look for a directory entry matching name
5097dd7cddfSDavid du Colombier * always searches for long names which match a short name
5107dd7cddfSDavid du Colombier */
5117dd7cddfSDavid du Colombier int
5129a747e4fSDavid du Colombier searchdir(Xfile *f, char *name, Dosptr *dp, int cflag, int longtype)
5137dd7cddfSDavid du Colombier {
5147dd7cddfSDavid du Colombier Xfs *xf;
5157dd7cddfSDavid du Colombier Iosect *p;
5167dd7cddfSDavid du Colombier Dosbpb *bp;
5177dd7cddfSDavid du Colombier Dosdir *d;
5187dd7cddfSDavid du Colombier char buf[261], *bname;
51959cc4ca5SDavid du Colombier int isect, addr, o, addr1, addr2, prevaddr, prevaddr1, o1, islong, have, need, sum;
5207dd7cddfSDavid du Colombier
5217dd7cddfSDavid du Colombier xf = f->xf;
5227dd7cddfSDavid du Colombier bp = xf->ptr;
5237dd7cddfSDavid du Colombier addr1 = -1;
5247dd7cddfSDavid du Colombier addr2 = -1;
52559cc4ca5SDavid du Colombier prevaddr1 = -1;
5267dd7cddfSDavid du Colombier o1 = 0;
5277dd7cddfSDavid du Colombier islong = 0;
5287dd7cddfSDavid du Colombier sum = -1;
5297dd7cddfSDavid du Colombier
5307dd7cddfSDavid du Colombier need = 1;
5319a747e4fSDavid du Colombier if(longtype!=Short && cflag)
5327dd7cddfSDavid du Colombier need += (utflen(name) + DOSRUNE-1) / DOSRUNE;
5337dd7cddfSDavid du Colombier
5343e12c5d1SDavid du Colombier memset(dp, 0, sizeof(Dosptr));
5357dd7cddfSDavid du Colombier dp->prevaddr = -1;
5367dd7cddfSDavid du Colombier dp->naddr = -1;
5373e12c5d1SDavid du Colombier dp->paddr = ((Dosptr *)f->ptr)->addr;
5383e12c5d1SDavid du Colombier dp->poffset = ((Dosptr *)f->ptr)->offset;
5393e12c5d1SDavid du Colombier
5407dd7cddfSDavid du Colombier have = 0;
5417dd7cddfSDavid du Colombier addr = -1;
5427dd7cddfSDavid du Colombier bname = nil;
5433e12c5d1SDavid du Colombier for(isect=0;; isect++){
54459cc4ca5SDavid du Colombier prevaddr = addr;
5453e12c5d1SDavid du Colombier addr = fileaddr(f, isect, cflag);
5463e12c5d1SDavid du Colombier if(addr < 0)
5473e12c5d1SDavid du Colombier break;
5483e12c5d1SDavid du Colombier p = getsect(xf, addr);
5493e12c5d1SDavid du Colombier if(p == 0)
5503e12c5d1SDavid du Colombier break;
5517dd7cddfSDavid du Colombier for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
5523e12c5d1SDavid du Colombier d = (Dosdir *)&p->iobuf[o];
5533e12c5d1SDavid du Colombier if(d->name[0] == 0x00){
5543e12c5d1SDavid du Colombier chat("end dir(0)...");
5553e12c5d1SDavid du Colombier putsect(p);
5563e12c5d1SDavid du Colombier if(!cflag)
5573e12c5d1SDavid du Colombier return -1;
5587dd7cddfSDavid du Colombier
5597dd7cddfSDavid du Colombier /*
5607dd7cddfSDavid du Colombier * addr1 & o1 are the start of the dirs
5617dd7cddfSDavid du Colombier * addr2 is the optional second cluster used if the long name
5627dd7cddfSDavid du Colombier * entry does not fit within the addr1 cluster
5637dd7cddfSDavid du Colombier *
5647dd7cddfSDavid du Colombier * have tells us the number of contiguous free dirs
5657dd7cddfSDavid du Colombier * starting at addr1.o1; need are necessary to hold the long name.
5667dd7cddfSDavid du Colombier */
5677dd7cddfSDavid du Colombier if(addr1 < 0){
5683e12c5d1SDavid du Colombier addr1 = addr;
56959cc4ca5SDavid du Colombier prevaddr1 = prevaddr;
5703e12c5d1SDavid du Colombier o1 = o;
5713e12c5d1SDavid du Colombier }
5727dd7cddfSDavid du Colombier if(addr2 < 0 && (bp->sectsize-o)/DOSDIRSIZE + have < need){
5737dd7cddfSDavid du Colombier addr2 = fileaddr(f, isect+1, cflag);
5747dd7cddfSDavid du Colombier if(addr2 < 0)
5757dd7cddfSDavid du Colombier goto breakout;
5767dd7cddfSDavid du Colombier }else if(addr2 < 0)
5777dd7cddfSDavid du Colombier addr2 = addr;
5787dd7cddfSDavid du Colombier if(addr2 == addr1)
5797dd7cddfSDavid du Colombier addr2 = -1;
5803e12c5d1SDavid du Colombier dp->addr = addr1;
5813e12c5d1SDavid du Colombier dp->offset = o1;
58259cc4ca5SDavid du Colombier dp->prevaddr = prevaddr1;
5837dd7cddfSDavid du Colombier dp->naddr = addr2;
5843e12c5d1SDavid du Colombier return 0;
5853e12c5d1SDavid du Colombier }
5867dd7cddfSDavid du Colombier if(d->name[0] == DOSEMPTY){
5877dd7cddfSDavid du Colombier if(chatty)
5887dd7cddfSDavid du Colombier fprint(2, "empty dir\n");
5897dd7cddfSDavid du Colombier
5907dd7cddfSDavid du Colombier have++;
5917dd7cddfSDavid du Colombier if(addr1 == -1){
5923e12c5d1SDavid du Colombier addr1 = addr;
5933e12c5d1SDavid du Colombier o1 = o;
59459cc4ca5SDavid du Colombier prevaddr1 = prevaddr;
5953e12c5d1SDavid du Colombier }
5967dd7cddfSDavid du Colombier if(addr2 == -1 && have >= need)
5977dd7cddfSDavid du Colombier addr2 = addr;
5983e12c5d1SDavid du Colombier continue;
5993e12c5d1SDavid du Colombier }
6007dd7cddfSDavid du Colombier have = 0;
6017dd7cddfSDavid du Colombier if(addr2 == -1)
6027dd7cddfSDavid du Colombier addr1 = -1;
6037dd7cddfSDavid du Colombier
6043e12c5d1SDavid du Colombier dirdump(d);
6057dd7cddfSDavid du Colombier if((d->attr & 0xf) == 0xf){
6067dd7cddfSDavid du Colombier bname = getnamesect(buf, bname, p->iobuf + o, &islong, &sum, 1);
6077dd7cddfSDavid du Colombier continue;
6087dd7cddfSDavid du Colombier }
6097dd7cddfSDavid du Colombier if(d->attr & DVLABEL){
6107dd7cddfSDavid du Colombier islong = 0;
6117dd7cddfSDavid du Colombier continue;
6127dd7cddfSDavid du Colombier }
6137dd7cddfSDavid du Colombier if(islong != 1 || sum != aliassum(d) || cistrcmp(bname, name) != 0){
6147dd7cddfSDavid du Colombier bname = buf;
6157dd7cddfSDavid du Colombier getname(buf, d);
6167dd7cddfSDavid du Colombier }
6177dd7cddfSDavid du Colombier islong = 0;
6187dd7cddfSDavid du Colombier if(cistrcmp(bname, name) != 0)
6197dd7cddfSDavid du Colombier continue;
6207dd7cddfSDavid du Colombier if(chatty)
6217dd7cddfSDavid du Colombier fprint(2, "found\n");
6223e12c5d1SDavid du Colombier if(cflag){
6233e12c5d1SDavid du Colombier putsect(p);
6243e12c5d1SDavid du Colombier return -1;
6253e12c5d1SDavid du Colombier }
6263e12c5d1SDavid du Colombier dp->addr = addr;
62759cc4ca5SDavid du Colombier dp->prevaddr = prevaddr;
6283e12c5d1SDavid du Colombier dp->offset = o;
6293e12c5d1SDavid du Colombier dp->p = p;
6303e12c5d1SDavid du Colombier dp->d = d;
6313e12c5d1SDavid du Colombier return 0;
6323e12c5d1SDavid du Colombier }
6333e12c5d1SDavid du Colombier putsect(p);
6343e12c5d1SDavid du Colombier }
6357dd7cddfSDavid du Colombier breakout:
6363e12c5d1SDavid du Colombier chat("end dir(1)...");
6373e12c5d1SDavid du Colombier return -1;
6383e12c5d1SDavid du Colombier }
6393e12c5d1SDavid du Colombier
6403e12c5d1SDavid du Colombier int
6413e12c5d1SDavid du Colombier emptydir(Xfile *f)
6423e12c5d1SDavid du Colombier {
6433e12c5d1SDavid du Colombier Xfs *xf = f->xf;
6443e12c5d1SDavid du Colombier Dosbpb *bp = xf->ptr;
6453e12c5d1SDavid du Colombier int isect, addr, o;
6463e12c5d1SDavid du Colombier Iosect *p;
6473e12c5d1SDavid du Colombier Dosdir *d;
6483e12c5d1SDavid du Colombier
6493e12c5d1SDavid du Colombier for(isect=0;; isect++){
6503e12c5d1SDavid du Colombier addr = fileaddr(f, isect, 0);
6513e12c5d1SDavid du Colombier if(addr < 0)
6523e12c5d1SDavid du Colombier break;
6533e12c5d1SDavid du Colombier p = getsect(xf, addr);
6543e12c5d1SDavid du Colombier if(p == 0)
6553e12c5d1SDavid du Colombier return -1;
6567dd7cddfSDavid du Colombier for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
6573e12c5d1SDavid du Colombier d = (Dosdir *)&p->iobuf[o];
6583e12c5d1SDavid du Colombier if(d->name[0] == 0x00){
6593e12c5d1SDavid du Colombier putsect(p);
6603e12c5d1SDavid du Colombier return 0;
6613e12c5d1SDavid du Colombier }
6627dd7cddfSDavid du Colombier if(d->name[0] == DOSEMPTY)
6633e12c5d1SDavid du Colombier continue;
6643e12c5d1SDavid du Colombier if(d->name[0] == '.')
6653e12c5d1SDavid du Colombier continue;
6663e12c5d1SDavid du Colombier if(d->attr&DVLABEL)
6673e12c5d1SDavid du Colombier continue;
6683e12c5d1SDavid du Colombier putsect(p);
6693e12c5d1SDavid du Colombier return -1;
6703e12c5d1SDavid du Colombier }
6713e12c5d1SDavid du Colombier putsect(p);
6723e12c5d1SDavid du Colombier }
6733e12c5d1SDavid du Colombier return 0;
6743e12c5d1SDavid du Colombier }
6753e12c5d1SDavid du Colombier
6763e12c5d1SDavid du Colombier long
6777dd7cddfSDavid du Colombier readdir(Xfile *f, void *vbuf, long offset, long count)
6783e12c5d1SDavid du Colombier {
6797dd7cddfSDavid du Colombier Xfs *xf;
6807dd7cddfSDavid du Colombier Dosbpb *bp;
6813e12c5d1SDavid du Colombier Dir dir;
6827dd7cddfSDavid du Colombier int isect, addr, o, islong, sum;
6833e12c5d1SDavid du Colombier Iosect *p;
6843e12c5d1SDavid du Colombier Dosdir *d;
6859a747e4fSDavid du Colombier long rcnt, n;
6869a747e4fSDavid du Colombier char *name, snamebuf[8+1+3+1], namebuf[DOSNAMELEN];
6879a747e4fSDavid du Colombier uchar *buf;
6883e12c5d1SDavid du Colombier
6897dd7cddfSDavid du Colombier buf = vbuf;
6907dd7cddfSDavid du Colombier rcnt = 0;
6917dd7cddfSDavid du Colombier xf = f->xf;
6927dd7cddfSDavid du Colombier bp = xf->ptr;
6933e12c5d1SDavid du Colombier if(count <= 0)
6943e12c5d1SDavid du Colombier return 0;
6957dd7cddfSDavid du Colombier islong = 0;
6967dd7cddfSDavid du Colombier sum = -1;
6977dd7cddfSDavid du Colombier name = nil;
6983e12c5d1SDavid du Colombier for(isect=0;; isect++){
6993e12c5d1SDavid du Colombier addr = fileaddr(f, isect, 0);
7003e12c5d1SDavid du Colombier if(addr < 0)
7013e12c5d1SDavid du Colombier break;
7023e12c5d1SDavid du Colombier p = getsect(xf, addr);
7033e12c5d1SDavid du Colombier if(p == 0)
7043e12c5d1SDavid du Colombier return -1;
7057dd7cddfSDavid du Colombier for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
7063e12c5d1SDavid du Colombier d = (Dosdir *)&p->iobuf[o];
7073e12c5d1SDavid du Colombier if(d->name[0] == 0x00){
7083e12c5d1SDavid du Colombier putsect(p);
7093e12c5d1SDavid du Colombier return rcnt;
7103e12c5d1SDavid du Colombier }
7117dd7cddfSDavid du Colombier if(d->name[0] == DOSEMPTY)
7123e12c5d1SDavid du Colombier continue;
7137dd7cddfSDavid du Colombier dirdump(d);
7143e12c5d1SDavid du Colombier if(d->name[0] == '.'){
7153e12c5d1SDavid du Colombier if(d->name[1] == ' ' || d->name[1] == 0)
7163e12c5d1SDavid du Colombier continue;
7173e12c5d1SDavid du Colombier if(d->name[1] == '.' &&
7183e12c5d1SDavid du Colombier (d->name[2] == ' ' || d->name[2] == 0))
7193e12c5d1SDavid du Colombier continue;
7203e12c5d1SDavid du Colombier }
7217dd7cddfSDavid du Colombier if((d->attr & 0xf) == 0xf){
7227dd7cddfSDavid du Colombier name = getnamesect(namebuf, name, p->iobuf+o, &islong, &sum, 1);
7233e12c5d1SDavid du Colombier continue;
7243e12c5d1SDavid du Colombier }
7257dd7cddfSDavid du Colombier if(d->attr & DVLABEL){
7267dd7cddfSDavid du Colombier islong = 0;
7277dd7cddfSDavid du Colombier continue;
7287dd7cddfSDavid du Colombier }
7299a747e4fSDavid du Colombier dir.name = snamebuf;
7309a747e4fSDavid du Colombier getdir(xf, &dir, d, addr, o);
7319a747e4fSDavid du Colombier if(islong == 1 && nameok(name) && sum == aliassum(d))
7329a747e4fSDavid du Colombier dir.name = name;
7339a747e4fSDavid du Colombier islong = 0;
7349a747e4fSDavid du Colombier n = convD2M(&dir, &buf[rcnt], count - rcnt);
7359a747e4fSDavid du Colombier name = nil;
7369a747e4fSDavid du Colombier if(n <= BIT16SZ){ /* no room for next entry */
7379a747e4fSDavid du Colombier putsect(p);
7389a747e4fSDavid du Colombier return rcnt;
7399a747e4fSDavid du Colombier }
7409a747e4fSDavid du Colombier rcnt += n;
7417dd7cddfSDavid du Colombier if(offset > 0){
7429a747e4fSDavid du Colombier offset -= rcnt;
7439a747e4fSDavid du Colombier rcnt = 0;
7447dd7cddfSDavid du Colombier islong = 0;
7457dd7cddfSDavid du Colombier continue;
7467dd7cddfSDavid du Colombier }
7479a747e4fSDavid du Colombier if(rcnt == count){
7483e12c5d1SDavid du Colombier putsect(p);
7493e12c5d1SDavid du Colombier return rcnt;
7503e12c5d1SDavid du Colombier }
7513e12c5d1SDavid du Colombier }
7523e12c5d1SDavid du Colombier putsect(p);
7533e12c5d1SDavid du Colombier }
7543e12c5d1SDavid du Colombier return rcnt;
7553e12c5d1SDavid du Colombier }
7563e12c5d1SDavid du Colombier
7577dd7cddfSDavid du Colombier /*
7587dd7cddfSDavid du Colombier * set up ndp for a directory's parent
7597dd7cddfSDavid du Colombier * the hardest part is setting up paddr
7607dd7cddfSDavid du Colombier */
7613e12c5d1SDavid du Colombier int
7623e12c5d1SDavid du Colombier walkup(Xfile *f, Dosptr *ndp)
7633e12c5d1SDavid du Colombier {
7647dd7cddfSDavid du Colombier Dosbpb *bp;
7657dd7cddfSDavid du Colombier Dosptr *dp;
7663e12c5d1SDavid du Colombier Dosdir *xd;
7673e12c5d1SDavid du Colombier Iosect *p;
7687dd7cddfSDavid du Colombier long k, o, so, start, pstart, ppstart, st, ppclust;
7693e12c5d1SDavid du Colombier
7707dd7cddfSDavid du Colombier bp = f->xf->ptr;
7717dd7cddfSDavid du Colombier dp = f->ptr;
7723e12c5d1SDavid du Colombier memset(ndp, 0, sizeof(Dosptr));
7737dd7cddfSDavid du Colombier ndp->prevaddr = -1;
7747dd7cddfSDavid du Colombier ndp->naddr = -1;
7753e12c5d1SDavid du Colombier ndp->addr = dp->paddr;
7763e12c5d1SDavid du Colombier ndp->offset = dp->poffset;
7777dd7cddfSDavid du Colombier
7789a747e4fSDavid du Colombier chat("walkup: paddr=%#lx...", dp->paddr);
7797dd7cddfSDavid du Colombier
7807dd7cddfSDavid du Colombier /*
7817dd7cddfSDavid du Colombier * root's paddr is always itself
7827dd7cddfSDavid du Colombier */
7837dd7cddfSDavid du Colombier if(isroot(dp->paddr))
7843e12c5d1SDavid du Colombier return 0;
7857dd7cddfSDavid du Colombier
7867dd7cddfSDavid du Colombier /*
7877dd7cddfSDavid du Colombier * find the start of our parent's directory
7887dd7cddfSDavid du Colombier */
7893e12c5d1SDavid du Colombier p = getsect(f->xf, dp->paddr);
7907dd7cddfSDavid du Colombier if(p == nil)
7913e12c5d1SDavid du Colombier goto error;
7923e12c5d1SDavid du Colombier xd = (Dosdir *)&p->iobuf[dp->poffset];
7933e12c5d1SDavid du Colombier dirdump(xd);
7947dd7cddfSDavid du Colombier start = getstart(f->xf, xd);
7959a747e4fSDavid du Colombier chat("start=%#lx...", start);
7963e12c5d1SDavid du Colombier if(start == 0)
7973e12c5d1SDavid du Colombier goto error;
7983e12c5d1SDavid du Colombier putsect(p);
7997dd7cddfSDavid du Colombier
8007dd7cddfSDavid du Colombier /*
8017dd7cddfSDavid du Colombier * verify that parent's . points to itself
8027dd7cddfSDavid du Colombier */
8037dd7cddfSDavid du Colombier p = getsect(f->xf, clust2sect(bp, start));
8047dd7cddfSDavid du Colombier if(p == nil)
8053e12c5d1SDavid du Colombier goto error;
8063e12c5d1SDavid du Colombier xd = (Dosdir *)p->iobuf;
8073e12c5d1SDavid du Colombier dirdump(xd);
8087dd7cddfSDavid du Colombier st = getstart(f->xf, xd);
8097dd7cddfSDavid du Colombier if(xd->name[0]!='.' || xd->name[1]!=' ' || start!=st)
8103e12c5d1SDavid du Colombier goto error;
8117dd7cddfSDavid du Colombier
8127dd7cddfSDavid du Colombier /*
8137dd7cddfSDavid du Colombier * parent's .. is the next entry, and has start of parent's parent
8147dd7cddfSDavid du Colombier */
8153e12c5d1SDavid du Colombier xd++;
8163e12c5d1SDavid du Colombier dirdump(xd);
8173e12c5d1SDavid du Colombier if(xd->name[0] != '.' || xd->name[1] != '.')
8183e12c5d1SDavid du Colombier goto error;
8197dd7cddfSDavid du Colombier pstart = getstart(f->xf, xd);
8203e12c5d1SDavid du Colombier putsect(p);
8217dd7cddfSDavid du Colombier
8227dd7cddfSDavid du Colombier /*
8237dd7cddfSDavid du Colombier * we're done if parent is root
8247dd7cddfSDavid du Colombier */
8257dd7cddfSDavid du Colombier if(pstart == 0 || f->xf->isfat32 && pstart == bp->rootstart)
8263e12c5d1SDavid du Colombier return 0;
8277dd7cddfSDavid du Colombier
8287dd7cddfSDavid du Colombier /*
8297dd7cddfSDavid du Colombier * verify that parent's . points to itself
8307dd7cddfSDavid du Colombier */
8317dd7cddfSDavid du Colombier p = getsect(f->xf, clust2sect(bp, pstart));
832219b2ee8SDavid du Colombier if(p == 0){
8339a747e4fSDavid du Colombier chat("getsect %ld failed\n", pstart);
8343e12c5d1SDavid du Colombier goto error;
835219b2ee8SDavid du Colombier }
8363e12c5d1SDavid du Colombier xd = (Dosdir *)p->iobuf;
837219b2ee8SDavid du Colombier dirdump(xd);
8387dd7cddfSDavid du Colombier st = getstart(f->xf, xd);
8397dd7cddfSDavid du Colombier if(xd->name[0]!='.' || xd->name[1]!=' ' || pstart!=st)
8403e12c5d1SDavid du Colombier goto error;
8417dd7cddfSDavid du Colombier
8427dd7cddfSDavid du Colombier /*
8437dd7cddfSDavid du Colombier * parent's parent's .. is the next entry, and has start of parent's parent's parent
8447dd7cddfSDavid du Colombier */
8453e12c5d1SDavid du Colombier xd++;
846219b2ee8SDavid du Colombier dirdump(xd);
8473e12c5d1SDavid du Colombier if(xd->name[0] != '.' || xd->name[1] != '.')
8483e12c5d1SDavid du Colombier goto error;
8497dd7cddfSDavid du Colombier ppstart = getstart(f->xf, xd);
8503e12c5d1SDavid du Colombier putsect(p);
8517dd7cddfSDavid du Colombier
8527dd7cddfSDavid du Colombier /*
8537dd7cddfSDavid du Colombier * open parent's parent's parent, and walk through it until parent's parent is found
8547dd7cddfSDavid du Colombier * need this to find parent's parent's addr and offset
8557dd7cddfSDavid du Colombier */
8567dd7cddfSDavid du Colombier ppclust = ppstart;
8577dd7cddfSDavid du Colombier if(f->xf->isfat32 && ppclust == 0){
8587dd7cddfSDavid du Colombier ppclust = bp->rootstart;
8597dd7cddfSDavid du Colombier chat("ppclust 0, resetting to rootstart\n");
8607dd7cddfSDavid du Colombier }
8617dd7cddfSDavid du Colombier k = ppclust ? clust2sect(bp, ppclust) : bp->rootaddr;
8623e12c5d1SDavid du Colombier p = getsect(f->xf, k);
8637dd7cddfSDavid du Colombier if(p == nil){
8649a747e4fSDavid du Colombier chat("getsect %ld failed\n", k);
8653e12c5d1SDavid du Colombier goto error;
866219b2ee8SDavid du Colombier }
8673e12c5d1SDavid du Colombier xd = (Dosdir *)p->iobuf;
868219b2ee8SDavid du Colombier dirdump(xd);
8697dd7cddfSDavid du Colombier if(ppstart){
8707dd7cddfSDavid du Colombier st = getstart(f->xf, xd);
8717dd7cddfSDavid du Colombier if(xd->name[0]!='.' || xd->name[1]!=' ' || ppstart!=st)
8723e12c5d1SDavid du Colombier goto error;
8737dd7cddfSDavid du Colombier }
8743e12c5d1SDavid du Colombier for(so=1;; so++){
8757dd7cddfSDavid du Colombier for(o=0; o<bp->sectsize; o+=DOSDIRSIZE){
8763e12c5d1SDavid du Colombier xd = (Dosdir *)&p->iobuf[o];
877219b2ee8SDavid du Colombier if(xd->name[0] == 0x00){
878219b2ee8SDavid du Colombier chat("end dir\n");
8793e12c5d1SDavid du Colombier goto error;
880219b2ee8SDavid du Colombier }
8817dd7cddfSDavid du Colombier if(xd->name[0] == DOSEMPTY)
8823e12c5d1SDavid du Colombier continue;
8837dd7cddfSDavid du Colombier st = getstart(f->xf, xd);
8847dd7cddfSDavid du Colombier if(st == pstart)
8853e12c5d1SDavid du Colombier goto out;
8863e12c5d1SDavid du Colombier }
8877dd7cddfSDavid du Colombier if(ppclust){
888219b2ee8SDavid du Colombier if(so%bp->clustsize == 0){
8897dd7cddfSDavid du Colombier mlock(bp);
8907dd7cddfSDavid du Colombier ppclust = getfat(f->xf, ppclust);
8917dd7cddfSDavid du Colombier unmlock(bp);
8927dd7cddfSDavid du Colombier if(ppclust < 0){
8939a747e4fSDavid du Colombier chat("getfat %ld failed\n", ppclust);
8943e12c5d1SDavid du Colombier goto error;
895219b2ee8SDavid du Colombier }
896219b2ee8SDavid du Colombier }
8977dd7cddfSDavid du Colombier k = clust2sect(bp, ppclust) +
898219b2ee8SDavid du Colombier so%bp->clustsize;
8993e12c5d1SDavid du Colombier }else{
9007dd7cddfSDavid du Colombier if(so*bp->sectsize >= bp->rootsize*DOSDIRSIZE)
9013e12c5d1SDavid du Colombier goto error;
9023e12c5d1SDavid du Colombier k = bp->rootaddr + so;
9033e12c5d1SDavid du Colombier }
9043e12c5d1SDavid du Colombier putsect(p);
9053e12c5d1SDavid du Colombier p = getsect(f->xf, k);
906219b2ee8SDavid du Colombier if(p == 0){
9079a747e4fSDavid du Colombier chat("getsect %ld failed\n", k);
9083e12c5d1SDavid du Colombier goto error;
9093e12c5d1SDavid du Colombier }
910219b2ee8SDavid du Colombier }
9113e12c5d1SDavid du Colombier out:
9123e12c5d1SDavid du Colombier putsect(p);
9133e12c5d1SDavid du Colombier ndp->paddr = k;
9143e12c5d1SDavid du Colombier ndp->poffset = o;
9153e12c5d1SDavid du Colombier return 0;
9163e12c5d1SDavid du Colombier
9173e12c5d1SDavid du Colombier error:
9183e12c5d1SDavid du Colombier if(p)
9193e12c5d1SDavid du Colombier putsect(p);
9203e12c5d1SDavid du Colombier return -1;
9213e12c5d1SDavid du Colombier }
9223e12c5d1SDavid du Colombier
9233e12c5d1SDavid du Colombier long
9247dd7cddfSDavid du Colombier readfile(Xfile *f, void *vbuf, long offset, long count)
9253e12c5d1SDavid du Colombier {
9263e12c5d1SDavid du Colombier Xfs *xf = f->xf;
9273e12c5d1SDavid du Colombier Dosbpb *bp = xf->ptr;
9283e12c5d1SDavid du Colombier Dosptr *dp = f->ptr;
9293e12c5d1SDavid du Colombier Dosdir *d = dp->d;
9303e12c5d1SDavid du Colombier int isect, addr, o, c;
9313e12c5d1SDavid du Colombier Iosect *p;
9327dd7cddfSDavid du Colombier uchar *buf;
9339a747e4fSDavid du Colombier long length, rcnt;
9343e12c5d1SDavid du Colombier
9359a747e4fSDavid du Colombier rcnt = 0;
9369a747e4fSDavid du Colombier length = GLONG(d->length);
9377dd7cddfSDavid du Colombier buf = vbuf;
9383e12c5d1SDavid du Colombier if(offset >= length)
9393e12c5d1SDavid du Colombier return 0;
9403e12c5d1SDavid du Colombier if(offset+count >= length)
9413e12c5d1SDavid du Colombier count = length - offset;
9423e12c5d1SDavid du Colombier isect = offset/bp->sectsize;
9433e12c5d1SDavid du Colombier o = offset%bp->sectsize;
9443e12c5d1SDavid du Colombier while(count > 0){
9453e12c5d1SDavid du Colombier addr = fileaddr(f, isect++, 0);
9463e12c5d1SDavid du Colombier if(addr < 0)
9473e12c5d1SDavid du Colombier break;
9483e12c5d1SDavid du Colombier c = bp->sectsize - o;
9493e12c5d1SDavid du Colombier if(c > count)
9503e12c5d1SDavid du Colombier c = count;
9513e12c5d1SDavid du Colombier p = getsect(xf, addr);
9523e12c5d1SDavid du Colombier if(p == 0)
9533e12c5d1SDavid du Colombier return -1;
9543e12c5d1SDavid du Colombier memmove(&buf[rcnt], &p->iobuf[o], c);
9553e12c5d1SDavid du Colombier putsect(p);
9563e12c5d1SDavid du Colombier count -= c;
9573e12c5d1SDavid du Colombier rcnt += c;
9583e12c5d1SDavid du Colombier o = 0;
9593e12c5d1SDavid du Colombier }
9603e12c5d1SDavid du Colombier return rcnt;
9613e12c5d1SDavid du Colombier }
9623e12c5d1SDavid du Colombier
9633e12c5d1SDavid du Colombier long
9647dd7cddfSDavid du Colombier writefile(Xfile *f, void *vbuf, long offset, long count)
9653e12c5d1SDavid du Colombier {
9663e12c5d1SDavid du Colombier Xfs *xf = f->xf;
9673e12c5d1SDavid du Colombier Dosbpb *bp = xf->ptr;
9683e12c5d1SDavid du Colombier Dosptr *dp = f->ptr;
9693e12c5d1SDavid du Colombier Dosdir *d = dp->d;
970219b2ee8SDavid du Colombier int isect, addr = 0, o, c;
9713e12c5d1SDavid du Colombier Iosect *p;
9727dd7cddfSDavid du Colombier uchar *buf;
973219b2ee8SDavid du Colombier long length, rcnt = 0, dlen;
9743e12c5d1SDavid du Colombier
9757dd7cddfSDavid du Colombier buf = vbuf;
9763e12c5d1SDavid du Colombier isect = offset/bp->sectsize;
9773e12c5d1SDavid du Colombier o = offset%bp->sectsize;
9783e12c5d1SDavid du Colombier while(count > 0){
9793e12c5d1SDavid du Colombier addr = fileaddr(f, isect++, 1);
9803e12c5d1SDavid du Colombier if(addr < 0)
9813e12c5d1SDavid du Colombier break;
9823e12c5d1SDavid du Colombier c = bp->sectsize - o;
9833e12c5d1SDavid du Colombier if(c > count)
9843e12c5d1SDavid du Colombier c = count;
9853e12c5d1SDavid du Colombier if(c == bp->sectsize){
9863e12c5d1SDavid du Colombier p = getosect(xf, addr);
9873e12c5d1SDavid du Colombier p->flags = 0;
9883e12c5d1SDavid du Colombier }else{
9893e12c5d1SDavid du Colombier p = getsect(xf, addr);
9907dd7cddfSDavid du Colombier if(p == nil)
9913e12c5d1SDavid du Colombier return -1;
9923e12c5d1SDavid du Colombier }
9933e12c5d1SDavid du Colombier memmove(&p->iobuf[o], &buf[rcnt], c);
9943e12c5d1SDavid du Colombier p->flags |= BMOD;
9953e12c5d1SDavid du Colombier putsect(p);
9963e12c5d1SDavid du Colombier count -= c;
9973e12c5d1SDavid du Colombier rcnt += c;
9983e12c5d1SDavid du Colombier o = 0;
9993e12c5d1SDavid du Colombier }
1000219b2ee8SDavid du Colombier if(rcnt <= 0 && addr < 0)
1001219b2ee8SDavid du Colombier return -1;
1002219b2ee8SDavid du Colombier length = 0;
1003219b2ee8SDavid du Colombier dlen = GLONG(d->length);
1004219b2ee8SDavid du Colombier if(rcnt > 0)
10053e12c5d1SDavid du Colombier length = offset+rcnt;
1006219b2ee8SDavid du Colombier else if(dp->addr && dp->clust){
1007219b2ee8SDavid du Colombier c = bp->clustsize*bp->sectsize;
1008219b2ee8SDavid du Colombier if(dp->iclust > (dlen+c-1)/c)
1009219b2ee8SDavid du Colombier length = c*dp->iclust;
1010219b2ee8SDavid du Colombier }
10119a747e4fSDavid du Colombier if(length > dlen)
10129a747e4fSDavid du Colombier PLONG(d->length, length);
1013219b2ee8SDavid du Colombier puttime(d, 0);
10143e12c5d1SDavid du Colombier dp->p->flags |= BMOD;
10153e12c5d1SDavid du Colombier return rcnt;
10163e12c5d1SDavid du Colombier }
10173e12c5d1SDavid du Colombier
10183e12c5d1SDavid du Colombier int
10199a747e4fSDavid du Colombier truncfile(Xfile *f, long length)
10203e12c5d1SDavid du Colombier {
10213e12c5d1SDavid du Colombier Xfs *xf = f->xf;
10223e12c5d1SDavid du Colombier Dosbpb *bp = xf->ptr;
10233e12c5d1SDavid du Colombier Dosptr *dp = f->ptr;
10243e12c5d1SDavid du Colombier Dosdir *d = dp->d;
10259a747e4fSDavid du Colombier long clust, next, n;
10263e12c5d1SDavid du Colombier
10277dd7cddfSDavid du Colombier mlock(bp);
10287dd7cddfSDavid du Colombier clust = getstart(f->xf, d);
10299a747e4fSDavid du Colombier n = length;
10309a747e4fSDavid du Colombier if(n <= 0)
10317dd7cddfSDavid du Colombier putstart(f->xf, d, 0);
10329a747e4fSDavid du Colombier else
10339a747e4fSDavid du Colombier n -= bp->sectsize;
10347dd7cddfSDavid du Colombier while(clust > 0){
10353e12c5d1SDavid du Colombier next = getfat(xf, clust);
10369a747e4fSDavid du Colombier if(n <= 0)
10373e12c5d1SDavid du Colombier putfat(xf, clust, 0);
10389a747e4fSDavid du Colombier else
10399a747e4fSDavid du Colombier n -= bp->clustsize*bp->sectsize;
10403e12c5d1SDavid du Colombier clust = next;
10413e12c5d1SDavid du Colombier }
10427dd7cddfSDavid du Colombier unmlock(bp);
10439a747e4fSDavid du Colombier PLONG(d->length, length);
10443e12c5d1SDavid du Colombier dp->iclust = 0;
10453e12c5d1SDavid du Colombier dp->clust = 0;
10463e12c5d1SDavid du Colombier dp->p->flags |= BMOD;
10473e12c5d1SDavid du Colombier return 0;
10483e12c5d1SDavid du Colombier }
10493e12c5d1SDavid du Colombier
10503e12c5d1SDavid du Colombier void
10517dd7cddfSDavid du Colombier putdir(Dosdir *d, Dir *dp)
10527dd7cddfSDavid du Colombier {
10539a747e4fSDavid du Colombier if(dp->mode != ~0){
10547dd7cddfSDavid du Colombier if(dp->mode & 2)
10557dd7cddfSDavid du Colombier d->attr &= ~DRONLY;
10567dd7cddfSDavid du Colombier else
10577dd7cddfSDavid du Colombier d->attr |= DRONLY;
10589a747e4fSDavid du Colombier if(dp->mode & DMEXCL)
10597dd7cddfSDavid du Colombier d->attr |= DSYSTEM;
10607dd7cddfSDavid du Colombier else
10617dd7cddfSDavid du Colombier d->attr &= ~DSYSTEM;
10629a747e4fSDavid du Colombier }
10639a747e4fSDavid du Colombier if(dp->mtime != ~0)
10647dd7cddfSDavid du Colombier puttime(d, dp->mtime);
10657dd7cddfSDavid du Colombier }
10667dd7cddfSDavid du Colombier
10677dd7cddfSDavid du Colombier /*
10687dd7cddfSDavid du Colombier * should extend this to deal with
10697dd7cddfSDavid du Colombier * creation and access dates
10707dd7cddfSDavid du Colombier */
10717dd7cddfSDavid du Colombier void
10727dd7cddfSDavid du Colombier getdir(Xfs *xfs, Dir *dp, Dosdir *d, int addr, int offset)
10733e12c5d1SDavid du Colombier {
10747dd7cddfSDavid du Colombier if(d == nil || addr == 0)
10757dd7cddfSDavid du Colombier panic("getdir on root");
10769a747e4fSDavid du Colombier dp->type = 0;
10779a747e4fSDavid du Colombier dp->dev = 0;
10783e12c5d1SDavid du Colombier getname(dp->name, d);
10797dd7cddfSDavid du Colombier
10807dd7cddfSDavid du Colombier dp->qid.path = addr*(Sectorsize/DOSDIRSIZE) +
10817dd7cddfSDavid du Colombier offset/DOSDIRSIZE;
10829a747e4fSDavid du Colombier dp->qid.vers = 0;
10837dd7cddfSDavid du Colombier
10843e12c5d1SDavid du Colombier if(d->attr & DRONLY)
10853e12c5d1SDavid du Colombier dp->mode = 0444;
10863e12c5d1SDavid du Colombier else
10873e12c5d1SDavid du Colombier dp->mode = 0666;
10883e12c5d1SDavid du Colombier dp->atime = gtime(d);
10893e12c5d1SDavid du Colombier dp->mtime = dp->atime;
10909a747e4fSDavid du Colombier dp->qid.type = QTFILE;
10913e12c5d1SDavid du Colombier if(d->attr & DDIR){
10929a747e4fSDavid du Colombier dp->qid.type = QTDIR;
10939a747e4fSDavid du Colombier dp->mode |= DMDIR|0111;
10949a747e4fSDavid du Colombier dp->length = 0;
10953e12c5d1SDavid du Colombier }else
10963e12c5d1SDavid du Colombier dp->length = GLONG(d->length);
10977dd7cddfSDavid du Colombier if(d->attr & DSYSTEM){
10989a747e4fSDavid du Colombier dp->mode |= DMEXCL;
10997dd7cddfSDavid du Colombier if(iscontig(xfs, d))
11009a747e4fSDavid du Colombier dp->mode |= DMAPPEND;
11013e12c5d1SDavid du Colombier }
11027dd7cddfSDavid du Colombier
11039a747e4fSDavid du Colombier dp->uid = "bill";
11049a747e4fSDavid du Colombier dp->muid = "bill";
11059a747e4fSDavid du Colombier dp->gid = "trog";
11063e12c5d1SDavid du Colombier }
11073e12c5d1SDavid du Colombier
11083e12c5d1SDavid du Colombier void
11093e12c5d1SDavid du Colombier getname(char *p, Dosdir *d)
11103e12c5d1SDavid du Colombier {
11113e12c5d1SDavid du Colombier int c, i;
11123e12c5d1SDavid du Colombier
11133e12c5d1SDavid du Colombier for(i=0; i<8; i++){
11143e12c5d1SDavid du Colombier c = d->name[i];
11157dd7cddfSDavid du Colombier if(c == '\0' || c == ' ')
11163e12c5d1SDavid du Colombier break;
11173e12c5d1SDavid du Colombier if(i == 0 && c == 0x05)
11183e12c5d1SDavid du Colombier c = 0xe5;
11193e12c5d1SDavid du Colombier *p++ = c;
11203e12c5d1SDavid du Colombier }
11213e12c5d1SDavid du Colombier for(i=0; i<3; i++){
11223e12c5d1SDavid du Colombier c = d->ext[i];
11237dd7cddfSDavid du Colombier if(c == '\0' || c == ' ')
11243e12c5d1SDavid du Colombier break;
11253e12c5d1SDavid du Colombier if(i == 0)
11263e12c5d1SDavid du Colombier *p++ = '.';
11273e12c5d1SDavid du Colombier *p++ = c;
11283e12c5d1SDavid du Colombier }
11293e12c5d1SDavid du Colombier *p = 0;
11303e12c5d1SDavid du Colombier }
11313e12c5d1SDavid du Colombier
11327dd7cddfSDavid du Colombier static char*
11337dd7cddfSDavid du Colombier getnamerunes(char *dst, uchar *buf, int step)
11347dd7cddfSDavid du Colombier {
11357dd7cddfSDavid du Colombier int i;
11367dd7cddfSDavid du Colombier Rune r;
11377dd7cddfSDavid du Colombier char dbuf[DOSRUNE * UTFmax + 1], *d;
11387dd7cddfSDavid du Colombier
11397dd7cddfSDavid du Colombier d = dbuf;
11407dd7cddfSDavid du Colombier r = 1;
11417dd7cddfSDavid du Colombier for(i = 1; r && i < 11; i += 2){
11427dd7cddfSDavid du Colombier r = buf[i] | (buf[i+1] << 8);
11437dd7cddfSDavid du Colombier d += runetochar(d, &r);
11447dd7cddfSDavid du Colombier }
11457dd7cddfSDavid du Colombier for(i = 14; r && i < 26; i += 2){
11467dd7cddfSDavid du Colombier r = buf[i] | (buf[i+1] << 8);
11477dd7cddfSDavid du Colombier d += runetochar(d, &r);
11487dd7cddfSDavid du Colombier }
11497dd7cddfSDavid du Colombier for(i = 28; r && i < 32; i += 2){
11507dd7cddfSDavid du Colombier r = buf[i] | (buf[i+1] << 8);
11517dd7cddfSDavid du Colombier d += runetochar(d, &r);
11527dd7cddfSDavid du Colombier }
11537dd7cddfSDavid du Colombier
11547dd7cddfSDavid du Colombier if(step == 1)
11557dd7cddfSDavid du Colombier dst -= d - dbuf;
11567dd7cddfSDavid du Colombier
11577dd7cddfSDavid du Colombier memmove(dst, dbuf, d - dbuf);
11587dd7cddfSDavid du Colombier
11597dd7cddfSDavid du Colombier if(step == -1){
11607dd7cddfSDavid du Colombier dst += d - dbuf;
11617dd7cddfSDavid du Colombier *dst = '\0';
11627dd7cddfSDavid du Colombier }
11637dd7cddfSDavid du Colombier
11647dd7cddfSDavid du Colombier return dst;
11657dd7cddfSDavid du Colombier }
11667dd7cddfSDavid du Colombier
11677dd7cddfSDavid du Colombier char*
11687dd7cddfSDavid du Colombier getnamesect(char *dbuf, char *d, uchar *buf, int *islong, int *sum, int step)
11697dd7cddfSDavid du Colombier {
11707dd7cddfSDavid du Colombier /*
11717dd7cddfSDavid du Colombier * validation checks to make sure we're
11727dd7cddfSDavid du Colombier * making up a consistent name
11737dd7cddfSDavid du Colombier */
11747dd7cddfSDavid du Colombier if(buf[11] != 0xf || buf[12] != 0){
11757dd7cddfSDavid du Colombier *islong = 0;
11767dd7cddfSDavid du Colombier return nil;
11777dd7cddfSDavid du Colombier }
11787dd7cddfSDavid du Colombier if(step == 1){
11797dd7cddfSDavid du Colombier if((buf[0] & 0xc0) == 0x40){
11807dd7cddfSDavid du Colombier *islong = buf[0] & 0x3f;
11817dd7cddfSDavid du Colombier *sum = buf[13];
11827dd7cddfSDavid du Colombier d = dbuf + DOSNAMELEN;
11837dd7cddfSDavid du Colombier *--d = '\0';
11847dd7cddfSDavid du Colombier }else if(*islong && *islong == buf[0] + 1 && *sum == buf[13]){
11857dd7cddfSDavid du Colombier *islong = buf[0];
11867dd7cddfSDavid du Colombier }else{
11877dd7cddfSDavid du Colombier *islong = 0;
11887dd7cddfSDavid du Colombier return nil;
11897dd7cddfSDavid du Colombier }
11907dd7cddfSDavid du Colombier }else{
11917dd7cddfSDavid du Colombier if(*islong + 1 == (buf[0] & 0xbf) && *sum == buf[13]){
11927dd7cddfSDavid du Colombier *islong = buf[0] & 0x3f;
11937dd7cddfSDavid du Colombier if(buf[0] & 0x40)
11947dd7cddfSDavid du Colombier *sum = -1;
11957dd7cddfSDavid du Colombier }else{
11967dd7cddfSDavid du Colombier *islong = 0;
11977dd7cddfSDavid du Colombier *sum = -1;
11987dd7cddfSDavid du Colombier return nil;
11997dd7cddfSDavid du Colombier }
12007dd7cddfSDavid du Colombier }
12017dd7cddfSDavid du Colombier if(*islong > 20){
12027dd7cddfSDavid du Colombier *islong = 0;
12037dd7cddfSDavid du Colombier *sum = -1;
12047dd7cddfSDavid du Colombier return nil;
12057dd7cddfSDavid du Colombier }
12067dd7cddfSDavid du Colombier
12077dd7cddfSDavid du Colombier return getnamerunes(d, buf, step);
12087dd7cddfSDavid du Colombier }
12097dd7cddfSDavid du Colombier
12103e12c5d1SDavid du Colombier void
12113e12c5d1SDavid du Colombier putname(char *p, Dosdir *d)
12123e12c5d1SDavid du Colombier {
12133e12c5d1SDavid du Colombier int i;
12143e12c5d1SDavid du Colombier
12153e12c5d1SDavid du Colombier memset(d->name, ' ', sizeof d->name+sizeof d->ext);
12163e12c5d1SDavid du Colombier for(i=0; i<sizeof d->name; i++){
12173e12c5d1SDavid du Colombier if(*p == 0 || *p == '.')
12183e12c5d1SDavid du Colombier break;
12193e12c5d1SDavid du Colombier d->name[i] = toupper(*p++);
12203e12c5d1SDavid du Colombier }
12213e12c5d1SDavid du Colombier p = strrchr(p, '.');
12223e12c5d1SDavid du Colombier if(p){
12233e12c5d1SDavid du Colombier for(i=0; i<sizeof d->ext; i++){
12243e12c5d1SDavid du Colombier if(*++p == 0)
12253e12c5d1SDavid du Colombier break;
12263e12c5d1SDavid du Colombier d->ext[i] = toupper(*p);
12273e12c5d1SDavid du Colombier }
12283e12c5d1SDavid du Colombier }
12293e12c5d1SDavid du Colombier }
12303e12c5d1SDavid du Colombier
12317dd7cddfSDavid du Colombier static void
12327dd7cddfSDavid du Colombier putnamesect(uchar *slot, Rune *longname, int curslot, int first, int sum)
12337dd7cddfSDavid du Colombier {
12347dd7cddfSDavid du Colombier Rune r;
12357dd7cddfSDavid du Colombier Dosdir ds;
12367dd7cddfSDavid du Colombier int i, j;
12377dd7cddfSDavid du Colombier
12387dd7cddfSDavid du Colombier memset(&ds, 0xff, sizeof ds);
12397dd7cddfSDavid du Colombier ds.attr = 0xf;
12407dd7cddfSDavid du Colombier ds.reserved[0] = 0;
12417dd7cddfSDavid du Colombier ds.reserved[1] = sum;
12427dd7cddfSDavid du Colombier ds.start[0] = 0;
12437dd7cddfSDavid du Colombier ds.start[1] = 0;
12447dd7cddfSDavid du Colombier if(first)
12457dd7cddfSDavid du Colombier ds.name[0] = 0x40 | curslot;
12467dd7cddfSDavid du Colombier else
12477dd7cddfSDavid du Colombier ds.name[0] = curslot;
12487dd7cddfSDavid du Colombier memmove(slot, &ds, sizeof ds);
12497dd7cddfSDavid du Colombier
12507dd7cddfSDavid du Colombier j = (curslot-1) * DOSRUNE;
12517dd7cddfSDavid du Colombier
12527dd7cddfSDavid du Colombier for(i = 1; i < 11; i += 2){
12537dd7cddfSDavid du Colombier r = longname[j++];
12547dd7cddfSDavid du Colombier slot[i] = r;
12557dd7cddfSDavid du Colombier slot[i+1] = r >> 8;
12567dd7cddfSDavid du Colombier if(r == 0)
12577dd7cddfSDavid du Colombier return;
12587dd7cddfSDavid du Colombier }
12597dd7cddfSDavid du Colombier for(i = 14; i < 26; i += 2){
12607dd7cddfSDavid du Colombier r = longname[j++];
12617dd7cddfSDavid du Colombier slot[i] = r;
12627dd7cddfSDavid du Colombier slot[i+1] = r >> 8;
12637dd7cddfSDavid du Colombier if(r == 0)
12647dd7cddfSDavid du Colombier return;
12657dd7cddfSDavid du Colombier }
12667dd7cddfSDavid du Colombier for(i = 28; i < 32; i += 2){
12677dd7cddfSDavid du Colombier r = longname[j++];
12687dd7cddfSDavid du Colombier slot[i] = r;
12697dd7cddfSDavid du Colombier slot[i+1] = r >> 8;
12707dd7cddfSDavid du Colombier if(r == 0)
12717dd7cddfSDavid du Colombier return;
12727dd7cddfSDavid du Colombier }
12737dd7cddfSDavid du Colombier }
12747dd7cddfSDavid du Colombier
12757dd7cddfSDavid du Colombier int
12767dd7cddfSDavid du Colombier aliassum(Dosdir *d)
12777dd7cddfSDavid du Colombier {
12787dd7cddfSDavid du Colombier int i, sum;
12797dd7cddfSDavid du Colombier
12807dd7cddfSDavid du Colombier if(d == nil)
12817dd7cddfSDavid du Colombier return -1;
12827dd7cddfSDavid du Colombier sum = 0;
12837dd7cddfSDavid du Colombier for(i = 0; i < 11; i++)
12847dd7cddfSDavid du Colombier sum = (((sum&1)<<7) | ((sum&0xfe)>>1)) + d->name[i];
12857dd7cddfSDavid du Colombier return sum & 0xff;
12867dd7cddfSDavid du Colombier }
12877dd7cddfSDavid du Colombier
12887dd7cddfSDavid du Colombier int
12897dd7cddfSDavid du Colombier putlongname(Xfs *xf, Dosptr *ndp, char *name, char sname[13])
12907dd7cddfSDavid du Colombier {
12917dd7cddfSDavid du Colombier Dosbpb *bp;
12927dd7cddfSDavid du Colombier Dosdir tmpd;
12939a747e4fSDavid du Colombier Rune longname[DOSNAMELEN+1];
12949a747e4fSDavid du Colombier int i, first, sum, nds, len;
12957dd7cddfSDavid du Colombier
12967dd7cddfSDavid du Colombier /* calculate checksum */
12977dd7cddfSDavid du Colombier putname(sname, &tmpd);
12987dd7cddfSDavid du Colombier sum = aliassum(&tmpd);
12997dd7cddfSDavid du Colombier
13007dd7cddfSDavid du Colombier bp = xf->ptr;
13017dd7cddfSDavid du Colombier first = 1;
13029a747e4fSDavid du Colombier len = utftorunes(longname, name, DOSNAMELEN);
13039a747e4fSDavid du Colombier if(chatty){
13049a747e4fSDavid du Colombier chat("utftorunes %s =", name);
13059a747e4fSDavid du Colombier for(i=0; i<len; i++)
13069a747e4fSDavid du Colombier chat(" %.4X", longname[i]);
13079a747e4fSDavid du Colombier chat("\n");
13089a747e4fSDavid du Colombier }
13097dd7cddfSDavid du Colombier for(nds = (len + DOSRUNE-1) / DOSRUNE; nds > 0; nds--){
13107dd7cddfSDavid du Colombier putnamesect(&ndp->p->iobuf[ndp->offset], longname, nds, first, sum);
13117dd7cddfSDavid du Colombier first = 0;
13127dd7cddfSDavid du Colombier ndp->offset += 32;
13137dd7cddfSDavid du Colombier if(ndp->offset == bp->sectsize){
13147dd7cddfSDavid du Colombier chat("long name moving over sector boundary\n");
13157dd7cddfSDavid du Colombier ndp->p->flags |= BMOD;
13167dd7cddfSDavid du Colombier putsect(ndp->p);
13177dd7cddfSDavid du Colombier ndp->p = nil;
13187dd7cddfSDavid du Colombier
13197dd7cddfSDavid du Colombier /*
13207dd7cddfSDavid du Colombier * switch to the next cluster for a long entry
13217dd7cddfSDavid du Colombier * naddr should be set up correctly by searchdir
13227dd7cddfSDavid du Colombier */
13237dd7cddfSDavid du Colombier ndp->prevaddr = ndp->addr;
13247dd7cddfSDavid du Colombier ndp->addr = ndp->naddr;
13257dd7cddfSDavid du Colombier ndp->naddr = -1;
13267dd7cddfSDavid du Colombier if(ndp->addr == -1)
13277dd7cddfSDavid du Colombier return -1;
13287dd7cddfSDavid du Colombier ndp->p = getsect(xf, ndp->addr);
13297dd7cddfSDavid du Colombier if(ndp->p == nil)
13307dd7cddfSDavid du Colombier return -1;
13317dd7cddfSDavid du Colombier ndp->offset = 0;
13327dd7cddfSDavid du Colombier ndp->d = (Dosdir *)&ndp->p->iobuf[ndp->offset];
13337dd7cddfSDavid du Colombier }
13347dd7cddfSDavid du Colombier }
13357dd7cddfSDavid du Colombier return 0;
13367dd7cddfSDavid du Colombier }
13377dd7cddfSDavid du Colombier
13389a747e4fSDavid du Colombier long
13393e12c5d1SDavid du Colombier getfat(Xfs *xf, int n)
13403e12c5d1SDavid du Colombier {
13413e12c5d1SDavid du Colombier Dosbpb *bp = xf->ptr;
13427dd7cddfSDavid du Colombier Iosect *p;
13437dd7cddfSDavid du Colombier ulong k, sect;
13447dd7cddfSDavid du Colombier int o, fb;
13453e12c5d1SDavid du Colombier
13467dd7cddfSDavid du Colombier if(n < FATRESRV || n >= bp->fatclusters)
13473e12c5d1SDavid du Colombier return -1;
13487dd7cddfSDavid du Colombier fb = bp->fatbits;
13497dd7cddfSDavid du Colombier k = (fb * n) >> 3;
13503e12c5d1SDavid du Colombier if(k >= bp->fatsize*bp->sectsize)
13513e12c5d1SDavid du Colombier panic("getfat");
13523e12c5d1SDavid du Colombier sect = k/bp->sectsize + bp->fataddr;
13533e12c5d1SDavid du Colombier o = k%bp->sectsize;
13543e12c5d1SDavid du Colombier p = getsect(xf, sect);
13557dd7cddfSDavid du Colombier if(p == nil)
13563e12c5d1SDavid du Colombier return -1;
13573e12c5d1SDavid du Colombier k = p->iobuf[o++];
13583e12c5d1SDavid du Colombier if(o >= bp->sectsize){
13593e12c5d1SDavid du Colombier putsect(p);
13603e12c5d1SDavid du Colombier p = getsect(xf, sect+1);
13617dd7cddfSDavid du Colombier if(p == nil)
13623e12c5d1SDavid du Colombier return -1;
13633e12c5d1SDavid du Colombier o = 0;
13643e12c5d1SDavid du Colombier }
13657dd7cddfSDavid du Colombier k |= p->iobuf[o++]<<8;
13667dd7cddfSDavid du Colombier if(fb == 32){
13677dd7cddfSDavid du Colombier /* fat32 is really fat28 */
13687dd7cddfSDavid du Colombier k |= p->iobuf[o++] << 16;
13697dd7cddfSDavid du Colombier k |= (p->iobuf[o] & 0x0f) << 24;
13707dd7cddfSDavid du Colombier fb = 28;
13717dd7cddfSDavid du Colombier }
13723e12c5d1SDavid du Colombier putsect(p);
13737dd7cddfSDavid du Colombier if(fb == 12){
13743e12c5d1SDavid du Colombier if(n&1)
13753e12c5d1SDavid du Colombier k >>= 4;
13763e12c5d1SDavid du Colombier else
13773e12c5d1SDavid du Colombier k &= 0xfff;
13783e12c5d1SDavid du Colombier }
13793e12c5d1SDavid du Colombier if(chatty > 1)
13809a747e4fSDavid du Colombier chat("fat(%#x)=%#lx...", n, k);
13817dd7cddfSDavid du Colombier
13827dd7cddfSDavid du Colombier /*
13839a747e4fSDavid du Colombier * This is a very strange check for out of range.
13849a747e4fSDavid du Colombier * As a concrete example, for a 16-bit FAT,
13859a747e4fSDavid du Colombier * FFF8 through FFFF all signify ``end of cluster chain.''
13869a747e4fSDavid du Colombier * This generalizes to other-sized FATs.
13877dd7cddfSDavid du Colombier */
13889a747e4fSDavid du Colombier if(k >= (1 << fb) - 8)
13897dd7cddfSDavid du Colombier return -1;
13907dd7cddfSDavid du Colombier
13917dd7cddfSDavid du Colombier return k;
13923e12c5d1SDavid du Colombier }
13933e12c5d1SDavid du Colombier
13943e12c5d1SDavid du Colombier void
13957dd7cddfSDavid du Colombier putfat(Xfs *xf, int n, ulong val)
13963e12c5d1SDavid du Colombier {
13977dd7cddfSDavid du Colombier Fatinfo *fi;
13987dd7cddfSDavid du Colombier Dosbpb *bp;
13997dd7cddfSDavid du Colombier Iosect *p;
14007dd7cddfSDavid du Colombier ulong k, sect, esect;
14013e12c5d1SDavid du Colombier int o;
14023e12c5d1SDavid du Colombier
14037dd7cddfSDavid du Colombier bp = xf->ptr;
14047dd7cddfSDavid du Colombier if(n < FATRESRV || n >= bp->fatclusters)
14057dd7cddfSDavid du Colombier panic("putfat n=%d", n);
14067dd7cddfSDavid du Colombier k = (bp->fatbits * n) >> 3;
14073e12c5d1SDavid du Colombier if(k >= bp->fatsize*bp->sectsize)
14083e12c5d1SDavid du Colombier panic("putfat");
14093e12c5d1SDavid du Colombier sect = k/bp->sectsize + bp->fataddr;
14107dd7cddfSDavid du Colombier esect = sect + bp->nfats * bp->fatsize;
14117dd7cddfSDavid du Colombier for(; sect<esect; sect+=bp->fatsize){
14123e12c5d1SDavid du Colombier o = k%bp->sectsize;
14133e12c5d1SDavid du Colombier p = getsect(xf, sect);
14147dd7cddfSDavid du Colombier if(p == nil)
14153e12c5d1SDavid du Colombier continue;
14163e12c5d1SDavid du Colombier switch(bp->fatbits){
14173e12c5d1SDavid du Colombier case 12:
14183e12c5d1SDavid du Colombier if(n&1){
14193e12c5d1SDavid du Colombier p->iobuf[o] &= 0x0f;
14203e12c5d1SDavid du Colombier p->iobuf[o++] |= val<<4;
14213e12c5d1SDavid du Colombier if(o >= bp->sectsize){
14223e12c5d1SDavid du Colombier p->flags |= BMOD;
14233e12c5d1SDavid du Colombier putsect(p);
14243e12c5d1SDavid du Colombier p = getsect(xf, sect+1);
14257dd7cddfSDavid du Colombier if(p == nil)
14263e12c5d1SDavid du Colombier continue;
14273e12c5d1SDavid du Colombier o = 0;
14283e12c5d1SDavid du Colombier }
14293e12c5d1SDavid du Colombier p->iobuf[o] = val>>4;
14303e12c5d1SDavid du Colombier }else{
14313e12c5d1SDavid du Colombier p->iobuf[o++] = val;
14323e12c5d1SDavid du Colombier if(o >= bp->sectsize){
14333e12c5d1SDavid du Colombier p->flags |= BMOD;
14343e12c5d1SDavid du Colombier putsect(p);
14353e12c5d1SDavid du Colombier p = getsect(xf, sect+1);
14367dd7cddfSDavid du Colombier if(p == nil)
14373e12c5d1SDavid du Colombier continue;
14383e12c5d1SDavid du Colombier o = 0;
14393e12c5d1SDavid du Colombier }
14403e12c5d1SDavid du Colombier p->iobuf[o] &= 0xf0;
14413e12c5d1SDavid du Colombier p->iobuf[o] |= (val>>8) & 0x0f;
14423e12c5d1SDavid du Colombier }
14433e12c5d1SDavid du Colombier break;
14443e12c5d1SDavid du Colombier case 16:
14453e12c5d1SDavid du Colombier p->iobuf[o++] = val;
14463e12c5d1SDavid du Colombier p->iobuf[o] = val>>8;
14473e12c5d1SDavid du Colombier break;
14487dd7cddfSDavid du Colombier case 32: /* fat32 is really fat28 */
14497dd7cddfSDavid du Colombier p->iobuf[o++] = val;
14507dd7cddfSDavid du Colombier p->iobuf[o++] = val>>8;
14517dd7cddfSDavid du Colombier p->iobuf[o++] = val>>16;
14527dd7cddfSDavid du Colombier p->iobuf[o] = (p->iobuf[o] & 0xf0) | ((val>>24) & 0x0f);
14537dd7cddfSDavid du Colombier break;
14547dd7cddfSDavid du Colombier default:
14557dd7cddfSDavid du Colombier panic("putfat fatbits");
14563e12c5d1SDavid du Colombier }
14573e12c5d1SDavid du Colombier p->flags |= BMOD;
14583e12c5d1SDavid du Colombier putsect(p);
14593e12c5d1SDavid du Colombier }
14607dd7cddfSDavid du Colombier
14617dd7cddfSDavid du Colombier if(val == 0)
14627dd7cddfSDavid du Colombier bp->freeclusters++;
14637dd7cddfSDavid du Colombier else
14647dd7cddfSDavid du Colombier bp->freeclusters--;
14657dd7cddfSDavid du Colombier
14667dd7cddfSDavid du Colombier if(bp->fatinfo){
14677dd7cddfSDavid du Colombier p = getsect(xf, bp->fatinfo);
14687dd7cddfSDavid du Colombier if(p != nil){
14697dd7cddfSDavid du Colombier fi = (Fatinfo*)p->iobuf;
14709a747e4fSDavid du Colombier PLONG(fi->nextfree, bp->freeptr);
14719a747e4fSDavid du Colombier PLONG(fi->freeclust, bp->freeclusters);
14727dd7cddfSDavid du Colombier p->flags |= BMOD;
14737dd7cddfSDavid du Colombier putsect(p);
14747dd7cddfSDavid du Colombier }
14757dd7cddfSDavid du Colombier }
14767dd7cddfSDavid du Colombier }
14777dd7cddfSDavid du Colombier
14787dd7cddfSDavid du Colombier /*
14797dd7cddfSDavid du Colombier * Contiguous falloc; if we can, use lastclust+1.
14807dd7cddfSDavid du Colombier * Otherwise, move the file to get some space.
14817dd7cddfSDavid du Colombier * If there just isn't enough contiguous space
14827dd7cddfSDavid du Colombier * anywhere on disk, fail.
14837dd7cddfSDavid du Colombier */
14847dd7cddfSDavid du Colombier int
14857dd7cddfSDavid du Colombier cfalloc(Xfile *f)
14867dd7cddfSDavid du Colombier {
14877dd7cddfSDavid du Colombier int l;
14887dd7cddfSDavid du Colombier
14897dd7cddfSDavid du Colombier if((l=makecontig(f, 8)) >= 0)
14907dd7cddfSDavid du Colombier return l;
14917dd7cddfSDavid du Colombier return makecontig(f, 1);
14927dd7cddfSDavid du Colombier }
14937dd7cddfSDavid du Colombier
14947dd7cddfSDavid du Colombier /*
14957dd7cddfSDavid du Colombier * Check whether a file is contiguous.
14967dd7cddfSDavid du Colombier */
14977dd7cddfSDavid du Colombier int
14987dd7cddfSDavid du Colombier iscontig(Xfs *xf, Dosdir *d)
14997dd7cddfSDavid du Colombier {
15007dd7cddfSDavid du Colombier long clust, next;
15017dd7cddfSDavid du Colombier
15027dd7cddfSDavid du Colombier clust = getstart(xf, d);
15037dd7cddfSDavid du Colombier if(clust <= 0)
15047dd7cddfSDavid du Colombier return 1;
15057dd7cddfSDavid du Colombier
15067dd7cddfSDavid du Colombier for(;;) {
15077dd7cddfSDavid du Colombier next = getfat(xf, clust);
15087dd7cddfSDavid du Colombier if(next < 0)
15097dd7cddfSDavid du Colombier return 1;
15107dd7cddfSDavid du Colombier if(next != clust+1)
15117dd7cddfSDavid du Colombier return 0;
15127dd7cddfSDavid du Colombier clust = next;
15137dd7cddfSDavid du Colombier }
15147dd7cddfSDavid du Colombier }
15157dd7cddfSDavid du Colombier
15167dd7cddfSDavid du Colombier /*
15177dd7cddfSDavid du Colombier * Make a file contiguous, with nextra clusters of
15187dd7cddfSDavid du Colombier * free space after it for later expansion.
15197dd7cddfSDavid du Colombier * Return the number of the first new cluster.
15207dd7cddfSDavid du Colombier */
15217dd7cddfSDavid du Colombier int
15227dd7cddfSDavid du Colombier makecontig(Xfile *f, int nextra)
15237dd7cddfSDavid du Colombier {
15247dd7cddfSDavid du Colombier Dosbpb *bp;
15257dd7cddfSDavid du Colombier Dosdir *d;
15267dd7cddfSDavid du Colombier Dosptr *dp;
15277dd7cddfSDavid du Colombier Xfs *xf;
15287dd7cddfSDavid du Colombier Iosect *wp, *rp;
15297dd7cddfSDavid du Colombier long clust, next, last, start, rclust, wclust, eclust, ostart;
15309a747e4fSDavid du Colombier int isok, i, n, nclust, nrun, rs, ws;
15317dd7cddfSDavid du Colombier
15327dd7cddfSDavid du Colombier xf = f->xf;
15337dd7cddfSDavid du Colombier bp = xf->ptr;
15347dd7cddfSDavid du Colombier dp = f->ptr;
15357dd7cddfSDavid du Colombier d = dp->d;
15367dd7cddfSDavid du Colombier
15377dd7cddfSDavid du Colombier isok = 1;
15387dd7cddfSDavid du Colombier nclust = 0;
15397dd7cddfSDavid du Colombier clust = fileclust(f, 0, 0);
15409a747e4fSDavid du Colombier chat("clust %#lux", clust);
15417dd7cddfSDavid du Colombier if(clust != -1) {
15427dd7cddfSDavid du Colombier for(;;) {
15437dd7cddfSDavid du Colombier nclust++;
15447dd7cddfSDavid du Colombier chat(".");
15457dd7cddfSDavid du Colombier next = getfat(xf, clust);
15467dd7cddfSDavid du Colombier if(next <= 0)
15477dd7cddfSDavid du Colombier break;
15487dd7cddfSDavid du Colombier if(next != clust+1)
15497dd7cddfSDavid du Colombier isok = 0;
15507dd7cddfSDavid du Colombier clust = next;
15517dd7cddfSDavid du Colombier }
15527dd7cddfSDavid du Colombier }
15537dd7cddfSDavid du Colombier chat("nclust %d\n", nclust);
15547dd7cddfSDavid du Colombier
15557dd7cddfSDavid du Colombier if(isok && clust != -1) {
15567dd7cddfSDavid du Colombier eclust = clust+1; /* eclust = first cluster past file */
15577dd7cddfSDavid du Colombier assert(eclust == fileclust(f, 0, 0)+nclust);
15587dd7cddfSDavid du Colombier for(i=0; i<nextra; i++)
15597dd7cddfSDavid du Colombier if(getfat(xf, eclust+i) != 0)
15607dd7cddfSDavid du Colombier break;
15617dd7cddfSDavid du Colombier if(i == nextra) { /* they were all free */
15629a747e4fSDavid du Colombier chat("eclust=%#lx, getfat eclust-1 = %#lux\n", eclust, getfat(xf, eclust-1));
15637dd7cddfSDavid du Colombier assert(getfat(xf, eclust-1) == 0xffffffff);
15647dd7cddfSDavid du Colombier putfat(xf, eclust-1, eclust);
15657dd7cddfSDavid du Colombier putfat(xf, eclust, 0xffffffff);
15667dd7cddfSDavid du Colombier bp->freeptr = clust+1; /* to help keep the blocks free */
15677dd7cddfSDavid du Colombier return eclust;
15687dd7cddfSDavid du Colombier }
15697dd7cddfSDavid du Colombier }
15707dd7cddfSDavid du Colombier
15717dd7cddfSDavid du Colombier /* need to search for nclust+nextra contiguous free blocks */
15727dd7cddfSDavid du Colombier last = -1;
15737dd7cddfSDavid du Colombier n = bp->freeptr;
15747dd7cddfSDavid du Colombier nrun = 0;
15757dd7cddfSDavid du Colombier for(;;){
15767dd7cddfSDavid du Colombier if(getfat(xf, n) == 0) {
15777dd7cddfSDavid du Colombier if(last+1 == n)
15787dd7cddfSDavid du Colombier nrun++;
15797dd7cddfSDavid du Colombier else
15807dd7cddfSDavid du Colombier nrun = 1;
15817dd7cddfSDavid du Colombier if(nrun >= nclust+nextra)
15827dd7cddfSDavid du Colombier break;
15837dd7cddfSDavid du Colombier last = n;
15847dd7cddfSDavid du Colombier }
15857dd7cddfSDavid du Colombier if(++n >= bp->fatclusters)
15867dd7cddfSDavid du Colombier n = FATRESRV;
15877dd7cddfSDavid du Colombier if(n == bp->freeptr) {
15887dd7cddfSDavid du Colombier errno = Econtig;
15897dd7cddfSDavid du Colombier return -1;
15907dd7cddfSDavid du Colombier }
15917dd7cddfSDavid du Colombier }
15927dd7cddfSDavid du Colombier bp->freeptr = n+1;
15937dd7cddfSDavid du Colombier
15947dd7cddfSDavid du Colombier /* copy old data over */
15957dd7cddfSDavid du Colombier start = n+1 - nrun;
15967dd7cddfSDavid du Colombier
15977dd7cddfSDavid du Colombier /* sanity check */
15987dd7cddfSDavid du Colombier for(i=0; i<nclust+nextra; i++)
15997dd7cddfSDavid du Colombier assert(getfat(xf, start+i) == 0);
16007dd7cddfSDavid du Colombier
16019a747e4fSDavid du Colombier chat("relocate chain %lux -> 0x%lux len %d\n", fileclust(f, 0, 0), start, nclust);
16027dd7cddfSDavid du Colombier
16037dd7cddfSDavid du Colombier wclust = start;
16047dd7cddfSDavid du Colombier for(rclust = fileclust(f, 0, 0); rclust > 0; rclust = next){
16057dd7cddfSDavid du Colombier rs = clust2sect(bp, rclust);
16067dd7cddfSDavid du Colombier ws = clust2sect(bp, wclust);
16077dd7cddfSDavid du Colombier for(i=0; i<bp->clustsize; i++, rs++, ws++){
16087dd7cddfSDavid du Colombier rp = getsect(xf, rs);
16097dd7cddfSDavid du Colombier if(rp == nil)
16107dd7cddfSDavid du Colombier return -1;
16117dd7cddfSDavid du Colombier wp = getosect(xf, ws);
16127dd7cddfSDavid du Colombier assert(wp != nil);
16137dd7cddfSDavid du Colombier memmove(wp->iobuf, rp->iobuf, bp->sectsize);
16147dd7cddfSDavid du Colombier wp->flags = BMOD;
16157dd7cddfSDavid du Colombier putsect(rp);
16167dd7cddfSDavid du Colombier putsect(wp);
16177dd7cddfSDavid du Colombier }
16189a747e4fSDavid du Colombier chat("move cluster %#lx -> %#lx...", rclust, wclust);
16197dd7cddfSDavid du Colombier next = getfat(xf, rclust);
16207dd7cddfSDavid du Colombier putfat(xf, wclust, wclust+1);
16217dd7cddfSDavid du Colombier wclust++;
16227dd7cddfSDavid du Colombier }
16237dd7cddfSDavid du Colombier
16247dd7cddfSDavid du Colombier /* now wclust points at the first new cluster; chain it in */
16257dd7cddfSDavid du Colombier chat("wclust 0x%lux start 0x%lux (fat->0x%lux) nclust %d\n", wclust, start, getfat(xf, start), nclust);
16267dd7cddfSDavid du Colombier assert(wclust == start+nclust);
16277dd7cddfSDavid du Colombier putfat(xf, wclust, 0xffffffff); /* end of file */
16287dd7cddfSDavid du Colombier
16297dd7cddfSDavid du Colombier /* update directory entry to point at new start */
16307dd7cddfSDavid du Colombier ostart = fileclust(f, 0, 0);
16317dd7cddfSDavid du Colombier putstart(xf, d, start);
16327dd7cddfSDavid du Colombier
16337dd7cddfSDavid du Colombier /* check our work */
16347dd7cddfSDavid du Colombier i = 0;
16357dd7cddfSDavid du Colombier clust = fileclust(f, 0, 0);
16367dd7cddfSDavid du Colombier if(clust != -1) {
16377dd7cddfSDavid du Colombier for(;;) {
16387dd7cddfSDavid du Colombier i++;
16397dd7cddfSDavid du Colombier next = getfat(xf, clust);
16407dd7cddfSDavid du Colombier if(next <= 0)
16417dd7cddfSDavid du Colombier break;
16427dd7cddfSDavid du Colombier assert(next == clust+1);
16437dd7cddfSDavid du Colombier clust = next;
16447dd7cddfSDavid du Colombier }
16457dd7cddfSDavid du Colombier }
16467dd7cddfSDavid du Colombier chat("chain check: len %d\n", i);
16477dd7cddfSDavid du Colombier assert(i == nclust+1);
16487dd7cddfSDavid du Colombier
16497dd7cddfSDavid du Colombier /* succeeded; remove old chain. */
16507dd7cddfSDavid du Colombier for(rclust = ostart; rclust > 0; rclust = next){
16517dd7cddfSDavid du Colombier next = getfat(xf, rclust);
16527dd7cddfSDavid du Colombier putfat(xf, rclust, 0); /* free cluster */
16537dd7cddfSDavid du Colombier }
16547dd7cddfSDavid du Colombier
16557dd7cddfSDavid du Colombier return start+nclust;
16563e12c5d1SDavid du Colombier }
16573e12c5d1SDavid du Colombier
16583e12c5d1SDavid du Colombier int
16593e12c5d1SDavid du Colombier falloc(Xfs *xf)
16603e12c5d1SDavid du Colombier {
16613e12c5d1SDavid du Colombier Dosbpb *bp = xf->ptr;
16623e12c5d1SDavid du Colombier Iosect *p;
16639a747e4fSDavid du Colombier int n, i, k;
16643e12c5d1SDavid du Colombier
16653e12c5d1SDavid du Colombier n = bp->freeptr;
16663e12c5d1SDavid du Colombier for(;;){
16673e12c5d1SDavid du Colombier if(getfat(xf, n) == 0)
16683e12c5d1SDavid du Colombier break;
16693e12c5d1SDavid du Colombier if(++n >= bp->fatclusters)
16707dd7cddfSDavid du Colombier n = FATRESRV;
16713e12c5d1SDavid du Colombier if(n == bp->freeptr)
16723e12c5d1SDavid du Colombier return -1;
16733e12c5d1SDavid du Colombier }
16743e12c5d1SDavid du Colombier bp->freeptr = n+1;
16753e12c5d1SDavid du Colombier if(bp->freeptr >= bp->fatclusters)
16767dd7cddfSDavid du Colombier bp->freeptr = FATRESRV;
16777dd7cddfSDavid du Colombier putfat(xf, n, 0xffffffff);
16787dd7cddfSDavid du Colombier k = clust2sect(bp, n);
16793e12c5d1SDavid du Colombier for(i=0; i<bp->clustsize; i++){
16803e12c5d1SDavid du Colombier p = getosect(xf, k+i);
16813e12c5d1SDavid du Colombier memset(p->iobuf, 0, bp->sectsize);
16823e12c5d1SDavid du Colombier p->flags = BMOD;
16833e12c5d1SDavid du Colombier putsect(p);
16843e12c5d1SDavid du Colombier }
16853e12c5d1SDavid du Colombier return n;
16863e12c5d1SDavid du Colombier }
16873e12c5d1SDavid du Colombier
16883e12c5d1SDavid du Colombier void
16897dd7cddfSDavid du Colombier ffree(Xfs *xf, long start)
16903e12c5d1SDavid du Colombier {
16917dd7cddfSDavid du Colombier putfat(xf, start, 0);
16927dd7cddfSDavid du Colombier }
16933e12c5d1SDavid du Colombier
16947dd7cddfSDavid du Colombier long
16957dd7cddfSDavid du Colombier clust2sect(Dosbpb *bp, long clust)
16967dd7cddfSDavid du Colombier {
16977dd7cddfSDavid du Colombier return bp->dataaddr + (clust - FATRESRV) * bp->clustsize;
16987dd7cddfSDavid du Colombier }
16997dd7cddfSDavid du Colombier
17007dd7cddfSDavid du Colombier long
17017dd7cddfSDavid du Colombier sect2clust(Dosbpb *bp, long sect)
17027dd7cddfSDavid du Colombier {
17037dd7cddfSDavid du Colombier long c;
17047dd7cddfSDavid du Colombier
17057dd7cddfSDavid du Colombier c = (sect - bp->dataaddr) / bp->clustsize + FATRESRV;
17067dd7cddfSDavid du Colombier assert(sect == clust2sect(bp, c));
17077dd7cddfSDavid du Colombier return c;
17083e12c5d1SDavid du Colombier }
17093e12c5d1SDavid du Colombier
17103e12c5d1SDavid du Colombier void
1711219b2ee8SDavid du Colombier puttime(Dosdir *d, long s)
17123e12c5d1SDavid du Colombier {
1713219b2ee8SDavid du Colombier Tm *t;
17143e12c5d1SDavid du Colombier ushort x;
17153e12c5d1SDavid du Colombier
1716219b2ee8SDavid du Colombier if(s == 0)
1717219b2ee8SDavid du Colombier s = time(0);
1718219b2ee8SDavid du Colombier t = localtime(s);
1719219b2ee8SDavid du Colombier
17203e12c5d1SDavid du Colombier x = (t->hour<<11) | (t->min<<5) | (t->sec>>1);
17219a747e4fSDavid du Colombier PSHORT(d->time, x);
17223e12c5d1SDavid du Colombier x = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday;
17239a747e4fSDavid du Colombier PSHORT(d->date, x);
17243e12c5d1SDavid du Colombier }
17253e12c5d1SDavid du Colombier
17263e12c5d1SDavid du Colombier long
17273e12c5d1SDavid du Colombier gtime(Dosdir *dp)
17283e12c5d1SDavid du Colombier {
17297dd7cddfSDavid du Colombier Tm tm;
17307dd7cddfSDavid du Colombier int i;
17313e12c5d1SDavid du Colombier
17323e12c5d1SDavid du Colombier i = GSHORT(dp->time);
17337dd7cddfSDavid du Colombier tm.hour = i >> 11;
17347dd7cddfSDavid du Colombier tm.min = (i >> 5) & 63;
17357dd7cddfSDavid du Colombier tm.sec = (i & 31) << 1;
17363e12c5d1SDavid du Colombier i = GSHORT(dp->date);
17377dd7cddfSDavid du Colombier tm.year = 80 + (i >> 9);
17387dd7cddfSDavid du Colombier tm.mon = ((i >> 5) & 15) - 1;
17397dd7cddfSDavid du Colombier tm.mday = i & 31;
17407dd7cddfSDavid du Colombier tm.zone[0] = '\0';
17417dd7cddfSDavid du Colombier tm.tzoff = 0;
17426b6b9ac8SDavid du Colombier tm.yday = 0;
17433e12c5d1SDavid du Colombier
17447dd7cddfSDavid du Colombier return tm2sec(&tm);
17457dd7cddfSDavid du Colombier }
17467dd7cddfSDavid du Colombier
17477dd7cddfSDavid du Colombier /*
17487dd7cddfSDavid du Colombier * structure dumps for debugging
17497dd7cddfSDavid du Colombier */
17507dd7cddfSDavid du Colombier void
17517dd7cddfSDavid du Colombier bootdump(int fd, Dosboot *b)
17527dd7cddfSDavid du Colombier {
17537dd7cddfSDavid du Colombier Biobuf bp;
17547dd7cddfSDavid du Colombier
17557dd7cddfSDavid du Colombier Binit(&bp, fd, OWRITE);
17567dd7cddfSDavid du Colombier Bprint(&bp, "magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
17577dd7cddfSDavid du Colombier b->magic[0], b->magic[1], b->magic[2]);
17587dd7cddfSDavid du Colombier Bprint(&bp, "version: \"%8.8s\"\n", (char*)b->version);
17597dd7cddfSDavid du Colombier Bprint(&bp, "sectsize: %d\n", GSHORT(b->sectsize));
17607dd7cddfSDavid du Colombier Bprint(&bp, "clustsize: %d\n", b->clustsize);
17617dd7cddfSDavid du Colombier Bprint(&bp, "nresrv: %d\n", GSHORT(b->nresrv));
17627dd7cddfSDavid du Colombier Bprint(&bp, "nfats: %d\n", b->nfats);
17637dd7cddfSDavid du Colombier Bprint(&bp, "rootsize: %d\n", GSHORT(b->rootsize));
17647dd7cddfSDavid du Colombier Bprint(&bp, "volsize: %d\n", GSHORT(b->volsize));
17657dd7cddfSDavid du Colombier Bprint(&bp, "mediadesc: 0x%2.2x\n", b->mediadesc);
17667dd7cddfSDavid du Colombier Bprint(&bp, "fatsize: %d\n", GSHORT(b->fatsize));
17677dd7cddfSDavid du Colombier Bprint(&bp, "trksize: %d\n", GSHORT(b->trksize));
17687dd7cddfSDavid du Colombier Bprint(&bp, "nheads: %d\n", GSHORT(b->nheads));
17697dd7cddfSDavid du Colombier Bprint(&bp, "nhidden: %ld\n", GLONG(b->nhidden));
17707dd7cddfSDavid du Colombier Bprint(&bp, "bigvolsize: %ld\n", GLONG(b->bigvolsize));
17717dd7cddfSDavid du Colombier Bprint(&bp, "driveno: %d\n", b->driveno);
17727dd7cddfSDavid du Colombier Bprint(&bp, "reserved0: 0x%2.2x\n", b->reserved0);
17737dd7cddfSDavid du Colombier Bprint(&bp, "bootsig: 0x%2.2x\n", b->bootsig);
17747dd7cddfSDavid du Colombier Bprint(&bp, "volid: 0x%8.8lux\n", GLONG(b->volid));
17757dd7cddfSDavid du Colombier Bprint(&bp, "label: \"%11.11s\"\n", (char*)b->label);
17767dd7cddfSDavid du Colombier Bterm(&bp);
17773e12c5d1SDavid du Colombier }
17783e12c5d1SDavid du Colombier
17793e12c5d1SDavid du Colombier void
17807dd7cddfSDavid du Colombier bootdump32(int fd, Dosboot32 *b)
17817dd7cddfSDavid du Colombier {
17827dd7cddfSDavid du Colombier Biobuf bp;
17837dd7cddfSDavid du Colombier
17847dd7cddfSDavid du Colombier Binit(&bp, fd, OWRITE);
17857dd7cddfSDavid du Colombier Bprint(&bp, "magic: 0x%2.2x 0x%2.2x 0x%2.2x\n",
17867dd7cddfSDavid du Colombier b->magic[0], b->magic[1], b->magic[2]);
17877dd7cddfSDavid du Colombier Bprint(&bp, "version: \"%8.8s\"\n", (char*)b->version);
17887dd7cddfSDavid du Colombier Bprint(&bp, "sectsize: %d\n", GSHORT(b->sectsize));
17897dd7cddfSDavid du Colombier Bprint(&bp, "clustsize: %d\n", b->clustsize);
17907dd7cddfSDavid du Colombier Bprint(&bp, "nresrv: %d\n", GSHORT(b->nresrv));
17917dd7cddfSDavid du Colombier Bprint(&bp, "nfats: %d\n", b->nfats);
17927dd7cddfSDavid du Colombier Bprint(&bp, "rootsize: %d\n", GSHORT(b->rootsize));
17937dd7cddfSDavid du Colombier Bprint(&bp, "volsize: %d\n", GSHORT(b->volsize));
17947dd7cddfSDavid du Colombier Bprint(&bp, "mediadesc: 0x%2.2x\n", b->mediadesc);
17957dd7cddfSDavid du Colombier Bprint(&bp, "fatsize: %d\n", GSHORT(b->fatsize));
17967dd7cddfSDavid du Colombier Bprint(&bp, "trksize: %d\n", GSHORT(b->trksize));
17977dd7cddfSDavid du Colombier Bprint(&bp, "nheads: %d\n", GSHORT(b->nheads));
17987dd7cddfSDavid du Colombier Bprint(&bp, "nhidden: %ld\n", GLONG(b->nhidden));
17997dd7cddfSDavid du Colombier Bprint(&bp, "bigvolsize: %ld\n", GLONG(b->bigvolsize));
18007dd7cddfSDavid du Colombier Bprint(&bp, "fatsize32: %ld\n", GLONG(b->fatsize32));
18017dd7cddfSDavid du Colombier Bprint(&bp, "extflags: %d\n", GSHORT(b->extflags));
18027dd7cddfSDavid du Colombier Bprint(&bp, "version: %d\n", GSHORT(b->version1));
18037dd7cddfSDavid du Colombier Bprint(&bp, "rootstart: %ld\n", GLONG(b->rootstart));
18047dd7cddfSDavid du Colombier Bprint(&bp, "infospec: %d\n", GSHORT(b->infospec));
18057dd7cddfSDavid du Colombier Bprint(&bp, "backupboot: %d\n", GSHORT(b->backupboot));
18067dd7cddfSDavid du Colombier Bprint(&bp, "reserved: %d %d %d %d %d %d %d %d %d %d %d %d\n",
18077dd7cddfSDavid du Colombier b->reserved[0], b->reserved[1], b->reserved[2], b->reserved[3],
18087dd7cddfSDavid du Colombier b->reserved[4], b->reserved[5], b->reserved[6], b->reserved[7],
18097dd7cddfSDavid du Colombier b->reserved[8], b->reserved[9], b->reserved[10], b->reserved[11]);
18107dd7cddfSDavid du Colombier Bterm(&bp);
18117dd7cddfSDavid du Colombier }
18127dd7cddfSDavid du Colombier
18137dd7cddfSDavid du Colombier void
18147dd7cddfSDavid du Colombier bootsecdump32(int fd, Xfs *xf, Dosboot32 *b32)
18157dd7cddfSDavid du Colombier {
18167dd7cddfSDavid du Colombier Fatinfo *fi;
18177dd7cddfSDavid du Colombier Iosect *p1;
18187dd7cddfSDavid du Colombier int fisec, bsec, res;
18197dd7cddfSDavid du Colombier
18207dd7cddfSDavid du Colombier fprint(fd, "\nfat32\n");
18217dd7cddfSDavid du Colombier bootdump32(fd, b32);
18227dd7cddfSDavid du Colombier res = GSHORT(b32->nresrv);
18237dd7cddfSDavid du Colombier bsec = GSHORT(b32->backupboot);
18247dd7cddfSDavid du Colombier if(bsec < res && bsec != 0){
18257dd7cddfSDavid du Colombier p1 = getsect(xf, bsec);
18267dd7cddfSDavid du Colombier if(p1 == nil)
18277dd7cddfSDavid du Colombier fprint(fd, "\ncouldn't get backup boot sector: %r\n");
18287dd7cddfSDavid du Colombier else{
18297dd7cddfSDavid du Colombier fprint(fd, "\nbackup boot\n");
18307dd7cddfSDavid du Colombier bootdump32(fd, (Dosboot32*)p1->iobuf);
18317dd7cddfSDavid du Colombier putsect(p1);
18327dd7cddfSDavid du Colombier }
18337dd7cddfSDavid du Colombier }else if(bsec != 0xffff)
18347dd7cddfSDavid du Colombier fprint(fd, "bad backup boot sector: %d reserved %d\n", bsec, res);
18357dd7cddfSDavid du Colombier fisec = GSHORT(b32->infospec);
18367dd7cddfSDavid du Colombier if(fisec < res && fisec != 0){
18377dd7cddfSDavid du Colombier p1 = getsect(xf, fisec);
18387dd7cddfSDavid du Colombier if(p1 == nil)
18397dd7cddfSDavid du Colombier fprint(fd, "\ncouldn't get fat info sector: %r\n");
18407dd7cddfSDavid du Colombier else{
18417dd7cddfSDavid du Colombier fprint(fd, "\nfat info %d\n", fisec);
18427dd7cddfSDavid du Colombier fi = (Fatinfo*)p1->iobuf;
18437dd7cddfSDavid du Colombier fprint(fd, "sig1: 0x%lux sb 0x%lux\n", GLONG(fi->sig1), FATINFOSIG1);
18447dd7cddfSDavid du Colombier fprint(fd, "sig: 0x%lux sb 0x%lux\n", GLONG(fi->sig), FATINFOSIG);
18457dd7cddfSDavid du Colombier fprint(fd, "freeclust: %lud\n", GLONG(fi->freeclust));
18467dd7cddfSDavid du Colombier fprint(fd, "nextfree: %lud\n", GLONG(fi->nextfree));
18477dd7cddfSDavid du Colombier fprint(fd, "reserved: %lud %lud %lud\n", GLONG(fi->resrv), GLONG(fi->resrv+4), GLONG(fi->resrv+8));
18487dd7cddfSDavid du Colombier putsect(p1);
18497dd7cddfSDavid du Colombier }
18507dd7cddfSDavid du Colombier }else if(fisec != 0xffff)
18517dd7cddfSDavid du Colombier fprint(2, "bad fat info sector: %d reserved %d\n", bsec, res);
18527dd7cddfSDavid du Colombier }
18537dd7cddfSDavid du Colombier
18547dd7cddfSDavid du Colombier void
18557dd7cddfSDavid du Colombier dirdump(void *vdbuf)
18563e12c5d1SDavid du Colombier {
18573e12c5d1SDavid du Colombier static char attrchar[] = "rhsvda67";
18587dd7cddfSDavid du Colombier Dosdir *d;
18597dd7cddfSDavid du Colombier char *name, namebuf[DOSNAMELEN];
18607dd7cddfSDavid du Colombier char buf[128], *s, *ebuf;
18617dd7cddfSDavid du Colombier uchar *dbuf;
18627dd7cddfSDavid du Colombier int i;
18633e12c5d1SDavid du Colombier
18643e12c5d1SDavid du Colombier if(!chatty)
18653e12c5d1SDavid du Colombier return;
18667dd7cddfSDavid du Colombier
18677dd7cddfSDavid du Colombier d = vdbuf;
18687dd7cddfSDavid du Colombier
18697dd7cddfSDavid du Colombier ebuf = buf + sizeof(buf);
18707dd7cddfSDavid du Colombier if(d->attr == 0xf){
18717dd7cddfSDavid du Colombier dbuf = vdbuf;
18727dd7cddfSDavid du Colombier name = namebuf + DOSNAMELEN;
18737dd7cddfSDavid du Colombier *--name = '\0';
18747dd7cddfSDavid du Colombier name = getnamerunes(name, dbuf, 1);
18757dd7cddfSDavid du Colombier seprint(buf, ebuf, "\"%s\" %2.2x %2.2ux %2.2ux %d", name, dbuf[0], dbuf[12], dbuf[13], GSHORT(d->start));
18767dd7cddfSDavid du Colombier }else{
18777dd7cddfSDavid du Colombier s = seprint(buf, ebuf, "\"%.8s.%.3s\" ", (char*)d->name, (char*)d->ext);
18787dd7cddfSDavid du Colombier for(i=7; i>=0; i--)
18797dd7cddfSDavid du Colombier *s++ = d->attr&(1<<i) ? attrchar[i] : '-';
18807dd7cddfSDavid du Colombier
18813e12c5d1SDavid du Colombier i = GSHORT(d->time);
18827dd7cddfSDavid du Colombier s = seprint(s, ebuf, " %2.2d:%2.2d:%2.2d", i>>11, (i>>5)&63, (i&31)<<1);
18833e12c5d1SDavid du Colombier i = GSHORT(d->date);
18847dd7cddfSDavid du Colombier s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);
18857dd7cddfSDavid du Colombier
18867dd7cddfSDavid du Colombier i = GSHORT(d->ctime);
18877dd7cddfSDavid du Colombier s = seprint(s, ebuf, " %2.2d:%2.2d:%2.2d", i>>11, (i>>5)&63, (i&31)<<1);
18887dd7cddfSDavid du Colombier i = GSHORT(d->cdate);
18897dd7cddfSDavid du Colombier s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);
18907dd7cddfSDavid du Colombier
18917dd7cddfSDavid du Colombier i = GSHORT(d->adate);
18927dd7cddfSDavid du Colombier s = seprint(s, ebuf, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31);
18937dd7cddfSDavid du Colombier
18947dd7cddfSDavid du Colombier seprint(s, ebuf, " %d %d", GSHORT(d->start), GSHORT(d->length));
18957dd7cddfSDavid du Colombier }
18963e12c5d1SDavid du Colombier chat("%s\n", buf);
18973e12c5d1SDavid du Colombier }
18987dd7cddfSDavid du Colombier
18997dd7cddfSDavid du Colombier int
19007dd7cddfSDavid du Colombier cistrcmp(char *s1, char *s2)
19017dd7cddfSDavid du Colombier {
19027dd7cddfSDavid du Colombier int c1, c2;
19037dd7cddfSDavid du Colombier
19047dd7cddfSDavid du Colombier while(*s1){
19057dd7cddfSDavid du Colombier c1 = *s1++;
19067dd7cddfSDavid du Colombier c2 = *s2++;
19077dd7cddfSDavid du Colombier
19087dd7cddfSDavid du Colombier if(c1 >= 'A' && c1 <= 'Z')
19097dd7cddfSDavid du Colombier c1 -= 'A' - 'a';
19107dd7cddfSDavid du Colombier
19117dd7cddfSDavid du Colombier if(c2 >= 'A' && c2 <= 'Z')
19127dd7cddfSDavid du Colombier c2 -= 'A' - 'a';
19137dd7cddfSDavid du Colombier
19147dd7cddfSDavid du Colombier if(c1 != c2)
19157dd7cddfSDavid du Colombier return c1 - c2;
19167dd7cddfSDavid du Colombier }
19177dd7cddfSDavid du Colombier return -*s2;
19187dd7cddfSDavid du Colombier }
19197dd7cddfSDavid du Colombier
19207dd7cddfSDavid du Colombier int
19219a747e4fSDavid du Colombier utftorunes(Rune *rr, char *s, int n)
19227dd7cddfSDavid du Colombier {
19239a747e4fSDavid du Colombier Rune *r, *re;
19247dd7cddfSDavid du Colombier int c;
19257dd7cddfSDavid du Colombier
19267dd7cddfSDavid du Colombier r = rr;
19279a747e4fSDavid du Colombier re = r + n - 1;
19289a747e4fSDavid du Colombier while(c = (uchar)*s){
19297dd7cddfSDavid du Colombier if(c < Runeself){
19307dd7cddfSDavid du Colombier *r = c;
19317dd7cddfSDavid du Colombier s++;
19327dd7cddfSDavid du Colombier }else
19337dd7cddfSDavid du Colombier s += chartorune(r, s);
19347dd7cddfSDavid du Colombier r++;
19359a747e4fSDavid du Colombier if(r >= re)
19369a747e4fSDavid du Colombier break;
19377dd7cddfSDavid du Colombier }
19387dd7cddfSDavid du Colombier *r = 0;
19397dd7cddfSDavid du Colombier return r - rr;
19407dd7cddfSDavid du Colombier }
1941