Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <bio.h>
#include "tapefs.h"

Idmap *
getpass(char *file)
{
        Biobuf *bp;
        char *cp;
        Idmap *up;
        int nid, maxid;
        char *line[4];

        if ((bp = Bopen(file, OREAD)) == 0)
                error("Can't open passwd/group");
        up = emalloc(1*sizeof(Idmap));
        maxid = 1;
        nid = 0;
        while ((cp = Brdline(bp, '\n'))) {
                int nf;
                cp[Blinelen(bp)-1] = 0;
                nf = getfields(cp, line, 3, 0, ":\n");
                if (nf<3) {
                        fprint(2, "bad format in %s\n", file);
                        break;
                }
                if (nid>=maxid) {
                        maxid *= 2;
                        up = (Idmap *)erealloc(up, maxid*sizeof(Idmap));
                }
                up[nid].id = atoi(line[2]);
                up[nid].name = strdup(line[0]);
                nid++;
        }               
        Bterm(bp);
        up[nid].name = 0;
        return up;
}

char *
mapid(Idmap *up, int id)
{
        char buf[16];

        if (up)
                while (up->name){
                        if (up->id==id)
                                return strdup(up->name);
                        up++;
                }
        sprint(buf, "%d", id);
        return strdup(buf);
}

Ram *
poppath(Fileinf fi, int new)
{
        char *suffix, *origname;
        Ram *dir, *ent;
        Fileinf f;

        if (*fi.name=='\0')
                return 0;
        origname = estrdup(fi.name);
        if (suffix=strrchr(fi.name, '/')){
                *suffix = 0;
                suffix++;
                if (*suffix=='\0'){
                        fi.mode |= DMDIR;
                        free(origname);
                        return poppath(fi, 1);
                }
                /*
                 * create parent directory of suffix;
                 * may recurse, thus shortening fi.name even further.
                 */
                f = fi;
                f.size = 0;
                f.addr = 0;
                f.mode = 0555|DMDIR;
                dir = poppath(f, 0);
                if (dir==0)
                        dir = ram;
        } else {
                suffix = fi.name;
                dir = ram;
                if (strcmp(suffix, ".")==0) {
                        free(origname);
                        return dir;
                }
        }
        ent = lookup(dir, suffix);
        fi.mode |= 0400;                        /* at least user read */
        if (ent){
                if (((fi.mode&DMDIR)!=0) != ((ent->qid.type&QTDIR)!=0)){
                        fprint(2,
                "%s file type changed; probably due to union dir.; ignoring\n",
                                origname);
                        free(origname);
                        return ent;
                }
                if (new)  {
                        ent->ndata = fi.size;
                        ent->addr = fi.addr;
                        ent->data = fi.data;
                        ent->perm = fi.mode;
                        ent->mtime = fi.mdate;
                        ent->user = mapid(uidmap, fi.uid);
                        ent->group = mapid(gidmap, fi.gid);
                }
        } else {
                fi.name = suffix;
                ent = popfile(dir, fi);
        }
        free(origname);
        return ent;
}

Ram *
popfile(Ram *dir, Fileinf fi)
{
        Ram *ent = (Ram *)emalloc(sizeof(Ram));
        if (*fi.name=='\0')
                return 0;
        ent->busy = 1;
        ent->open = 0;
        ent->parent = dir;
        ent->next = dir->child;
        dir->child = ent;
        ent->child = 0;
        ent->qid.path = ++path;
        ent->qid.vers = 0;
        if(fi.mode&DMDIR)
                ent->qid.type = QTDIR;
        else
                ent->qid.type = QTFILE;
        ent->perm = fi.mode;
        ent->name = estrdup(fi.name);
        ent->atime = ent->mtime = fi.mdate;
        ent->user = mapid(uidmap, fi.uid);
        ent->group = mapid(gidmap, fi.gid);
        ent->ndata = fi.size;
        ent->data = fi.data;
        ent->addr = fi.addr;
        ent->replete |= replete;
        return ent;
}

Ram *
lookup(Ram *dir, char *name)
{
        Ram *r;

        if (dir==0)
                return 0;
        for (r=dir->child; r; r=r->next){
                if (r->busy==0 || strcmp(r->name, name)!=0)
                        continue;
                return r;
        }
        return 0;
}