11 * types of destination file sytems
17 void protowarn(char *msg, void *);
18 void protoenum(char *new, char *old, Dir *d, void *);
22 void error(char *, ...);
24 int uptodate(Dir*, char*);
26 void warn(char *, ...);
28 Biobufhdr bout; /* stdout when writing archive */
46 int fskind; /* Fs, Archive */
47 int setuid; /* on Fs: set uid and gid? */
51 main(int argc, char **argv)
64 Binits(&bout, 1, OWRITE, boutbuf, sizeof boutbuf);
68 fprint(2, "cannot use -d with -a\n");
72 newroot = EARGF(usage());
84 oldroot = EARGF(usage());
99 buflen = atoi(EARGF(usage()))-8;
108 if((xflag || oflag) && fskind != Archive){
109 fprint(2, "cannot use -x and -o without -a\n");
113 buf = malloc(buflen);
114 zbuf = malloc(buflen);
115 memset(zbuf, 0, buflen);
118 for(i = 0; i < argc; i++){
120 fprint(2, "processing %q\n", proto);
121 if(rdproto(proto, oldroot, protoenum, protowarn, nil) < 0){
122 fprint(2, "%q: can't open %q: skipping\n", prog, proto);
127 fprint(2, "file system made\n");
129 exits("skipped protos");
130 if(fskind == Archive){
132 Bprint(&bout, "end of archive\n");
139 * check if file to is up to date with
140 * respect to the file represented by df
143 uptodate(Dir *df, char *to)
148 if(fskind == Archive || ream || (dt = dirstat(to)) == nil)
150 ret = dt->mtime >= df->mtime;
159 int f, t, n, needwrite, nowarnyet = 1;
163 f = open(oldfile, OREAD);
165 warn("can't open %q: %r", oldfile);
169 if(fskind == Archive)
172 strcpy(cptmp, newfile);
173 p = utfrrune(cptmp, L'/');
175 error("internal temporary file error");
176 strcpy(p+1, "__mkfstmp");
177 t = create(cptmp, OWRITE, 0666);
179 warn("can't create %q: %r", newfile);
186 for(tot = 0; tot < d->length; tot += n){
187 len = d->length - tot;
188 /* don't read beyond d->length */
191 n = read(f, buf, len);
193 if(n < 0 && nowarnyet) {
194 warn("can't read %q: %r", oldfile);
198 * don't quit: pad to d->length (in pieces) to agree
199 * with the length in the header, already emitted.
204 if(fskind == Archive){
205 if(Bwrite(&bout, buf, n) != n)
206 error("write error: %r");
207 }else if(memcmp(buf, zbuf, n) == 0){
208 if(seek(t, n, 1) < 0)
209 error("can't write zeros to %q: %r", newfile);
212 if(write(t, buf, n) < n)
213 error("can't write %q: %r", newfile);
219 if(seek(t, -1, 1) < 0 || write(t, zbuf, 1) != 1)
220 error("can't write zero at end of %q: %r", newfile);
222 if(tot != d->length){
223 /* this should no longer happen */
224 warn("wrong number of bytes written to %q (was %lld should be %lld)\n",
225 newfile, tot, d->length);
226 if(fskind == Archive){
227 warn("seeking to proper position\n");
228 /* does no good if stdout is a pipe */
229 Bseek(&bout, d->length - tot, 1);
232 if(fskind == Archive)
240 if(dirfwstat(t, &nd) < 0)
241 error("can't move tmp file to %q: %r", newfile);
255 if(fskind == Archive){
259 fd = create(newfile, OREAD, d->mode);
265 if((d1 = dirstat(newfile)) == nil || !(d1->mode & DMDIR)){
267 error("can't create %q", newfile);
270 if(dirwstat(newfile, &nd) < 0)
271 warn("can't set modes for %q: %r", newfile);
274 dirwstat(newfile, &nd);
277 if(dirfwstat(fd, &nd) < 0)
278 warn("can't set modes for %q: %r", newfile);
288 Bprint(&bout, "%q %luo %q %q %lud %lld\n",
289 newfile, d->mode, d->uid, d->gid, d->mtime, d->length);
293 protowarn(char *msg, void *)
299 protoenum(char *new, char *old, Dir *d, void *)
303 sprint(newfile, "%s%s", newroot, new);
304 sprint(oldfile, "%s", old);
307 if(!(d->mode & DMDIR))
308 Bprint(&bout, "%q\n", cleanname(oldfile));
312 Bprint(&bout, "%q\t%ld\t%lld\n", new, d->mtime, d->length);
315 if(verb && (fskind == Archive || ream))
316 fprint(2, "%q\n", new);
317 if(fskind == Fs && !setuid){
321 if(!uptodate(d, newfile)){
322 if(verb && (fskind != Archive && ream == 0))
323 fprint(2, "%q\n", new);
333 if(verb && (fskind != Archive && ream == 0))
334 fprint(2, "%q\n", new);
335 if(dirwstat(newfile, &nd) < 0)
336 warn("can't set modes for %q: %r", new);
339 dirwstat(newfile, &nd);
344 error(char *fmt, ...)
349 sprint(buf, "%q: %q: ", prog, proto);
351 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
353 fprint(2, "%s\n", buf);
363 sprint(buf, "%q: %q: ", prog, proto);
365 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
367 fprint(2, "%s\n", buf);
373 fprint(2, "usage: %q [-adprvoxUD] [-d root] [-s source] [-z n] proto ...\n", prog);