From 2b69dba5038ffd0b59cf30a4c44bce549e5097f8 Mon Sep 17 00:00:00 2001 From: forsyth Date: Mon, 16 May 2011 23:28:07 +0100 Subject: 20110516-2327 --- CHANGES | 2 + appl/cmd/vacfs.b | 112 ++++++++++-------- appl/cmd/vacget.b | 90 ++++++++------- appl/cmd/vacput.b | 245 +++++++++++++++++++++++++-------------- appl/lib/vac.b | 335 ++++++++++++++++++++---------------------------------- appl/lib/venti.b | 101 +++++++++++++++- dis/lib/vac.dis | Bin 17880 -> 15720 bytes dis/lib/venti.dis | Bin 8873 -> 10115 bytes dis/vacfs.dis | Bin 8305 -> 8361 bytes dis/vacget.dis | Bin 4203 -> 4130 bytes dis/vacput.dis | Bin 6585 -> 6991 bytes include/version.h | 2 +- man/1/vacget | 34 +++++- man/2/venti | 10 +- module/vac.m | 63 +++------- module/venti.m | 10 +- opt/README | 1 + 17 files changed, 548 insertions(+), 457 deletions(-) diff --git a/CHANGES b/CHANGES index a2d512ba..7cbe223b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +20110516 + merge changes from vac branch of mechiel-inferno-os (googlecode) 20110426 emu/Linux/asm-arm.S linux system call interface changed [issue 215, mechiel] 20110419 diff --git a/appl/cmd/vacfs.b b/appl/cmd/vacfs.b index f707f568..9e7a024e 100644 --- a/appl/cmd/vacfs.b +++ b/appl/cmd/vacfs.b @@ -2,35 +2,36 @@ implement Vacfs; include "sys.m"; sys: Sys; + sprint: import sys; include "draw.m"; include "arg.m"; +include "dial.m"; + dial: Dial; include "string.m"; + str: String; include "daytime.m"; + dt: Daytime; include "venti.m"; + venti: Venti; + Root, Entry, Score, Session: import venti; + Roottype, Dirtype, Pointertype0, Datatype: import venti; include "vac.m"; + vac: Vac; + Direntry, Vacdir, Vacfile: import vac; include "styx.m"; styx: Styx; Tmsg, Rmsg: import styx; include "styxservers.m"; - -str: String; -daytime: Daytime; -venti: Venti; -vac: Vac; -styxservers: Styxservers; - -print, sprint, fprint, fildes: import sys; -Score, Session: import venti; -Roottype, Dirtype, Pointertype0, Datatype: import venti; -Root, Entry, Direntry, Metablock, Metaentry, Entrysize, Modeperm, Modeappend, Modeexcl, Modedir, Modesnapshot, Vacdir, Vacfile, Source: import vac; -Styxserver, Fid, Navigator, Navop, Enotfound: import styxservers; + styxservers: Styxservers; + Styxserver, Fid, Navigator, Navop, Enotfound: import styxservers; Vacfs: module { init: fn(nil: ref Draw->Context, args: list of string); }; -addr := "net!$venti!venti"; -dflag := pflag := 0; +addr := "$venti"; +dflag: int; +pflag: int; session: ref Session; ss: ref Styxserver; @@ -183,7 +184,7 @@ getfile(qid: int): ref Elem.File pick file := get(qid) { File => return file; } - error("internal error, getfile"); + fail("internal error, getfile"); return nil; } @@ -192,7 +193,7 @@ getdir(qid: int): ref Elem.Dir pick d := get(qid) { Dir => return d; } - error("internal error, getdir"); + fail("internal error, getdir"); return nil; } @@ -200,8 +201,9 @@ init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; arg := load Arg Arg->PATH; + dial = load Dial Dial->PATH; str = load String String->PATH; - daytime = load Daytime Daytime->PATH; + dt = load Daytime Daytime->PATH; venti = load Venti Venti->PATH; styx = load Styx Styx->PATH; styxservers = load Styxservers Styxservers->PATH; @@ -213,7 +215,7 @@ init(nil: ref Draw->Context, args: list of string) sys->pctl(sys->NEWPGRP, nil); if(venti == nil || vac == nil) - error("loading venti,vac"); + fail("loading venti,vac"); arg->init(args); arg->setusage(arg->progname()+" [-Ddp] [-a addr] [[tag:]score]"); @@ -221,11 +223,9 @@ init(nil: ref Draw->Context, args: list of string) case ch { 'D' => styxservers->traceset(1); 'a' => addr = arg->earg(); - 'd' => dflag++; - vac->dflag++; + 'd' => vac->dflag = dflag++; 'p' => pflag++; - * => warn(sprint("bad option: -%c", ch)); - arg->usage(); + * => arg->usage(); } args = arg->argv(); if(len args > 1) @@ -239,22 +239,23 @@ init(nil: ref Draw->Context, args: list of string) if(tag == nil) tag = "vac"; if(tag != "vac") - error("bad score type: "+tag); + fail("bad score type: "+tag); (ok, s) := Score.parse(scorestr); if(ok != 0) - error("bad score: "+scorestr); + fail("bad score: "+scorestr); score = ref s; } - (cok, conn) := sys->dial(addr, nil); - if(cok < 0) - error(sprint("dialing %s: %r", addr)); + addr = dial->netmkaddr(addr, "net", "venti"); + cc := dial->dial(addr, nil); + if(cc == nil) + fail(sprint("dialing %s: %r", addr)); say("have connection"); - fd := conn.dfd; + fd := cc.dfd; session = Session.new(fd); if(session == nil) - error(sprint("handshake: %r")); + fail(sprint("handshake: %r")); say("have handshake"); rqid := 0; @@ -262,14 +263,14 @@ init(nil: ref Draw->Context, args: list of string) if(args == nil) { de := Direntry.new(); de.uid = de.gid = de.mid = user(); - de.ctime = de.atime = de.mtime = daytime->now(); + de.ctime = de.atime = de.mtime = dt->now(); de.mode = Vac->Modedir|8r755; de.emode = Sys->DMDIR|8r755; red = ref Elem.Dir(rqid, de, big 0, nil, rqid, 0, 0, nil); } else { (vd, de, err) := vac->vdroot(session, *score); if(err != nil) - error(err); + fail(err); rqid = ++lastqid; red = ref Elem.Dir(rqid, de, big 0, vd, rqid, 0, 0, nil); } @@ -284,12 +285,16 @@ init(nil: ref Draw->Context, args: list of string) (msgc, ss) = Styxserver.new(sys->fildes(0), nav, big rqid); for(;;) { - pick m := <- msgc { + mm := <-msgc; + if(mm == nil) + fail("eof"); + + pick m := mm { Readerror => - say("read error: "+m.error); + fail("read error: "+m.error); Read => - say(sprint("have read, offset=%ubd count=%d", m.offset, m.count)); + if(dflag) say(sprint("have read, offset=%ubd count=%d", m.offset, m.count)); (c, err) := ss.canread(m); if(c == nil){ ss.reply(ref Rmsg.Error(m.tag, err)); @@ -353,14 +358,14 @@ navigator(c: chan of ref Navop) loop: for(;;) { navop := <- c; - say(sprint("have navop, path=%bd", navop.path)); + if(dflag) say(sprint("have navop, path=%bd", navop.path)); pick n := navop { Stat => - say(sprint("have stat")); + if(dflag) say(sprint("have stat")); n.reply <-= (get(int n.path).stat(), nil); Walk => - say(sprint("have walk, name=%q", n.name)); + if(dflag) say(sprint("have walk, name=%q", n.name)); ed := getdir(int n.path); (ne, err) := walk(ed, n.name); if(err != nil) { @@ -370,7 +375,7 @@ loop: n.reply <-= (ne.stat(), nil); Readdir => - say(sprint("have readdir path=%bd offset=%d count=%d", n.path, n.offset, n.count)); + if(dflag) say(sprint("have readdir path=%bd offset=%d count=%d", n.path, n.offset, n.count)); if(n.path == big 0) { n.reply <-= (nil, nil); break; @@ -423,22 +428,21 @@ loop: user(): string { - if((fd := sys->open("/dev/user", Sys->OREAD)) != nil - && (n := sys->read(fd, d := array[128] of byte, len d)) > 0) + fd := sys->open("/dev/user", Sys->OREAD); + if(fd != nil) + if((n := sys->read(fd, d := array[128] of byte, len d)) > 0) return string d[:n]; return "nobody"; } -error(s: string) +pid(): int { - killgrp(); - fprint(fildes(2), "%s\n", s); - raise "fail:"+s; + return sys->pctl(0, nil); } -warn(s: string) +killgrp(pid: int) { - fprint(fildes(2), "%s\n", s); + sys->fprint(sys->open(sprint("/prog/%d/ctl", pid), sys->OWRITE), "killgrp"); } say(s: string) @@ -447,9 +451,17 @@ say(s: string) warn(s); } -killgrp() +fd2: ref Sys->FD; +warn(s: string) { - fd := sys->open("/prog/"+string sys->pctl(0, nil)+"/ctl", sys->OWRITE); - if(fd != nil) - sys->fprint(fd, "killgrp\n"); + if(fd2 == nil) + fd2 = sys->fildes(2); + sys->fprint(fd2, "%s\n", s); +} + +fail(s: string) +{ + warn(s); + killgrp(pid()); + raise "fail:"+s; } diff --git a/appl/cmd/vacget.b b/appl/cmd/vacget.b index c14ad28a..f0491188 100644 --- a/appl/cmd/vacget.b +++ b/appl/cmd/vacget.b @@ -2,30 +2,33 @@ implement Vacget; include "sys.m"; sys: Sys; + sprint: import sys; include "draw.m"; include "bufio.m"; bufio: Bufio; Iobuf: import bufio; include "arg.m"; +include "dial.m"; + dial: Dial; include "string.m"; + str: String; include "venti.m"; + venti: Venti; + Root, Entry, Score, Session: import venti; include "vac.m"; - -str: String; -venti: Venti; -vac: Vac; - -print, sprint, fprint, fildes: import sys; -Score, Session: import venti; -Roottype, Dirtype, Pointertype0, Datatype: import venti; -Root, Entry, Direntry, Metablock, Metaentry, Entrysize, Modeperm, Modeappend, Modeexcl, Modedir, Modesnapshot, Vacdir, Vacfile, Source: import vac; + vac: Vac; + Direntry, Vacdir, Vacfile: import vac; Vacget: module { init: fn(nil: ref Draw->Context, args: list of string); }; -addr := "net!$venti!venti"; -dflag := vflag := pflag := tflag := 0; +addr := "$venti"; +dflag: int; +vflag: int; +pflag: int; +tflag: int; + session: ref Session; init(nil: ref Draw->Context, args: list of string) @@ -33,26 +36,25 @@ init(nil: ref Draw->Context, args: list of string) sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; arg := load Arg Arg->PATH; + dial = load Dial Dial->PATH; str = load String String->PATH; venti = load Venti Venti->PATH; vac = load Vac Vac->PATH; if(venti == nil || vac == nil) - error("loading venti,vac"); + fail("loading venti,vac"); venti->init(); vac->init(); arg->init(args); - arg->setusage(sprint("%s [-dtv] [-a addr] [tag:]score", arg->progname())); + arg->setusage(arg->progname()+" [-dtv] [-a addr] [tag:]score"); while((c := arg->opt()) != 0) case c { 'a' => addr = arg->earg(); - 'd' => dflag++; - vac->dflag++; + 'd' => vac->dflag = dflag++; 'p' => pflag++; 't' => tflag++; 'v' => vflag++; - * => warn(sprint("bad option: -%c", c)); - arg->usage(); + * => arg->usage(); } args = arg->argv(); if(len args != 1) @@ -64,27 +66,28 @@ init(nil: ref Draw->Context, args: list of string) if(tag == nil) tag = "vac"; if(tag != "vac") - error("bad score type: "+tag); + fail("bad score type: "+tag); (sok, score) := Score.parse(scorestr); if(sok != 0) - error("bad score: "+scorestr); + fail("bad score: "+scorestr); say("have score"); - (cok, conn) := sys->dial(addr, nil); - if(cok < 0) - error(sprint("dialing %s: %r", addr)); + addr = dial->netmkaddr(addr, "net", "venti"); + cc := dial->dial(addr, nil); + if(cc == nil) + fail(sprint("dialing %s: %r", addr)); say("have connection"); - fd := conn.dfd; + fd := cc.dfd; session = Session.new(fd); if(session == nil) - error(sprint("handshake: %r")); + fail(sprint("handshake: %r")); say("have handshake"); (vd, nil, err) := vac->vdroot(session, score); if(err != nil) - error(err); + fail(err); say("starting walk"); walk(".", vd); @@ -120,21 +123,21 @@ walk(path: string, vd: ref Vacdir) for(;;) { (n, de) := vd.readdir(); if(n < 0) - error(sprint("reading direntry in %s: %r", path)); + fail(sprint("reading direntry in %s: %r", path)); if(n == 0) break; - say("walk: have direntry, elem="+de.elem); + if(dflag) say("walk: have direntry, elem="+de.elem); newpath := path+"/"+de.elem; (e, me) := vd.open(de); if(e == nil) - error(sprint("reading entry for %s: %r", newpath)); + fail(sprint("reading entry for %s: %r", newpath)); - oflags := de.mode&~(Modeperm|Modeappend|Modeexcl|Modedir|Modesnapshot); + oflags := de.mode&~(vac->Modeperm|vac->Modeappend|vac->Modeexcl|vac->Modedir|vac->Modesnapshot); if(oflags) warn(sprint("%s: not all bits in mode can be set: 0x%x", newpath, oflags)); if(tflag || vflag) - print("%s\n", newpath); + sys->print("%s\n", newpath); if(me != nil) { if(!tflag) @@ -148,10 +151,10 @@ walk(path: string, vd: ref Vacdir) say("writing file"); fd := create(newpath, sys->OWRITE, de); if(fd == nil) - error(sprint("creating %s: %r", newpath)); + fail(sprint("creating %s: %r", newpath)); bio := bufio->fopen(fd, bufio->OWRITE); if(bio == nil) - error(sprint("bufio fopen %s: %r", newpath)); + fail(sprint("bufio fopen %s: %r", newpath)); buf := array[sys->ATOMICIO] of byte; vf := Vacfile.new(session, e); @@ -160,15 +163,15 @@ walk(path: string, vd: ref Vacdir) if(rn == 0) break; if(rn < 0) - error(sprint("reading vac %s: %r", newpath)); + fail(sprint("reading vac %s: %r", newpath)); wn := bio.write(buf, rn); if(wn != rn) - error(sprint("writing local %s: %r", newpath)); + fail(sprint("writing local %s: %r", newpath)); } bok := bio.flush(); bio.close(); if(bok == bufio->ERROR || bok == bufio->EOF) - error(sprint("bufio close: %r")); + fail(sprint("bufio close: %r")); if(pflag) { d := sys->nulldir; @@ -181,19 +184,22 @@ walk(path: string, vd: ref Vacdir) } } -error(s: string) +say(s: string) { - fprint(fildes(2), "%s\n", s); - raise "fail:"+s; + if(dflag) + warn(s); } +fd2: ref Sys->FD; warn(s: string) { - fprint(fildes(2), "%s\n", s); + if(fd2 == nil) + fd2 = sys->fildes(2); + sys->fprint(fd2, "%s\n", s); } -say(s: string) +fail(s: string) { - if(dflag) - warn(s); + warn(s); + raise "fail:"+s; } diff --git a/appl/cmd/vacput.b b/appl/cmd/vacput.b index e01bdd36..a1a07a48 100644 --- a/appl/cmd/vacput.b +++ b/appl/cmd/vacput.b @@ -2,81 +2,113 @@ implement Vacput; include "sys.m"; sys: Sys; + sprint: import sys; include "draw.m"; +include "arg.m"; include "daytime.m"; + dt: Daytime; include "bufio.m"; bufio: Bufio; Iobuf: import bufio; -include "arg.m"; +include "dial.m"; + dial: Dial; include "string.m"; + str: String; +include "tables.m"; + tables: Tables; + Strhash: import tables; include "venti.m"; + venti: Venti; + Root, Entry, Score, Session: import venti; include "vac.m"; - -daytime: Daytime; -str: String; -venti: Venti; -vac: Vac; - -print, sprint, fprint, fildes: import sys; -Score, Session: import venti; -Roottype, Dirtype, Pointertype0, Datatype: import venti; -Root, Entry, Direntry, Metablock, Metaentry, Entrysize, File, Sink, MSink: import vac; + vac: Vac; + Direntry, File, Sink, MSink: import vac; Vacput: module { init: fn(nil: ref Draw->Context, args: list of string); }; -addr := "net!$venti!venti"; -dflag := 0; -vflag := 0; +addr := "$venti"; +dflag: int; +iflag: int; +vflag: int; +xflag: int; blocksize := vac->Dsize; +uid: string; +gid: string; + +pathgen: big; + +bout: ref Iobuf; session: ref Session; name := "vac"; +itab, +xtab: ref Strhash[string]; # include/exclude paths init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; - daytime = load Daytime Daytime->PATH; + dt = load Daytime Daytime->PATH; bufio = load Bufio Bufio->PATH; arg := load Arg Arg->PATH; + dial = load Dial Dial->PATH; str = load String String->PATH; + tables = load Tables Tables->PATH; venti = load Venti Venti->PATH; vac = load Vac Vac->PATH; if(venti == nil || vac == nil) - error("loading venti,vac"); + fail("loading venti,vac"); venti->init(); vac->init(); arg->init(args); - arg->setusage(sprint("%s [-dtv] [-a addr] [-b blocksize] [-n name] path ...", arg->progname())); + arg->setusage(arg->progname()+" [-dv] [-i | -x] [-a addr] [-b blocksize] [-n name] [-u uid] [-g gid] path ..."); while((c := arg->opt()) != 0) case c { 'a' => addr = arg->earg(); 'b' => blocksize = int arg->earg(); 'n' => name = arg->earg(); - 'd' => dflag++; - vac->dflag++; + 'd' => vac->dflag = dflag++; + 'i' => iflag++; 'v' => vflag++; - * => warn(sprint("bad option: -%c", c)); - arg->usage(); + 'x' => xflag++; + 'g' => gid = arg->earg(); + 'u' => uid = arg->earg(); + * => arg->usage(); } args = arg->argv(); if(len args == 0) arg->usage(); + if(iflag && xflag) { + warn("cannot have both -i and -x"); + arg->usage(); + } - (cok, conn) := sys->dial(addr, nil); - if(cok < 0) - error(sprint("dialing %s: %r", addr)); + if(vflag) + bout = bufio->fopen(sys->fildes(1), bufio->OWRITE); + + if(iflag || xflag) { + t := readpaths(); + if(iflag) + itab = t; + else + xtab = t; + } + + addr = dial->netmkaddr(addr, "net", "venti"); + cc := dial->dial(addr, nil); + if(cc == nil) + fail(sprint("dialing %s: %r", addr)); say("have connection"); - fd := conn.dfd; + fd := cc.dfd; session = Session.new(fd); if(session == nil) - error(sprint("handshake: %r")); + fail(sprint("handshake: %r")); say("have handshake"); topde: ref Direntry; - if(len args == 1 && ((nil, d) := sys->stat(hd args)).t0 == 0 && d.mode&Sys->DMDIR) { + if(len args == 1 && ((nil, d) := sys->stat(hd args)).t0 == 0 && (d.mode&Sys->DMDIR)) { topde = Direntry.mk(d); topde.elem = name; } else { @@ -86,7 +118,12 @@ init(nil: ref Draw->Context, args: list of string) topde.mode = 8r777|Vac->Modedir; topde.mtime = topde.atime = 0; } - topde.ctime = daytime->now(); + topde.qid = pathgen++; + if(uid != nil) + topde.uid = uid; + if(gid != nil) + topde.gid = gid; + topde.ctime = dt->now(); s := Sink.new(session, blocksize); ms := MSink.new(session, blocksize); @@ -94,66 +131,93 @@ init(nil: ref Draw->Context, args: list of string) writepath(hd args, s, ms); say("tree written"); + if(vflag && bout.flush() == bufio->ERROR) + fail(sprint("write stdout: %r")); + e0 := s.finish(); if(e0 == nil) - error(sprint("writing top entry: %r")); + fail(sprint("writing top entry: %r")); e1 := ms.finish(); if(e1 == nil) - error(sprint("writing top meta entry: %r")); - say(sprint("top entries written (%s, %s)", e0.score.text(), e1.score.text())); + fail(sprint("writing top meta entry: %r")); + topde.qidspace = 1; + topde.qidoff = big 0; + topde.qidmax = pathgen; s2 := MSink.new(session, blocksize); if(s2.add(topde) < 0) - error(sprint("adding direntry for top entries: %r")); + fail(sprint("adding direntry for top entries: %r")); e2 := s2.finish(); say("top meta entry written, "+e2.score.text()); - td := array[Entrysize*3] of byte; - td[0*Entrysize:] = e0.pack(); - td[1*Entrysize:] = e1.pack(); - td[2*Entrysize:] = e2.pack(); - (tok, tscore) := session.write(Dirtype, td); + td := array[venti->Entrysize*3] of byte; + td[0*venti->Entrysize:] = e0.pack(); + td[1*venti->Entrysize:] = e1.pack(); + td[2*venti->Entrysize:] = e2.pack(); + (tok, tscore) := session.write(venti->Dirtype, td); if(tok < 0) - error(sprint("writing top-level entries: %r")); - say("top entry written, "+tscore.text()); + fail(sprint("writing top-level entries: %r")); - root := Root.new(name, "vac", tscore, blocksize, nil); + root := ref Root(venti->Rootversion, name, "vac", tscore, blocksize, nil); rd := root.pack(); if(rd == nil) - error(sprint("root pack: %r")); - (rok, rscore) := session.write(Roottype, rd); + fail(sprint("root pack: %r")); + (rok, rscore) := session.write(venti->Roottype, rd); if(rok < 0) - error(sprint("writing root score: %r")); - say("root written, "+rscore.text()); - print("vac:%s\n", rscore.text()); + fail(sprint("writing root score: %r")); + sys->print("vac:%s\n", rscore.text()); if(session.sync() < 0) - error(sprint("syncing server: %r")); + fail(sprint("syncing server: %r")); +} + +readpaths(): ref Strhash[string] +{ + t := Strhash[string].new(199, nil); + b := bufio->fopen(sys->fildes(0), bufio->OREAD); + if(b == nil) + fail(sprint("fopen: %r")); + for(;;) { + s := b.gets('\n'); + if(s == nil) + break; + if(s[len s-1] == '\n') + s = s[:len s-1]; + t.add(s, s); + } + return t; +} + +usepath(p: string): int +{ + if(itab != nil) + return itab.find(p) != nil; + if(xtab != nil) + return xtab.find(p) == nil; + return 1; } writepath(path: string, s: ref Sink, ms: ref MSink) { - if(vflag) - print("%s\n", path); -say("writepath "+path); + if(!usepath(path)) + return; + + if(vflag && bout.puts(path+"\n") == bufio->ERROR) + fail(sprint("write stdout: %r")); + fd := sys->open(path, sys->OREAD); if(fd == nil) - error(sprint("opening %s: %r", path)); + fail(sprint("opening %s: %r", path)); (ok, dir) := sys->fstat(fd); if(ok < 0) - error(sprint("fstat %s: %r", path)); -say("writepath: file opened"); - if(dir.mode&sys->DMAUTH) { - warn(path+": is auth file, skipping"); - return; - } - if(dir.mode&sys->DMTMP) { - warn(path+": is temporary file, skipping"); - return; - } + fail(sprint("fstat %s: %r", path)); + if(dir.mode&sys->DMAUTH) + return warn(path+": is auth file, skipping"); + if(dir.mode&sys->DMTMP) + return warn(path+": is temporary file, skipping"); e, me: ref Entry; de: ref Direntry; + qid := pathgen++; if(dir.mode & sys->DMDIR) { -say("writepath: file is dir"); ns := Sink.new(session, blocksize); nms := MSink.new(session, blocksize); for(;;) { @@ -161,7 +225,7 @@ say("writepath: file is dir"); if(n == 0) break; if(n < 0) - error(sprint("dirread %s: %r", path)); + fail(sprint("dirread %s: %r", path)); for(i := 0; i < len dirs; i++) { d := dirs[i]; npath := path+"/"+d.name; @@ -170,45 +234,49 @@ say("writepath: file is dir"); } e = ns.finish(); if(e == nil) - error(sprint("error flushing dirsink for %s: %r", path)); + fail(sprint("error flushing dirsink for %s: %r", path)); me = nms.finish(); if(me == nil) - error(sprint("error flushing metasink for %s: %r", path)); + fail(sprint("error flushing metasink for %s: %r", path)); } else { -say("writepath: file is normale file"); e = writefile(path, fd); if(e == nil) - error(sprint("error flushing filesink for %s: %r", path)); + fail(sprint("error flushing filesink for %s: %r", path)); } -say("writepath: wrote path, "+e.score.text()); + case dir.name { + "/" => dir.name = "root"; + "." => dir.name = "dot"; + } de = Direntry.mk(dir); -say("writepath: have direntry"); + de.qid = qid; + if(uid != nil) + de.uid = uid; + if(gid != nil) + de.gid = gid; i := s.add(e); if(i < 0) - error(sprint("adding entry to sink: %r")); + fail(sprint("adding entry to sink: %r")); mi := 0; if(me != nil) mi = s.add(me); if(mi < 0) - error(sprint("adding mentry to sink: %r")); + fail(sprint("adding mentry to sink: %r")); de.entry = i; de.mentry = mi; i = ms.add(de); if(i < 0) - error(sprint("adding direntry to msink: %r")); -say("writepath done"); + fail(sprint("adding direntry to msink: %r")); } writefile(path: string, fd: ref Sys->FD): ref Entry { bio := bufio->fopen(fd, bufio->OREAD); if(bio == nil) - error(sprint("bufio opening %s: %r", path)); - say(sprint("bufio opened path %s", path)); + fail(sprint("bufio opening %s: %r", path)); - f := File.new(session, Datatype, blocksize); + f := File.new(session, venti->Datatype, blocksize); for(;;) { buf := array[blocksize] of byte; n := 0; @@ -218,13 +286,12 @@ writefile(path: string, fd: ref Sys->FD): ref Entry if(have == 0) break; if(have < 0) - error(sprint("reading %s: %r", path)); + fail(sprint("reading %s: %r", path)); n += have; } - say(sprint("have buf, length %d", n)); if(f.write(buf[:n]) < 0) - error(sprint("writing %s: %r", path)); + fail(sprint("writing %s: %r", path)); if(n != len buf) break; } @@ -234,21 +301,19 @@ writefile(path: string, fd: ref Sys->FD): ref Entry user(): string { - if((fd := sys->open("/dev/user", Sys->OREAD)) != nil - && (n := sys->read(fd, d := array[128] of byte, len d)) > 0) + fd := sys->open("/dev/user", Sys->OREAD); + if(fd != nil) + if((n := sys->read(fd, d := array[128] of byte, len d)) > 0) return string d[:n]; return "nobody"; } -error(s: string) -{ - warn(s); - raise "fail:"+s; -} - +fd2: ref Sys->FD; warn(s: string) { - fprint(fildes(2), "%s\n", s); + if(fd2 == nil) + fd2 = sys->fildes(2); + sys->fprint(fd2, "%s\n", s); } say(s: string) @@ -256,3 +321,9 @@ say(s: string) if(dflag) warn(s); } + +fail(s: string) +{ + warn(s); + raise "fail:"+s; +} diff --git a/appl/lib/vac.b b/appl/lib/vac.b index 2ea78c12..829f3d37 100644 --- a/appl/lib/vac.b +++ b/appl/lib/vac.b @@ -1,19 +1,17 @@ implement Vac; include "sys.m"; + sys: Sys; + sprint: import sys; include "venti.m"; + venti: Venti; + Entrysize, Scoresize, Roottype, Dirtype, Pointertype0, Datatype: import venti; + Root, Entry, Score, Session: import venti; include "vac.m"; -sys: Sys; -venti: Venti; - -werrstr, sprint, fprint, fildes: import sys; -Roottype, Dirtype, Pointertype0, Datatype: import venti; -Score, Session, Scoresize: import venti; dflag = 0; -# from venti.b BIT8SZ: con 1; BIT16SZ: con 2; BIT32SZ: con 4; @@ -32,7 +30,6 @@ blankdirentry: Direntry; blankmetablock: Metablock; blankmetaentry: Metaentry; - init() { sys = load Sys Sys->PATH; @@ -40,158 +37,9 @@ init() venti->init(); } -pstring(a: array of byte, o: int, s: string): int -{ - sa := array of byte s; # could do conversion ourselves - n := len sa; - a[o] = byte (n >> 8); - a[o+1] = byte n; - a[o+2:] = sa; - return o+BIT16SZ+n; -} - -gstring(a: array of byte, o: int): (string, int) -{ - if(o < 0 || o+BIT16SZ > len a) - return (nil, -1); - l := (int a[o] << 8) | int a[o+1]; - if(l > Maxstringsize) - return (nil, -1); - o += BIT16SZ; - e := o+l; - if(e > len a) - return (nil, -1); - return (string a[o:e], e); -} - -gtstring(a: array of byte, o: int, n: int): string -{ - e := o + n; - if(e > len a) - return nil; - for(i := o; i < e; i++) - if(a[i] == byte 0) - break; - return string a[o:i]; -} - - -Root.new(name, rtype: string, score: Score, blocksize: int, prev: ref Score): ref Root -{ - return ref Root(Rootversion, name, rtype, score, blocksize, prev); -} - -Root.pack(r: self ref Root): array of byte -{ - d := array[Rootsize] of byte; - i := 0; - i = p16(d, i, r.version); - i = ptstring(d, i, r.name, Rootnamelen); - if(i < 0) - return nil; - i = ptstring(d, i, r.rtype, Rootnamelen); - if(i < 0) - return nil; - i = pscore(d, i, r.score); - i = p16(d, i, r.blocksize); - if(r.prev == nil) { - for(j := 0; j < Scoresize; j++) - d[i+j] = byte 0; - i += Scoresize; - } else - i = pscore(d, i, *r.prev); - if(i != len d) { - sys->werrstr("root pack, bad length: "+string i); - return nil; - } - return d; -} - -Root.unpack(d: array of byte): ref Root -{ - if(len d != Rootsize){ - sys->werrstr("root entry is wrong length"); - return nil; - } - r := ref blankroot; - r.version = g16(d, 0); - if(r.version != Rootversion){ - sys->werrstr("unknown root version"); - return nil; - } - o := BIT16SZ; - r.name = gtstring(d, o, Rootnamelen); - o += Rootnamelen; - r.rtype = gtstring(d, o, Rootnamelen); - o += Rootnamelen; - r.score = gscore(d, o); - o += Scoresize; - r.blocksize = g16(d, o); - o += BIT16SZ; - r.prev = ref gscore(d, o); - return r; -} - -Entry.new(psize, dsize, flags: int, size: big, score: Venti->Score): ref Entry -{ - return ref Entry(0, psize, dsize, (flags&Entrydepthmask)>>Entrydepthshift, flags, size, score); -} - -Entry.pack(e: self ref Entry): array of byte -{ - d := array[Entrysize] of byte; - i := 0; - i = p32(d, i, e.gen); - i = p16(d, i, e.psize); - i = p16(d, i, e.dsize); - e.flags |= e.depth<werrstr("entry is wrong length"); - return nil; - } - e := ref blankentry; - i := 0; - e.gen = g32(d, i); - i += BIT32SZ; - e.psize = g16(d, i); - i += BIT16SZ; - e.dsize = g16(d, i); - i += BIT16SZ; - e.flags = int d[i]; - e.depth = (e.flags & Entrydepthmask) >> Entrydepthshift; - e.flags &= ~Entrydepthmask; - i += BIT8SZ; - i += 5; # skip something... - e.size = g48(d, i); - i += BIT48SZ; - e.score = gscore(d, i); - i += Scoresize; - if((e.flags & Entryactive) == 0) - return e; - if(!checksize(e.psize) || !checksize(e.dsize)){ - sys->werrstr(sys->sprint("bad blocksize (%d or %d)", e.psize, e.dsize)); - return nil; - } - return e; -} - Direntry.new(): ref Direntry { - return ref Direntry(9, "", 0, 0, 0, 0, big 0, "", "", "", 0, 0, 0, 0, 0, 0); + return ref Direntry(9, "", 0, 0, 0, 0, big 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, big 0, big 0); } Direntry.mk(d: Sys->Dir): ref Direntry @@ -206,7 +54,7 @@ Direntry.mk(d: Sys->Dir): ref Direntry mode |= Modedir; if(d.mode&sys->DMTMP) mode |= Modetemp; - return ref Direntry(9, d.name, 0, 0, 0, 0, d.qid.path, d.uid, d.gid, d.muid, d.mtime, 0, 0, atime, mode, d.mode); + return ref Direntry(9, d.name, 0, 0, 0, 0, d.qid.path, d.uid, d.gid, d.muid, d.mtime, 0, 0, atime, mode, d.mode, 0, big 0, big 0); } Direntry.mkdir(de: self ref Direntry): ref Sys->Dir @@ -233,8 +81,14 @@ strlen(s: string): int Direntry.pack(de: self ref Direntry): array of byte { - # assume version 9 - length := 4+2+strlen(de.elem)+4+4+4+4+8+strlen(de.uid)+strlen(de.gid)+strlen(de.mid)+4+4+4+4+4; # + qidspace? + if(de.version != 9) { + sys->werrstr("only version 9 supported"); + return nil; + } + + length := 4+2+strlen(de.elem)+4+4+4+4+8+strlen(de.uid)+strlen(de.gid)+strlen(de.mid)+4+4+4+4+4; + if(de.qidspace) + length += 1+2+8+8; d := array[length] of byte; i := 0; @@ -256,8 +110,14 @@ Direntry.pack(de: self ref Direntry): array of byte i = p32(d, i, de.ctime); i = p32(d, i, de.atime); i = p32(d, i, de.mode); + if(de.qidspace) { + d[i++] = byte DirQidspace; + i = p16(d, i, 16); + i = p64(d, i, de.qidoff); + i = p64(d, i, de.qidmax); + } if(i != len d) { - werrstr(sprint("bad length for direntry (expected %d, have %d)", len d, i)); + sys->werrstr(sprint("bad length for direntry (expected %d, have %d)", len d, i)); return nil; } return d; @@ -271,12 +131,12 @@ Direntry.unpack(d: array of byte): ref Direntry magic: int; (magic, i) = eg32(d, i); if(magic != Direntrymagic) { - werrstr(sprint("bad magic (%x, want %x)", magic, Direntrymagic)); + sys->werrstr(sprint("bad magic (%x, want %x)", magic, Direntrymagic)); return nil; } (de.version, i) = eg16(d, i); if(de.version != 8 && de.version != 9) { - werrstr(sprint("bad version (%d)", de.version)); + sys->werrstr(sprint("bad version (%d)", de.version)); return nil; } (de.elem, i) = egstring(d, i); @@ -309,12 +169,28 @@ Direntry.unpack(d: array of byte): ref Direntry de.emode |= sys->DMDIR; if(de.mode&Modetemp) de.emode |= sys->DMTMP; - if(de.version == 9) - ; # xxx handle qid space?, can be in here + while(i < len d) { + t := int d[i++]; + n: int; + (n, i) = eg16(d, i); + case t { + DirQidspace => + if(n != 16) { + sys->werrstr(sprint("invalid qidspace length %d", n)); + return nil; + } + de.qidspace = 1; + (de.qidoff, i) = eg64(d, i); + (de.qidmax, i) = eg64(d, i); + * => + # ignore other optional fields + i += n; + } + } return de; } exception e { "too small:*" => - werrstr("direntry "+e); + sys->werrstr("direntry "+e); return nil; * => raise e; @@ -340,13 +216,13 @@ Metablock.pack(mb: self ref Metablock, d: array of byte) Metablock.unpack(d: array of byte): ref Metablock { if(len d < Metablocksize) { - werrstr(sprint("bad length for metablock (%d, want %d)", len d, Metablocksize)); + sys->werrstr(sprint("bad length for metablock (%d, want %d)", len d, Metablocksize)); return nil; } i := 0; magic := g32(d, i); if(magic != Metablockmagic && magic != Metablockmagic+1) { - werrstr(sprint("bad magic for metablock (%x, need %x)", magic, Metablockmagic)); + sys->werrstr(sprint("bad magic for metablock (%x, need %x)", magic, Metablockmagic)); return nil; } i += BIT32SZ; @@ -361,7 +237,7 @@ Metablock.unpack(d: array of byte): ref Metablock mb.nindex = g16(d, i); i += BIT16SZ; if(mb.nindex == 0) { - werrstr("bad metablock, nindex=0"); + sys->werrstr("bad metablock, nindex=0"); return nil; } return mb; @@ -378,7 +254,7 @@ Metaentry.unpack(d: array of byte, i: int): ref Metaentry { o := Metablocksize+i*Metaentrysize; if(o+Metaentrysize > len d) { - werrstr(sprint("meta entry lies outside meta block, i=%d", i)); + sys->werrstr(sprint("meta entry lies outside meta block, i=%d", i)); return nil; } @@ -388,7 +264,7 @@ Metaentry.unpack(d: array of byte, i: int): ref Metaentry me.size = g16(d, o); o += BIT16SZ; if(me.offset+me.size > len d) { - werrstr(sprint("meta entry points outside meta block, i=%d", i)); + sys->werrstr(sprint("meta entry points outside meta block, i=%d", i)); return nil; } return me; @@ -435,14 +311,14 @@ fflush(f: ref File, last: int): (int, ref Entry) if(!last && !f.p[i].full()) return (0, nil); if(last && f.p[i].o == Scoresize) { - flags := Entryactive; + flags := venti->Entryactive; if(f.dtype == Dirtype) - flags |= Entrydir; - flags |= i<Entrydir; + flags |= i<Entrydepthshift; score := Score(f.p[i].data()); if(len score.a == 0) score = Score.zero(); - return (0, Entry.new(len f.p[i].d, f.dsize, flags, f.size, score)); + return (0, ref Entry(0, len f.p[i].d, f.dsize, i, flags, f.size, score)); } (ok, score) := f.s.write(Pointertype0+i, f.p[i].data()); if(ok < 0) @@ -456,7 +332,7 @@ fflush(f: ref File, last: int): (int, ref Entry) } f.p[i+1].add(score); } - werrstr("internal error in fflush"); + sys->werrstr("internal error in fflush"); return (-1, nil); } @@ -601,7 +477,7 @@ MSink.add(m: self ref MSink, de: ref Direntry): int d := de.pack(); if(d == nil) return -1; -say(sprint("msink: adding direntry, length %d", len d)); +if(dflag) say(sprint("msink: adding direntry, length %d", len d)); if(Metablocksize+len m.l*Metaentrysize+m.nde + Metaentrysize+len d > len m.de) if(mflush(m, 0) < 0) return -1; @@ -621,7 +497,7 @@ MSink.finish(m: self ref MSink): ref Entry Source.new(s: ref Session, e: ref Entry): ref Source { dsize := e.dsize; - if(e.flags&Entrydir) + if(e.flags&venti->Entrydir) dsize = Entrysize*(dsize/Entrysize); return ref Source(s, e, dsize); } @@ -660,7 +536,7 @@ Source.get(s: self ref Source, i: big, d: array of byte): int dtype := Pointertype0+depth-1; if(depth == 0) { dtype = Datatype; - if(s.e.flags & Entrydir) + if(s.e.flags & venti->Entrydir) dtype = Dirtype; bsize = want; } @@ -714,11 +590,11 @@ Vacfile.read(v: self ref Vacfile, d: array of byte, n: int): int Vacfile.pread(v: self ref Vacfile, d: array of byte, n: int, offset: big): int { dsize := v.s.dsize; -say(sprint("vf.preadn, len d %d, n %d, offset %bd", len d, n, offset)); +if(dflag) say(sprint("vf.preadn, len d %d, n %d, offset %bd", len d, n, offset)); have := v.s.get(big (offset/big dsize), buf := array[dsize] of byte); if(have <= 0) return have; -say(sprint("vacfile.pread: have=%d dsize=%d", have, dsize)); +if(dflag) say(sprint("vacfile.pread: have=%d dsize=%d", have, dsize)); o := int (offset % big dsize); have -= o; if(have > n) @@ -752,7 +628,7 @@ mecmp(d: array of byte, i: int, elem: string, fromfossil: int): (int, int) n := g16(d, o); o += BIT16SZ; if(o+n > len d) { - werrstr("bad elem in direntry"); + sys->werrstr("bad elem in direntry"); return (0, 1); } return (elemcmp(d[o:o+n], array of byte elem, fromfossil), 0); @@ -801,54 +677,56 @@ Vacdir.walk(v: self ref Vacdir, elem: string): ref Direntry return de; i++; } - werrstr(sprint("no such file or directory")); + sys->werrstr(sprint("no such file or directory")); return nil; } vfreadentry(vf: ref Vacfile, entry: int): ref Entry { -say(sprint("vfreadentry: reading entry=%d", entry)); +if(dflag) say(sprint("vfreadentry: reading entry=%d", entry)); ebuf := array[Entrysize] of byte; n := vf.pread(ebuf, len ebuf, big entry*big Entrysize); if(n < 0) return nil; if(n != len ebuf) { - werrstr(sprint("bad archive, entry=%d not present (read %d, wanted %d)", entry, n, len ebuf)); + sys->werrstr(sprint("bad archive, entry=%d not present (read %d, wanted %d)", entry, n, len ebuf)); return nil; } e := Entry.unpack(ebuf); - if(~e.flags&Entryactive) { - werrstr("entry not active"); + if(e == nil) + return nil; + if(~e.flags&venti->Entryactive) { + sys->werrstr("entry not active"); return nil; } # p9p writes archives with Entrylocal set? - if(0 && e.flags&Entrylocal) { - werrstr("entry is local"); + if(0 && e.flags&venti->Entrylocal) { + sys->werrstr("entry is local"); return nil; } -say(sprint("vreadentry: have entry, score=%s", e.score.text())); +if(dflag) say(sprint("vreadentry: have entry, score=%s", e.score.text())); return e; } Vacdir.open(vd: self ref Vacdir, de: ref Direntry): (ref Entry, ref Entry) { -say(sprint("vacdir.open: opening entry=%d", de.entry)); +if(dflag) say(sprint("vacdir.open: opening entry=%d", de.entry)); e := vfreadentry(vd.vf, de.entry); if(e == nil) return (nil, nil); isdir1 := de.mode & Modedir; - isdir2 := e.flags & Entrydir; + isdir2 := e.flags & venti->Entrydir; if(isdir1 && !isdir2 || !isdir1 && isdir2) { - werrstr("direntry directory bit does not match entry directory bit"); + sys->werrstr("direntry directory bit does not match entry directory bit"); return (nil, nil); } -say(sprint("vacdir.open: have entry, score=%s size=%bd", e.score.text(), e.size)); +if(dflag) say(sprint("vacdir.open: have entry, score=%s size=%bd", e.score.text(), e.size)); me: ref Entry; if(de.mode&Modedir) { me = vfreadentry(vd.vf, de.mentry); if(me == nil) return (nil, nil); -say(sprint("vacdir.open: have mentry, score=%s size=%bd", me.score.text(), e.size)); +if(dflag) say(sprint("vacdir.open: have mentry, score=%s size=%bd", me.score.text(), e.size)); } return (e, me); } @@ -860,8 +738,10 @@ readdirentry(buf: array of byte, i: int, allowroot: int): ref Direntry return nil; o := me.offset; de := Direntry.unpack(buf[o:o+me.size]); + if(de == nil) + return nil; if(badelem(de.elem) && !(allowroot && de.elem == "/")) { - werrstr(sprint("bad direntry: %s", de.elem)); + sys->werrstr(sprint("bad direntry: %s", de.elem)); return nil; } return de; @@ -882,12 +762,12 @@ badelem(elem: string): int vdreaddir(vd: ref Vacdir, allowroot: int): (int, ref Direntry) { -say(sprint("vdreaddir: ms.e.size=%bd vd.p=%bd vd.i=%d", vd.ms.e.size, vd.p, vd.i)); +if(dflag) say(sprint("vdreaddir: ms.e.size=%bd vd.p=%bd vd.i=%d", vd.ms.e.size, vd.p, vd.i)); dsize := vd.ms.dsize; n := vd.ms.get(vd.p, buf := array[dsize] of byte); if(n <= 0) return (n, nil); -say(sprint("vdreaddir: have buf, length=%d e.size=%bd", n, vd.ms.e.size)); +if(dflag) say(sprint("vdreaddir: have buf, length=%d e.size=%bd", n, vd.ms.e.size)); mb := Metablock.unpack(buf); if(mb == nil) return (-1, nil); @@ -899,7 +779,7 @@ say(sprint("vdreaddir: have buf, length=%d e.size=%bd", n, vd.ms.e.size)); vd.p++; vd.i = 0; } -say("vdreaddir: have entry"); +if(dflag) say("vdreaddir: have entry"); return (1, de); } @@ -918,20 +798,18 @@ Vacdir.rewind(vd: self ref Vacdir) vdroot(session: ref Session, score: Venti->Score): (ref Vacdir, ref Direntry, string) { - d := session.read(score, Roottype, Rootsize); + d := session.read(score, venti->Roottype, venti->Rootsize); if(d == nil) return (nil, nil, sprint("reading vac score: %r")); r := Root.unpack(d); if(r == nil) return (nil, nil, sprint("bad vac root block: %r")); - say("have root"); topscore := r.score; d = session.read(topscore, Dirtype, 3*Entrysize); if(d == nil) return (nil, nil, sprint("reading rootdir score: %r")); if(len d != 3*Entrysize) { - say("top entries not in directory of 3 elements, assuming it's from fossil"); if(len d % Entrysize != 0 && len d == 2*Entrysize != 0) # what's in the second 40 bytes? looks like 2nd 20 bytes of it is zero score return (nil, nil, sprint("bad fossil rootdir, have %d bytes, need %d or %d", len d, Entrysize, 2*Entrysize)); e := Entry.unpack(d[:Entrysize]); @@ -941,9 +819,7 @@ vdroot(session: ref Session, score: Venti->Score): (ref Vacdir, ref Direntry, st d = session.read(topscore, Dirtype, 3*Entrysize); if(d == nil) return (nil, nil, sprint("reading fossil rootdir block: %r")); - say("have fossil top entries"); } - say("have top entries"); e := array[3] of ref Entry; j := 0; @@ -953,14 +829,13 @@ vdroot(session: ref Session, score: Venti->Score): (ref Vacdir, ref Direntry, st return (nil, nil, sprint("reading root entry %d: %r", j)); j++; } - say("top entries unpacked"); +if(dflag) say("top entries unpacked"); mroot := Vacdir.mk(nil, Source.new(session, e[2])); (ok, de) := vdreaddir(mroot, 1); if(ok <= 0) return (nil, nil, sprint("reading root meta entry: %r")); -say(sprint("vdroot: new score=%s", score.text())); return (Vacdir.new(session, e[0], e[1]), de, nil); } @@ -974,6 +849,32 @@ checksize(n: int): int return 1; } + +gstring(a: array of byte, o: int): (string, int) +{ + if(o < 0 || o+BIT16SZ > len a) + return (nil, -1); + l := (int a[o] << 8) | int a[o+1]; + if(l > Maxstringsize) + return (nil, -1); + o += BIT16SZ; + e := o+l; + if(e > len a) + return (nil, -1); + return (string a[o:e], e); +} + +gtstring(a: array of byte, o: int, n: int): string +{ + e := o + n; + if(e > len a) + return nil; + for(i := o; i < e; i++) + if(a[i] == byte 0) + break; + return string a[o:i]; +} + gscore(f: array of byte, i: int): Score { s := Score(array[Scoresize] of byte); @@ -993,16 +894,12 @@ g32(f: array of byte, i: int): int g48(f: array of byte, i: int): big { - b1 := (((((int f[i+0] << 8) | int f[i+1]) << 8) | int f[i+2]) << 8) | int f[i+3]; - b0 := (int f[i+4] << 8) | int f[i+5]; - return (big b1 << 16) | big b0; + return big g16(f, i)<<32 | (big g32(f, i+2) & 16rFFFFFFFF); } g64(f: array of byte, i: int): big { - b0 := (((((int f[i+3] << 8) | int f[i+2]) << 8) | int f[i+1]) << 8) | int f[i]; - b1 := (((((int f[i+7] << 8) | int f[i+6]) << 8) | int f[i+5]) << 8) | int f[i+4]; - return (big b1 << 32) | (big b0 & 16rFFFFFFFF); + return big g32(f, i)<<32 | (big g32(f, i+4) & 16rFFFFFFFF); } p16(d: array of byte, i: int, v: int): int @@ -1033,6 +930,16 @@ p64(d: array of byte, i: int, v: big): int return i+BIT64SZ; } +pstring(a: array of byte, o: int, s: string): int +{ + sa := array of byte s; # could do conversion ourselves + n := len sa; + a[o] = byte (n >> 8); + a[o+1] = byte n; + a[o+2:] = sa; + return o+BIT16SZ+n; +} + ptstring(d: array of byte, i: int, s: string, l: int): int { a := array of byte s; @@ -1101,5 +1008,5 @@ eg64(f: array of byte, i: int): (big, int) say(s: string) { if(dflag) - fprint(fildes(2), "%s\n", s); + sys->fprint(sys->fildes(2), "%s\n", s); } diff --git a/appl/lib/venti.b b/appl/lib/venti.b index 94235a0e..cfb3a8ec 100644 --- a/appl/lib/venti.b +++ b/appl/lib/venti.b @@ -2,6 +2,7 @@ implement Venti; include "sys.m"; sys: Sys; + sprint: import sys; include "venti.m"; BIT8SZ: con 1; @@ -566,7 +567,34 @@ gtstring(a: array of byte, o: int, n: int): string break; return string a[o:i]; } -unpackroot(d: array of byte): ref Root + +Root.pack(r: self ref Root): array of byte +{ + d := array[Rootsize] of byte; + i := 0; + i = p16(d, i, r.version); + i = ptstring(d, i, r.name, Rootnamelen); + if(i < 0) + return nil; + i = ptstring(d, i, r.rtype, Rootnamelen); + if(i < 0) + return nil; + i = pscore(d, i, r.score); + i = p16(d, i, r.blocksize); + if(r.prev == nil) { + for(j := 0; j < Scoresize; j++) + d[i+j] = byte 0; + i += Scoresize; + } else + i = pscore(d, i, *r.prev); + if(i != len d) { + sys->werrstr("root pack, bad length: "+string i); + return nil; + } + return d; +} + +Root.unpack(d: array of byte): ref Root { if(len d != Rootsize){ sys->werrstr("root entry is wrong length"); @@ -587,11 +615,34 @@ unpackroot(d: array of byte): ref Root o += Scoresize; r.blocksize = g16(d, o); o += BIT16SZ; - r.prev = gscore(d, o); + prev := gscore(d, o); + if(!prev.eq(Score(array[Scoresize] of {* => byte 0}))) + r.prev = ref prev; return r; } -unpackentry(d: array of byte): ref Entry + +Entry.pack(e: self ref Entry): array of byte +{ + d := array[Entrysize] of byte; + i := 0; + i = p32(d, i, e.gen); + i = p16(d, i, e.psize); + i = p16(d, i, e.dsize); + e.flags |= e.depth<werrstr(sprint("bad length, have %d, want %d", i, len d)); + return nil; + } + return d; +} + +Entry.unpack(d: array of byte): ref Entry { if(len d != Entrysize){ sys->werrstr("entry is wrong length"); @@ -606,7 +657,7 @@ unpackentry(d: array of byte): ref Entry e.dsize = g16(d, i); i += BIT16SZ; e.flags = int d[i]; - e.depth= (e.flags & Entrydepthmask) >> Entrydepthshift; + e.depth = (e.flags & Entrydepthmask) >> Entrydepthshift; e.flags &= ~Entrydepthmask; i += BIT8SZ; i += 5; # skip something... @@ -662,3 +713,45 @@ g64(f: array of byte, i: int): big b1 := (((((int f[i+4] << 8) | int f[i+5]) << 8) | int f[i+6]) << 8) | int f[i+7]; return (big b0 << 32) | (big b1 & 16rFFFFFFFF); } + +p16(d: array of byte, i: int, v: int): int +{ + d[i+0] = byte (v>>8); + d[i+1] = byte v; + return i+BIT16SZ; +} + +p32(d: array of byte, i: int, v: int): int +{ + p16(d, i+0, v>>16); + p16(d, i+2, v); + return i+BIT32SZ; +} + +p48(d: array of byte, i: int, v: big): int +{ + p16(d, i+0, int (v>>32)); + p32(d, i+2, int v); + return i+BIT48SZ; +} + +ptstring(d: array of byte, i: int, s: string, l: int): int +{ + a := array of byte s; + if(len a > l) { + sys->werrstr("string too long: "+s); + return -1; + } + for(j := 0; j < len a; j++) + d[i+j] = a[j]; + while(j < l) + d[i+j++] = byte 0; + return i+l; +} + +pscore(d: array of byte, i: int, s: Score): int +{ + for(j := 0; j < Scoresize; j++) + d[i+j] = s.a[j]; + return i+Scoresize; +} diff --git a/dis/lib/vac.dis b/dis/lib/vac.dis index 7af761b2..12735128 100644 Binary files a/dis/lib/vac.dis and b/dis/lib/vac.dis differ diff --git a/dis/lib/venti.dis b/dis/lib/venti.dis index 262f79e3..482f5389 100644 Binary files a/dis/lib/venti.dis and b/dis/lib/venti.dis differ diff --git a/dis/vacfs.dis b/dis/vacfs.dis index a05ec1b9..33a78ddf 100644 Binary files a/dis/vacfs.dis and b/dis/vacfs.dis differ diff --git a/dis/vacget.dis b/dis/vacget.dis index c68f1c98..722bb59d 100644 Binary files a/dis/vacget.dis and b/dis/vacget.dis differ diff --git a/dis/vacput.dis b/dis/vacput.dis index 2b45397c..82453c52 100644 Binary files a/dis/vacput.dis and b/dis/vacput.dis differ diff --git a/include/version.h b/include/version.h index a736ae91..272b825a 100644 --- a/include/version.h +++ b/include/version.h @@ -1 +1 @@ -#define VERSION "Fourth Edition (20110426)" +#define VERSION "Fourth Edition (20110516)" diff --git a/man/1/vacget b/man/1/vacget index 8a5b04f9..7f364864 100644 --- a/man/1/vacget +++ b/man/1/vacget @@ -15,6 +15,10 @@ vacget, vacput \- venti archive utilities [ .B -vd ] [ +.B -i +| +.B -x +] [ .B -a .I addr ] [ @@ -23,6 +27,10 @@ vacget, vacput \- venti archive utilities ] [ .B -n .I name +] [ +.B -u uid +] [ +.B -g gid ] .I path ... .SH DESCRIPTION @@ -62,14 +70,34 @@ bytes instead of the default 8192 byte blocks. Only for vacput. Use .I name as the name in the root block. Only for vacput. +.TP +.BR -i " or " -x +Read a list of files from stdin to include +.RB ( -i ) +or exclude +.RB ( -x ) +from the (recursively walked) +.I paths +specified on the command-line. +Only for vacput. +.TP +.BI -u " uid" +Use +.I uid +for all files. +Only for vacput. +.TP +.BI -g " gid" +Use +.I gid +for all files. +Only for vacput. .SH SOURCE .B /appl/cmd/vacget.b .br .B /appl/cmd/vacput.b .SH SEE ALSO -.IR vcache (1), .IR venti (2), -.IR vacfs (4), -.IR ventisrv (8) +.IR vacfs (4) .SH BUGS These tools need more testing. diff --git a/man/2/venti b/man/2/venti index fdb0d2ac..27150a86 100644 --- a/man/2/venti +++ b/man/2/venti @@ -8,8 +8,6 @@ venti := load Venti Venti->PATH; Session: import venti; init: fn(); -unpackentry: fn(d: array of byte): ref Entry; -unpackroot: fn(d: array of byte): ref Root; Session: adt { new: fn(fd: ref Sys->FD): ref Session; @@ -48,7 +46,7 @@ Blocks are additionally tagged with a facilitating recovery in the event of corruption. A .B Session -represents an session with a Venti server. +represents a session with a Venti server. .TP .IB s .new(\fIfd\fP) .B New @@ -99,9 +97,7 @@ contains the Venti score for the block that has been written. tells the Venti server to make sure that all data is committed to active storage. .SH SOURCE +.B /module/venti.m +.br .B /appl/lib/venti.b .SH BUGS -to do: -Score adt -entry packing/unpacking -other Vmsgs, Session.rpc()? diff --git a/module/vac.m b/module/vac.m index e9501cd1..4c8700e6 100644 --- a/module/vac.m +++ b/module/vac.m @@ -4,9 +4,6 @@ Vac: module { dflag: int; - # taken from venti.m, merge back later - # some of this needs to be removed from venti.m since it does not belong there - # mode bits Modeperm: con 8r777; Modesticky, @@ -24,45 +21,16 @@ Vac: module { Modedev, Modenamedpipe: con 1<<(9+iota); - Entrysize: con 40; - Rootsize: con 300; Metablocksize: con 12; Metaentrysize: con 4; Dsize: con 8*1024; - Entryactive: con (1<<0); # entry is in use - Entrydir: con (1<<1); # a directory - Entrydepthshift: con 2; # shift for pointer depth - Entrydepthmask: con (16r7<<2); # mask for pointer depth - Entrylocal: con (1<<5); # used for local storage: should not be set for venti blocks - - Root: adt { - version: int; - name: string; - rtype: string; - score: Venti->Score; # to a Dir block - blocksize: int; # maximum block size - prev: ref Venti->Score; # last root block - - new: fn(name, rtype: string, score: Venti->Score, blocksize: int, prev: ref Venti->Score): ref Root; - unpack: fn(d: array of byte): ref Root; - pack: fn(r: self ref Root): array of byte; - }; - - Entry: adt { - gen: int; # generation number (XXX should be unsigned) - psize: int; # pointer block size - dsize: int; # data block size - depth: int; # unpacked from flags - flags: int; - size: big; # (XXX should be unsigned) - score: Venti->Score; - - new: fn(psize, dsize, flags: int, size: big, score: Venti->Score): ref Entry; - pack: fn(e: self ref Entry): array of byte; - unpack: fn(d: array of byte): ref Entry; - }; + # DirPlan9, DirNT & DirGen not valid in version >= 9 + DirPlan9, + DirNT, + DirQidspace, + DirGen: con 1+iota; Direntry: adt { version: int; @@ -72,6 +40,9 @@ Vac: module { qid: big; uid, gid, mid: string; mtime, mcount, ctime, atime, mode, emode: int; + qidspace: int; + qidoff: big; + qidmax: big; new: fn(): ref Direntry; mk: fn(d: Sys->Dir): ref Direntry; @@ -115,7 +86,7 @@ Vac: module { new: fn(s: ref Venti->Session, dtype, dsize: int): ref File; write: fn(f: self ref File, d: array of byte): int; - finish: fn(f: self ref File): ref Entry; + finish: fn(f: self ref File): ref Venti->Entry; }; # for writing venti directories @@ -125,8 +96,8 @@ Vac: module { nd, ne: int; new: fn(s: ref Venti->Session, dsize: int): ref Sink; - add: fn(m: self ref Sink, e: ref Entry): int; - finish: fn(m: self ref Sink): ref Entry; + add: fn(m: self ref Sink, e: ref Venti->Entry): int; + finish: fn(m: self ref Sink): ref Venti->Entry; }; Mentry: adt { @@ -145,16 +116,16 @@ Vac: module { new: fn(s: ref Venti->Session, dsize: int): ref MSink; add: fn(m: self ref MSink, de: ref Direntry): int; - finish: fn(m: self ref MSink): ref Entry; + finish: fn(m: self ref MSink): ref Venti->Entry; }; # for reading pages from a hash tree referenced by an entry Source: adt { session: ref Venti->Session; - e: ref Entry; + e: ref Venti->Entry; dsize: int; # real dsize - new: fn(s: ref Venti->Session, e: ref Entry): ref Source; + new: fn(s: ref Venti->Session, e: ref Venti->Entry): ref Source; get: fn(s: self ref Source, i: big, d: array of byte): int; }; @@ -164,7 +135,7 @@ Vac: module { o: big; mk: fn(s: ref Source): ref Vacfile; - new: fn(session: ref Venti->Session, e: ref Entry): ref Vacfile; + new: fn(session: ref Venti->Session, e: ref Venti->Entry): ref Vacfile; read: fn(v: self ref Vacfile, d: array of byte, n: int): int; seek: fn(v: self ref Vacfile, offset: big): big; pread: fn(v: self ref Vacfile, d: array of byte, n: int, offset: big): int; @@ -178,9 +149,9 @@ Vac: module { i: int; mk: fn(vf: ref Vacfile, ms: ref Source): ref Vacdir; - new: fn(session: ref Venti->Session, e, me: ref Entry): ref Vacdir; + new: fn(session: ref Venti->Session, e, me: ref Venti->Entry): ref Vacdir; walk: fn(v: self ref Vacdir, elem: string): ref Direntry; - open: fn(v: self ref Vacdir, de: ref Direntry): (ref Entry, ref Entry); + open: fn(v: self ref Vacdir, de: ref Direntry): (ref Venti->Entry, ref Venti->Entry); readdir: fn(v: self ref Vacdir): (int, ref Direntry); rewind: fn(v: self ref Vacdir); }; diff --git a/module/venti.m b/module/venti.m index 021d436c..440a276d 100644 --- a/module/venti.m +++ b/module/venti.m @@ -124,7 +124,10 @@ Venti: module { rtype: string; score: Venti->Score; # to a Dir block blocksize: int; # maximum block size - prev: Venti->Score; # last root block + prev: ref Venti->Score; # last root block + + pack: fn(r: self ref Root): array of byte; + unpack: fn(d: array of byte): ref Root; }; Entry: adt { @@ -135,6 +138,9 @@ Venti: module { flags: int; size: big; # (XXX should be unsigned) score: Venti->Score; + + pack: fn(e: self ref Entry): array of byte; + unpack: fn(d: array of byte): ref Entry; }; Score: adt { a: array of byte; @@ -153,7 +159,5 @@ Venti: module { sync: fn(s: self ref Session): int; rpc: fn(s: self ref Session, m: ref Vmsg): (ref Vmsg, string); }; - unpackentry: fn(d: array of byte): ref Entry; - unpackroot: fn(d: array of byte): ref Root; init: fn(); }; diff --git a/opt/README b/opt/README index 98da882b..6c2ffdbd 100644 --- a/opt/README +++ b/opt/README @@ -1 +1,2 @@ optional components live in subdirectories of /opt. +see opt(6) and opt(1) -- cgit v1.2.3