ref: 6c35d0b041df30eacf7601d50d187adb90542b4d
parent: 104aa29f9fe37221d10e4cbaea1d8a8dd6b0d2ca
author: Ori Bernstein <[email protected]>
date: Sat Jan 1 16:29:51 EST 2022
fs: start checking permissions
--- a/TODO
+++ b/TODO
@@ -1,14 +1,11 @@
*** must have before usable for testing ***
- correctly implement deadlists
- auth against authservers
-- users and groups:
- - permission checks
- - user and group loading
-- complete wstat: implement missing operations
- implement special file modes: ORCLOSE, OEXCL, etc
-- add missing management commands in console
*** nice to have, can get testing without**
+- Reserve blocks for deletion
+- add missing management commands in console
- transient exec snapshots
- performance optimization:
- async page writeback: currently, every write to device is sync.
--- a/blk.c
+++ b/blk.c
@@ -251,8 +251,10 @@
PBIT64(p, (uvlong)LogEnd);
if(ol->head.addr == -1)
ol->head = lb->bp;
- if(ol->tail != lb)
+ if(ol->tail != lb){
+ putblk(ol->tail);
ol->tail = lb;
+ }
return 0;
}
@@ -476,13 +478,9 @@
*/
if((bp = blkalloc_lk(a)) == -1)
return -1;
- if((b = mallocz(sizeof(Blk), 1)) == nil)
+ if((b = initblk(bp, Tlog)) == nil)
return -1;
setflag(b, Bdirty);
- b->type = Tlog;
- b->bp.addr = bp;
- b->ref = 1;
- b->data = b->buf + Hdrsz;
b->logsz = Loghdsz;
PBIT64(b->data+b->logsz, (uvlong)LogEnd);
--- a/cache.c
+++ b/cache.c
@@ -7,7 +7,7 @@
#include "fns.h"
void
-cachedel(vlong del)
+cachedel_lk(vlong del)
{
Bucket *bkt;
Blk *b, **p;
@@ -42,6 +42,7 @@
b->cprev = nil;
clrflag(b, Bcached);
fs->ccount--;
+ putblk(b);
}
Blk*
@@ -87,14 +88,20 @@
fs->ccount++;
refblk(b);
}
- for(c = fs->ctail; c != nil && fs->ccount >= fs->cmax; c = fs->ctail){
- cachedel(c->bp.addr);
- putblk(c);
- }
+ for(c = fs->ctail; c != nil && fs->ccount >= fs->cmax; c = fs->ctail)
+ cachedel_lk(c->bp.addr);
Cached:
unlock(&fs->lrulk);
return b;
+}
+
+void
+cachedel(vlong del)
+{
+ lock(&fs->lrulk);
+ cachedel_lk(del);
+ unlock(&fs->lrulk);
}
Blk*
--- a/cons.c
+++ b/cons.c
@@ -99,13 +99,13 @@
for(i = 0; i < fs->nusers; i++){
u = &fs->users[i];
fprint(fd, "%d:%s:", u->id, u->name);
- if((v = uid2user(fs->users, fs->nusers, u->lead)) == nil)
+ if((v = uid2user(u->lead)) == nil)
fprint(fd, "???:");
else
fprint(fd, "%s:", v->name);
sep = "";
for(j = 0; j < u->nmemb; j++){
- if((v = uid2user(fs->users, fs->nusers, u->memb[j])) == nil)
+ if((v = uid2user(u->memb[j])) == nil)
fprint(fd, "%s???", sep);
else
fprint(fd, "%s%s", sep, v->name);
--- a/dat.h
+++ b/dat.h
@@ -274,6 +274,9 @@
Owmode = 1<<1, /* [4]mode: update file mode */
Owmtime = 1<<2, /* [8]mtime: update mtime, in nsec */
Owatime = 1<<3, /* [8]atime: update atime, in nsec */
+ Owuid = 1<<4, /* [4]uid: set uid */
+ Owgid = 1<<5, /* [4]uid: set gid */
+ Owmuid = 1<<6, /* [4]uid: set muid */
};
/*
@@ -439,14 +442,14 @@
struct Xdir {
/* file data */
Qid qid; /* unique id from server */
- vlong mode; /* permissions */
- vlong atime; /* last read time */
- vlong mtime; /* last write time */
+ int mode; /* permissions */
+ vlong atime; /* last read time: nsec */
+ vlong mtime; /* last write time: nsec */
uvlong length; /* file length */
int uid; /* owner name */
int gid; /* group name */
int muid; /* last modifier name */
- char name[Keymax]; /* last element of path */
+ char *name; /* last element of path */
};
struct Dent {
@@ -462,7 +465,7 @@
struct Mount {
long ref;
vlong gen;
- char *user;
+ int uid;
char *name;
Tree *root;
};
@@ -483,6 +486,10 @@
long ref;
int mode;
int iounit;
+
+ int duid;
+ int dgid;
+ int dmode;
Scan *scan; /* in progres scan */
Dent *dent; /* (pqid, name) ref, modified on rename */
--- a/dump.c
+++ b/dump.c
@@ -49,7 +49,7 @@
int n, ws;
char *p;
Tree t;
- Dir d;
+ Xdir d;
n = 0;
if(flg){
@@ -76,7 +76,7 @@
if(kv2dir(v, &d) == -1)
n = fmtprint(fmt, "bad dir");
else
- n = fmtprint(fmt, "[qid=(%lld,%lud,%d), %lo, t=%lud,%lud, l=%lld]",
+ n = fmtprint(fmt, "[qid=(%lld,%lud,%d), %o, t=%lld,%lld, l=%lld]",
d.qid.path, d.qid.vers, d.qid.type,
d.mode, d.atime, d.mtime, d.length);
break;
@@ -102,8 +102,20 @@
n += fmtprint(fmt, "mtime:%llx ", GBIT64(p));
p += 8;
}
+ if(ws & Owuid){
+ n += fmtprint(fmt, "uid:%d ", GBIT32(p));
+ p += 4;
+ }
+ if(ws & Owgid){
+ n += fmtprint(fmt, "gid:%d ", GBIT32(p));
+ p += 4;
+ }
+ if(ws & Owmuid){
+ n += fmtprint(fmt, "muid:%d ", GBIT32(p));
+ p += 4;
+ }
if(p != v->v + v->nv){
- fprint(2, "v->nv: %d\n", v->nv);
+ fprint(2, "v->nv: %d, sz=%d\n", v->nv, (int)(p - v->v));
abort();
}
break;
--- a/fns.h
+++ b/fns.h
@@ -52,8 +52,8 @@
void setval(Blk*, int, Kvp*);
char* loadusers(int, Tree*);
-User* uid2user(User*, int, int);
-User* name2user(User*, int, char*);
+User* uid2user(int);
+User* name2user(char*);
char* btupsert(Tree*, Msg*, int);
char* btlookup(Tree*, Key*, Kvp*, char*, int);
@@ -102,9 +102,10 @@
char* unpack32(int*, char*, char*, void*);
char* unpack64(int*, char*, char*, void*);
char* unpackstr(int*, char*, char*, char**);
-int dir2kv(vlong, Dir*, Kvp*, char*, int);
+int dir2kv(vlong, Xdir*, Kvp*, char*, int);
int kv2statbuf(Kvp*, char*, int);
-int kv2dir(Kvp*, Dir*);
+int dir2statbuf(Xdir*, char*, int);
+int kv2dir(Kvp*, Xdir*);
int kv2qid(Kvp*, Qid*);
char* packbp(char*, int, Bptr*);
@@ -112,6 +113,7 @@
char* packtree(char*, int, Tree*);
Tree* unpacktree(Tree*, char*, int);
char* packdkey(char*, int, vlong, char*);
+char* packdval(char*, int, Xdir*);
/* fmt */
int Bconv(Fmt*);
--- a/fs.c
+++ b/fs.c
@@ -9,7 +9,7 @@
static char* clearb(Fid*, vlong, vlong);
-// FIXME: hack.
+// FIXME: hack. We sync way too often.
static char*
updatesnap(Fid *f)
{
@@ -278,7 +278,7 @@
}
static Dent*
-getdent(vlong pqid, Dir *d)
+getdent(vlong pqid, Xdir *d)
{
Dent *de;
char *e;
@@ -296,6 +296,7 @@
if((de = mallocz(sizeof(Dent), 1)) == nil)
return nil;
+ de->Xdir = *d;
de->ref = 1;
de->qid = d->qid;
de->length = d->length;
@@ -497,6 +498,62 @@
respond(m, &r);
}
+int
+ingroup(int uid, int gid)
+{
+ User *u, *g;
+ int i, in;
+
+ rlock(&fs->userlk);
+ in = 0;
+ u = uid2user(uid);
+ g = uid2user(gid);
+ if(u != nil && g != nil)
+ for(i = 0; i < g->nmemb; i++)
+ if(u->id == g->memb[i])
+ in = 1;
+ runlock(&fs->userlk);
+ return in;
+}
+
+int
+mode2bits(int req)
+{
+ int m;
+
+ m = 0;
+ switch(req&0xf){
+ case OREAD: m = DMREAD; break;
+ case OWRITE: m = DMWRITE; break;
+ case ORDWR: m = DMREAD|DMWRITE; break;
+ case OEXEC: m = DMREAD|DMEXEC; break;
+ }
+ if(req&OTRUNC)
+ m |= DMWRITE;
+ return m;
+}
+
+int
+fsaccess(Mount *mnt, int fmode, int fuid, int fgid, int m)
+{
+ /* uid none gets only other permissions */
+ if(mnt->uid != 0) {
+ if(mnt->uid == fuid)
+ if((m & (fmode>>6)) == m)
+ return 0;
+ if(ingroup(mnt->uid, fgid))
+ if((m & (fmode>>3)) == m)
+ return 0;
+ }
+ if(m & fmode) {
+ if((fmode & DMDIR) && (m == DMEXEC))
+ return 0;
+ if(!ingroup(mnt->uid, 9999))
+ return 0;
+ }
+ return -1;
+}
+
static void
fsattach(Fmsg *m, int iounit)
{
@@ -503,11 +560,12 @@
char *e, *p, dbuf[Kvmax], kvbuf[Kvmax];
Mount *mnt;
Dent *de;
+ User *u;
Fcall r;
+ Xdir d;
Kvp kv;
Key dk;
Fid f;
- Dir d;
if((mnt = mallocz(sizeof(Mount), 1)) == nil){
rerror(m, Emem);
@@ -517,10 +575,15 @@
rerror(m, Emem);
return;
}
- if((mnt->user = strdup("glenda")) == nil){
- rerror(m, Emem);
+ rlock(&fs->userlk);
+ if((u = name2user("glenda")) == nil){
+ rerror(m, Enouser);
+ runlock(&fs->userlk);
return;
}
+ mnt->uid = u->id;
+ runlock(&fs->userlk);
+
if((mnt->root = openlabel(m->aname)) == nil){
rerror(m, Enosnap);
return;
@@ -560,6 +623,9 @@
f.mode = -1;
f.iounit = iounit;
f.dent = de;
+ f.duid = mnt->uid;
+ f.dgid = d.gid;
+ f.dmode = d.mode;
if(dupfid(m->fid, &f) == nil){
rerror(m, Enomem);
return;
@@ -575,13 +641,14 @@
fswalk(Fmsg *m)
{
char *p, *e, kbuf[Maxent], kvbuf[Kvmax];
+ int duid, dgid, dmode;
vlong up, prev;
Fid *o, *f;
Dent *dent;
Fcall r;
+ Xdir d;
Kvp kv;
Key k;
- Dir d;
int i;
if((o = getfid(m->fid)) == nil){
@@ -589,6 +656,7 @@
return;
}
if(o->mode != -1){
+print("use walk\n");
rerror(m, Einuse);
return;
}
@@ -595,6 +663,10 @@
e = nil;
up = o->qpath;
prev = o->qpath;
+ d = *o->dent;
+ duid = d.uid;
+ dgid = d.gid;
+ dmode = d.mode;
r.type = Rwalk;
for(i = 0; i < m->nwname; i++){
if((p = packdkey(kbuf, sizeof(kbuf), prev, m->wname[i])) == nil){
@@ -607,6 +679,9 @@
if((e = lookup(o, &k, &kv, kvbuf, sizeof(kvbuf), 0)) != nil){
break;
}
+ duid = d.uid;
+ dgid = d.gid;
+ dmode = d.mode;
if(kv2dir(&kv, &d) == -1){
rerror(m, Efs);
putfid(o);
@@ -643,6 +718,9 @@
if(i == m->nwname){
f->qpath = r.wqid[i-1].path;
f->dent = dent;
+ f->duid = duid;
+ f->dgid = dgid;
+ f->dmode = dmode;
}
}
respond(m, &r);
@@ -688,7 +766,8 @@
Fcall r;
Dent *de;
Msg mb[3];
- Dir o, d;
+ Xdir o;
+ Dir d;
Fid *f;
Kvp kv;
Key k;
@@ -709,6 +788,12 @@
}
de = f->dent;
k = f->dent->Key;
+ rlock(de);
+ if(fsaccess(f->mnt, de->mode, de->uid, de->gid, DMWRITE) == -1){
+ rerror(m, Eperm);
+ runlock(de);
+ return;
+ }
/* A nop qid change is allowed. */
if(d.qid.path != ~0 || d.qid.vers != ~0){
@@ -737,7 +822,7 @@
mb[nm].op = Odelete;
mb[nm].Key = f->dent->Key;
nm++;
- if((e = btlookup(f->mnt->root, f->dent, &kv, kvbuf, sizeof(kvbuf))) != nil){
+ if((e = btlookup(f->mnt->root, de, &kv, kvbuf, sizeof(kvbuf))) != nil){
rerror(m, e);
goto Out;
}
@@ -756,13 +841,17 @@
k = mb[nm].Key;
nm++;
}
+ runlock(de);
+ wlock(de);
p = opbuf+1;
op = 0;
mb[nm].Key = k;
mb[nm].op = Owstat;
+ de->qid.vers++;
if(d.length != ~0){
op |= Owsize;
+ de->length = d.length;
PBIT64(p, d.length);
p += 8;
sync = 0;
@@ -769,6 +858,7 @@
}
if(d.mode != ~0){
op |= Owmode;
+ de->mode = d.mode;
PBIT32(p, d.mode);
p += 4;
sync = 0;
@@ -775,14 +865,22 @@
}
if(d.mtime != ~0){
op |= Owmtime;
+ de->mtime = d.mtime;
PBIT64(p, (vlong)d.mtime*Nsec);
p += 8;
sync = 0;
}
+ op |= Owmuid;
+ de->muid = f->mnt->uid;
+ PBIT32(p, f->mnt->uid);
+ p += 4;
+ wunlock(de);
+
opbuf[0] = op;
mb[nm].v = opbuf;
mb[nm].nv = p - opbuf;
nm++;
+
if(sync){
rerror(m, Eimpl);
}else{
@@ -831,11 +929,11 @@
fscreate(Fmsg *m)
{
char *e, buf[Kvmax];
- Dent *dent;
+ Dent *de;
Fcall r;
Msg mb;
Fid *f;
- Dir d;
+ Xdir d;
if(okname(m->name) == -1){
rerror(m, Ename);
@@ -849,6 +947,15 @@
rerror(m, "unknown permission");
return;
}
+ de = f->dent;
+ rlock(de);
+ if(fsaccess(f->mnt, de->mode, de->uid, de->gid, DMWRITE) == -1){
+ rerror(m, Eperm);
+ runlock(de);
+ return;
+ }
+ runlock(de);
+
d.qid.type = 0;
if(m->perm & DMDIR)
d.qid.type |= QTDIR;
@@ -862,12 +969,13 @@
d.qid.vers = 0;
d.mode = m->perm;
d.name = m->name;
- d.atime = (nsec() + Nsec/2)/Nsec;
+ d.atime = nsec();
d.mtime = d.atime;
d.length = 0;
- d.uid = "glenda";
- d.gid = "glenda";
- d.muid = "glenda";
+ d.uid = f->mnt->uid;
+ d.gid = f->dgid;
+ d.muid = f->mnt->uid;
+
mb.op = Oinsert;
if(dir2kv(f->qpath, &d, &mb, buf, sizeof(buf)) == -1){
rerror(m, Efs);
@@ -879,8 +987,8 @@
putfid(f);
return;
}
- dent = getdent(f->qpath, &d);
- if(dent == nil){
+ de = getdent(f->qpath, &d);
+ if(de == nil){
if(m->fid != m->newfid)
clunkfid(f);
rerror(m, Enomem);
@@ -891,24 +999,25 @@
lock(f);
if(f->mode != -1){
unlock(f);
- clunkdent(dent);
+ clunkdent(de);
+print("use create\n");
rerror(m, Einuse);
putfid(f);
return;
}
- f->mode = m->mode;
+ f->mode = mode2bits(m->mode);
f->qpath = d.qid.path;
- f->dent = dent;
- wlock(f->dent);
- if((e = clearb(f, 0, dent->length)) != nil){
+ f->dent = de;
+ wlock(de);
+ if((e = clearb(f, 0, de->length)) != nil){
unlock(f);
- clunkdent(dent);
+ clunkdent(de);
rerror(m, e);
putfid(f);
return;
}
- dent->length = 0;
- wunlock(f->dent);
+ de->length = 0;
+ wunlock(de);
unlock(f);
r.type = Rcreate;
@@ -971,6 +1080,11 @@
clunkfid(f);
return;
}
+ if(fsaccess(f->mnt, f->dmode, f->duid, f->dgid, OWRITE) == -1){
+ rerror(m, Eperm);
+ runlock(f->dent);
+ return;
+ }
mb.op = Odelete;
mb.k = f->dent->k;
mb.nk = f->dent->nk;
@@ -1001,67 +1115,17 @@
clunkfid(f);
}
-int
-ingroup(char *user, char *group)
-{
- User *u, *g;
- int i, in;
-
- rlock(&fs->userlk);
- in = 0;
- u = name2user(fs->users, fs->nusers, user);
- g = name2user(fs->users, fs->nusers, group);
- if(u != nil && g != nil)
- for(i = 0; i < g->nmemb; i++)
- if(u->id == g->memb[i])
- in = 1;
- runlock(&fs->userlk);
- return in;
-}
-
-int
-fsaccess(Mount *mnt, Dir *d, int req)
-{
- int m;
-
- m = 0;
- switch(req&0xf){
- case OREAD: m = DMREAD; break;
- case OWRITE: m = DMWRITE; break;
- case ORDWR: m = DMREAD|DMWRITE; break;
- }
- if(req&OEXEC)
- m |= DMEXEC;
- if(req&OTRUNC)
- m |= DMWRITE;
-
- /* uid none gets only other permissions */
- if(strcmp(mnt->user, "none") != 0) {
- if(strcmp(mnt->user, d->uid) == 0)
- if((m<<6) & d->mode)
- return 0;
- if(ingroup(mnt->user, d->gid))
- if((m<<3) & d->mode)
- return 0;
- }
- if(m & d->mode) {
- if((d->mode & DMDIR) && (m == DMEXEC))
- return 0;
- if(!ingroup(mnt->user, "noworld"))
- return 0;
- }
- return -1;
-}
-
void
fsopen(Fmsg *m)
{
char *e, buf[Kvmax];
Fcall r;
- Dir d;
+ Xdir d;
Fid *f;
Kvp kv;
+ int mb;
+ mb = mode2bits(m->mode);
if((f = getfid(m->fid)) == nil){
rerror(m, Efid);
return;
@@ -1076,7 +1140,7 @@
putfid(f);
return;
}
- if(fsaccess(f->mnt, &d, m->mode) == -1){
+ if(fsaccess(f->mnt, d.mode, d.uid, d.gid, mb) == -1){
rerror(m, Eperm);
putfid(f);
return;
@@ -1091,12 +1155,13 @@
lock(f);
if(f->mode != -1){
rerror(m, Einuse);
+print("in use open\n");
unlock(f);
putfid(f);
return;
}
- f->mode = m->mode;
-// if((f->mode & 0x7) == OEXEC){
+ f->mode = mode2bits(m->mode);
+// if((f->mode & DMEXEC)){
// lock(&fs->root.lk);
// f->root = fs->root;
// refblk(fs->root.bp);
@@ -1119,7 +1184,6 @@
char pfx[Dpfxsz], *p, *e;
int n, ns, done;
Scan *s;
- Dir d;
s = f->scan;
if(s != nil && s->offset != 0 && s->offset != m->offset)
@@ -1143,7 +1207,6 @@
unlock(f);
}
if(s->done){
- fprint(2, "early done...\n");
r->count = 0;
return nil;
}
@@ -1150,8 +1213,7 @@
p = r->data;
n = m->count;
if(s->overflow){
- kv2dir(&s->kv, &d);
- if((ns = convD2M(&d, (uchar*)p, n)) <= BIT16SZ)
+ if((ns = kv2statbuf(&s->kv, p, n)) == -1)
return Edscan;
s->overflow = 0;
p += ns;
@@ -1162,8 +1224,7 @@
return e;
if(done)
break;
- kv2dir(&s->kv, &d);
- if((ns = convD2M(&d, (uchar*)p, n)) <= BIT16SZ){
+ if((ns = kv2statbuf(&s->kv, p, n)) == -1){
s->overflow = 1;
break;
}
@@ -1265,8 +1326,8 @@
rerror(m, Efid);
return;
}
- if((f->mode&0x7) != OWRITE){
- dprint("f->mode: %x\n", f->mode);
+ if(!(f->mode & DMWRITE)){
+print("f->mode: %x\n", f->mode);
rerror(m, Einuse);
putfid(f);
return;
@@ -1309,6 +1370,10 @@
p += 8;
f->dent->length = m->offset+m->count;
}
+ sbuf[0] |= Owmuid;
+ PBIT32(p, f->mnt->uid);
+ p += 4;
+
kv[i].v = sbuf;
kv[i].nv = p - sbuf;
if((e = btupsert(f->mnt->root, kv, i+1)) != nil){
--- a/pack.c
+++ b/pack.c
@@ -132,69 +132,68 @@
}
int
-dir2kv(vlong up, Dir *d, Kvp *kv, char *buf, int nbuf)
+dir2kv(vlong up, Xdir *d, Kvp *kv, char *buf, int nbuf)
{
- char *k, *ek, *v, *ev, *eb;
- int err;
+ char *ek, *ev, *eb;
- err = 0;
- k = buf;
- ek = buf;
+ if((ek = packdkey(buf, nbuf, up, d->name)) == nil)
+ return -1;
+ kv->k = buf;
+ kv->nk = ek - buf;
eb = buf + nbuf;
- ek = pack8(&err, ek, eb, Kent);
- ek = pack64(&err, ek, eb, up);
- ek = packstr(&err, ek, eb, d->name);
-
- v = ek;
- ev = ek;
- ev = pack64(&err, ev, eb, d->qid.path);
- ev = pack32(&err, ev, eb, d->qid.vers);
- ev = pack8(&err, ev, eb, d->qid.type);
- ev = pack32(&err, ev, eb, d->mode);
- ev = pack64(&err, ev, eb, (vlong)d->atime*Nsec);
- ev = pack64(&err, ev, eb, (vlong)d->mtime*Nsec);
- ev = pack64(&err, ev, eb, d->length);
- ev = packstr(&err, ev, eb, d->uid);
- ev = packstr(&err, ev, eb, d->gid);
- ev = packstr(&err, ev, eb, d->muid);
- if(err){
- werrstr("stat too big: %.*s...", 32, d->name);
+ if((ev = packdval(ek, eb - ek, d)) == nil)
return -1;
- }
- kv->k = k;
- kv->nk = ek - k;
- kv->v = v;
- kv->nv = ev - v;
+ kv->v = ek;
+ kv->nv = ev - ek;
return 0;
}
-int
-name2dkey(vlong up, char *name, Key *k, char *buf, int nbuf)
+char*
+packdkey(char *p, int sz, vlong up, char *name)
{
- char *ek, *eb;
+ char *ep;
int err;
err = 0;
- ek = buf;
- eb = buf + nbuf;
- ek = pack8(&err, ek, eb, Kent);
- ek = pack64(&err, ek, eb, up);
- ek = packstr(&err, ek, eb, name);
+ ep = p + sz;
+ p = pack8(&err, p, ep, Kent);
+ p = pack64(&err, p, ep, up);
+ p = packstr(&err, p, ep, name);
if(err)
- return -1;
- k->k = buf;
- k->nk = ek - buf;
- return k->nk;
+ return nil;
+ return p;
}
+char*
+packdval(char *p, int sz, Xdir *d)
+{
+ char *e;
+ int err;
+
+ err = 0;
+ e = p + sz;
+ p = pack64(&err, p, e, d->qid.path);
+ p = pack32(&err, p, e, d->qid.vers);
+ p = pack8(&err, p, e, d->qid.type);
+ p = pack32(&err, p, e, d->mode);
+ p = pack64(&err, p, e, d->atime);
+ p = pack64(&err, p, e, d->mtime);
+ p = pack64(&err, p, e, d->length);
+ p = pack32(&err, p, e, d->uid);
+ p = pack32(&err, p, e, d->gid);
+ p = pack32(&err, p, e, d->muid);
+ if(err)
+ abort();
+ return p;
+}
+
int
-kv2dir(Kvp *kv, Dir *d)
+kv2dir(Kvp *kv, Xdir *d)
{
char *k, *ek, *v, *ev;
- vlong atime, mtime;
int err;
- memset(d, 0, sizeof(Dir));
+ memset(d, 0, sizeof(Xdir));
err = 0;
k = kv->k + 9;
ek = kv->k + kv->nk;
@@ -210,12 +209,12 @@
v = unpack32(&err, v, ev, &d->qid.vers);
v = unpack8(&err, v, ev, &d->qid.type);
v = unpack32(&err, v, ev, &d->mode);
- v = unpack64(&err, v, ev, &atime);
- v = unpack64(&err, v, ev, &mtime);
+ v = unpack64(&err, v, ev, &d->atime);
+ v = unpack64(&err, v, ev, &d->mtime);
v = unpack64(&err, v, ev, &d->length);
- v = unpackstr(&err, v, ev, &d->uid);
- v = unpackstr(&err, v, ev, &d->gid);
- v = unpackstr(&err, v, ev, &d->muid);
+ v = unpack32(&err, v, ev, &d->uid);
+ v = unpack32(&err, v, ev, &d->gid);
+ v = unpack32(&err, v, ev, &d->muid);
if(err){
// print("fucked: %P\n", kv);
werrstr("val too small [%s]", d->name);
@@ -229,8 +228,6 @@
werrstr("stat full of fuck");
return -1;
}
- d->atime = (atime+Nsec/2)/Nsec;
- d->mtime = (mtime+Nsec/2)/Nsec;
return 0;
}
@@ -237,14 +234,59 @@
int
kv2statbuf(Kvp *kv, char *buf, int nbuf)
{
- Dir d;
- int n;
+ int sz, nn, nu, ng, nm, ret;
+ vlong atime, mtime;
+ User *u, *g, *m;
+ char *p;
+ Xdir d;
if(kv2dir(kv, &d) == -1)
return -1;
- if((n = convD2M(&d, (uchar*)buf, nbuf)) <= BIT16SZ)
- return -1;
- return n;
+
+ ret = -1;
+ rlock(&fs->userlk);
+ if((u = uid2user(d.uid)) == nil)
+ goto Out;
+ if((g = uid2user(d.gid)) == nil)
+ goto Out;
+ if((m = uid2user(d.muid)) == nil)
+ goto Out;
+
+ p = buf;
+ nn = strlen(d.name);
+ nu = strlen(u->name);
+ ng = strlen(g->name);
+ nm = strlen(m->name);
+ atime = (d.atime+Nsec/2)/Nsec;
+ mtime = (d.mtime+Nsec/2)/Nsec;
+ sz = STATFIXLEN + nn + nu + ng + nm;
+ if(sz > nbuf)
+ goto Out;
+
+ PBIT16(p, sz-2); p += 2;
+ PBIT16(p, -1 /*type*/); p += 2;
+ PBIT32(p, -1 /*dev*/); p += 4;
+ PBIT8(p, d.qid.type); p += 1;
+ PBIT32(p, d.qid.vers); p += 4;
+ PBIT64(p, d.qid.path); p += 8;
+ PBIT32(p, d.mode); p += 4;
+ PBIT32(p, atime); p += 4;
+ PBIT32(p, mtime); p += 4;
+ PBIT64(p, d.length); p += 8;
+
+ PBIT16(p, nn); p += 2;
+ memcpy(p, d.name, nn); p += nn;
+ PBIT16(p, nu); p += 2;
+ memcpy(p, u->name, nu); p += nu;
+ PBIT16(p, ng); p += 2;
+ memcpy(p, g->name, ng); p += ng;
+ PBIT16(p, nm); p += 2;
+ memcpy(p, m->name, nm); p += nm;
+ assert(p - buf == sz);
+ ret = sz;
+Out:
+ runlock(&fs->userlk);
+ return ret;
}
int
@@ -286,22 +328,6 @@
bp.hash = GBIT64(p); p += 8;
bp.gen = GBIT64(p);
return bp;
-}
-
-char*
-packdkey(char *p, int sz, vlong up, char *name)
-{
- char *ep;
- int err;
-
- err = 0;
- ep = p + sz;
- p = pack8(&err, p, ep, Kent);
- p = pack64(&err, p, ep, up);
- p = packstr(&err, p, ep, name);
- if(err)
- return 0;
- return p;
}
Tree*
--- a/ream.c
+++ b/ream.c
@@ -13,19 +13,19 @@
{
char buf[512];
Kvp kv;
- Dir d;
+ Xdir d;
/* nb: values must be inserted in key order */
memset(&d, 0, sizeof(Dir));
d.qid = (Qid){fs->nextqid++, 0, QTDIR};
- d.mode = 0755;
+ d.mode = DMDIR|0755;
d.atime = 0;
d.mtime = 0;
d.length = 0;
d.name = "";
- d.uid = "glenda";
- d.gid = "glenda";
- d.muid = "glenda";
+ d.uid = 2;
+ d.gid = 2;
+ d.muid = 2;
if(dir2kv(-1, &d, &kv, buf, sizeof(buf)) == -1)
sysfatal("ream: pack root: %r");
setval(r, 0, &kv);
@@ -101,7 +101,7 @@
b->bp.addr = addr;
b->logsz = 32;
b->data = b->buf + Hdrsz;
- setflag(b, Bdirty);
+ b->flag |= Bdirty;
p = b->data+Loghdsz;
PBIT64(p+ 0, addr|LogFree); /* addr */
--- a/tree.c
+++ b/tree.c
@@ -314,9 +314,9 @@
void
statupdate(Kvp *kv, Msg *m)
{
- int op, err;
- char *p, *e;
- Dir d;
+ int op;
+ char *p;
+ Xdir d;
p = m->v;
op = *p++;
@@ -339,26 +339,25 @@
d.atime = GBIT64(p);
p += 8;
}
+ if(op & Owuid){
+ d.uid = GBIT32(p);
+ p += 4;
+ }
+ if(op & Owgid){
+ d.gid = GBIT32(p);
+ p += 4;
+ }
+ if(op & Owmuid){
+ d.muid = GBIT32(p);
+ p += 4;
+ }
if(p != m->v + m->nv){
fprint(2, "kv=%P, m=%M\n", kv, m);
fprint(2, "malformed stat message (op=%x, len=%lld, sz=%d)\n", op, p - m->v, m->nv);
abort();
}
- err = 0;
- p = kv->v;
- e = kv->v + kv->nv;
- p = pack64(&err, p, e, d.qid.path);
- p = pack32(&err, p, e, d.qid.vers);
- p = pack8(&err, p, e, d.qid.type);
- p = pack32(&err, p, e, d.mode);
- p = pack64(&err, p, e, (vlong)d.atime*Nsec);
- p = pack64(&err, p, e, (vlong)d.mtime*Nsec);
- p = pack64(&err, p, e, d.length);
- p = packstr(&err, p, e, d.uid);
- p = packstr(&err, p, e, d.gid);
- p = packstr(&err, p, e, d.muid);
- if(err){
- fprint(2, "wstat not fixed size(%llx != %d)\n", p - kv->v, kv->nv);
+ if(packdval(kv->v, kv->nv, &d) == nil){
+ fprint(2, "repacking dir failed");
abort();
}
}
--- a/user.c
+++ b/user.c
@@ -14,7 +14,7 @@
"-1:adm::\n"
"0:none::\n"
"1:tor:tor:\n"
- "1:glenda:glenda:\n"
+ "2:glenda:glenda:\n"
"10000:sys::\n"
"10001:map:map:\n"
"10002:doc::\n"
@@ -27,9 +27,9 @@
{
char *p, kbuf[Keymax], rbuf[Kvmax];
int err;
+ Xdir d;
Kvp kv;
Key k;
- Dir d;
err = 0;
if((p = packdkey(kbuf, sizeof(kbuf), up, name)) == nil)
@@ -112,24 +112,24 @@
}
User*
-name2user(User *users, int nusers, char *name)
+name2user(char *name)
{
int i;
- for(i = 0; i < nusers; i++)
- if(strcmp(users[i].name, name) == 0)
- return &users[i];
+ for(i = 0; i < fs->nusers; i++)
+ if(strcmp(fs->users[i].name, name) == 0)
+ return &fs->users[i];
return nil;
}
User*
-uid2user(User *users, int nusers, int id)
+uid2user(int id)
{
int i;
- for(i = 0; i < nusers; i++)
- if(users[i].id == id)
- return &users[i];
+ for(i = 0; i < fs->nusers; i++)
+ if(fs->users[i].id == id)
+ return &fs->users[i];
return nil;
}
@@ -193,7 +193,11 @@
if((f = getfield(&p, ':')) == nil)
return Esyntax;
if(f[0] != '\0'){
- if((u = name2user(users, nusers, f)) == nil){
+ u = nil;
+ for(i = 0; i < nusers; i++)
+ if(strcmp(users[i].name, f) == 0)
+ u = &users[i];
+ if(u == nil){
fprint(fd, "/adm/users:%d: leader %s does not exist\n", lnum, f);
err = Enouser;
goto Error;
@@ -207,7 +211,11 @@
while((m = getfield(&f, ',')) != nil){
if(m[0] == '\0')
continue;
- if((u = name2user(users, nusers, m)) == nil){
+ u = nil;
+ for(i = 0; i < nusers; i++)
+ if(strcmp(users[i].name, m) == 0)
+ u = &users[i];
+ if(u == nil){
fprint(fd, "/adm/users:%d: user %s does not exist\n", lnum, m);
err = Enouser;
goto Error;