19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <auth.h>
59a747e4fSDavid du Colombier #include <fcall.h>
69a747e4fSDavid du Colombier #include <disk.h>
79a747e4fSDavid du Colombier
89a747e4fSDavid du Colombier enum {
99a747e4fSDavid du Colombier LEN = 8*1024,
109a747e4fSDavid du Colombier HUNKS = 128,
119a747e4fSDavid du Colombier };
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier typedef struct File File;
149a747e4fSDavid du Colombier struct File{
159a747e4fSDavid du Colombier char *new;
169a747e4fSDavid du Colombier char *elem;
179a747e4fSDavid du Colombier char *old;
189a747e4fSDavid du Colombier char *uid;
199a747e4fSDavid du Colombier char *gid;
209a747e4fSDavid du Colombier ulong mode;
219a747e4fSDavid du Colombier };
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier typedef void Mkfserr(char*, void*);
249a747e4fSDavid du Colombier typedef void Mkfsenum(char*, char*, Dir*, void*);
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier typedef struct Name Name;
279a747e4fSDavid du Colombier struct Name {
289a747e4fSDavid du Colombier int n;
299a747e4fSDavid du Colombier char *s;
309a747e4fSDavid du Colombier };
319a747e4fSDavid du Colombier
329a747e4fSDavid du Colombier typedef struct Mkaux Mkaux;
339a747e4fSDavid du Colombier struct Mkaux {
349a747e4fSDavid du Colombier Mkfserr *warn;
359a747e4fSDavid du Colombier Mkfsenum *mkenum;
369a747e4fSDavid du Colombier char *root;
379a747e4fSDavid du Colombier char *xroot;
389a747e4fSDavid du Colombier char *proto;
399a747e4fSDavid du Colombier jmp_buf jmp;
409a747e4fSDavid du Colombier Biobuf *b;
419a747e4fSDavid du Colombier
429a747e4fSDavid du Colombier Name oldfile;
439a747e4fSDavid du Colombier Name fullname;
449a747e4fSDavid du Colombier int lineno;
459a747e4fSDavid du Colombier int indent;
469a747e4fSDavid du Colombier
479a747e4fSDavid du Colombier void *a;
489a747e4fSDavid du Colombier };
499a747e4fSDavid du Colombier
509a747e4fSDavid du Colombier static void domkfs(Mkaux *mkaux, File *me, int level);
519a747e4fSDavid du Colombier
529a747e4fSDavid du Colombier static int copyfile(Mkaux*, File*, Dir*, int);
539a747e4fSDavid du Colombier static void freefile(File*);
549a747e4fSDavid du Colombier static File* getfile(Mkaux*, File*);
559a747e4fSDavid du Colombier static char* getmode(Mkaux*, char*, ulong*);
569a747e4fSDavid du Colombier static char* getname(Mkaux*, char*, char**);
579a747e4fSDavid du Colombier static char* getpath(Mkaux*, char*);
589a747e4fSDavid du Colombier static int mkfile(Mkaux*, File*);
599a747e4fSDavid du Colombier static char* mkpath(Mkaux*, char*, char*);
609a747e4fSDavid du Colombier static void mktree(Mkaux*, File*, int);
619a747e4fSDavid du Colombier static void setnames(Mkaux*, File*);
629a747e4fSDavid du Colombier static void skipdir(Mkaux*);
639a747e4fSDavid du Colombier static void warn(Mkaux*, char *, ...);
649a747e4fSDavid du Colombier
659a747e4fSDavid du Colombier //static void
669a747e4fSDavid du Colombier //mprint(char *new, char *old, Dir *d, void*)
679a747e4fSDavid du Colombier //{
689a747e4fSDavid du Colombier // print("%s %s %D\n", new, old, d);
699a747e4fSDavid du Colombier //}
709a747e4fSDavid du Colombier
719a747e4fSDavid du Colombier int
revrdproto(char * proto,char * root,char * xroot,Mkfsenum * mkenum,Mkfserr * mkerr,void * a)729a747e4fSDavid du Colombier revrdproto(char *proto, char *root, char *xroot, Mkfsenum *mkenum, Mkfserr *mkerr, void *a)
739a747e4fSDavid du Colombier {
749a747e4fSDavid du Colombier Mkaux mx, *m;
759a747e4fSDavid du Colombier File file;
769a747e4fSDavid du Colombier int rv;
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier m = &mx;
799a747e4fSDavid du Colombier memset(&mx, 0, sizeof mx);
809a747e4fSDavid du Colombier if(root == nil)
819a747e4fSDavid du Colombier root = "/";
829a747e4fSDavid du Colombier
839a747e4fSDavid du Colombier m->root = root;
849a747e4fSDavid du Colombier m->xroot = xroot;
859a747e4fSDavid du Colombier m->warn = mkerr;
869a747e4fSDavid du Colombier m->mkenum = mkenum;
879a747e4fSDavid du Colombier m->a = a;
889a747e4fSDavid du Colombier m->proto = proto;
899a747e4fSDavid du Colombier m->lineno = 0;
909a747e4fSDavid du Colombier m->indent = 0;
919a747e4fSDavid du Colombier if((m->b = Bopen(proto, OREAD)) == nil) {
929a747e4fSDavid du Colombier werrstr("open '%s': %r", proto);
939a747e4fSDavid du Colombier return -1;
949a747e4fSDavid du Colombier }
959a747e4fSDavid du Colombier
969a747e4fSDavid du Colombier memset(&file, 0, sizeof file);
979a747e4fSDavid du Colombier file.new = "";
989a747e4fSDavid du Colombier file.old = nil;
999a747e4fSDavid du Colombier
1009a747e4fSDavid du Colombier rv = 0;
1019a747e4fSDavid du Colombier if(setjmp(m->jmp) == 0)
1029a747e4fSDavid du Colombier domkfs(m, &file, -1);
1039a747e4fSDavid du Colombier else
1049a747e4fSDavid du Colombier rv = -1;
1059a747e4fSDavid du Colombier free(m->oldfile.s);
1069a747e4fSDavid du Colombier free(m->fullname.s);
1079a747e4fSDavid du Colombier return rv;
1089a747e4fSDavid du Colombier }
1099a747e4fSDavid du Colombier
1109a747e4fSDavid du Colombier static void*
emalloc(Mkaux * mkaux,ulong n)1119a747e4fSDavid du Colombier emalloc(Mkaux *mkaux, ulong n)
1129a747e4fSDavid du Colombier {
1139a747e4fSDavid du Colombier void *v;
1149a747e4fSDavid du Colombier
1159a747e4fSDavid du Colombier v = malloc(n);
1169a747e4fSDavid du Colombier if(v == nil)
1179a747e4fSDavid du Colombier longjmp(mkaux->jmp, 1); /* memory leak */
1189a747e4fSDavid du Colombier memset(v, 0, n);
1199a747e4fSDavid du Colombier return v;
1209a747e4fSDavid du Colombier }
1219a747e4fSDavid du Colombier
1229a747e4fSDavid du Colombier static char*
estrdup(Mkaux * mkaux,char * s)1239a747e4fSDavid du Colombier estrdup(Mkaux *mkaux, char *s)
1249a747e4fSDavid du Colombier {
1259a747e4fSDavid du Colombier s = strdup(s);
1269a747e4fSDavid du Colombier if(s == nil)
1279a747e4fSDavid du Colombier longjmp(mkaux->jmp, 1); /* memory leak */
1289a747e4fSDavid du Colombier return s;
1299a747e4fSDavid du Colombier }
1309a747e4fSDavid du Colombier
1319a747e4fSDavid du Colombier static void
domkfs(Mkaux * mkaux,File * me,int level)1329a747e4fSDavid du Colombier domkfs(Mkaux *mkaux, File *me, int level)
1339a747e4fSDavid du Colombier {
1349a747e4fSDavid du Colombier File *child;
1359a747e4fSDavid du Colombier int rec;
1369a747e4fSDavid du Colombier
1379a747e4fSDavid du Colombier child = getfile(mkaux, me);
1389a747e4fSDavid du Colombier if(!child)
1399a747e4fSDavid du Colombier return;
1409a747e4fSDavid du Colombier if((child->elem[0] == '+' || child->elem[0] == '*') && child->elem[1] == '\0'){
1419a747e4fSDavid du Colombier rec = child->elem[0] == '+';
1429a747e4fSDavid du Colombier free(child->new);
1439a747e4fSDavid du Colombier child->new = estrdup(mkaux, me->new);
1449a747e4fSDavid du Colombier setnames(mkaux, child);
1459a747e4fSDavid du Colombier mktree(mkaux, child, rec);
1469a747e4fSDavid du Colombier freefile(child);
1479a747e4fSDavid du Colombier child = getfile(mkaux, me);
1489a747e4fSDavid du Colombier }
1499a747e4fSDavid du Colombier while(child && mkaux->indent > level){
1509a747e4fSDavid du Colombier if(mkfile(mkaux, child))
1519a747e4fSDavid du Colombier domkfs(mkaux, child, mkaux->indent);
1529a747e4fSDavid du Colombier freefile(child);
1539a747e4fSDavid du Colombier child = getfile(mkaux, me);
1549a747e4fSDavid du Colombier }
1559a747e4fSDavid du Colombier if(child){
1569a747e4fSDavid du Colombier freefile(child);
1579a747e4fSDavid du Colombier Bseek(mkaux->b, -Blinelen(mkaux->b), 1);
1589a747e4fSDavid du Colombier mkaux->lineno--;
1599a747e4fSDavid du Colombier }
1609a747e4fSDavid du Colombier }
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier enum {
1639a747e4fSDavid du Colombier SLOP = 30
1649a747e4fSDavid du Colombier };
1659a747e4fSDavid du Colombier
1669a747e4fSDavid du Colombier static void
setname(Mkaux * mkaux,Name * name,char * s1,char * s2)1679a747e4fSDavid du Colombier setname(Mkaux *mkaux, Name *name, char *s1, char *s2)
1689a747e4fSDavid du Colombier {
1699a747e4fSDavid du Colombier int l;
1709a747e4fSDavid du Colombier
1719a747e4fSDavid du Colombier l = strlen(s1)+strlen(s2)+1;
1729a747e4fSDavid du Colombier if(name->n < l) {
1739a747e4fSDavid du Colombier free(name->s);
1749a747e4fSDavid du Colombier name->s = emalloc(mkaux, l+SLOP);
1759a747e4fSDavid du Colombier name->n = l+SLOP;
1769a747e4fSDavid du Colombier }
1779a747e4fSDavid du Colombier snprint(name->s, name->n, "%s%s%s", s1, s2[0] && s2[0]!='/' ? "/" : "", s2);
1789a747e4fSDavid du Colombier }
1799a747e4fSDavid du Colombier
1809a747e4fSDavid du Colombier static void
mktree(Mkaux * mkaux,File * me,int rec)1819a747e4fSDavid du Colombier mktree(Mkaux *mkaux, File *me, int rec)
1829a747e4fSDavid du Colombier {
1839a747e4fSDavid du Colombier File child;
1849a747e4fSDavid du Colombier Dir *d;
1859a747e4fSDavid du Colombier int i, n, fd;
1869a747e4fSDavid du Colombier
1879a747e4fSDavid du Colombier setname(mkaux, &mkaux->fullname, mkaux->root, me->new);
1889a747e4fSDavid du Colombier fd = open(mkaux->fullname.s, OREAD);
1899a747e4fSDavid du Colombier if(fd < 0){
1909a747e4fSDavid du Colombier warn(mkaux, "can't open %s: %r", mkaux->fullname.s);
1919a747e4fSDavid du Colombier return;
1929a747e4fSDavid du Colombier }
1939a747e4fSDavid du Colombier
1949a747e4fSDavid du Colombier child = *me;
1959a747e4fSDavid du Colombier while((n = dirread(fd, &d)) > 0){
1969a747e4fSDavid du Colombier for(i = 0; i < n; i++){
1979a747e4fSDavid du Colombier child.new = mkpath(mkaux, me->new, d[i].name);
1989a747e4fSDavid du Colombier if(me->old)
1999a747e4fSDavid du Colombier child.old = mkpath(mkaux, me->old, d[i].name);
2009a747e4fSDavid du Colombier child.elem = d[i].name;
2019a747e4fSDavid du Colombier setnames(mkaux, &child);
2029a747e4fSDavid du Colombier if(copyfile(mkaux, &child, &d[i], 1) && rec)
2039a747e4fSDavid du Colombier mktree(mkaux, &child, rec);
2049a747e4fSDavid du Colombier free(child.new);
2059a747e4fSDavid du Colombier if(child.old)
2069a747e4fSDavid du Colombier free(child.old);
2079a747e4fSDavid du Colombier }
2089a747e4fSDavid du Colombier }
2099a747e4fSDavid du Colombier close(fd);
2109a747e4fSDavid du Colombier }
2119a747e4fSDavid du Colombier
2129a747e4fSDavid du Colombier static int
mkfile(Mkaux * mkaux,File * f)2139a747e4fSDavid du Colombier mkfile(Mkaux *mkaux, File *f)
2149a747e4fSDavid du Colombier {
2159a747e4fSDavid du Colombier Dir *d;
2169a747e4fSDavid du Colombier
2179a747e4fSDavid du Colombier setname(mkaux, &mkaux->fullname, mkaux->root, f->new);
2189a747e4fSDavid du Colombier if((d = dirstat(mkaux->fullname.s)) == nil){
2199a747e4fSDavid du Colombier warn(mkaux, "can't stat file %s: %r", mkaux->fullname.s);
2209a747e4fSDavid du Colombier skipdir(mkaux);
2219a747e4fSDavid du Colombier return 0;
2229a747e4fSDavid du Colombier }
2239a747e4fSDavid du Colombier return copyfile(mkaux, f, d, 0);
2249a747e4fSDavid du Colombier }
2259a747e4fSDavid du Colombier
2269a747e4fSDavid du Colombier static int
copyfile(Mkaux * mkaux,File * f,Dir * d,int permonly)2279a747e4fSDavid du Colombier copyfile(Mkaux *mkaux, File *f, Dir *d, int permonly)
2289a747e4fSDavid du Colombier {
2299a747e4fSDavid du Colombier Dir *nd;
2309a747e4fSDavid du Colombier ulong xmode;
2319a747e4fSDavid du Colombier char *p;
2329a747e4fSDavid du Colombier
2339a747e4fSDavid du Colombier /*
2349a747e4fSDavid du Colombier * Extra stat here is inefficient but accounts for binds.
2359a747e4fSDavid du Colombier */
2369a747e4fSDavid du Colombier setname(mkaux, &mkaux->fullname, mkaux->root, f->new);
2379a747e4fSDavid du Colombier if((nd = dirstat(mkaux->fullname.s)) != nil)
2389a747e4fSDavid du Colombier d = nd;
2399a747e4fSDavid du Colombier
2409a747e4fSDavid du Colombier setname(mkaux, &mkaux->fullname, mkaux->xroot, f->old ? f->old : f->new);
2419a747e4fSDavid du Colombier d->name = f->elem;
2429a747e4fSDavid du Colombier if(d->type != 'M'){
2439a747e4fSDavid du Colombier d->uid = "sys";
2449a747e4fSDavid du Colombier d->gid = "sys";
2459a747e4fSDavid du Colombier xmode = (d->mode >> 6) & 7;
2469a747e4fSDavid du Colombier d->mode |= xmode | (xmode << 3);
2479a747e4fSDavid du Colombier }
2489a747e4fSDavid du Colombier if(strcmp(f->uid, "-") != 0)
2499a747e4fSDavid du Colombier d->uid = f->uid;
2509a747e4fSDavid du Colombier if(strcmp(f->gid, "-") != 0)
2519a747e4fSDavid du Colombier d->gid = f->gid;
2529a747e4fSDavid du Colombier if(f->mode != ~0){
2539a747e4fSDavid du Colombier if(permonly)
2549a747e4fSDavid du Colombier d->mode = (d->mode & ~0666) | (f->mode & 0666);
2559a747e4fSDavid du Colombier else if((d->mode&DMDIR) != (f->mode&DMDIR))
2569a747e4fSDavid du Colombier warn(mkaux, "inconsistent mode for %s", f->new);
2579a747e4fSDavid du Colombier else
2589a747e4fSDavid du Colombier d->mode = f->mode;
2599a747e4fSDavid du Colombier }
2609a747e4fSDavid du Colombier
2619a747e4fSDavid du Colombier if(p = strrchr(f->new, '/'))
2629a747e4fSDavid du Colombier d->name = p+1;
2639a747e4fSDavid du Colombier else
2649a747e4fSDavid du Colombier d->name = f->new;
2659a747e4fSDavid du Colombier
2669a747e4fSDavid du Colombier mkaux->mkenum(f->new, mkaux->fullname.s, d, mkaux->a);
2679a747e4fSDavid du Colombier xmode = d->mode;
2689a747e4fSDavid du Colombier free(nd);
2699a747e4fSDavid du Colombier return (xmode&DMDIR) != 0;
2709a747e4fSDavid du Colombier }
2719a747e4fSDavid du Colombier
2729a747e4fSDavid du Colombier static char *
mkpath(Mkaux * mkaux,char * prefix,char * elem)2739a747e4fSDavid du Colombier mkpath(Mkaux *mkaux, char *prefix, char *elem)
2749a747e4fSDavid du Colombier {
2759a747e4fSDavid du Colombier char *p;
2769a747e4fSDavid du Colombier int n;
2779a747e4fSDavid du Colombier
2789a747e4fSDavid du Colombier n = strlen(prefix) + strlen(elem) + 2;
2799a747e4fSDavid du Colombier p = emalloc(mkaux, n);
2809a747e4fSDavid du Colombier strcpy(p, prefix);
2819a747e4fSDavid du Colombier strcat(p, "/");
2829a747e4fSDavid du Colombier strcat(p, elem);
2839a747e4fSDavid du Colombier return p;
2849a747e4fSDavid du Colombier }
2859a747e4fSDavid du Colombier
2869a747e4fSDavid du Colombier static void
setnames(Mkaux * mkaux,File * f)2879a747e4fSDavid du Colombier setnames(Mkaux *mkaux, File *f)
2889a747e4fSDavid du Colombier {
2899a747e4fSDavid du Colombier
2909a747e4fSDavid du Colombier if(f->old){
2919a747e4fSDavid du Colombier if(f->old[0] == '/')
2929a747e4fSDavid du Colombier setname(mkaux, &mkaux->oldfile, f->old, "");
2939a747e4fSDavid du Colombier else
2949a747e4fSDavid du Colombier setname(mkaux, &mkaux->oldfile, mkaux->xroot, f->old);
2959a747e4fSDavid du Colombier } else
2969a747e4fSDavid du Colombier setname(mkaux, &mkaux->oldfile, mkaux->xroot, f->new);
2979a747e4fSDavid du Colombier }
2989a747e4fSDavid du Colombier
2999a747e4fSDavid du Colombier static void
freefile(File * f)3009a747e4fSDavid du Colombier freefile(File *f)
3019a747e4fSDavid du Colombier {
3029a747e4fSDavid du Colombier if(f->old)
3039a747e4fSDavid du Colombier free(f->old);
3049a747e4fSDavid du Colombier if(f->new)
3059a747e4fSDavid du Colombier free(f->new);
3069a747e4fSDavid du Colombier free(f);
3079a747e4fSDavid du Colombier }
3089a747e4fSDavid du Colombier
3099a747e4fSDavid du Colombier /*
3109a747e4fSDavid du Colombier * skip all files in the proto that
3119a747e4fSDavid du Colombier * could be in the current dir
3129a747e4fSDavid du Colombier */
3139a747e4fSDavid du Colombier static void
skipdir(Mkaux * mkaux)3149a747e4fSDavid du Colombier skipdir(Mkaux *mkaux)
3159a747e4fSDavid du Colombier {
3169a747e4fSDavid du Colombier char *p, c;
3179a747e4fSDavid du Colombier int level;
3189a747e4fSDavid du Colombier
3199a747e4fSDavid du Colombier if(mkaux->indent < 0)
3209a747e4fSDavid du Colombier return;
3219a747e4fSDavid du Colombier level = mkaux->indent;
3229a747e4fSDavid du Colombier for(;;){
3239a747e4fSDavid du Colombier mkaux->indent = 0;
3249a747e4fSDavid du Colombier p = Brdline(mkaux->b, '\n');
3259a747e4fSDavid du Colombier mkaux->lineno++;
3269a747e4fSDavid du Colombier if(!p){
3279a747e4fSDavid du Colombier mkaux->indent = -1;
3289a747e4fSDavid du Colombier return;
3299a747e4fSDavid du Colombier }
3309a747e4fSDavid du Colombier while((c = *p++) != '\n')
3319a747e4fSDavid du Colombier if(c == ' ')
3329a747e4fSDavid du Colombier mkaux->indent++;
3339a747e4fSDavid du Colombier else if(c == '\t')
3349a747e4fSDavid du Colombier mkaux->indent += 8;
3359a747e4fSDavid du Colombier else
3369a747e4fSDavid du Colombier break;
3379a747e4fSDavid du Colombier if(mkaux->indent <= level){
3389a747e4fSDavid du Colombier Bseek(mkaux->b, -Blinelen(mkaux->b), 1);
3399a747e4fSDavid du Colombier mkaux->lineno--;
3409a747e4fSDavid du Colombier return;
3419a747e4fSDavid du Colombier }
3429a747e4fSDavid du Colombier }
3439a747e4fSDavid du Colombier }
3449a747e4fSDavid du Colombier
3459a747e4fSDavid du Colombier static File*
getfile(Mkaux * mkaux,File * old)3469a747e4fSDavid du Colombier getfile(Mkaux *mkaux, File *old)
3479a747e4fSDavid du Colombier {
3489a747e4fSDavid du Colombier File *f;
3499a747e4fSDavid du Colombier char *elem;
3509a747e4fSDavid du Colombier char *p;
3519a747e4fSDavid du Colombier int c;
3529a747e4fSDavid du Colombier
3539a747e4fSDavid du Colombier if(mkaux->indent < 0)
3549a747e4fSDavid du Colombier return 0;
3559a747e4fSDavid du Colombier loop:
3569a747e4fSDavid du Colombier mkaux->indent = 0;
3579a747e4fSDavid du Colombier p = Brdline(mkaux->b, '\n');
3589a747e4fSDavid du Colombier mkaux->lineno++;
3599a747e4fSDavid du Colombier if(!p){
3609a747e4fSDavid du Colombier mkaux->indent = -1;
3619a747e4fSDavid du Colombier return 0;
3629a747e4fSDavid du Colombier }
3639a747e4fSDavid du Colombier while((c = *p++) != '\n')
3649a747e4fSDavid du Colombier if(c == ' ')
3659a747e4fSDavid du Colombier mkaux->indent++;
3669a747e4fSDavid du Colombier else if(c == '\t')
3679a747e4fSDavid du Colombier mkaux->indent += 8;
3689a747e4fSDavid du Colombier else
3699a747e4fSDavid du Colombier break;
3709a747e4fSDavid du Colombier if(c == '\n' || c == '#')
3719a747e4fSDavid du Colombier goto loop;
3729a747e4fSDavid du Colombier p--;
3739a747e4fSDavid du Colombier f = emalloc(mkaux, sizeof *f);
3749a747e4fSDavid du Colombier p = getname(mkaux, p, &elem);
3759a747e4fSDavid du Colombier if(p == nil)
3769a747e4fSDavid du Colombier return nil;
3779a747e4fSDavid du Colombier
3789a747e4fSDavid du Colombier f->new = mkpath(mkaux, old->new, elem);
3799a747e4fSDavid du Colombier free(elem);
3809a747e4fSDavid du Colombier f->elem = utfrrune(f->new, L'/') + 1;
3819a747e4fSDavid du Colombier p = getmode(mkaux, p, &f->mode);
3829a747e4fSDavid du Colombier p = getname(mkaux, p, &f->uid); /* LEAK */
3839a747e4fSDavid du Colombier if(p == nil)
3849a747e4fSDavid du Colombier return nil;
3859a747e4fSDavid du Colombier
3869a747e4fSDavid du Colombier if(!*f->uid)
387*e0d6d19cSDavid du Colombier f->uid = "-"; /* LEAK */
3889a747e4fSDavid du Colombier p = getname(mkaux, p, &f->gid); /* LEAK */
3899a747e4fSDavid du Colombier if(p == nil)
3909a747e4fSDavid du Colombier return nil;
3919a747e4fSDavid du Colombier
3929a747e4fSDavid du Colombier if(!*f->gid)
393*e0d6d19cSDavid du Colombier f->gid = "-"; /* LEAK */
3949a747e4fSDavid du Colombier f->old = getpath(mkaux, p);
3959a747e4fSDavid du Colombier if(f->old && strcmp(f->old, "-") == 0){
3969a747e4fSDavid du Colombier free(f->old);
3979a747e4fSDavid du Colombier f->old = 0;
3989a747e4fSDavid du Colombier }
3999a747e4fSDavid du Colombier setnames(mkaux, f);
4009a747e4fSDavid du Colombier
4019a747e4fSDavid du Colombier return f;
4029a747e4fSDavid du Colombier }
4039a747e4fSDavid du Colombier
4049a747e4fSDavid du Colombier static char*
getpath(Mkaux * mkaux,char * p)4059a747e4fSDavid du Colombier getpath(Mkaux *mkaux, char *p)
4069a747e4fSDavid du Colombier {
4079a747e4fSDavid du Colombier char *q, *new;
4089a747e4fSDavid du Colombier int c, n;
4099a747e4fSDavid du Colombier
4109a747e4fSDavid du Colombier while((c = *p) == ' ' || c == '\t')
4119a747e4fSDavid du Colombier p++;
4129a747e4fSDavid du Colombier q = p;
4139a747e4fSDavid du Colombier while((c = *q) != '\n' && c != ' ' && c != '\t')
4149a747e4fSDavid du Colombier q++;
4159a747e4fSDavid du Colombier if(q == p)
4169a747e4fSDavid du Colombier return 0;
4179a747e4fSDavid du Colombier n = q - p;
4189a747e4fSDavid du Colombier new = emalloc(mkaux, n + 1);
4199a747e4fSDavid du Colombier memcpy(new, p, n);
4209a747e4fSDavid du Colombier new[n] = 0;
4219a747e4fSDavid du Colombier return new;
4229a747e4fSDavid du Colombier }
4239a747e4fSDavid du Colombier
4249a747e4fSDavid du Colombier static char*
getname(Mkaux * mkaux,char * p,char ** buf)4259a747e4fSDavid du Colombier getname(Mkaux *mkaux, char *p, char **buf)
4269a747e4fSDavid du Colombier {
4279a747e4fSDavid du Colombier char *s, *start;
4289a747e4fSDavid du Colombier int c;
4299a747e4fSDavid du Colombier
4309a747e4fSDavid du Colombier while((c = *p) == ' ' || c == '\t')
4319a747e4fSDavid du Colombier p++;
4329a747e4fSDavid du Colombier
4339a747e4fSDavid du Colombier start = p;
4349a747e4fSDavid du Colombier while((c = *p) != '\n' && c != ' ' && c != '\t')
4359a747e4fSDavid du Colombier p++;
4369a747e4fSDavid du Colombier
4379a747e4fSDavid du Colombier *buf = malloc(p+1-start);
4389a747e4fSDavid du Colombier if(*buf == nil)
4399a747e4fSDavid du Colombier return nil;
4409a747e4fSDavid du Colombier memmove(*buf, start, p-start);
4419a747e4fSDavid du Colombier
4429a747e4fSDavid du Colombier (*buf)[p-start] = '\0';
4439a747e4fSDavid du Colombier
4449a747e4fSDavid du Colombier if(**buf == '$'){
4459a747e4fSDavid du Colombier s = getenv(*buf+1);
4469a747e4fSDavid du Colombier if(s == 0){
4479a747e4fSDavid du Colombier warn(mkaux, "can't read environment variable %s", *buf+1);
4489a747e4fSDavid du Colombier skipdir(mkaux);
4499a747e4fSDavid du Colombier free(*buf);
4509a747e4fSDavid du Colombier return nil;
4519a747e4fSDavid du Colombier }
4529a747e4fSDavid du Colombier free(*buf);
4539a747e4fSDavid du Colombier *buf = s;
4549a747e4fSDavid du Colombier }
4559a747e4fSDavid du Colombier return p;
4569a747e4fSDavid du Colombier }
4579a747e4fSDavid du Colombier
4589a747e4fSDavid du Colombier static char*
getmode(Mkaux * mkaux,char * p,ulong * xmode)4599a747e4fSDavid du Colombier getmode(Mkaux *mkaux, char *p, ulong *xmode)
4609a747e4fSDavid du Colombier {
4619a747e4fSDavid du Colombier char *buf, *s;
4629a747e4fSDavid du Colombier ulong m;
4639a747e4fSDavid du Colombier
4649a747e4fSDavid du Colombier *xmode = ~0;
4659a747e4fSDavid du Colombier p = getname(mkaux, p, &buf);
4669a747e4fSDavid du Colombier if(p == nil)
4679a747e4fSDavid du Colombier return nil;
4689a747e4fSDavid du Colombier
4699a747e4fSDavid du Colombier s = buf;
4709a747e4fSDavid du Colombier if(!*s || strcmp(s, "-") == 0)
4719a747e4fSDavid du Colombier return p;
4729a747e4fSDavid du Colombier m = 0;
4739a747e4fSDavid du Colombier if(*s == 'd'){
4749a747e4fSDavid du Colombier m |= DMDIR;
4759a747e4fSDavid du Colombier s++;
4769a747e4fSDavid du Colombier }
4779a747e4fSDavid du Colombier if(*s == 'a'){
4789a747e4fSDavid du Colombier m |= DMAPPEND;
4799a747e4fSDavid du Colombier s++;
4809a747e4fSDavid du Colombier }
4819a747e4fSDavid du Colombier if(*s == 'l'){
4829a747e4fSDavid du Colombier m |= DMEXCL;
4839a747e4fSDavid du Colombier s++;
4849a747e4fSDavid du Colombier }
4859a747e4fSDavid du Colombier if(s[0] < '0' || s[0] > '7'
4869a747e4fSDavid du Colombier || s[1] < '0' || s[1] > '7'
4879a747e4fSDavid du Colombier || s[2] < '0' || s[2] > '7'
4889a747e4fSDavid du Colombier || s[3]){
4899a747e4fSDavid du Colombier warn(mkaux, "bad mode specification %s", buf);
4909a747e4fSDavid du Colombier free(buf);
4919a747e4fSDavid du Colombier return p;
4929a747e4fSDavid du Colombier }
4939a747e4fSDavid du Colombier *xmode = m | strtoul(s, 0, 8);
4949a747e4fSDavid du Colombier free(buf);
4959a747e4fSDavid du Colombier return p;
4969a747e4fSDavid du Colombier }
4979a747e4fSDavid du Colombier
4989a747e4fSDavid du Colombier static void
warn(Mkaux * mkaux,char * fmt,...)4999a747e4fSDavid du Colombier warn(Mkaux *mkaux, char *fmt, ...)
5009a747e4fSDavid du Colombier {
5019a747e4fSDavid du Colombier char buf[256];
5029a747e4fSDavid du Colombier va_list va;
5039a747e4fSDavid du Colombier
5049a747e4fSDavid du Colombier va_start(va, fmt);
5059a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, va);
5069a747e4fSDavid du Colombier va_end(va);
5079a747e4fSDavid du Colombier
5089a747e4fSDavid du Colombier if(mkaux->warn)
5099a747e4fSDavid du Colombier mkaux->warn(buf, mkaux->a);
5109a747e4fSDavid du Colombier else
5119a747e4fSDavid du Colombier fprint(2, "warning: %s\n", buf);
5129a747e4fSDavid du Colombier }
513