summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorforsyth <forsyth@vitanuova.com>2011-05-16 23:28:07 +0100
committerforsyth <forsyth@vitanuova.com>2011-05-16 23:28:07 +0100
commit2b69dba5038ffd0b59cf30a4c44bce549e5097f8 (patch)
tree385d35337b2895a07a2df21bafeb80dd4536e25d
parentd728e3107d7ae935bc511e72efc8a0c43fdbf0a0 (diff)
20110516-2327
-rw-r--r--CHANGES2
-rw-r--r--appl/cmd/vacfs.b112
-rw-r--r--appl/cmd/vacget.b90
-rw-r--r--appl/cmd/vacput.b245
-rw-r--r--appl/lib/vac.b335
-rw-r--r--appl/lib/venti.b101
-rw-r--r--dis/lib/vac.disbin17880 -> 15720 bytes
-rw-r--r--dis/lib/venti.disbin8873 -> 10115 bytes
-rw-r--r--dis/vacfs.disbin8305 -> 8361 bytes
-rw-r--r--dis/vacget.disbin4203 -> 4130 bytes
-rw-r--r--dis/vacput.disbin6585 -> 6991 bytes
-rw-r--r--include/version.h2
-rw-r--r--man/1/vacget34
-rw-r--r--man/2/venti10
-rw-r--r--module/vac.m63
-rw-r--r--module/venti.m10
-rw-r--r--opt/README1
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<<Entrydepthshift;
- d[i++] = byte e.flags;
- for(j := 0; j < 5; j++)
- d[i++] = byte 0;
- i = p48(d, i, e.size);
- i = pscore(d, i, e.score);
- if(i != len d) {
- 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");
- 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<<Entrydepthshift;
+ flags |= venti->Entrydir;
+ flags |= i<<venti->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<<Entrydepthshift;
+ d[i++] = byte e.flags;
+ for(j := 0; j < 5; j++)
+ d[i++] = byte 0;
+ i = p48(d, i, e.size);
+ i = pscore(d, i, e.score);
+ if(i != len d) {
+ sys->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
--- a/dis/lib/vac.dis
+++ b/dis/lib/vac.dis
Binary files differ
diff --git a/dis/lib/venti.dis b/dis/lib/venti.dis
index 262f79e3..482f5389 100644
--- a/dis/lib/venti.dis
+++ b/dis/lib/venti.dis
Binary files differ
diff --git a/dis/vacfs.dis b/dis/vacfs.dis
index a05ec1b9..33a78ddf 100644
--- a/dis/vacfs.dis
+++ b/dis/vacfs.dis
Binary files differ
diff --git a/dis/vacget.dis b/dis/vacget.dis
index c68f1c98..722bb59d 100644
--- a/dis/vacget.dis
+++ b/dis/vacget.dis
Binary files differ
diff --git a/dis/vacput.dis b/dis/vacput.dis
index 2b45397c..82453c52 100644
--- a/dis/vacput.dis
+++ b/dis/vacput.dis
Binary files 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)