Blame


1 64f9764e 2008-06-14 rsc #include "stdinc.h"
2 c52cda30 2008-06-14 rsc #include <fcall.h> /* dirmodefmt */
3 64f9764e 2008-06-14 rsc #include "vac.h"
4 64f9764e 2008-06-14 rsc
5 948cc14e 2008-06-15 rsc #ifndef PLAN9PORT
6 948cc14e 2008-06-15 rsc #pragma varargck type "t" ulong
7 948cc14e 2008-06-15 rsc #endif
8 948cc14e 2008-06-15 rsc
9 64f9764e 2008-06-14 rsc VacFs *fs;
10 64f9764e 2008-06-14 rsc int tostdout;
11 286bb40b 2008-12-07 rsc int diff;
12 64f9764e 2008-06-14 rsc int nwant;
13 64f9764e 2008-06-14 rsc char **want;
14 64f9764e 2008-06-14 rsc int *found;
15 64f9764e 2008-06-14 rsc int chatty;
16 64f9764e 2008-06-14 rsc VtConn *conn;
17 64f9764e 2008-06-14 rsc int errors;
18 64f9764e 2008-06-14 rsc int settimes;
19 64f9764e 2008-06-14 rsc int table;
20 64f9764e 2008-06-14 rsc
21 64f9764e 2008-06-14 rsc int mtimefmt(Fmt*);
22 64f9764e 2008-06-14 rsc void unvac(VacFile*, char*, VacDir*);
23 64f9764e 2008-06-14 rsc
24 64f9764e 2008-06-14 rsc void
25 64f9764e 2008-06-14 rsc usage(void)
26 64f9764e 2008-06-14 rsc {
27 286bb40b 2008-12-07 rsc fprint(2, "usage: unvac [-TVcdtv] [-h host] file.vac [file ...]\n");
28 64f9764e 2008-06-14 rsc threadexitsall("usage");
29 64f9764e 2008-06-14 rsc }
30 64f9764e 2008-06-14 rsc
31 286bb40b 2008-12-07 rsc struct
32 286bb40b 2008-12-07 rsc {
33 286bb40b 2008-12-07 rsc vlong data;
34 286bb40b 2008-12-07 rsc vlong skipdata;
35 286bb40b 2008-12-07 rsc } stats;
36 286bb40b 2008-12-07 rsc
37 64f9764e 2008-06-14 rsc void
38 64f9764e 2008-06-14 rsc threadmain(int argc, char *argv[])
39 64f9764e 2008-06-14 rsc {
40 286bb40b 2008-12-07 rsc int i, printstats;
41 64f9764e 2008-06-14 rsc char *host;
42 64f9764e 2008-06-14 rsc VacFile *f;
43 64f9764e 2008-06-14 rsc
44 64f9764e 2008-06-14 rsc fmtinstall('H', encodefmt);
45 64f9764e 2008-06-14 rsc fmtinstall('V', vtscorefmt);
46 64f9764e 2008-06-14 rsc fmtinstall('F', vtfcallfmt);
47 c52cda30 2008-06-14 rsc fmtinstall('t', mtimefmt);
48 64f9764e 2008-06-14 rsc fmtinstall('M', dirmodefmt);
49 fa325e9b 2020-01-10 cross
50 64f9764e 2008-06-14 rsc host = nil;
51 286bb40b 2008-12-07 rsc printstats = 0;
52 286bb40b 2008-12-07 rsc
53 64f9764e 2008-06-14 rsc ARGBEGIN{
54 64f9764e 2008-06-14 rsc case 'T':
55 64f9764e 2008-06-14 rsc settimes = 1;
56 64f9764e 2008-06-14 rsc break;
57 64f9764e 2008-06-14 rsc case 'V':
58 64f9764e 2008-06-14 rsc chattyventi = 1;
59 64f9764e 2008-06-14 rsc break;
60 64f9764e 2008-06-14 rsc case 'c':
61 64f9764e 2008-06-14 rsc tostdout++;
62 286bb40b 2008-12-07 rsc break;
63 286bb40b 2008-12-07 rsc case 'd':
64 286bb40b 2008-12-07 rsc diff++;
65 64f9764e 2008-06-14 rsc break;
66 64f9764e 2008-06-14 rsc case 'h':
67 64f9764e 2008-06-14 rsc host = EARGF(usage());
68 64f9764e 2008-06-14 rsc break;
69 286bb40b 2008-12-07 rsc case 's':
70 286bb40b 2008-12-07 rsc printstats++;
71 286bb40b 2008-12-07 rsc break;
72 64f9764e 2008-06-14 rsc case 't':
73 64f9764e 2008-06-14 rsc table++;
74 64f9764e 2008-06-14 rsc break;
75 64f9764e 2008-06-14 rsc case 'v':
76 64f9764e 2008-06-14 rsc chatty++;
77 64f9764e 2008-06-14 rsc break;
78 64f9764e 2008-06-14 rsc default:
79 64f9764e 2008-06-14 rsc usage();
80 64f9764e 2008-06-14 rsc }ARGEND
81 64f9764e 2008-06-14 rsc
82 64f9764e 2008-06-14 rsc if(argc < 1)
83 64f9764e 2008-06-14 rsc usage();
84 64f9764e 2008-06-14 rsc
85 286bb40b 2008-12-07 rsc if(tostdout && diff){
86 286bb40b 2008-12-07 rsc fprint(2, "cannot use -c with -d\n");
87 286bb40b 2008-12-07 rsc usage();
88 286bb40b 2008-12-07 rsc }
89 286bb40b 2008-12-07 rsc
90 64f9764e 2008-06-14 rsc conn = vtdial(host);
91 64f9764e 2008-06-14 rsc if(conn == nil)
92 64f9764e 2008-06-14 rsc sysfatal("could not connect to server: %r");
93 64f9764e 2008-06-14 rsc
94 64f9764e 2008-06-14 rsc if(vtconnect(conn) < 0)
95 64f9764e 2008-06-14 rsc sysfatal("vtconnect: %r");
96 64f9764e 2008-06-14 rsc
97 59b460f8 2020-01-13 rsc fs = vacfsopen(conn, argv[0], VtOREAD, 128<<20);
98 64f9764e 2008-06-14 rsc if(fs == nil)
99 64f9764e 2008-06-14 rsc sysfatal("vacfsopen: %r");
100 64f9764e 2008-06-14 rsc
101 64f9764e 2008-06-14 rsc nwant = argc-1;
102 64f9764e 2008-06-14 rsc want = argv+1;
103 64f9764e 2008-06-14 rsc found = vtmallocz(nwant*sizeof found[0]);
104 64f9764e 2008-06-14 rsc
105 64f9764e 2008-06-14 rsc if((f = vacfsgetroot(fs)) == nil)
106 64f9764e 2008-06-14 rsc sysfatal("vacfsgetroot: %r");
107 fa325e9b 2020-01-10 cross
108 64f9764e 2008-06-14 rsc unvac(f, nil, nil);
109 64f9764e 2008-06-14 rsc for(i=0; i<nwant; i++){
110 64f9764e 2008-06-14 rsc if(want[i] && !found[i]){
111 64f9764e 2008-06-14 rsc fprint(2, "warning: didn't find %s\n", want[i]);
112 64f9764e 2008-06-14 rsc errors++;
113 64f9764e 2008-06-14 rsc }
114 64f9764e 2008-06-14 rsc }
115 64f9764e 2008-06-14 rsc if(errors)
116 64f9764e 2008-06-14 rsc threadexitsall("errors");
117 286bb40b 2008-12-07 rsc if(printstats)
118 286bb40b 2008-12-07 rsc fprint(2, "%lld bytes read, %lld bytes skipped\n",
119 286bb40b 2008-12-07 rsc stats.data, stats.skipdata);
120 64f9764e 2008-06-14 rsc threadexitsall(0);
121 64f9764e 2008-06-14 rsc }
122 64f9764e 2008-06-14 rsc
123 64f9764e 2008-06-14 rsc int
124 64f9764e 2008-06-14 rsc writen(int fd, char *buf, int n)
125 64f9764e 2008-06-14 rsc {
126 64f9764e 2008-06-14 rsc int m;
127 64f9764e 2008-06-14 rsc int oldn;
128 fa325e9b 2020-01-10 cross
129 64f9764e 2008-06-14 rsc oldn = n;
130 64f9764e 2008-06-14 rsc while(n > 0){
131 64f9764e 2008-06-14 rsc m = write(fd, buf, n);
132 64f9764e 2008-06-14 rsc if(m <= 0)
133 64f9764e 2008-06-14 rsc return -1;
134 64f9764e 2008-06-14 rsc buf += m;
135 64f9764e 2008-06-14 rsc n -= m;
136 64f9764e 2008-06-14 rsc }
137 64f9764e 2008-06-14 rsc return oldn;
138 64f9764e 2008-06-14 rsc }
139 64f9764e 2008-06-14 rsc
140 64f9764e 2008-06-14 rsc int
141 64f9764e 2008-06-14 rsc wantfile(char *name)
142 64f9764e 2008-06-14 rsc {
143 64f9764e 2008-06-14 rsc int i, namelen, n;
144 fa325e9b 2020-01-10 cross
145 64f9764e 2008-06-14 rsc if(nwant == 0)
146 64f9764e 2008-06-14 rsc return 1;
147 64f9764e 2008-06-14 rsc
148 64f9764e 2008-06-14 rsc namelen = strlen(name);
149 64f9764e 2008-06-14 rsc for(i=0; i<nwant; i++){
150 64f9764e 2008-06-14 rsc if(want[i] == nil)
151 64f9764e 2008-06-14 rsc continue;
152 64f9764e 2008-06-14 rsc n = strlen(want[i]);
153 64f9764e 2008-06-14 rsc if(n < namelen && name[n] == '/' && memcmp(name, want[i], n) == 0)
154 64f9764e 2008-06-14 rsc return 1;
155 b5a2d4da 2008-12-06 rsc if(namelen < n && want[i][namelen] == '/' && memcmp(want[i], name, namelen) == 0)
156 64f9764e 2008-06-14 rsc return 1;
157 64f9764e 2008-06-14 rsc if(n == namelen && memcmp(name, want[i], n) == 0){
158 64f9764e 2008-06-14 rsc found[i] = 1;
159 64f9764e 2008-06-14 rsc return 1;
160 64f9764e 2008-06-14 rsc }
161 64f9764e 2008-06-14 rsc }
162 64f9764e 2008-06-14 rsc return 0;
163 64f9764e 2008-06-14 rsc }
164 64f9764e 2008-06-14 rsc
165 64f9764e 2008-06-14 rsc void
166 64f9764e 2008-06-14 rsc unvac(VacFile *f, char *name, VacDir *vdir)
167 64f9764e 2008-06-14 rsc {
168 64f9764e 2008-06-14 rsc static char buf[65536];
169 286bb40b 2008-12-07 rsc int fd, n, m, bsize;
170 c52cda30 2008-06-14 rsc ulong mode, mode9;
171 64f9764e 2008-06-14 rsc char *newname;
172 64f9764e 2008-06-14 rsc char *what;
173 64f9764e 2008-06-14 rsc vlong off;
174 64f9764e 2008-06-14 rsc Dir d, *dp;
175 64f9764e 2008-06-14 rsc VacDirEnum *vde;
176 64f9764e 2008-06-14 rsc VacDir newvdir;
177 64f9764e 2008-06-14 rsc VacFile *newf;
178 64f9764e 2008-06-14 rsc
179 64f9764e 2008-06-14 rsc if(vdir)
180 64f9764e 2008-06-14 rsc mode = vdir->mode;
181 64f9764e 2008-06-14 rsc else
182 64f9764e 2008-06-14 rsc mode = vacfilegetmode(f);
183 64f9764e 2008-06-14 rsc
184 64f9764e 2008-06-14 rsc if(vdir){
185 64f9764e 2008-06-14 rsc if(table){
186 64f9764e 2008-06-14 rsc if(chatty){
187 64f9764e 2008-06-14 rsc mode9 = vdir->mode&0777;
188 64f9764e 2008-06-14 rsc if(mode&ModeDir)
189 64f9764e 2008-06-14 rsc mode9 |= DMDIR;
190 64f9764e 2008-06-14 rsc if(mode&ModeAppend)
191 64f9764e 2008-06-14 rsc mode9 |= DMAPPEND;
192 64f9764e 2008-06-14 rsc if(mode&ModeExclusive)
193 64f9764e 2008-06-14 rsc mode9 |= DMEXCL;
194 948cc14e 2008-06-15 rsc #ifdef PLAN9PORT
195 948cc14e 2008-06-15 rsc if(mode&ModeLink)
196 948cc14e 2008-06-15 rsc mode9 |= DMSYMLINK;
197 64f9764e 2008-06-14 rsc if(mode&ModeNamedPipe)
198 64f9764e 2008-06-14 rsc mode9 |= DMNAMEDPIPE;
199 64f9764e 2008-06-14 rsc if(mode&ModeSetUid)
200 64f9764e 2008-06-14 rsc mode9 |= DMSETUID;
201 64f9764e 2008-06-14 rsc if(mode&ModeSetGid)
202 64f9764e 2008-06-14 rsc mode9 |= DMSETGID;
203 64f9764e 2008-06-14 rsc if(mode&ModeDevice)
204 64f9764e 2008-06-14 rsc mode9 |= DMDEVICE;
205 948cc14e 2008-06-15 rsc #endif
206 c52cda30 2008-06-14 rsc print("%M %-10s %-10s %11lld %t %s\n",
207 64f9764e 2008-06-14 rsc mode9, vdir->uid, vdir->gid, vdir->size,
208 64f9764e 2008-06-14 rsc vdir->mtime, name);
209 64f9764e 2008-06-14 rsc }else
210 64f9764e 2008-06-14 rsc print("%s%s\n", name, (mode&ModeDir) ? "/" : "");
211 64f9764e 2008-06-14 rsc }
212 64f9764e 2008-06-14 rsc else if(chatty)
213 64f9764e 2008-06-14 rsc fprint(2, "%s%s\n", name, (mode&ModeDir) ? "/" : "");
214 64f9764e 2008-06-14 rsc }
215 64f9764e 2008-06-14 rsc
216 64f9764e 2008-06-14 rsc if(mode&(ModeDevice|ModeLink|ModeNamedPipe|ModeExclusive)){
217 64f9764e 2008-06-14 rsc if(table)
218 64f9764e 2008-06-14 rsc return;
219 64f9764e 2008-06-14 rsc if(mode&ModeDevice)
220 64f9764e 2008-06-14 rsc what = "device";
221 64f9764e 2008-06-14 rsc else if(mode&ModeLink)
222 64f9764e 2008-06-14 rsc what = "link";
223 64f9764e 2008-06-14 rsc else if(mode&ModeNamedPipe)
224 64f9764e 2008-06-14 rsc what = "named pipe";
225 64f9764e 2008-06-14 rsc else if(mode&ModeExclusive)
226 64f9764e 2008-06-14 rsc what = "lock";
227 64f9764e 2008-06-14 rsc else
228 64f9764e 2008-06-14 rsc what = "unknown type of file";
229 64f9764e 2008-06-14 rsc fprint(2, "warning: ignoring %s %s\n", what, name);
230 64f9764e 2008-06-14 rsc return;
231 64f9764e 2008-06-14 rsc }
232 fa325e9b 2020-01-10 cross
233 64f9764e 2008-06-14 rsc if(mode&ModeDir){
234 64f9764e 2008-06-14 rsc if((vde = vdeopen(f)) == nil){
235 64f9764e 2008-06-14 rsc fprint(2, "vdeopen %s: %r", name);
236 64f9764e 2008-06-14 rsc errors++;
237 64f9764e 2008-06-14 rsc return;
238 64f9764e 2008-06-14 rsc }
239 64f9764e 2008-06-14 rsc if(!table && !tostdout && vdir){
240 64f9764e 2008-06-14 rsc // create directory
241 64f9764e 2008-06-14 rsc if((dp = dirstat(name)) == nil){
242 707b99e6 2011-02-23 rsc if((fd = create(name, OREAD, DMDIR|0700|(mode&0777))) < 0){
243 64f9764e 2008-06-14 rsc fprint(2, "mkdir %s: %r\n", name);
244 64f9764e 2008-06-14 rsc vdeclose(vde);
245 64f9764e 2008-06-14 rsc }
246 64f9764e 2008-06-14 rsc close(fd);
247 64f9764e 2008-06-14 rsc }else{
248 64f9764e 2008-06-14 rsc if(!(dp->mode&DMDIR)){
249 64f9764e 2008-06-14 rsc fprint(2, "%s already exists and is not a directory\n", name);
250 64f9764e 2008-06-14 rsc errors++;
251 64f9764e 2008-06-14 rsc free(dp);
252 64f9764e 2008-06-14 rsc vdeclose(vde);
253 64f9764e 2008-06-14 rsc return;
254 64f9764e 2008-06-14 rsc }
255 64f9764e 2008-06-14 rsc free(dp);
256 64f9764e 2008-06-14 rsc }
257 64f9764e 2008-06-14 rsc }
258 64f9764e 2008-06-14 rsc while(vderead(vde, &newvdir) > 0){
259 64f9764e 2008-06-14 rsc if(name == nil)
260 64f9764e 2008-06-14 rsc newname = newvdir.elem;
261 64f9764e 2008-06-14 rsc else
262 64f9764e 2008-06-14 rsc newname = smprint("%s/%s", name, newvdir.elem);
263 64f9764e 2008-06-14 rsc if(wantfile(newname)){
264 64f9764e 2008-06-14 rsc if((newf = vacfilewalk(f, newvdir.elem)) == nil){
265 64f9764e 2008-06-14 rsc fprint(2, "walk %s: %r\n", name);
266 64f9764e 2008-06-14 rsc errors++;
267 64f9764e 2008-06-14 rsc }else if(newf == f){
268 64f9764e 2008-06-14 rsc fprint(2, "walk loop: %s\n", newname);
269 64f9764e 2008-06-14 rsc vacfiledecref(newf);
270 64f9764e 2008-06-14 rsc }else{
271 64f9764e 2008-06-14 rsc unvac(newf, newname, &newvdir);
272 64f9764e 2008-06-14 rsc vacfiledecref(newf);
273 64f9764e 2008-06-14 rsc }
274 64f9764e 2008-06-14 rsc }
275 64f9764e 2008-06-14 rsc if(newname != newvdir.elem)
276 64f9764e 2008-06-14 rsc free(newname);
277 64f9764e 2008-06-14 rsc vdcleanup(&newvdir);
278 64f9764e 2008-06-14 rsc }
279 64f9764e 2008-06-14 rsc vdeclose(vde);
280 64f9764e 2008-06-14 rsc }else{
281 64f9764e 2008-06-14 rsc if(!table){
282 286bb40b 2008-12-07 rsc off = 0;
283 64f9764e 2008-06-14 rsc if(tostdout)
284 64f9764e 2008-06-14 rsc fd = dup(1, -1);
285 286bb40b 2008-12-07 rsc else if(diff && (fd = open(name, ORDWR)) >= 0){
286 286bb40b 2008-12-07 rsc bsize = vacfiledsize(f);
287 286bb40b 2008-12-07 rsc while((n = readn(fd, buf, bsize)) > 0){
288 286bb40b 2008-12-07 rsc if(sha1matches(f, off/bsize, (uchar*)buf, n)){
289 286bb40b 2008-12-07 rsc off += n;
290 286bb40b 2008-12-07 rsc stats.skipdata += n;
291 286bb40b 2008-12-07 rsc continue;
292 286bb40b 2008-12-07 rsc }
293 286bb40b 2008-12-07 rsc seek(fd, off, 0);
294 286bb40b 2008-12-07 rsc if((m = vacfileread(f, buf, n, off)) < 0)
295 286bb40b 2008-12-07 rsc break;
296 286bb40b 2008-12-07 rsc if(writen(fd, buf, m) != m){
297 286bb40b 2008-12-07 rsc fprint(2, "write %s: %r\n", name);
298 286bb40b 2008-12-07 rsc goto Err;
299 286bb40b 2008-12-07 rsc }
300 286bb40b 2008-12-07 rsc off += m;
301 286bb40b 2008-12-07 rsc stats.data += m;
302 286bb40b 2008-12-07 rsc if(m < n){
303 286bb40b 2008-12-07 rsc nulldir(&d);
304 286bb40b 2008-12-07 rsc d.length = off;
305 286bb40b 2008-12-07 rsc if(dirfwstat(fd, &d) < 0){
306 286bb40b 2008-12-07 rsc fprint(2, "dirfwstat %s: %r\n", name);
307 286bb40b 2008-12-07 rsc goto Err;
308 286bb40b 2008-12-07 rsc }
309 286bb40b 2008-12-07 rsc break;
310 286bb40b 2008-12-07 rsc }
311 286bb40b 2008-12-07 rsc }
312 286bb40b 2008-12-07 rsc }
313 64f9764e 2008-06-14 rsc else if((fd = create(name, OWRITE, mode&0777)) < 0){
314 64f9764e 2008-06-14 rsc fprint(2, "create %s: %r\n", name);
315 64f9764e 2008-06-14 rsc errors++;
316 64f9764e 2008-06-14 rsc return;
317 64f9764e 2008-06-14 rsc }
318 64f9764e 2008-06-14 rsc while((n = vacfileread(f, buf, sizeof buf, off)) > 0){
319 64f9764e 2008-06-14 rsc if(writen(fd, buf, n) != n){
320 64f9764e 2008-06-14 rsc fprint(2, "write %s: %r\n", name);
321 286bb40b 2008-12-07 rsc Err:
322 64f9764e 2008-06-14 rsc errors++;
323 64f9764e 2008-06-14 rsc close(fd);
324 64f9764e 2008-06-14 rsc remove(name);
325 64f9764e 2008-06-14 rsc return;
326 64f9764e 2008-06-14 rsc }
327 64f9764e 2008-06-14 rsc off += n;
328 286bb40b 2008-12-07 rsc stats.data += n;
329 64f9764e 2008-06-14 rsc }
330 64f9764e 2008-06-14 rsc close(fd);
331 64f9764e 2008-06-14 rsc }
332 64f9764e 2008-06-14 rsc }
333 64f9764e 2008-06-14 rsc if(vdir && settimes && !tostdout){
334 64f9764e 2008-06-14 rsc nulldir(&d);
335 64f9764e 2008-06-14 rsc d.mtime = vdir->mtime;
336 64f9764e 2008-06-14 rsc if(dirwstat(name, &d) < 0)
337 64f9764e 2008-06-14 rsc fprint(2, "warning: setting mtime on %s: %r", name);
338 64f9764e 2008-06-14 rsc }
339 64f9764e 2008-06-14 rsc }
340 64f9764e 2008-06-14 rsc
341 64f9764e 2008-06-14 rsc int
342 64f9764e 2008-06-14 rsc mtimefmt(Fmt *f)
343 64f9764e 2008-06-14 rsc {
344 64f9764e 2008-06-14 rsc Tm *tm;
345 fa325e9b 2020-01-10 cross
346 64f9764e 2008-06-14 rsc tm = localtime(va_arg(f->args, ulong));
347 64f9764e 2008-06-14 rsc fmtprint(f, "%04d-%02d-%02d %02d:%02d",
348 64f9764e 2008-06-14 rsc tm->year+1900, tm->mon+1, tm->mday,
349 64f9764e 2008-06-14 rsc tm->hour, tm->min);
350 64f9764e 2008-06-14 rsc return 0;
351 64f9764e 2008-06-14 rsc }