15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier #include "dat.h"
35e96a66cSDavid du Colombier #include "fns.h"
4fe853e23SDavid du Colombier #include "flfmt9660.h"
55e96a66cSDavid du Colombier
65e96a66cSDavid du Colombier #define blockWrite _blockWrite /* hack */
75e96a66cSDavid du Colombier
85e96a66cSDavid du Colombier static void usage(void);
95e96a66cSDavid du Colombier static u64int fdsize(int fd);
105e96a66cSDavid du Colombier static void partition(int fd, int bsize, Header *h);
115e96a66cSDavid du Colombier static u64int unittoull(char *s);
125e96a66cSDavid du Colombier static u32int blockAlloc(int type, u32int tag);
135e96a66cSDavid du Colombier static void blockRead(int part, u32int addr);
145e96a66cSDavid du Colombier static void blockWrite(int part, u32int addr);
157abd426fSDavid du Colombier static void superInit(char *label, u32int root, uchar[VtScoreSize]);
165e96a66cSDavid du Colombier static void rootMetaInit(Entry *e);
175e96a66cSDavid du Colombier static u32int rootInit(Entry *e);
185e96a66cSDavid du Colombier static void topLevel(char *name);
195e96a66cSDavid du Colombier static int parseScore(uchar[VtScoreSize], char*);
205e96a66cSDavid du Colombier static u32int ventiRoot(char*, char*);
21*d7aba6c3SDavid du Colombier static VtConn *z;
225e96a66cSDavid du Colombier
235e96a66cSDavid du Colombier #define TWID64 ((u64int)~(u64int)0)
245e96a66cSDavid du Colombier
255e96a66cSDavid du Colombier Disk *disk;
265e96a66cSDavid du Colombier Fs *fs;
275e96a66cSDavid du Colombier uchar *buf;
285e96a66cSDavid du Colombier int bsize = 8*1024;
295e96a66cSDavid du Colombier u64int qid = 1;
30fe853e23SDavid du Colombier int iso9660off;
31fe853e23SDavid du Colombier char *iso9660file;
325e96a66cSDavid du Colombier
335e96a66cSDavid du Colombier int
confirm(char * msg)345e96a66cSDavid du Colombier confirm(char *msg)
355e96a66cSDavid du Colombier {
365e96a66cSDavid du Colombier char buf[100];
375e96a66cSDavid du Colombier int n;
385e96a66cSDavid du Colombier
395e96a66cSDavid du Colombier fprint(2, "%s [y/n]: ", msg);
405e96a66cSDavid du Colombier n = read(0, buf, sizeof buf - 1);
415e96a66cSDavid du Colombier if(n <= 0)
425e96a66cSDavid du Colombier return 0;
435e96a66cSDavid du Colombier if(buf[0] == 'y')
445e96a66cSDavid du Colombier return 1;
455e96a66cSDavid du Colombier return 0;
465e96a66cSDavid du Colombier }
475e96a66cSDavid du Colombier
485e96a66cSDavid du Colombier void
threadmain(int argc,char * argv[])49*d7aba6c3SDavid du Colombier threadmain(int argc, char *argv[])
505e96a66cSDavid du Colombier {
515e96a66cSDavid du Colombier int fd, force;
525e96a66cSDavid du Colombier Header h;
535e96a66cSDavid du Colombier ulong bn;
545e96a66cSDavid du Colombier Entry e;
555e96a66cSDavid du Colombier char *label = "vfs";
565e96a66cSDavid du Colombier char *host = nil;
575e96a66cSDavid du Colombier char *score = nil;
585e96a66cSDavid du Colombier u32int root;
595e96a66cSDavid du Colombier Dir *d;
605e96a66cSDavid du Colombier
615e96a66cSDavid du Colombier force = 0;
625e96a66cSDavid du Colombier ARGBEGIN{
635e96a66cSDavid du Colombier default:
645e96a66cSDavid du Colombier usage();
655e96a66cSDavid du Colombier case 'b':
665e96a66cSDavid du Colombier bsize = unittoull(EARGF(usage()));
675e96a66cSDavid du Colombier if(bsize == ~0)
685e96a66cSDavid du Colombier usage();
695e96a66cSDavid du Colombier break;
705e96a66cSDavid du Colombier case 'h':
715e96a66cSDavid du Colombier host = EARGF(usage());
725e96a66cSDavid du Colombier break;
73fe853e23SDavid du Colombier case 'i':
74fe853e23SDavid du Colombier iso9660file = EARGF(usage());
75fe853e23SDavid du Colombier iso9660off = atoi(EARGF(usage()));
76fe853e23SDavid du Colombier break;
775e96a66cSDavid du Colombier case 'l':
785e96a66cSDavid du Colombier label = EARGF(usage());
795e96a66cSDavid du Colombier break;
805e96a66cSDavid du Colombier case 'v':
815e96a66cSDavid du Colombier score = EARGF(usage());
825e96a66cSDavid du Colombier break;
835e96a66cSDavid du Colombier
845e96a66cSDavid du Colombier /*
855e96a66cSDavid du Colombier * This is -y instead of -f because flchk has a
865e96a66cSDavid du Colombier * (frequently used) -f option. I type flfmt instead
875e96a66cSDavid du Colombier * of flchk all the time, and want to make it hard
885e96a66cSDavid du Colombier * to reformat my file system accidentally.
895e96a66cSDavid du Colombier */
905e96a66cSDavid du Colombier case 'y':
915e96a66cSDavid du Colombier force = 1;
925e96a66cSDavid du Colombier break;
935e96a66cSDavid du Colombier }ARGEND
945e96a66cSDavid du Colombier
955e96a66cSDavid du Colombier if(argc != 1)
965e96a66cSDavid du Colombier usage();
975e96a66cSDavid du Colombier
98fe853e23SDavid du Colombier if(iso9660file && score)
99*d7aba6c3SDavid du Colombier sysfatal("cannot use -i with -v");
1005e96a66cSDavid du Colombier
1015e96a66cSDavid du Colombier fmtinstall('V', scoreFmt);
1025e96a66cSDavid du Colombier fmtinstall('L', labelFmt);
1035e96a66cSDavid du Colombier
1045e96a66cSDavid du Colombier fd = open(argv[0], ORDWR);
1055e96a66cSDavid du Colombier if(fd < 0)
106*d7aba6c3SDavid du Colombier sysfatal("could not open file: %s: %r", argv[0]);
1075e96a66cSDavid du Colombier
108*d7aba6c3SDavid du Colombier buf = vtmallocz(bsize);
1095e96a66cSDavid du Colombier if(pread(fd, buf, bsize, HeaderOffset) != bsize)
110*d7aba6c3SDavid du Colombier sysfatal("could not read fs header block: %r");
1115e96a66cSDavid du Colombier
1125e96a66cSDavid du Colombier if(headerUnpack(&h, buf) && !force
1135e96a66cSDavid du Colombier && !confirm("fs header block already exists; are you sure?"))
1145e96a66cSDavid du Colombier goto Out;
1155e96a66cSDavid du Colombier
1165e96a66cSDavid du Colombier if((d = dirfstat(fd)) == nil)
117*d7aba6c3SDavid du Colombier sysfatal("dirfstat: %r");
1185e96a66cSDavid du Colombier
1195e96a66cSDavid du Colombier if(d->type == 'M' && !force
1205e96a66cSDavid du Colombier && !confirm("fs file is mounted via devmnt (is not a kernel device); are you sure?"))
1215e96a66cSDavid du Colombier goto Out;
1225e96a66cSDavid du Colombier
1235e96a66cSDavid du Colombier partition(fd, bsize, &h);
1245e96a66cSDavid du Colombier headerPack(&h, buf);
1255e96a66cSDavid du Colombier if(pwrite(fd, buf, bsize, HeaderOffset) < bsize)
126*d7aba6c3SDavid du Colombier sysfatal("could not write fs header: %r");
1275e96a66cSDavid du Colombier
1285e96a66cSDavid du Colombier disk = diskAlloc(fd);
1295e96a66cSDavid du Colombier if(disk == nil)
130*d7aba6c3SDavid du Colombier sysfatal("could not open disk: %r");
1315e96a66cSDavid du Colombier
132fe853e23SDavid du Colombier if(iso9660file)
133fe853e23SDavid du Colombier iso9660init(fd, &h, iso9660file, iso9660off);
134fe853e23SDavid du Colombier
1355e96a66cSDavid du Colombier /* zero labels */
1365e96a66cSDavid du Colombier memset(buf, 0, bsize);
1375e96a66cSDavid du Colombier for(bn = 0; bn < diskSize(disk, PartLabel); bn++)
1385e96a66cSDavid du Colombier blockWrite(PartLabel, bn);
1395e96a66cSDavid du Colombier
140fe853e23SDavid du Colombier if(iso9660file)
141fe853e23SDavid du Colombier iso9660labels(disk, buf, blockWrite);
142fe853e23SDavid du Colombier
1435e96a66cSDavid du Colombier if(score)
1445e96a66cSDavid du Colombier root = ventiRoot(host, score);
1455e96a66cSDavid du Colombier else{
1465e96a66cSDavid du Colombier rootMetaInit(&e);
1475e96a66cSDavid du Colombier root = rootInit(&e);
1485e96a66cSDavid du Colombier }
1495e96a66cSDavid du Colombier
150*d7aba6c3SDavid du Colombier superInit(label, root, vtzeroscore);
1515e96a66cSDavid du Colombier diskFree(disk);
1525e96a66cSDavid du Colombier
153e6c6b7f8SDavid du Colombier if(score == nil)
1545e96a66cSDavid du Colombier topLevel(argv[0]);
1555e96a66cSDavid du Colombier
1565e96a66cSDavid du Colombier Out:
157*d7aba6c3SDavid du Colombier threadexitsall(0);
1585e96a66cSDavid du Colombier }
1595e96a66cSDavid du Colombier
1605e96a66cSDavid du Colombier static u64int
fdsize(int fd)1615e96a66cSDavid du Colombier fdsize(int fd)
1625e96a66cSDavid du Colombier {
1635e96a66cSDavid du Colombier Dir *dir;
1645e96a66cSDavid du Colombier u64int size;
1655e96a66cSDavid du Colombier
1665e96a66cSDavid du Colombier dir = dirfstat(fd);
1675e96a66cSDavid du Colombier if(dir == nil)
168*d7aba6c3SDavid du Colombier sysfatal("could not stat file: %r");
1695e96a66cSDavid du Colombier size = dir->length;
1705e96a66cSDavid du Colombier free(dir);
1715e96a66cSDavid du Colombier return size;
1725e96a66cSDavid du Colombier }
1735e96a66cSDavid du Colombier
1745e96a66cSDavid du Colombier static void
usage(void)1755e96a66cSDavid du Colombier usage(void)
1765e96a66cSDavid du Colombier {
1770c6300e7SDavid du Colombier fprint(2, "usage: %s [-b blocksize] [-h host] [-i file offset] "
1780c6300e7SDavid du Colombier "[-l label] [-v score] [-y] file\n", argv0);
179*d7aba6c3SDavid du Colombier threadexitsall("usage");
1805e96a66cSDavid du Colombier }
1815e96a66cSDavid du Colombier
1825e96a66cSDavid du Colombier static void
partition(int fd,int bsize,Header * h)1835e96a66cSDavid du Colombier partition(int fd, int bsize, Header *h)
1845e96a66cSDavid du Colombier {
1855e96a66cSDavid du Colombier ulong nblock, ndata, nlabel;
1865e96a66cSDavid du Colombier ulong lpb;
1875e96a66cSDavid du Colombier
1885e96a66cSDavid du Colombier if(bsize % 512 != 0)
1895e96a66cSDavid du Colombier sysfatal("block size must be a multiple of 512 bytes");
1905e96a66cSDavid du Colombier if(bsize > VtMaxLumpSize)
1915e96a66cSDavid du Colombier sysfatal("block size must be less than %d", VtMaxLumpSize);
1925e96a66cSDavid du Colombier
1935e96a66cSDavid du Colombier memset(h, 0, sizeof(*h));
1945e96a66cSDavid du Colombier h->blockSize = bsize;
1955e96a66cSDavid du Colombier
1965e96a66cSDavid du Colombier lpb = bsize/LabelSize;
1975e96a66cSDavid du Colombier
1985e96a66cSDavid du Colombier nblock = fdsize(fd)/bsize;
1995e96a66cSDavid du Colombier
2005e96a66cSDavid du Colombier /* sanity check */
2015e96a66cSDavid du Colombier if(nblock < (HeaderOffset*10)/bsize)
202*d7aba6c3SDavid du Colombier sysfatal("file too small");
2035e96a66cSDavid du Colombier
2045e96a66cSDavid du Colombier h->super = (HeaderOffset + 2*bsize)/bsize;
2055e96a66cSDavid du Colombier h->label = h->super + 1;
2065e96a66cSDavid du Colombier ndata = ((u64int)lpb)*(nblock - h->label)/(lpb+1);
2075e96a66cSDavid du Colombier nlabel = (ndata + lpb - 1)/lpb;
2085e96a66cSDavid du Colombier h->data = h->label + nlabel;
2095e96a66cSDavid du Colombier h->end = h->data + ndata;
2105e96a66cSDavid du Colombier
2115e96a66cSDavid du Colombier }
2125e96a66cSDavid du Colombier
2135e96a66cSDavid du Colombier static u32int
tagGen(void)2145e96a66cSDavid du Colombier tagGen(void)
2155e96a66cSDavid du Colombier {
2165e96a66cSDavid du Colombier u32int tag;
2175e96a66cSDavid du Colombier
2185e96a66cSDavid du Colombier for(;;){
2195e96a66cSDavid du Colombier tag = lrand();
2205e96a66cSDavid du Colombier if(tag > RootTag)
2215e96a66cSDavid du Colombier break;
2225e96a66cSDavid du Colombier }
2235e96a66cSDavid du Colombier return tag;
2245e96a66cSDavid du Colombier }
2255e96a66cSDavid du Colombier
2265e96a66cSDavid du Colombier static void
entryInit(Entry * e)2275e96a66cSDavid du Colombier entryInit(Entry *e)
2285e96a66cSDavid du Colombier {
2295e96a66cSDavid du Colombier e->gen = 0;
2305e96a66cSDavid du Colombier e->dsize = bsize;
2315e96a66cSDavid du Colombier e->psize = bsize/VtEntrySize*VtEntrySize;
2325e96a66cSDavid du Colombier e->flags = VtEntryActive;
2335e96a66cSDavid du Colombier e->depth = 0;
2345e96a66cSDavid du Colombier e->size = 0;
235*d7aba6c3SDavid du Colombier memmove(e->score, vtzeroscore, VtScoreSize);
2365e96a66cSDavid du Colombier e->tag = tagGen();
2375e96a66cSDavid du Colombier e->snap = 0;
2385e96a66cSDavid du Colombier e->archive = 0;
2395e96a66cSDavid du Colombier }
2405e96a66cSDavid du Colombier
2415e96a66cSDavid du Colombier static void
rootMetaInit(Entry * e)2425e96a66cSDavid du Colombier rootMetaInit(Entry *e)
2435e96a66cSDavid du Colombier {
2445e96a66cSDavid du Colombier u32int addr;
2455e96a66cSDavid du Colombier u32int tag;
2465e96a66cSDavid du Colombier DirEntry de;
2475e96a66cSDavid du Colombier MetaBlock mb;
2485e96a66cSDavid du Colombier MetaEntry me;
2495e96a66cSDavid du Colombier
2505e96a66cSDavid du Colombier memset(&de, 0, sizeof(de));
251*d7aba6c3SDavid du Colombier de.elem = vtstrdup("root");
2525e96a66cSDavid du Colombier de.entry = 0;
2535e96a66cSDavid du Colombier de.gen = 0;
2545e96a66cSDavid du Colombier de.mentry = 1;
2555e96a66cSDavid du Colombier de.mgen = 0;
2565e96a66cSDavid du Colombier de.size = 0;
2575e96a66cSDavid du Colombier de.qid = qid++;
258*d7aba6c3SDavid du Colombier de.uid = vtstrdup("adm");
259*d7aba6c3SDavid du Colombier de.gid = vtstrdup("adm");
260*d7aba6c3SDavid du Colombier de.mid = vtstrdup("adm");
2615e96a66cSDavid du Colombier de.mtime = time(0);
2625e96a66cSDavid du Colombier de.mcount = 0;
2635e96a66cSDavid du Colombier de.ctime = time(0);
2645e96a66cSDavid du Colombier de.atime = time(0);
2655e96a66cSDavid du Colombier de.mode = ModeDir | 0555;
2665e96a66cSDavid du Colombier
2675e96a66cSDavid du Colombier tag = tagGen();
2685e96a66cSDavid du Colombier addr = blockAlloc(BtData, tag);
2695e96a66cSDavid du Colombier
2705e96a66cSDavid du Colombier /* build up meta block */
2715e96a66cSDavid du Colombier memset(buf, 0, bsize);
2725e96a66cSDavid du Colombier mbInit(&mb, buf, bsize, bsize/100);
2735e96a66cSDavid du Colombier me.size = deSize(&de);
2745e96a66cSDavid du Colombier me.p = mbAlloc(&mb, me.size);
2755e96a66cSDavid du Colombier assert(me.p != nil);
2765e96a66cSDavid du Colombier dePack(&de, &me);
2775e96a66cSDavid du Colombier mbInsert(&mb, 0, &me);
2785e96a66cSDavid du Colombier mbPack(&mb);
2795e96a66cSDavid du Colombier blockWrite(PartData, addr);
2805e96a66cSDavid du Colombier deCleanup(&de);
2815e96a66cSDavid du Colombier
2825e96a66cSDavid du Colombier /* build up entry for meta block */
2835e96a66cSDavid du Colombier entryInit(e);
2845e96a66cSDavid du Colombier e->flags |= VtEntryLocal;
2855e96a66cSDavid du Colombier e->size = bsize;
2865e96a66cSDavid du Colombier e->tag = tag;
2875e96a66cSDavid du Colombier localToGlobal(addr, e->score);
2885e96a66cSDavid du Colombier }
2895e96a66cSDavid du Colombier
2905e96a66cSDavid du Colombier static u32int
rootInit(Entry * e)2915e96a66cSDavid du Colombier rootInit(Entry *e)
2925e96a66cSDavid du Colombier {
2935e96a66cSDavid du Colombier ulong addr;
2945e96a66cSDavid du Colombier u32int tag;
2955e96a66cSDavid du Colombier
2965e96a66cSDavid du Colombier tag = tagGen();
2975e96a66cSDavid du Colombier
2985e96a66cSDavid du Colombier addr = blockAlloc(BtDir, tag);
2995e96a66cSDavid du Colombier memset(buf, 0, bsize);
3005e96a66cSDavid du Colombier
3015e96a66cSDavid du Colombier /* root meta data is in the third entry */
3025e96a66cSDavid du Colombier entryPack(e, buf, 2);
3035e96a66cSDavid du Colombier
3045e96a66cSDavid du Colombier entryInit(e);
305*d7aba6c3SDavid du Colombier e->flags |= _VtEntryDir;
3065e96a66cSDavid du Colombier entryPack(e, buf, 0);
3075e96a66cSDavid du Colombier
3085e96a66cSDavid du Colombier entryInit(e);
3095e96a66cSDavid du Colombier entryPack(e, buf, 1);
3105e96a66cSDavid du Colombier
3115e96a66cSDavid du Colombier blockWrite(PartData, addr);
3125e96a66cSDavid du Colombier
3135e96a66cSDavid du Colombier entryInit(e);
314*d7aba6c3SDavid du Colombier e->flags |= VtEntryLocal|_VtEntryDir;
3155e96a66cSDavid du Colombier e->size = VtEntrySize*3;
3165e96a66cSDavid du Colombier e->tag = tag;
3175e96a66cSDavid du Colombier localToGlobal(addr, e->score);
3185e96a66cSDavid du Colombier
3195e96a66cSDavid du Colombier addr = blockAlloc(BtDir, RootTag);
3205e96a66cSDavid du Colombier memset(buf, 0, bsize);
3215e96a66cSDavid du Colombier entryPack(e, buf, 0);
3225e96a66cSDavid du Colombier
3235e96a66cSDavid du Colombier blockWrite(PartData, addr);
3245e96a66cSDavid du Colombier
3255e96a66cSDavid du Colombier return addr;
3265e96a66cSDavid du Colombier }
3275e96a66cSDavid du Colombier
3285e96a66cSDavid du Colombier
3295e96a66cSDavid du Colombier static u32int
blockAlloc(int type,u32int tag)3305e96a66cSDavid du Colombier blockAlloc(int type, u32int tag)
3315e96a66cSDavid du Colombier {
3325e96a66cSDavid du Colombier static u32int addr;
3335e96a66cSDavid du Colombier Label l;
3345e96a66cSDavid du Colombier int lpb;
3355e96a66cSDavid du Colombier
3365e96a66cSDavid du Colombier lpb = bsize/LabelSize;
3375e96a66cSDavid du Colombier
3385e96a66cSDavid du Colombier blockRead(PartLabel, addr/lpb);
339fe853e23SDavid du Colombier if(!labelUnpack(&l, buf, addr % lpb))
340*d7aba6c3SDavid du Colombier sysfatal("bad label: %r");
341fe853e23SDavid du Colombier if(l.state != BsFree)
342*d7aba6c3SDavid du Colombier sysfatal("want to allocate block already in use");
3435e96a66cSDavid du Colombier l.epoch = 1;
3445e96a66cSDavid du Colombier l.epochClose = ~(u32int)0;
3455e96a66cSDavid du Colombier l.type = type;
3465e96a66cSDavid du Colombier l.state = BsAlloc;
3475e96a66cSDavid du Colombier l.tag = tag;
3485e96a66cSDavid du Colombier labelPack(&l, buf, addr % lpb);
3495e96a66cSDavid du Colombier blockWrite(PartLabel, addr/lpb);
3505e96a66cSDavid du Colombier return addr++;
3515e96a66cSDavid du Colombier }
3525e96a66cSDavid du Colombier
3535e96a66cSDavid du Colombier static void
superInit(char * label,u32int root,uchar score[VtScoreSize])3547abd426fSDavid du Colombier superInit(char *label, u32int root, uchar score[VtScoreSize])
3555e96a66cSDavid du Colombier {
3565e96a66cSDavid du Colombier Super s;
3575e96a66cSDavid du Colombier
3585e96a66cSDavid du Colombier memset(buf, 0, bsize);
3595e96a66cSDavid du Colombier memset(&s, 0, sizeof(s));
3605e96a66cSDavid du Colombier s.version = SuperVersion;
3615e96a66cSDavid du Colombier s.epochLow = 1;
3625e96a66cSDavid du Colombier s.epochHigh = 1;
3635e96a66cSDavid du Colombier s.qid = qid;
3645e96a66cSDavid du Colombier s.active = root;
3655e96a66cSDavid du Colombier s.next = NilBlock;
3665e96a66cSDavid du Colombier s.current = NilBlock;
3675e96a66cSDavid du Colombier strecpy(s.name, s.name+sizeof(s.name), label);
3687abd426fSDavid du Colombier memmove(s.last, score, VtScoreSize);
3695e96a66cSDavid du Colombier
3705e96a66cSDavid du Colombier superPack(&s, buf);
3715e96a66cSDavid du Colombier blockWrite(PartSuper, 0);
3725e96a66cSDavid du Colombier }
3735e96a66cSDavid du Colombier
3745e96a66cSDavid du Colombier static u64int
unittoull(char * s)3755e96a66cSDavid du Colombier unittoull(char *s)
3765e96a66cSDavid du Colombier {
3775e96a66cSDavid du Colombier char *es;
3785e96a66cSDavid du Colombier u64int n;
3795e96a66cSDavid du Colombier
3805e96a66cSDavid du Colombier if(s == nil)
3815e96a66cSDavid du Colombier return TWID64;
3825e96a66cSDavid du Colombier n = strtoul(s, &es, 0);
3835e96a66cSDavid du Colombier if(*es == 'k' || *es == 'K'){
3845e96a66cSDavid du Colombier n *= 1024;
3855e96a66cSDavid du Colombier es++;
3865e96a66cSDavid du Colombier }else if(*es == 'm' || *es == 'M'){
3875e96a66cSDavid du Colombier n *= 1024*1024;
3885e96a66cSDavid du Colombier es++;
3895e96a66cSDavid du Colombier }else if(*es == 'g' || *es == 'G'){
3905e96a66cSDavid du Colombier n *= 1024*1024*1024;
3915e96a66cSDavid du Colombier es++;
3925e96a66cSDavid du Colombier }
3935e96a66cSDavid du Colombier if(*es != '\0')
3945e96a66cSDavid du Colombier return TWID64;
3955e96a66cSDavid du Colombier return n;
3965e96a66cSDavid du Colombier }
3975e96a66cSDavid du Colombier
3985e96a66cSDavid du Colombier static void
blockRead(int part,u32int addr)3995e96a66cSDavid du Colombier blockRead(int part, u32int addr)
4005e96a66cSDavid du Colombier {
4015e96a66cSDavid du Colombier if(!diskReadRaw(disk, part, addr, buf))
402*d7aba6c3SDavid du Colombier sysfatal("read failed: %r");
4035e96a66cSDavid du Colombier }
4045e96a66cSDavid du Colombier
4055e96a66cSDavid du Colombier static void
blockWrite(int part,u32int addr)4065e96a66cSDavid du Colombier blockWrite(int part, u32int addr)
4075e96a66cSDavid du Colombier {
4085e96a66cSDavid du Colombier if(!diskWriteRaw(disk, part, addr, buf))
409*d7aba6c3SDavid du Colombier sysfatal("write failed: %r");
4105e96a66cSDavid du Colombier }
4115e96a66cSDavid du Colombier
4125e96a66cSDavid du Colombier static void
addFile(File * root,char * name,uint mode)4135e96a66cSDavid du Colombier addFile(File *root, char *name, uint mode)
4145e96a66cSDavid du Colombier {
4155e96a66cSDavid du Colombier File *f;
4165e96a66cSDavid du Colombier
4175e96a66cSDavid du Colombier f = fileCreate(root, name, mode | ModeDir, "adm");
4185e96a66cSDavid du Colombier if(f == nil)
419*d7aba6c3SDavid du Colombier sysfatal("could not create file: %s: %r", name);
4205e96a66cSDavid du Colombier fileDecRef(f);
4215e96a66cSDavid du Colombier }
4225e96a66cSDavid du Colombier
4235e96a66cSDavid du Colombier static void
topLevel(char * name)4245e96a66cSDavid du Colombier topLevel(char *name)
4255e96a66cSDavid du Colombier {
4265e96a66cSDavid du Colombier Fs *fs;
4275e96a66cSDavid du Colombier File *root;
4285e96a66cSDavid du Colombier
4295e96a66cSDavid du Colombier /* ok, now we can open as a fs */
4305e96a66cSDavid du Colombier fs = fsOpen(name, z, 100, OReadWrite);
4315e96a66cSDavid du Colombier if(fs == nil)
432*d7aba6c3SDavid du Colombier sysfatal("could not open file system: %r");
433*d7aba6c3SDavid du Colombier rlock(&fs->elk);
4345e96a66cSDavid du Colombier root = fsGetRoot(fs);
4355e96a66cSDavid du Colombier if(root == nil)
436*d7aba6c3SDavid du Colombier sysfatal("could not open root: %r");
437c3c4501eSDavid du Colombier addFile(root, "active", 0555);
4385e96a66cSDavid du Colombier addFile(root, "archive", 0555);
4395e96a66cSDavid du Colombier addFile(root, "snapshot", 0555);
4405e96a66cSDavid du Colombier fileDecRef(root);
441fe853e23SDavid du Colombier if(iso9660file)
442fe853e23SDavid du Colombier iso9660copy(fs);
443*d7aba6c3SDavid du Colombier runlock(&fs->elk);
4445e96a66cSDavid du Colombier fsClose(fs);
4455e96a66cSDavid du Colombier }
4465e96a66cSDavid du Colombier
4475e96a66cSDavid du Colombier static int
ventiRead(uchar score[VtScoreSize],int type)4485e96a66cSDavid du Colombier ventiRead(uchar score[VtScoreSize], int type)
4495e96a66cSDavid du Colombier {
4505e96a66cSDavid du Colombier int n;
4515e96a66cSDavid du Colombier
452*d7aba6c3SDavid du Colombier n = vtread(z, score, type, buf, bsize);
4535e96a66cSDavid du Colombier if(n < 0)
454*d7aba6c3SDavid du Colombier sysfatal("ventiRead %V (%d) failed: %r", score, type);
455*d7aba6c3SDavid du Colombier vtzeroextend(type, buf, n, bsize);
4565e96a66cSDavid du Colombier return n;
4575e96a66cSDavid du Colombier }
4585e96a66cSDavid du Colombier
4595e96a66cSDavid du Colombier static u32int
ventiRoot(char * host,char * s)4605e96a66cSDavid du Colombier ventiRoot(char *host, char *s)
4615e96a66cSDavid du Colombier {
4625e96a66cSDavid du Colombier int i, n;
4635e96a66cSDavid du Colombier uchar score[VtScoreSize];
4645e96a66cSDavid du Colombier u32int addr, tag;
4655e96a66cSDavid du Colombier DirEntry de;
4665e96a66cSDavid du Colombier MetaBlock mb;
4675e96a66cSDavid du Colombier MetaEntry me;
4685e96a66cSDavid du Colombier Entry e;
4695e96a66cSDavid du Colombier VtRoot root;
4705e96a66cSDavid du Colombier
4715e96a66cSDavid du Colombier if(!parseScore(score, s))
472*d7aba6c3SDavid du Colombier sysfatal("bad score '%s'", s);
4735e96a66cSDavid du Colombier
474*d7aba6c3SDavid du Colombier if((z = vtdial(host)) == nil
475*d7aba6c3SDavid du Colombier || vtconnect(z) < 0)
476*d7aba6c3SDavid du Colombier sysfatal("connect to venti: %r");
4775e96a66cSDavid du Colombier
4785e96a66cSDavid du Colombier tag = tagGen();
4795e96a66cSDavid du Colombier addr = blockAlloc(BtDir, tag);
4805e96a66cSDavid du Colombier
4815e96a66cSDavid du Colombier ventiRead(score, VtRootType);
482*d7aba6c3SDavid du Colombier if(vtrootunpack(&root, buf) < 0)
483*d7aba6c3SDavid du Colombier sysfatal("corrupted root: vtrootunpack");
4845e96a66cSDavid du Colombier n = ventiRead(root.score, VtDirType);
4855e96a66cSDavid du Colombier
4865e96a66cSDavid du Colombier /*
4875e96a66cSDavid du Colombier * Fossil's vac archives start with an extra layer of source,
4885e96a66cSDavid du Colombier * but vac's don't.
4895e96a66cSDavid du Colombier */
4905e96a66cSDavid du Colombier if(n <= 2*VtEntrySize){
4915e96a66cSDavid du Colombier if(!entryUnpack(&e, buf, 0))
492*d7aba6c3SDavid du Colombier sysfatal("bad root: top entry");
4935e96a66cSDavid du Colombier n = ventiRead(e.score, VtDirType);
4945e96a66cSDavid du Colombier }
4955e96a66cSDavid du Colombier
4965e96a66cSDavid du Colombier /*
4975e96a66cSDavid du Colombier * There should be three root sources (and nothing else) here.
4985e96a66cSDavid du Colombier */
4995e96a66cSDavid du Colombier for(i=0; i<3; i++){
5005e96a66cSDavid du Colombier if(!entryUnpack(&e, buf, i)
5015e96a66cSDavid du Colombier || !(e.flags&VtEntryActive)
5025e96a66cSDavid du Colombier || e.psize < 256
5035e96a66cSDavid du Colombier || e.dsize < 256)
504*d7aba6c3SDavid du Colombier sysfatal("bad root: entry %d", i);
5055e96a66cSDavid du Colombier fprint(2, "%V\n", e.score);
5065e96a66cSDavid du Colombier }
5075e96a66cSDavid du Colombier if(n > 3*VtEntrySize)
508*d7aba6c3SDavid du Colombier sysfatal("bad root: entry count");
5095e96a66cSDavid du Colombier
5105e96a66cSDavid du Colombier blockWrite(PartData, addr);
5115e96a66cSDavid du Colombier
5125e96a66cSDavid du Colombier /*
5135e96a66cSDavid du Colombier * Maximum qid is recorded in root's msource, entry #2 (conveniently in e).
5145e96a66cSDavid du Colombier */
5155e96a66cSDavid du Colombier ventiRead(e.score, VtDataType);
5165e96a66cSDavid du Colombier if(!mbUnpack(&mb, buf, bsize))
517*d7aba6c3SDavid du Colombier sysfatal("bad root: mbUnpack");
5185e96a66cSDavid du Colombier meUnpack(&me, &mb, 0);
5195e96a66cSDavid du Colombier if(!deUnpack(&de, &me))
520*d7aba6c3SDavid du Colombier sysfatal("bad root: dirUnpack");
5215e96a66cSDavid du Colombier if(!de.qidSpace)
522*d7aba6c3SDavid du Colombier sysfatal("bad root: no qidSpace");
5235e96a66cSDavid du Colombier qid = de.qidMax;
5245e96a66cSDavid du Colombier
5255e96a66cSDavid du Colombier /*
5265e96a66cSDavid du Colombier * Recreate the top layer of source.
5275e96a66cSDavid du Colombier */
5285e96a66cSDavid du Colombier entryInit(&e);
529*d7aba6c3SDavid du Colombier e.flags |= VtEntryLocal|_VtEntryDir;
5305e96a66cSDavid du Colombier e.size = VtEntrySize*3;
5315e96a66cSDavid du Colombier e.tag = tag;
5325e96a66cSDavid du Colombier localToGlobal(addr, e.score);
5335e96a66cSDavid du Colombier
5345e96a66cSDavid du Colombier addr = blockAlloc(BtDir, RootTag);
5355e96a66cSDavid du Colombier memset(buf, 0, bsize);
5365e96a66cSDavid du Colombier entryPack(&e, buf, 0);
5375e96a66cSDavid du Colombier blockWrite(PartData, addr);
5385e96a66cSDavid du Colombier
5395e96a66cSDavid du Colombier return addr;
5405e96a66cSDavid du Colombier }
5415e96a66cSDavid du Colombier
5425e96a66cSDavid du Colombier static int
parseScore(uchar * score,char * buf)5435e96a66cSDavid du Colombier parseScore(uchar *score, char *buf)
5445e96a66cSDavid du Colombier {
5455e96a66cSDavid du Colombier int i, c;
5465e96a66cSDavid du Colombier
5475e96a66cSDavid du Colombier memset(score, 0, VtScoreSize);
5485e96a66cSDavid du Colombier
5495e96a66cSDavid du Colombier if(strlen(buf) < VtScoreSize*2)
5505e96a66cSDavid du Colombier return 0;
5515e96a66cSDavid du Colombier for(i=0; i<VtScoreSize*2; i++){
5525e96a66cSDavid du Colombier if(buf[i] >= '0' && buf[i] <= '9')
5535e96a66cSDavid du Colombier c = buf[i] - '0';
5545e96a66cSDavid du Colombier else if(buf[i] >= 'a' && buf[i] <= 'f')
5555e96a66cSDavid du Colombier c = buf[i] - 'a' + 10;
5565e96a66cSDavid du Colombier else if(buf[i] >= 'A' && buf[i] <= 'F')
5575e96a66cSDavid du Colombier c = buf[i] - 'A' + 10;
5585e96a66cSDavid du Colombier else
5595e96a66cSDavid du Colombier return 0;
5605e96a66cSDavid du Colombier
5615e96a66cSDavid du Colombier if((i & 1) == 0)
5625e96a66cSDavid du Colombier c <<= 4;
5635e96a66cSDavid du Colombier
5645e96a66cSDavid du Colombier score[i>>1] |= c;
5655e96a66cSDavid du Colombier }
5665e96a66cSDavid du Colombier return 1;
5675e96a66cSDavid du Colombier }
568