17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <bio.h> 47dd7cddfSDavid du Colombier #include <auth.h> 57dd7cddfSDavid du Colombier #include <fcall.h> 67dd7cddfSDavid du Colombier #include <disk.h> 77dd7cddfSDavid du Colombier 87dd7cddfSDavid du Colombier enum { 97dd7cddfSDavid du Colombier LEN = 8*1024, 107dd7cddfSDavid du Colombier HUNKS = 128, 117dd7cddfSDavid du Colombier }; 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier typedef struct File File; 147dd7cddfSDavid du Colombier struct File{ 157dd7cddfSDavid du Colombier char *new; 167dd7cddfSDavid du Colombier char *elem; 177dd7cddfSDavid du Colombier char *old; 18*9a747e4fSDavid du Colombier char *uid; 19*9a747e4fSDavid du Colombier char *gid; 207dd7cddfSDavid du Colombier ulong mode; 217dd7cddfSDavid du Colombier }; 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier typedef void Mkfserr(char*, void*); 247dd7cddfSDavid du Colombier typedef void Mkfsenum(char*, char*, Dir*, void*); 257dd7cddfSDavid du Colombier 267dd7cddfSDavid du Colombier typedef struct Name Name; 277dd7cddfSDavid du Colombier struct Name { 287dd7cddfSDavid du Colombier int n; 297dd7cddfSDavid du Colombier char *s; 307dd7cddfSDavid du Colombier }; 317dd7cddfSDavid du Colombier 327dd7cddfSDavid du Colombier typedef struct Mkaux Mkaux; 337dd7cddfSDavid du Colombier struct Mkaux { 347dd7cddfSDavid du Colombier Mkfserr *warn; 357dd7cddfSDavid du Colombier Mkfsenum *mkenum; 367dd7cddfSDavid du Colombier char *root; 377dd7cddfSDavid du Colombier char *proto; 387dd7cddfSDavid du Colombier jmp_buf jmp; 397dd7cddfSDavid du Colombier Biobuf *b; 407dd7cddfSDavid du Colombier 417dd7cddfSDavid du Colombier Name oldfile; 427dd7cddfSDavid du Colombier Name fullname; 437dd7cddfSDavid du Colombier int lineno; 447dd7cddfSDavid du Colombier int indent; 457dd7cddfSDavid du Colombier 467dd7cddfSDavid du Colombier void *a; 477dd7cddfSDavid du Colombier }; 487dd7cddfSDavid du Colombier 497dd7cddfSDavid du Colombier static void domkfs(Mkaux *mkaux, File *me, int level); 507dd7cddfSDavid du Colombier 517dd7cddfSDavid du Colombier static int copyfile(Mkaux*, File*, Dir*, int); 527dd7cddfSDavid du Colombier static void freefile(File*); 537dd7cddfSDavid du Colombier static File* getfile(Mkaux*, File*); 547dd7cddfSDavid du Colombier static char* getmode(Mkaux*, char*, ulong*); 55*9a747e4fSDavid du Colombier static char* getname(Mkaux*, char*, char**); 5659cc4ca5SDavid du Colombier static char* getpath(Mkaux*, char*); 577dd7cddfSDavid du Colombier static int mkfile(Mkaux*, File*); 5859cc4ca5SDavid du Colombier static char* mkpath(Mkaux*, char*, char*); 597dd7cddfSDavid du Colombier static void mktree(Mkaux*, File*, int); 607dd7cddfSDavid du Colombier static void setnames(Mkaux*, File*); 617dd7cddfSDavid du Colombier static void skipdir(Mkaux*); 627dd7cddfSDavid du Colombier static void warn(Mkaux*, char *, ...); 637dd7cddfSDavid du Colombier 647dd7cddfSDavid du Colombier //static void 657dd7cddfSDavid du Colombier //mprint(char *new, char *old, Dir *d, void*) 667dd7cddfSDavid du Colombier //{ 677dd7cddfSDavid du Colombier // print("%s %s %D\n", new, old, d); 687dd7cddfSDavid du Colombier //} 697dd7cddfSDavid du Colombier 707dd7cddfSDavid du Colombier int 717dd7cddfSDavid du Colombier rdproto(char *proto, char *root, Mkfsenum *mkenum, Mkfserr *mkerr, void *a) 727dd7cddfSDavid du Colombier { 737dd7cddfSDavid du Colombier Mkaux mx, *m; 747dd7cddfSDavid du Colombier File file; 7559cc4ca5SDavid du Colombier int rv; 767dd7cddfSDavid du Colombier 777dd7cddfSDavid du Colombier m = &mx; 787dd7cddfSDavid du Colombier memset(&mx, 0, sizeof mx); 797dd7cddfSDavid du Colombier if(root == nil) 807dd7cddfSDavid du Colombier root = "/"; 817dd7cddfSDavid du Colombier 827dd7cddfSDavid du Colombier m->root = root; 837dd7cddfSDavid du Colombier m->warn = mkerr; 847dd7cddfSDavid du Colombier m->mkenum = mkenum; 857dd7cddfSDavid du Colombier m->a = a; 867dd7cddfSDavid du Colombier m->proto = proto; 877dd7cddfSDavid du Colombier m->lineno = 0; 887dd7cddfSDavid du Colombier m->indent = 0; 897dd7cddfSDavid du Colombier if((m->b = Bopen(proto, OREAD)) == nil) { 907dd7cddfSDavid du Colombier werrstr("open '%s': %r", proto); 917dd7cddfSDavid du Colombier return -1; 927dd7cddfSDavid du Colombier } 937dd7cddfSDavid du Colombier 947dd7cddfSDavid du Colombier memset(&file, 0, sizeof file); 957dd7cddfSDavid du Colombier file.new = ""; 967dd7cddfSDavid du Colombier file.old = nil; 9759cc4ca5SDavid du Colombier 9859cc4ca5SDavid du Colombier rv = 0; 9959cc4ca5SDavid du Colombier if(setjmp(m->jmp) == 0) 1007dd7cddfSDavid du Colombier domkfs(m, &file, -1); 10159cc4ca5SDavid du Colombier else 10259cc4ca5SDavid du Colombier rv = -1; 1037dd7cddfSDavid du Colombier free(m->oldfile.s); 1047dd7cddfSDavid du Colombier free(m->fullname.s); 10559cc4ca5SDavid du Colombier return rv; 10659cc4ca5SDavid du Colombier } 10759cc4ca5SDavid du Colombier 10859cc4ca5SDavid du Colombier static void* 10959cc4ca5SDavid du Colombier emalloc(Mkaux *mkaux, ulong n) 11059cc4ca5SDavid du Colombier { 11159cc4ca5SDavid du Colombier void *v; 11259cc4ca5SDavid du Colombier 11359cc4ca5SDavid du Colombier v = malloc(n); 11459cc4ca5SDavid du Colombier if(v == nil) 11559cc4ca5SDavid du Colombier longjmp(mkaux->jmp, 1); /* memory leak */ 11659cc4ca5SDavid du Colombier memset(v, 0, n); 11759cc4ca5SDavid du Colombier return v; 11859cc4ca5SDavid du Colombier } 11959cc4ca5SDavid du Colombier 12059cc4ca5SDavid du Colombier static char* 12159cc4ca5SDavid du Colombier estrdup(Mkaux *mkaux, char *s) 12259cc4ca5SDavid du Colombier { 12359cc4ca5SDavid du Colombier s = strdup(s); 12459cc4ca5SDavid du Colombier if(s == nil) 12559cc4ca5SDavid du Colombier longjmp(mkaux->jmp, 1); /* memory leak */ 12659cc4ca5SDavid du Colombier return s; 1277dd7cddfSDavid du Colombier } 1287dd7cddfSDavid du Colombier 1297dd7cddfSDavid du Colombier static void 1307dd7cddfSDavid du Colombier domkfs(Mkaux *mkaux, File *me, int level) 1317dd7cddfSDavid du Colombier { 1327dd7cddfSDavid du Colombier File *child; 1337dd7cddfSDavid du Colombier int rec; 1347dd7cddfSDavid du Colombier 1357dd7cddfSDavid du Colombier child = getfile(mkaux, me); 1367dd7cddfSDavid du Colombier if(!child) 1377dd7cddfSDavid du Colombier return; 1387dd7cddfSDavid du Colombier if((child->elem[0] == '+' || child->elem[0] == '*') && child->elem[1] == '\0'){ 1397dd7cddfSDavid du Colombier rec = child->elem[0] == '+'; 1407dd7cddfSDavid du Colombier free(child->new); 14159cc4ca5SDavid du Colombier child->new = estrdup(mkaux, me->new); 1427dd7cddfSDavid du Colombier setnames(mkaux, child); 1437dd7cddfSDavid du Colombier mktree(mkaux, child, rec); 1447dd7cddfSDavid du Colombier freefile(child); 1457dd7cddfSDavid du Colombier child = getfile(mkaux, me); 1467dd7cddfSDavid du Colombier } 1477dd7cddfSDavid du Colombier while(child && mkaux->indent > level){ 1487dd7cddfSDavid du Colombier if(mkfile(mkaux, child)) 1497dd7cddfSDavid du Colombier domkfs(mkaux, child, mkaux->indent); 1507dd7cddfSDavid du Colombier freefile(child); 1517dd7cddfSDavid du Colombier child = getfile(mkaux, me); 1527dd7cddfSDavid du Colombier } 1537dd7cddfSDavid du Colombier if(child){ 1547dd7cddfSDavid du Colombier freefile(child); 1557dd7cddfSDavid du Colombier Bseek(mkaux->b, -Blinelen(mkaux->b), 1); 1567dd7cddfSDavid du Colombier mkaux->lineno--; 1577dd7cddfSDavid du Colombier } 1587dd7cddfSDavid du Colombier } 1597dd7cddfSDavid du Colombier 1607dd7cddfSDavid du Colombier static void 1617dd7cddfSDavid du Colombier mktree(Mkaux *mkaux, File *me, int rec) 1627dd7cddfSDavid du Colombier { 1637dd7cddfSDavid du Colombier File child; 164*9a747e4fSDavid du Colombier Dir *d; 1657dd7cddfSDavid du Colombier int i, n, fd; 1667dd7cddfSDavid du Colombier 1677dd7cddfSDavid du Colombier fd = open(mkaux->oldfile.s, OREAD); 1687dd7cddfSDavid du Colombier if(fd < 0){ 1697dd7cddfSDavid du Colombier warn(mkaux, "can't open %s: %r", mkaux->oldfile.s); 1707dd7cddfSDavid du Colombier return; 1717dd7cddfSDavid du Colombier } 1727dd7cddfSDavid du Colombier 1737dd7cddfSDavid du Colombier child = *me; 174*9a747e4fSDavid du Colombier while((n = dirread(fd, &d)) > 0){ 1757dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 17659cc4ca5SDavid du Colombier child.new = mkpath(mkaux, me->new, d[i].name); 1777dd7cddfSDavid du Colombier if(me->old) 17859cc4ca5SDavid du Colombier child.old = mkpath(mkaux, me->old, d[i].name); 1797dd7cddfSDavid du Colombier child.elem = d[i].name; 1807dd7cddfSDavid du Colombier setnames(mkaux, &child); 181*9a747e4fSDavid du Colombier if((!(d[i].mode&DMDIR) || rec) && copyfile(mkaux, &child, &d[i], 1) && rec) 1827dd7cddfSDavid du Colombier mktree(mkaux, &child, rec); 1837dd7cddfSDavid du Colombier free(child.new); 1847dd7cddfSDavid du Colombier if(child.old) 1857dd7cddfSDavid du Colombier free(child.old); 1867dd7cddfSDavid du Colombier } 1877dd7cddfSDavid du Colombier } 1887dd7cddfSDavid du Colombier close(fd); 1897dd7cddfSDavid du Colombier } 1907dd7cddfSDavid du Colombier 1917dd7cddfSDavid du Colombier static int 1927dd7cddfSDavid du Colombier mkfile(Mkaux *mkaux, File *f) 1937dd7cddfSDavid du Colombier { 194*9a747e4fSDavid du Colombier Dir *d; 1957dd7cddfSDavid du Colombier 196*9a747e4fSDavid du Colombier if((d = dirstat(mkaux->oldfile.s)) == nil){ 1977dd7cddfSDavid du Colombier warn(mkaux, "can't stat file %s: %r", mkaux->oldfile.s); 1987dd7cddfSDavid du Colombier skipdir(mkaux); 1997dd7cddfSDavid du Colombier return 0; 2007dd7cddfSDavid du Colombier } 201*9a747e4fSDavid du Colombier return copyfile(mkaux, f, d, 0); 2027dd7cddfSDavid du Colombier } 2037dd7cddfSDavid du Colombier 2047dd7cddfSDavid du Colombier enum { 2057dd7cddfSDavid du Colombier SLOP = 30 2067dd7cddfSDavid du Colombier }; 2077dd7cddfSDavid du Colombier 2087dd7cddfSDavid du Colombier static void 20959cc4ca5SDavid du Colombier setname(Mkaux *mkaux, Name *name, char *s1, char *s2) 2107dd7cddfSDavid du Colombier { 2117dd7cddfSDavid du Colombier int l; 2127dd7cddfSDavid du Colombier 2137dd7cddfSDavid du Colombier l = strlen(s1)+strlen(s2)+1; 2147dd7cddfSDavid du Colombier if(name->n < l) { 2157dd7cddfSDavid du Colombier free(name->s); 21659cc4ca5SDavid du Colombier name->s = emalloc(mkaux, l+SLOP); 2177dd7cddfSDavid du Colombier name->n = l+SLOP; 2187dd7cddfSDavid du Colombier } 219*9a747e4fSDavid du Colombier snprint(name->s, name->n, "%s%s%s", s1, s1[0]==0 || s1[strlen(s1)-1]!='/' ? "/" : "", s2); 2207dd7cddfSDavid du Colombier } 2217dd7cddfSDavid du Colombier 2227dd7cddfSDavid du Colombier static int 2237dd7cddfSDavid du Colombier copyfile(Mkaux *mkaux, File *f, Dir *d, int permonly) 2247dd7cddfSDavid du Colombier { 225*9a747e4fSDavid du Colombier Dir *nd; 2267dd7cddfSDavid du Colombier ulong xmode; 2277dd7cddfSDavid du Colombier char *p; 2287dd7cddfSDavid du Colombier 22980ee5cbfSDavid du Colombier setname(mkaux, &mkaux->fullname, mkaux->root, f->old ? f->old : f->new); 23080ee5cbfSDavid du Colombier /* 23180ee5cbfSDavid du Colombier * Extra stat here is inefficient but accounts for binds. 23280ee5cbfSDavid du Colombier */ 233*9a747e4fSDavid du Colombier if((nd = dirstat(mkaux->fullname.s)) != nil) 234*9a747e4fSDavid du Colombier d = nd; 235*9a747e4fSDavid du Colombier 236*9a747e4fSDavid du Colombier d->name = f->elem; 2377dd7cddfSDavid du Colombier if(d->type != 'M'){ 238*9a747e4fSDavid du Colombier d->uid = "sys"; 239*9a747e4fSDavid du Colombier d->gid = "sys"; 2407dd7cddfSDavid du Colombier xmode = (d->mode >> 6) & 7; 2417dd7cddfSDavid du Colombier d->mode |= xmode | (xmode << 3); 2427dd7cddfSDavid du Colombier } 2437dd7cddfSDavid du Colombier if(strcmp(f->uid, "-") != 0) 244*9a747e4fSDavid du Colombier d->uid = f->uid; 2457dd7cddfSDavid du Colombier if(strcmp(f->gid, "-") != 0) 246*9a747e4fSDavid du Colombier d->gid = f->gid; 2477dd7cddfSDavid du Colombier if(f->mode != ~0){ 2487dd7cddfSDavid du Colombier if(permonly) 2497dd7cddfSDavid du Colombier d->mode = (d->mode & ~0666) | (f->mode & 0666); 250*9a747e4fSDavid du Colombier else if((d->mode&DMDIR) != (f->mode&DMDIR)) 2517dd7cddfSDavid du Colombier warn(mkaux, "inconsistent mode for %s", f->new); 2527dd7cddfSDavid du Colombier else 2537dd7cddfSDavid du Colombier d->mode = f->mode; 2547dd7cddfSDavid du Colombier } 2557dd7cddfSDavid du Colombier 2567dd7cddfSDavid du Colombier if(p = strrchr(f->new, '/')) 257*9a747e4fSDavid du Colombier d->name = p+1; 2587dd7cddfSDavid du Colombier else 259*9a747e4fSDavid du Colombier d->name = f->new; 2607dd7cddfSDavid du Colombier 2617dd7cddfSDavid du Colombier mkaux->mkenum(f->new, mkaux->fullname.s, d, mkaux->a); 262*9a747e4fSDavid du Colombier xmode = d->mode; 263*9a747e4fSDavid du Colombier free(nd); 264*9a747e4fSDavid du Colombier return (xmode&DMDIR) != 0; 2657dd7cddfSDavid du Colombier } 2667dd7cddfSDavid du Colombier 2677dd7cddfSDavid du Colombier static char * 26859cc4ca5SDavid du Colombier mkpath(Mkaux *mkaux, char *prefix, char *elem) 2697dd7cddfSDavid du Colombier { 2707dd7cddfSDavid du Colombier char *p; 2717dd7cddfSDavid du Colombier int n; 2727dd7cddfSDavid du Colombier 2737dd7cddfSDavid du Colombier n = strlen(prefix) + strlen(elem) + 2; 27459cc4ca5SDavid du Colombier p = emalloc(mkaux, n); 27580ee5cbfSDavid du Colombier strcpy(p, prefix); 27680ee5cbfSDavid du Colombier strcat(p, "/"); 27780ee5cbfSDavid du Colombier strcat(p, elem); 2787dd7cddfSDavid du Colombier return p; 2797dd7cddfSDavid du Colombier } 2807dd7cddfSDavid du Colombier 2817dd7cddfSDavid du Colombier static void 2827dd7cddfSDavid du Colombier setnames(Mkaux *mkaux, File *f) 2837dd7cddfSDavid du Colombier { 2847dd7cddfSDavid du Colombier 2857dd7cddfSDavid du Colombier if(f->old){ 2867dd7cddfSDavid du Colombier if(f->old[0] == '/') 28759cc4ca5SDavid du Colombier setname(mkaux, &mkaux->oldfile, f->old, ""); 288*9a747e4fSDavid du Colombier else 289*9a747e4fSDavid du Colombier setname(mkaux, &mkaux->oldfile, mkaux->root, f->old); 2907dd7cddfSDavid du Colombier } else 29159cc4ca5SDavid du Colombier setname(mkaux, &mkaux->oldfile, mkaux->root, f->new); 2927dd7cddfSDavid du Colombier } 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier static void 2957dd7cddfSDavid du Colombier freefile(File *f) 2967dd7cddfSDavid du Colombier { 2977dd7cddfSDavid du Colombier if(f->old) 2987dd7cddfSDavid du Colombier free(f->old); 2997dd7cddfSDavid du Colombier if(f->new) 3007dd7cddfSDavid du Colombier free(f->new); 3017dd7cddfSDavid du Colombier free(f); 3027dd7cddfSDavid du Colombier } 3037dd7cddfSDavid du Colombier 3047dd7cddfSDavid du Colombier /* 3057dd7cddfSDavid du Colombier * skip all files in the proto that 3067dd7cddfSDavid du Colombier * could be in the current dir 3077dd7cddfSDavid du Colombier */ 3087dd7cddfSDavid du Colombier static void 3097dd7cddfSDavid du Colombier skipdir(Mkaux *mkaux) 3107dd7cddfSDavid du Colombier { 3117dd7cddfSDavid du Colombier char *p, c; 3127dd7cddfSDavid du Colombier int level; 3137dd7cddfSDavid du Colombier 3147dd7cddfSDavid du Colombier if(mkaux->indent < 0) 3157dd7cddfSDavid du Colombier return; 3167dd7cddfSDavid du Colombier level = mkaux->indent; 3177dd7cddfSDavid du Colombier for(;;){ 3187dd7cddfSDavid du Colombier mkaux->indent = 0; 3197dd7cddfSDavid du Colombier p = Brdline(mkaux->b, '\n'); 3207dd7cddfSDavid du Colombier mkaux->lineno++; 3217dd7cddfSDavid du Colombier if(!p){ 3227dd7cddfSDavid du Colombier mkaux->indent = -1; 3237dd7cddfSDavid du Colombier return; 3247dd7cddfSDavid du Colombier } 3257dd7cddfSDavid du Colombier while((c = *p++) != '\n') 3267dd7cddfSDavid du Colombier if(c == ' ') 3277dd7cddfSDavid du Colombier mkaux->indent++; 3287dd7cddfSDavid du Colombier else if(c == '\t') 3297dd7cddfSDavid du Colombier mkaux->indent += 8; 3307dd7cddfSDavid du Colombier else 3317dd7cddfSDavid du Colombier break; 3327dd7cddfSDavid du Colombier if(mkaux->indent <= level){ 3337dd7cddfSDavid du Colombier Bseek(mkaux->b, -Blinelen(mkaux->b), 1); 3347dd7cddfSDavid du Colombier mkaux->lineno--; 3357dd7cddfSDavid du Colombier return; 3367dd7cddfSDavid du Colombier } 3377dd7cddfSDavid du Colombier } 3387dd7cddfSDavid du Colombier } 3397dd7cddfSDavid du Colombier 3407dd7cddfSDavid du Colombier static File* 3417dd7cddfSDavid du Colombier getfile(Mkaux *mkaux, File *old) 3427dd7cddfSDavid du Colombier { 3437dd7cddfSDavid du Colombier File *f; 344*9a747e4fSDavid du Colombier char *elem; 3457dd7cddfSDavid du Colombier char *p; 3467dd7cddfSDavid du Colombier int c; 3477dd7cddfSDavid du Colombier 3487dd7cddfSDavid du Colombier if(mkaux->indent < 0) 3497dd7cddfSDavid du Colombier return 0; 3507dd7cddfSDavid du Colombier loop: 3517dd7cddfSDavid du Colombier mkaux->indent = 0; 3527dd7cddfSDavid du Colombier p = Brdline(mkaux->b, '\n'); 3537dd7cddfSDavid du Colombier mkaux->lineno++; 3547dd7cddfSDavid du Colombier if(!p){ 3557dd7cddfSDavid du Colombier mkaux->indent = -1; 3567dd7cddfSDavid du Colombier return 0; 3577dd7cddfSDavid du Colombier } 3587dd7cddfSDavid du Colombier while((c = *p++) != '\n') 3597dd7cddfSDavid du Colombier if(c == ' ') 3607dd7cddfSDavid du Colombier mkaux->indent++; 3617dd7cddfSDavid du Colombier else if(c == '\t') 3627dd7cddfSDavid du Colombier mkaux->indent += 8; 3637dd7cddfSDavid du Colombier else 3647dd7cddfSDavid du Colombier break; 3657dd7cddfSDavid du Colombier if(c == '\n' || c == '#') 3667dd7cddfSDavid du Colombier goto loop; 3677dd7cddfSDavid du Colombier p--; 36859cc4ca5SDavid du Colombier f = emalloc(mkaux, sizeof *f); 369*9a747e4fSDavid du Colombier p = getname(mkaux, p, &elem); 3707dd7cddfSDavid du Colombier if(p == nil) 3717dd7cddfSDavid du Colombier return nil; 3727dd7cddfSDavid du Colombier 37359cc4ca5SDavid du Colombier f->new = mkpath(mkaux, old->new, elem); 374*9a747e4fSDavid du Colombier free(elem); 3757dd7cddfSDavid du Colombier f->elem = utfrrune(f->new, L'/') + 1; 3767dd7cddfSDavid du Colombier p = getmode(mkaux, p, &f->mode); 377*9a747e4fSDavid du Colombier p = getname(mkaux, p, &f->uid); /* LEAK */ 3787dd7cddfSDavid du Colombier if(p == nil) 3797dd7cddfSDavid du Colombier return nil; 3807dd7cddfSDavid du Colombier 3817dd7cddfSDavid du Colombier if(!*f->uid) 3827dd7cddfSDavid du Colombier strcpy(f->uid, "-"); 383*9a747e4fSDavid du Colombier p = getname(mkaux, p, &f->gid); /* LEAK */ 3847dd7cddfSDavid du Colombier if(p == nil) 3857dd7cddfSDavid du Colombier return nil; 3867dd7cddfSDavid du Colombier 3877dd7cddfSDavid du Colombier if(!*f->gid) 3887dd7cddfSDavid du Colombier strcpy(f->gid, "-"); 38959cc4ca5SDavid du Colombier f->old = getpath(mkaux, p); 3907dd7cddfSDavid du Colombier if(f->old && strcmp(f->old, "-") == 0){ 3917dd7cddfSDavid du Colombier free(f->old); 3927dd7cddfSDavid du Colombier f->old = 0; 3937dd7cddfSDavid du Colombier } 3947dd7cddfSDavid du Colombier setnames(mkaux, f); 3957dd7cddfSDavid du Colombier 3967dd7cddfSDavid du Colombier return f; 3977dd7cddfSDavid du Colombier } 3987dd7cddfSDavid du Colombier 3997dd7cddfSDavid du Colombier static char* 40059cc4ca5SDavid du Colombier getpath(Mkaux *mkaux, char *p) 4017dd7cddfSDavid du Colombier { 4027dd7cddfSDavid du Colombier char *q, *new; 4037dd7cddfSDavid du Colombier int c, n; 4047dd7cddfSDavid du Colombier 4057dd7cddfSDavid du Colombier while((c = *p) == ' ' || c == '\t') 4067dd7cddfSDavid du Colombier p++; 4077dd7cddfSDavid du Colombier q = p; 4087dd7cddfSDavid du Colombier while((c = *q) != '\n' && c != ' ' && c != '\t') 4097dd7cddfSDavid du Colombier q++; 4107dd7cddfSDavid du Colombier if(q == p) 4117dd7cddfSDavid du Colombier return 0; 4127dd7cddfSDavid du Colombier n = q - p; 41359cc4ca5SDavid du Colombier new = emalloc(mkaux, n + 1); 4147dd7cddfSDavid du Colombier memcpy(new, p, n); 4157dd7cddfSDavid du Colombier new[n] = 0; 4167dd7cddfSDavid du Colombier return new; 4177dd7cddfSDavid du Colombier } 4187dd7cddfSDavid du Colombier 4197dd7cddfSDavid du Colombier static char* 420*9a747e4fSDavid du Colombier getname(Mkaux *mkaux, char *p, char **buf) 4217dd7cddfSDavid du Colombier { 422*9a747e4fSDavid du Colombier char *s, *start; 423*9a747e4fSDavid du Colombier int c; 4247dd7cddfSDavid du Colombier 4257dd7cddfSDavid du Colombier while((c = *p) == ' ' || c == '\t') 4267dd7cddfSDavid du Colombier p++; 4277dd7cddfSDavid du Colombier 428*9a747e4fSDavid du Colombier start = p; 429*9a747e4fSDavid du Colombier while((c = *p) != '\n' && c != ' ' && c != '\t') 430*9a747e4fSDavid du Colombier p++; 431*9a747e4fSDavid du Colombier 432*9a747e4fSDavid du Colombier *buf = malloc(p+2-start); /* +2: need at least 2 bytes; might strcpy "-" into buf */ 433*9a747e4fSDavid du Colombier if(*buf == nil) 434*9a747e4fSDavid du Colombier return nil; 435*9a747e4fSDavid du Colombier memmove(*buf, start, p-start); 436*9a747e4fSDavid du Colombier 437*9a747e4fSDavid du Colombier (*buf)[p-start] = '\0'; 438*9a747e4fSDavid du Colombier 439*9a747e4fSDavid du Colombier if(**buf == '$'){ 440*9a747e4fSDavid du Colombier s = getenv(*buf+1); 4417dd7cddfSDavid du Colombier if(s == 0){ 442*9a747e4fSDavid du Colombier warn(mkaux, "can't read environment variable %s", *buf+1); 4437dd7cddfSDavid du Colombier skipdir(mkaux); 444*9a747e4fSDavid du Colombier free(*buf); 4457dd7cddfSDavid du Colombier return nil; 4467dd7cddfSDavid du Colombier } 447*9a747e4fSDavid du Colombier free(*buf); 448*9a747e4fSDavid du Colombier *buf = s; 4497dd7cddfSDavid du Colombier } 4507dd7cddfSDavid du Colombier return p; 4517dd7cddfSDavid du Colombier } 4527dd7cddfSDavid du Colombier 4537dd7cddfSDavid du Colombier static char* 4547dd7cddfSDavid du Colombier getmode(Mkaux *mkaux, char *p, ulong *xmode) 4557dd7cddfSDavid du Colombier { 456*9a747e4fSDavid du Colombier char *buf, *s; 4577dd7cddfSDavid du Colombier ulong m; 4587dd7cddfSDavid du Colombier 4597dd7cddfSDavid du Colombier *xmode = ~0; 460*9a747e4fSDavid du Colombier p = getname(mkaux, p, &buf); 461*9a747e4fSDavid du Colombier if(p == nil) 462*9a747e4fSDavid du Colombier return nil; 463*9a747e4fSDavid du Colombier 4647dd7cddfSDavid du Colombier s = buf; 4657dd7cddfSDavid du Colombier if(!*s || strcmp(s, "-") == 0) 4667dd7cddfSDavid du Colombier return p; 4677dd7cddfSDavid du Colombier m = 0; 4687dd7cddfSDavid du Colombier if(*s == 'd'){ 469*9a747e4fSDavid du Colombier m |= DMDIR; 4707dd7cddfSDavid du Colombier s++; 4717dd7cddfSDavid du Colombier } 4727dd7cddfSDavid du Colombier if(*s == 'a'){ 473*9a747e4fSDavid du Colombier m |= DMAPPEND; 4747dd7cddfSDavid du Colombier s++; 4757dd7cddfSDavid du Colombier } 4767dd7cddfSDavid du Colombier if(*s == 'l'){ 477*9a747e4fSDavid du Colombier m |= DMEXCL; 4787dd7cddfSDavid du Colombier s++; 4797dd7cddfSDavid du Colombier } 4807dd7cddfSDavid du Colombier if(s[0] < '0' || s[0] > '7' 4817dd7cddfSDavid du Colombier || s[1] < '0' || s[1] > '7' 4827dd7cddfSDavid du Colombier || s[2] < '0' || s[2] > '7' 4837dd7cddfSDavid du Colombier || s[3]){ 4847dd7cddfSDavid du Colombier warn(mkaux, "bad mode specification %s", buf); 485*9a747e4fSDavid du Colombier free(buf); 4867dd7cddfSDavid du Colombier return p; 4877dd7cddfSDavid du Colombier } 4887dd7cddfSDavid du Colombier *xmode = m | strtoul(s, 0, 8); 489*9a747e4fSDavid du Colombier free(buf); 4907dd7cddfSDavid du Colombier return p; 4917dd7cddfSDavid du Colombier } 4927dd7cddfSDavid du Colombier 4937dd7cddfSDavid du Colombier static void 4947dd7cddfSDavid du Colombier warn(Mkaux *mkaux, char *fmt, ...) 4957dd7cddfSDavid du Colombier { 4967dd7cddfSDavid du Colombier char buf[256]; 4977dd7cddfSDavid du Colombier va_list va; 4987dd7cddfSDavid du Colombier 4997dd7cddfSDavid du Colombier va_start(va, fmt); 500*9a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, va); 5017dd7cddfSDavid du Colombier va_end(va); 5027dd7cddfSDavid du Colombier 5037dd7cddfSDavid du Colombier if(mkaux->warn) 5047dd7cddfSDavid du Colombier mkaux->warn(buf, mkaux->a); 5057dd7cddfSDavid du Colombier else 5067dd7cddfSDavid du Colombier fprint(2, "warning: %s\n", buf); 5077dd7cddfSDavid du Colombier } 508