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*);
215e96a66cSDavid du Colombier static VtSession *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
main(int argc,char * argv[])495e96a66cSDavid du Colombier main(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)
99fe853e23SDavid du Colombier vtFatal("cannot use -i with -v");
100fe853e23SDavid du Colombier
1015e96a66cSDavid du Colombier vtAttach();
1025e96a66cSDavid du Colombier
1035e96a66cSDavid du Colombier fmtinstall('V', scoreFmt);
1045e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt);
1055e96a66cSDavid du Colombier fmtinstall('L', labelFmt);
1065e96a66cSDavid du Colombier
1075e96a66cSDavid du Colombier fd = open(argv[0], ORDWR);
1085e96a66cSDavid du Colombier if(fd < 0)
1095e96a66cSDavid du Colombier vtFatal("could not open file: %s: %r", argv[0]);
1105e96a66cSDavid du Colombier
1115e96a66cSDavid du Colombier buf = vtMemAllocZ(bsize);
1125e96a66cSDavid du Colombier if(pread(fd, buf, bsize, HeaderOffset) != bsize)
1135e96a66cSDavid du Colombier vtFatal("could not read fs header block: %r");
1145e96a66cSDavid du Colombier
1155e96a66cSDavid du Colombier if(headerUnpack(&h, buf) && !force
1165e96a66cSDavid du Colombier && !confirm("fs header block already exists; are you sure?"))
1175e96a66cSDavid du Colombier goto Out;
1185e96a66cSDavid du Colombier
1195e96a66cSDavid du Colombier if((d = dirfstat(fd)) == nil)
1205e96a66cSDavid du Colombier vtFatal("dirfstat: %r");
1215e96a66cSDavid du Colombier
1225e96a66cSDavid du Colombier if(d->type == 'M' && !force
1235e96a66cSDavid du Colombier && !confirm("fs file is mounted via devmnt (is not a kernel device); are you sure?"))
1245e96a66cSDavid du Colombier goto Out;
1255e96a66cSDavid du Colombier
1265e96a66cSDavid du Colombier partition(fd, bsize, &h);
1275e96a66cSDavid du Colombier headerPack(&h, buf);
1285e96a66cSDavid du Colombier if(pwrite(fd, buf, bsize, HeaderOffset) < bsize)
1295e96a66cSDavid du Colombier vtFatal("could not write fs header: %r");
1305e96a66cSDavid du Colombier
1315e96a66cSDavid du Colombier disk = diskAlloc(fd);
1325e96a66cSDavid du Colombier if(disk == nil)
1335e96a66cSDavid du Colombier vtFatal("could not open disk: %r");
1345e96a66cSDavid du Colombier
135fe853e23SDavid du Colombier if(iso9660file)
136fe853e23SDavid du Colombier iso9660init(fd, &h, iso9660file, iso9660off);
137fe853e23SDavid du Colombier
1385e96a66cSDavid du Colombier /* zero labels */
1395e96a66cSDavid du Colombier memset(buf, 0, bsize);
1405e96a66cSDavid du Colombier for(bn = 0; bn < diskSize(disk, PartLabel); bn++)
1415e96a66cSDavid du Colombier blockWrite(PartLabel, bn);
1425e96a66cSDavid du Colombier
143fe853e23SDavid du Colombier if(iso9660file)
144fe853e23SDavid du Colombier iso9660labels(disk, buf, blockWrite);
145fe853e23SDavid du Colombier
1465e96a66cSDavid du Colombier if(score)
1475e96a66cSDavid du Colombier root = ventiRoot(host, score);
1485e96a66cSDavid du Colombier else{
1495e96a66cSDavid du Colombier rootMetaInit(&e);
1505e96a66cSDavid du Colombier root = rootInit(&e);
1515e96a66cSDavid du Colombier }
1525e96a66cSDavid du Colombier
1537abd426fSDavid du Colombier superInit(label, root, vtZeroScore);
1545e96a66cSDavid du Colombier diskFree(disk);
1555e96a66cSDavid du Colombier
156e6c6b7f8SDavid du Colombier if(score == nil)
1575e96a66cSDavid du Colombier topLevel(argv[0]);
1585e96a66cSDavid du Colombier
1595e96a66cSDavid du Colombier Out:
1605e96a66cSDavid du Colombier vtDetach();
1615e96a66cSDavid du Colombier exits(0);
1625e96a66cSDavid du Colombier }
1635e96a66cSDavid du Colombier
1645e96a66cSDavid du Colombier static u64int
fdsize(int fd)1655e96a66cSDavid du Colombier fdsize(int fd)
1665e96a66cSDavid du Colombier {
1675e96a66cSDavid du Colombier Dir *dir;
1685e96a66cSDavid du Colombier u64int size;
1695e96a66cSDavid du Colombier
1705e96a66cSDavid du Colombier dir = dirfstat(fd);
1715e96a66cSDavid du Colombier if(dir == nil)
1725e96a66cSDavid du Colombier vtFatal("could not stat file: %r");
1735e96a66cSDavid du Colombier size = dir->length;
1745e96a66cSDavid du Colombier free(dir);
1755e96a66cSDavid du Colombier return size;
1765e96a66cSDavid du Colombier }
1775e96a66cSDavid du Colombier
1785e96a66cSDavid du Colombier static void
usage(void)1795e96a66cSDavid du Colombier usage(void)
1805e96a66cSDavid du Colombier {
181*0c6300e7SDavid du Colombier fprint(2, "usage: %s [-b blocksize] [-h host] [-i file offset] "
182*0c6300e7SDavid du Colombier "[-l label] [-v score] [-y] file\n", argv0);
1835e96a66cSDavid du Colombier exits("usage");
1845e96a66cSDavid du Colombier }
1855e96a66cSDavid du Colombier
1865e96a66cSDavid du Colombier static void
partition(int fd,int bsize,Header * h)1875e96a66cSDavid du Colombier partition(int fd, int bsize, Header *h)
1885e96a66cSDavid du Colombier {
1895e96a66cSDavid du Colombier ulong nblock, ndata, nlabel;
1905e96a66cSDavid du Colombier ulong lpb;
1915e96a66cSDavid du Colombier
1925e96a66cSDavid du Colombier if(bsize % 512 != 0)
1935e96a66cSDavid du Colombier sysfatal("block size must be a multiple of 512 bytes");
1945e96a66cSDavid du Colombier if(bsize > VtMaxLumpSize)
1955e96a66cSDavid du Colombier sysfatal("block size must be less than %d", VtMaxLumpSize);
1965e96a66cSDavid du Colombier
1975e96a66cSDavid du Colombier memset(h, 0, sizeof(*h));
1985e96a66cSDavid du Colombier h->blockSize = bsize;
1995e96a66cSDavid du Colombier
2005e96a66cSDavid du Colombier lpb = bsize/LabelSize;
2015e96a66cSDavid du Colombier
2025e96a66cSDavid du Colombier nblock = fdsize(fd)/bsize;
2035e96a66cSDavid du Colombier
2045e96a66cSDavid du Colombier /* sanity check */
2055e96a66cSDavid du Colombier if(nblock < (HeaderOffset*10)/bsize)
2065e96a66cSDavid du Colombier vtFatal("file too small");
2075e96a66cSDavid du Colombier
2085e96a66cSDavid du Colombier h->super = (HeaderOffset + 2*bsize)/bsize;
2095e96a66cSDavid du Colombier h->label = h->super + 1;
2105e96a66cSDavid du Colombier ndata = ((u64int)lpb)*(nblock - h->label)/(lpb+1);
2115e96a66cSDavid du Colombier nlabel = (ndata + lpb - 1)/lpb;
2125e96a66cSDavid du Colombier h->data = h->label + nlabel;
2135e96a66cSDavid du Colombier h->end = h->data + ndata;
2145e96a66cSDavid du Colombier
2155e96a66cSDavid du Colombier }
2165e96a66cSDavid du Colombier
2175e96a66cSDavid du Colombier static u32int
tagGen(void)2185e96a66cSDavid du Colombier tagGen(void)
2195e96a66cSDavid du Colombier {
2205e96a66cSDavid du Colombier u32int tag;
2215e96a66cSDavid du Colombier
2225e96a66cSDavid du Colombier for(;;){
2235e96a66cSDavid du Colombier tag = lrand();
2245e96a66cSDavid du Colombier if(tag > RootTag)
2255e96a66cSDavid du Colombier break;
2265e96a66cSDavid du Colombier }
2275e96a66cSDavid du Colombier return tag;
2285e96a66cSDavid du Colombier }
2295e96a66cSDavid du Colombier
2305e96a66cSDavid du Colombier static void
entryInit(Entry * e)2315e96a66cSDavid du Colombier entryInit(Entry *e)
2325e96a66cSDavid du Colombier {
2335e96a66cSDavid du Colombier e->gen = 0;
2345e96a66cSDavid du Colombier e->dsize = bsize;
2355e96a66cSDavid du Colombier e->psize = bsize/VtEntrySize*VtEntrySize;
2365e96a66cSDavid du Colombier e->flags = VtEntryActive;
2375e96a66cSDavid du Colombier e->depth = 0;
2385e96a66cSDavid du Colombier e->size = 0;
2395e96a66cSDavid du Colombier memmove(e->score, vtZeroScore, VtScoreSize);
2405e96a66cSDavid du Colombier e->tag = tagGen();
2415e96a66cSDavid du Colombier e->snap = 0;
2425e96a66cSDavid du Colombier e->archive = 0;
2435e96a66cSDavid du Colombier }
2445e96a66cSDavid du Colombier
2455e96a66cSDavid du Colombier static void
rootMetaInit(Entry * e)2465e96a66cSDavid du Colombier rootMetaInit(Entry *e)
2475e96a66cSDavid du Colombier {
2485e96a66cSDavid du Colombier u32int addr;
2495e96a66cSDavid du Colombier u32int tag;
2505e96a66cSDavid du Colombier DirEntry de;
2515e96a66cSDavid du Colombier MetaBlock mb;
2525e96a66cSDavid du Colombier MetaEntry me;
2535e96a66cSDavid du Colombier
2545e96a66cSDavid du Colombier memset(&de, 0, sizeof(de));
2555e96a66cSDavid du Colombier de.elem = vtStrDup("root");
2565e96a66cSDavid du Colombier de.entry = 0;
2575e96a66cSDavid du Colombier de.gen = 0;
2585e96a66cSDavid du Colombier de.mentry = 1;
2595e96a66cSDavid du Colombier de.mgen = 0;
2605e96a66cSDavid du Colombier de.size = 0;
2615e96a66cSDavid du Colombier de.qid = qid++;
2625e96a66cSDavid du Colombier de.uid = vtStrDup("adm");
2635e96a66cSDavid du Colombier de.gid = vtStrDup("adm");
2645e96a66cSDavid du Colombier de.mid = vtStrDup("adm");
2655e96a66cSDavid du Colombier de.mtime = time(0);
2665e96a66cSDavid du Colombier de.mcount = 0;
2675e96a66cSDavid du Colombier de.ctime = time(0);
2685e96a66cSDavid du Colombier de.atime = time(0);
2695e96a66cSDavid du Colombier de.mode = ModeDir | 0555;
2705e96a66cSDavid du Colombier
2715e96a66cSDavid du Colombier tag = tagGen();
2725e96a66cSDavid du Colombier addr = blockAlloc(BtData, tag);
2735e96a66cSDavid du Colombier
2745e96a66cSDavid du Colombier /* build up meta block */
2755e96a66cSDavid du Colombier memset(buf, 0, bsize);
2765e96a66cSDavid du Colombier mbInit(&mb, buf, bsize, bsize/100);
2775e96a66cSDavid du Colombier me.size = deSize(&de);
2785e96a66cSDavid du Colombier me.p = mbAlloc(&mb, me.size);
2795e96a66cSDavid du Colombier assert(me.p != nil);
2805e96a66cSDavid du Colombier dePack(&de, &me);
2815e96a66cSDavid du Colombier mbInsert(&mb, 0, &me);
2825e96a66cSDavid du Colombier mbPack(&mb);
2835e96a66cSDavid du Colombier blockWrite(PartData, addr);
2845e96a66cSDavid du Colombier deCleanup(&de);
2855e96a66cSDavid du Colombier
2865e96a66cSDavid du Colombier /* build up entry for meta block */
2875e96a66cSDavid du Colombier entryInit(e);
2885e96a66cSDavid du Colombier e->flags |= VtEntryLocal;
2895e96a66cSDavid du Colombier e->size = bsize;
2905e96a66cSDavid du Colombier e->tag = tag;
2915e96a66cSDavid du Colombier localToGlobal(addr, e->score);
2925e96a66cSDavid du Colombier }
2935e96a66cSDavid du Colombier
2945e96a66cSDavid du Colombier static u32int
rootInit(Entry * e)2955e96a66cSDavid du Colombier rootInit(Entry *e)
2965e96a66cSDavid du Colombier {
2975e96a66cSDavid du Colombier ulong addr;
2985e96a66cSDavid du Colombier u32int tag;
2995e96a66cSDavid du Colombier
3005e96a66cSDavid du Colombier tag = tagGen();
3015e96a66cSDavid du Colombier
3025e96a66cSDavid du Colombier addr = blockAlloc(BtDir, tag);
3035e96a66cSDavid du Colombier memset(buf, 0, bsize);
3045e96a66cSDavid du Colombier
3055e96a66cSDavid du Colombier /* root meta data is in the third entry */
3065e96a66cSDavid du Colombier entryPack(e, buf, 2);
3075e96a66cSDavid du Colombier
3085e96a66cSDavid du Colombier entryInit(e);
3095e96a66cSDavid du Colombier e->flags |= VtEntryDir;
3105e96a66cSDavid du Colombier entryPack(e, buf, 0);
3115e96a66cSDavid du Colombier
3125e96a66cSDavid du Colombier entryInit(e);
3135e96a66cSDavid du Colombier entryPack(e, buf, 1);
3145e96a66cSDavid du Colombier
3155e96a66cSDavid du Colombier blockWrite(PartData, addr);
3165e96a66cSDavid du Colombier
3175e96a66cSDavid du Colombier entryInit(e);
3185e96a66cSDavid du Colombier e->flags |= VtEntryLocal|VtEntryDir;
3195e96a66cSDavid du Colombier e->size = VtEntrySize*3;
3205e96a66cSDavid du Colombier e->tag = tag;
3215e96a66cSDavid du Colombier localToGlobal(addr, e->score);
3225e96a66cSDavid du Colombier
3235e96a66cSDavid du Colombier addr = blockAlloc(BtDir, RootTag);
3245e96a66cSDavid du Colombier memset(buf, 0, bsize);
3255e96a66cSDavid du Colombier entryPack(e, buf, 0);
3265e96a66cSDavid du Colombier
3275e96a66cSDavid du Colombier blockWrite(PartData, addr);
3285e96a66cSDavid du Colombier
3295e96a66cSDavid du Colombier return addr;
3305e96a66cSDavid du Colombier }
3315e96a66cSDavid du Colombier
3325e96a66cSDavid du Colombier
3335e96a66cSDavid du Colombier static u32int
blockAlloc(int type,u32int tag)3345e96a66cSDavid du Colombier blockAlloc(int type, u32int tag)
3355e96a66cSDavid du Colombier {
3365e96a66cSDavid du Colombier static u32int addr;
3375e96a66cSDavid du Colombier Label l;
3385e96a66cSDavid du Colombier int lpb;
3395e96a66cSDavid du Colombier
3405e96a66cSDavid du Colombier lpb = bsize/LabelSize;
3415e96a66cSDavid du Colombier
3425e96a66cSDavid du Colombier blockRead(PartLabel, addr/lpb);
343fe853e23SDavid du Colombier if(!labelUnpack(&l, buf, addr % lpb))
3445e96a66cSDavid du Colombier vtFatal("bad label: %r");
345fe853e23SDavid du Colombier if(l.state != BsFree)
346fe853e23SDavid du Colombier vtFatal("want to allocate block already in use");
3475e96a66cSDavid du Colombier l.epoch = 1;
3485e96a66cSDavid du Colombier l.epochClose = ~(u32int)0;
3495e96a66cSDavid du Colombier l.type = type;
3505e96a66cSDavid du Colombier l.state = BsAlloc;
3515e96a66cSDavid du Colombier l.tag = tag;
3525e96a66cSDavid du Colombier labelPack(&l, buf, addr % lpb);
3535e96a66cSDavid du Colombier blockWrite(PartLabel, addr/lpb);
3545e96a66cSDavid du Colombier return addr++;
3555e96a66cSDavid du Colombier }
3565e96a66cSDavid du Colombier
3575e96a66cSDavid du Colombier static void
superInit(char * label,u32int root,uchar score[VtScoreSize])3587abd426fSDavid du Colombier superInit(char *label, u32int root, uchar score[VtScoreSize])
3595e96a66cSDavid du Colombier {
3605e96a66cSDavid du Colombier Super s;
3615e96a66cSDavid du Colombier
3625e96a66cSDavid du Colombier memset(buf, 0, bsize);
3635e96a66cSDavid du Colombier memset(&s, 0, sizeof(s));
3645e96a66cSDavid du Colombier s.version = SuperVersion;
3655e96a66cSDavid du Colombier s.epochLow = 1;
3665e96a66cSDavid du Colombier s.epochHigh = 1;
3675e96a66cSDavid du Colombier s.qid = qid;
3685e96a66cSDavid du Colombier s.active = root;
3695e96a66cSDavid du Colombier s.next = NilBlock;
3705e96a66cSDavid du Colombier s.current = NilBlock;
3715e96a66cSDavid du Colombier strecpy(s.name, s.name+sizeof(s.name), label);
3727abd426fSDavid du Colombier memmove(s.last, score, VtScoreSize);
3735e96a66cSDavid du Colombier
3745e96a66cSDavid du Colombier superPack(&s, buf);
3755e96a66cSDavid du Colombier blockWrite(PartSuper, 0);
3765e96a66cSDavid du Colombier }
3775e96a66cSDavid du Colombier
3785e96a66cSDavid du Colombier static u64int
unittoull(char * s)3795e96a66cSDavid du Colombier unittoull(char *s)
3805e96a66cSDavid du Colombier {
3815e96a66cSDavid du Colombier char *es;
3825e96a66cSDavid du Colombier u64int n;
3835e96a66cSDavid du Colombier
3845e96a66cSDavid du Colombier if(s == nil)
3855e96a66cSDavid du Colombier return TWID64;
3865e96a66cSDavid du Colombier n = strtoul(s, &es, 0);
3875e96a66cSDavid du Colombier if(*es == 'k' || *es == 'K'){
3885e96a66cSDavid du Colombier n *= 1024;
3895e96a66cSDavid du Colombier es++;
3905e96a66cSDavid du Colombier }else if(*es == 'm' || *es == 'M'){
3915e96a66cSDavid du Colombier n *= 1024*1024;
3925e96a66cSDavid du Colombier es++;
3935e96a66cSDavid du Colombier }else if(*es == 'g' || *es == 'G'){
3945e96a66cSDavid du Colombier n *= 1024*1024*1024;
3955e96a66cSDavid du Colombier es++;
3965e96a66cSDavid du Colombier }
3975e96a66cSDavid du Colombier if(*es != '\0')
3985e96a66cSDavid du Colombier return TWID64;
3995e96a66cSDavid du Colombier return n;
4005e96a66cSDavid du Colombier }
4015e96a66cSDavid du Colombier
4025e96a66cSDavid du Colombier static void
blockRead(int part,u32int addr)4035e96a66cSDavid du Colombier blockRead(int part, u32int addr)
4045e96a66cSDavid du Colombier {
4055e96a66cSDavid du Colombier if(!diskReadRaw(disk, part, addr, buf))
4065e96a66cSDavid du Colombier vtFatal("read failed: %r");
4075e96a66cSDavid du Colombier }
4085e96a66cSDavid du Colombier
4095e96a66cSDavid du Colombier static void
blockWrite(int part,u32int addr)4105e96a66cSDavid du Colombier blockWrite(int part, u32int addr)
4115e96a66cSDavid du Colombier {
4125e96a66cSDavid du Colombier if(!diskWriteRaw(disk, part, addr, buf))
4135e96a66cSDavid du Colombier vtFatal("write failed: %r");
4145e96a66cSDavid du Colombier }
4155e96a66cSDavid du Colombier
4165e96a66cSDavid du Colombier static void
addFile(File * root,char * name,uint mode)4175e96a66cSDavid du Colombier addFile(File *root, char *name, uint mode)
4185e96a66cSDavid du Colombier {
4195e96a66cSDavid du Colombier File *f;
4205e96a66cSDavid du Colombier
4215e96a66cSDavid du Colombier f = fileCreate(root, name, mode | ModeDir, "adm");
4225e96a66cSDavid du Colombier if(f == nil)
4235e96a66cSDavid du Colombier vtFatal("could not create file: %s: %r", name);
4245e96a66cSDavid du Colombier fileDecRef(f);
4255e96a66cSDavid du Colombier }
4265e96a66cSDavid du Colombier
4275e96a66cSDavid du Colombier static void
topLevel(char * name)4285e96a66cSDavid du Colombier topLevel(char *name)
4295e96a66cSDavid du Colombier {
4305e96a66cSDavid du Colombier Fs *fs;
4315e96a66cSDavid du Colombier File *root;
4325e96a66cSDavid du Colombier
4335e96a66cSDavid du Colombier /* ok, now we can open as a fs */
4345e96a66cSDavid du Colombier fs = fsOpen(name, z, 100, OReadWrite);
4355e96a66cSDavid du Colombier if(fs == nil)
4365e96a66cSDavid du Colombier vtFatal("could not open file system: %r");
4375e96a66cSDavid du Colombier vtRLock(fs->elk);
4385e96a66cSDavid du Colombier root = fsGetRoot(fs);
4395e96a66cSDavid du Colombier if(root == nil)
4405e96a66cSDavid du Colombier vtFatal("could not open root: %r");
441c3c4501eSDavid du Colombier addFile(root, "active", 0555);
4425e96a66cSDavid du Colombier addFile(root, "archive", 0555);
4435e96a66cSDavid du Colombier addFile(root, "snapshot", 0555);
4445e96a66cSDavid du Colombier fileDecRef(root);
445fe853e23SDavid du Colombier if(iso9660file)
446fe853e23SDavid du Colombier iso9660copy(fs);
4475e96a66cSDavid du Colombier vtRUnlock(fs->elk);
4485e96a66cSDavid du Colombier fsClose(fs);
4495e96a66cSDavid du Colombier }
4505e96a66cSDavid du Colombier
4515e96a66cSDavid du Colombier static int
ventiRead(uchar score[VtScoreSize],int type)4525e96a66cSDavid du Colombier ventiRead(uchar score[VtScoreSize], int type)
4535e96a66cSDavid du Colombier {
4545e96a66cSDavid du Colombier int n;
4555e96a66cSDavid du Colombier
4565e96a66cSDavid du Colombier n = vtRead(z, score, type, buf, bsize);
4575e96a66cSDavid du Colombier if(n < 0)
4585e96a66cSDavid du Colombier vtFatal("ventiRead %V (%d) failed: %R", score, type);
4595e96a66cSDavid du Colombier vtZeroExtend(type, buf, n, bsize);
4605e96a66cSDavid du Colombier return n;
4615e96a66cSDavid du Colombier }
4625e96a66cSDavid du Colombier
4635e96a66cSDavid du Colombier static u32int
ventiRoot(char * host,char * s)4645e96a66cSDavid du Colombier ventiRoot(char *host, char *s)
4655e96a66cSDavid du Colombier {
4665e96a66cSDavid du Colombier int i, n;
4675e96a66cSDavid du Colombier uchar score[VtScoreSize];
4685e96a66cSDavid du Colombier u32int addr, tag;
4695e96a66cSDavid du Colombier DirEntry de;
4705e96a66cSDavid du Colombier MetaBlock mb;
4715e96a66cSDavid du Colombier MetaEntry me;
4725e96a66cSDavid du Colombier Entry e;
4735e96a66cSDavid du Colombier VtRoot root;
4745e96a66cSDavid du Colombier
4755e96a66cSDavid du Colombier if(!parseScore(score, s))
4765e96a66cSDavid du Colombier vtFatal("bad score '%s'", s);
4775e96a66cSDavid du Colombier
4785e96a66cSDavid du Colombier if((z = vtDial(host, 0)) == nil
4795e96a66cSDavid du Colombier || !vtConnect(z, nil))
4805e96a66cSDavid du Colombier vtFatal("connect to venti: %R");
4815e96a66cSDavid du Colombier
4825e96a66cSDavid du Colombier tag = tagGen();
4835e96a66cSDavid du Colombier addr = blockAlloc(BtDir, tag);
4845e96a66cSDavid du Colombier
4855e96a66cSDavid du Colombier ventiRead(score, VtRootType);
4865e96a66cSDavid du Colombier if(!vtRootUnpack(&root, buf))
4875e96a66cSDavid du Colombier vtFatal("corrupted root: vtRootUnpack");
4885e96a66cSDavid du Colombier n = ventiRead(root.score, VtDirType);
4895e96a66cSDavid du Colombier
4905e96a66cSDavid du Colombier /*
4915e96a66cSDavid du Colombier * Fossil's vac archives start with an extra layer of source,
4925e96a66cSDavid du Colombier * but vac's don't.
4935e96a66cSDavid du Colombier */
4945e96a66cSDavid du Colombier if(n <= 2*VtEntrySize){
4955e96a66cSDavid du Colombier if(!entryUnpack(&e, buf, 0))
4965e96a66cSDavid du Colombier vtFatal("bad root: top entry");
4975e96a66cSDavid du Colombier n = ventiRead(e.score, VtDirType);
4985e96a66cSDavid du Colombier }
4995e96a66cSDavid du Colombier
5005e96a66cSDavid du Colombier /*
5015e96a66cSDavid du Colombier * There should be three root sources (and nothing else) here.
5025e96a66cSDavid du Colombier */
5035e96a66cSDavid du Colombier for(i=0; i<3; i++){
5045e96a66cSDavid du Colombier if(!entryUnpack(&e, buf, i)
5055e96a66cSDavid du Colombier || !(e.flags&VtEntryActive)
5065e96a66cSDavid du Colombier || e.psize < 256
5075e96a66cSDavid du Colombier || e.dsize < 256)
5085e96a66cSDavid du Colombier vtFatal("bad root: entry %d", i);
5095e96a66cSDavid du Colombier fprint(2, "%V\n", e.score);
5105e96a66cSDavid du Colombier }
5115e96a66cSDavid du Colombier if(n > 3*VtEntrySize)
5125e96a66cSDavid du Colombier vtFatal("bad root: entry count");
5135e96a66cSDavid du Colombier
5145e96a66cSDavid du Colombier blockWrite(PartData, addr);
5155e96a66cSDavid du Colombier
5165e96a66cSDavid du Colombier /*
5175e96a66cSDavid du Colombier * Maximum qid is recorded in root's msource, entry #2 (conveniently in e).
5185e96a66cSDavid du Colombier */
5195e96a66cSDavid du Colombier ventiRead(e.score, VtDataType);
5205e96a66cSDavid du Colombier if(!mbUnpack(&mb, buf, bsize))
5215e96a66cSDavid du Colombier vtFatal("bad root: mbUnpack");
5225e96a66cSDavid du Colombier meUnpack(&me, &mb, 0);
5235e96a66cSDavid du Colombier if(!deUnpack(&de, &me))
5245e96a66cSDavid du Colombier vtFatal("bad root: dirUnpack");
5255e96a66cSDavid du Colombier if(!de.qidSpace)
5265e96a66cSDavid du Colombier vtFatal("bad root: no qidSpace");
5275e96a66cSDavid du Colombier qid = de.qidMax;
5285e96a66cSDavid du Colombier
5295e96a66cSDavid du Colombier /*
5305e96a66cSDavid du Colombier * Recreate the top layer of source.
5315e96a66cSDavid du Colombier */
5325e96a66cSDavid du Colombier entryInit(&e);
5335e96a66cSDavid du Colombier e.flags |= VtEntryLocal|VtEntryDir;
5345e96a66cSDavid du Colombier e.size = VtEntrySize*3;
5355e96a66cSDavid du Colombier e.tag = tag;
5365e96a66cSDavid du Colombier localToGlobal(addr, e.score);
5375e96a66cSDavid du Colombier
5385e96a66cSDavid du Colombier addr = blockAlloc(BtDir, RootTag);
5395e96a66cSDavid du Colombier memset(buf, 0, bsize);
5405e96a66cSDavid du Colombier entryPack(&e, buf, 0);
5415e96a66cSDavid du Colombier blockWrite(PartData, addr);
5425e96a66cSDavid du Colombier
5435e96a66cSDavid du Colombier return addr;
5445e96a66cSDavid du Colombier }
5455e96a66cSDavid du Colombier
5465e96a66cSDavid du Colombier static int
parseScore(uchar * score,char * buf)5475e96a66cSDavid du Colombier parseScore(uchar *score, char *buf)
5485e96a66cSDavid du Colombier {
5495e96a66cSDavid du Colombier int i, c;
5505e96a66cSDavid du Colombier
5515e96a66cSDavid du Colombier memset(score, 0, VtScoreSize);
5525e96a66cSDavid du Colombier
5535e96a66cSDavid du Colombier if(strlen(buf) < VtScoreSize*2)
5545e96a66cSDavid du Colombier return 0;
5555e96a66cSDavid du Colombier for(i=0; i<VtScoreSize*2; i++){
5565e96a66cSDavid du Colombier if(buf[i] >= '0' && buf[i] <= '9')
5575e96a66cSDavid du Colombier c = buf[i] - '0';
5585e96a66cSDavid du Colombier else if(buf[i] >= 'a' && buf[i] <= 'f')
5595e96a66cSDavid du Colombier c = buf[i] - 'a' + 10;
5605e96a66cSDavid du Colombier else if(buf[i] >= 'A' && buf[i] <= 'F')
5615e96a66cSDavid du Colombier c = buf[i] - 'A' + 10;
5625e96a66cSDavid du Colombier else
5635e96a66cSDavid du Colombier return 0;
5645e96a66cSDavid du Colombier
5655e96a66cSDavid du Colombier if((i & 1) == 0)
5665e96a66cSDavid du Colombier c <<= 4;
5675e96a66cSDavid du Colombier
5685e96a66cSDavid du Colombier score[i>>1] |= c;
5695e96a66cSDavid du Colombier }
5705e96a66cSDavid du Colombier return 1;
5715e96a66cSDavid du Colombier }
572