]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/libdisk/proto.c
upas/fs: fix infinite loop in putcache
[plan9front.git] / sys / src / libdisk / proto.c
index 30cada224320b1f0533a0d22883cd8344ad7ba07..962c054da2c2446da3d8d7104b5f0b10d5c9b443 100644 (file)
@@ -64,6 +64,8 @@ static void domkfs(Mkaux *mkaux, File *me, int level);
 
 static int     copyfile(Mkaux*, File*, Dir*, int);
 static void    freefile(File*);
+static void    freeoptptr(Opt*, void*);
+static char*   getline(Mkaux*);
 static File*   getfile(Mkaux*, File*);
 static char*   getmode(Mkaux*, char*, ulong*);
 static char*   getname(Mkaux*, char*, char**);
@@ -72,16 +74,11 @@ static int  mkfile(Mkaux*, File*);
 static char*   mkpath(Mkaux*, char*, char*);
 static void    mktree(Mkaux*, File*, int);
 static void    setname(Mkaux*, Name*, File*);
+static void    setopt(Mkaux*, char*, char*);
 static void    skipdir(Mkaux*);
 static void    warn(Mkaux*, char *, ...);
 static void    popopt(Mkaux *mkaux);
 
-//static void
-//mprint(char *new, char *old, Dir *d, void*)
-//{
-//     print("%s %s %D\n", new, old, d);
-//}
-
 int
 rdproto(char *proto, char *root, Mkfsenum *mkenum, Mkfserr *mkerr, void *a)
 {
@@ -151,7 +148,7 @@ domkfs(Mkaux *mkaux, File *me, int level)
        int rec;
 
        child = getfile(mkaux, me);
-       if(!child)
+       if(child == nil)
                return;
        if((child->elem[0] == '+' || child->elem[0] == '*') && child->elem[1] == '\0'){
                rec = child->elem[0] == '+';
@@ -162,13 +159,13 @@ domkfs(Mkaux *mkaux, File *me, int level)
                freefile(child);
                child = getfile(mkaux, me);
        }
-       while(child && mkaux->indent > level){
+       while(child != nil && mkaux->indent > level){
                if(mkfile(mkaux, child))
                        domkfs(mkaux, child, mkaux->indent);
                freefile(child);
                child = getfile(mkaux, me);
        }
-       if(child){
+       if(child != nil){
                freefile(child);
                Bseek(mkaux->b, -Blinelen(mkaux->b), 1);
                mkaux->lineno--;
@@ -198,15 +195,14 @@ mktree(Mkaux *mkaux, File *me, int rec)
                                        continue;
                        }
                        child.new = mkpath(mkaux, me->new, d[i].name);
-                       if(me->old)
+                       if(me->old != nil)
                                child.old = mkpath(mkaux, me->old, d[i].name);
                        child.elem = d[i].name;
                        setname(mkaux, &mkaux->oldfile, &child);
                        if((!(d[i].mode&DMDIR) || rec) && copyfile(mkaux, &child, &d[i], 1) && rec)
                                mktree(mkaux, &child, rec);
                        free(child.new);
-                       if(child.old)
-                               free(child.old);
+                       free(child.old);
                }
                free(d);
        }
@@ -281,11 +277,11 @@ copyfile(Mkaux *mkaux, File *f, Dir *d, int permonly)
        o = mkaux->opt;
        if(strcmp(f->uid, "-") != 0)
                d->uid = f->uid;
-       else if(o && o->uid)
+       else if(o != nil && o->uid != nil)
                d->uid = o->uid;
        if(strcmp(f->gid, "-") != 0)
                d->gid = f->gid;
-       else if(o && o->gid)
+       else if(o != nil && o->gid != nil)
                d->gid = o->gid;
        if(f->mode != ~0){
                if(permonly)
@@ -294,10 +290,10 @@ copyfile(Mkaux *mkaux, File *f, Dir *d, int permonly)
                        warn(mkaux, "inconsistent mode for %s", f->new);
                else
                        d->mode = f->mode;
-       } else if(o && o->mask)
+       } else if(o != nil && o->mask)
                d->mode = (d->mode & ~o->mask) | (o->mode & o->mask);
 
-       if(p = strrchr(f->new, '/'))
+       if((p = strrchr(f->new, '/')) != nil)
                d->name = p+1;
        else
                d->name = f->new;
