17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <bio.h> 47dd7cddfSDavid du Colombier #include <auth.h> 57dd7cddfSDavid du Colombier #include <fcall.h> 67dd7cddfSDavid du Colombier #include <thread.h> 77dd7cddfSDavid du Colombier #include <9p.h> 87dd7cddfSDavid du Colombier 97dd7cddfSDavid du Colombier /* little endian */ 107dd7cddfSDavid du Colombier #define SHORT(p) (((uchar*)(p))[0] | (((uchar*)(p))[1] << 8)) 117dd7cddfSDavid du Colombier #define LONG(p) ((ulong)SHORT(p) |(((ulong)SHORT((p)+2)) << 16)) 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier typedef struct Ofile Ofile; 147dd7cddfSDavid du Colombier typedef struct Odir Odir; 157dd7cddfSDavid du Colombier 167dd7cddfSDavid du Colombier enum { 177dd7cddfSDavid du Colombier /* special block map entries */ 187dd7cddfSDavid du Colombier Bspecial = 0xFFFFFFFD, 197dd7cddfSDavid du Colombier Bendchain = 0xFFFFFFFE, 207dd7cddfSDavid du Colombier Bunused = 0xFFFFFFFF, 217dd7cddfSDavid du Colombier 227dd7cddfSDavid du Colombier Blocksize = 0x200, 237dd7cddfSDavid du Colombier 247dd7cddfSDavid du Colombier Odirsize = 0x80, 257dd7cddfSDavid du Colombier 267dd7cddfSDavid du Colombier /* Odir types */ 277dd7cddfSDavid du Colombier Tstorage = 1, 287dd7cddfSDavid du Colombier Tstream = 2, 297dd7cddfSDavid du Colombier Troot = 5, 307dd7cddfSDavid du Colombier }; 317dd7cddfSDavid du Colombier 327dd7cddfSDavid du Colombier /* 337dd7cddfSDavid du Colombier * the file consists of chains of blocks of size 0x200. 347dd7cddfSDavid du Colombier * to find what block follows block n, you look at 357dd7cddfSDavid du Colombier * blockmap[n]. that block follows it unless it is Bspecial 367dd7cddfSDavid du Colombier * or Bendchain. 377dd7cddfSDavid du Colombier * 387dd7cddfSDavid du Colombier * it's like the MS-DOS file system allocation tables. 397dd7cddfSDavid du Colombier */ 407dd7cddfSDavid du Colombier struct Ofile { 417dd7cddfSDavid du Colombier Biobuf *b; 427dd7cddfSDavid du Colombier ulong nblock; 437dd7cddfSDavid du Colombier ulong *blockmap; 447dd7cddfSDavid du Colombier ulong rootblock; 457dd7cddfSDavid du Colombier ulong smapblock; 467dd7cddfSDavid du Colombier ulong *smallmap; 477dd7cddfSDavid du Colombier }; 487dd7cddfSDavid du Colombier 497dd7cddfSDavid du Colombier /* Odir headers are found in directory listings in the Olefile */ 507dd7cddfSDavid du Colombier /* prev and next form a binary tree of directory entries */ 517dd7cddfSDavid du Colombier struct Odir { 527dd7cddfSDavid du Colombier Ofile *f; 537dd7cddfSDavid du Colombier Rune name[32+1]; 547dd7cddfSDavid du Colombier uchar type; 557dd7cddfSDavid du Colombier uchar isroot; 567dd7cddfSDavid du Colombier ulong left; 577dd7cddfSDavid du Colombier ulong right; 587dd7cddfSDavid du Colombier ulong dir; 597dd7cddfSDavid du Colombier ulong start; 607dd7cddfSDavid du Colombier ulong size; 617dd7cddfSDavid du Colombier }; 627dd7cddfSDavid du Colombier 637dd7cddfSDavid du Colombier void* 647dd7cddfSDavid du Colombier emalloc(ulong sz) 657dd7cddfSDavid du Colombier { 667dd7cddfSDavid du Colombier void *v; 677dd7cddfSDavid du Colombier 687dd7cddfSDavid du Colombier v = malloc(sz); 697dd7cddfSDavid du Colombier assert(v != nil); 707dd7cddfSDavid du Colombier return v; 717dd7cddfSDavid du Colombier } 727dd7cddfSDavid du Colombier 737dd7cddfSDavid du Colombier int 747dd7cddfSDavid du Colombier convM2OD(Odir *f, void *buf, int nbuf) 757dd7cddfSDavid du Colombier { 767dd7cddfSDavid du Colombier int i; 777dd7cddfSDavid du Colombier char *p; 787dd7cddfSDavid du Colombier int len; 797dd7cddfSDavid du Colombier 807dd7cddfSDavid du Colombier if(nbuf < Odirsize) 817dd7cddfSDavid du Colombier return -1; 827dd7cddfSDavid du Colombier 837dd7cddfSDavid du Colombier /* 847dd7cddfSDavid du Colombier * the short at 0x40 is the length of the name. 857dd7cddfSDavid du Colombier * when zero, it means there is no Odir here. 867dd7cddfSDavid du Colombier */ 877dd7cddfSDavid du Colombier p = buf; 887dd7cddfSDavid du Colombier len = SHORT(p+0x40); 897dd7cddfSDavid du Colombier if(len == 0) 907dd7cddfSDavid du Colombier return 0; 917dd7cddfSDavid du Colombier 927dd7cddfSDavid du Colombier if(len > 32) /* shouldn't happen */ 937dd7cddfSDavid du Colombier len = 32; 947dd7cddfSDavid du Colombier 957dd7cddfSDavid du Colombier for(i=0; i<len; i++) 967dd7cddfSDavid du Colombier f->name[i] = SHORT(p+i*2); 977dd7cddfSDavid du Colombier f->name[len] = 0; 987dd7cddfSDavid du Colombier 997dd7cddfSDavid du Colombier f->type = p[0x42]; 1007dd7cddfSDavid du Colombier f->left = LONG(p+0x44); 1017dd7cddfSDavid du Colombier f->right = LONG(p+0x48); 1027dd7cddfSDavid du Colombier f->dir = LONG(p+0x4C); 1037dd7cddfSDavid du Colombier f->start = LONG(p+0x74); 1047dd7cddfSDavid du Colombier f->size = LONG(p+0x78); 1057dd7cddfSDavid du Colombier 1067dd7cddfSDavid du Colombier /* BUG: grab time in ms format from here */ 1077dd7cddfSDavid du Colombier 1087dd7cddfSDavid du Colombier return 1; 1097dd7cddfSDavid du Colombier } 1107dd7cddfSDavid du Colombier 1117dd7cddfSDavid du Colombier int 1127dd7cddfSDavid du Colombier oreadblock(Ofile *f, int block, ulong off, char *buf, int nbuf) 1137dd7cddfSDavid du Colombier { 1147dd7cddfSDavid du Colombier if(block < 0 || block >= f->nblock) { 1157dd7cddfSDavid du Colombier werrstr("attempt to read %x/%lux\n", block, f->nblock); 1167dd7cddfSDavid du Colombier return -1; 1177dd7cddfSDavid du Colombier } 1187dd7cddfSDavid du Colombier 1197dd7cddfSDavid du Colombier if(off >= Blocksize) 1207dd7cddfSDavid du Colombier return 0; 1217dd7cddfSDavid du Colombier 1227dd7cddfSDavid du Colombier if(off+nbuf > Blocksize) 1237dd7cddfSDavid du Colombier nbuf = Blocksize-off; 1247dd7cddfSDavid du Colombier 1257dd7cddfSDavid du Colombier /* blocks start numbering at -1 [sic] */ 1267dd7cddfSDavid du Colombier off += (block+1)*Blocksize; 1277dd7cddfSDavid du Colombier 1287dd7cddfSDavid du Colombier if(Bseek(f->b, off, 0) != off) 1297dd7cddfSDavid du Colombier return -1; 1307dd7cddfSDavid du Colombier 1317dd7cddfSDavid du Colombier return Bread(f->b, buf, nbuf); 1327dd7cddfSDavid du Colombier } 1337dd7cddfSDavid du Colombier 1347dd7cddfSDavid du Colombier int 1357dd7cddfSDavid du Colombier chainlen(Ofile *f, ulong start) 1367dd7cddfSDavid du Colombier { 1377dd7cddfSDavid du Colombier int i; 1387dd7cddfSDavid du Colombier for(i=0; start < 0xFFFF0000; i++) 1397dd7cddfSDavid du Colombier start = f->blockmap[start]; 1407dd7cddfSDavid du Colombier 1417dd7cddfSDavid du Colombier return i; 1427dd7cddfSDavid du Colombier } 1437dd7cddfSDavid du Colombier 1447dd7cddfSDavid du Colombier /* 1457dd7cddfSDavid du Colombier * read nbuf bytes starting at offset off from the 1467dd7cddfSDavid du Colombier * chain whose first block is block. the chain is linked 1477dd7cddfSDavid du Colombier * together via the blockmap as described above, 1487dd7cddfSDavid du Colombier * like the MS-DOS file allocation tables. 1497dd7cddfSDavid du Colombier */ 1507dd7cddfSDavid du Colombier int 1517dd7cddfSDavid du Colombier oreadchain(Ofile *f, ulong block, int off, char *buf, int nbuf) 1527dd7cddfSDavid du Colombier { 1537dd7cddfSDavid du Colombier int i; 1547dd7cddfSDavid du Colombier int offblock; 1557dd7cddfSDavid du Colombier 1567dd7cddfSDavid du Colombier offblock = off/Blocksize; 1577dd7cddfSDavid du Colombier for(i=0; i<offblock && block < 0xFFFF0000; i++) 1587dd7cddfSDavid du Colombier block = f->blockmap[block]; 1597dd7cddfSDavid du Colombier return oreadblock(f, block, off%Blocksize, buf, nbuf); 1607dd7cddfSDavid du Colombier } 1617dd7cddfSDavid du Colombier 1627dd7cddfSDavid du Colombier int 1637dd7cddfSDavid du Colombier oreadfile(Odir *d, int off, char *buf, int nbuf) 1647dd7cddfSDavid du Colombier { 1657dd7cddfSDavid du Colombier /* 1667dd7cddfSDavid du Colombier * if d->size < 0x1000 then d->start refers 1677dd7cddfSDavid du Colombier * to a small depot block, else a big one. 1687dd7cddfSDavid du Colombier * if this is the root entry, it's a big one 1697dd7cddfSDavid du Colombier * no matter what. 1707dd7cddfSDavid du Colombier */ 1717dd7cddfSDavid du Colombier 1727dd7cddfSDavid du Colombier if(off >= d->size) 1737dd7cddfSDavid du Colombier return 0; 1747dd7cddfSDavid du Colombier if(off+nbuf > d->size) 1757dd7cddfSDavid du Colombier nbuf = d->size-off; 1767dd7cddfSDavid du Colombier 1777dd7cddfSDavid du Colombier if(d->size >= 0x1000 1787dd7cddfSDavid du Colombier || memcmp(d->name, L"Root Entry", 11*sizeof(Rune)) == 0) 1797dd7cddfSDavid du Colombier return oreadchain(d->f, d->start, off, buf, nbuf); 1807dd7cddfSDavid du Colombier else { /* small block */ 1817dd7cddfSDavid du Colombier off += d->start*64; 1827dd7cddfSDavid du Colombier return oreadchain(d->f, d->f->smapblock, off, buf, nbuf); 1837dd7cddfSDavid du Colombier } 1847dd7cddfSDavid du Colombier } 1857dd7cddfSDavid du Colombier 1867dd7cddfSDavid du Colombier int 1877dd7cddfSDavid du Colombier oreaddir(Ofile *f, int entry, Odir *d) 1887dd7cddfSDavid du Colombier { 1897dd7cddfSDavid du Colombier char buf[Odirsize]; 1907dd7cddfSDavid du Colombier 1917dd7cddfSDavid du Colombier if(oreadchain(f, f->rootblock, entry*Odirsize, buf, Odirsize) != Odirsize) 1927dd7cddfSDavid du Colombier return -1; 1937dd7cddfSDavid du Colombier 1947dd7cddfSDavid du Colombier d->f = f; 1957dd7cddfSDavid du Colombier return convM2OD(d, buf, Odirsize); 1967dd7cddfSDavid du Colombier } 1977dd7cddfSDavid du Colombier 1987dd7cddfSDavid du Colombier void 1997dd7cddfSDavid du Colombier dumpdir(Ofile *f, ulong dnum) 2007dd7cddfSDavid du Colombier { 2017dd7cddfSDavid du Colombier Odir d; 2027dd7cddfSDavid du Colombier 2037dd7cddfSDavid du Colombier if(oreaddir(f, dnum, &d) != 1) { 2047dd7cddfSDavid du Colombier fprint(2, "dumpdir %lux failed\n", dnum); 2057dd7cddfSDavid du Colombier return; 2067dd7cddfSDavid du Colombier } 2077dd7cddfSDavid du Colombier 2087dd7cddfSDavid du Colombier fprint(2, "%.8lux type %d size %lud l %.8lux r %.8lux d %.8lux (%S)\n", dnum, d.type, d.size, d.left, d.right, d.dir, d.name); 2097dd7cddfSDavid du Colombier if(d.left != (ulong)-1) 2107dd7cddfSDavid du Colombier dumpdir(f, d.left); 2117dd7cddfSDavid du Colombier if(d.right != (ulong)-1) 2127dd7cddfSDavid du Colombier dumpdir(f, d.right); 2137dd7cddfSDavid du Colombier if(d.dir != (ulong)-1) 2147dd7cddfSDavid du Colombier dumpdir(f, d.dir); 2157dd7cddfSDavid du Colombier } 2167dd7cddfSDavid du Colombier 2177dd7cddfSDavid du Colombier Ofile* 2187dd7cddfSDavid du Colombier oleopen(char *fn) 2197dd7cddfSDavid du Colombier { 2207dd7cddfSDavid du Colombier int i, j, k, block; 2217dd7cddfSDavid du Colombier int ndepot; 2227dd7cddfSDavid du Colombier ulong u; 2237dd7cddfSDavid du Colombier Odir rootdir; 2247dd7cddfSDavid du Colombier ulong extrablock; 2257dd7cddfSDavid du Colombier uchar buf[Blocksize]; 2267dd7cddfSDavid du Colombier 2277dd7cddfSDavid du Colombier Ofile *f; 2287dd7cddfSDavid du Colombier Biobuf *b; 2297dd7cddfSDavid du Colombier static char magic[] = { 2307dd7cddfSDavid du Colombier 0xD0, 0xCF, 0x11, 0xE0, 2317dd7cddfSDavid du Colombier 0xA1, 0xB1, 0x1A, 0xE1 2327dd7cddfSDavid du Colombier }; 2337dd7cddfSDavid du Colombier 2347dd7cddfSDavid du Colombier b = Bopen(fn, OREAD); 2357dd7cddfSDavid du Colombier if(b == nil) 2367dd7cddfSDavid du Colombier return nil; 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombier /* the first bytes are magic */ 2397dd7cddfSDavid du Colombier if(Bread(b, buf, sizeof magic) != sizeof magic 2407dd7cddfSDavid du Colombier || memcmp(buf, magic, sizeof magic) != 0) { 2417dd7cddfSDavid du Colombier werrstr("bad magic: not OLE file"); 2427dd7cddfSDavid du Colombier Bterm(b); 2437dd7cddfSDavid du Colombier return nil; 2447dd7cddfSDavid du Colombier } 2457dd7cddfSDavid du Colombier 2467dd7cddfSDavid du Colombier f = emalloc(sizeof *f); 2477dd7cddfSDavid du Colombier f->b = b; 2487dd7cddfSDavid du Colombier 2497dd7cddfSDavid du Colombier /* 2507dd7cddfSDavid du Colombier * the header contains a list of depots, which are 2517dd7cddfSDavid du Colombier * block maps. we assimilate them into one large map, 2527dd7cddfSDavid du Colombier * kept in main memory. 2537dd7cddfSDavid du Colombier */ 2547dd7cddfSDavid du Colombier Bseek(b, 0, 0); 2557dd7cddfSDavid du Colombier if(Bread(b, buf, Blocksize) != Blocksize) { 2567dd7cddfSDavid du Colombier Bterm(b); 2577dd7cddfSDavid du Colombier free(f); 2587dd7cddfSDavid du Colombier return nil; 2597dd7cddfSDavid du Colombier } 2607dd7cddfSDavid du Colombier 2617dd7cddfSDavid du Colombier ndepot = LONG(buf+0x2C); 2627dd7cddfSDavid du Colombier f->nblock = ndepot*(Blocksize/4); 2637dd7cddfSDavid du Colombier // fprint(2, "ndepot = %d f->nblock = %lud\n", ndepot, f->nblock); 2647dd7cddfSDavid du Colombier f->rootblock = LONG(buf+0x30); 2657dd7cddfSDavid du Colombier f->smapblock = LONG(buf+0x3C); 2667dd7cddfSDavid du Colombier f->blockmap = emalloc(sizeof(f->blockmap[0])*f->nblock); 2677dd7cddfSDavid du Colombier extrablock = LONG(buf+0x44); 2687dd7cddfSDavid du Colombier 2697dd7cddfSDavid du Colombier u = 0; 2707dd7cddfSDavid du Colombier 2717dd7cddfSDavid du Colombier /* the big block map fills to the end of the first 512-byte block */ 2727dd7cddfSDavid du Colombier for(i=0; i<ndepot && i<(0x200-0x4C)/4; i++) { 2737dd7cddfSDavid du Colombier if(Bseek(b, 0x4C+4*i, 0) != 0x4C+4*i 2747dd7cddfSDavid du Colombier || Bread(b, buf, 4) != 4) { 2757dd7cddfSDavid du Colombier print("bseek %d fail\n", 0x4C+4*i); 2767dd7cddfSDavid du Colombier goto Die; 2777dd7cddfSDavid du Colombier } 2787dd7cddfSDavid du Colombier block = LONG(buf); 2797dd7cddfSDavid du Colombier if((ulong)block == Bendchain) { 2807dd7cddfSDavid du Colombier ndepot = i; 2817dd7cddfSDavid du Colombier f->nblock = ndepot*(Blocksize/4); 2827dd7cddfSDavid du Colombier break; 2837dd7cddfSDavid du Colombier } 2847dd7cddfSDavid du Colombier 2857dd7cddfSDavid du Colombier if(Bseek(b, (block+1)*Blocksize, 0) != (block+1)*Blocksize) { 2867dd7cddfSDavid du Colombier print("Xbseek %d fail\n", (block+1)*Blocksize); 2877dd7cddfSDavid du Colombier goto Die; 2887dd7cddfSDavid du Colombier } 2897dd7cddfSDavid du Colombier for(j=0; j<Blocksize/4; j++) { 2907dd7cddfSDavid du Colombier if(Bread(b, buf, 4) != 4) { 2917dd7cddfSDavid du Colombier print("Bread fail seek block %x, %d i %d ndepot %d\n", block, (block+1)*Blocksize, i, ndepot); 2927dd7cddfSDavid du Colombier goto Die; 2937dd7cddfSDavid du Colombier } 2947dd7cddfSDavid du Colombier f->blockmap[u++] = LONG(buf); 2957dd7cddfSDavid du Colombier } 2967dd7cddfSDavid du Colombier } 2977dd7cddfSDavid du Colombier /* 2987dd7cddfSDavid du Colombier * if the first block can't hold it, it continues in the block at LONG(hdr+0x44). 2997dd7cddfSDavid du Colombier * if that in turn is not big enough, there's a next block number at the end of 3007dd7cddfSDavid du Colombier * each block. 3017dd7cddfSDavid du Colombier */ 3027dd7cddfSDavid du Colombier while(i < ndepot) { 3037dd7cddfSDavid du Colombier for(k=0; k<(0x200-4)/4 && i<ndepot; i++, k++) { 3047dd7cddfSDavid du Colombier if(Bseek(b, 0x200+extrablock*Blocksize+4*i, 0) != 0x200+extrablock*0x200+4*i 3057dd7cddfSDavid du Colombier || Bread(b, buf, 4) != 4) { 3067dd7cddfSDavid du Colombier print("bseek %d fail\n", 0x4C+4*i); 3077dd7cddfSDavid du Colombier goto Die; 3087dd7cddfSDavid du Colombier } 3097dd7cddfSDavid du Colombier block = LONG(buf); 3107dd7cddfSDavid du Colombier if((ulong)block == Bendchain) { 3117dd7cddfSDavid du Colombier ndepot = i; 3127dd7cddfSDavid du Colombier f->nblock = ndepot*(Blocksize/4); 3137dd7cddfSDavid du Colombier goto Break2; 3147dd7cddfSDavid du Colombier } 3157dd7cddfSDavid du Colombier 3167dd7cddfSDavid du Colombier if(Bseek(b, (block+1)*Blocksize, 0) != (block+1)*Blocksize) { 3177dd7cddfSDavid du Colombier print("Xbseek %d fail\n", (block+1)*Blocksize); 3187dd7cddfSDavid du Colombier goto Die; 3197dd7cddfSDavid du Colombier } 3207dd7cddfSDavid du Colombier for(j=0; j<Blocksize/4; j++) { 3217dd7cddfSDavid du Colombier if(Bread(b, buf, 4) != 4) { 3227dd7cddfSDavid du Colombier print("Bread fail seek block %x, %d i %d ndepot %d\n", block, (block+1)*Blocksize, i, ndepot); 3237dd7cddfSDavid du Colombier goto Die; 3247dd7cddfSDavid du Colombier } 3257dd7cddfSDavid du Colombier f->blockmap[u++] = LONG(buf); 3267dd7cddfSDavid du Colombier } 3277dd7cddfSDavid du Colombier } 3287dd7cddfSDavid du Colombier if(Bseek(b, 0x200+extrablock*Blocksize+Blocksize-4, 0) != 0x200+extrablock*Blocksize+Blocksize-4 3297dd7cddfSDavid du Colombier || Bread(b, buf, 4) != 4) { 3307dd7cddfSDavid du Colombier print("bseek %d fail\n", 0x4C+4*i); 3317dd7cddfSDavid du Colombier goto Die; 3327dd7cddfSDavid du Colombier } 3337dd7cddfSDavid du Colombier extrablock = LONG(buf); 3347dd7cddfSDavid du Colombier } 3357dd7cddfSDavid du Colombier Break2:; 3367dd7cddfSDavid du Colombier 3377dd7cddfSDavid du Colombier if(oreaddir(f, 0, &rootdir) <= 0) 3387dd7cddfSDavid du Colombier goto Die; 3397dd7cddfSDavid du Colombier 3407dd7cddfSDavid du Colombier f->smapblock = rootdir.start; 3417dd7cddfSDavid du Colombier return f; 3427dd7cddfSDavid du Colombier 3437dd7cddfSDavid du Colombier Die: 3447dd7cddfSDavid du Colombier Bterm(b); 3457dd7cddfSDavid du Colombier free(f->blockmap); 3467dd7cddfSDavid du Colombier free(f); 3477dd7cddfSDavid du Colombier return nil; 3487dd7cddfSDavid du Colombier } 3497dd7cddfSDavid du Colombier 3507dd7cddfSDavid du Colombier void 351*9a747e4fSDavid du Colombier oleread(Req *r) 3527dd7cddfSDavid du Colombier { 3537dd7cddfSDavid du Colombier Odir *d; 3547dd7cddfSDavid du Colombier char *p; 3557dd7cddfSDavid du Colombier int e, n; 3567dd7cddfSDavid du Colombier long c; 3577dd7cddfSDavid du Colombier vlong o; 3587dd7cddfSDavid du Colombier 359*9a747e4fSDavid du Colombier o = r->ifcall.offset; 360*9a747e4fSDavid du Colombier d = r->fid->file->aux; 3617dd7cddfSDavid du Colombier if(d == nil) { 3627dd7cddfSDavid du Colombier respond(r, "cannot happen"); 3637dd7cddfSDavid du Colombier return; 3647dd7cddfSDavid du Colombier } 3657dd7cddfSDavid du Colombier 366*9a747e4fSDavid du Colombier c = r->ifcall.count; 3677dd7cddfSDavid du Colombier 3687dd7cddfSDavid du Colombier if(o >= d->size) { 369*9a747e4fSDavid du Colombier r->ofcall.count = 0; 3707dd7cddfSDavid du Colombier respond(r, nil); 3717dd7cddfSDavid du Colombier return; 3727dd7cddfSDavid du Colombier } 3737dd7cddfSDavid du Colombier 3747dd7cddfSDavid du Colombier if(o+c > d->size) 3757dd7cddfSDavid du Colombier c = d->size-o; 3767dd7cddfSDavid du Colombier 3777dd7cddfSDavid du Colombier /* 3787dd7cddfSDavid du Colombier * oreadfile returns so little data, it will 3797dd7cddfSDavid du Colombier * help to read as much as we can. 3807dd7cddfSDavid du Colombier */ 3817dd7cddfSDavid du Colombier e = c+o; 3827dd7cddfSDavid du Colombier n = 0; 383*9a747e4fSDavid du Colombier for(p=r->ofcall.data; o<e; o+=n, p+=n) { 3847dd7cddfSDavid du Colombier n = oreadfile(d, o, p, e-o); 3857dd7cddfSDavid du Colombier if(n <= 0) 3867dd7cddfSDavid du Colombier break; 3877dd7cddfSDavid du Colombier } 3887dd7cddfSDavid du Colombier 389*9a747e4fSDavid du Colombier if(n == -1 && o == r->ifcall.offset) 3907dd7cddfSDavid du Colombier respond(r, "error reading word file"); 3917dd7cddfSDavid du Colombier else { 392*9a747e4fSDavid du Colombier r->ofcall.count = o - r->ifcall.offset; 3937dd7cddfSDavid du Colombier respond(r, nil); 3947dd7cddfSDavid du Colombier } 3957dd7cddfSDavid du Colombier } 3967dd7cddfSDavid du Colombier 3977dd7cddfSDavid du Colombier Odir* 3987dd7cddfSDavid du Colombier copydir(Odir *d) 3997dd7cddfSDavid du Colombier { 4007dd7cddfSDavid du Colombier Odir *e; 4017dd7cddfSDavid du Colombier 4027dd7cddfSDavid du Colombier e = emalloc(sizeof(*d)); 4037dd7cddfSDavid du Colombier *e = *d; 4047dd7cddfSDavid du Colombier return e; 4057dd7cddfSDavid du Colombier } 4067dd7cddfSDavid du Colombier 4077dd7cddfSDavid du Colombier void 4087dd7cddfSDavid du Colombier filldir(File *t, Ofile *f, int dnum, int nrecur) 4097dd7cddfSDavid du Colombier { 4107dd7cddfSDavid du Colombier Odir d; 4117dd7cddfSDavid du Colombier int i; 412*9a747e4fSDavid du Colombier Rune rbuf[40]; 413*9a747e4fSDavid du Colombier char buf[UTFmax*nelem(rbuf)]; 4147dd7cddfSDavid du Colombier File *nt; 4157dd7cddfSDavid du Colombier 4167dd7cddfSDavid du Colombier if(dnum == 0xFFFFFFFF || oreaddir(f, dnum, &d) != 1) 4177dd7cddfSDavid du Colombier return; 4187dd7cddfSDavid du Colombier 4197dd7cddfSDavid du Colombier /* 4207dd7cddfSDavid du Colombier * i hope there are no broken files with 4217dd7cddfSDavid du Colombier * circular trees. i hate infinite loops. 4227dd7cddfSDavid du Colombier */ 4237dd7cddfSDavid du Colombier if(nrecur > 100) 4247dd7cddfSDavid du Colombier sysfatal("tree too large in office file: probably circular"); 4257dd7cddfSDavid du Colombier 4267dd7cddfSDavid du Colombier filldir(t, f, d.left, nrecur+1); 4277dd7cddfSDavid du Colombier 4287dd7cddfSDavid du Colombier /* add current tree entry */ 429*9a747e4fSDavid du Colombier runestrecpy(rbuf, rbuf+sizeof rbuf, d.name); 430*9a747e4fSDavid du Colombier for(i=0; rbuf[i]; i++) 4317dd7cddfSDavid du Colombier if(rbuf[i] == L' ') 4327dd7cddfSDavid du Colombier rbuf[i] = L'␣'; 4337dd7cddfSDavid du Colombier else if(rbuf[i] <= 0x20 || rbuf[i] == L'/' 4347dd7cddfSDavid du Colombier || (0x80 <= rbuf[i] && rbuf[i] <= 0x9F)) 4357dd7cddfSDavid du Colombier rbuf[i] = ':'; 4367dd7cddfSDavid du Colombier 437*9a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%S", rbuf); 4387dd7cddfSDavid du Colombier 4397dd7cddfSDavid du Colombier if(d.dir == 0xFFFFFFFF) { 4407dd7cddfSDavid du Colombier /* make file */ 441*9a747e4fSDavid du Colombier nt = createfile(t, buf, nil, 0444, nil); 442*9a747e4fSDavid du Colombier if(nt ==nil) 443*9a747e4fSDavid du Colombier fprint(2, "nt nil: create %s: %r\n", buf); 4447dd7cddfSDavid du Colombier nt->aux = copydir(&d); 4457dd7cddfSDavid du Colombier nt->length = d.size; 4467dd7cddfSDavid du Colombier } else /* make directory */ 447*9a747e4fSDavid du Colombier nt = createfile(t, buf, nil, DMDIR|0777, nil); 4487dd7cddfSDavid du Colombier 4497dd7cddfSDavid du Colombier filldir(t, f, d.right, nrecur+1); 4507dd7cddfSDavid du Colombier 4517dd7cddfSDavid du Colombier if(d.dir != 0xFFFFFFFF) 4527dd7cddfSDavid du Colombier filldir(nt, f, d.dir, nrecur+1); 4537dd7cddfSDavid du Colombier 454*9a747e4fSDavid du Colombier closefile(nt); 4557dd7cddfSDavid du Colombier } 4567dd7cddfSDavid du Colombier 4577dd7cddfSDavid du Colombier Srv olesrv = { 4587dd7cddfSDavid du Colombier .read= oleread, 4597dd7cddfSDavid du Colombier }; 4607dd7cddfSDavid du Colombier 4617dd7cddfSDavid du Colombier void 4627dd7cddfSDavid du Colombier main(int argc, char **argv) 4637dd7cddfSDavid du Colombier { 4647dd7cddfSDavid du Colombier char *mtpt; 4657dd7cddfSDavid du Colombier Ofile *f; 4667dd7cddfSDavid du Colombier Odir d; 4677dd7cddfSDavid du Colombier 4687dd7cddfSDavid du Colombier mtpt = "/mnt/doc"; 4697dd7cddfSDavid du Colombier ARGBEGIN{ 4707dd7cddfSDavid du Colombier case 'm': 4717dd7cddfSDavid du Colombier mtpt = ARGF(); 4727dd7cddfSDavid du Colombier break; 4737dd7cddfSDavid du Colombier 4747dd7cddfSDavid du Colombier default: 4757dd7cddfSDavid du Colombier goto Usage; 4767dd7cddfSDavid du Colombier }ARGEND 4777dd7cddfSDavid du Colombier 4787dd7cddfSDavid du Colombier if(argc != 1) { 4797dd7cddfSDavid du Colombier Usage: 4807dd7cddfSDavid du Colombier fprint(2, "usage: olefs file\n"); 4817dd7cddfSDavid du Colombier exits("usage"); 4827dd7cddfSDavid du Colombier } 4837dd7cddfSDavid du Colombier 4847dd7cddfSDavid du Colombier f = oleopen(argv[0]); 4857dd7cddfSDavid du Colombier if(f == nil) { 4867dd7cddfSDavid du Colombier print("error: %r\n"); 4877dd7cddfSDavid du Colombier exits("open"); 4887dd7cddfSDavid du Colombier } 4897dd7cddfSDavid du Colombier 4907dd7cddfSDavid du Colombier // dumpdir(f, 0); 4917dd7cddfSDavid du Colombier 4927dd7cddfSDavid du Colombier if(oreaddir(f, 0, &d) != 1) { 4937dd7cddfSDavid du Colombier fprint(2, "oreaddir error: %r\n"); 4947dd7cddfSDavid du Colombier exits("oreaddir"); 4957dd7cddfSDavid du Colombier } 4967dd7cddfSDavid du Colombier 497*9a747e4fSDavid du Colombier olesrv.tree = alloctree(nil, nil, DMDIR|0777, nil); 4987dd7cddfSDavid du Colombier filldir(olesrv.tree->root, f, d.dir, 0); 4997dd7cddfSDavid du Colombier postmountsrv(&olesrv, nil, mtpt, MREPL); 5007dd7cddfSDavid du Colombier exits(0); 5017dd7cddfSDavid du Colombier } 502