13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <bio.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier enum{ 73e12c5d1SDavid du Colombier LEN = 8*1024, 83e12c5d1SDavid du Colombier HUNKS = 128, 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier /* 113e12c5d1SDavid du Colombier * types of destination file sytems 123e12c5d1SDavid du Colombier */ 133e12c5d1SDavid du Colombier Kfs = 0, 143e12c5d1SDavid du Colombier Fs, 153e12c5d1SDavid du Colombier Archive, 163e12c5d1SDavid du Colombier }; 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier typedef struct File File; 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier struct File{ 213e12c5d1SDavid du Colombier char *new; 223e12c5d1SDavid du Colombier char *elem; 233e12c5d1SDavid du Colombier char *old; 24*9a747e4fSDavid du Colombier char *uid; 25*9a747e4fSDavid du Colombier char *gid; 263e12c5d1SDavid du Colombier ulong mode; 273e12c5d1SDavid du Colombier }; 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier void arch(Dir*); 30219b2ee8SDavid du Colombier void copy(Dir*); 31219b2ee8SDavid du Colombier int copyfile(File*, Dir*, int); 323e12c5d1SDavid du Colombier void* emalloc(ulong); 333e12c5d1SDavid du Colombier void error(char *, ...); 34219b2ee8SDavid du Colombier void freefile(File*); 35219b2ee8SDavid du Colombier File* getfile(File*); 36219b2ee8SDavid du Colombier char* getmode(char*, ulong*); 37*9a747e4fSDavid du Colombier char* getname(char*, char**); 38219b2ee8SDavid du Colombier char* getpath(char*); 39219b2ee8SDavid du Colombier void kfscmd(char *); 40219b2ee8SDavid du Colombier void mkdir(Dir*); 41219b2ee8SDavid du Colombier int mkfile(File*); 42219b2ee8SDavid du Colombier void mkfs(File*, int); 43219b2ee8SDavid du Colombier char* mkpath(char*, char*); 44219b2ee8SDavid du Colombier void mktree(File*, int); 45219b2ee8SDavid du Colombier void mountkfs(char*); 46219b2ee8SDavid du Colombier void printfile(File*); 47219b2ee8SDavid du Colombier void setnames(File*); 48219b2ee8SDavid du Colombier void setusers(void); 49219b2ee8SDavid du Colombier void skipdir(void); 50219b2ee8SDavid du Colombier char* strdup(char*); 51219b2ee8SDavid du Colombier int uptodate(Dir*, char*); 523e12c5d1SDavid du Colombier void usage(void); 53219b2ee8SDavid du Colombier void warn(char *, ...); 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier Biobuf *b; 563e12c5d1SDavid du Colombier Biobufhdr bout; /* stdout when writing archive */ 573e12c5d1SDavid du Colombier uchar boutbuf[2*LEN]; 583e12c5d1SDavid du Colombier char newfile[LEN]; 593e12c5d1SDavid du Colombier char oldfile[LEN]; 603e12c5d1SDavid du Colombier char *proto; 613e12c5d1SDavid du Colombier char *cputype; 623e12c5d1SDavid du Colombier char *users; 633e12c5d1SDavid du Colombier char *oldroot; 643e12c5d1SDavid du Colombier char *newroot; 653e12c5d1SDavid du Colombier char *prog = "mkfs"; 663e12c5d1SDavid du Colombier int lineno; 673e12c5d1SDavid du Colombier char *buf; 683e12c5d1SDavid du Colombier char *zbuf; 693e12c5d1SDavid du Colombier int buflen = 1024-8; 703e12c5d1SDavid du Colombier int indent; 713e12c5d1SDavid du Colombier int verb; 723e12c5d1SDavid du Colombier int modes; 733e12c5d1SDavid du Colombier int ream; 74219b2ee8SDavid du Colombier int debug; 753e12c5d1SDavid du Colombier int xflag; 763e12c5d1SDavid du Colombier int sfd; 773e12c5d1SDavid du Colombier int fskind; /* Kfs, Fs, Archive */ 78*9a747e4fSDavid du Colombier int setuid; /* on Fs: set uid and gid? */ 793e12c5d1SDavid du Colombier char *user; 803e12c5d1SDavid du Colombier 813e12c5d1SDavid du Colombier void 823e12c5d1SDavid du Colombier main(int argc, char **argv) 833e12c5d1SDavid du Colombier { 843e12c5d1SDavid du Colombier File file; 85*9a747e4fSDavid du Colombier char *name; 863e12c5d1SDavid du Colombier int i, errs; 873e12c5d1SDavid du Colombier 88*9a747e4fSDavid du Colombier quotefmtinstall(); 893e12c5d1SDavid du Colombier user = getuser(); 90*9a747e4fSDavid du Colombier name = ""; 913e12c5d1SDavid du Colombier memset(&file, 0, sizeof file); 923e12c5d1SDavid du Colombier file.new = ""; 933e12c5d1SDavid du Colombier file.old = 0; 943e12c5d1SDavid du Colombier oldroot = ""; 953e12c5d1SDavid du Colombier newroot = "/n/kfs"; 963e12c5d1SDavid du Colombier users = 0; 973e12c5d1SDavid du Colombier fskind = Kfs; 983e12c5d1SDavid du Colombier ARGBEGIN{ 993e12c5d1SDavid du Colombier case 'a': 1007dd7cddfSDavid du Colombier if(fskind != Kfs) { 1017dd7cddfSDavid du Colombier fprint(2, "cannot use -a with -d\n"); 1027dd7cddfSDavid du Colombier usage(); 1037dd7cddfSDavid du Colombier } 1043e12c5d1SDavid du Colombier fskind = Archive; 1053e12c5d1SDavid du Colombier newroot = ""; 1063e12c5d1SDavid du Colombier Binits(&bout, 1, OWRITE, boutbuf, sizeof boutbuf); 1073e12c5d1SDavid du Colombier break; 1083e12c5d1SDavid du Colombier case 'd': 1097dd7cddfSDavid du Colombier if(fskind != Kfs) { 1107dd7cddfSDavid du Colombier fprint(2, "cannot use -d with -a\n"); 1117dd7cddfSDavid du Colombier usage(); 1127dd7cddfSDavid du Colombier } 1133e12c5d1SDavid du Colombier fskind = Fs; 1143e12c5d1SDavid du Colombier newroot = ARGF(); 1153e12c5d1SDavid du Colombier break; 116219b2ee8SDavid du Colombier case 'D': 117219b2ee8SDavid du Colombier debug = 1; 118219b2ee8SDavid du Colombier break; 1193e12c5d1SDavid du Colombier case 'n': 120*9a747e4fSDavid du Colombier name = EARGF(usage()); 1213e12c5d1SDavid du Colombier break; 1223e12c5d1SDavid du Colombier case 'p': 1233e12c5d1SDavid du Colombier modes = 1; 1243e12c5d1SDavid du Colombier break; 1253e12c5d1SDavid du Colombier case 'r': 1263e12c5d1SDavid du Colombier ream = 1; 1273e12c5d1SDavid du Colombier break; 1283e12c5d1SDavid du Colombier case 's': 1293e12c5d1SDavid du Colombier oldroot = ARGF(); 1303e12c5d1SDavid du Colombier break; 1313e12c5d1SDavid du Colombier case 'u': 1323e12c5d1SDavid du Colombier users = ARGF(); 1333e12c5d1SDavid du Colombier break; 134*9a747e4fSDavid du Colombier case 'U': 135*9a747e4fSDavid du Colombier setuid = 1; 136*9a747e4fSDavid du Colombier break; 1373e12c5d1SDavid du Colombier case 'v': 1383e12c5d1SDavid du Colombier verb = 1; 1393e12c5d1SDavid du Colombier break; 1403e12c5d1SDavid du Colombier case 'x': 1413e12c5d1SDavid du Colombier xflag = 1; 1423e12c5d1SDavid du Colombier break; 1433e12c5d1SDavid du Colombier case 'z': 1443e12c5d1SDavid du Colombier buflen = atoi(ARGF())-8; 1453e12c5d1SDavid du Colombier break; 1463e12c5d1SDavid du Colombier default: 1473e12c5d1SDavid du Colombier usage(); 1483e12c5d1SDavid du Colombier }ARGEND 1493e12c5d1SDavid du Colombier 1503e12c5d1SDavid du Colombier if(!argc) 1513e12c5d1SDavid du Colombier usage(); 1523e12c5d1SDavid du Colombier 1533e12c5d1SDavid du Colombier buf = emalloc(buflen); 1543e12c5d1SDavid du Colombier zbuf = emalloc(buflen); 1553e12c5d1SDavid du Colombier memset(zbuf, 0, buflen); 1563e12c5d1SDavid du Colombier 1573e12c5d1SDavid du Colombier mountkfs(name); 1583e12c5d1SDavid du Colombier kfscmd("allow"); 1593e12c5d1SDavid du Colombier proto = "users"; 1603e12c5d1SDavid du Colombier setusers(); 1613e12c5d1SDavid du Colombier cputype = getenv("cputype"); 1623e12c5d1SDavid du Colombier if(cputype == 0) 1633e12c5d1SDavid du Colombier cputype = "68020"; 1643e12c5d1SDavid du Colombier 1653e12c5d1SDavid du Colombier errs = 0; 1663e12c5d1SDavid du Colombier for(i = 0; i < argc; i++){ 1673e12c5d1SDavid du Colombier proto = argv[i]; 168*9a747e4fSDavid du Colombier fprint(2, "processing %q\n", proto); 1693e12c5d1SDavid du Colombier 1703e12c5d1SDavid du Colombier b = Bopen(proto, OREAD); 1713e12c5d1SDavid du Colombier if(!b){ 172*9a747e4fSDavid du Colombier fprint(2, "%q: can't open %q: skipping\n", prog, proto); 1733e12c5d1SDavid du Colombier errs++; 1743e12c5d1SDavid du Colombier continue; 1753e12c5d1SDavid du Colombier } 1763e12c5d1SDavid du Colombier 1773e12c5d1SDavid du Colombier lineno = 0; 178219b2ee8SDavid du Colombier indent = 0; 1793e12c5d1SDavid du Colombier mkfs(&file, -1); 180219b2ee8SDavid du Colombier Bterm(b); 1813e12c5d1SDavid du Colombier } 1823e12c5d1SDavid du Colombier fprint(2, "file system made\n"); 1833e12c5d1SDavid du Colombier kfscmd("disallow"); 1843e12c5d1SDavid du Colombier kfscmd("sync"); 1853e12c5d1SDavid du Colombier if(errs) 1863e12c5d1SDavid du Colombier exits("skipped protos"); 1873e12c5d1SDavid du Colombier if(fskind == Archive){ 1883e12c5d1SDavid du Colombier Bprint(&bout, "end of archive\n"); 189219b2ee8SDavid du Colombier Bterm(&bout); 1903e12c5d1SDavid du Colombier } 1913e12c5d1SDavid du Colombier exits(0); 1923e12c5d1SDavid du Colombier } 1933e12c5d1SDavid du Colombier 1943e12c5d1SDavid du Colombier void 1953e12c5d1SDavid du Colombier mkfs(File *me, int level) 1963e12c5d1SDavid du Colombier { 1973e12c5d1SDavid du Colombier File *child; 1983e12c5d1SDavid du Colombier int rec; 1993e12c5d1SDavid du Colombier 2003e12c5d1SDavid du Colombier child = getfile(me); 2013e12c5d1SDavid du Colombier if(!child) 2023e12c5d1SDavid du Colombier return; 2033e12c5d1SDavid du Colombier if((child->elem[0] == '+' || child->elem[0] == '*') && child->elem[1] == '\0'){ 2043e12c5d1SDavid du Colombier rec = child->elem[0] == '+'; 2053e12c5d1SDavid du Colombier free(child->new); 2063e12c5d1SDavid du Colombier child->new = strdup(me->new); 2073e12c5d1SDavid du Colombier setnames(child); 2083e12c5d1SDavid du Colombier mktree(child, rec); 2093e12c5d1SDavid du Colombier freefile(child); 2103e12c5d1SDavid du Colombier child = getfile(me); 2113e12c5d1SDavid du Colombier } 2123e12c5d1SDavid du Colombier while(child && indent > level){ 2133e12c5d1SDavid du Colombier if(mkfile(child)) 2143e12c5d1SDavid du Colombier mkfs(child, indent); 2153e12c5d1SDavid du Colombier freefile(child); 2163e12c5d1SDavid du Colombier child = getfile(me); 2173e12c5d1SDavid du Colombier } 2183e12c5d1SDavid du Colombier if(child){ 2193e12c5d1SDavid du Colombier freefile(child); 2203e12c5d1SDavid du Colombier Bseek(b, -Blinelen(b), 1); 2213e12c5d1SDavid du Colombier lineno--; 2223e12c5d1SDavid du Colombier } 2233e12c5d1SDavid du Colombier } 2243e12c5d1SDavid du Colombier 2253e12c5d1SDavid du Colombier void 2263e12c5d1SDavid du Colombier mktree(File *me, int rec) 2273e12c5d1SDavid du Colombier { 2283e12c5d1SDavid du Colombier File child; 229*9a747e4fSDavid du Colombier Dir *d; 2303e12c5d1SDavid du Colombier int i, n, fd; 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier fd = open(oldfile, OREAD); 2333e12c5d1SDavid du Colombier if(fd < 0){ 234*9a747e4fSDavid du Colombier warn("can't open %q: %r", oldfile); 2353e12c5d1SDavid du Colombier return; 2363e12c5d1SDavid du Colombier } 2373e12c5d1SDavid du Colombier 2383e12c5d1SDavid du Colombier child = *me; 239*9a747e4fSDavid du Colombier while((n = dirread(fd, &d)) > 0){ 2403e12c5d1SDavid du Colombier for(i = 0; i < n; i++){ 2413e12c5d1SDavid du Colombier child.new = mkpath(me->new, d[i].name); 2423e12c5d1SDavid du Colombier if(me->old) 2433e12c5d1SDavid du Colombier child.old = mkpath(me->old, d[i].name); 2443e12c5d1SDavid du Colombier child.elem = d[i].name; 2453e12c5d1SDavid du Colombier setnames(&child); 2463e12c5d1SDavid du Colombier if(copyfile(&child, &d[i], 1) && rec) 2473e12c5d1SDavid du Colombier mktree(&child, rec); 2483e12c5d1SDavid du Colombier free(child.new); 2493e12c5d1SDavid du Colombier if(child.old) 2503e12c5d1SDavid du Colombier free(child.old); 2513e12c5d1SDavid du Colombier } 2523e12c5d1SDavid du Colombier } 2533e12c5d1SDavid du Colombier close(fd); 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier 2563e12c5d1SDavid du Colombier int 2573e12c5d1SDavid du Colombier mkfile(File *f) 2583e12c5d1SDavid du Colombier { 259*9a747e4fSDavid du Colombier Dir *dir; 2603e12c5d1SDavid du Colombier 261*9a747e4fSDavid du Colombier if((dir = dirstat(oldfile)) == nil){ 262*9a747e4fSDavid du Colombier warn("can't stat file %q: %r", oldfile); 263219b2ee8SDavid du Colombier skipdir(); 2643e12c5d1SDavid du Colombier return 0; 2653e12c5d1SDavid du Colombier } 266*9a747e4fSDavid du Colombier return copyfile(f, dir, 0); 2673e12c5d1SDavid du Colombier } 2683e12c5d1SDavid du Colombier 2693e12c5d1SDavid du Colombier int 2703e12c5d1SDavid du Colombier copyfile(File *f, Dir *d, int permonly) 2713e12c5d1SDavid du Colombier { 2723e12c5d1SDavid du Colombier ulong mode; 273*9a747e4fSDavid du Colombier Dir nd; 2743e12c5d1SDavid du Colombier 2753e12c5d1SDavid du Colombier if(xflag){ 276*9a747e4fSDavid du Colombier Bprint(&bout, "%q\t%ld\t%lld\n", f->new, d->mtime, d->length); 277*9a747e4fSDavid du Colombier return (d->mode & DMDIR) != 0; 2783e12c5d1SDavid du Colombier } 2797dd7cddfSDavid du Colombier if(verb && (fskind == Archive || ream)) 280*9a747e4fSDavid du Colombier fprint(2, "%q\n", f->new); 281*9a747e4fSDavid du Colombier d->name = f->elem; 2823e12c5d1SDavid du Colombier if(d->type != 'M'){ 283*9a747e4fSDavid du Colombier d->uid = "sys"; 284*9a747e4fSDavid du Colombier d->gid = "sys"; 2853e12c5d1SDavid du Colombier mode = (d->mode >> 6) & 7; 2863e12c5d1SDavid du Colombier d->mode |= mode | (mode << 3); 2873e12c5d1SDavid du Colombier } 2883e12c5d1SDavid du Colombier if(strcmp(f->uid, "-") != 0) 289*9a747e4fSDavid du Colombier d->uid = f->uid; 2903e12c5d1SDavid du Colombier if(strcmp(f->gid, "-") != 0) 291*9a747e4fSDavid du Colombier d->gid = f->gid; 292*9a747e4fSDavid du Colombier if(fskind == Fs && !setuid){ 293*9a747e4fSDavid du Colombier d->uid = ""; 294*9a747e4fSDavid du Colombier d->gid = ""; 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier if(f->mode != ~0){ 2973e12c5d1SDavid du Colombier if(permonly) 2983e12c5d1SDavid du Colombier d->mode = (d->mode & ~0666) | (f->mode & 0666); 299*9a747e4fSDavid du Colombier else if((d->mode&DMDIR) != (f->mode&DMDIR)) 300*9a747e4fSDavid du Colombier warn("inconsistent mode for %q", f->new); 3013e12c5d1SDavid du Colombier else 3023e12c5d1SDavid du Colombier d->mode = f->mode; 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier if(!uptodate(d, newfile)){ 3057dd7cddfSDavid du Colombier if(verb && (fskind != Archive && ream == 0)) 306*9a747e4fSDavid du Colombier fprint(2, "%q\n", f->new); 307*9a747e4fSDavid du Colombier if(d->mode & DMDIR) 3083e12c5d1SDavid du Colombier mkdir(d); 3093e12c5d1SDavid du Colombier else 3103e12c5d1SDavid du Colombier copy(d); 3117dd7cddfSDavid du Colombier }else if(modes){ 312*9a747e4fSDavid du Colombier nulldir(&nd); 313*9a747e4fSDavid du Colombier nd.mode = d->mode; 314*9a747e4fSDavid du Colombier nd.gid = d->gid; 315*9a747e4fSDavid du Colombier nd.mtime = d->mtime; 3167dd7cddfSDavid du Colombier if(verb && (fskind != Archive && ream == 0)) 317*9a747e4fSDavid du Colombier fprint(2, "%q\n", f->new); 318*9a747e4fSDavid du Colombier if(dirwstat(newfile, &nd) < 0) 319*9a747e4fSDavid du Colombier warn("can't set modes for %q: %r", f->new); 320*9a747e4fSDavid du Colombier nulldir(&nd); 321*9a747e4fSDavid du Colombier nd.uid = d->uid; 322*9a747e4fSDavid du Colombier dirwstat(newfile, &nd); 3237dd7cddfSDavid du Colombier } 324*9a747e4fSDavid du Colombier return (d->mode & DMDIR) != 0; 3253e12c5d1SDavid du Colombier } 3263e12c5d1SDavid du Colombier 3273e12c5d1SDavid du Colombier /* 3283e12c5d1SDavid du Colombier * check if file to is up to date with 3293e12c5d1SDavid du Colombier * respect to the file represented by df 3303e12c5d1SDavid du Colombier */ 3313e12c5d1SDavid du Colombier int 3323e12c5d1SDavid du Colombier uptodate(Dir *df, char *to) 3333e12c5d1SDavid du Colombier { 334*9a747e4fSDavid du Colombier int ret; 335*9a747e4fSDavid du Colombier Dir *dt; 3363e12c5d1SDavid du Colombier 337*9a747e4fSDavid du Colombier if(fskind == Archive || ream || (dt = dirstat(to)) == nil) 3383e12c5d1SDavid du Colombier return 0; 339*9a747e4fSDavid du Colombier ret = dt->mtime >= df->mtime; 340*9a747e4fSDavid du Colombier free(dt); 341*9a747e4fSDavid du Colombier return ret; 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier 3443e12c5d1SDavid du Colombier void 3453e12c5d1SDavid du Colombier copy(Dir *d) 3463e12c5d1SDavid du Colombier { 3473e12c5d1SDavid du Colombier char cptmp[LEN], *p; 3483e12c5d1SDavid du Colombier long tot; 349*9a747e4fSDavid du Colombier int f, t, n, needwrite; 350*9a747e4fSDavid du Colombier Dir nd; 3513e12c5d1SDavid du Colombier 3523e12c5d1SDavid du Colombier f = open(oldfile, OREAD); 3533e12c5d1SDavid du Colombier if(f < 0){ 354*9a747e4fSDavid du Colombier warn("can't open %q: %r", oldfile); 3553e12c5d1SDavid du Colombier return; 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier t = -1; 3583e12c5d1SDavid du Colombier if(fskind == Archive) 3593e12c5d1SDavid du Colombier arch(d); 3603e12c5d1SDavid du Colombier else{ 3613e12c5d1SDavid du Colombier strcpy(cptmp, newfile); 3623e12c5d1SDavid du Colombier p = utfrrune(cptmp, L'/'); 3633e12c5d1SDavid du Colombier if(!p) 3643e12c5d1SDavid du Colombier error("internal temporary file error"); 3653e12c5d1SDavid du Colombier strcpy(p+1, "__mkfstmp"); 3663e12c5d1SDavid du Colombier t = create(cptmp, OWRITE, 0666); 3673e12c5d1SDavid du Colombier if(t < 0){ 368*9a747e4fSDavid du Colombier warn("can't create %q: %r", newfile); 3693e12c5d1SDavid du Colombier close(f); 3703e12c5d1SDavid du Colombier return; 3713e12c5d1SDavid du Colombier } 3723e12c5d1SDavid du Colombier } 3733e12c5d1SDavid du Colombier 374*9a747e4fSDavid du Colombier needwrite = 0; 3753e12c5d1SDavid du Colombier for(tot = 0;; tot += n){ 3763e12c5d1SDavid du Colombier n = read(f, buf, buflen); 3773e12c5d1SDavid du Colombier if(n < 0){ 378*9a747e4fSDavid du Colombier warn("can't read %q: %r", oldfile); 3793e12c5d1SDavid du Colombier break; 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier if(n == 0) 3823e12c5d1SDavid du Colombier break; 3833e12c5d1SDavid du Colombier if(fskind == Archive){ 3843e12c5d1SDavid du Colombier if(Bwrite(&bout, buf, n) != n) 3853e12c5d1SDavid du Colombier error("write error: %r"); 386*9a747e4fSDavid du Colombier }else if(memcmp(buf, zbuf, n) == 0){ 387*9a747e4fSDavid du Colombier if(seek(t, n, 1) < 0) 388*9a747e4fSDavid du Colombier error("can't write zeros to %q: %r", newfile); 389*9a747e4fSDavid du Colombier needwrite = 1; 390*9a747e4fSDavid du Colombier }else{ 391*9a747e4fSDavid du Colombier if(write(t, buf, n) < n) 392*9a747e4fSDavid du Colombier error("can't write %q: %r", newfile); 393*9a747e4fSDavid du Colombier needwrite = 0; 394*9a747e4fSDavid du Colombier } 3953e12c5d1SDavid du Colombier } 3963e12c5d1SDavid du Colombier close(f); 397*9a747e4fSDavid du Colombier if(needwrite){ 398*9a747e4fSDavid du Colombier if(seek(t, -1, 1) < 0 || write(t, zbuf, 1) != 1) 399*9a747e4fSDavid du Colombier error("can't write zero at end of %q: %r", newfile); 400*9a747e4fSDavid du Colombier } 4013e12c5d1SDavid du Colombier if(tot != d->length){ 402*9a747e4fSDavid du Colombier warn("wrong number bytes written to %q (was %d should be %d)\n", 4033e12c5d1SDavid du Colombier newfile, tot, d->length); 4043e12c5d1SDavid du Colombier if(fskind == Archive){ 4053e12c5d1SDavid du Colombier warn("seeking to proper position\n"); 4063e12c5d1SDavid du Colombier Bseek(&bout, d->length - tot, 1); 4073e12c5d1SDavid du Colombier } 4083e12c5d1SDavid du Colombier } 4093e12c5d1SDavid du Colombier if(fskind == Archive) 4103e12c5d1SDavid du Colombier return; 4113e12c5d1SDavid du Colombier remove(newfile); 412*9a747e4fSDavid du Colombier nulldir(&nd); 413*9a747e4fSDavid du Colombier nd.mode = d->mode; 414*9a747e4fSDavid du Colombier nd.gid = d->gid; 415*9a747e4fSDavid du Colombier nd.mtime = d->mtime; 416*9a747e4fSDavid du Colombier nd.name = d->name; 417*9a747e4fSDavid du Colombier if(dirfwstat(t, &nd) < 0) 418*9a747e4fSDavid du Colombier error("can't move tmp file to %q: %r", newfile); 419*9a747e4fSDavid du Colombier nulldir(&nd); 420*9a747e4fSDavid du Colombier nd.uid = d->uid; 421*9a747e4fSDavid du Colombier dirfwstat(t, &nd); 4223e12c5d1SDavid du Colombier close(t); 4233e12c5d1SDavid du Colombier } 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier void 4263e12c5d1SDavid du Colombier mkdir(Dir *d) 4273e12c5d1SDavid du Colombier { 428*9a747e4fSDavid du Colombier Dir *d1; 429*9a747e4fSDavid du Colombier Dir nd; 4303e12c5d1SDavid du Colombier int fd; 4313e12c5d1SDavid du Colombier 4323e12c5d1SDavid du Colombier if(fskind == Archive){ 4333e12c5d1SDavid du Colombier arch(d); 4343e12c5d1SDavid du Colombier return; 4353e12c5d1SDavid du Colombier } 4363e12c5d1SDavid du Colombier fd = create(newfile, OREAD, d->mode); 437*9a747e4fSDavid du Colombier nulldir(&nd); 438*9a747e4fSDavid du Colombier nd.mode = d->mode; 439*9a747e4fSDavid du Colombier nd.gid = d->gid; 440*9a747e4fSDavid du Colombier nd.mtime = d->mtime; 4413e12c5d1SDavid du Colombier if(fd < 0){ 442*9a747e4fSDavid du Colombier if((d1 = dirstat(newfile)) == nil || !(d1->mode & DMDIR)){ 443*9a747e4fSDavid du Colombier free(d1); 444*9a747e4fSDavid du Colombier error("can't create %q", newfile); 445*9a747e4fSDavid du Colombier } 446*9a747e4fSDavid du Colombier free(d1); 447*9a747e4fSDavid du Colombier if(dirwstat(newfile, &nd) < 0) 448*9a747e4fSDavid du Colombier warn("can't set modes for %q: %r", newfile); 449*9a747e4fSDavid du Colombier nulldir(&nd); 450*9a747e4fSDavid du Colombier nd.uid = d->uid; 451*9a747e4fSDavid du Colombier dirwstat(newfile, &nd); 4523e12c5d1SDavid du Colombier return; 4533e12c5d1SDavid du Colombier } 454*9a747e4fSDavid du Colombier if(dirfwstat(fd, &nd) < 0) 455*9a747e4fSDavid du Colombier warn("can't set modes for %q: %r", newfile); 456*9a747e4fSDavid du Colombier nulldir(&nd); 457*9a747e4fSDavid du Colombier nd.uid = d->uid; 458*9a747e4fSDavid du Colombier dirfwstat(fd, &nd); 4593e12c5d1SDavid du Colombier close(fd); 4603e12c5d1SDavid du Colombier } 4613e12c5d1SDavid du Colombier 4623e12c5d1SDavid du Colombier void 4633e12c5d1SDavid du Colombier arch(Dir *d) 4643e12c5d1SDavid du Colombier { 465*9a747e4fSDavid du Colombier Bprint(&bout, "%q %luo %q %q %lud %lld\n", 466219b2ee8SDavid du Colombier newfile, d->mode, d->uid, d->gid, d->mtime, d->length); 4673e12c5d1SDavid du Colombier } 4683e12c5d1SDavid du Colombier 4693e12c5d1SDavid du Colombier char * 4703e12c5d1SDavid du Colombier mkpath(char *prefix, char *elem) 4713e12c5d1SDavid du Colombier { 4723e12c5d1SDavid du Colombier char *p; 4733e12c5d1SDavid du Colombier int n; 4743e12c5d1SDavid du Colombier 4753e12c5d1SDavid du Colombier n = strlen(prefix) + strlen(elem) + 2; 4763e12c5d1SDavid du Colombier p = emalloc(n); 4773e12c5d1SDavid du Colombier sprint(p, "%s/%s", prefix, elem); 4783e12c5d1SDavid du Colombier return p; 4793e12c5d1SDavid du Colombier } 4803e12c5d1SDavid du Colombier 4813e12c5d1SDavid du Colombier char * 4823e12c5d1SDavid du Colombier strdup(char *s) 4833e12c5d1SDavid du Colombier { 4843e12c5d1SDavid du Colombier char *t; 4853e12c5d1SDavid du Colombier 4863e12c5d1SDavid du Colombier t = emalloc(strlen(s) + 1); 4873e12c5d1SDavid du Colombier return strcpy(t, s); 4883e12c5d1SDavid du Colombier } 4893e12c5d1SDavid du Colombier 4903e12c5d1SDavid du Colombier void 4913e12c5d1SDavid du Colombier setnames(File *f) 4923e12c5d1SDavid du Colombier { 4933e12c5d1SDavid du Colombier sprint(newfile, "%s%s", newroot, f->new); 4943e12c5d1SDavid du Colombier if(f->old){ 4953e12c5d1SDavid du Colombier if(f->old[0] == '/') 4963e12c5d1SDavid du Colombier sprint(oldfile, "%s%s", oldroot, f->old); 4973e12c5d1SDavid du Colombier else 4983e12c5d1SDavid du Colombier strcpy(oldfile, f->old); 4993e12c5d1SDavid du Colombier }else 5003e12c5d1SDavid du Colombier sprint(oldfile, "%s%s", oldroot, f->new); 5013e12c5d1SDavid du Colombier if(strlen(newfile) >= sizeof newfile 5023e12c5d1SDavid du Colombier || strlen(oldfile) >= sizeof oldfile) 5033e12c5d1SDavid du Colombier error("name overfile"); 5043e12c5d1SDavid du Colombier } 5053e12c5d1SDavid du Colombier 5063e12c5d1SDavid du Colombier void 5073e12c5d1SDavid du Colombier freefile(File *f) 5083e12c5d1SDavid du Colombier { 5093e12c5d1SDavid du Colombier if(f->old) 5103e12c5d1SDavid du Colombier free(f->old); 5113e12c5d1SDavid du Colombier if(f->new) 5123e12c5d1SDavid du Colombier free(f->new); 5133e12c5d1SDavid du Colombier free(f); 5143e12c5d1SDavid du Colombier } 5153e12c5d1SDavid du Colombier 516219b2ee8SDavid du Colombier /* 517219b2ee8SDavid du Colombier * skip all files in the proto that 518219b2ee8SDavid du Colombier * could be in the current dir 519219b2ee8SDavid du Colombier */ 520219b2ee8SDavid du Colombier void 521219b2ee8SDavid du Colombier skipdir(void) 522219b2ee8SDavid du Colombier { 523219b2ee8SDavid du Colombier char *p, c; 524219b2ee8SDavid du Colombier int level; 525219b2ee8SDavid du Colombier 526219b2ee8SDavid du Colombier if(indent < 0) 527219b2ee8SDavid du Colombier return; 528219b2ee8SDavid du Colombier level = indent; 529219b2ee8SDavid du Colombier for(;;){ 530219b2ee8SDavid du Colombier indent = 0; 531219b2ee8SDavid du Colombier p = Brdline(b, '\n'); 532219b2ee8SDavid du Colombier lineno++; 533219b2ee8SDavid du Colombier if(!p){ 534219b2ee8SDavid du Colombier indent = -1; 535219b2ee8SDavid du Colombier return; 536219b2ee8SDavid du Colombier } 537219b2ee8SDavid du Colombier while((c = *p++) != '\n') 538219b2ee8SDavid du Colombier if(c == ' ') 539219b2ee8SDavid du Colombier indent++; 540219b2ee8SDavid du Colombier else if(c == '\t') 541219b2ee8SDavid du Colombier indent += 8; 542219b2ee8SDavid du Colombier else 543219b2ee8SDavid du Colombier break; 544219b2ee8SDavid du Colombier if(indent <= level){ 545219b2ee8SDavid du Colombier Bseek(b, -Blinelen(b), 1); 546219b2ee8SDavid du Colombier lineno--; 547219b2ee8SDavid du Colombier return; 548219b2ee8SDavid du Colombier } 549219b2ee8SDavid du Colombier } 550219b2ee8SDavid du Colombier } 551219b2ee8SDavid du Colombier 5523e12c5d1SDavid du Colombier File* 5533e12c5d1SDavid du Colombier getfile(File *old) 5543e12c5d1SDavid du Colombier { 5553e12c5d1SDavid du Colombier File *f; 556*9a747e4fSDavid du Colombier char *elem; 5573e12c5d1SDavid du Colombier char *p; 5583e12c5d1SDavid du Colombier int c; 5593e12c5d1SDavid du Colombier 560219b2ee8SDavid du Colombier if(indent < 0) 561219b2ee8SDavid du Colombier return 0; 5623e12c5d1SDavid du Colombier loop: 5633e12c5d1SDavid du Colombier indent = 0; 5643e12c5d1SDavid du Colombier p = Brdline(b, '\n'); 5653e12c5d1SDavid du Colombier lineno++; 5663e12c5d1SDavid du Colombier if(!p){ 5673e12c5d1SDavid du Colombier indent = -1; 5683e12c5d1SDavid du Colombier return 0; 5693e12c5d1SDavid du Colombier } 570219b2ee8SDavid du Colombier while((c = *p++) != '\n') 5713e12c5d1SDavid du Colombier if(c == ' ') 5723e12c5d1SDavid du Colombier indent++; 5733e12c5d1SDavid du Colombier else if(c == '\t') 5743e12c5d1SDavid du Colombier indent += 8; 5753e12c5d1SDavid du Colombier else 5763e12c5d1SDavid du Colombier break; 577219b2ee8SDavid du Colombier if(c == '\n' || c == '#') 5783e12c5d1SDavid du Colombier goto loop; 5793e12c5d1SDavid du Colombier p--; 5803e12c5d1SDavid du Colombier f = emalloc(sizeof *f); 581*9a747e4fSDavid du Colombier p = getname(p, &elem); 582219b2ee8SDavid du Colombier if(debug) 583*9a747e4fSDavid du Colombier fprint(2, "getfile: %q root %q\n", elem, old->new); 5843e12c5d1SDavid du Colombier f->new = mkpath(old->new, elem); 5853e12c5d1SDavid du Colombier f->elem = utfrrune(f->new, L'/') + 1; 5863e12c5d1SDavid du Colombier p = getmode(p, &f->mode); 587*9a747e4fSDavid du Colombier p = getname(p, &f->uid); 5883e12c5d1SDavid du Colombier if(!*f->uid) 589*9a747e4fSDavid du Colombier f->uid = "-"; 590*9a747e4fSDavid du Colombier p = getname(p, &f->gid); 5913e12c5d1SDavid du Colombier if(!*f->gid) 592*9a747e4fSDavid du Colombier f->gid = "-"; 5933e12c5d1SDavid du Colombier f->old = getpath(p); 5943e12c5d1SDavid du Colombier if(f->old && strcmp(f->old, "-") == 0){ 5953e12c5d1SDavid du Colombier free(f->old); 5963e12c5d1SDavid du Colombier f->old = 0; 5973e12c5d1SDavid du Colombier } 5983e12c5d1SDavid du Colombier setnames(f); 599219b2ee8SDavid du Colombier 600219b2ee8SDavid du Colombier if(debug) 601219b2ee8SDavid du Colombier printfile(f); 602219b2ee8SDavid du Colombier 6033e12c5d1SDavid du Colombier return f; 6043e12c5d1SDavid du Colombier } 6053e12c5d1SDavid du Colombier 6063e12c5d1SDavid du Colombier char* 6073e12c5d1SDavid du Colombier getpath(char *p) 6083e12c5d1SDavid du Colombier { 609219b2ee8SDavid du Colombier char *q, *new; 610219b2ee8SDavid du Colombier int c, n; 6113e12c5d1SDavid du Colombier 6123e12c5d1SDavid du Colombier while((c = *p) == ' ' || c == '\t') 6133e12c5d1SDavid du Colombier p++; 6143e12c5d1SDavid du Colombier q = p; 615219b2ee8SDavid du Colombier while((c = *q) != '\n' && c != ' ' && c != '\t') 6163e12c5d1SDavid du Colombier q++; 617219b2ee8SDavid du Colombier if(q == p) 6183e12c5d1SDavid du Colombier return 0; 619219b2ee8SDavid du Colombier n = q - p; 620219b2ee8SDavid du Colombier new = emalloc(n + 1); 621219b2ee8SDavid du Colombier memcpy(new, p, n); 622219b2ee8SDavid du Colombier new[n] = 0; 623219b2ee8SDavid du Colombier return new; 6243e12c5d1SDavid du Colombier } 6253e12c5d1SDavid du Colombier 6263e12c5d1SDavid du Colombier char* 627*9a747e4fSDavid du Colombier getname(char *p, char **buf) 6283e12c5d1SDavid du Colombier { 629*9a747e4fSDavid du Colombier char *s, *start; 630*9a747e4fSDavid du Colombier int c; 6313e12c5d1SDavid du Colombier 6323e12c5d1SDavid du Colombier while((c = *p) == ' ' || c == '\t') 6333e12c5d1SDavid du Colombier p++; 6343e12c5d1SDavid du Colombier 635*9a747e4fSDavid du Colombier start = p; 636*9a747e4fSDavid du Colombier while((c = *p) != '\n' && c != ' ' && c != '\t' && c != '\0') 637*9a747e4fSDavid du Colombier p++; 638*9a747e4fSDavid du Colombier 639*9a747e4fSDavid du Colombier *buf = malloc(p+1-start); 640*9a747e4fSDavid du Colombier if(*buf == nil) 641*9a747e4fSDavid du Colombier return nil; 642*9a747e4fSDavid du Colombier memmove(*buf, start, p-start); 643*9a747e4fSDavid du Colombier (*buf)[p-start] = '\0'; 644*9a747e4fSDavid du Colombier 645*9a747e4fSDavid du Colombier if(**buf == '$'){ 646*9a747e4fSDavid du Colombier s = getenv(*buf+1); 647*9a747e4fSDavid du Colombier if(s == 0){ 648*9a747e4fSDavid du Colombier warn("can't read environment variable %q", *buf+1); 649*9a747e4fSDavid du Colombier skipdir(); 650*9a747e4fSDavid du Colombier free(*buf); 651*9a747e4fSDavid du Colombier return nil; 652*9a747e4fSDavid du Colombier } 653*9a747e4fSDavid du Colombier free(*buf); 654*9a747e4fSDavid du Colombier *buf = s; 6553e12c5d1SDavid du Colombier } 6563e12c5d1SDavid du Colombier return p; 6573e12c5d1SDavid du Colombier } 6583e12c5d1SDavid du Colombier 6593e12c5d1SDavid du Colombier char* 660*9a747e4fSDavid du Colombier getmode(char *p, ulong *xmode) 6613e12c5d1SDavid du Colombier { 662*9a747e4fSDavid du Colombier char *buf, *s; 6633e12c5d1SDavid du Colombier ulong m; 6643e12c5d1SDavid du Colombier 665*9a747e4fSDavid du Colombier *xmode = ~0; 666*9a747e4fSDavid du Colombier p = getname(p, &buf); 667*9a747e4fSDavid du Colombier if(p == nil) 668*9a747e4fSDavid du Colombier return nil; 669*9a747e4fSDavid du Colombier 6703e12c5d1SDavid du Colombier s = buf; 6713e12c5d1SDavid du Colombier if(!*s || strcmp(s, "-") == 0) 6723e12c5d1SDavid du Colombier return p; 6733e12c5d1SDavid du Colombier m = 0; 6743e12c5d1SDavid du Colombier if(*s == 'd'){ 675*9a747e4fSDavid du Colombier m |= DMDIR; 6763e12c5d1SDavid du Colombier s++; 6773e12c5d1SDavid du Colombier } 6783e12c5d1SDavid du Colombier if(*s == 'a'){ 679*9a747e4fSDavid du Colombier m |= DMAPPEND; 6803e12c5d1SDavid du Colombier s++; 6813e12c5d1SDavid du Colombier } 6823e12c5d1SDavid du Colombier if(*s == 'l'){ 683*9a747e4fSDavid du Colombier m |= DMEXCL; 6843e12c5d1SDavid du Colombier s++; 6853e12c5d1SDavid du Colombier } 6863e12c5d1SDavid du Colombier if(s[0] < '0' || s[0] > '7' 6873e12c5d1SDavid du Colombier || s[1] < '0' || s[1] > '7' 6883e12c5d1SDavid du Colombier || s[2] < '0' || s[2] > '7' 6893e12c5d1SDavid du Colombier || s[3]){ 690*9a747e4fSDavid du Colombier warn("bad mode specification %q", buf); 691*9a747e4fSDavid du Colombier free(buf); 6923e12c5d1SDavid du Colombier return p; 6933e12c5d1SDavid du Colombier } 694*9a747e4fSDavid du Colombier *xmode = m | strtoul(s, 0, 8); 695*9a747e4fSDavid du Colombier free(buf); 6963e12c5d1SDavid du Colombier return p; 6973e12c5d1SDavid du Colombier } 6983e12c5d1SDavid du Colombier 6993e12c5d1SDavid du Colombier void 7003e12c5d1SDavid du Colombier setusers(void) 7013e12c5d1SDavid du Colombier { 7023e12c5d1SDavid du Colombier File file; 7033e12c5d1SDavid du Colombier int m; 7043e12c5d1SDavid du Colombier 7053e12c5d1SDavid du Colombier if(fskind != Kfs) 7063e12c5d1SDavid du Colombier return; 7073e12c5d1SDavid du Colombier m = modes; 7083e12c5d1SDavid du Colombier modes = 1; 709*9a747e4fSDavid du Colombier file.uid = "adm"; 710*9a747e4fSDavid du Colombier file.gid = "adm"; 711*9a747e4fSDavid du Colombier file.mode = DMDIR|0775; 7123e12c5d1SDavid du Colombier file.new = "/adm"; 7133e12c5d1SDavid du Colombier file.elem = "adm"; 7143e12c5d1SDavid du Colombier file.old = 0; 7153e12c5d1SDavid du Colombier setnames(&file); 7163e12c5d1SDavid du Colombier mkfile(&file); 7173e12c5d1SDavid du Colombier file.new = "/adm/users"; 7183e12c5d1SDavid du Colombier file.old = users; 7193e12c5d1SDavid du Colombier file.elem = "users"; 7203e12c5d1SDavid du Colombier file.mode = 0664; 7213e12c5d1SDavid du Colombier setnames(&file); 7223e12c5d1SDavid du Colombier mkfile(&file); 7233e12c5d1SDavid du Colombier kfscmd("user"); 7243e12c5d1SDavid du Colombier mkfile(&file); 725*9a747e4fSDavid du Colombier file.mode = DMDIR|0775; 7263e12c5d1SDavid du Colombier file.new = "/adm"; 7273e12c5d1SDavid du Colombier file.old = "/adm"; 7283e12c5d1SDavid du Colombier file.elem = "adm"; 7293e12c5d1SDavid du Colombier setnames(&file); 7303e12c5d1SDavid du Colombier mkfile(&file); 7313e12c5d1SDavid du Colombier modes = m; 7323e12c5d1SDavid du Colombier } 7333e12c5d1SDavid du Colombier 7343e12c5d1SDavid du Colombier void 7353e12c5d1SDavid du Colombier mountkfs(char *name) 7363e12c5d1SDavid du Colombier { 737*9a747e4fSDavid du Colombier char kname[64]; 7383e12c5d1SDavid du Colombier 7393e12c5d1SDavid du Colombier if(fskind != Kfs) 7403e12c5d1SDavid du Colombier return; 7413e12c5d1SDavid du Colombier if(name[0]) 742*9a747e4fSDavid du Colombier snprint(kname, sizeof kname, "/srv/kfs.%s", name); 7433e12c5d1SDavid du Colombier else 7443e12c5d1SDavid du Colombier strcpy(kname, "/srv/kfs"); 7453e12c5d1SDavid du Colombier sfd = open(kname, ORDWR); 7463e12c5d1SDavid du Colombier if(sfd < 0){ 747*9a747e4fSDavid du Colombier fprint(2, "can't open %q\n", kname); 7483e12c5d1SDavid du Colombier exits("open /srv/kfs"); 7493e12c5d1SDavid du Colombier } 750*9a747e4fSDavid du Colombier if(mount(sfd, -1, "/n/kfs", MREPL|MCREATE, "") < 0){ 7513e12c5d1SDavid du Colombier fprint(2, "can't mount kfs on /n/kfs\n"); 7523e12c5d1SDavid du Colombier exits("mount kfs"); 7533e12c5d1SDavid du Colombier } 7543e12c5d1SDavid du Colombier close(sfd); 7553e12c5d1SDavid du Colombier strcat(kname, ".cmd"); 7563e12c5d1SDavid du Colombier sfd = open(kname, ORDWR); 7573e12c5d1SDavid du Colombier if(sfd < 0){ 758*9a747e4fSDavid du Colombier fprint(2, "can't open %q\n", kname); 7593e12c5d1SDavid du Colombier exits("open /srv/kfs"); 7603e12c5d1SDavid du Colombier } 7613e12c5d1SDavid du Colombier } 7623e12c5d1SDavid du Colombier 7633e12c5d1SDavid du Colombier void 7643e12c5d1SDavid du Colombier kfscmd(char *cmd) 7653e12c5d1SDavid du Colombier { 7663e12c5d1SDavid du Colombier char buf[4*1024]; 7673e12c5d1SDavid du Colombier int n; 7683e12c5d1SDavid du Colombier 7693e12c5d1SDavid du Colombier if(fskind != Kfs) 7703e12c5d1SDavid du Colombier return; 7713e12c5d1SDavid du Colombier if(write(sfd, cmd, strlen(cmd)) != strlen(cmd)){ 772*9a747e4fSDavid du Colombier fprint(2, "%q: error writing %q: %r", prog, cmd); 7733e12c5d1SDavid du Colombier return; 7743e12c5d1SDavid du Colombier } 7753e12c5d1SDavid du Colombier for(;;){ 7763e12c5d1SDavid du Colombier n = read(sfd, buf, sizeof buf - 1); 7773e12c5d1SDavid du Colombier if(n <= 0) 7783e12c5d1SDavid du Colombier return; 7793e12c5d1SDavid du Colombier buf[n] = '\0'; 7803e12c5d1SDavid du Colombier if(strcmp(buf, "done") == 0 || strcmp(buf, "success") == 0) 7813e12c5d1SDavid du Colombier return; 7823e12c5d1SDavid du Colombier if(strcmp(buf, "unknown command") == 0){ 783*9a747e4fSDavid du Colombier fprint(2, "%q: command %q not recognized\n", prog, cmd); 7843e12c5d1SDavid du Colombier return; 7853e12c5d1SDavid du Colombier } 7863e12c5d1SDavid du Colombier } 7873e12c5d1SDavid du Colombier } 7883e12c5d1SDavid du Colombier 7893e12c5d1SDavid du Colombier void * 7903e12c5d1SDavid du Colombier emalloc(ulong n) 7913e12c5d1SDavid du Colombier { 7923e12c5d1SDavid du Colombier void *p; 7933e12c5d1SDavid du Colombier 7943e12c5d1SDavid du Colombier if((p = malloc(n)) == 0) 7953e12c5d1SDavid du Colombier error("out of memory"); 7963e12c5d1SDavid du Colombier return p; 7973e12c5d1SDavid du Colombier } 7983e12c5d1SDavid du Colombier 7993e12c5d1SDavid du Colombier void 8003e12c5d1SDavid du Colombier error(char *fmt, ...) 8013e12c5d1SDavid du Colombier { 8023e12c5d1SDavid du Colombier char buf[1024]; 8037dd7cddfSDavid du Colombier va_list arg; 8043e12c5d1SDavid du Colombier 805*9a747e4fSDavid du Colombier sprint(buf, "%q: %q:%d: ", prog, proto, lineno); 8067dd7cddfSDavid du Colombier va_start(arg, fmt); 807*9a747e4fSDavid du Colombier vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg); 8087dd7cddfSDavid du Colombier va_end(arg); 8093e12c5d1SDavid du Colombier fprint(2, "%s\n", buf); 8103e12c5d1SDavid du Colombier kfscmd("disallow"); 8113e12c5d1SDavid du Colombier kfscmd("sync"); 8123e12c5d1SDavid du Colombier exits(0); 8133e12c5d1SDavid du Colombier } 8143e12c5d1SDavid du Colombier 8153e12c5d1SDavid du Colombier void 8163e12c5d1SDavid du Colombier warn(char *fmt, ...) 8173e12c5d1SDavid du Colombier { 8183e12c5d1SDavid du Colombier char buf[1024]; 8197dd7cddfSDavid du Colombier va_list arg; 8203e12c5d1SDavid du Colombier 821*9a747e4fSDavid du Colombier sprint(buf, "%q: %q:%d: ", prog, proto, lineno); 8227dd7cddfSDavid du Colombier va_start(arg, fmt); 823*9a747e4fSDavid du Colombier vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg); 8247dd7cddfSDavid du Colombier va_end(arg); 8253e12c5d1SDavid du Colombier fprint(2, "%s\n", buf); 8263e12c5d1SDavid du Colombier } 8273e12c5d1SDavid du Colombier 8283e12c5d1SDavid du Colombier void 829219b2ee8SDavid du Colombier printfile(File *f) 830219b2ee8SDavid du Colombier { 831219b2ee8SDavid du Colombier if(f->old) 832*9a747e4fSDavid du Colombier fprint(2, "%q from %q %q %q %lo\n", f->new, f->old, f->uid, f->gid, f->mode); 833219b2ee8SDavid du Colombier else 834*9a747e4fSDavid du Colombier fprint(2, "%q %q %q %lo\n", f->new, f->uid, f->gid, f->mode); 835219b2ee8SDavid du Colombier } 836219b2ee8SDavid du Colombier 837219b2ee8SDavid du Colombier void 8383e12c5d1SDavid du Colombier usage(void) 8393e12c5d1SDavid du Colombier { 840*9a747e4fSDavid du Colombier fprint(2, "usage: %q [-aprvx] [-d root] [-n name] [-s source] [-u users] [-z n] proto ...\n", prog); 8413e12c5d1SDavid du Colombier exits("usage"); 8423e12c5d1SDavid du Colombier } 843