11 * types of destination file sytems
18 void protowarn(char *msg, void *);
19 void protoenum(char *new, char *old, Dir *d, void *);
23 void error(char *, ...);
27 int uptodate(Dir*, char*);
29 void warn(char *, ...);
31 Biobufhdr bout; /* stdout when writing archive */
50 int fskind; /* Kfs, Fs, Archive */
51 int setuid; /* on Fs: set uid and gid? */
55 main(int argc, char **argv)
70 fprint(2, "cannot use -a with -d\n");
75 Binits(&bout, 1, OWRITE, boutbuf, sizeof boutbuf);
79 fprint(2, "cannot use -d with -a\n");
89 name = EARGF(usage());
113 buflen = atoi(ARGF())-8;
122 buf = malloc(buflen);
123 zbuf = malloc(buflen);
124 memset(zbuf, 0, buflen);
128 cputype = getenv("cputype");
133 for(i = 0; i < argc; i++){
135 fprint(2, "processing %q\n", proto);
136 if(rdproto(proto, oldroot, protoenum, protowarn, nil) < 0){
137 fprint(2, "%q: can't open %q: skipping\n", prog, proto);
142 fprint(2, "file system made\n");
146 exits("skipped protos");
147 if(fskind == Archive){
148 Bprint(&bout, "end of archive\n");
155 * check if file to is up to date with
156 * respect to the file represented by df
159 uptodate(Dir *df, char *to)
164 if(fskind == Archive || ream || (dt = dirstat(to)) == nil)
166 ret = dt->mtime >= df->mtime;
175 int f, t, n, needwrite, nowarnyet = 1;
179 f = open(oldfile, OREAD);
181 warn("can't open %q: %r", oldfile);
185 if(fskind == Archive)
188 strcpy(cptmp, newfile);
189 p = utfrrune(cptmp, L'/');
191 error("internal temporary file error");
192 strcpy(p+1, "__mkfstmp");
193 t = create(cptmp, OWRITE, 0666);
195 warn("can't create %q: %r", newfile);
202 for(tot = 0; tot < d->length; tot += n){
203 len = d->length - tot;
204 /* don't read beyond d->length */
207 n = read(f, buf, len);
209 if(n < 0 && nowarnyet) {
210 warn("can't read %q: %r", oldfile);
214 * don't quit: pad to d->length (in pieces) to agree
215 * with the length in the header, already emitted.
220 if(fskind == Archive){
221 if(Bwrite(&bout, buf, n) != n)
222 error("write error: %r");
223 }else if(memcmp(buf, zbuf, n) == 0){
224 if(seek(t, n, 1) < 0)
225 error("can't write zeros to %q: %r", newfile);
228 if(write(t, buf, n) < n)
229 error("can't write %q: %r", newfile);
235 if(seek(t, -1, 1) < 0 || write(t, zbuf, 1) != 1)
236 error("can't write zero at end of %q: %r", newfile);
238 if(tot != d->length){
239 /* this should no longer happen */
240 warn("wrong number of bytes written to %q (was %lld should be %lld)\n",
241 newfile, tot, d->length);
242 if(fskind == Archive){
243 warn("seeking to proper position\n");
244 /* does no good if stdout is a pipe */
245 Bseek(&bout, d->length - tot, 1);
248 if(fskind == Archive)
256 if(dirfwstat(t, &nd) < 0)
257 error("can't move tmp file to %q: %r", newfile);
271 if(fskind == Archive){
275 fd = create(newfile, OREAD, d->mode);
281 if((d1 = dirstat(newfile)) == nil || !(d1->mode & DMDIR)){
283 error("can't create %q", newfile);
286 if(dirwstat(newfile, &nd) < 0)
287 warn("can't set modes for %q: %r", newfile);
290 dirwstat(newfile, &nd);
293 if(dirfwstat(fd, &nd) < 0)
294 warn("can't set modes for %q: %r", newfile);
304 Bprint(&bout, "%q %luo %q %q %lud %lld\n",
305 newfile, d->mode, d->uid, d->gid, d->mtime, d->length);
309 protowarn(char *msg, void *)
315 protoenum(char *new, char *old, Dir *d, void *)
319 sprint(newfile, "%s%s", newroot, new);
320 sprint(oldfile, "%s", old);
323 Bprint(&bout, "%q\t%ld\t%lld\n", new, d->mtime, d->length);
326 if(verb && (fskind == Archive || ream))
327 fprint(2, "%q\n", new);
328 if(fskind == Fs && !setuid){
332 if(!uptodate(d, newfile)){
333 if(verb && (fskind != Archive && ream == 0))
334 fprint(2, "%q\n", new);
344 if(verb && (fskind != Archive && ream == 0))
345 fprint(2, "%q\n", new);
346 if(dirwstat(newfile, &nd) < 0)
347 warn("can't set modes for %q: %r", new);
350 dirwstat(newfile, &nd);
362 snprint(kname, sizeof kname, "/srv/kfs.%s", name);
364 strcpy(kname, "/srv/kfs");
365 sfd = open(kname, ORDWR);
367 fprint(2, "can't open %q\n", kname);
368 exits("open /srv/kfs");
370 if(mount(sfd, -1, "/n/kfs", MREPL|MCREATE, "") < 0){
371 fprint(2, "can't mount kfs on /n/kfs\n");
375 strcat(kname, ".cmd");
376 sfd = open(kname, ORDWR);
378 fprint(2, "can't open %q\n", kname);
379 exits("open /srv/kfs");
391 if(write(sfd, cmd, strlen(cmd)) != strlen(cmd)){
392 fprint(2, "%q: error writing %q: %r", prog, cmd);
396 n = read(sfd, buf, sizeof buf - 1);
400 if(strcmp(buf, "done") == 0 || strcmp(buf, "success") == 0)
402 if(strcmp(buf, "unknown command") == 0){
403 fprint(2, "%q: command %q not recognized\n", prog, cmd);
410 error(char *fmt, ...)
415 sprint(buf, "%q: %q: ", prog, proto);
417 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
419 fprint(2, "%s\n", buf);
431 sprint(buf, "%q: %q: ", prog, proto);
433 vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
435 fprint(2, "%s\n", buf);
441 fprint(2, "usage: %q [-adprvxUD] [-d root] [-n name] [-s source] [-u users] [-z n] proto ...\n", prog);