|  | #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; | 
|  | Ram *dir, *ent; | 
|  | Fileinf f; | 
|  |  | 
|  | if (*fi.name=='\0') | 
|  | return 0; | 
|  | if (suffix=strrchr(fi.name, '/')){ | 
|  | *suffix = 0; | 
|  | suffix++; | 
|  | if (*suffix=='\0'){ | 
|  | fi.mode |= DMDIR; | 
|  | return poppath(fi, 1); | 
|  | } | 
|  | 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) | 
|  | 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/%s directory botch\n", fi.name, suffix); | 
|  | exits(""); | 
|  | } | 
|  | 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); | 
|  | } | 
|  | 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; | 
|  | } |