2 #include <fcall.h> /* dirmodefmt */
6 #pragma varargck type "t" ulong
22 void unvac(VacFile*, char*, VacDir*);
27 fprint(2, "usage: unvac [-TVcdtv] [-h host] file.vac [file ...]\n");
28 threadexitsall("usage");
38 threadmain(int argc, char *argv[])
44 fmtinstall('H', encodefmt);
45 fmtinstall('V', vtscorefmt);
46 fmtinstall('F', vtfcallfmt);
47 fmtinstall('t', mtimefmt);
48 fmtinstall('M', dirmodefmt);
67 host = EARGF(usage());
86 fprint(2, "cannot use -c with -d\n");
92 sysfatal("could not connect to server: %r");
94 if(vtconnect(conn) < 0)
95 sysfatal("vtconnect: %r");
97 fs = vacfsopen(conn, argv[0], VtOREAD, 128<<20);
99 sysfatal("vacfsopen: %r");
103 found = vtmallocz(nwant*sizeof found[0]);
105 if((f = vacfsgetroot(fs)) == nil)
106 sysfatal("vacfsgetroot: %r");
109 for(i=0; i<nwant; i++){
110 if(want[i] && !found[i]){
111 fprint(2, "warning: didn't find %s\n", want[i]);
116 threadexitsall("errors");
118 fprint(2, "%lld bytes read, %lld bytes skipped\n",
119 stats.data, stats.skipdata);
124 writen(int fd, char *buf, int n)
131 m = write(fd, buf, n);
148 namelen = strlen(name);
149 for(i=0; i<nwant; i++){
153 if(n < namelen && name[n] == '/' && memcmp(name, want[i], n) == 0)
155 if(namelen < n && want[i][namelen] == '/' && memcmp(want[i], name, namelen) == 0)
157 if(n == namelen && memcmp(name, want[i], n) == 0){
166 unvac(VacFile *f, char *name, VacDir *vdir)
168 static char buf[65536];
182 mode = vacfilegetmode(f);
187 mode9 = vdir->mode&0777;
192 if(mode&ModeExclusive)
197 if(mode&ModeNamedPipe)
198 mode9 |= DMNAMEDPIPE;
206 print("%M %-10s %-10s %11lld %t %s\n",
207 mode9, vdir->uid, vdir->gid, vdir->size,
210 print("%s%s\n", name, (mode&ModeDir) ? "/" : "");
213 fprint(2, "%s%s\n", name, (mode&ModeDir) ? "/" : "");
216 if(mode&(ModeDevice|ModeLink|ModeNamedPipe|ModeExclusive)){
221 else if(mode&ModeLink)
223 else if(mode&ModeNamedPipe)
225 else if(mode&ModeExclusive)
228 what = "unknown type of file";
229 fprint(2, "warning: ignoring %s %s\n", what, name);
234 if((vde = vdeopen(f)) == nil){
235 fprint(2, "vdeopen %s: %r", name);
239 if(!table && !tostdout && vdir){
241 if((dp = dirstat(name)) == nil){
242 if((fd = create(name, OREAD, DMDIR|0700|(mode&0777))) < 0){
243 fprint(2, "mkdir %s: %r\n", name);
248 if(!(dp->mode&DMDIR)){
249 fprint(2, "%s already exists and is not a directory\n", name);
258 while(vderead(vde, &newvdir) > 0){
260 newname = newvdir.elem;
262 newname = smprint("%s/%s", name, newvdir.elem);
263 if(wantfile(newname)){
264 if((newf = vacfilewalk(f, newvdir.elem)) == nil){
265 fprint(2, "walk %s: %r\n", name);
268 fprint(2, "walk loop: %s\n", newname);
271 unvac(newf, newname, &newvdir);
275 if(newname != newvdir.elem)
285 else if(diff && (fd = open(name, ORDWR)) >= 0){
286 bsize = vacfiledsize(f);
287 while((n = readn(fd, buf, bsize)) > 0){
288 if(sha1matches(f, off/bsize, (uchar*)buf, n)){
294 if((m = vacfileread(f, buf, n, off)) < 0)
296 if(writen(fd, buf, m) != m){
297 fprint(2, "write %s: %r\n", name);
305 if(dirfwstat(fd, &d) < 0){
306 fprint(2, "dirfwstat %s: %r\n", name);
313 else if((fd = create(name, OWRITE, mode&0777)) < 0){
314 fprint(2, "create %s: %r\n", name);
318 while((n = vacfileread(f, buf, sizeof buf, off)) > 0){
319 if(writen(fd, buf, n) != n){
320 fprint(2, "write %s: %r\n", name);
333 if(vdir && settimes && !tostdout){
335 d.mtime = vdir->mtime;
336 if(dirwstat(name, &d) < 0)
337 fprint(2, "warning: setting mtime on %s: %r", name);
346 tm = localtime(va_arg(f->args, ulong));
347 fmtprint(f, "%04d-%02d-%02d %02d:%02d",
348 tm->year+1900, tm->mon+1, tm->mday,