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