int vacmerge(VacFile *fp, char *name) { VacFs *mfs; VacDir vd; VacDirEnum *de; VacFile *mp; uint64_t maxqid, offset; if(strlen(name) < 4 || strcmp(name+strlen(name)-4, ".vac") != 0) return -1; if((mfs = vacfsopen(z, name, VtOREAD, 100)) == nil) return -1; if(verbose) fprint(2, "merging %s\n", name); mp = vacfsgetroot(mfs); de = vdeopen(mp); if(de){ offset = 0; if(vacfsgetmaxqid(mfs, &maxqid) >= 0){ _vacfsnextqid(fs, &offset); vacfsjumpqid(fs, maxqid+1); } while(vderead(de, &vd) > 0){ if(vd.qid > maxqid){ warn("vacmerge %s: maxqid=%lld but %s has %lld", name, maxqid, vd.elem, vd.qid); vacfsjumpqid(fs, vd.qid - maxqid); maxqid = vd.qid; } vacmergefile(fp, mp, &vd, name, offset, maxqid); vdcleanup(&vd); } vdeclose(de); } vacfiledecref(mp); vacfsclose(mfs); return 0; }
int vacdirread(Fid *f, char *p, int32_t off, int32_t cnt) { int i, n, nb; VacDir vd; /* * special case of rewinding a directory * otherwise ignore the offset */ if(off == 0 && f->vde){ vdeclose(f->vde); f->vde = nil; } if(f->vde == nil){ f->vde = vdeopen(f->file); if(f->vde == nil) return -1; } for(nb = 0; nb < cnt; nb += n) { i = vderead(f->vde, &vd); if(i < 0) return -1; if(i == 0) break; n = vacstat(f->file, &vd, (uint8_t*)p, cnt-nb); if(n <= BIT16SZ) { vdeunread(f->vde); break; } vdcleanup(&vd); p += n; } return nb; }
VacFile* recentarchive(VacFs *fs, char *path) { VacFile *fp, *f; VacDirEnum *de; VacDir vd; char buf[10]; int year, mmdd, nn, n, n1; char *p; fp = vacfsgetroot(fs); de = vdeopen(fp); year = 0; if(de){ for(; vderead(de, &vd) > 0; vdcleanup(&vd)){ if(strlen(vd.elem) != 4) continue; if((n = strtol(vd.elem, &p, 10)) < 1900 || *p != 0) continue; if(year < n) year = n; } } vdeclose(de); if(year == 0){ vacfiledecref(fp); return nil; } snprint(buf, sizeof buf, "%04d", year); if((f = vacfilewalk(fp, buf)) == nil){ fprint(2, "warning: dirread %s but cannot walk", buf); vacfiledecref(fp); return nil; } fp = f; de = vdeopen(fp); mmdd = 0; nn = 0; if(de){ for(; vderead(de, &vd) > 0; vdcleanup(&vd)){ if(strlen(vd.elem) < 4) continue; if((n = strtol(vd.elem, &p, 10)) < 100 || n > 1231 || p != vd.elem+4) continue; if(*p == '.'){ if(p[1] == '0' || (n1 = strtol(p+1, &p, 10)) == 0 || *p != 0) continue; }else{ if(*p != 0) continue; n1 = 0; } if(n < mmdd || (n == mmdd && n1 < nn)) continue; mmdd = n; nn = n1; } } vdeclose(de); if(mmdd == 0){ vacfiledecref(fp); return nil; } if(nn == 0) snprint(buf, sizeof buf, "%04d", mmdd); else snprint(buf, sizeof buf, "%04d.%d", mmdd, nn); if((f = vacfilewalk(fp, buf)) == nil){ fprint(2, "warning: dirread %s but cannot walk", buf); vacfiledecref(fp); return nil; } vacfiledecref(fp); sprint(path, "%04d/%s", year, buf); return f; }
void unvac(VacFile *f, char *name, VacDir *vdir) { static char buf[65536]; int fd, n, m, bsize; ulong mode, mode9; char *newname; char *what; vlong off; Dir d, *dp; VacDirEnum *vde; VacDir newvdir; VacFile *newf; if(vdir) mode = vdir->mode; else mode = vacfilegetmode(f); if(vdir){ if(table){ if(chatty){ mode9 = vdir->mode&0777; if(mode&ModeDir) mode9 |= DMDIR; if(mode&ModeAppend) mode9 |= DMAPPEND; if(mode&ModeExclusive) mode9 |= DMEXCL; print("%M %-10s %-10s %11lld %t %s\n", mode9, vdir->uid, vdir->gid, vdir->size, vdir->mtime, name); }else print("%s%s\n", name, (mode&ModeDir) ? "/" : ""); } else if(chatty) fprint(2, "%s%s\n", name, (mode&ModeDir) ? "/" : ""); } if(mode&(ModeDevice|ModeLink|ModeNamedPipe|ModeExclusive)){ if(table) return; if(mode&ModeDevice) what = "device"; else if(mode&ModeLink) what = "link"; else if(mode&ModeNamedPipe) what = "named pipe"; else if(mode&ModeExclusive) what = "lock"; else what = "unknown type of file"; fprint(2, "warning: ignoring %s %s\n", what, name); return; } if(mode&ModeDir){ if((vde = vdeopen(f)) == nil){ fprint(2, "vdeopen %s: %r", name); errors++; return; } if(!table && !tostdout && vdir){ // create directory if((dp = dirstat(name)) == nil){ if((fd = create(name, OREAD, DMDIR|(mode&0777))) < 0){ fprint(2, "mkdir %s: %r\n", name); vdeclose(vde); } close(fd); }else{ if(!(dp->mode&DMDIR)){ fprint(2, "%s already exists and is not a directory\n", name); errors++; free(dp); vdeclose(vde); return; } free(dp); } } while(vderead(vde, &newvdir) > 0){ if(name == nil) newname = newvdir.elem; else newname = smprint("%s/%s", name, newvdir.elem); if(wantfile(newname)){ if((newf = vacfilewalk(f, newvdir.elem)) == nil){ fprint(2, "walk %s: %r\n", name); errors++; }else if(newf == f){ fprint(2, "walk loop: %s\n", newname); vacfiledecref(newf); }else{ unvac(newf, newname, &newvdir); vacfiledecref(newf); } } if(newname != newvdir.elem) free(newname); vdcleanup(&newvdir); } vdeclose(vde); }else{ if(!table){ off = 0; if(tostdout) fd = dup(1, -1); else if(diff && (fd = open(name, ORDWR)) >= 0){ bsize = vacfiledsize(f); while((n = readn(fd, buf, bsize)) > 0){ if(sha1matches(f, off/bsize, (uchar*)buf, n)){ off += n; stats.skipdata += n; continue; } seek(fd, off, 0); if((m = vacfileread(f, buf, n, off)) < 0) break; if(writen(fd, buf, m) != m){ fprint(2, "write %s: %r\n", name); goto Err; } off += m; stats.data += m; if(m < n){ nulldir(&d); d.length = off; if(dirfwstat(fd, &d) < 0){ fprint(2, "dirfwstat %s: %r\n", name); goto Err; } break; } } } else if((fd = create(name, OWRITE, mode&0777)) < 0){ fprint(2, "create %s: %r\n", name); errors++; return; } while((n = vacfileread(f, buf, sizeof buf, off)) > 0){ if(writen(fd, buf, n) != n){ fprint(2, "write %s: %r\n", name); Err: errors++; close(fd); remove(name); return; } off += n; stats.data += n; } close(fd); } } if(vdir && settimes && !tostdout){ nulldir(&d); d.mtime = vdir->mtime; if(dirwstat(name, &d) < 0) fprint(2, "warning: setting mtime on %s: %r", name); } }