Blame


1 7763a61a 2003-11-23 devnull #include "stdinc.h"
2 7763a61a 2003-11-23 devnull #include "vac.h"
3 7763a61a 2003-11-23 devnull #include "dat.h"
4 7763a61a 2003-11-23 devnull #include "fns.h"
5 7763a61a 2003-11-23 devnull
6 7763a61a 2003-11-23 devnull typedef struct Sink Sink;
7 7763a61a 2003-11-23 devnull typedef struct MetaSink MetaSink;
8 7763a61a 2003-11-23 devnull typedef struct DirSink DirSink;
9 7763a61a 2003-11-23 devnull
10 7763a61a 2003-11-23 devnull struct Sink {
11 7763a61a 2003-11-23 devnull VtSession *z;
12 7763a61a 2003-11-23 devnull VtEntry dir;
13 7763a61a 2003-11-23 devnull uchar *buf;
14 7763a61a 2003-11-23 devnull uchar *pbuf[VtPointerDepth+1];
15 7763a61a 2003-11-23 devnull };
16 7763a61a 2003-11-23 devnull
17 7763a61a 2003-11-23 devnull struct DirSink {
18 7763a61a 2003-11-23 devnull Sink *sink;
19 7763a61a 2003-11-23 devnull MetaSink *msink;
20 7763a61a 2003-11-23 devnull ulong nentry;
21 7763a61a 2003-11-23 devnull uchar *buf;
22 7763a61a 2003-11-23 devnull uchar *p; /* current pointer */
23 7763a61a 2003-11-23 devnull uchar *ep; /* end pointer */
24 7763a61a 2003-11-23 devnull };
25 7763a61a 2003-11-23 devnull
26 7763a61a 2003-11-23 devnull struct MetaSink {
27 7763a61a 2003-11-23 devnull Sink *sink;
28 7763a61a 2003-11-23 devnull uchar *buf;
29 7763a61a 2003-11-23 devnull int maxindex;
30 7763a61a 2003-11-23 devnull int nindex;
31 7763a61a 2003-11-23 devnull uchar *rp; /* start of current record */
32 7763a61a 2003-11-23 devnull uchar *p; /* current pointer */
33 7763a61a 2003-11-23 devnull uchar *ep; /* end pointer */
34 7763a61a 2003-11-23 devnull };
35 7763a61a 2003-11-23 devnull
36 7763a61a 2003-11-23 devnull static void usage(void);
37 7763a61a 2003-11-23 devnull static int strpCmp(void*, void*);
38 7763a61a 2003-11-23 devnull static void warn(char *fmt, ...);
39 7763a61a 2003-11-23 devnull static void cleanup(void);
40 7763a61a 2003-11-23 devnull static u64int unittoull(char *s);
41 7763a61a 2003-11-23 devnull static int vac(VtSession *z, char *argv[]);
42 7763a61a 2003-11-23 devnull static void vacFile(DirSink *dsink, char *lname, char *sname, VacFile*);
43 7763a61a 2003-11-23 devnull static void vacStdin(DirSink *dsink, char *name, VacFile *vf);
44 7763a61a 2003-11-23 devnull static void vacData(DirSink *dsink, int fd, char *lname, VacFile*, Dir*);
45 7763a61a 2003-11-23 devnull static void vacDir(DirSink *dsink, int fd, char *lname, char *sname, VacFile*);
46 7763a61a 2003-11-23 devnull static int vacMerge(DirSink *dsink, char *lname, char *sname);
47 7763a61a 2003-11-23 devnull
48 7763a61a 2003-11-23 devnull Sink *sinkAlloc(VtSession *z, int psize, int dsize);
49 7763a61a 2003-11-23 devnull void sinkWrite(Sink *k, uchar *data, int n);
50 7763a61a 2003-11-23 devnull void sinkWriteScore(Sink *k, uchar *score, int n);
51 7763a61a 2003-11-23 devnull void sinkClose(Sink *k);
52 7763a61a 2003-11-23 devnull void sinkFree(Sink *k);
53 7763a61a 2003-11-23 devnull
54 7763a61a 2003-11-23 devnull DirSink *dirSinkAlloc(VtSession *z, int psize, int dsize);
55 7763a61a 2003-11-23 devnull void dirSinkWrite(DirSink *k, VtEntry*);
56 7763a61a 2003-11-23 devnull void dirSinkWriteSink(DirSink *k, Sink*);
57 7763a61a 2003-11-23 devnull int dirSinkWriteFile(DirSink *k, VacFile *vf);
58 7763a61a 2003-11-23 devnull void dirSinkClose(DirSink *k);
59 7763a61a 2003-11-23 devnull void dirSinkFree(DirSink *k);
60 7763a61a 2003-11-23 devnull
61 7763a61a 2003-11-23 devnull MetaSink *metaSinkAlloc(VtSession *z, int psize, int dsize);
62 7763a61a 2003-11-23 devnull void metaSinkPutc(MetaSink *k, int c);
63 7763a61a 2003-11-23 devnull void metaSinkPutString(MetaSink *k, char *s);
64 7763a61a 2003-11-23 devnull void metaSinkPutUint32(MetaSink *k, ulong x);
65 7763a61a 2003-11-23 devnull void metaSinkPutUint64(MetaSink *k, uvlong x);
66 7763a61a 2003-11-23 devnull void metaSinkWrite(MetaSink *k, uchar *data, int n);
67 7763a61a 2003-11-23 devnull void metaSinkWriteDir(MetaSink *ms, VacDir *vd);
68 7763a61a 2003-11-23 devnull void metaSinkEOR(MetaSink *k);
69 7763a61a 2003-11-23 devnull void metaSinkClose(MetaSink *k);
70 7763a61a 2003-11-23 devnull void metaSinkFree(MetaSink *k);
71 7763a61a 2003-11-23 devnull void plan9ToVacDir(VacDir*, Dir*, ulong entry, uvlong qid);
72 7763a61a 2003-11-23 devnull
73 7763a61a 2003-11-23 devnull enum {
74 7763a61a 2003-11-23 devnull Version = 8,
75 7763a61a 2003-11-23 devnull BlockSize = 8*1024,
76 7763a61a 2003-11-23 devnull MaxExclude = 1000,
77 7763a61a 2003-11-23 devnull };
78 7763a61a 2003-11-23 devnull
79 7763a61a 2003-11-23 devnull struct {
80 7763a61a 2003-11-23 devnull ulong file;
81 7763a61a 2003-11-23 devnull ulong sfile;
82 7763a61a 2003-11-23 devnull ulong data;
83 7763a61a 2003-11-23 devnull ulong sdata;
84 7763a61a 2003-11-23 devnull ulong skip;
85 7763a61a 2003-11-23 devnull ulong meta;
86 7763a61a 2003-11-23 devnull } stats;
87 7763a61a 2003-11-23 devnull
88 7763a61a 2003-11-23 devnull int bsize = BlockSize;
89 7763a61a 2003-11-23 devnull int maxbsize;
90 7763a61a 2003-11-23 devnull char *oname, *dfile;
91 7763a61a 2003-11-23 devnull int verbose;
92 7763a61a 2003-11-23 devnull uvlong fileid = 1;
93 7763a61a 2003-11-23 devnull int qdiff;
94 7763a61a 2003-11-23 devnull char *exclude[MaxExclude];
95 7763a61a 2003-11-23 devnull int nexclude;
96 7763a61a 2003-11-23 devnull int nowrite;
97 7763a61a 2003-11-23 devnull int merge;
98 7763a61a 2003-11-23 devnull char *isi;
99 7763a61a 2003-11-23 devnull
100 7763a61a 2003-11-23 devnull void
101 7763a61a 2003-11-23 devnull main(int argc, char *argv[])
102 7763a61a 2003-11-23 devnull {
103 7763a61a 2003-11-23 devnull VtSession *z;
104 7763a61a 2003-11-23 devnull char *p;
105 7763a61a 2003-11-23 devnull char *host = nil;
106 7763a61a 2003-11-23 devnull int statsFlag = 0;
107 7763a61a 2003-11-23 devnull
108 7763a61a 2003-11-23 devnull atexit(cleanup);
109 7763a61a 2003-11-23 devnull
110 7763a61a 2003-11-23 devnull ARGBEGIN{
111 7763a61a 2003-11-23 devnull default:
112 7763a61a 2003-11-23 devnull usage();
113 7763a61a 2003-11-23 devnull case 'b':
114 7763a61a 2003-11-23 devnull p = ARGF();
115 7763a61a 2003-11-23 devnull if(p == 0)
116 7763a61a 2003-11-23 devnull usage();
117 7763a61a 2003-11-23 devnull bsize = unittoull(p);
118 7763a61a 2003-11-23 devnull if(bsize == ~0)
119 7763a61a 2003-11-23 devnull usage();
120 7763a61a 2003-11-23 devnull break;
121 7763a61a 2003-11-23 devnull case 'd':
122 7763a61a 2003-11-23 devnull dfile = ARGF();
123 7763a61a 2003-11-23 devnull if(dfile == nil)
124 7763a61a 2003-11-23 devnull usage();
125 7763a61a 2003-11-23 devnull break;
126 7763a61a 2003-11-23 devnull case 'e':
127 7763a61a 2003-11-23 devnull if(nexclude >= MaxExclude)
128 7763a61a 2003-11-23 devnull sysfatal("too many exclusions\n");
129 7763a61a 2003-11-23 devnull exclude[nexclude] = ARGF();
130 7763a61a 2003-11-23 devnull if(exclude[nexclude] == nil)
131 7763a61a 2003-11-23 devnull usage();
132 7763a61a 2003-11-23 devnull nexclude++;
133 7763a61a 2003-11-23 devnull break;
134 7763a61a 2003-11-23 devnull case 'f':
135 7763a61a 2003-11-23 devnull oname = ARGF();
136 7763a61a 2003-11-23 devnull if(oname == 0)
137 7763a61a 2003-11-23 devnull usage();
138 7763a61a 2003-11-23 devnull break;
139 7763a61a 2003-11-23 devnull case 'h':
140 7763a61a 2003-11-23 devnull host = ARGF();
141 7763a61a 2003-11-23 devnull if(host == nil)
142 7763a61a 2003-11-23 devnull usage();
143 7763a61a 2003-11-23 devnull break;
144 7763a61a 2003-11-23 devnull case 'i':
145 7763a61a 2003-11-23 devnull isi = ARGF();
146 7763a61a 2003-11-23 devnull if(isi == nil)
147 7763a61a 2003-11-23 devnull usage();
148 7763a61a 2003-11-23 devnull break;
149 7763a61a 2003-11-23 devnull case 'n':
150 7763a61a 2003-11-23 devnull nowrite++;
151 7763a61a 2003-11-23 devnull break;
152 7763a61a 2003-11-23 devnull case 'm':
153 7763a61a 2003-11-23 devnull merge++;
154 7763a61a 2003-11-23 devnull break;
155 7763a61a 2003-11-23 devnull case 'q':
156 7763a61a 2003-11-23 devnull qdiff++;
157 7763a61a 2003-11-23 devnull break;
158 7763a61a 2003-11-23 devnull case 's':
159 7763a61a 2003-11-23 devnull statsFlag++;
160 7763a61a 2003-11-23 devnull break;
161 7763a61a 2003-11-23 devnull case 'v':
162 7763a61a 2003-11-23 devnull verbose++;
163 7763a61a 2003-11-23 devnull break;
164 7763a61a 2003-11-23 devnull }ARGEND;
165 7763a61a 2003-11-23 devnull
166 7763a61a 2003-11-23 devnull if(bsize < 512)
167 7763a61a 2003-11-23 devnull bsize = 512;
168 7763a61a 2003-11-23 devnull if(bsize > VtMaxLumpSize)
169 7763a61a 2003-11-23 devnull bsize = VtMaxLumpSize;
170 7763a61a 2003-11-23 devnull maxbsize = bsize;
171 7763a61a 2003-11-23 devnull
172 7763a61a 2003-11-23 devnull vtAttach();
173 7763a61a 2003-11-23 devnull
174 7763a61a 2003-11-23 devnull fmtinstall('V', vtScoreFmt);
175 7763a61a 2003-11-23 devnull fmtinstall('R', vtErrFmt);
176 7763a61a 2003-11-23 devnull
177 7763a61a 2003-11-23 devnull z = vtDial(host, 0);
178 7763a61a 2003-11-23 devnull if(z == nil)
179 7763a61a 2003-11-23 devnull vtFatal("could not connect to server: %R");
180 7763a61a 2003-11-23 devnull
181 7763a61a 2003-11-23 devnull if(!vtConnect(z, 0))
182 7763a61a 2003-11-23 devnull vtFatal("vtConnect: %R");
183 7763a61a 2003-11-23 devnull
184 7763a61a 2003-11-23 devnull qsort(exclude, nexclude, sizeof(char*), strpCmp);
185 7763a61a 2003-11-23 devnull
186 7763a61a 2003-11-23 devnull vac(z, argv);
187 7763a61a 2003-11-23 devnull if(!vtSync(z))
188 7763a61a 2003-11-23 devnull fprint(2, "warning: could not ask server to flush pending writes: %R\n");
189 7763a61a 2003-11-23 devnull
190 7763a61a 2003-11-23 devnull if(statsFlag)
191 7763a61a 2003-11-23 devnull fprint(2, "files %ld:%ld data %ld:%ld:%ld meta %ld\n", stats.file, stats.sfile,
192 7763a61a 2003-11-23 devnull stats.data, stats.skip, stats.sdata, stats.meta);
193 7763a61a 2003-11-23 devnull //packetStats();
194 7763a61a 2003-11-23 devnull vtClose(z);
195 7763a61a 2003-11-23 devnull vtDetach();
196 7763a61a 2003-11-23 devnull
197 7763a61a 2003-11-23 devnull exits(0);
198 7763a61a 2003-11-23 devnull }
199 7763a61a 2003-11-23 devnull
200 7763a61a 2003-11-23 devnull void
201 7763a61a 2003-11-23 devnull static usage(void)
202 7763a61a 2003-11-23 devnull {
203 7763a61a 2003-11-23 devnull fprint(2, "usage: %s [-amqsv] [-h host] [-d vacfile] [-b blocksize] [-i name] [-e exclude] [-f vacfile] file ... \n", argv0);
204 7763a61a 2003-11-23 devnull exits("usage");
205 7763a61a 2003-11-23 devnull }
206 7763a61a 2003-11-23 devnull
207 7763a61a 2003-11-23 devnull static
208 7763a61a 2003-11-23 devnull int strpCmp(void *p0, void *p1)
209 7763a61a 2003-11-23 devnull {
210 7763a61a 2003-11-23 devnull return strcmp(*(char**)p0, *(char**)p1);
211 7763a61a 2003-11-23 devnull }
212 7763a61a 2003-11-23 devnull
213 7763a61a 2003-11-23 devnull
214 7763a61a 2003-11-23 devnull int
215 7763a61a 2003-11-23 devnull readBlock(int fd, uchar *buf, int n)
216 7763a61a 2003-11-23 devnull {
217 7763a61a 2003-11-23 devnull int m, t = 0;
218 7763a61a 2003-11-23 devnull
219 7763a61a 2003-11-23 devnull while(t < n){
220 7763a61a 2003-11-23 devnull m = read(fd, buf+t, n-t);
221 7763a61a 2003-11-23 devnull if(m < 0)
222 7763a61a 2003-11-23 devnull return -1;
223 7763a61a 2003-11-23 devnull if(m == 0)
224 7763a61a 2003-11-23 devnull break;
225 7763a61a 2003-11-23 devnull t += m;
226 7763a61a 2003-11-23 devnull }
227 7763a61a 2003-11-23 devnull return t;
228 7763a61a 2003-11-23 devnull }
229 7763a61a 2003-11-23 devnull
230 7763a61a 2003-11-23 devnull int
231 7763a61a 2003-11-23 devnull vacWrite(VtSession *z, uchar score[VtScoreSize], int type, uchar *buf, int n)
232 7763a61a 2003-11-23 devnull {
233 7763a61a 2003-11-23 devnull assert(n > 0);
234 7763a61a 2003-11-23 devnull if(nowrite) {
235 7763a61a 2003-11-23 devnull vtSha1(score, buf, n);
236 7763a61a 2003-11-23 devnull return 1;
237 7763a61a 2003-11-23 devnull }
238 7763a61a 2003-11-23 devnull if(!vtWrite(z, score, type, buf, n))
239 7763a61a 2003-11-23 devnull return 0;
240 7763a61a 2003-11-23 devnull if(!vtSha1Check(score, buf, n)) {
241 7763a61a 2003-11-23 devnull uchar score2[VtScoreSize];
242 7763a61a 2003-11-23 devnull
243 7763a61a 2003-11-23 devnull vtSha1(score2, buf, n);
244 7763a61a 2003-11-23 devnull fprint(2, "vtSha1Check: n = %d %V %V\n", n, score, score2);
245 7763a61a 2003-11-23 devnull vtSetError("vtSha1Check failed");
246 7763a61a 2003-11-23 devnull return 0;
247 7763a61a 2003-11-23 devnull }
248 7763a61a 2003-11-23 devnull return 1;
249 7763a61a 2003-11-23 devnull }
250 7763a61a 2003-11-23 devnull
251 7763a61a 2003-11-23 devnull
252 7763a61a 2003-11-23 devnull static int
253 7763a61a 2003-11-23 devnull vac(VtSession *z, char *argv[])
254 7763a61a 2003-11-23 devnull {
255 7763a61a 2003-11-23 devnull DirSink *dsink, *ds;
256 7763a61a 2003-11-23 devnull MetaSink *ms;
257 7763a61a 2003-11-23 devnull VtRoot root;
258 7763a61a 2003-11-23 devnull uchar score[VtScoreSize], buf[VtRootSize];
259 7763a61a 2003-11-23 devnull char cwd[2048];
260 7763a61a 2003-11-23 devnull int cd, i;
261 7763a61a 2003-11-23 devnull char *cp2, *cp;
262 7763a61a 2003-11-23 devnull VacFS *fs;
263 7763a61a 2003-11-23 devnull VacFile *vff;
264 7763a61a 2003-11-23 devnull int fd;
265 7763a61a 2003-11-23 devnull Dir *dir;
266 7763a61a 2003-11-23 devnull VacDir vd;
267 7763a61a 2003-11-23 devnull
268 7763a61a 2003-11-23 devnull if(getwd(cwd, sizeof(cwd)) == 0)
269 7763a61a 2003-11-23 devnull sysfatal("can't find current directory: %r\n");
270 7763a61a 2003-11-23 devnull
271 7763a61a 2003-11-23 devnull dsink = dirSinkAlloc(z, bsize, bsize);
272 7763a61a 2003-11-23 devnull
273 7763a61a 2003-11-23 devnull fs = nil;
274 7763a61a 2003-11-23 devnull if(dfile != nil) {
275 7763a61a 2003-11-23 devnull fs = vfsOpen(z, dfile, 1, 10000);
276 7763a61a 2003-11-23 devnull if(fs == nil)
277 7763a61a 2003-11-23 devnull fprint(2, "could not open diff: %s: %s\n", dfile, vtGetError());
278 7763a61a 2003-11-23 devnull }
279 7763a61a 2003-11-23 devnull
280 7763a61a 2003-11-23 devnull
281 7763a61a 2003-11-23 devnull if(oname != nil) {
282 7763a61a 2003-11-23 devnull fd = create(oname, OWRITE, 0666);
283 7763a61a 2003-11-23 devnull if(fd < 0)
284 7763a61a 2003-11-23 devnull sysfatal("could not create file: %s: %r", oname);
285 7763a61a 2003-11-23 devnull } else
286 7763a61a 2003-11-23 devnull fd = 1;
287 7763a61a 2003-11-23 devnull
288 7763a61a 2003-11-23 devnull dir = dirfstat(fd);
289 7763a61a 2003-11-23 devnull if(dir == nil)
290 7763a61a 2003-11-23 devnull sysfatal("dirfstat failed: %r");
291 7763a61a 2003-11-23 devnull
292 7763a61a 2003-11-23 devnull for(; *argv; argv++) {
293 7763a61a 2003-11-23 devnull cp2 = *argv;
294 7763a61a 2003-11-23 devnull cd = 0;
295 7763a61a 2003-11-23 devnull for (cp = *argv; *cp; cp++)
296 7763a61a 2003-11-23 devnull if (*cp == '/')
297 7763a61a 2003-11-23 devnull cp2 = cp;
298 7763a61a 2003-11-23 devnull if (cp2 != *argv) {
299 7763a61a 2003-11-23 devnull *cp2 = '\0';
300 7763a61a 2003-11-23 devnull chdir(*argv);
301 7763a61a 2003-11-23 devnull *cp2 = '/';
302 7763a61a 2003-11-23 devnull cp2++;
303 7763a61a 2003-11-23 devnull cd = 1;
304 7763a61a 2003-11-23 devnull }
305 7763a61a 2003-11-23 devnull vff = nil;
306 7763a61a 2003-11-23 devnull if(fs)
307 7763a61a 2003-11-23 devnull vff = vfOpen(fs, cp2);
308 7763a61a 2003-11-23 devnull vacFile(dsink, argv[0], cp2, vff);
309 7763a61a 2003-11-23 devnull if(vff)
310 7763a61a 2003-11-23 devnull vfDecRef(vff);
311 7763a61a 2003-11-23 devnull if(cd && chdir(cwd) < 0)
312 7763a61a 2003-11-23 devnull sysfatal("can't cd back to %s: %r\n", cwd);
313 7763a61a 2003-11-23 devnull }
314 7763a61a 2003-11-23 devnull
315 7763a61a 2003-11-23 devnull if(isi) {
316 7763a61a 2003-11-23 devnull vff = nil;
317 7763a61a 2003-11-23 devnull if(fs)
318 7763a61a 2003-11-23 devnull vff = vfOpen(fs, isi);
319 7763a61a 2003-11-23 devnull vacStdin(dsink, isi, vff);
320 7763a61a 2003-11-23 devnull if(vff)
321 7763a61a 2003-11-23 devnull vfDecRef(vff);
322 7763a61a 2003-11-23 devnull }
323 7763a61a 2003-11-23 devnull
324 7763a61a 2003-11-23 devnull dirSinkClose(dsink);
325 7763a61a 2003-11-23 devnull
326 7763a61a 2003-11-23 devnull /* build meta information for the root */
327 7763a61a 2003-11-23 devnull ms = metaSinkAlloc(z, bsize, bsize);
328 7763a61a 2003-11-23 devnull /* fake into a directory */
329 7763a61a 2003-11-23 devnull dir->mode |= (dir->mode&0444)>>2;
330 7763a61a 2003-11-23 devnull dir->qid.type |= QTDIR;
331 7763a61a 2003-11-23 devnull dir->mode |= DMDIR;
332 7763a61a 2003-11-23 devnull plan9ToVacDir(&vd, dir, 0, fileid++);
333 7763a61a 2003-11-23 devnull if(strcmp(vd.elem, "/") == 0){
334 7763a61a 2003-11-23 devnull vtMemFree(vd.elem);
335 7763a61a 2003-11-23 devnull vd.elem = vtStrDup("root");
336 7763a61a 2003-11-23 devnull }
337 7763a61a 2003-11-23 devnull metaSinkWriteDir(ms, &vd);
338 7763a61a 2003-11-23 devnull vdCleanup(&vd);
339 7763a61a 2003-11-23 devnull metaSinkClose(ms);
340 7763a61a 2003-11-23 devnull
341 7763a61a 2003-11-23 devnull ds = dirSinkAlloc(z, bsize, bsize);
342 7763a61a 2003-11-23 devnull dirSinkWriteSink(ds, dsink->sink);
343 7763a61a 2003-11-23 devnull dirSinkWriteSink(ds, dsink->msink->sink);
344 7763a61a 2003-11-23 devnull dirSinkWriteSink(ds, ms->sink);
345 7763a61a 2003-11-23 devnull dirSinkClose(ds);
346 7763a61a 2003-11-23 devnull
347 7763a61a 2003-11-23 devnull memset(&root, 0, sizeof(root));
348 7763a61a 2003-11-23 devnull root.version = VtRootVersion;
349 7763a61a 2003-11-23 devnull strncpy(root.name, dir->name, sizeof(root.name));
350 7763a61a 2003-11-23 devnull root.name[sizeof(root.name)-1] = 0;
351 7763a61a 2003-11-23 devnull free(dir);
352 7763a61a 2003-11-23 devnull sprint(root.type, "vac");
353 7763a61a 2003-11-23 devnull memmove(root.score, ds->sink->dir.score, VtScoreSize);
354 7763a61a 2003-11-23 devnull root.blockSize = maxbsize;
355 7763a61a 2003-11-23 devnull if(fs != nil)
356 7763a61a 2003-11-23 devnull vfsGetScore(fs, root.prev);
357 7763a61a 2003-11-23 devnull
358 7763a61a 2003-11-23 devnull metaSinkFree(ms);
359 7763a61a 2003-11-23 devnull dirSinkFree(ds);
360 7763a61a 2003-11-23 devnull dirSinkFree(dsink);
361 7763a61a 2003-11-23 devnull if(fs != nil)
362 7763a61a 2003-11-23 devnull vfsClose(fs);
363 7763a61a 2003-11-23 devnull
364 7763a61a 2003-11-23 devnull vtRootPack(&root, buf);
365 7763a61a 2003-11-23 devnull if(!vacWrite(z, score, VtRootType, buf, VtRootSize))
366 7763a61a 2003-11-23 devnull vtFatal("vacWrite failed: %s", vtGetError());
367 7763a61a 2003-11-23 devnull
368 7763a61a 2003-11-23 devnull fprint(fd, "vac:");
369 7763a61a 2003-11-23 devnull for(i=0; i<VtScoreSize; i++)
370 7763a61a 2003-11-23 devnull fprint(fd, "%.2x", score[i]);
371 7763a61a 2003-11-23 devnull fprint(fd, "\n");
372 7763a61a 2003-11-23 devnull
373 7763a61a 2003-11-23 devnull /* avoid remove at cleanup */
374 7763a61a 2003-11-23 devnull oname = nil;
375 7763a61a 2003-11-23 devnull return 1;
376 7763a61a 2003-11-23 devnull }
377 7763a61a 2003-11-23 devnull
378 7763a61a 2003-11-23 devnull static int
379 7763a61a 2003-11-23 devnull isExcluded(char *name)
380 7763a61a 2003-11-23 devnull {
381 7763a61a 2003-11-23 devnull int bot, top, i, x;
382 7763a61a 2003-11-23 devnull
383 7763a61a 2003-11-23 devnull bot = 0;
384 7763a61a 2003-11-23 devnull top = nexclude;
385 7763a61a 2003-11-23 devnull while(bot < top) {
386 7763a61a 2003-11-23 devnull i = (bot+top)>>1;
387 7763a61a 2003-11-23 devnull x = strcmp(exclude[i], name);
388 7763a61a 2003-11-23 devnull if(x == 0)
389 7763a61a 2003-11-23 devnull return 1;
390 7763a61a 2003-11-23 devnull if(x < 0)
391 7763a61a 2003-11-23 devnull bot = i + 1;
392 7763a61a 2003-11-23 devnull else /* x > 0 */
393 7763a61a 2003-11-23 devnull top = i;
394 7763a61a 2003-11-23 devnull }
395 7763a61a 2003-11-23 devnull return 0;
396 7763a61a 2003-11-23 devnull }
397 7763a61a 2003-11-23 devnull
398 7763a61a 2003-11-23 devnull static void
399 7763a61a 2003-11-23 devnull vacFile(DirSink *dsink, char *lname, char *sname, VacFile *vf)
400 7763a61a 2003-11-23 devnull {
401 7763a61a 2003-11-23 devnull int fd;
402 7763a61a 2003-11-23 devnull Dir *dir;
403 7763a61a 2003-11-23 devnull VacDir vd;
404 7763a61a 2003-11-23 devnull ulong entry;
405 7763a61a 2003-11-23 devnull
406 7763a61a 2003-11-23 devnull if(isExcluded(lname)) {
407 7763a61a 2003-11-23 devnull warn("excluding: %s", lname);
408 7763a61a 2003-11-23 devnull return;
409 7763a61a 2003-11-23 devnull }
410 7763a61a 2003-11-23 devnull
411 7763a61a 2003-11-23 devnull if(merge && vacMerge(dsink, lname, sname))
412 7763a61a 2003-11-23 devnull return;
413 7763a61a 2003-11-23 devnull
414 7763a61a 2003-11-23 devnull fd = open(sname, OREAD);
415 7763a61a 2003-11-23 devnull if(fd < 0) {
416 7763a61a 2003-11-23 devnull warn("could not open file: %s: %s", lname, vtOSError());
417 7763a61a 2003-11-23 devnull return;
418 7763a61a 2003-11-23 devnull }
419 7763a61a 2003-11-23 devnull
420 7763a61a 2003-11-23 devnull if(verbose)
421 7763a61a 2003-11-23 devnull fprint(2, "%s\n", lname);
422 7763a61a 2003-11-23 devnull
423 7763a61a 2003-11-23 devnull dir = dirfstat(fd);
424 7763a61a 2003-11-23 devnull if(dir == nil) {
425 7763a61a 2003-11-23 devnull warn("can't stat %s: %r", lname);
426 7763a61a 2003-11-23 devnull close(fd);
427 7763a61a 2003-11-23 devnull return;
428 7763a61a 2003-11-23 devnull }
429 7763a61a 2003-11-23 devnull
430 7763a61a 2003-11-23 devnull entry = dsink->nentry;
431 7763a61a 2003-11-23 devnull
432 7763a61a 2003-11-23 devnull if(dir->mode & DMDIR)
433 7763a61a 2003-11-23 devnull vacDir(dsink, fd, lname, sname, vf);
434 7763a61a 2003-11-23 devnull else
435 7763a61a 2003-11-23 devnull vacData(dsink, fd, lname, vf, dir);
436 7763a61a 2003-11-23 devnull
437 7763a61a 2003-11-23 devnull plan9ToVacDir(&vd, dir, entry, fileid++);
438 7763a61a 2003-11-23 devnull metaSinkWriteDir(dsink->msink, &vd);
439 7763a61a 2003-11-23 devnull vdCleanup(&vd);
440 7763a61a 2003-11-23 devnull
441 7763a61a 2003-11-23 devnull free(dir);
442 7763a61a 2003-11-23 devnull close(fd);
443 7763a61a 2003-11-23 devnull }
444 7763a61a 2003-11-23 devnull
445 7763a61a 2003-11-23 devnull static void
446 7763a61a 2003-11-23 devnull vacStdin(DirSink *dsink, char *name, VacFile *vf)
447 7763a61a 2003-11-23 devnull {
448 7763a61a 2003-11-23 devnull Dir *dir;
449 7763a61a 2003-11-23 devnull VacDir vd;
450 7763a61a 2003-11-23 devnull ulong entry;
451 7763a61a 2003-11-23 devnull
452 7763a61a 2003-11-23 devnull if(verbose)
453 7763a61a 2003-11-23 devnull fprint(2, "%s\n", "<stdio>");
454 7763a61a 2003-11-23 devnull
455 7763a61a 2003-11-23 devnull dir = dirfstat(0);
456 7763a61a 2003-11-23 devnull if(dir == nil) {
457 7763a61a 2003-11-23 devnull warn("can't stat <stdio>: %r");
458 7763a61a 2003-11-23 devnull return;
459 7763a61a 2003-11-23 devnull }
460 7763a61a 2003-11-23 devnull
461 7763a61a 2003-11-23 devnull entry = dsink->nentry;
462 7763a61a 2003-11-23 devnull
463 7763a61a 2003-11-23 devnull vacData(dsink, 0, "<stdin>", vf, dir);
464 7763a61a 2003-11-23 devnull
465 7763a61a 2003-11-23 devnull plan9ToVacDir(&vd, dir, entry, fileid++);
466 7763a61a 2003-11-23 devnull vd.elem = vtStrDup(name);
467 7763a61a 2003-11-23 devnull metaSinkWriteDir(dsink->msink, &vd);
468 7763a61a 2003-11-23 devnull vdCleanup(&vd);
469 7763a61a 2003-11-23 devnull
470 7763a61a 2003-11-23 devnull free(dir);
471 7763a61a 2003-11-23 devnull }
472 7763a61a 2003-11-23 devnull
473 7763a61a 2003-11-23 devnull static ulong
474 7763a61a 2003-11-23 devnull vacDataSkip(Sink *sink, VacFile *vf, int fd, ulong blocks, uchar *buf, char *lname)
475 7763a61a 2003-11-23 devnull {
476 7763a61a 2003-11-23 devnull int n;
477 7763a61a 2003-11-23 devnull ulong i;
478 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
479 7763a61a 2003-11-23 devnull
480 7763a61a 2003-11-23 devnull /* skip blocks for append only files */
481 7763a61a 2003-11-23 devnull if(seek(fd, (blocks-1)*bsize, 0) != (blocks-1)*bsize) {
482 7763a61a 2003-11-23 devnull warn("error seeking: %s", lname);
483 7763a61a 2003-11-23 devnull goto Err;
484 7763a61a 2003-11-23 devnull }
485 7763a61a 2003-11-23 devnull n = readBlock(fd, buf, bsize);
486 7763a61a 2003-11-23 devnull if(n < bsize) {
487 7763a61a 2003-11-23 devnull warn("error checking append only file: %s", lname);
488 7763a61a 2003-11-23 devnull goto Err;
489 7763a61a 2003-11-23 devnull }
490 7763a61a 2003-11-23 devnull if(!vfGetBlockScore(vf, blocks-1, score) || !vtSha1Check(score, buf, n)) {
491 7763a61a 2003-11-23 devnull warn("last block of append file did not match: %s", lname);
492 7763a61a 2003-11-23 devnull goto Err;
493 7763a61a 2003-11-23 devnull }
494 7763a61a 2003-11-23 devnull
495 7763a61a 2003-11-23 devnull for(i=0; i<blocks; i++) {
496 7763a61a 2003-11-23 devnull if(!vfGetBlockScore(vf, i, score)) {
497 7763a61a 2003-11-23 devnull warn("could not get score: %s: %lud", lname, i);
498 7763a61a 2003-11-23 devnull seek(fd, i*bsize, 0);
499 7763a61a 2003-11-23 devnull return i;
500 7763a61a 2003-11-23 devnull }
501 7763a61a 2003-11-23 devnull stats.skip++;
502 7763a61a 2003-11-23 devnull sinkWriteScore(sink, score, bsize);
503 7763a61a 2003-11-23 devnull }
504 7763a61a 2003-11-23 devnull
505 7763a61a 2003-11-23 devnull return i;
506 7763a61a 2003-11-23 devnull Err:
507 7763a61a 2003-11-23 devnull seek(fd, 0, 0);
508 7763a61a 2003-11-23 devnull return 0;
509 7763a61a 2003-11-23 devnull }
510 7763a61a 2003-11-23 devnull
511 7763a61a 2003-11-23 devnull static void
512 7763a61a 2003-11-23 devnull vacData(DirSink *dsink, int fd, char *lname, VacFile *vf, Dir *dir)
513 7763a61a 2003-11-23 devnull {
514 7763a61a 2003-11-23 devnull uchar *buf;
515 7763a61a 2003-11-23 devnull Sink *sink;
516 7763a61a 2003-11-23 devnull int n;
517 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
518 7763a61a 2003-11-23 devnull ulong block, same;
519 7763a61a 2003-11-23 devnull VacDir vd;
520 7763a61a 2003-11-23 devnull ulong vfblocks;
521 7763a61a 2003-11-23 devnull
522 7763a61a 2003-11-23 devnull vfblocks = 0;
523 7763a61a 2003-11-23 devnull if(vf != nil && qdiff) {
524 7763a61a 2003-11-23 devnull vfGetDir(vf, &vd);
525 7763a61a 2003-11-23 devnull if(vd.mtime == dir->mtime)
526 7763a61a 2003-11-23 devnull if(vd.size == dir->length)
527 7763a61a 2003-11-23 devnull if(!vd.plan9 || /* vd.p9path == dir->qid.path && */ vd.p9version == dir->qid.vers)
528 7763a61a 2003-11-23 devnull if(dirSinkWriteFile(dsink, vf)) {
529 7763a61a 2003-11-23 devnull stats.sfile++;
530 7763a61a 2003-11-23 devnull vdCleanup(&vd);
531 7763a61a 2003-11-23 devnull return;
532 7763a61a 2003-11-23 devnull }
533 7763a61a 2003-11-23 devnull
534 7763a61a 2003-11-23 devnull /* look for an append only file */
535 7763a61a 2003-11-23 devnull if((dir->mode&DMAPPEND) != 0)
536 7763a61a 2003-11-23 devnull if(vd.size < dir->length)
537 7763a61a 2003-11-23 devnull if(vd.plan9)
538 7763a61a 2003-11-23 devnull if(vd.p9path == dir->qid.path)
539 7763a61a 2003-11-23 devnull vfblocks = vd.size/bsize;
540 7763a61a 2003-11-23 devnull
541 7763a61a 2003-11-23 devnull vdCleanup(&vd);
542 7763a61a 2003-11-23 devnull }
543 7763a61a 2003-11-23 devnull stats.file++;
544 7763a61a 2003-11-23 devnull
545 7763a61a 2003-11-23 devnull buf = vtMemAlloc(bsize);
546 7763a61a 2003-11-23 devnull sink = sinkAlloc(dsink->sink->z, bsize, bsize);
547 7763a61a 2003-11-23 devnull block = 0;
548 7763a61a 2003-11-23 devnull same = stats.sdata+stats.skip;
549 7763a61a 2003-11-23 devnull
550 7763a61a 2003-11-23 devnull if(vfblocks > 1)
551 7763a61a 2003-11-23 devnull block += vacDataSkip(sink, vf, fd, vfblocks, buf, lname);
552 7763a61a 2003-11-23 devnull
553 7763a61a 2003-11-23 devnull if(0) fprint(2, "vacData: %s: %ld\n", lname, block);
554 7763a61a 2003-11-23 devnull for(;;) {
555 7763a61a 2003-11-23 devnull n = readBlock(fd, buf, bsize);
556 7763a61a 2003-11-23 devnull if(0 && n < 0)
557 7763a61a 2003-11-23 devnull warn("file truncated due to read error: %s: %s", lname, vtOSError());
558 7763a61a 2003-11-23 devnull if(n <= 0)
559 7763a61a 2003-11-23 devnull break;
560 7763a61a 2003-11-23 devnull if(vf != nil && vfGetBlockScore(vf, block, score) && vtSha1Check(score, buf, n)) {
561 7763a61a 2003-11-23 devnull stats.sdata++;
562 7763a61a 2003-11-23 devnull sinkWriteScore(sink, score, n);
563 7763a61a 2003-11-23 devnull } else
564 7763a61a 2003-11-23 devnull sinkWrite(sink, buf, n);
565 7763a61a 2003-11-23 devnull block++;
566 7763a61a 2003-11-23 devnull }
567 7763a61a 2003-11-23 devnull same = stats.sdata+stats.skip - same;
568 7763a61a 2003-11-23 devnull
569 7763a61a 2003-11-23 devnull if(same && (dir->mode&DMAPPEND) != 0)
570 7763a61a 2003-11-23 devnull if(0)fprint(2, "%s: total %lud same %lud:%lud diff %lud\n",
571 7763a61a 2003-11-23 devnull lname, block, same, vfblocks, block-same);
572 7763a61a 2003-11-23 devnull
573 7763a61a 2003-11-23 devnull sinkClose(sink);
574 7763a61a 2003-11-23 devnull dirSinkWriteSink(dsink, sink);
575 7763a61a 2003-11-23 devnull sinkFree(sink);
576 7763a61a 2003-11-23 devnull free(buf);
577 7763a61a 2003-11-23 devnull }
578 7763a61a 2003-11-23 devnull
579 7763a61a 2003-11-23 devnull
580 7763a61a 2003-11-23 devnull static void
581 7763a61a 2003-11-23 devnull vacDir(DirSink *dsink, int fd, char *lname, char *sname, VacFile *vf)
582 7763a61a 2003-11-23 devnull {
583 7763a61a 2003-11-23 devnull Dir *dirs;
584 7763a61a 2003-11-23 devnull char *ln, *sn;
585 7763a61a 2003-11-23 devnull int i, nd;
586 7763a61a 2003-11-23 devnull DirSink *ds;
587 7763a61a 2003-11-23 devnull VacFile *vvf;
588 7763a61a 2003-11-23 devnull char *name;
589 7763a61a 2003-11-23 devnull
590 7763a61a 2003-11-23 devnull ds = dirSinkAlloc(dsink->sink->z, bsize, bsize);
591 7763a61a 2003-11-23 devnull while((nd = dirread(fd, &dirs)) > 0){
592 7763a61a 2003-11-23 devnull for(i = 0; i < nd; i++){
593 7763a61a 2003-11-23 devnull name = dirs[i].name;
594 7763a61a 2003-11-23 devnull /* check for bad file names */
595 7763a61a 2003-11-23 devnull if(name[0] == 0 || strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
596 7763a61a 2003-11-23 devnull continue;
597 7763a61a 2003-11-23 devnull ln = vtMemAlloc(strlen(lname) + strlen(name) + 2);
598 7763a61a 2003-11-23 devnull sn = vtMemAlloc(strlen(sname) + strlen(name) + 2);
599 7763a61a 2003-11-23 devnull sprint(ln, "%s/%s", lname, name);
600 7763a61a 2003-11-23 devnull sprint(sn, "%s/%s", sname, name);
601 7763a61a 2003-11-23 devnull if(vf != nil)
602 7763a61a 2003-11-23 devnull vvf = vfWalk(vf, name);
603 7763a61a 2003-11-23 devnull else
604 7763a61a 2003-11-23 devnull vvf = nil;
605 7763a61a 2003-11-23 devnull vacFile(ds, ln, sn, vvf);
606 7763a61a 2003-11-23 devnull if(vvf != nil)
607 7763a61a 2003-11-23 devnull vfDecRef(vvf);
608 7763a61a 2003-11-23 devnull vtMemFree(ln);
609 7763a61a 2003-11-23 devnull vtMemFree(sn);
610 7763a61a 2003-11-23 devnull }
611 7763a61a 2003-11-23 devnull free(dirs);
612 7763a61a 2003-11-23 devnull }
613 7763a61a 2003-11-23 devnull dirSinkClose(ds);
614 7763a61a 2003-11-23 devnull dirSinkWriteSink(dsink, ds->sink);
615 7763a61a 2003-11-23 devnull dirSinkWriteSink(dsink, ds->msink->sink);
616 7763a61a 2003-11-23 devnull dirSinkFree(ds);
617 7763a61a 2003-11-23 devnull }
618 7763a61a 2003-11-23 devnull
619 7763a61a 2003-11-23 devnull static int
620 7763a61a 2003-11-23 devnull vacMergeFile(DirSink *dsink, VacFile *vf, VacDir *dir, uvlong offset, uvlong *max)
621 7763a61a 2003-11-23 devnull {
622 7763a61a 2003-11-23 devnull uchar buf[VtEntrySize];
623 7763a61a 2003-11-23 devnull VtEntry dd, md;
624 7763a61a 2003-11-23 devnull int e;
625 7763a61a 2003-11-23 devnull
626 7763a61a 2003-11-23 devnull if(vfRead(vf, buf, VtEntrySize, (uvlong)dir->entry*VtEntrySize) != VtEntrySize) {
627 7763a61a 2003-11-23 devnull warn("could not read venti dir entry: %s\n", dir->elem);
628 7763a61a 2003-11-23 devnull return 0;
629 7763a61a 2003-11-23 devnull }
630 7763a61a 2003-11-23 devnull vtEntryUnpack(&dd, buf, 0);
631 7763a61a 2003-11-23 devnull
632 7763a61a 2003-11-23 devnull if(dir->mode & ModeDir) {
633 7763a61a 2003-11-23 devnull e = dir->mentry;
634 7763a61a 2003-11-23 devnull if(e == 0)
635 7763a61a 2003-11-23 devnull e = dir->entry + 1;
636 7763a61a 2003-11-23 devnull
637 7763a61a 2003-11-23 devnull if(vfRead(vf, buf, VtEntrySize, e*VtEntrySize) != VtEntrySize) {
638 7763a61a 2003-11-23 devnull warn("could not read venti dir entry: %s\n", dir->elem);
639 7763a61a 2003-11-23 devnull return 0;
640 7763a61a 2003-11-23 devnull }
641 7763a61a 2003-11-23 devnull vtEntryUnpack(&md, buf, 0);
642 7763a61a 2003-11-23 devnull }
643 7763a61a 2003-11-23 devnull
644 7763a61a 2003-11-23 devnull /* max might incorrect in some old dumps */
645 7763a61a 2003-11-23 devnull if(dir->qid >= *max) {
646 7763a61a 2003-11-23 devnull warn("qid out of range: %s", dir->elem);
647 7763a61a 2003-11-23 devnull *max = dir->qid;
648 7763a61a 2003-11-23 devnull }
649 7763a61a 2003-11-23 devnull
650 7763a61a 2003-11-23 devnull dir->qid += offset;
651 7763a61a 2003-11-23 devnull dir->entry = dsink->nentry;
652 7763a61a 2003-11-23 devnull
653 7763a61a 2003-11-23 devnull if(dir->qidSpace) {
654 7763a61a 2003-11-23 devnull dir->qidOffset += offset;
655 7763a61a 2003-11-23 devnull } else {
656 7763a61a 2003-11-23 devnull dir->qidSpace = 1;
657 7763a61a 2003-11-23 devnull dir->qidOffset = offset;
658 7763a61a 2003-11-23 devnull dir->qidMax = *max;
659 7763a61a 2003-11-23 devnull }
660 7763a61a 2003-11-23 devnull
661 7763a61a 2003-11-23 devnull dirSinkWrite(dsink, &dd);
662 7763a61a 2003-11-23 devnull if(dir->mode & ModeDir)
663 7763a61a 2003-11-23 devnull dirSinkWrite(dsink, &md);
664 7763a61a 2003-11-23 devnull metaSinkWriteDir(dsink->msink, dir);
665 7763a61a 2003-11-23 devnull
666 7763a61a 2003-11-23 devnull return 1;
667 7763a61a 2003-11-23 devnull }
668 7763a61a 2003-11-23 devnull
669 7763a61a 2003-11-23 devnull static int
670 7763a61a 2003-11-23 devnull vacMerge(DirSink *dsink, char *lname, char *sname)
671 7763a61a 2003-11-23 devnull {
672 7763a61a 2003-11-23 devnull char *p;
673 7763a61a 2003-11-23 devnull VacFS *fs;
674 7763a61a 2003-11-23 devnull VacFile *vf;
675 7763a61a 2003-11-23 devnull VacDirEnum *d;
676 7763a61a 2003-11-23 devnull VacDir dir;
677 7763a61a 2003-11-23 devnull uvlong max;
678 7763a61a 2003-11-23 devnull
679 7763a61a 2003-11-23 devnull p = strrchr(sname, '.');
680 7763a61a 2003-11-23 devnull if(p == 0 || strcmp(p, ".vac"))
681 7763a61a 2003-11-23 devnull return 0;
682 7763a61a 2003-11-23 devnull
683 7763a61a 2003-11-23 devnull d = nil;
684 7763a61a 2003-11-23 devnull fs = vfsOpen(dsink->sink->z, sname, 1, 100);
685 7763a61a 2003-11-23 devnull if(fs == nil)
686 7763a61a 2003-11-23 devnull return 0;
687 7763a61a 2003-11-23 devnull
688 7763a61a 2003-11-23 devnull vf = vfOpen(fs, "/");
689 7763a61a 2003-11-23 devnull if(vf == nil)
690 7763a61a 2003-11-23 devnull goto Done;
691 7763a61a 2003-11-23 devnull max = vfGetId(vf);
692 7763a61a 2003-11-23 devnull d = vdeOpen(fs, "/");
693 7763a61a 2003-11-23 devnull if(d == nil)
694 7763a61a 2003-11-23 devnull goto Done;
695 7763a61a 2003-11-23 devnull
696 7763a61a 2003-11-23 devnull if(verbose)
697 7763a61a 2003-11-23 devnull fprint(2, "merging: %s\n", lname);
698 7763a61a 2003-11-23 devnull
699 7763a61a 2003-11-23 devnull if(maxbsize < vfsGetBlockSize(fs))
700 7763a61a 2003-11-23 devnull maxbsize = vfsGetBlockSize(fs);
701 7763a61a 2003-11-23 devnull
702 7763a61a 2003-11-23 devnull for(;;) {
703 7763a61a 2003-11-23 devnull if(vdeRead(d, &dir, 1) < 1)
704 7763a61a 2003-11-23 devnull break;
705 7763a61a 2003-11-23 devnull vacMergeFile(dsink, vf, &dir, fileid, &max);
706 7763a61a 2003-11-23 devnull vdCleanup(&dir);
707 7763a61a 2003-11-23 devnull }
708 7763a61a 2003-11-23 devnull fileid += max;
709 7763a61a 2003-11-23 devnull
710 7763a61a 2003-11-23 devnull Done:
711 7763a61a 2003-11-23 devnull if(d != nil)
712 7763a61a 2003-11-23 devnull vdeFree(d);
713 7763a61a 2003-11-23 devnull if(vf != nil)
714 7763a61a 2003-11-23 devnull vfDecRef(vf);
715 7763a61a 2003-11-23 devnull vfsClose(fs);
716 7763a61a 2003-11-23 devnull return 1;
717 7763a61a 2003-11-23 devnull }
718 7763a61a 2003-11-23 devnull
719 7763a61a 2003-11-23 devnull Sink *
720 7763a61a 2003-11-23 devnull sinkAlloc(VtSession *z, int psize, int dsize)
721 7763a61a 2003-11-23 devnull {
722 7763a61a 2003-11-23 devnull Sink *k;
723 7763a61a 2003-11-23 devnull int i;
724 7763a61a 2003-11-23 devnull
725 7763a61a 2003-11-23 devnull if(psize < 512 || psize > VtMaxLumpSize)
726 7763a61a 2003-11-23 devnull vtFatal("sinkAlloc: bad psize");
727 7763a61a 2003-11-23 devnull if(dsize < 512 || dsize > VtMaxLumpSize)
728 7763a61a 2003-11-23 devnull vtFatal("sinkAlloc: bad psize");
729 7763a61a 2003-11-23 devnull
730 7763a61a 2003-11-23 devnull psize = VtScoreSize*(psize/VtScoreSize);
731 7763a61a 2003-11-23 devnull
732 7763a61a 2003-11-23 devnull k = vtMemAllocZ(sizeof(Sink));
733 7763a61a 2003-11-23 devnull k->z = z;
734 7763a61a 2003-11-23 devnull k->dir.flags = VtEntryActive;
735 7763a61a 2003-11-23 devnull k->dir.psize = psize;
736 7763a61a 2003-11-23 devnull k->dir.dsize = dsize;
737 7763a61a 2003-11-23 devnull k->buf = vtMemAllocZ(VtPointerDepth*k->dir.psize + VtScoreSize);
738 7763a61a 2003-11-23 devnull for(i=0; i<=VtPointerDepth; i++)
739 7763a61a 2003-11-23 devnull k->pbuf[i] = k->buf + i*k->dir.psize;
740 7763a61a 2003-11-23 devnull return k;
741 7763a61a 2003-11-23 devnull }
742 7763a61a 2003-11-23 devnull
743 7763a61a 2003-11-23 devnull void
744 7763a61a 2003-11-23 devnull sinkWriteScore(Sink *k, uchar score[VtScoreSize], int n)
745 7763a61a 2003-11-23 devnull {
746 7763a61a 2003-11-23 devnull int i;
747 7763a61a 2003-11-23 devnull uchar *p;
748 7763a61a 2003-11-23 devnull VtEntry *d;
749 7763a61a 2003-11-23 devnull
750 7763a61a 2003-11-23 devnull memmove(k->pbuf[0], score, VtScoreSize);
751 7763a61a 2003-11-23 devnull
752 7763a61a 2003-11-23 devnull d = &k->dir;
753 7763a61a 2003-11-23 devnull
754 7763a61a 2003-11-23 devnull for(i=0; i<VtPointerDepth; i++) {
755 7763a61a 2003-11-23 devnull k->pbuf[i] += VtScoreSize;
756 7763a61a 2003-11-23 devnull if(k->pbuf[i] < k->buf + d->psize*(i+1))
757 7763a61a 2003-11-23 devnull break;
758 7763a61a 2003-11-23 devnull if(i == VtPointerDepth-1)
759 7763a61a 2003-11-23 devnull vtFatal("file too big");
760 7763a61a 2003-11-23 devnull p = k->buf+i*d->psize;
761 7763a61a 2003-11-23 devnull stats.meta++;
762 7763a61a 2003-11-23 devnull if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, d->psize))
763 7763a61a 2003-11-23 devnull vtFatal("vacWrite failed: %s", vtGetError());
764 7763a61a 2003-11-23 devnull k->pbuf[i] = p;
765 7763a61a 2003-11-23 devnull }
766 7763a61a 2003-11-23 devnull
767 7763a61a 2003-11-23 devnull /* round size up to multiple of dsize */
768 7763a61a 2003-11-23 devnull d->size = d->dsize * ((d->size + d->dsize-1)/d->dsize);
769 7763a61a 2003-11-23 devnull
770 7763a61a 2003-11-23 devnull d->size += n;
771 7763a61a 2003-11-23 devnull }
772 7763a61a 2003-11-23 devnull
773 7763a61a 2003-11-23 devnull void
774 7763a61a 2003-11-23 devnull sinkWrite(Sink *k, uchar *p, int n)
775 7763a61a 2003-11-23 devnull {
776 7763a61a 2003-11-23 devnull int type;
777 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
778 7763a61a 2003-11-23 devnull
779 7763a61a 2003-11-23 devnull if(n > k->dir.dsize)
780 7763a61a 2003-11-23 devnull vtFatal("sinkWrite: size too big");
781 7763a61a 2003-11-23 devnull
782 7763a61a 2003-11-23 devnull if(k->dir.flags & VtEntryDir) {
783 7763a61a 2003-11-23 devnull type = VtDirType;
784 7763a61a 2003-11-23 devnull stats.meta++;
785 7763a61a 2003-11-23 devnull } else {
786 7763a61a 2003-11-23 devnull type = VtDataType;
787 7763a61a 2003-11-23 devnull stats.data++;
788 7763a61a 2003-11-23 devnull }
789 7763a61a 2003-11-23 devnull if(!vacWrite(k->z, score, type, p, n))
790 7763a61a 2003-11-23 devnull vtFatal("vacWrite failed: %s", vtGetError());
791 7763a61a 2003-11-23 devnull
792 7763a61a 2003-11-23 devnull sinkWriteScore(k, score, n);
793 7763a61a 2003-11-23 devnull }
794 7763a61a 2003-11-23 devnull
795 7763a61a 2003-11-23 devnull static int
796 7763a61a 2003-11-23 devnull sizeToDepth(uvlong s, int psize, int dsize)
797 7763a61a 2003-11-23 devnull {
798 7763a61a 2003-11-23 devnull int np;
799 7763a61a 2003-11-23 devnull int d;
800 7763a61a 2003-11-23 devnull
801 7763a61a 2003-11-23 devnull /* determine pointer depth */
802 7763a61a 2003-11-23 devnull np = psize/VtScoreSize;
803 7763a61a 2003-11-23 devnull s = (s + dsize - 1)/dsize;
804 7763a61a 2003-11-23 devnull for(d = 0; s > 1; d++)
805 7763a61a 2003-11-23 devnull s = (s + np - 1)/np;
806 7763a61a 2003-11-23 devnull return d;
807 7763a61a 2003-11-23 devnull }
808 7763a61a 2003-11-23 devnull
809 7763a61a 2003-11-23 devnull void
810 7763a61a 2003-11-23 devnull sinkClose(Sink *k)
811 7763a61a 2003-11-23 devnull {
812 7763a61a 2003-11-23 devnull int i, n;
813 7763a61a 2003-11-23 devnull uchar *p;
814 7763a61a 2003-11-23 devnull VtEntry *kd;
815 7763a61a 2003-11-23 devnull
816 7763a61a 2003-11-23 devnull kd = &k->dir;
817 7763a61a 2003-11-23 devnull
818 7763a61a 2003-11-23 devnull /* empty */
819 7763a61a 2003-11-23 devnull if(kd->size == 0) {
820 7763a61a 2003-11-23 devnull memmove(kd->score, vtZeroScore, VtScoreSize);
821 7763a61a 2003-11-23 devnull return;
822 7763a61a 2003-11-23 devnull }
823 7763a61a 2003-11-23 devnull
824 7763a61a 2003-11-23 devnull for(n=VtPointerDepth-1; n>0; n--)
825 7763a61a 2003-11-23 devnull if(k->pbuf[n] > k->buf + kd->psize*n)
826 7763a61a 2003-11-23 devnull break;
827 7763a61a 2003-11-23 devnull
828 7763a61a 2003-11-23 devnull kd->depth = sizeToDepth(kd->size, kd->psize, kd->dsize);
829 7763a61a 2003-11-23 devnull
830 7763a61a 2003-11-23 devnull /* skip full part of tree */
831 7763a61a 2003-11-23 devnull for(i=0; i<n && k->pbuf[i] == k->buf + kd->psize*i; i++)
832 7763a61a 2003-11-23 devnull ;
833 7763a61a 2003-11-23 devnull
834 7763a61a 2003-11-23 devnull /* is the tree completely full */
835 7763a61a 2003-11-23 devnull if(i == n && k->pbuf[n] == k->buf + kd->psize*n + VtScoreSize) {
836 7763a61a 2003-11-23 devnull memmove(kd->score, k->pbuf[n] - VtScoreSize, VtScoreSize);
837 7763a61a 2003-11-23 devnull return;
838 7763a61a 2003-11-23 devnull }
839 7763a61a 2003-11-23 devnull n++;
840 7763a61a 2003-11-23 devnull
841 7763a61a 2003-11-23 devnull /* clean up the edge */
842 7763a61a 2003-11-23 devnull for(; i<n; i++) {
843 7763a61a 2003-11-23 devnull p = k->buf+i*kd->psize;
844 7763a61a 2003-11-23 devnull stats.meta++;
845 7763a61a 2003-11-23 devnull if(!vacWrite(k->z, k->pbuf[i+1], VtPointerType0+i, p, k->pbuf[i]-p))
846 7763a61a 2003-11-23 devnull vtFatal("vacWrite failed: %s", vtGetError());
847 7763a61a 2003-11-23 devnull k->pbuf[i+1] += VtScoreSize;
848 7763a61a 2003-11-23 devnull }
849 7763a61a 2003-11-23 devnull memmove(kd->score, k->pbuf[i] - VtScoreSize, VtScoreSize);
850 7763a61a 2003-11-23 devnull }
851 7763a61a 2003-11-23 devnull
852 7763a61a 2003-11-23 devnull void
853 7763a61a 2003-11-23 devnull sinkFree(Sink *k)
854 7763a61a 2003-11-23 devnull {
855 7763a61a 2003-11-23 devnull vtMemFree(k->buf);
856 7763a61a 2003-11-23 devnull vtMemFree(k);
857 7763a61a 2003-11-23 devnull }
858 7763a61a 2003-11-23 devnull
859 7763a61a 2003-11-23 devnull DirSink *
860 7763a61a 2003-11-23 devnull dirSinkAlloc(VtSession *z, int psize, int dsize)
861 7763a61a 2003-11-23 devnull {
862 7763a61a 2003-11-23 devnull DirSink *k;
863 7763a61a 2003-11-23 devnull int ds;
864 7763a61a 2003-11-23 devnull
865 7763a61a 2003-11-23 devnull ds = VtEntrySize*(dsize/VtEntrySize);
866 7763a61a 2003-11-23 devnull
867 7763a61a 2003-11-23 devnull k = vtMemAllocZ(sizeof(DirSink));
868 7763a61a 2003-11-23 devnull k->sink = sinkAlloc(z, psize, ds);
869 7763a61a 2003-11-23 devnull k->sink->dir.flags |= VtEntryDir;
870 7763a61a 2003-11-23 devnull k->msink = metaSinkAlloc(z, psize, dsize);
871 7763a61a 2003-11-23 devnull k->buf = vtMemAlloc(ds);
872 7763a61a 2003-11-23 devnull k->p = k->buf;
873 7763a61a 2003-11-23 devnull k->ep = k->buf + ds;
874 7763a61a 2003-11-23 devnull return k;
875 7763a61a 2003-11-23 devnull }
876 7763a61a 2003-11-23 devnull
877 7763a61a 2003-11-23 devnull void
878 7763a61a 2003-11-23 devnull dirSinkWrite(DirSink *k, VtEntry *dir)
879 7763a61a 2003-11-23 devnull {
880 7763a61a 2003-11-23 devnull if(k->p + VtEntrySize > k->ep) {
881 7763a61a 2003-11-23 devnull sinkWrite(k->sink, k->buf, k->p - k->buf);
882 7763a61a 2003-11-23 devnull k->p = k->buf;
883 7763a61a 2003-11-23 devnull }
884 7763a61a 2003-11-23 devnull vtEntryPack(dir, k->p, 0);
885 7763a61a 2003-11-23 devnull k->nentry++;
886 7763a61a 2003-11-23 devnull k->p += VtEntrySize;
887 7763a61a 2003-11-23 devnull }
888 7763a61a 2003-11-23 devnull
889 7763a61a 2003-11-23 devnull void
890 7763a61a 2003-11-23 devnull dirSinkWriteSink(DirSink *k, Sink *sink)
891 7763a61a 2003-11-23 devnull {
892 7763a61a 2003-11-23 devnull dirSinkWrite(k, &sink->dir);
893 7763a61a 2003-11-23 devnull }
894 7763a61a 2003-11-23 devnull
895 7763a61a 2003-11-23 devnull int
896 7763a61a 2003-11-23 devnull dirSinkWriteFile(DirSink *k, VacFile *vf)
897 7763a61a 2003-11-23 devnull {
898 7763a61a 2003-11-23 devnull VtEntry dir;
899 7763a61a 2003-11-23 devnull
900 7763a61a 2003-11-23 devnull if(!vfGetVtEntry(vf, &dir))
901 7763a61a 2003-11-23 devnull return 0;
902 7763a61a 2003-11-23 devnull dirSinkWrite(k, &dir);
903 7763a61a 2003-11-23 devnull return 1;
904 7763a61a 2003-11-23 devnull }
905 7763a61a 2003-11-23 devnull
906 7763a61a 2003-11-23 devnull void
907 7763a61a 2003-11-23 devnull dirSinkClose(DirSink *k)
908 7763a61a 2003-11-23 devnull {
909 7763a61a 2003-11-23 devnull metaSinkClose(k->msink);
910 7763a61a 2003-11-23 devnull if(k->p != k->buf)
911 7763a61a 2003-11-23 devnull sinkWrite(k->sink, k->buf, k->p - k->buf);
912 7763a61a 2003-11-23 devnull sinkClose(k->sink);
913 7763a61a 2003-11-23 devnull }
914 7763a61a 2003-11-23 devnull
915 7763a61a 2003-11-23 devnull void
916 7763a61a 2003-11-23 devnull dirSinkFree(DirSink *k)
917 7763a61a 2003-11-23 devnull {
918 7763a61a 2003-11-23 devnull sinkFree(k->sink);
919 7763a61a 2003-11-23 devnull metaSinkFree(k->msink);
920 7763a61a 2003-11-23 devnull vtMemFree(k->buf);
921 7763a61a 2003-11-23 devnull vtMemFree(k);
922 7763a61a 2003-11-23 devnull }
923 7763a61a 2003-11-23 devnull
924 7763a61a 2003-11-23 devnull MetaSink *
925 7763a61a 2003-11-23 devnull metaSinkAlloc(VtSession *z, int psize, int dsize)
926 7763a61a 2003-11-23 devnull {
927 7763a61a 2003-11-23 devnull MetaSink *k;
928 7763a61a 2003-11-23 devnull
929 7763a61a 2003-11-23 devnull k = vtMemAllocZ(sizeof(MetaSink));
930 7763a61a 2003-11-23 devnull k->sink = sinkAlloc(z, psize, dsize);
931 7763a61a 2003-11-23 devnull k->buf = vtMemAlloc(dsize);
932 7763a61a 2003-11-23 devnull k->maxindex = dsize/100; /* 100 byte entries seems reasonable */
933 7763a61a 2003-11-23 devnull if(k->maxindex < 1)
934 7763a61a 2003-11-23 devnull k->maxindex = 1;
935 7763a61a 2003-11-23 devnull k->rp = k->p = k->buf + MetaHeaderSize + k->maxindex*MetaIndexSize;
936 7763a61a 2003-11-23 devnull k->ep = k->buf + dsize;
937 7763a61a 2003-11-23 devnull return k;
938 7763a61a 2003-11-23 devnull }
939 7763a61a 2003-11-23 devnull
940 7763a61a 2003-11-23 devnull /* hack to get base to compare routine - not reentrant */
941 7763a61a 2003-11-23 devnull uchar *blockBase;
942 7763a61a 2003-11-23 devnull
943 7763a61a 2003-11-23 devnull int
944 7763a61a 2003-11-23 devnull dirCmp(void *p0, void *p1)
945 7763a61a 2003-11-23 devnull {
946 7763a61a 2003-11-23 devnull uchar *q0, *q1;
947 7763a61a 2003-11-23 devnull int n0, n1, r;
948 7763a61a 2003-11-23 devnull
949 7763a61a 2003-11-23 devnull /* name is first element of entry */
950 7763a61a 2003-11-23 devnull q0 = p0;
951 7763a61a 2003-11-23 devnull q0 = blockBase + (q0[0]<<8) + q0[1];
952 7763a61a 2003-11-23 devnull n0 = (q0[6]<<8) + q0[7];
953 7763a61a 2003-11-23 devnull q0 += 8;
954 7763a61a 2003-11-23 devnull
955 7763a61a 2003-11-23 devnull q1 = p1;
956 7763a61a 2003-11-23 devnull q1 = blockBase + (q1[0]<<8) + q1[1];
957 7763a61a 2003-11-23 devnull n1 = (q1[6]<<8) + q1[7];
958 7763a61a 2003-11-23 devnull q1 += 8;
959 7763a61a 2003-11-23 devnull
960 7763a61a 2003-11-23 devnull if(n0 == n1)
961 7763a61a 2003-11-23 devnull return memcmp(q0, q1, n0);
962 7763a61a 2003-11-23 devnull else if (n0 < n1) {
963 7763a61a 2003-11-23 devnull r = memcmp(q0, q1, n0);
964 7763a61a 2003-11-23 devnull return (r==0)?1:r;
965 7763a61a 2003-11-23 devnull } else {
966 7763a61a 2003-11-23 devnull r = memcmp(q0, q1, n1);
967 7763a61a 2003-11-23 devnull return (r==0)?-1:r;
968 7763a61a 2003-11-23 devnull }
969 7763a61a 2003-11-23 devnull }
970 7763a61a 2003-11-23 devnull
971 7763a61a 2003-11-23 devnull void
972 7763a61a 2003-11-23 devnull metaSinkFlush(MetaSink *k)
973 7763a61a 2003-11-23 devnull {
974 7763a61a 2003-11-23 devnull uchar *p;
975 7763a61a 2003-11-23 devnull int n;
976 7763a61a 2003-11-23 devnull MetaBlock mb;
977 7763a61a 2003-11-23 devnull
978 7763a61a 2003-11-23 devnull if(k->nindex == 0)
979 7763a61a 2003-11-23 devnull return;
980 7763a61a 2003-11-23 devnull assert(k->nindex <= k->maxindex);
981 7763a61a 2003-11-23 devnull
982 7763a61a 2003-11-23 devnull p = k->buf;
983 7763a61a 2003-11-23 devnull n = k->rp - p;
984 7763a61a 2003-11-23 devnull
985 7763a61a 2003-11-23 devnull mb.size = n;
986 7763a61a 2003-11-23 devnull mb.free = 0;
987 7763a61a 2003-11-23 devnull mb.nindex = k->nindex;
988 7763a61a 2003-11-23 devnull mb.maxindex = k->maxindex;
989 7763a61a 2003-11-23 devnull mb.buf = p;
990 7763a61a 2003-11-23 devnull mbPack(&mb);
991 7763a61a 2003-11-23 devnull
992 7763a61a 2003-11-23 devnull p += MetaHeaderSize;
993 7763a61a 2003-11-23 devnull
994 7763a61a 2003-11-23 devnull /* XXX this is not reentrant! */
995 7763a61a 2003-11-23 devnull blockBase = k->buf;
996 7763a61a 2003-11-23 devnull qsort(p, k->nindex, MetaIndexSize, dirCmp);
997 7763a61a 2003-11-23 devnull p += k->nindex*MetaIndexSize;
998 7763a61a 2003-11-23 devnull
999 7763a61a 2003-11-23 devnull memset(p, 0, (k->maxindex-k->nindex)*MetaIndexSize);
1000 7763a61a 2003-11-23 devnull p += (k->maxindex-k->nindex)*MetaIndexSize;
1001 7763a61a 2003-11-23 devnull
1002 7763a61a 2003-11-23 devnull sinkWrite(k->sink, k->buf, n);
1003 7763a61a 2003-11-23 devnull
1004 7763a61a 2003-11-23 devnull /* move down partial entry */
1005 7763a61a 2003-11-23 devnull n = k->p - k->rp;
1006 7763a61a 2003-11-23 devnull memmove(p, k->rp, n);
1007 7763a61a 2003-11-23 devnull k->rp = p;
1008 7763a61a 2003-11-23 devnull k->p = p + n;
1009 7763a61a 2003-11-23 devnull k->nindex = 0;
1010 7763a61a 2003-11-23 devnull }
1011 7763a61a 2003-11-23 devnull
1012 7763a61a 2003-11-23 devnull void
1013 7763a61a 2003-11-23 devnull metaSinkPutc(MetaSink *k, int c)
1014 7763a61a 2003-11-23 devnull {
1015 7763a61a 2003-11-23 devnull if(k->p+1 > k->ep)
1016 7763a61a 2003-11-23 devnull metaSinkFlush(k);
1017 7763a61a 2003-11-23 devnull if(k->p+1 > k->ep)
1018 7763a61a 2003-11-23 devnull vtFatal("directory entry too large");
1019 7763a61a 2003-11-23 devnull k->p[0] = c;
1020 7763a61a 2003-11-23 devnull k->p++;
1021 7763a61a 2003-11-23 devnull }
1022 7763a61a 2003-11-23 devnull
1023 7763a61a 2003-11-23 devnull void
1024 7763a61a 2003-11-23 devnull metaSinkPutString(MetaSink *k, char *s)
1025 7763a61a 2003-11-23 devnull {
1026 7763a61a 2003-11-23 devnull int n = strlen(s);
1027 7763a61a 2003-11-23 devnull metaSinkPutc(k, n>>8);
1028 7763a61a 2003-11-23 devnull metaSinkPutc(k, n);
1029 7763a61a 2003-11-23 devnull metaSinkWrite(k, (uchar*)s, n);
1030 7763a61a 2003-11-23 devnull }
1031 7763a61a 2003-11-23 devnull
1032 7763a61a 2003-11-23 devnull void
1033 7763a61a 2003-11-23 devnull metaSinkPutUint32(MetaSink *k, ulong x)
1034 7763a61a 2003-11-23 devnull {
1035 7763a61a 2003-11-23 devnull metaSinkPutc(k, x>>24);
1036 7763a61a 2003-11-23 devnull metaSinkPutc(k, x>>16);
1037 7763a61a 2003-11-23 devnull metaSinkPutc(k, x>>8);
1038 7763a61a 2003-11-23 devnull metaSinkPutc(k, x);
1039 7763a61a 2003-11-23 devnull }
1040 7763a61a 2003-11-23 devnull
1041 7763a61a 2003-11-23 devnull void
1042 7763a61a 2003-11-23 devnull metaSinkPutUint64(MetaSink *k, uvlong x)
1043 7763a61a 2003-11-23 devnull {
1044 7763a61a 2003-11-23 devnull metaSinkPutUint32(k, x>>32);
1045 7763a61a 2003-11-23 devnull metaSinkPutUint32(k, x);
1046 7763a61a 2003-11-23 devnull }
1047 7763a61a 2003-11-23 devnull
1048 7763a61a 2003-11-23 devnull void
1049 7763a61a 2003-11-23 devnull metaSinkWrite(MetaSink *k, uchar *data, int n)
1050 7763a61a 2003-11-23 devnull {
1051 7763a61a 2003-11-23 devnull if(k->p + n > k->ep)
1052 7763a61a 2003-11-23 devnull metaSinkFlush(k);
1053 7763a61a 2003-11-23 devnull if(k->p + n > k->ep)
1054 7763a61a 2003-11-23 devnull vtFatal("directory entry too large");
1055 7763a61a 2003-11-23 devnull
1056 7763a61a 2003-11-23 devnull memmove(k->p, data, n);
1057 7763a61a 2003-11-23 devnull k->p += n;
1058 7763a61a 2003-11-23 devnull }
1059 7763a61a 2003-11-23 devnull
1060 7763a61a 2003-11-23 devnull void
1061 7763a61a 2003-11-23 devnull metaSinkWriteDir(MetaSink *ms, VacDir *dir)
1062 7763a61a 2003-11-23 devnull {
1063 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, DirMagic);
1064 7763a61a 2003-11-23 devnull metaSinkPutc(ms, Version>>8);
1065 7763a61a 2003-11-23 devnull metaSinkPutc(ms, Version);
1066 7763a61a 2003-11-23 devnull metaSinkPutString(ms, dir->elem);
1067 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->entry);
1068 7763a61a 2003-11-23 devnull metaSinkPutUint64(ms, dir->qid);
1069 7763a61a 2003-11-23 devnull metaSinkPutString(ms, dir->uid);
1070 7763a61a 2003-11-23 devnull metaSinkPutString(ms, dir->gid);
1071 7763a61a 2003-11-23 devnull metaSinkPutString(ms, dir->mid);
1072 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->mtime);
1073 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->mcount);
1074 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->ctime);
1075 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->atime);
1076 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->mode);
1077 7763a61a 2003-11-23 devnull
1078 7763a61a 2003-11-23 devnull if(dir->plan9) {
1079 7763a61a 2003-11-23 devnull metaSinkPutc(ms, DirPlan9Entry); /* plan9 extra info */
1080 7763a61a 2003-11-23 devnull metaSinkPutc(ms, 0); /* plan9 extra size */
1081 7763a61a 2003-11-23 devnull metaSinkPutc(ms, 12); /* plan9 extra size */
1082 7763a61a 2003-11-23 devnull metaSinkPutUint64(ms, dir->p9path);
1083 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->p9version);
1084 7763a61a 2003-11-23 devnull }
1085 7763a61a 2003-11-23 devnull
1086 7763a61a 2003-11-23 devnull if(dir->qidSpace != 0) {
1087 7763a61a 2003-11-23 devnull metaSinkPutc(ms, DirQidSpaceEntry);
1088 7763a61a 2003-11-23 devnull metaSinkPutc(ms, 0);
1089 7763a61a 2003-11-23 devnull metaSinkPutc(ms, 16);
1090 7763a61a 2003-11-23 devnull metaSinkPutUint64(ms, dir->qidOffset);
1091 7763a61a 2003-11-23 devnull metaSinkPutUint64(ms, dir->qidMax);
1092 7763a61a 2003-11-23 devnull }
1093 7763a61a 2003-11-23 devnull
1094 7763a61a 2003-11-23 devnull if(dir->gen != 0) {
1095 7763a61a 2003-11-23 devnull metaSinkPutc(ms, DirGenEntry);
1096 7763a61a 2003-11-23 devnull metaSinkPutc(ms, 0);
1097 7763a61a 2003-11-23 devnull metaSinkPutc(ms, 4);
1098 7763a61a 2003-11-23 devnull metaSinkPutUint32(ms, dir->gen);
1099 7763a61a 2003-11-23 devnull }
1100 7763a61a 2003-11-23 devnull
1101 7763a61a 2003-11-23 devnull metaSinkEOR(ms);
1102 7763a61a 2003-11-23 devnull }
1103 7763a61a 2003-11-23 devnull
1104 7763a61a 2003-11-23 devnull
1105 7763a61a 2003-11-23 devnull void
1106 7763a61a 2003-11-23 devnull plan9ToVacDir(VacDir *vd, Dir *dir, ulong entry, uvlong qid)
1107 7763a61a 2003-11-23 devnull {
1108 7763a61a 2003-11-23 devnull memset(vd, 0, sizeof(VacDir));
1109 7763a61a 2003-11-23 devnull
1110 7763a61a 2003-11-23 devnull vd->elem = vtStrDup(dir->name);
1111 7763a61a 2003-11-23 devnull vd->entry = entry;
1112 7763a61a 2003-11-23 devnull vd->qid = qid;
1113 7763a61a 2003-11-23 devnull vd->uid = vtStrDup(dir->uid);
1114 7763a61a 2003-11-23 devnull vd->gid = vtStrDup(dir->gid);
1115 7763a61a 2003-11-23 devnull vd->mid = vtStrDup(dir->muid);
1116 7763a61a 2003-11-23 devnull vd->mtime = dir->mtime;
1117 7763a61a 2003-11-23 devnull vd->mcount = 0;
1118 7763a61a 2003-11-23 devnull vd->ctime = dir->mtime; /* ctime: not available on plan 9 */
1119 7763a61a 2003-11-23 devnull vd->atime = dir->atime;
1120 7763a61a 2003-11-23 devnull
1121 7763a61a 2003-11-23 devnull vd->mode = dir->mode & 0777;
1122 7763a61a 2003-11-23 devnull if(dir->mode & DMDIR)
1123 7763a61a 2003-11-23 devnull vd->mode |= ModeDir;
1124 7763a61a 2003-11-23 devnull if(dir->mode & DMAPPEND)
1125 7763a61a 2003-11-23 devnull vd->mode |= ModeAppend;
1126 7763a61a 2003-11-23 devnull if(dir->mode & DMEXCL)
1127 7763a61a 2003-11-23 devnull vd->mode |= ModeExclusive;
1128 7763a61a 2003-11-23 devnull
1129 7763a61a 2003-11-23 devnull vd->plan9 = 1;
1130 7763a61a 2003-11-23 devnull vd->p9path = dir->qid.path;
1131 7763a61a 2003-11-23 devnull vd->p9version = dir->qid.vers;
1132 7763a61a 2003-11-23 devnull }
1133 7763a61a 2003-11-23 devnull
1134 7763a61a 2003-11-23 devnull
1135 7763a61a 2003-11-23 devnull void
1136 7763a61a 2003-11-23 devnull metaSinkEOR(MetaSink *k)
1137 7763a61a 2003-11-23 devnull {
1138 7763a61a 2003-11-23 devnull uchar *p;
1139 7763a61a 2003-11-23 devnull int o, n;
1140 7763a61a 2003-11-23 devnull
1141 7763a61a 2003-11-23 devnull p = k->buf + MetaHeaderSize;
1142 7763a61a 2003-11-23 devnull p += k->nindex * MetaIndexSize;
1143 7763a61a 2003-11-23 devnull o = k->rp-k->buf; /* offset from start of block */
1144 7763a61a 2003-11-23 devnull n = k->p-k->rp; /* size of entry */
1145 7763a61a 2003-11-23 devnull p[0] = o >> 8;
1146 7763a61a 2003-11-23 devnull p[1] = o;
1147 7763a61a 2003-11-23 devnull p[2] = n >> 8;
1148 7763a61a 2003-11-23 devnull p[3] = n;
1149 7763a61a 2003-11-23 devnull k->rp = k->p;
1150 7763a61a 2003-11-23 devnull k->nindex++;
1151 7763a61a 2003-11-23 devnull if(k->nindex == k->maxindex)
1152 7763a61a 2003-11-23 devnull metaSinkFlush(k);
1153 7763a61a 2003-11-23 devnull }
1154 7763a61a 2003-11-23 devnull
1155 7763a61a 2003-11-23 devnull void
1156 7763a61a 2003-11-23 devnull metaSinkClose(MetaSink *k)
1157 7763a61a 2003-11-23 devnull {
1158 7763a61a 2003-11-23 devnull metaSinkFlush(k);
1159 7763a61a 2003-11-23 devnull sinkClose(k->sink);
1160 7763a61a 2003-11-23 devnull }
1161 7763a61a 2003-11-23 devnull
1162 7763a61a 2003-11-23 devnull void
1163 7763a61a 2003-11-23 devnull metaSinkFree(MetaSink *k)
1164 7763a61a 2003-11-23 devnull {
1165 7763a61a 2003-11-23 devnull sinkFree(k->sink);
1166 7763a61a 2003-11-23 devnull vtMemFree(k->buf);
1167 7763a61a 2003-11-23 devnull vtMemFree(k);
1168 7763a61a 2003-11-23 devnull }
1169 7763a61a 2003-11-23 devnull
1170 7763a61a 2003-11-23 devnull static void
1171 7763a61a 2003-11-23 devnull warn(char *fmt, ...)
1172 7763a61a 2003-11-23 devnull {
1173 7763a61a 2003-11-23 devnull va_list arg;
1174 7763a61a 2003-11-23 devnull
1175 7763a61a 2003-11-23 devnull va_start(arg, fmt);
1176 7763a61a 2003-11-23 devnull fprint(2, "%s: ", argv0);
1177 7763a61a 2003-11-23 devnull vfprint(2, fmt, arg);
1178 7763a61a 2003-11-23 devnull fprint(2, "\n");
1179 7763a61a 2003-11-23 devnull va_end(arg);
1180 7763a61a 2003-11-23 devnull }
1181 7763a61a 2003-11-23 devnull
1182 7763a61a 2003-11-23 devnull static void
1183 7763a61a 2003-11-23 devnull cleanup(void)
1184 7763a61a 2003-11-23 devnull {
1185 7763a61a 2003-11-23 devnull if(oname != nil)
1186 7763a61a 2003-11-23 devnull remove(oname);
1187 7763a61a 2003-11-23 devnull }
1188 7763a61a 2003-11-23 devnull
1189 7763a61a 2003-11-23 devnull #define TWID64 ((u64int)~(u64int)0)
1190 7763a61a 2003-11-23 devnull
1191 7763a61a 2003-11-23 devnull static u64int
1192 7763a61a 2003-11-23 devnull unittoull(char *s)
1193 7763a61a 2003-11-23 devnull {
1194 7763a61a 2003-11-23 devnull char *es;
1195 7763a61a 2003-11-23 devnull u64int n;
1196 7763a61a 2003-11-23 devnull
1197 7763a61a 2003-11-23 devnull if(s == nil)
1198 7763a61a 2003-11-23 devnull return TWID64;
1199 7763a61a 2003-11-23 devnull n = strtoul(s, &es, 0);
1200 7763a61a 2003-11-23 devnull if(*es == 'k' || *es == 'K'){
1201 7763a61a 2003-11-23 devnull n *= 1024;
1202 7763a61a 2003-11-23 devnull es++;
1203 7763a61a 2003-11-23 devnull }else if(*es == 'm' || *es == 'M'){
1204 7763a61a 2003-11-23 devnull n *= 1024*1024;
1205 7763a61a 2003-11-23 devnull es++;
1206 7763a61a 2003-11-23 devnull }else if(*es == 'g' || *es == 'G'){
1207 7763a61a 2003-11-23 devnull n *= 1024*1024*1024;
1208 7763a61a 2003-11-23 devnull es++;
1209 7763a61a 2003-11-23 devnull }
1210 7763a61a 2003-11-23 devnull if(*es != '\0')
1211 7763a61a 2003-11-23 devnull return TWID64;
1212 7763a61a 2003-11-23 devnull return n;
1213 7763a61a 2003-11-23 devnull }