Blame


1 3d77c87e 2004-03-15 devnull #include "stdinc.h"
2 3d77c87e 2004-03-15 devnull #include "vac.h"
3 3d77c87e 2004-03-15 devnull #include "dat.h"
4 3d77c87e 2004-03-15 devnull #include "fns.h"
5 7763a61a 2003-11-23 devnull
6 003c13aa 2008-06-15 rsc // TODO: qids
7 2277c5d7 2004-03-21 devnull
8 003c13aa 2008-06-15 rsc void
9 003c13aa 2008-06-15 rsc usage(void)
10 003c13aa 2008-06-15 rsc {
11 e05b0ff3 2008-07-03 rsc fprint(2, "vac [-imqsv] [-a archive.vac] [-b bsize] [-d old.vac] [-f new.vac] [-e exclude]... [-h host] file...\n");
12 003c13aa 2008-06-15 rsc threadexitsall("usage");
13 003c13aa 2008-06-15 rsc }
14 7763a61a 2003-11-23 devnull
15 003c13aa 2008-06-15 rsc enum
16 003c13aa 2008-06-15 rsc {
17 3d77c87e 2004-03-15 devnull BlockSize = 8*1024,
18 3d77c87e 2004-03-15 devnull };
19 3d77c87e 2004-03-15 devnull
20 003c13aa 2008-06-15 rsc struct
21 003c13aa 2008-06-15 rsc {
22 003c13aa 2008-06-15 rsc int nfile;
23 003c13aa 2008-06-15 rsc int ndir;
24 003c13aa 2008-06-15 rsc vlong data;
25 003c13aa 2008-06-15 rsc vlong skipdata;
26 003c13aa 2008-06-15 rsc int skipfiles;
27 3d77c87e 2004-03-15 devnull } stats;
28 3d77c87e 2004-03-15 devnull
29 3d77c87e 2004-03-15 devnull int qdiff;
30 003c13aa 2008-06-15 rsc int merge;
31 003c13aa 2008-06-15 rsc int verbose;
32 003c13aa 2008-06-15 rsc char *host;
33 003c13aa 2008-06-15 rsc VtConn *z;
34 003c13aa 2008-06-15 rsc VacFs *fs;
35 e05b0ff3 2008-07-03 rsc char *archivefile;
36 003c13aa 2008-06-15 rsc char *vacfile;
37 3d77c87e 2004-03-15 devnull
38 003c13aa 2008-06-15 rsc int vacmerge(VacFile*, char*);
39 003c13aa 2008-06-15 rsc void vac(VacFile*, VacFile*, char*, Dir*);
40 003c13aa 2008-06-15 rsc void vacstdin(VacFile*, char*);
41 e05b0ff3 2008-07-03 rsc VacFile *recentarchive(VacFs*, char*);
42 64f9764e 2008-06-14 rsc
43 003c13aa 2008-06-15 rsc static u64int unittoull(char*);
44 003c13aa 2008-06-15 rsc static void warn(char *fmt, ...);
45 003c13aa 2008-06-15 rsc static void removevacfile(void);
46 7763a61a 2003-11-23 devnull
47 4395d738 2008-06-15 rsc #ifdef PLAN9PORT
48 003c13aa 2008-06-15 rsc /*
49 003c13aa 2008-06-15 rsc * We're between a rock and a hard place here.
50 003c13aa 2008-06-15 rsc * The pw library (getpwnam, etc.) reads the
51 003c13aa 2008-06-15 rsc * password and group files into an on-stack buffer,
52 003c13aa 2008-06-15 rsc * so if you have some huge groups, you overflow
53 003c13aa 2008-06-15 rsc * the stack. Because of this, the thread library turns
54 003c13aa 2008-06-15 rsc * it off by default, so that dirstat returns "14571" instead of "rsc".
55 003c13aa 2008-06-15 rsc * But for vac we want names. So cautiously turn the pwlibrary
56 003c13aa 2008-06-15 rsc * back on (see threadmain) and make the main thread stack huge.
57 003c13aa 2008-06-15 rsc */
58 003c13aa 2008-06-15 rsc extern int _p9usepwlibrary;
59 003c13aa 2008-06-15 rsc int mainstacksize = 4*1024*1024;
60 003c13aa 2008-06-15 rsc
61 4395d738 2008-06-15 rsc #endif
62 7763a61a 2003-11-23 devnull void
63 003c13aa 2008-06-15 rsc threadmain(int argc, char **argv)
64 7763a61a 2003-11-23 devnull {
65 003c13aa 2008-06-15 rsc int i, j, fd, n, printstats;
66 003c13aa 2008-06-15 rsc Dir *d;
67 003c13aa 2008-06-15 rsc char *s;
68 003c13aa 2008-06-15 rsc uvlong u;
69 003c13aa 2008-06-15 rsc VacFile *f, *fdiff;
70 003c13aa 2008-06-15 rsc VacFs *fsdiff;
71 003c13aa 2008-06-15 rsc int blocksize;
72 003c13aa 2008-06-15 rsc int outfd;
73 003c13aa 2008-06-15 rsc char *stdinname;
74 003c13aa 2008-06-15 rsc char *diffvac;
75 003c13aa 2008-06-15 rsc uvlong qid;
76 3d77c87e 2004-03-15 devnull
77 003c13aa 2008-06-15 rsc #ifdef PLAN9PORT
78 64f9764e 2008-06-14 rsc /* see comment above */
79 64f9764e 2008-06-14 rsc _p9usepwlibrary = 1;
80 003c13aa 2008-06-15 rsc #endif
81 64f9764e 2008-06-14 rsc
82 e05b0ff3 2008-07-03 rsc fmtinstall('F', vtfcallfmt);
83 003c13aa 2008-06-15 rsc fmtinstall('H', encodefmt);
84 003c13aa 2008-06-15 rsc fmtinstall('V', vtscorefmt);
85 3d77c87e 2004-03-15 devnull
86 003c13aa 2008-06-15 rsc blocksize = BlockSize;
87 003c13aa 2008-06-15 rsc stdinname = nil;
88 003c13aa 2008-06-15 rsc printstats = 0;
89 003c13aa 2008-06-15 rsc fsdiff = nil;
90 003c13aa 2008-06-15 rsc diffvac = nil;
91 e05b0ff3 2008-07-03 rsc
92 7763a61a 2003-11-23 devnull ARGBEGIN{
93 e05b0ff3 2008-07-03 rsc case 'V':
94 e05b0ff3 2008-07-03 rsc chattyventi++;
95 e05b0ff3 2008-07-03 rsc break;
96 e05b0ff3 2008-07-03 rsc case 'a':
97 e05b0ff3 2008-07-03 rsc archivefile = EARGF(usage());
98 e05b0ff3 2008-07-03 rsc break;
99 7763a61a 2003-11-23 devnull case 'b':
100 003c13aa 2008-06-15 rsc u = unittoull(EARGF(usage()));
101 003c13aa 2008-06-15 rsc if(u < 512)
102 003c13aa 2008-06-15 rsc u = 512;
103 003c13aa 2008-06-15 rsc blocksize = u;
104 7763a61a 2003-11-23 devnull break;
105 3d77c87e 2004-03-15 devnull case 'd':
106 003c13aa 2008-06-15 rsc diffvac = EARGF(usage());
107 3d77c87e 2004-03-15 devnull break;
108 3d77c87e 2004-03-15 devnull case 'e':
109 e05b0ff3 2008-07-03 rsc excludepattern(EARGF(usage()));
110 3d77c87e 2004-03-15 devnull break;
111 3d77c87e 2004-03-15 devnull case 'f':
112 003c13aa 2008-06-15 rsc vacfile = EARGF(usage());
113 3d77c87e 2004-03-15 devnull break;
114 7763a61a 2003-11-23 devnull case 'h':
115 003c13aa 2008-06-15 rsc host = EARGF(usage());
116 7763a61a 2003-11-23 devnull break;
117 3d77c87e 2004-03-15 devnull case 'i':
118 003c13aa 2008-06-15 rsc stdinname = EARGF(usage());
119 3d77c87e 2004-03-15 devnull break;
120 3d77c87e 2004-03-15 devnull case 'm':
121 3d77c87e 2004-03-15 devnull merge++;
122 3d77c87e 2004-03-15 devnull break;
123 3d77c87e 2004-03-15 devnull case 'q':
124 3d77c87e 2004-03-15 devnull qdiff++;
125 3d77c87e 2004-03-15 devnull break;
126 3d77c87e 2004-03-15 devnull case 's':
127 003c13aa 2008-06-15 rsc printstats++;
128 3d77c87e 2004-03-15 devnull break;
129 3d77c87e 2004-03-15 devnull case 'v':
130 3d77c87e 2004-03-15 devnull verbose++;
131 3d77c87e 2004-03-15 devnull break;
132 e05b0ff3 2008-07-03 rsc case 'x':
133 e05b0ff3 2008-07-03 rsc loadexcludefile(EARGF(usage()));
134 e05b0ff3 2008-07-03 rsc break;
135 003c13aa 2008-06-15 rsc default:
136 2277c5d7 2004-03-21 devnull usage();
137 003c13aa 2008-06-15 rsc }ARGEND
138 003c13aa 2008-06-15 rsc
139 003c13aa 2008-06-15 rsc if(argc == 0 && !stdinname)
140 003c13aa 2008-06-15 rsc usage();
141 e05b0ff3 2008-07-03 rsc
142 e05b0ff3 2008-07-03 rsc if(archivefile && (vacfile || diffvac)){
143 e05b0ff3 2008-07-03 rsc fprint(2, "cannot use -a with -f, -d\n");
144 e05b0ff3 2008-07-03 rsc usage();
145 e05b0ff3 2008-07-03 rsc }
146 2277c5d7 2004-03-21 devnull
147 3d77c87e 2004-03-15 devnull z = vtdial(host);
148 7763a61a 2003-11-23 devnull if(z == nil)
149 3d77c87e 2004-03-15 devnull sysfatal("could not connect to server: %r");
150 3d77c87e 2004-03-15 devnull if(vtconnect(z) < 0)
151 3d77c87e 2004-03-15 devnull sysfatal("vtconnect: %r");
152 7763a61a 2003-11-23 devnull
153 e05b0ff3 2008-07-03 rsc // Setup:
154 e05b0ff3 2008-07-03 rsc // fs is the output vac file system
155 e05b0ff3 2008-07-03 rsc // f is directory in output vac to write new files
156 e05b0ff3 2008-07-03 rsc // fdiff is corresponding directory in existing vac
157 e05b0ff3 2008-07-03 rsc if(archivefile){
158 e05b0ff3 2008-07-03 rsc VacFile *fp;
159 e05b0ff3 2008-07-03 rsc char yyyy[5];
160 e05b0ff3 2008-07-03 rsc char mmdd[10];
161 e05b0ff3 2008-07-03 rsc char oldpath[40];
162 e05b0ff3 2008-07-03 rsc Tm tm;
163 64f9764e 2008-06-14 rsc
164 003c13aa 2008-06-15 rsc fdiff = nil;
165 e05b0ff3 2008-07-03 rsc if((outfd = open(archivefile, ORDWR)) < 0){
166 e05b0ff3 2008-07-03 rsc if(access(archivefile, 0) >= 0)
167 e05b0ff3 2008-07-03 rsc sysfatal("open %s: %r", archivefile);
168 e05b0ff3 2008-07-03 rsc if((outfd = create(archivefile, OWRITE, 0666)) < 0)
169 e05b0ff3 2008-07-03 rsc sysfatal("create %s: %r", archivefile);
170 e05b0ff3 2008-07-03 rsc atexit(removevacfile); // because it is new
171 75d04888 2009-05-25 rsc if((fs = vacfscreate(z, blocksize, 4<<20)) == nil)
172 e05b0ff3 2008-07-03 rsc sysfatal("vacfscreate: %r");
173 e05b0ff3 2008-07-03 rsc }else{
174 75d04888 2009-05-25 rsc if((fs = vacfsopen(z, archivefile, VtORDWR, 4<<20)) == nil)
175 e05b0ff3 2008-07-03 rsc sysfatal("vacfsopen %s: %r", archivefile);
176 e05b0ff3 2008-07-03 rsc if((fdiff = recentarchive(fs, oldpath)) != nil){
177 e05b0ff3 2008-07-03 rsc if(verbose)
178 e05b0ff3 2008-07-03 rsc fprint(2, "diff %s\n", oldpath);
179 e05b0ff3 2008-07-03 rsc }else
180 e05b0ff3 2008-07-03 rsc if(verbose)
181 e05b0ff3 2008-07-03 rsc fprint(2, "no recent archive to diff against\n");
182 e05b0ff3 2008-07-03 rsc }
183 e05b0ff3 2008-07-03 rsc
184 e05b0ff3 2008-07-03 rsc // Create yyyy/mmdd.
185 e05b0ff3 2008-07-03 rsc tm = *localtime(time(0));
186 e05b0ff3 2008-07-03 rsc snprint(yyyy, sizeof yyyy, "%04d", tm.year+1900);
187 e05b0ff3 2008-07-03 rsc fp = vacfsgetroot(fs);
188 e05b0ff3 2008-07-03 rsc if((f = vacfilewalk(fp, yyyy)) == nil
189 e05b0ff3 2008-07-03 rsc && (f = vacfilecreate(fp, yyyy, ModeDir|0555)) == nil)
190 e05b0ff3 2008-07-03 rsc sysfatal("vacfscreate %s: %r", yyyy);
191 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
192 e05b0ff3 2008-07-03 rsc fp = f;
193 e05b0ff3 2008-07-03 rsc
194 e05b0ff3 2008-07-03 rsc snprint(mmdd, sizeof mmdd, "%02d%02d", tm.mon+1, tm.mday);
195 e05b0ff3 2008-07-03 rsc n = 0;
196 e05b0ff3 2008-07-03 rsc while((f = vacfilewalk(fp, mmdd)) != nil){
197 e05b0ff3 2008-07-03 rsc vacfiledecref(f);
198 e05b0ff3 2008-07-03 rsc n++;
199 e05b0ff3 2008-07-03 rsc snprint(mmdd+4, sizeof mmdd-4, ".%d", n);
200 e05b0ff3 2008-07-03 rsc }
201 e05b0ff3 2008-07-03 rsc f = vacfilecreate(fp, mmdd, ModeDir|0555);
202 e05b0ff3 2008-07-03 rsc if(f == nil)
203 e05b0ff3 2008-07-03 rsc sysfatal("vacfscreate %s/%s: %r", yyyy, mmdd);
204 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
205 e05b0ff3 2008-07-03 rsc
206 e05b0ff3 2008-07-03 rsc if(verbose)
207 e05b0ff3 2008-07-03 rsc fprint(2, "archive %s/%s\n", yyyy, mmdd);
208 e05b0ff3 2008-07-03 rsc }else{
209 e05b0ff3 2008-07-03 rsc if(vacfile == nil)
210 e05b0ff3 2008-07-03 rsc outfd = 1;
211 e05b0ff3 2008-07-03 rsc else if((outfd = create(vacfile, OWRITE, 0666)) < 0)
212 e05b0ff3 2008-07-03 rsc sysfatal("create %s: %r", vacfile);
213 e05b0ff3 2008-07-03 rsc atexit(removevacfile);
214 75d04888 2009-05-25 rsc if((fs = vacfscreate(z, blocksize, 4<<20)) == nil)
215 e05b0ff3 2008-07-03 rsc sysfatal("vacfscreate: %r");
216 e05b0ff3 2008-07-03 rsc f = vacfsgetroot(fs);
217 e05b0ff3 2008-07-03 rsc
218 e05b0ff3 2008-07-03 rsc fdiff = nil;
219 e05b0ff3 2008-07-03 rsc if(diffvac){
220 e05b0ff3 2008-07-03 rsc if((fsdiff = vacfsopen(z, diffvac, VtOREAD, 128)) == nil)
221 e05b0ff3 2008-07-03 rsc warn("vacfsopen %s: %r", diffvac);
222 e05b0ff3 2008-07-03 rsc else
223 e05b0ff3 2008-07-03 rsc fdiff = vacfsgetroot(fsdiff);
224 e05b0ff3 2008-07-03 rsc }
225 e05b0ff3 2008-07-03 rsc }
226 e05b0ff3 2008-07-03 rsc
227 003c13aa 2008-06-15 rsc if(stdinname)
228 003c13aa 2008-06-15 rsc vacstdin(f, stdinname);
229 003c13aa 2008-06-15 rsc for(i=0; i<argc; i++){
230 003c13aa 2008-06-15 rsc // We can't use / and . and .. and ../.. as valid archive
231 003c13aa 2008-06-15 rsc // names, so expand to the list of files in the directory.
232 003c13aa 2008-06-15 rsc if(argv[i][0] == 0){
233 003c13aa 2008-06-15 rsc warn("empty string given as command-line argument");
234 003c13aa 2008-06-15 rsc continue;
235 003c13aa 2008-06-15 rsc }
236 003c13aa 2008-06-15 rsc cleanname(argv[i]);
237 003c13aa 2008-06-15 rsc if(strcmp(argv[i], "/") == 0
238 003c13aa 2008-06-15 rsc || strcmp(argv[i], ".") == 0
239 003c13aa 2008-06-15 rsc || strcmp(argv[i], "..") == 0
240 003c13aa 2008-06-15 rsc || (strlen(argv[i]) > 3 && strcmp(argv[i]+strlen(argv[i])-3, "/..") == 0)){
241 003c13aa 2008-06-15 rsc if((fd = open(argv[i], OREAD)) < 0){
242 003c13aa 2008-06-15 rsc warn("open %s: %r", argv[i]);
243 64f9764e 2008-06-14 rsc continue;
244 64f9764e 2008-06-14 rsc }
245 003c13aa 2008-06-15 rsc while((n = dirread(fd, &d)) > 0){
246 003c13aa 2008-06-15 rsc for(j=0; j<n; j++){
247 003c13aa 2008-06-15 rsc s = vtmalloc(strlen(argv[i])+1+strlen(d[j].name)+1);
248 003c13aa 2008-06-15 rsc strcpy(s, argv[i]);
249 003c13aa 2008-06-15 rsc strcat(s, "/");
250 003c13aa 2008-06-15 rsc strcat(s, d[j].name);
251 003c13aa 2008-06-15 rsc cleanname(s);
252 003c13aa 2008-06-15 rsc vac(f, fdiff, s, &d[j]);
253 003c13aa 2008-06-15 rsc }
254 003c13aa 2008-06-15 rsc free(d);
255 64f9764e 2008-06-14 rsc }
256 003c13aa 2008-06-15 rsc close(fd);
257 64f9764e 2008-06-14 rsc continue;
258 64f9764e 2008-06-14 rsc }
259 003c13aa 2008-06-15 rsc if((d = dirstat(argv[i])) == nil){
260 003c13aa 2008-06-15 rsc warn("stat %s: %r", argv[i]);
261 003c13aa 2008-06-15 rsc continue;
262 003c13aa 2008-06-15 rsc }
263 003c13aa 2008-06-15 rsc vac(f, fdiff, argv[i], d);
264 003c13aa 2008-06-15 rsc free(d);
265 64f9764e 2008-06-14 rsc }
266 003c13aa 2008-06-15 rsc if(fdiff)
267 003c13aa 2008-06-15 rsc vacfiledecref(fdiff);
268 003c13aa 2008-06-15 rsc
269 003c13aa 2008-06-15 rsc /*
270 003c13aa 2008-06-15 rsc * Record the maximum qid so that vacs can be merged
271 003c13aa 2008-06-15 rsc * without introducing overlapping qids. Older versions
272 003c13aa 2008-06-15 rsc * of vac arranged that the root would have the largest
273 003c13aa 2008-06-15 rsc * qid in the file system, but we can't do that anymore
274 003c13aa 2008-06-15 rsc * (the root gets created first!).
275 003c13aa 2008-06-15 rsc */
276 003c13aa 2008-06-15 rsc if(_vacfsnextqid(fs, &qid) >= 0)
277 003c13aa 2008-06-15 rsc vacfilesetqidspace(f, 0, qid);
278 003c13aa 2008-06-15 rsc vacfiledecref(f);
279 7763a61a 2003-11-23 devnull
280 003c13aa 2008-06-15 rsc /*
281 003c13aa 2008-06-15 rsc * Copy fsdiff's root block score into fs's slot for that,
282 003c13aa 2008-06-15 rsc * so that vacfssync will copy it into root.prev for us.
283 003c13aa 2008-06-15 rsc * Just nice documentation, no effect.
284 003c13aa 2008-06-15 rsc */
285 003c13aa 2008-06-15 rsc if(fsdiff)
286 003c13aa 2008-06-15 rsc memmove(fs->score, fsdiff->score, VtScoreSize);
287 003c13aa 2008-06-15 rsc if(vacfssync(fs) < 0)
288 003c13aa 2008-06-15 rsc fprint(2, "vacfssync: %r\n");
289 3d77c87e 2004-03-15 devnull
290 003c13aa 2008-06-15 rsc fprint(outfd, "vac:%V\n", fs->score);
291 003c13aa 2008-06-15 rsc atexitdont(removevacfile);
292 e05b0ff3 2008-07-03 rsc vacfsclose(fs);
293 003c13aa 2008-06-15 rsc vthangup(z);
294 003c13aa 2008-06-15 rsc
295 003c13aa 2008-06-15 rsc if(printstats){
296 003c13aa 2008-06-15 rsc fprint(2,
297 003c13aa 2008-06-15 rsc "%d files, %d files skipped, %d directories\n"
298 003c13aa 2008-06-15 rsc "%lld data bytes written, %lld data bytes skipped\n",
299 003c13aa 2008-06-15 rsc stats.nfile, stats.skipfiles, stats.ndir, stats.data, stats.skipdata);
300 003c13aa 2008-06-15 rsc dup(2, 1);
301 003c13aa 2008-06-15 rsc packetstats();
302 3d77c87e 2004-03-15 devnull }
303 003c13aa 2008-06-15 rsc threadexitsall(0);
304 3d77c87e 2004-03-15 devnull }
305 3d77c87e 2004-03-15 devnull
306 e05b0ff3 2008-07-03 rsc VacFile*
307 e05b0ff3 2008-07-03 rsc recentarchive(VacFs *fs, char *path)
308 e05b0ff3 2008-07-03 rsc {
309 e05b0ff3 2008-07-03 rsc VacFile *fp, *f;
310 e05b0ff3 2008-07-03 rsc VacDirEnum *de;
311 e05b0ff3 2008-07-03 rsc VacDir vd;
312 e05b0ff3 2008-07-03 rsc char buf[10];
313 e05b0ff3 2008-07-03 rsc int year, mmdd, nn, n, n1;
314 e05b0ff3 2008-07-03 rsc char *p;
315 e05b0ff3 2008-07-03 rsc
316 e05b0ff3 2008-07-03 rsc fp = vacfsgetroot(fs);
317 e05b0ff3 2008-07-03 rsc de = vdeopen(fp);
318 e05b0ff3 2008-07-03 rsc year = 0;
319 e05b0ff3 2008-07-03 rsc if(de){
320 e05b0ff3 2008-07-03 rsc for(; vderead(de, &vd) > 0; vdcleanup(&vd)){
321 e05b0ff3 2008-07-03 rsc if(strlen(vd.elem) != 4)
322 e05b0ff3 2008-07-03 rsc continue;
323 e05b0ff3 2008-07-03 rsc if((n = strtol(vd.elem, &p, 10)) < 1900 || *p != 0)
324 e05b0ff3 2008-07-03 rsc continue;
325 e05b0ff3 2008-07-03 rsc if(year < n)
326 e05b0ff3 2008-07-03 rsc year = n;
327 e05b0ff3 2008-07-03 rsc }
328 e05b0ff3 2008-07-03 rsc }
329 e05b0ff3 2008-07-03 rsc vdeclose(de);
330 e05b0ff3 2008-07-03 rsc if(year == 0){
331 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
332 e05b0ff3 2008-07-03 rsc return nil;
333 e05b0ff3 2008-07-03 rsc }
334 e05b0ff3 2008-07-03 rsc snprint(buf, sizeof buf, "%04d", year);
335 e05b0ff3 2008-07-03 rsc if((f = vacfilewalk(fp, buf)) == nil){
336 e05b0ff3 2008-07-03 rsc fprint(2, "warning: dirread %s but cannot walk", buf);
337 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
338 e05b0ff3 2008-07-03 rsc return nil;
339 e05b0ff3 2008-07-03 rsc }
340 e05b0ff3 2008-07-03 rsc fp = f;
341 e05b0ff3 2008-07-03 rsc
342 e05b0ff3 2008-07-03 rsc de = vdeopen(fp);
343 e05b0ff3 2008-07-03 rsc mmdd = 0;
344 e05b0ff3 2008-07-03 rsc nn = 0;
345 e05b0ff3 2008-07-03 rsc if(de){
346 e05b0ff3 2008-07-03 rsc for(; vderead(de, &vd) > 0; vdcleanup(&vd)){
347 e05b0ff3 2008-07-03 rsc if(strlen(vd.elem) < 4)
348 e05b0ff3 2008-07-03 rsc continue;
349 e05b0ff3 2008-07-03 rsc if((n = strtol(vd.elem, &p, 10)) < 100 || n > 1231 || p != vd.elem+4)
350 e05b0ff3 2008-07-03 rsc continue;
351 e05b0ff3 2008-07-03 rsc if(*p == '.'){
352 e05b0ff3 2008-07-03 rsc if(p[1] == '0' || (n1 = strtol(p+1, &p, 10)) == 0 || *p != 0)
353 e05b0ff3 2008-07-03 rsc continue;
354 e05b0ff3 2008-07-03 rsc }else{
355 e05b0ff3 2008-07-03 rsc if(*p != 0)
356 e05b0ff3 2008-07-03 rsc continue;
357 e05b0ff3 2008-07-03 rsc n1 = 0;
358 e05b0ff3 2008-07-03 rsc }
359 e05b0ff3 2008-07-03 rsc if(n < mmdd || (n == mmdd && n1 < nn))
360 e05b0ff3 2008-07-03 rsc continue;
361 e05b0ff3 2008-07-03 rsc mmdd = n;
362 e05b0ff3 2008-07-03 rsc nn = n1;
363 e05b0ff3 2008-07-03 rsc }
364 e05b0ff3 2008-07-03 rsc }
365 e05b0ff3 2008-07-03 rsc vdeclose(de);
366 e05b0ff3 2008-07-03 rsc if(mmdd == 0){
367 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
368 e05b0ff3 2008-07-03 rsc return nil;
369 e05b0ff3 2008-07-03 rsc }
370 e05b0ff3 2008-07-03 rsc if(nn == 0)
371 e05b0ff3 2008-07-03 rsc snprint(buf, sizeof buf, "%04d", mmdd);
372 e05b0ff3 2008-07-03 rsc else
373 e05b0ff3 2008-07-03 rsc snprint(buf, sizeof buf, "%04d.%d", mmdd, nn);
374 e05b0ff3 2008-07-03 rsc if((f = vacfilewalk(fp, buf)) == nil){
375 e05b0ff3 2008-07-03 rsc fprint(2, "warning: dirread %s but cannot walk", buf);
376 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
377 e05b0ff3 2008-07-03 rsc return nil;
378 e05b0ff3 2008-07-03 rsc }
379 e05b0ff3 2008-07-03 rsc vacfiledecref(fp);
380 e05b0ff3 2008-07-03 rsc
381 e05b0ff3 2008-07-03 rsc sprint(path, "%04d/%s", year, buf);
382 e05b0ff3 2008-07-03 rsc return f;
383 e05b0ff3 2008-07-03 rsc }
384 e05b0ff3 2008-07-03 rsc
385 003c13aa 2008-06-15 rsc static void
386 003c13aa 2008-06-15 rsc removevacfile(void)
387 3d77c87e 2004-03-15 devnull {
388 003c13aa 2008-06-15 rsc if(vacfile)
389 003c13aa 2008-06-15 rsc remove(vacfile);
390 3d77c87e 2004-03-15 devnull }
391 3d77c87e 2004-03-15 devnull
392 003c13aa 2008-06-15 rsc void
393 003c13aa 2008-06-15 rsc plan9tovacdir(VacDir *vd, Dir *dir)
394 7763a61a 2003-11-23 devnull {
395 003c13aa 2008-06-15 rsc memset(vd, 0, sizeof *vd);
396 7763a61a 2003-11-23 devnull
397 003c13aa 2008-06-15 rsc vd->elem = dir->name;
398 003c13aa 2008-06-15 rsc vd->uid = dir->uid;
399 003c13aa 2008-06-15 rsc vd->gid = dir->gid;
400 003c13aa 2008-06-15 rsc vd->mid = dir->muid;
401 003c13aa 2008-06-15 rsc if(vd->mid == nil)
402 003c13aa 2008-06-15 rsc vd->mid = "";
403 003c13aa 2008-06-15 rsc vd->mtime = dir->mtime;
404 003c13aa 2008-06-15 rsc vd->mcount = 0;
405 003c13aa 2008-06-15 rsc vd->ctime = dir->mtime; /* ctime: not available on plan 9 */
406 003c13aa 2008-06-15 rsc vd->atime = dir->atime;
407 003c13aa 2008-06-15 rsc vd->size = dir->length;
408 7763a61a 2003-11-23 devnull
409 003c13aa 2008-06-15 rsc vd->mode = dir->mode & 0777;
410 003c13aa 2008-06-15 rsc if(dir->mode & DMDIR)
411 003c13aa 2008-06-15 rsc vd->mode |= ModeDir;
412 003c13aa 2008-06-15 rsc if(dir->mode & DMAPPEND)
413 003c13aa 2008-06-15 rsc vd->mode |= ModeAppend;
414 003c13aa 2008-06-15 rsc if(dir->mode & DMEXCL)
415 003c13aa 2008-06-15 rsc vd->mode |= ModeExclusive;
416 003c13aa 2008-06-15 rsc #ifdef PLAN9PORT
417 003c13aa 2008-06-15 rsc if(dir->mode & DMDEVICE)
418 003c13aa 2008-06-15 rsc vd->mode |= ModeDevice;
419 003c13aa 2008-06-15 rsc if(dir->mode & DMNAMEDPIPE)
420 003c13aa 2008-06-15 rsc vd->mode |= ModeNamedPipe;
421 003c13aa 2008-06-15 rsc if(dir->mode & DMSYMLINK)
422 003c13aa 2008-06-15 rsc vd->mode |= ModeLink;
423 003c13aa 2008-06-15 rsc #endif
424 7763a61a 2003-11-23 devnull
425 003c13aa 2008-06-15 rsc vd->plan9 = 1;
426 003c13aa 2008-06-15 rsc vd->p9path = dir->qid.path;
427 003c13aa 2008-06-15 rsc vd->p9version = dir->qid.vers;
428 7763a61a 2003-11-23 devnull }
429 7763a61a 2003-11-23 devnull
430 003c13aa 2008-06-15 rsc #ifdef PLAN9PORT
431 003c13aa 2008-06-15 rsc enum {
432 003c13aa 2008-06-15 rsc Special =
433 003c13aa 2008-06-15 rsc DMSOCKET |
434 003c13aa 2008-06-15 rsc DMSYMLINK |
435 003c13aa 2008-06-15 rsc DMNAMEDPIPE |
436 003c13aa 2008-06-15 rsc DMDEVICE
437 003c13aa 2008-06-15 rsc };
438 003c13aa 2008-06-15 rsc #endif
439 7763a61a 2003-11-23 devnull
440 003c13aa 2008-06-15 rsc /*
441 003c13aa 2008-06-15 rsc * Archive the file named name, which has stat info d,
442 003c13aa 2008-06-15 rsc * into the vac directory fp (p = parent).
443 003c13aa 2008-06-15 rsc *
444 003c13aa 2008-06-15 rsc * If we're doing a vac -d against another archive, the
445 003c13aa 2008-06-15 rsc * equivalent directory to fp in that archive is diffp.
446 003c13aa 2008-06-15 rsc */
447 003c13aa 2008-06-15 rsc void
448 003c13aa 2008-06-15 rsc vac(VacFile *fp, VacFile *diffp, char *name, Dir *d)
449 7763a61a 2003-11-23 devnull {
450 003c13aa 2008-06-15 rsc char *elem, *s;
451 75d04888 2009-05-25 rsc static char *buf;
452 003c13aa 2008-06-15 rsc int fd, i, n, bsize;
453 003c13aa 2008-06-15 rsc vlong off;
454 003c13aa 2008-06-15 rsc Dir *dk; // kids
455 003c13aa 2008-06-15 rsc VacDir vd, vddiff;
456 003c13aa 2008-06-15 rsc VacFile *f, *fdiff;
457 003c13aa 2008-06-15 rsc VtEntry e;
458 7763a61a 2003-11-23 devnull
459 e05b0ff3 2008-07-03 rsc if(!includefile(name)){
460 003c13aa 2008-06-15 rsc warn("excluding %s%s", name, (d->mode&DMDIR) ? "/" : "");
461 003c13aa 2008-06-15 rsc return;
462 7763a61a 2003-11-23 devnull }
463 7763a61a 2003-11-23 devnull
464 003c13aa 2008-06-15 rsc if(d->mode&DMDIR)
465 003c13aa 2008-06-15 rsc stats.ndir++;
466 003c13aa 2008-06-15 rsc else
467 003c13aa 2008-06-15 rsc stats.nfile++;
468 7763a61a 2003-11-23 devnull
469 003c13aa 2008-06-15 rsc if(merge && vacmerge(fp, name) >= 0)
470 003c13aa 2008-06-15 rsc return;
471 003c13aa 2008-06-15 rsc
472 003c13aa 2008-06-15 rsc if(verbose)
473 003c13aa 2008-06-15 rsc fprint(2, "%s%s\n", name, (d->mode&DMDIR) ? "/" : "");
474 7763a61a 2003-11-23 devnull
475 003c13aa 2008-06-15 rsc #ifdef PLAN9PORT
476 003c13aa 2008-06-15 rsc if(d->mode&Special)
477 003c13aa 2008-06-15 rsc fd = -1;
478 003c13aa 2008-06-15 rsc else
479 003c13aa 2008-06-15 rsc #endif
480 003c13aa 2008-06-15 rsc if((fd = open(name, OREAD)) < 0){
481 003c13aa 2008-06-15 rsc warn("open %s: %r", name);
482 003c13aa 2008-06-15 rsc return;
483 7763a61a 2003-11-23 devnull }
484 7763a61a 2003-11-23 devnull
485 003c13aa 2008-06-15 rsc elem = strrchr(name, '/');
486 003c13aa 2008-06-15 rsc if(elem)
487 003c13aa 2008-06-15 rsc elem++;
488 003c13aa 2008-06-15 rsc else
489 003c13aa 2008-06-15 rsc elem = name;
490 7763a61a 2003-11-23 devnull
491 003c13aa 2008-06-15 rsc plan9tovacdir(&vd, d);
492 003c13aa 2008-06-15 rsc if((f = vacfilecreate(fp, elem, vd.mode)) == nil){
493 003c13aa 2008-06-15 rsc warn("vacfilecreate %s: %r", name);
494 003c13aa 2008-06-15 rsc return;
495 7763a61a 2003-11-23 devnull }
496 003c13aa 2008-06-15 rsc if(diffp)
497 003c13aa 2008-06-15 rsc fdiff = vacfilewalk(diffp, elem);
498 003c13aa 2008-06-15 rsc else
499 003c13aa 2008-06-15 rsc fdiff = nil;
500 7763a61a 2003-11-23 devnull
501 003c13aa 2008-06-15 rsc if(vacfilesetdir(f, &vd) < 0)
502 003c13aa 2008-06-15 rsc warn("vacfilesetdir %s: %r", name);
503 7763a61a 2003-11-23 devnull
504 003c13aa 2008-06-15 rsc #ifdef PLAN9PORT
505 003c13aa 2008-06-15 rsc if(d->mode&(DMSOCKET|DMNAMEDPIPE)){
506 003c13aa 2008-06-15 rsc /* don't write anything */
507 7763a61a 2003-11-23 devnull }
508 003c13aa 2008-06-15 rsc else if(d->mode&DMSYMLINK){
509 003c13aa 2008-06-15 rsc n = readlink(name, buf, sizeof buf);
510 003c13aa 2008-06-15 rsc if(n > 0 && vacfilewrite(f, buf, n, 0) < 0){
511 003c13aa 2008-06-15 rsc warn("venti write %s: %r", name);
512 003c13aa 2008-06-15 rsc goto Out;
513 003c13aa 2008-06-15 rsc }
514 003c13aa 2008-06-15 rsc stats.data += n;
515 003c13aa 2008-06-15 rsc }else if(d->mode&DMDEVICE){
516 003c13aa 2008-06-15 rsc snprint(buf, sizeof buf, "%c %d %d",
517 003c13aa 2008-06-15 rsc (char)((d->qid.path >> 16) & 0xFF),
518 003c13aa 2008-06-15 rsc (int)(d->qid.path & 0xFF),
519 003c13aa 2008-06-15 rsc (int)((d->qid.path >> 8) & 0xFF));
520 003c13aa 2008-06-15 rsc if(vacfilewrite(f, buf, strlen(buf), 0) < 0){
521 003c13aa 2008-06-15 rsc warn("venti write %s: %r", name);
522 003c13aa 2008-06-15 rsc goto Out;
523 003c13aa 2008-06-15 rsc }
524 003c13aa 2008-06-15 rsc stats.data += strlen(buf);
525 003c13aa 2008-06-15 rsc }else
526 003c13aa 2008-06-15 rsc #endif
527 003c13aa 2008-06-15 rsc if(d->mode&DMDIR){
528 003c13aa 2008-06-15 rsc while((n = dirread(fd, &dk)) > 0){
529 003c13aa 2008-06-15 rsc for(i=0; i<n; i++){
530 003c13aa 2008-06-15 rsc s = vtmalloc(strlen(name)+1+strlen(dk[i].name)+1);
531 003c13aa 2008-06-15 rsc strcpy(s, name);
532 003c13aa 2008-06-15 rsc strcat(s, "/");
533 003c13aa 2008-06-15 rsc strcat(s, dk[i].name);
534 003c13aa 2008-06-15 rsc vac(f, fdiff, s, &dk[i]);
535 003c13aa 2008-06-15 rsc free(s);
536 003c13aa 2008-06-15 rsc }
537 003c13aa 2008-06-15 rsc free(dk);
538 003c13aa 2008-06-15 rsc }
539 003c13aa 2008-06-15 rsc }else{
540 003c13aa 2008-06-15 rsc off = 0;
541 003c13aa 2008-06-15 rsc bsize = fs->bsize;
542 75d04888 2009-05-25 rsc if(buf == nil)
543 75d04888 2009-05-25 rsc buf = vtmallocz(bsize);
544 003c13aa 2008-06-15 rsc if(fdiff){
545 003c13aa 2008-06-15 rsc /*
546 003c13aa 2008-06-15 rsc * Copy fdiff's contents into f by moving the score.
547 003c13aa 2008-06-15 rsc * We'll diff and update below.
548 003c13aa 2008-06-15 rsc */
549 003c13aa 2008-06-15 rsc if(vacfilegetentries(fdiff, &e, nil) >= 0)
550 003c13aa 2008-06-15 rsc if(vacfilesetentries(f, &e, nil) >= 0){
551 003c13aa 2008-06-15 rsc bsize = e.dsize;
552 003c13aa 2008-06-15 rsc
553 003c13aa 2008-06-15 rsc /*
554 003c13aa 2008-06-15 rsc * Or if -q is set, and the metadata looks the same,
555 003c13aa 2008-06-15 rsc * don't even bother reading the file.
556 003c13aa 2008-06-15 rsc */
557 003c13aa 2008-06-15 rsc if(qdiff && vacfilegetdir(fdiff, &vddiff) >= 0){
558 003c13aa 2008-06-15 rsc if(vddiff.mtime == vd.mtime)
559 003c13aa 2008-06-15 rsc if(vddiff.size == vd.size)
560 003c13aa 2008-06-15 rsc if(!vddiff.plan9 || (/* vddiff.p9path == vd.p9path && */ vddiff.p9version == vd.p9version)){
561 003c13aa 2008-06-15 rsc stats.skipfiles++;
562 003c13aa 2008-06-15 rsc stats.nfile--;
563 003c13aa 2008-06-15 rsc vdcleanup(&vddiff);
564 003c13aa 2008-06-15 rsc goto Out;
565 003c13aa 2008-06-15 rsc }
566 003c13aa 2008-06-15 rsc
567 003c13aa 2008-06-15 rsc /*
568 003c13aa 2008-06-15 rsc * Skip over presumably-unchanged prefix
569 003c13aa 2008-06-15 rsc * of an append-only file.
570 003c13aa 2008-06-15 rsc */
571 003c13aa 2008-06-15 rsc if(vd.mode&ModeAppend)
572 003c13aa 2008-06-15 rsc if(vddiff.size < vd.size)
573 003c13aa 2008-06-15 rsc if(vddiff.plan9 && vd.plan9)
574 003c13aa 2008-06-15 rsc if(vddiff.p9path == vd.p9path){
575 003c13aa 2008-06-15 rsc off = vd.size/bsize*bsize;
576 003c13aa 2008-06-15 rsc if(seek(fd, off, 0) >= 0)
577 003c13aa 2008-06-15 rsc stats.skipdata += off;
578 003c13aa 2008-06-15 rsc else{
579 003c13aa 2008-06-15 rsc seek(fd, 0, 0); // paranoia
580 003c13aa 2008-06-15 rsc off = 0;
581 003c13aa 2008-06-15 rsc }
582 003c13aa 2008-06-15 rsc }
583 7763a61a 2003-11-23 devnull
584 003c13aa 2008-06-15 rsc vdcleanup(&vddiff);
585 003c13aa 2008-06-15 rsc // XXX different verbose chatty prints for kaminsky?
586 003c13aa 2008-06-15 rsc }
587 71f05672 2005-09-13 devnull }
588 71f05672 2005-09-13 devnull }
589 003c13aa 2008-06-15 rsc if(qdiff && verbose)
590 003c13aa 2008-06-15 rsc fprint(2, "+%s\n", name);
591 003c13aa 2008-06-15 rsc while((n = readn(fd, buf, bsize)) > 0){
592 003c13aa 2008-06-15 rsc if(fdiff && sha1matches(f, off/bsize, (uchar*)buf, n)){
593 003c13aa 2008-06-15 rsc off += n;
594 003c13aa 2008-06-15 rsc stats.skipdata += n;
595 003c13aa 2008-06-15 rsc continue;
596 003c13aa 2008-06-15 rsc }
597 003c13aa 2008-06-15 rsc if(vacfilewrite(f, buf, n, off) < 0){
598 003c13aa 2008-06-15 rsc warn("venti write %s: %r", name);
599 003c13aa 2008-06-15 rsc goto Out;
600 003c13aa 2008-06-15 rsc }
601 003c13aa 2008-06-15 rsc stats.data += n;
602 003c13aa 2008-06-15 rsc off += n;
603 003c13aa 2008-06-15 rsc }
604 003c13aa 2008-06-15 rsc /*
605 003c13aa 2008-06-15 rsc * Since we started with fdiff's contents,
606 003c13aa 2008-06-15 rsc * set the size in case fdiff was bigger.
607 003c13aa 2008-06-15 rsc */
608 003c13aa 2008-06-15 rsc if(fdiff && vacfilesetsize(f, off) < 0)
609 003c13aa 2008-06-15 rsc warn("vtfilesetsize %s: %r", name);
610 71f05672 2005-09-13 devnull }
611 71f05672 2005-09-13 devnull
612 003c13aa 2008-06-15 rsc Out:
613 003c13aa 2008-06-15 rsc vacfileflush(f, 1);
614 003c13aa 2008-06-15 rsc vacfiledecref(f);
615 003c13aa 2008-06-15 rsc if(fdiff)
616 003c13aa 2008-06-15 rsc vacfiledecref(fdiff);
617 003c13aa 2008-06-15 rsc close(fd);
618 71f05672 2005-09-13 devnull }
619 71f05672 2005-09-13 devnull
620 7763a61a 2003-11-23 devnull void
621 003c13aa 2008-06-15 rsc vacstdin(VacFile *fp, char *name)
622 7763a61a 2003-11-23 devnull {
623 003c13aa 2008-06-15 rsc vlong off;
624 003c13aa 2008-06-15 rsc VacFile *f;
625 003c13aa 2008-06-15 rsc static char buf[8192];
626 003c13aa 2008-06-15 rsc int n;
627 7763a61a 2003-11-23 devnull
628 003c13aa 2008-06-15 rsc if((f = vacfilecreate(fp, name, 0666)) == nil){
629 003c13aa 2008-06-15 rsc warn("vacfilecreate %s: %r", name);
630 003c13aa 2008-06-15 rsc return;
631 7763a61a 2003-11-23 devnull }
632 7763a61a 2003-11-23 devnull
633 003c13aa 2008-06-15 rsc off = 0;
634 003c13aa 2008-06-15 rsc while((n = read(0, buf, sizeof buf)) > 0){
635 003c13aa 2008-06-15 rsc if(vacfilewrite(f, buf, n, off) < 0){
636 003c13aa 2008-06-15 rsc warn("venti write %s: %r", name);
637 003c13aa 2008-06-15 rsc vacfiledecref(f);
638 003c13aa 2008-06-15 rsc return;
639 003c13aa 2008-06-15 rsc }
640 003c13aa 2008-06-15 rsc off += n;
641 7763a61a 2003-11-23 devnull }
642 003c13aa 2008-06-15 rsc vacfileflush(f, 1);
643 003c13aa 2008-06-15 rsc vacfiledecref(f);
644 7763a61a 2003-11-23 devnull }
645 7763a61a 2003-11-23 devnull
646 003c13aa 2008-06-15 rsc /*
647 003c13aa 2008-06-15 rsc * fp is the directory we're writing.
648 003c13aa 2008-06-15 rsc * mp is the directory whose contents we're merging in.
649 003c13aa 2008-06-15 rsc * d is the directory entry of the file from mp that we want to add to fp.
650 003c13aa 2008-06-15 rsc * vacfile is the name of the .vac file, for error messages.
651 003c13aa 2008-06-15 rsc * offset is the qid that qid==0 in mp should correspond to.
652 003c13aa 2008-06-15 rsc * max is the maximum qid we expect to see (not really needed).
653 003c13aa 2008-06-15 rsc */
654 003c13aa 2008-06-15 rsc int
655 003c13aa 2008-06-15 rsc vacmergefile(VacFile *fp, VacFile *mp, VacDir *d, char *vacfile,
656 003c13aa 2008-06-15 rsc vlong offset, vlong max)
657 7763a61a 2003-11-23 devnull {
658 003c13aa 2008-06-15 rsc VtEntry ed, em;
659 003c13aa 2008-06-15 rsc VacFile *mf;
660 003c13aa 2008-06-15 rsc VacFile *f;
661 7763a61a 2003-11-23 devnull
662 003c13aa 2008-06-15 rsc mf = vacfilewalk(mp, d->elem);
663 003c13aa 2008-06-15 rsc if(mf == nil){
664 003c13aa 2008-06-15 rsc warn("could not walk %s in %s", d->elem, vacfile);
665 003c13aa 2008-06-15 rsc return -1;
666 7763a61a 2003-11-23 devnull }
667 003c13aa 2008-06-15 rsc if(vacfilegetentries(mf, &ed, &em) < 0){
668 003c13aa 2008-06-15 rsc warn("could not get entries for %s in %s", d->elem, vacfile);
669 003c13aa 2008-06-15 rsc vacfiledecref(mf);
670 003c13aa 2008-06-15 rsc return -1;
671 7763a61a 2003-11-23 devnull }
672 003c13aa 2008-06-15 rsc
673 003c13aa 2008-06-15 rsc if((f = vacfilecreate(fp, d->elem, d->mode)) == nil){
674 003c13aa 2008-06-15 rsc warn("vacfilecreate %s: %r", d->elem);
675 003c13aa 2008-06-15 rsc vacfiledecref(mf);
676 003c13aa 2008-06-15 rsc return -1;
677 7763a61a 2003-11-23 devnull }
678 003c13aa 2008-06-15 rsc if(d->qidspace){
679 003c13aa 2008-06-15 rsc d->qidoffset += offset;
680 003c13aa 2008-06-15 rsc d->qidmax += offset;
681 003c13aa 2008-06-15 rsc }else{
682 003c13aa 2008-06-15 rsc d->qidspace = 1;
683 003c13aa 2008-06-15 rsc d->qidoffset = offset;
684 003c13aa 2008-06-15 rsc d->qidmax = max;
685 7763a61a 2003-11-23 devnull }
686 fa3c8da1 2008-06-15 rsc if(vacfilesetdir(f, d) < 0
687 fa3c8da1 2008-06-15 rsc || vacfilesetentries(f, &ed, &em) < 0
688 fa3c8da1 2008-06-15 rsc || vacfilesetqidspace(f, d->qidoffset, d->qidmax) < 0){
689 003c13aa 2008-06-15 rsc warn("vacmergefile %s: %r", d->elem);
690 003c13aa 2008-06-15 rsc vacfiledecref(mf);
691 003c13aa 2008-06-15 rsc vacfiledecref(f);
692 3d77c87e 2004-03-15 devnull return -1;
693 003c13aa 2008-06-15 rsc }
694 003c13aa 2008-06-15 rsc
695 003c13aa 2008-06-15 rsc vacfiledecref(mf);
696 003c13aa 2008-06-15 rsc vacfiledecref(f);
697 3d77c87e 2004-03-15 devnull return 0;
698 7763a61a 2003-11-23 devnull }
699 7763a61a 2003-11-23 devnull
700 7763a61a 2003-11-23 devnull int
701 003c13aa 2008-06-15 rsc vacmerge(VacFile *fp, char *name)
702 7763a61a 2003-11-23 devnull {
703 003c13aa 2008-06-15 rsc VacFs *mfs;
704 003c13aa 2008-06-15 rsc VacDir vd;
705 003c13aa 2008-06-15 rsc VacDirEnum *de;
706 003c13aa 2008-06-15 rsc VacFile *mp;
707 003c13aa 2008-06-15 rsc uvlong maxqid, offset;
708 7763a61a 2003-11-23 devnull
709 003c13aa 2008-06-15 rsc if(strlen(name) < 4 || strcmp(name+strlen(name)-4, ".vac") != 0)
710 003c13aa 2008-06-15 rsc return -1;
711 75d04888 2009-05-25 rsc if((mfs = vacfsopen(z, name, VtOREAD, 4<<20)) == nil)
712 003c13aa 2008-06-15 rsc return -1;
713 003c13aa 2008-06-15 rsc if(verbose)
714 003c13aa 2008-06-15 rsc fprint(2, "merging %s\n", name);
715 7763a61a 2003-11-23 devnull
716 9b3ac170 2008-07-02 rsc mp = vacfsgetroot(mfs);
717 9b3ac170 2008-07-02 rsc de = vdeopen(mp);
718 003c13aa 2008-06-15 rsc if(de){
719 003c13aa 2008-06-15 rsc offset = 0;
720 003c13aa 2008-06-15 rsc if(vacfsgetmaxqid(mfs, &maxqid) >= 0){
721 003c13aa 2008-06-15 rsc _vacfsnextqid(fs, &offset);
722 003c13aa 2008-06-15 rsc vacfsjumpqid(fs, maxqid+1);
723 003c13aa 2008-06-15 rsc }
724 003c13aa 2008-06-15 rsc while(vderead(de, &vd) > 0){
725 003c13aa 2008-06-15 rsc if(vd.qid > maxqid){
726 003c13aa 2008-06-15 rsc warn("vacmerge %s: maxqid=%lld but %s has %lld",
727 003c13aa 2008-06-15 rsc name, maxqid, vd.elem, vd.qid);
728 003c13aa 2008-06-15 rsc vacfsjumpqid(fs, vd.qid - maxqid);
729 003c13aa 2008-06-15 rsc maxqid = vd.qid;
730 003c13aa 2008-06-15 rsc }
731 003c13aa 2008-06-15 rsc vacmergefile(fp, mp, &vd, name,
732 003c13aa 2008-06-15 rsc offset, maxqid);
733 003c13aa 2008-06-15 rsc vdcleanup(&vd);
734 003c13aa 2008-06-15 rsc }
735 003c13aa 2008-06-15 rsc vdeclose(de);
736 7763a61a 2003-11-23 devnull }
737 9b3ac170 2008-07-02 rsc vacfiledecref(mp);
738 003c13aa 2008-06-15 rsc vacfsclose(mfs);
739 003c13aa 2008-06-15 rsc return 0;
740 7763a61a 2003-11-23 devnull }
741 7763a61a 2003-11-23 devnull
742 7763a61a 2003-11-23 devnull #define TWID64 ((u64int)~(u64int)0)
743 7763a61a 2003-11-23 devnull
744 7763a61a 2003-11-23 devnull static u64int
745 7763a61a 2003-11-23 devnull unittoull(char *s)
746 7763a61a 2003-11-23 devnull {
747 7763a61a 2003-11-23 devnull char *es;
748 7763a61a 2003-11-23 devnull u64int n;
749 7763a61a 2003-11-23 devnull
750 7763a61a 2003-11-23 devnull if(s == nil)
751 7763a61a 2003-11-23 devnull return TWID64;
752 7763a61a 2003-11-23 devnull n = strtoul(s, &es, 0);
753 7763a61a 2003-11-23 devnull if(*es == 'k' || *es == 'K'){
754 7763a61a 2003-11-23 devnull n *= 1024;
755 7763a61a 2003-11-23 devnull es++;
756 7763a61a 2003-11-23 devnull }else if(*es == 'm' || *es == 'M'){
757 7763a61a 2003-11-23 devnull n *= 1024*1024;
758 7763a61a 2003-11-23 devnull es++;
759 7763a61a 2003-11-23 devnull }else if(*es == 'g' || *es == 'G'){
760 7763a61a 2003-11-23 devnull n *= 1024*1024*1024;
761 7763a61a 2003-11-23 devnull es++;
762 7763a61a 2003-11-23 devnull }
763 7763a61a 2003-11-23 devnull if(*es != '\0')
764 7763a61a 2003-11-23 devnull return TWID64;
765 7763a61a 2003-11-23 devnull return n;
766 7763a61a 2003-11-23 devnull }
767 003c13aa 2008-06-15 rsc
768 003c13aa 2008-06-15 rsc static void
769 003c13aa 2008-06-15 rsc warn(char *fmt, ...)
770 003c13aa 2008-06-15 rsc {
771 003c13aa 2008-06-15 rsc va_list arg;
772 003c13aa 2008-06-15 rsc
773 003c13aa 2008-06-15 rsc va_start(arg, fmt);
774 003c13aa 2008-06-15 rsc fprint(2, "vac: ");
775 003c13aa 2008-06-15 rsc vfprint(2, fmt, arg);
776 003c13aa 2008-06-15 rsc fprint(2, "\n");
777 003c13aa 2008-06-15 rsc va_end(arg);
778 003c13aa 2008-06-15 rsc }
779 003c13aa 2008-06-15 rsc