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 */
47 int fskind; /* Fs, Archive */
48 int setuid; /* on Fs: set uid and gid? */
52 main(int argc, char **argv)
65 Binits(&bout, 1, OWRITE, boutbuf, sizeof boutbuf);
69 fprint(2, "cannot use -d with -a\n");
73 newroot = EARGF(usage());
85 oldroot = EARGF(usage());
100 buflen = atoi(EARGF(usage()))-8;
109 if((xflag || oflag) && fskind != Archive){
110 fprint(2, "cannot use -x and -o without -a\n");
114 buf = malloc(buflen);
115 zbuf = malloc(buflen);
116 memset(zbuf, 0, buflen);
118 cputype = getenv("cputype");
123 for(i = 0; i < argc; i++){
125 fprint(2, "processing %q\n", proto);
126 if(rdproto(proto, oldroot, protoenum, protowarn, nil) < 0){
127 fprint(2, "%q: can't open %q: skipping\n", prog, proto);
132 fprint(2, "file system made\n");
134 exits("skipped protos");
135 if(fskind == Archive){
137 Bprint(&bout, "end of archive\n");
144 * check if file to is up to date with
145 * respect to the file represented by df
148 uptodate(Dir *df, char *to)
153 if(fskind == Archive || ream || (dt = dirstat(to)) == nil)
155 ret = dt->mtime >= df->mtime;
164 int f, t, n, needwrite, nowarnyet = 1;
168 f = open(oldfile, OREAD);
170 warn("can't open %q: %r", oldfile);
174 if(fskind == Archive)
177 strcpy(cptmp, newfile);
178 p = utfrrune(cptmp, L'/');
180 error("internal temporary file error");
181 strcpy(p+1, "__mkfstmp");
182 t = create(cptmp, OWRITE, 0666);
184 warn("can't create %q: %r", newfile);
191 for(tot = 0; tot < d->length; tot += n){
192 len = d->length - tot;
193 /* don't read beyond d->length */
196 n = read(f, buf, len);
198 if(n < 0 && nowarnyet) {
199 warn("can't read %q: %r", oldfile);
203 * don't quit: pad to d->length (in pieces) to agree
204 * with the length in the header, already emitted.
209 if(fskind == Archive){
210 if(Bwrite(&bout, buf, n) != n)
211 error("write error: %r");
212 }else if(memcmp(buf, zbuf, n) == 0){
213 if(seek(t, n, 1) < 0)
214 error("can't write zeros to %q: %r", newfile);
217 if(write(t, buf, n) < n)
218 error("can't write %q: %r", newfile);
224 if(seek(t, -1, 1) < 0 || write(t, zbuf, 1) != 1)
225 error("can't write zero at end of %q: %r", newfile);
227 if(tot != d->length){
228 /* this should no longer happen */
229 warn("wrong number of bytes written to %q (was %lld should be %lld)\n",
230 newfile, tot, d->length);
231 if(fskind == Archive){
232 warn("seeking to proper position\n");
233 /* does no good if stdout is a pipe */
234 Bseek(&bout, d->length - tot, 1);
237 if(fskind == Archive)
245 if(dirfwstat(t, &nd) < 0)
246 error("can't move tmp file to %q: %r", newfile);
260 if(fskind == Archive){
264 fd = create(newfile, OREAD, d->mode);
270 if((d1 = dirstat(newfile)) == nil || !(d1->mode & DMDIR)){
272 error("can't create %q", newfile);
275 if(dirwstat(newfile, &nd) < 0)
276 warn("can't set modes for %q: %r", newfile);
279 dirwstat(newfile, &nd);
282 if(dirfwstat(fd, &nd) < 0)
283 warn("can't set modes for %q: %r", newfile);
293 Bprint(&bout, "%q %luo %q %q %lud %lld\n",
294 newfile, d->mode, d->uid, d->gid, d->mtime, d->length);
298 protowarn(char *msg, void *)
304 protoenum(char *new, char *old, Dir *d, void *)
308 sprint(newfile, "%s%s", newroot, new);
309 sprint(oldfile, "%s", old);
312 if(!(d->mode & DMDIR))
313 Bprint(&bout, "%q\n", cleanname(oldfile));
317 Bprint(&bout, "%q\t%ld\t%lld\n", new, d->mtime, d->length);
320 if(verb && (fskind == Archive || ream))
321 fprint(2, "%q\n", new);
322 if(fskind == Fs && !setuid){
326 if(!uptodate(d, newfile)){
327 if(verb && (fskind != Archive && ream == 0))
328 fprint(2, "%q\n", new);
338 if(verb && (fskind != Archive && ream == 0))
339 fprint(2, "%q\n", new);
340 if(dirwstat(newfile, &nd) < 0)
341 warn("can't set modes for %q: %r", new);
344 dirwstat(newfile, &nd);
349 error(char *fmt, ...)
354 sprint(buf, "%q: %q: ", prog, proto);
356 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
358 fprint(2, "%s\n", buf);
368 sprint(buf, "%q: %q: ", prog, proto);
370 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
372 fprint(2, "%s\n", buf);
378 fprint(2, "usage: %q [-adprvoxUD] [-d root] [-s source] [-z n] proto ...\n", prog);