@@ -415,28 +411,22 @@ setopt(Mkaux *mkaux, char *key, char *val)
        o = mkaux->opt;
        if(o == nil || mkaux->indent > o->level){
                o = emalloc(mkaux, sizeof(*o));
-               if(o == nil)
-                       longjmp(mkaux->jmp, 1);
-               if(mkaux->opt){
+               if(mkaux->opt != nil)
                        *o = *mkaux->opt;
-                       if(o->uid)
-                               o->uid = estrdup(mkaux, o->uid);
-                       if(o->gid)
-                               o->gid = estrdup(mkaux, o->gid);
-               }else
-                       memset(o, 0, sizeof(*o));
                o->level = mkaux->indent;
                o->prev = mkaux->opt;
                mkaux->opt = o;
        } else if(mkaux->indent < o->level)
                return;
        if(strcmp(key, "skip") == 0){
-               o->skip = regcomp(val);
+               freeoptptr(o, &o->skip);
+               if((o->skip = regcomp(val)) == nil)
+                       warn(mkaux, "bad regular expression %s", val);
        } else if(strcmp(key, "uid") == 0){
-               free(o->uid); 
+               freeoptptr(o, &o->uid);
                o->uid = *val ? estrdup(mkaux, val) : nil;
        } else if(strcmp(key, "gid") == 0){
-               free(o->gid); 
+               freeoptptr(o, &o->gid);
                o->gid = *val ? estrdup(mkaux, val) : nil;
        } else if(strcmp(key, "mode") == 0){
                if(!parsemode(val, &o->mask, &o->mode))
@@ -451,23 +441,37 @@ popopt(Mkaux *mkaux)
 {
        Opt *o;
 
-       while(o = mkaux->opt){
+       while((o = mkaux->opt) != nil){
                if(o->level <= mkaux->indent)
                        break;
                mkaux->opt = o->prev;
-               free(o->uid);
-               free(o->gid);
+               freeoptptr(o, &o->skip);
+               freeoptptr(o, &o->uid);
+               freeoptptr(o, &o->gid);
                free(o);
        }
 }
 
+static void
+freeoptptr(Opt *o, void *p)
+{
+       int x = (void**)p - (void**)o;
+       void *v = ((void**)o)[x];
+       if(v == nil)
+               return;
+       ((void**)o)[x] = nil;
+       if((o = o->prev) != nil)
+               if(((void**)o)[x] == v)
+                       return;
+       free(v);
+}
+
+
 static void
 freefile(File *f)
 {
-       if(f->old)
-               free(f->old);
-       if(f->new)
-               free(f->new);
+       free(f->old);
+       free(f->new);
        free(f);
 }
 
@@ -478,27 +482,10 @@ freefile(File *f)
 static void
 skipdir(Mkaux *mkaux)
 {
-       char *p, c;
        int level;
 
-       if(mkaux->indent < 0)
-               return;
        level = mkaux->indent;
-       for(;;){
-               mkaux->indent = 0;
-               mkaux->lineno++;
-               p = Brdline(mkaux->b, '\n');
-               if(p == nil || p[Blinelen(mkaux->b)-1] != '\n'){
-                       mkaux->indent = -1;
-                       return;
-               }
-               while((c = *p++) != '\n')
-                       if(c == ' ')
-                               mkaux->indent++;
-                       else if(c == '\t')
-                               mkaux->indent += 8;
-                       else
-                               break;
+       while(getline(mkaux) != nil){
                if(mkaux->indent <= level){
                        popopt(mkaux);
                        Bseek(mkaux->b, -Blinelen(mkaux->b), 1);
@@ -508,67 +495,92 @@ skipdir(Mkaux *mkaux)
        }
 }
 
-static File*
-getfile(Mkaux *mkaux, File *old)
+static char*
+getline(Mkaux *mkaux)
 {
-       File *f;
-       char *elem;
-       char *p, *s;
+       char *p;
        int c;
 
        if(mkaux->indent < 0)
                return nil;
 loop:
        mkaux->indent = 0;
-       mkaux->lineno++;
        p = Brdline(mkaux->b, '\n');
-       s = &p[Blinelen(mkaux->b)-1];
-       if(p == nil || *s != '\n'){
+       mkaux->lineno++;
+       if(p == nil){
                mkaux->indent = -1;
                return nil;
        }
-       *s = 0;
-       while((c = *p++) != 0)
+       if(memchr(p, 0, Blinelen(mkaux->b)) != nil){
+               warn(mkaux, "null bytes in proto");
+               longjmp(mkaux->jmp, 1);
+               return nil;
+       }
+       while((c = *p++) != '\n')
                if(c == ' ')
                        mkaux->indent++;
                else if(c == '\t')
                        mkaux->indent += 8;
                else
                        break;
-       if(c == 0 || c == '#')
+       if(c == '\n' || c == '#')
                goto loop;
-       p--;
+       return --p;
+}
+
+static File*
+getfile(Mkaux *mkaux, File *old)
+{
+       File *f;
+       char *elem;
+       char *p, *s;
+
+loop:
+       if((p = getline(mkaux)) == nil)
+               return nil;
        popopt(mkaux);
-       if(s = strchr(p, '=')){
+
+       *strchr(p, '\n') = 0;
+       if((s = strchr(p, '=')) != nil){
                *s++ = 0;
                setopt(mkaux, p, s);
                goto loop;
-       }
-       f = emalloc(mkaux, sizeof *f);
-       p = getname(mkaux, p, &elem);
-       if(p == nil)
+       }else
+               p[strlen(p)] = '\n';
+
+       if((p = getname(mkaux, p, &elem)) == nil)
                return nil;
+
+       f = emalloc(mkaux, sizeof *f);
        f->new = mkpath(mkaux, old->new, elem);
        free(elem);
        f->elem = utfrrune(f->new, L'/') + 1;
-       p = getmode(mkaux, p, &f->mode);
-       p = getname(mkaux, p, &f->uid); /* LEAK */
-       if(p == nil)
+
+       if((p = getmode(mkaux, p, &f->mode)) == nil){
+               freefile(f);
                return nil;
+       }
 
-       if(!*f->uid)
-               strcpy(f->uid, "-");
-       p = getname(mkaux, p, &f->gid); /* LEAK */
-       if(p == nil)
+       if((p = getname(mkaux, p, &f->uid)) == nil){
+               freefile(f);
                return nil;
+       }
+       if(*f->uid == 0)
+               strcpy(f->uid, "-");
 
-       if(!*f->gid)
+       if((p = getname(mkaux, p, &f->gid)) == nil){
+               freefile(f);
+               return nil;
+       }
+       if(*f->gid == 0)
                strcpy(f->gid, "-");
+
        f->old = getpath(mkaux, p);
-       if(f->old && strcmp(f->old, "-") == 0){
+       if(f->old != nil && strcmp(f->old, "-") == 0){
                free(f->old);
                f->old = nil;
        }
+
        setname(mkaux, &mkaux->oldfile, f);
 
        return f;
@@ -583,7 +595,7 @@ getpath(Mkaux *mkaux, char *p)
        while((c = *p) == ' ' || c == '\t')
                p++;
        q = p;
-       while((c = *q) != 0 && c != ' ' && c != '\t')
+       while((c = *q) != '\n' && c != ' ' && c != '\t')
                q++;
        if(q == p)
                return nil;
@@ -604,7 +616,7 @@ getname(Mkaux *mkaux, char *p, char **buf)
                p++;
 
        start = p;
-       while((c = *p) != 0 && c != ' ' && c != '\t')
+       while((c = *p) != '\n' && c != ' ' && c != '\t')
                p++;
 
        *buf = malloc(p+2-start);       /* +2: need at least 2 bytes; might strcpy "-" into buf */
@@ -612,14 +624,14 @@ getname(Mkaux *mkaux, char *p, char **buf)
                return nil;
        memmove(*buf, start, p-start);
 
-       (*buf)[p-start] = '\0';
+       (*buf)[p-start] = 0;
 
        if(**buf == '$'){
                s = getenv(*buf+1);
                if(s == nil){
                        warn(mkaux, "can't read environment variable %s", *buf+1);
-                       skipdir(mkaux);
                        free(*buf);
+                       skipdir(mkaux);
                        return nil;
                }
                free(*buf);
@@ -635,12 +647,11 @@ getmode(Mkaux *mkaux, char *p, ulong *xmode)
        ulong m;
 
        *xmode = ~0;
-       p = getname(mkaux, p, &buf);
-       if(p == nil)
+       if((p = getname(mkaux, p, &buf)) == nil)
                return nil;
 
        s = buf;
-       if(!*s || strcmp(s, "-") == 0)
+       if(*s == 0 || strcmp(s, "-") == 0)
                return p;
        m = 0;
        if(*s == 'd'){
@@ -678,7 +689,7 @@ warn(Mkaux *mkaux, char *fmt, ...)
        vseprint(buf, buf+sizeof(buf), fmt, va);
        va_end(va);
 
-       if(mkaux->warn)
+       if(mkaux->warn != nil)
                mkaux->warn(buf, mkaux->a);
        else
                fprint(2, "warning: %s\n", buf);