166 lines
2.9 KiB
C
166 lines
2.9 KiB
C
#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;
|
|
}
|