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;
249a747e4fSDavid du Colombier char *uid;
259a747e4fSDavid 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*);
379a747e4fSDavid 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 */
789a747e4fSDavid du Colombier int setuid; /* on Fs: set uid and gid? */
793e12c5d1SDavid du Colombier char *user;
803e12c5d1SDavid du Colombier
813e12c5d1SDavid du Colombier void
main(int argc,char ** argv)823e12c5d1SDavid du Colombier main(int argc, char **argv)
833e12c5d1SDavid du Colombier {
843e12c5d1SDavid du Colombier File file;
859a747e4fSDavid du Colombier char *name;
863e12c5d1SDavid du Colombier int i, errs;
873e12c5d1SDavid du Colombier
889a747e4fSDavid du Colombier quotefmtinstall();
893e12c5d1SDavid du Colombier user = getuser();
909a747e4fSDavid 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':
1209a747e4fSDavid 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;
1349a747e4fSDavid du Colombier case 'U':
1359a747e4fSDavid du Colombier setuid = 1;
1369a747e4fSDavid 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];
1689a747e4fSDavid du Colombier fprint(2, "processing %q\n", proto);
1693e12c5d1SDavid du Colombier
1703e12c5d1SDavid du Colombier b = Bopen(proto, OREAD);
1713e12c5d1SDavid du Colombier if(!b){
1729a747e4fSDavid 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
mkfs(File * me,int level)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
mktree(File * me,int rec)2263e12c5d1SDavid du Colombier mktree(File *me, int rec)
2273e12c5d1SDavid du Colombier {
2283e12c5d1SDavid du Colombier File child;
2299a747e4fSDavid 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){
2349a747e4fSDavid du Colombier warn("can't open %q: %r", oldfile);
2353e12c5d1SDavid du Colombier return;
2363e12c5d1SDavid du Colombier }
2373e12c5d1SDavid du Colombier
2383e12c5d1SDavid du Colombier child = *me;
2399a747e4fSDavid 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
mkfile(File * f)2573e12c5d1SDavid du Colombier mkfile(File *f)
2583e12c5d1SDavid du Colombier {
2599a747e4fSDavid du Colombier Dir *dir;
2603e12c5d1SDavid du Colombier
2619a747e4fSDavid du Colombier if((dir = dirstat(oldfile)) == nil){
2629a747e4fSDavid du Colombier warn("can't stat file %q: %r", oldfile);
263219b2ee8SDavid du Colombier skipdir();
2643e12c5d1SDavid du Colombier return 0;
2653e12c5d1SDavid du Colombier }
2669a747e4fSDavid du Colombier return copyfile(f, dir, 0);
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier
2693e12c5d1SDavid du Colombier int
copyfile(File * f,Dir * d,int permonly)2703e12c5d1SDavid du Colombier copyfile(File *f, Dir *d, int permonly)
2713e12c5d1SDavid du Colombier {
2723e12c5d1SDavid du Colombier ulong mode;
2739a747e4fSDavid du Colombier Dir nd;
2743e12c5d1SDavid du Colombier
2753e12c5d1SDavid du Colombier if(xflag){
2769a747e4fSDavid du Colombier Bprint(&bout, "%q\t%ld\t%lld\n", f->new, d->mtime, d->length);
2779a747e4fSDavid du Colombier return (d->mode & DMDIR) != 0;
2783e12c5d1SDavid du Colombier }
2797dd7cddfSDavid du Colombier if(verb && (fskind == Archive || ream))
2809a747e4fSDavid du Colombier fprint(2, "%q\n", f->new);
2819a747e4fSDavid du Colombier d->name = f->elem;
2823e12c5d1SDavid du Colombier if(d->type != 'M'){
2839a747e4fSDavid du Colombier d->uid = "sys";
2849a747e4fSDavid 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)
2899a747e4fSDavid du Colombier d->uid = f->uid;
2903e12c5d1SDavid du Colombier if(strcmp(f->gid, "-") != 0)
2919a747e4fSDavid du Colombier d->gid = f->gid;
2929a747e4fSDavid du Colombier if(fskind == Fs && !setuid){
2939a747e4fSDavid du Colombier d->uid = "";
2949a747e4fSDavid 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);
2999a747e4fSDavid du Colombier else if((d->mode&DMDIR) != (f->mode&DMDIR))
3009a747e4fSDavid 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))
3069a747e4fSDavid du Colombier fprint(2, "%q\n", f->new);
3079a747e4fSDavid 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){
3129a747e4fSDavid du Colombier nulldir(&nd);
3139a747e4fSDavid du Colombier nd.mode = d->mode;
3149a747e4fSDavid du Colombier nd.gid = d->gid;
3159a747e4fSDavid du Colombier nd.mtime = d->mtime;
3167dd7cddfSDavid du Colombier if(verb && (fskind != Archive && ream == 0))
3179a747e4fSDavid du Colombier fprint(2, "%q\n", f->new);
3189a747e4fSDavid du Colombier if(dirwstat(newfile, &nd) < 0)
3199a747e4fSDavid du Colombier warn("can't set modes for %q: %r", f->new);
3209a747e4fSDavid du Colombier nulldir(&nd);
3219a747e4fSDavid du Colombier nd.uid = d->uid;
3229a747e4fSDavid du Colombier dirwstat(newfile, &nd);
3237dd7cddfSDavid du Colombier }
3249a747e4fSDavid 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
uptodate(Dir * df,char * to)3323e12c5d1SDavid du Colombier uptodate(Dir *df, char *to)
3333e12c5d1SDavid du Colombier {
3349a747e4fSDavid du Colombier int ret;
3359a747e4fSDavid du Colombier Dir *dt;
3363e12c5d1SDavid du Colombier
3379a747e4fSDavid du Colombier if(fskind == Archive || ream || (dt = dirstat(to)) == nil)
3383e12c5d1SDavid du Colombier return 0;
3399a747e4fSDavid du Colombier ret = dt->mtime >= df->mtime;
3409a747e4fSDavid du Colombier free(dt);
3419a747e4fSDavid du Colombier return ret;
3423e12c5d1SDavid du Colombier }
3433e12c5d1SDavid du Colombier
3443e12c5d1SDavid du Colombier void
copy(Dir * d)3453e12c5d1SDavid du Colombier copy(Dir *d)
3463e12c5d1SDavid du Colombier {
3473e12c5d1SDavid du Colombier char cptmp[LEN], *p;
348*603dff34SDavid du Colombier int f, t, n, needwrite, nowarnyet = 1;
349*603dff34SDavid du Colombier vlong tot, len;
3509a747e4fSDavid du Colombier Dir nd;
3513e12c5d1SDavid du Colombier
3523e12c5d1SDavid du Colombier f = open(oldfile, OREAD);
3533e12c5d1SDavid du Colombier if(f < 0){
3549a747e4fSDavid 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){
3689a747e4fSDavid 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
3749a747e4fSDavid du Colombier needwrite = 0;
375*603dff34SDavid du Colombier for(tot = 0; tot < d->length; tot += n){
376*603dff34SDavid du Colombier len = d->length - tot;
377*603dff34SDavid du Colombier /* don't read beyond d->length */
378*603dff34SDavid du Colombier if (len > buflen)
379*603dff34SDavid du Colombier len = buflen;
380*603dff34SDavid du Colombier n = read(f, buf, len);
381*603dff34SDavid du Colombier if(n <= 0) {
382*603dff34SDavid du Colombier if(n < 0 && nowarnyet) {
3839a747e4fSDavid du Colombier warn("can't read %q: %r", oldfile);
384*603dff34SDavid du Colombier nowarnyet = 0;
3853e12c5d1SDavid du Colombier }
386*603dff34SDavid du Colombier /*
387*603dff34SDavid du Colombier * don't quit: pad to d->length (in pieces) to agree
388*603dff34SDavid du Colombier * with the length in the header, already emitted.
389*603dff34SDavid du Colombier */
390*603dff34SDavid du Colombier memset(buf, 0, len);
391*603dff34SDavid du Colombier n = len;
392*603dff34SDavid du Colombier }
3933e12c5d1SDavid du Colombier if(fskind == Archive){
3943e12c5d1SDavid du Colombier if(Bwrite(&bout, buf, n) != n)
3953e12c5d1SDavid du Colombier error("write error: %r");
3969a747e4fSDavid du Colombier }else if(memcmp(buf, zbuf, n) == 0){
3979a747e4fSDavid du Colombier if(seek(t, n, 1) < 0)
3989a747e4fSDavid du Colombier error("can't write zeros to %q: %r", newfile);
3999a747e4fSDavid du Colombier needwrite = 1;
4009a747e4fSDavid du Colombier }else{
4019a747e4fSDavid du Colombier if(write(t, buf, n) < n)
4029a747e4fSDavid du Colombier error("can't write %q: %r", newfile);
4039a747e4fSDavid du Colombier needwrite = 0;
4049a747e4fSDavid du Colombier }
4053e12c5d1SDavid du Colombier }
4063e12c5d1SDavid du Colombier close(f);
4079a747e4fSDavid du Colombier if(needwrite){
4089a747e4fSDavid du Colombier if(seek(t, -1, 1) < 0 || write(t, zbuf, 1) != 1)
4099a747e4fSDavid du Colombier error("can't write zero at end of %q: %r", newfile);
4109a747e4fSDavid du Colombier }
4113e12c5d1SDavid du Colombier if(tot != d->length){
412*603dff34SDavid du Colombier /* this should no longer happen */
413*603dff34SDavid du Colombier warn("wrong number of bytes written to %q (was %lld should be %lld)\n",
4143e12c5d1SDavid du Colombier newfile, tot, d->length);
4153e12c5d1SDavid du Colombier if(fskind == Archive){
4163e12c5d1SDavid du Colombier warn("seeking to proper position\n");
417*603dff34SDavid du Colombier /* does no good if stdout is a pipe */
4183e12c5d1SDavid du Colombier Bseek(&bout, d->length - tot, 1);
4193e12c5d1SDavid du Colombier }
4203e12c5d1SDavid du Colombier }
4213e12c5d1SDavid du Colombier if(fskind == Archive)
4223e12c5d1SDavid du Colombier return;
4233e12c5d1SDavid du Colombier remove(newfile);
4249a747e4fSDavid du Colombier nulldir(&nd);
4259a747e4fSDavid du Colombier nd.mode = d->mode;
4269a747e4fSDavid du Colombier nd.gid = d->gid;
4279a747e4fSDavid du Colombier nd.mtime = d->mtime;
4289a747e4fSDavid du Colombier nd.name = d->name;
4299a747e4fSDavid du Colombier if(dirfwstat(t, &nd) < 0)
4309a747e4fSDavid du Colombier error("can't move tmp file to %q: %r", newfile);
4319a747e4fSDavid du Colombier nulldir(&nd);
4329a747e4fSDavid du Colombier nd.uid = d->uid;
4339a747e4fSDavid du Colombier dirfwstat(t, &nd);
4343e12c5d1SDavid du Colombier close(t);
4353e12c5d1SDavid du Colombier }
4363e12c5d1SDavid du Colombier
4373e12c5d1SDavid du Colombier void
mkdir(Dir * d)4383e12c5d1SDavid du Colombier mkdir(Dir *d)
4393e12c5d1SDavid du Colombier {
4409a747e4fSDavid du Colombier Dir *d1;
4419a747e4fSDavid du Colombier Dir nd;
4423e12c5d1SDavid du Colombier int fd;
4433e12c5d1SDavid du Colombier
4443e12c5d1SDavid du Colombier if(fskind == Archive){
4453e12c5d1SDavid du Colombier arch(d);
4463e12c5d1SDavid du Colombier return;
4473e12c5d1SDavid du Colombier }
4483e12c5d1SDavid du Colombier fd = create(newfile, OREAD, d->mode);
4499a747e4fSDavid du Colombier nulldir(&nd);
4509a747e4fSDavid du Colombier nd.mode = d->mode;
4519a747e4fSDavid du Colombier nd.gid = d->gid;
4529a747e4fSDavid du Colombier nd.mtime = d->mtime;
4533e12c5d1SDavid du Colombier if(fd < 0){
4549a747e4fSDavid du Colombier if((d1 = dirstat(newfile)) == nil || !(d1->mode & DMDIR)){
4559a747e4fSDavid du Colombier free(d1);
4569a747e4fSDavid du Colombier error("can't create %q", newfile);
4579a747e4fSDavid du Colombier }
4589a747e4fSDavid du Colombier free(d1);
4599a747e4fSDavid du Colombier if(dirwstat(newfile, &nd) < 0)
4609a747e4fSDavid du Colombier warn("can't set modes for %q: %r", newfile);
4619a747e4fSDavid du Colombier nulldir(&nd);
4629a747e4fSDavid du Colombier nd.uid = d->uid;
4639a747e4fSDavid du Colombier dirwstat(newfile, &nd);
4643e12c5d1SDavid du Colombier return;
4653e12c5d1SDavid du Colombier }
4669a747e4fSDavid du Colombier if(dirfwstat(fd, &nd) < 0)
4679a747e4fSDavid du Colombier warn("can't set modes for %q: %r", newfile);
4689a747e4fSDavid du Colombier nulldir(&nd);
4699a747e4fSDavid du Colombier nd.uid = d->uid;
4709a747e4fSDavid du Colombier dirfwstat(fd, &nd);
4713e12c5d1SDavid du Colombier close(fd);
4723e12c5d1SDavid du Colombier }
4733e12c5d1SDavid du Colombier
4743e12c5d1SDavid du Colombier void
arch(Dir * d)4753e12c5d1SDavid du Colombier arch(Dir *d)
4763e12c5d1SDavid du Colombier {
4779a747e4fSDavid du Colombier Bprint(&bout, "%q %luo %q %q %lud %lld\n",
478219b2ee8SDavid du Colombier newfile, d->mode, d->uid, d->gid, d->mtime, d->length);
4793e12c5d1SDavid du Colombier }
4803e12c5d1SDavid du Colombier
4813e12c5d1SDavid du Colombier char *
mkpath(char * prefix,char * elem)4823e12c5d1SDavid du Colombier mkpath(char *prefix, char *elem)
4833e12c5d1SDavid du Colombier {
4843e12c5d1SDavid du Colombier char *p;
4853e12c5d1SDavid du Colombier int n;
4863e12c5d1SDavid du Colombier
4873e12c5d1SDavid du Colombier n = strlen(prefix) + strlen(elem) + 2;
4883e12c5d1SDavid du Colombier p = emalloc(n);
4893e12c5d1SDavid du Colombier sprint(p, "%s/%s", prefix, elem);
4903e12c5d1SDavid du Colombier return p;
4913e12c5d1SDavid du Colombier }
4923e12c5d1SDavid du Colombier
4933e12c5d1SDavid du Colombier char *
strdup(char * s)4943e12c5d1SDavid du Colombier strdup(char *s)
4953e12c5d1SDavid du Colombier {
4963e12c5d1SDavid du Colombier char *t;
4973e12c5d1SDavid du Colombier
4983e12c5d1SDavid du Colombier t = emalloc(strlen(s) + 1);
4993e12c5d1SDavid du Colombier return strcpy(t, s);
5003e12c5d1SDavid du Colombier }
5013e12c5d1SDavid du Colombier
5023e12c5d1SDavid du Colombier void
setnames(File * f)5033e12c5d1SDavid du Colombier setnames(File *f)
5043e12c5d1SDavid du Colombier {
5053e12c5d1SDavid du Colombier sprint(newfile, "%s%s", newroot, f->new);
5063e12c5d1SDavid du Colombier if(f->old){
5073e12c5d1SDavid du Colombier if(f->old[0] == '/')
5083e12c5d1SDavid du Colombier sprint(oldfile, "%s%s", oldroot, f->old);
5093e12c5d1SDavid du Colombier else
5103e12c5d1SDavid du Colombier strcpy(oldfile, f->old);
5113e12c5d1SDavid du Colombier }else
5123e12c5d1SDavid du Colombier sprint(oldfile, "%s%s", oldroot, f->new);
5133e12c5d1SDavid du Colombier if(strlen(newfile) >= sizeof newfile
5143e12c5d1SDavid du Colombier || strlen(oldfile) >= sizeof oldfile)
5153e12c5d1SDavid du Colombier error("name overfile");
5163e12c5d1SDavid du Colombier }
5173e12c5d1SDavid du Colombier
5183e12c5d1SDavid du Colombier void
freefile(File * f)5193e12c5d1SDavid du Colombier freefile(File *f)
5203e12c5d1SDavid du Colombier {
5213e12c5d1SDavid du Colombier if(f->old)
5223e12c5d1SDavid du Colombier free(f->old);
5233e12c5d1SDavid du Colombier if(f->new)
5243e12c5d1SDavid du Colombier free(f->new);
5253e12c5d1SDavid du Colombier free(f);
5263e12c5d1SDavid du Colombier }
5273e12c5d1SDavid du Colombier
528219b2ee8SDavid du Colombier /*
529219b2ee8SDavid du Colombier * skip all files in the proto that
530219b2ee8SDavid du Colombier * could be in the current dir
531219b2ee8SDavid du Colombier */
532219b2ee8SDavid du Colombier void
skipdir(void)533219b2ee8SDavid du Colombier skipdir(void)
534219b2ee8SDavid du Colombier {
535219b2ee8SDavid du Colombier char *p, c;
536219b2ee8SDavid du Colombier int level;
537219b2ee8SDavid du Colombier
5383ff48bf5SDavid du Colombier if(indent < 0 || b == nil) /* b is nil when copying adm/users */
539219b2ee8SDavid du Colombier return;
540219b2ee8SDavid du Colombier level = indent;
541219b2ee8SDavid du Colombier for(;;){
542219b2ee8SDavid du Colombier indent = 0;
543219b2ee8SDavid du Colombier p = Brdline(b, '\n');
544219b2ee8SDavid du Colombier lineno++;
545219b2ee8SDavid du Colombier if(!p){
546219b2ee8SDavid du Colombier indent = -1;
547219b2ee8SDavid du Colombier return;
548219b2ee8SDavid du Colombier }
549219b2ee8SDavid du Colombier while((c = *p++) != '\n')
550219b2ee8SDavid du Colombier if(c == ' ')
551219b2ee8SDavid du Colombier indent++;
552219b2ee8SDavid du Colombier else if(c == '\t')
553219b2ee8SDavid du Colombier indent += 8;
554219b2ee8SDavid du Colombier else
555219b2ee8SDavid du Colombier break;
556219b2ee8SDavid du Colombier if(indent <= level){
557219b2ee8SDavid du Colombier Bseek(b, -Blinelen(b), 1);
558219b2ee8SDavid du Colombier lineno--;
559219b2ee8SDavid du Colombier return;
560219b2ee8SDavid du Colombier }
561219b2ee8SDavid du Colombier }
562219b2ee8SDavid du Colombier }
563219b2ee8SDavid du Colombier
5643e12c5d1SDavid du Colombier File*
getfile(File * old)5653e12c5d1SDavid du Colombier getfile(File *old)
5663e12c5d1SDavid du Colombier {
5673e12c5d1SDavid du Colombier File *f;
5689a747e4fSDavid du Colombier char *elem;
5693e12c5d1SDavid du Colombier char *p;
5703e12c5d1SDavid du Colombier int c;
5713e12c5d1SDavid du Colombier
572219b2ee8SDavid du Colombier if(indent < 0)
573219b2ee8SDavid du Colombier return 0;
5743e12c5d1SDavid du Colombier loop:
5753e12c5d1SDavid du Colombier indent = 0;
5763e12c5d1SDavid du Colombier p = Brdline(b, '\n');
5773e12c5d1SDavid du Colombier lineno++;
5783e12c5d1SDavid du Colombier if(!p){
5793e12c5d1SDavid du Colombier indent = -1;
5803e12c5d1SDavid du Colombier return 0;
5813e12c5d1SDavid du Colombier }
582219b2ee8SDavid du Colombier while((c = *p++) != '\n')
5833e12c5d1SDavid du Colombier if(c == ' ')
5843e12c5d1SDavid du Colombier indent++;
5853e12c5d1SDavid du Colombier else if(c == '\t')
5863e12c5d1SDavid du Colombier indent += 8;
5873e12c5d1SDavid du Colombier else
5883e12c5d1SDavid du Colombier break;
589219b2ee8SDavid du Colombier if(c == '\n' || c == '#')
5903e12c5d1SDavid du Colombier goto loop;
5913e12c5d1SDavid du Colombier p--;
5923e12c5d1SDavid du Colombier f = emalloc(sizeof *f);
5939a747e4fSDavid du Colombier p = getname(p, &elem);
594219b2ee8SDavid du Colombier if(debug)
5959a747e4fSDavid du Colombier fprint(2, "getfile: %q root %q\n", elem, old->new);
5963e12c5d1SDavid du Colombier f->new = mkpath(old->new, elem);
5973e12c5d1SDavid du Colombier f->elem = utfrrune(f->new, L'/') + 1;
5983e12c5d1SDavid du Colombier p = getmode(p, &f->mode);
5999a747e4fSDavid du Colombier p = getname(p, &f->uid);
6003e12c5d1SDavid du Colombier if(!*f->uid)
6019a747e4fSDavid du Colombier f->uid = "-";
6029a747e4fSDavid du Colombier p = getname(p, &f->gid);
6033e12c5d1SDavid du Colombier if(!*f->gid)
6049a747e4fSDavid du Colombier f->gid = "-";
6053e12c5d1SDavid du Colombier f->old = getpath(p);
6063e12c5d1SDavid du Colombier if(f->old && strcmp(f->old, "-") == 0){
6073e12c5d1SDavid du Colombier free(f->old);
6083e12c5d1SDavid du Colombier f->old = 0;
6093e12c5d1SDavid du Colombier }
6103e12c5d1SDavid du Colombier setnames(f);
611219b2ee8SDavid du Colombier
612219b2ee8SDavid du Colombier if(debug)
613219b2ee8SDavid du Colombier printfile(f);
614219b2ee8SDavid du Colombier
6153e12c5d1SDavid du Colombier return f;
6163e12c5d1SDavid du Colombier }
6173e12c5d1SDavid du Colombier
6183e12c5d1SDavid du Colombier char*
getpath(char * p)6193e12c5d1SDavid du Colombier getpath(char *p)
6203e12c5d1SDavid du Colombier {
621219b2ee8SDavid du Colombier char *q, *new;
622219b2ee8SDavid du Colombier int c, n;
6233e12c5d1SDavid du Colombier
6243e12c5d1SDavid du Colombier while((c = *p) == ' ' || c == '\t')
6253e12c5d1SDavid du Colombier p++;
6263e12c5d1SDavid du Colombier q = p;
627219b2ee8SDavid du Colombier while((c = *q) != '\n' && c != ' ' && c != '\t')
6283e12c5d1SDavid du Colombier q++;
629219b2ee8SDavid du Colombier if(q == p)
6303e12c5d1SDavid du Colombier return 0;
631219b2ee8SDavid du Colombier n = q - p;
632219b2ee8SDavid du Colombier new = emalloc(n + 1);
633219b2ee8SDavid du Colombier memcpy(new, p, n);
634219b2ee8SDavid du Colombier new[n] = 0;
635219b2ee8SDavid du Colombier return new;
6363e12c5d1SDavid du Colombier }
6373e12c5d1SDavid du Colombier
6383e12c5d1SDavid du Colombier char*
getname(char * p,char ** buf)6399a747e4fSDavid du Colombier getname(char *p, char **buf)
6403e12c5d1SDavid du Colombier {
6419a747e4fSDavid du Colombier char *s, *start;
6429a747e4fSDavid du Colombier int c;
6433e12c5d1SDavid du Colombier
6443e12c5d1SDavid du Colombier while((c = *p) == ' ' || c == '\t')
6453e12c5d1SDavid du Colombier p++;
6463e12c5d1SDavid du Colombier
6479a747e4fSDavid du Colombier start = p;
6489a747e4fSDavid du Colombier while((c = *p) != '\n' && c != ' ' && c != '\t' && c != '\0')
6499a747e4fSDavid du Colombier p++;
6509a747e4fSDavid du Colombier
6519a747e4fSDavid du Colombier *buf = malloc(p+1-start);
6529a747e4fSDavid du Colombier if(*buf == nil)
6539a747e4fSDavid du Colombier return nil;
6549a747e4fSDavid du Colombier memmove(*buf, start, p-start);
6559a747e4fSDavid du Colombier (*buf)[p-start] = '\0';
6569a747e4fSDavid du Colombier
6579a747e4fSDavid du Colombier if(**buf == '$'){
6589a747e4fSDavid du Colombier s = getenv(*buf+1);
6599a747e4fSDavid du Colombier if(s == 0){
6609a747e4fSDavid du Colombier warn("can't read environment variable %q", *buf+1);
6619a747e4fSDavid du Colombier skipdir();
6629a747e4fSDavid du Colombier free(*buf);
6639a747e4fSDavid du Colombier return nil;
6649a747e4fSDavid du Colombier }
6659a747e4fSDavid du Colombier free(*buf);
6669a747e4fSDavid du Colombier *buf = s;
6673e12c5d1SDavid du Colombier }
6683e12c5d1SDavid du Colombier return p;
6693e12c5d1SDavid du Colombier }
6703e12c5d1SDavid du Colombier
6713e12c5d1SDavid du Colombier char*
getmode(char * p,ulong * xmode)6729a747e4fSDavid du Colombier getmode(char *p, ulong *xmode)
6733e12c5d1SDavid du Colombier {
6749a747e4fSDavid du Colombier char *buf, *s;
6753e12c5d1SDavid du Colombier ulong m;
6763e12c5d1SDavid du Colombier
6779a747e4fSDavid du Colombier *xmode = ~0;
6789a747e4fSDavid du Colombier p = getname(p, &buf);
6799a747e4fSDavid du Colombier if(p == nil)
6809a747e4fSDavid du Colombier return nil;
6819a747e4fSDavid du Colombier
6823e12c5d1SDavid du Colombier s = buf;
6833e12c5d1SDavid du Colombier if(!*s || strcmp(s, "-") == 0)
6843e12c5d1SDavid du Colombier return p;
6853e12c5d1SDavid du Colombier m = 0;
6863e12c5d1SDavid du Colombier if(*s == 'd'){
6879a747e4fSDavid du Colombier m |= DMDIR;
6883e12c5d1SDavid du Colombier s++;
6893e12c5d1SDavid du Colombier }
6903e12c5d1SDavid du Colombier if(*s == 'a'){
6919a747e4fSDavid du Colombier m |= DMAPPEND;
6923e12c5d1SDavid du Colombier s++;
6933e12c5d1SDavid du Colombier }
6943e12c5d1SDavid du Colombier if(*s == 'l'){
6959a747e4fSDavid du Colombier m |= DMEXCL;
6963e12c5d1SDavid du Colombier s++;
6973e12c5d1SDavid du Colombier }
6983e12c5d1SDavid du Colombier if(s[0] < '0' || s[0] > '7'
6993e12c5d1SDavid du Colombier || s[1] < '0' || s[1] > '7'
7003e12c5d1SDavid du Colombier || s[2] < '0' || s[2] > '7'
7013e12c5d1SDavid du Colombier || s[3]){
7029a747e4fSDavid du Colombier warn("bad mode specification %q", buf);
7039a747e4fSDavid du Colombier free(buf);
7043e12c5d1SDavid du Colombier return p;
7053e12c5d1SDavid du Colombier }
7069a747e4fSDavid du Colombier *xmode = m | strtoul(s, 0, 8);
7079a747e4fSDavid du Colombier free(buf);
7083e12c5d1SDavid du Colombier return p;
7093e12c5d1SDavid du Colombier }
7103e12c5d1SDavid du Colombier
7113e12c5d1SDavid du Colombier void
setusers(void)7123e12c5d1SDavid du Colombier setusers(void)
7133e12c5d1SDavid du Colombier {
7143e12c5d1SDavid du Colombier File file;
7153e12c5d1SDavid du Colombier int m;
7163e12c5d1SDavid du Colombier
7173e12c5d1SDavid du Colombier if(fskind != Kfs)
7183e12c5d1SDavid du Colombier return;
7193e12c5d1SDavid du Colombier m = modes;
7203e12c5d1SDavid du Colombier modes = 1;
7219a747e4fSDavid du Colombier file.uid = "adm";
7229a747e4fSDavid du Colombier file.gid = "adm";
7239a747e4fSDavid du Colombier file.mode = DMDIR|0775;
7243e12c5d1SDavid du Colombier file.new = "/adm";
7253e12c5d1SDavid du Colombier file.elem = "adm";
7263e12c5d1SDavid du Colombier file.old = 0;
7273e12c5d1SDavid du Colombier setnames(&file);
7283ff48bf5SDavid du Colombier strcpy(oldfile, file.new); /* Don't use root for /adm */
7293e12c5d1SDavid du Colombier mkfile(&file);
7303e12c5d1SDavid du Colombier file.new = "/adm/users";
7313e12c5d1SDavid du Colombier file.old = users;
7323e12c5d1SDavid du Colombier file.elem = "users";
7333e12c5d1SDavid du Colombier file.mode = 0664;
7343e12c5d1SDavid du Colombier setnames(&file);
7353ff48bf5SDavid du Colombier if (file.old)
7363ff48bf5SDavid du Colombier strcpy(oldfile, file.old); /* Don't use root for /adm/users */
7373e12c5d1SDavid du Colombier mkfile(&file);
7383e12c5d1SDavid du Colombier kfscmd("user");
7393e12c5d1SDavid du Colombier mkfile(&file);
7409a747e4fSDavid du Colombier file.mode = DMDIR|0775;
7413e12c5d1SDavid du Colombier file.new = "/adm";
7423e12c5d1SDavid du Colombier file.old = "/adm";
7433e12c5d1SDavid du Colombier file.elem = "adm";
7443e12c5d1SDavid du Colombier setnames(&file);
7453ff48bf5SDavid du Colombier strcpy(oldfile, file.old); /* Don't use root for /adm */
7463e12c5d1SDavid du Colombier mkfile(&file);
7473e12c5d1SDavid du Colombier modes = m;
7483e12c5d1SDavid du Colombier }
7493e12c5d1SDavid du Colombier
7503e12c5d1SDavid du Colombier void
mountkfs(char * name)7513e12c5d1SDavid du Colombier mountkfs(char *name)
7523e12c5d1SDavid du Colombier {
7539a747e4fSDavid du Colombier char kname[64];
7543e12c5d1SDavid du Colombier
7553e12c5d1SDavid du Colombier if(fskind != Kfs)
7563e12c5d1SDavid du Colombier return;
7573e12c5d1SDavid du Colombier if(name[0])
7589a747e4fSDavid du Colombier snprint(kname, sizeof kname, "/srv/kfs.%s", name);
7593e12c5d1SDavid du Colombier else
7603e12c5d1SDavid du Colombier strcpy(kname, "/srv/kfs");
7613e12c5d1SDavid du Colombier sfd = open(kname, ORDWR);
7623e12c5d1SDavid du Colombier if(sfd < 0){
7639a747e4fSDavid du Colombier fprint(2, "can't open %q\n", kname);
7643e12c5d1SDavid du Colombier exits("open /srv/kfs");
7653e12c5d1SDavid du Colombier }
7669a747e4fSDavid du Colombier if(mount(sfd, -1, "/n/kfs", MREPL|MCREATE, "") < 0){
7673e12c5d1SDavid du Colombier fprint(2, "can't mount kfs on /n/kfs\n");
7683e12c5d1SDavid du Colombier exits("mount kfs");
7693e12c5d1SDavid du Colombier }
7703e12c5d1SDavid du Colombier close(sfd);
7713e12c5d1SDavid du Colombier strcat(kname, ".cmd");
7723e12c5d1SDavid du Colombier sfd = open(kname, ORDWR);
7733e12c5d1SDavid du Colombier if(sfd < 0){
7749a747e4fSDavid du Colombier fprint(2, "can't open %q\n", kname);
7753e12c5d1SDavid du Colombier exits("open /srv/kfs");
7763e12c5d1SDavid du Colombier }
7773e12c5d1SDavid du Colombier }
7783e12c5d1SDavid du Colombier
7793e12c5d1SDavid du Colombier void
kfscmd(char * cmd)7803e12c5d1SDavid du Colombier kfscmd(char *cmd)
7813e12c5d1SDavid du Colombier {
7823e12c5d1SDavid du Colombier char buf[4*1024];
7833e12c5d1SDavid du Colombier int n;
7843e12c5d1SDavid du Colombier
7853e12c5d1SDavid du Colombier if(fskind != Kfs)
7863e12c5d1SDavid du Colombier return;
7873e12c5d1SDavid du Colombier if(write(sfd, cmd, strlen(cmd)) != strlen(cmd)){
7889a747e4fSDavid du Colombier fprint(2, "%q: error writing %q: %r", prog, cmd);
7893e12c5d1SDavid du Colombier return;
7903e12c5d1SDavid du Colombier }
7913e12c5d1SDavid du Colombier for(;;){
7923e12c5d1SDavid du Colombier n = read(sfd, buf, sizeof buf - 1);
7933e12c5d1SDavid du Colombier if(n <= 0)
7943e12c5d1SDavid du Colombier return;
7953e12c5d1SDavid du Colombier buf[n] = '\0';
7963e12c5d1SDavid du Colombier if(strcmp(buf, "done") == 0 || strcmp(buf, "success") == 0)
7973e12c5d1SDavid du Colombier return;
7983e12c5d1SDavid du Colombier if(strcmp(buf, "unknown command") == 0){
7999a747e4fSDavid du Colombier fprint(2, "%q: command %q not recognized\n", prog, cmd);
8003e12c5d1SDavid du Colombier return;
8013e12c5d1SDavid du Colombier }
8023e12c5d1SDavid du Colombier }
8033e12c5d1SDavid du Colombier }
8043e12c5d1SDavid du Colombier
8053e12c5d1SDavid du Colombier void *
emalloc(ulong n)8063e12c5d1SDavid du Colombier emalloc(ulong n)
8073e12c5d1SDavid du Colombier {
8083e12c5d1SDavid du Colombier void *p;
8093e12c5d1SDavid du Colombier
8103e12c5d1SDavid du Colombier if((p = malloc(n)) == 0)
8113e12c5d1SDavid du Colombier error("out of memory");
8123e12c5d1SDavid du Colombier return p;
8133e12c5d1SDavid du Colombier }
8143e12c5d1SDavid du Colombier
8153e12c5d1SDavid du Colombier void
error(char * fmt,...)8163e12c5d1SDavid du Colombier error(char *fmt, ...)
8173e12c5d1SDavid du Colombier {
8183e12c5d1SDavid du Colombier char buf[1024];
8197dd7cddfSDavid du Colombier va_list arg;
8203e12c5d1SDavid du Colombier
8219a747e4fSDavid du Colombier sprint(buf, "%q: %q:%d: ", prog, proto, lineno);
8227dd7cddfSDavid du Colombier va_start(arg, fmt);
8239a747e4fSDavid 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 kfscmd("disallow");
8273e12c5d1SDavid du Colombier kfscmd("sync");
8283e12c5d1SDavid du Colombier exits(0);
8293e12c5d1SDavid du Colombier }
8303e12c5d1SDavid du Colombier
8313e12c5d1SDavid du Colombier void
warn(char * fmt,...)8323e12c5d1SDavid du Colombier warn(char *fmt, ...)
8333e12c5d1SDavid du Colombier {
8343e12c5d1SDavid du Colombier char buf[1024];
8357dd7cddfSDavid du Colombier va_list arg;
8363e12c5d1SDavid du Colombier
8379a747e4fSDavid du Colombier sprint(buf, "%q: %q:%d: ", prog, proto, lineno);
8387dd7cddfSDavid du Colombier va_start(arg, fmt);
8399a747e4fSDavid du Colombier vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);
8407dd7cddfSDavid du Colombier va_end(arg);
8413e12c5d1SDavid du Colombier fprint(2, "%s\n", buf);
8423e12c5d1SDavid du Colombier }
8433e12c5d1SDavid du Colombier
8443e12c5d1SDavid du Colombier void
printfile(File * f)845219b2ee8SDavid du Colombier printfile(File *f)
846219b2ee8SDavid du Colombier {
847219b2ee8SDavid du Colombier if(f->old)
8489a747e4fSDavid du Colombier fprint(2, "%q from %q %q %q %lo\n", f->new, f->old, f->uid, f->gid, f->mode);
849219b2ee8SDavid du Colombier else
8509a747e4fSDavid du Colombier fprint(2, "%q %q %q %lo\n", f->new, f->uid, f->gid, f->mode);
851219b2ee8SDavid du Colombier }
852219b2ee8SDavid du Colombier
853219b2ee8SDavid du Colombier void
usage(void)8543e12c5d1SDavid du Colombier usage(void)
8553e12c5d1SDavid du Colombier {
8569a747e4fSDavid du Colombier fprint(2, "usage: %q [-aprvx] [-d root] [-n name] [-s source] [-u users] [-z n] proto ...\n", prog);
8573e12c5d1SDavid du Colombier exits("usage");
8583e12c5d1SDavid du Colombier }
859