implement Vacget; include "sys.m"; sys: Sys;include "draw.m";include "bufio.m"; bufio: Bufio; Iobuf: import bufio;include "arg.m";include "string.m";include "venti.m";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; Vacget: module { init: fn(nil: ref Draw->Context, args: list of string);}; addr := "net!$venti!venti";dflag := vflag := pflag := tflag := 0;session: ref Session; init(nil: ref Draw->Context, args: list of string){ sys = load Sys Sys->PATH; bufio = load Bufio Bufio->PATH; arg := load Arg Arg->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"); venti->init(); vac->init(); arg->init(args); arg->setusage(sprint("%s [-dtv] [-a addr] [tag:]score", arg->progname())); while((c := arg->opt()) != 0) case c { 'a' => addr = arg->earg(); 'd' => dflag++; vac->dflag++; 'p' => pflag++; 't' => tflag++; 'v' => vflag++; * => warn(sprint("bad option: -%c", c)); arg->usage(); } args = arg->argv(); if(len args != 1) arg->usage(); (tag, scorestr) := str->splitstrr(hd args, ":"); if(tag != nil) tag = tag[:len tag-1]; if(tag == nil) tag = "vac"; if(tag != "vac") error("bad score type: "+tag); (sok, score) := Score.parse(scorestr); if(sok != 0) error("bad score: "+scorestr); say("have score"); (cok, conn) := sys->dial(addr, nil); if(cok < 0) error(sprint("dialing %s: %r", addr)); say("have connection"); fd := conn.dfd; session = Session.new(fd); if(session == nil) error(sprint("handshake: %r")); say("have handshake"); (vd, nil, err) := vac->vdroot(session, score); if(err != nil) error(err); say("starting walk"); walk(".", vd);} create(path: string, omode: int, de: ref Direntry): ref Sys->FD{ perm := Sys->DMDIR | Sys->DMAPPEND | Sys->DMEXCL | Sys->DMTMP; perm &= de.emode; perm |= 8r666; if(de.emode & Sys->DMDIR) perm |= 8r777; fd := sys->create(path, omode, perm); if(fd == nil) return nil; if(pflag) { d := sys->nulldir; d.uid = de.uid; d.gid = de.gid; d.mode = de.emode; if(sys->fwstat(fd, d) != 0) { warn(sprint("fwstat %s for uid/gid/mode: %r", path)); d.uid = d.gid = ""; sys->fwstat(fd, d); } } return fd;} walk(path: string, vd: ref Vacdir){ say("start of walk: "+path); for(;;) { (n, de) := vd.readdir(); if(n < 0) error(sprint("reading direntry in %s: %r", path)); if(n == 0) break; 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)); oflags := de.mode&~(Modeperm|Modeappend|Modeexcl|Modedir|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); if(me != nil) { if(!tflag) create(newpath, Sys->OREAD, de); # ignore error, possibly for already existing dir. # if creating really failed, writing files in the dir will fail later on. walk(newpath, Vacdir.new(session, e, me)); } else { if(tflag) continue; say("writing file"); fd := create(newpath, sys->OWRITE, de); if(fd == nil) error(sprint("creating %s: %r", newpath)); bio := bufio->fopen(fd, bufio->OWRITE); if(bio == nil) error(sprint("bufio fopen %s: %r", newpath)); buf := array[sys->ATOMICIO] of byte; vf := Vacfile.new(session, e); for(;;) { rn := vf.read(buf, len buf); if(rn == 0) break; if(rn < 0) error(sprint("reading vac %s: %r", newpath)); wn := bio.write(buf, rn); if(wn != rn) error(sprint("writing local %s: %r", newpath)); } bok := bio.flush(); bio.close(); if(bok == bufio->ERROR || bok == bufio->EOF) error(sprint("bufio close: %r")); if(pflag) { d := sys->nulldir; d.mtime = de.mtime; if(sys->fwstat(fd, d) < 0) warn(sprint("fwstat %s for mtime: %r", newpath)); } fd = nil; } }} error(s: string){ fprint(fildes(2), "%s\n", s); raise "fail:"+s;} warn(s: string){ fprint(fildes(2), "%s\n", s);} say(s: string){ if(dflag) warn(s);}
implement Vacget;
include "sys.m";
sys: Sys;
include "draw.m";
include "bufio.m";
bufio: Bufio;
Iobuf: import bufio;
include "arg.m";
include "string.m";
include "venti.m";
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;
Vacget: module {
init: fn(nil: ref Draw->Context, args: list of string);
};
addr := "net!$venti!venti";
dflag := vflag := pflag := tflag := 0;
session: ref Session;
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
arg := load Arg Arg->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");
venti->init();
vac->init();
arg->init(args);
arg->setusage(sprint("%s [-dtv] [-a addr] [tag:]score", arg->progname()));
while((c := arg->opt()) != 0)
case c {
'a' => addr = arg->earg();
'd' => dflag++;
vac->dflag++;
'p' => pflag++;
't' => tflag++;
'v' => vflag++;
* => warn(sprint("bad option: -%c", c));
arg->usage();
}
args = arg->argv();
if(len args != 1)
arg->usage();
(tag, scorestr) := str->splitstrr(hd args, ":");
if(tag != nil)
tag = tag[:len tag-1];
if(tag == nil)
tag = "vac";
if(tag != "vac")
error("bad score type: "+tag);
(sok, score) := Score.parse(scorestr);
if(sok != 0)
error("bad score: "+scorestr);
say("have score");
(cok, conn) := sys->dial(addr, nil);
if(cok < 0)
error(sprint("dialing %s: %r", addr));
say("have connection");
fd := conn.dfd;
session = Session.new(fd);
if(session == nil)
error(sprint("handshake: %r"));
say("have handshake");
(vd, nil, err) := vac->vdroot(session, score);
if(err != nil)
error(err);
say("starting walk");
walk(".", vd);
}
create(path: string, omode: int, de: ref Direntry): ref Sys->FD
{
perm := Sys->DMDIR | Sys->DMAPPEND | Sys->DMEXCL | Sys->DMTMP;
perm &= de.emode;
perm |= 8r666;
if(de.emode & Sys->DMDIR)
perm |= 8r777;
fd := sys->create(path, omode, perm);
if(fd == nil)
return nil;
if(pflag) {
d := sys->nulldir;
d.uid = de.uid;
d.gid = de.gid;
d.mode = de.emode;
if(sys->fwstat(fd, d) != 0) {
warn(sprint("fwstat %s for uid/gid/mode: %r", path));
d.uid = d.gid = "";
sys->fwstat(fd, d);
}
}
return fd;
}
walk(path: string, vd: ref Vacdir)
{
say("start of walk: "+path);
for(;;) {
(n, de) := vd.readdir();
if(n < 0)
error(sprint("reading direntry in %s: %r", path));
if(n == 0)
break;
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));
oflags := de.mode&~(Modeperm|Modeappend|Modeexcl|Modedir|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);
if(me != nil) {
if(!tflag)
create(newpath, Sys->OREAD, de);
# ignore error, possibly for already existing dir.
# if creating really failed, writing files in the dir will fail later on.
walk(newpath, Vacdir.new(session, e, me));
} else {
if(tflag)
continue;
say("writing file");
fd := create(newpath, sys->OWRITE, de);
if(fd == nil)
error(sprint("creating %s: %r", newpath));
bio := bufio->fopen(fd, bufio->OWRITE);
if(bio == nil)
error(sprint("bufio fopen %s: %r", newpath));
buf := array[sys->ATOMICIO] of byte;
vf := Vacfile.new(session, e);
for(;;) {
rn := vf.read(buf, len buf);
if(rn == 0)
break;
if(rn < 0)
error(sprint("reading vac %s: %r", newpath));
wn := bio.write(buf, rn);
if(wn != rn)
error(sprint("writing local %s: %r", newpath));
}
bok := bio.flush();
bio.close();
if(bok == bufio->ERROR || bok == bufio->EOF)
error(sprint("bufio close: %r"));
if(pflag) {
d := sys->nulldir;
d.mtime = de.mtime;
if(sys->fwstat(fd, d) < 0)
warn(sprint("fwstat %s for mtime: %r", newpath));
}
fd = nil;
}
}
}
error(s: string)
{
fprint(fildes(2), "%s\n", s);
raise "fail:"+s;
}
warn(s: string)
{
fprint(fildes(2), "%s\n", s);
}
say(s: string)
{
if(dflag)
warn(s);
}