ref: 2c149cc04dbca3a1f4d5bf6b2a8917dfe7ebb92c
parent: 5ef5a68f7eddfd864d5a3fabcd240abf210cee7e
author: 9ferno <[email protected]>
date: Sat Nov 12 03:05:36 EST 2022
updated user processing
--- a/9p.c
+++ b/9p.c
@@ -38,18 +38,18 @@
return;
}
- if((uid = lookupid(req->ifcall.uname, 0)) <= 0){
+ if((uid = lookupid(req->ifcall.uname)) <= 0){
respond(req, "no such user");
return;
}
- dbuf = getbufchk(Broot, Breadonly, Tdentry, Qproot);
+ dbuf = getbufchk(Bdroot, Breadonly, Tdentry, Qproot);
if(dbuf == nil){
respond(req, "phase error");
return;
}
d = &dbuf->io->d;
- req->fid->aux = newaux(Broot, uid);
+ req->fid->aux = newaux(Bdroot, uid);
req->fid->qid = (Qid){Qproot, d->qid.version, QTDIR};
putbuf(dbuf);
req->ofcall.qid = req->fid->qid;
@@ -107,16 +107,16 @@
dir->length = 0;
if(buf == nil){
dir->name = estrdup9p(d->name);
- dir->uid = username(d->uid, 0, dir->uid);
- dir->gid = username(d->gid, 0, dir->gid);
- dir->muid = username(d->muid, 0, dir->muid);
+ dir->uid = username(d->uid, dir->uid);
+ dir->gid = username(d->gid, dir->gid);
+ dir->muid = username(d->muid, dir->muid);
}else{
memset(buf, 0, Namelen + 3 * Userlen);
strncpy(buf, d->name, Namelen - 1);
dir->name = buf;
- dir->uid = username(d->uid, 0, buf + Namelen);
- dir->gid = username(d->gid, 0, buf + Namelen + Userlen);
- dir->muid = username(d->muid, 0, buf + Namelen + 2 * Userlen);
+ dir->uid = username(d->uid, buf + Namelen);
+ dir->gid = username(d->gid, buf + Namelen + Userlen);
+ dir->muid = username(d->muid, buf + Namelen + 2 * Userlen);
}
}
@@ -229,7 +229,7 @@
/* TODO gid setting needs more fine tuning to align with stat(5) */
if(emptystr(req->d.gid) == 0 &&
- (gid = lookupid(req->d.gid, 0)) != 0){
+ (gid = lookupid(req->d.gid)) != 0){
d->gid = gid;
}
}
--- a/TODO
+++ b/TODO
@@ -1,4 +1,5 @@
test exclusive use file access
+streamline the error codes
mafswrite():
add user and remove user messages
users format has changed as per this http://9p.io/wiki/plan9/Setting_up_Fossil/index.html
--- a/all.h
+++ b/all.h
@@ -172,7 +172,7 @@
int ingroup(s16 uid, s16 gid, int locked);
void initconfig(u64 bno);
int leadgroup(s16 uid, s16 gid);
-s16 lookupid(char *name, int locked);
+s16 lookupid(char *name);
u64 min(u64 a, u64 b);
int mkqidcmp(Qid*, Dentry*);
void mkqid9p1(Qid9p1*, Qid*);
@@ -191,7 +191,7 @@
int strtouid(char*);
int strtouid1(char*);
void sync(void);
-char *username(s16 uid, int locked, char *username);
+char *username(s16 uid, char *username);
void usersinit(void);
void writeconfig(u64 bno);
--- a/dat.c
+++ b/dat.c
@@ -60,8 +60,10 @@
[Eqidmode] "wstat -- qid.type/dir.mode mismatch",
[Eronly] "file system read only",
[Ersc] "it's russ's fault. bug him.",
- [Eshutdown] "mafs shutting down",
- [Esystem] "mafs system error",
+ [Eshutdown] "m[]afs shutting down",
+ [Esystem] "m[a]fs system error",
[Etoolong] "name too long",
+ [Einvusers] "invalid users contents",
+ [Enousers] "no users",
[Ewalk] "walk -- too many (system wide)",
};
--- a/dat.h
+++ b/dat.h
@@ -15,39 +15,16 @@
GiB = KiB*MiB, /* Gibibytes */
TiB = KiB*GiB, /* Tibibytes */
- Nusers = 32, /* max. number of users */
+ Ngroups = 32, /* maximum number of groups an user can belong to */
None = 0, /* user ID for "none" */
Noworld = 9999, /* conventional id for "noworld" group */
Userlen = 32,
+
Nsec = 1000ULL*1000*1000,
Usec = 1000ULL*1000,
Msec = 1000ULL,
MAXRPC = 8192ULL,
Nbkp = 2,
-
- /* Qpnone is the Tag.path of free blocks/extents(Tfree),
- and zero'ed out dentry blocks */
- Qpnone = 0,
- Qpmagic = 1, /* magic block Tag.qpath */
- Qpconfig = 2, /* /adm/config block Tag.qpath */
- Qpsuper = 3, /* /adm/super block Tag.qpath */
-
- Qpadm = 5, /* /adm */
- Qpusers = 6, /* /adm/users */
- Qpbkp = 7, /* /adm/bkp block Tag.qpath */
- Qpconfig0 = 8, /* /adm/bkp/config.0 block Tag.qpath */
- Qpsuper0 = 9, /* /adm/bkp/super.0 block Tag.qpath */
- Qproot0 = 10, /* /adm/bkp/root.0 block Tag.qpath */
- Qpconfig1 = 11, /* /adm/bkp/config.1 block Tag.qpath */
- Qpsuper1 = 12, /* /adm/bkp/super.1 block Tag.qpath */
- Qproot1 = 13, /* /adm/bkp/root.1 block Tag.qpath */
- Qpctl = 14, /* /adm/ctl */
- Qpfrees = 15, /* /adm/frees block Tag.qpath */
- Nqidgen = 64,
- Qproot = Nqidgen-1, /* /, so fscreate() can disallow any create's below */
-
- /* check qpath for overflows - TODO, should be 2^64 */
- Maxqpath = 72057594037927936ULL, /* 2^56 */
};
/*
@@ -64,24 +41,55 @@
Bmagicb = 0, /* block number of first block. Bmagic conflicts with bio.h */
Bconfig = 1, /* block number of config contents */
Bsuper = 2, /* block number of super contents */
- Broot = 3, /* block number of root directory */
- Badm = 4, /* block number of /adm directory */
- Bdconfig = 5, /* block number of /adm/config dentry */
- Bdsuper = 6, /* block number of /adm/super dentry */
- Bdusers = 7, /* block number of /adm/users file */
- Busers = 8, /* block number of /adm/users file contents */
- Bbkp = 9, /* block number of /adm/bkp directory */
- Bdconfig0 = 10, /* block number of /adm/bkp/config.0 dentry */
- Bdsuper0 = 11, /* block number of /adm/bkp/super.0 dentry */
- Bdroot0 = 12, /* block number of /adm/bkp/root.0 dentry */
- Bdconfig1 = 13, /* block number of /adm/bkp/config.1 dentry */
- Bdsuper1 = 14, /* block number of /adm/bkp/super.1 dentry */
- Bdroot1 = 15, /* block number of /adm/bkp/root.1 dentry */
- Bdctl = 16, /* block number of /adm/ctl dentry, empty contents, virtual file */
- Bdfrees = 17, /* block number of /adm/frees dentry, text file of free extents */
- Nbused, /* blocks used up by default */
+ Bdadm = 3, /* block number of /adm directory */
+ Bdconfig= 4, /* block number of /adm/config dentry */
+ Bdsuper = 5, /* block number of /adm/super dentry */
+ Bdbkp = 6, /* block number of /adm/bkp directory */
+ Bdconfig0 = 7, /* block number of /adm/bkp/config.0 dentry */
+ Bdsuper0 = 8, /* block number of /adm/bkp/super.0 dentry */
+ Bdroot0 = 9, /* block number of /adm/bkp/root.0 dentry */
+ Bdconfig1 = 10, /* block number of /adm/bkp/config.1 dentry */
+ Bdsuper1 = 11, /* block number of /adm/bkp/super.1 dentry */
+ Bdroot1 = 12, /* block number of /adm/bkp/root.1 dentry */
+ Bdusers = 13, /* block number of /adm/users/ dentry */
+ Bdusersinuse = 14, /* block number of /adm/users/inuse dentry */
+ Busersinuse = 15, /* block number of /adm/users/inuse file contents */
+ Bdfrees = 16, /* block number of /adm/frees dentry, text file of free extents */
+
+ Bdctl = 17, /* block number of /adm/ctl dentry, empty contents, virtual file */
+ Bdusersstaging = 18,/* block number of /adm/users/staging dentry */
+ Bdroot = 19, /* block number of root directory */
+ Nbused, /* blocks used up by default */
Nminblocks = Nbused+(Nbkp*3), /* number of blocks used by the above and the backup blocks */
+ /* Qpnone is the Tag.path of free blocks/extents(Tfree),
+ and zero'ed out dentry blocks */
+ Qpnone = 0,
+ Qpmagic = 15, /* magic block Tag.qpath */
+ Qpconfig = Bconfig, /* /adm/config block Tag.qpath */
+ Qpsuper = Bsuper, /* /adm/super block Tag.qpath */
+
+ Qpadm = Bdadm, /* /adm */
+ Qpbkp = Bdbkp, /* /adm/bkp block Tag.qpath */
+ Qpconfig0 = Bdconfig0,/* /adm/bkp/config.0 block Tag.qpath */
+ Qpsuper0 = Bdsuper0, /* /adm/bkp/super.0 block Tag.qpath */
+ Qproot0 = Bdroot0, /* /adm/bkp/root.0 block Tag.qpath */
+ Qpconfig1 = Bdconfig1,/* /adm/bkp/config.1 block Tag.qpath */
+ Qpsuper1 = Bdsuper1, /* /adm/bkp/super.1 block Tag.qpath */
+ Qproot1 = Bdroot1, /* /adm/bkp/root.1 block Tag.qpath */
+ Qpusers = Bdusers, /* /adm/users block Tag.qpath */
+ Qpusersinuse = Bdusersinuse, /* /adm/users/inuse block Tag.qpath */
+ Qpfrees = Bdfrees, /* /adm/frees block Tag.qpath */
+
+ Qpctl = Bdctl, /* /adm/ctl */
+ Qpusersstaging = Bdusersstaging,/* /adm/users/staging block Tag.qpath */
+ Qproot = Bdroot, /* /, so fscreate() can disallow any create's below */
+
+ Nqidgen = 64,
+
+ /* check qpath for overflows - TODO, should be 2^64 */
+ Maxqpath = 72057594037927936ULL, /* 2^56 */
+
Nthdirty = 9, /* dirty byte is the 9th byte in the Tag */
};
@@ -214,14 +222,18 @@
/* u64 lastreadahead; TODO */
};
+/*
+ every user is also a group with one user.
+ */
struct User
{
s16 id; /* user id */
- s16 lid; /* id of the leader of group */
- s16 members[Nusers]; /* group table, member id's */
- int nmembers; /* number of group entries */
+ s16 lid; /* id of the leader of group */
char name[Userlen]; /* user name */
- User *next;
+ s16 *members;/* list of member id's belonging to this group */
+ int nmembers;/* number of members in this group */
+ int nalloc; /* allocated space members */
+ User *prev, *next; /* linked list sorted by id */
};
struct Bkp
@@ -245,6 +257,7 @@
Nworks = 1024, /* make this a parameter? */
Nprocs = 32, /* make this a parameter? */
Nlru = 32,
+ Nuserserrmsg = 64,
};
/*
@@ -296,7 +309,8 @@
Eshutdown,
Esystem,
Etoolong,
- Etoou64,
+ Einvusers,
+ Enousers,
Ewalk,
MAXERR
@@ -364,3 +378,4 @@
extern char *procname;
extern Config config;
+extern char userserrmsg[Nuserserrmsg];
--- a/docs/mafs.ms
+++ b/docs/mafs.ms
@@ -1509,25 +1509,42 @@
ramfs -m /n/ramfs
touch /n/ramfs/file
cat /dev/zero | tput -p > /n/ramfs/file
- 172.49 MB/s
- 174.56 MB/s
- 163.50 MB/s
- 125.00 MB/s
- 102.99 MB/s
- 87.81 MB/s
- 77.78 MB/s
- 69.50 MB/s
- 63.71 MB/s
- 58.65 MB/s
- 54.72 MB/s
+ 196.00 MB/s
+ 198.76 MB/s
+ 187.58 MB/s
+ 176.96 MB/s
+ 175.87 MB/s
+ 180.42 MB/s
+ 183.52 MB/s
+ 185.99 MB/s
+ 187.96 MB/s
+ 189.54 MB/s
+ 190.83 MB/s
+ 191.89 MB/s
+ 192.80 MB/s
dd -if /dev/zero -of /n/ramfs/file -count 700 -bs 1m
disk/mfs -r mfs_ramfs_file /n/ramfs/file
mount -c /srv/mfs_ramfs_file /n/mfs_ramfs_file
cat /dev/zero | tput -p > /n/mfs_ramfs_file/zeros.file
- 6.26 MB/s
- 5.99 MB/s
- 5.90 MB/s
+ 7.51 MB/s
+ 7.24 MB/s
+ 7.15 MB/s
+ 7.11 MB/s
+ 7.07 MB/s
+ 7.06 MB/s
+ 7.04 MB/s
+ 7.03 MB/s
+ 7.02 MB/s
+ 7.01 MB/s
+ 7.01 MB/s
+ 7.00 MB/s
+ 7.00 MB/s
+ 6.99 MB/s
+ 6.99 MB/s
+ 6.98 MB/s
+ 6.95 MB/s
+ 6.86 MB/s
echo halt >> /n/mfs_ramfs_file/adm/ctl; lc /srv
unmount /n/mfs_ramfs
@@ -1534,10 +1551,18 @@
disk/mafs -r mafs_ramafs_file /n/ramfs/file
mount -c /srv/mafs_ramafs_file /n/mafs_ramafs_file
cat /dev/zero | tput -p > /n/mafs_ramafs_file/zeros.file # throttles down to mfs speed
- 45.49 MB/s
- 31.52 MB/s
- 23.16 MB/s
- 24.54 MB/s
+ 33.12 MB/s
+ 33.17 MB/s
+ 33.08 MB/s
+ 32.34 MB/s
+ 26.87 MB/s
+ 23.22 MB/s
+ 20.63 MB/s
+ 18.67 MB/s
+ 17.16 MB/s
+ 15.94 MB/s
+ 14.94 MB/s
+ 14.11 MB/s
echo halt >> /n/mafs_ramafs_file/adm/ctl; lc /srv
unmount /n/ramfs
.fi
--- a/find.c
+++ b/find.c
@@ -64,7 +64,7 @@
if(debug)
print("%s %llud bytes %llud blocks\n", devfile, size, size/Rawblocksize);
- walkdentry(Broot, 0);
+ walkdentry(Bdroot, 0);
exits(0);
}
--- a/sub.c
+++ b/sub.c
@@ -234,16 +234,18 @@
{
Iobuf *b;
Dentry *d;
- char users[] = "-1:adm:adm:\n"
+ char users[128+Userlen*3];
+ char *user;
+
+ user = getuser();
+ snprint(users, 128+Userlen*3, "-1:adm:adm:%s\n"
"0:none:adm:\n" /* user ID for "none" */
"9999:noworld::\n" /* conventional id for "noworld" group */
"10000:sys::\n"
- "10001:upas:upas:\n"
- "10002:bootes:bootes:\n"
- "10006:glenda:glenda:\n"
- "10007:manies::\n";
+ "10001:upas:upas:\n" /* what is this for? */
+ "10006:%s:%s:\n", user, user, user);
- b = getbuf(Badm, Bwritable, Bfreshalloc);
+ b = getbuf(Bdadm, Bwritable, Bfreshalloc);
memset(b->io, 0, Rawblocksize);
settag(b, Tdentry, Qpadm);
d = &b->io->d;
@@ -256,17 +258,17 @@
d->qid.path = Qpadm;
d->qid.version = 0;
d->mtime = nsec();
- d->pdblkno = Broot;
+ d->pdblkno = Bdroot;
d->pqpath = Qproot;
- d->dblocks[0] = Bbkp;
+ d->dblocks[0] = Bdbkp;
d->dblocks[1] = Bdconfig;
- d->dblocks[2] = Bdctl;
- d->dblocks[3] = Bdsuper;
- d->dblocks[4] = Bdusers;
- d->dblocks[5] = Bdfrees;
+ d->dblocks[2] = Bdsuper;
+ d->dblocks[3] = Bdusers;
+ d->dblocks[4] = Bdfrees;
+ d->dblocks[5] = Bdctl;
putbuf(b);
- b = getbuf(Bbkp, Bwritable, Bfreshalloc);
+ b = getbuf(Bdbkp, Bwritable, Bfreshalloc);
memset(b->io, 0, Rawblocksize);
settag(b, Tdentry, Qpbkp);
d = &b->io->d;
@@ -280,7 +282,7 @@
d->qid.version = 0;
d->mtime = nsec();
d->size = strlen(users)+1;
- d->pdblkno = Badm;
+ d->pdblkno = Bdadm;
d->pqpath = Qpadm;
d->dblocks[0] = Bdconfig0;
d->dblocks[1] = Bdsuper0;
@@ -290,32 +292,55 @@
d->dblocks[5] = Bdroot1;
putbuf(b);
- reamfile(Bdconfig, Qpconfig, "config", 0, Badm, Qpadm, Bconfig);
- reamfile(Bdctl, Qpctl, "ctl", 0, Badm, Qpadm, 0);
- reamfile(Bdsuper, Qpsuper, "super", 0, Badm, Qpadm, Bsuper);
- reamfile(Bdusers, Qpusers, "users",
- strlen(users)+1, Badm, Qpadm, Busers);
- reamfile(Bdfrees, Qpfrees, "frees", 0, Badm, Qpadm, 0);
+ b = getbuf(Bdusers, Bwritable, Bfreshalloc);
+ memset(b->io, 0, Rawblocksize);
+ settag(b, Tdentry, Qpusers);
+ d = &b->io->d;
+ strncpy(d->name, "users", 4);
+ d->uid = d->muid = d->gid = -1;
+ d->mode = DMDIR |
+ ((DMREAD|DMWRITE|DMEXEC) << 6) |
+ ((DMREAD|DMWRITE|DMEXEC) << 3) |
+ ((DMREAD|DMWRITE|DMEXEC) << 0);
+ d->qid.path = Qpusers;
+ d->qid.version = 0;
+ d->mtime = nsec();
+ d->size = strlen(users)+1;
+ d->pdblkno = Bdadm;
+ d->pqpath = Qpadm;
+ d->dblocks[0] = Bdusersinuse;
+ d->dblocks[1] = Bdusersstaging;
+ putbuf(b);
+ reamfile(Bdconfig, Qpconfig, "config", 0, Bdadm, Qpadm, Bconfig);
+ reamfile(Bdctl, Qpctl, "ctl", 0, Bdadm, Qpadm, 0);
+ reamfile(Bdsuper, Qpsuper, "super", 0, Bdadm, Qpadm, Bsuper);
+ reamfile(Bdfrees, Qpfrees, "frees", 0, Bdadm, Qpadm, 0);
+
reamfile(Bdconfig0, Qpconfig0, "config.0",
- Blocksize, Bbkp, Qpbkp, config.config.dest[0]);
+ Blocksize, Bdbkp, Qpbkp, config.config.dest[0]);
reamfile(Bdsuper0, Qpsuper0, "super.0",
- Blocksize, Bbkp, Qpbkp, config.super.dest[0]);
+ Blocksize, Bdbkp, Qpbkp, config.super.dest[0]);
reamfile(Bdroot0, Qproot0, "root.0",
- Blocksize, Bbkp, Qpbkp, config.root.dest[0]);
+ Blocksize, Bdbkp, Qpbkp, config.root.dest[0]);
reamfile(Bdconfig1, Qpconfig1, "config.1",
- Blocksize, Bbkp, Qpbkp, config.config.dest[1]);
+ Blocksize, Bdbkp, Qpbkp, config.config.dest[1]);
reamfile(Bdsuper1, Qpsuper1, "super.1",
- Blocksize, Bbkp, Qpbkp, config.super.dest[1]);
+ Blocksize, Bdbkp, Qpbkp, config.super.dest[1]);
reamfile(Bdroot1, Qproot1, "root.1",
- Blocksize, Bbkp, Qpbkp, config.root.dest[1]);
+ Blocksize, Bdbkp, Qpbkp, config.root.dest[1]);
- b = getbuf(Busers, Bwritable, Bfreshalloc);
+ reamfile(Bdusersinuse, Qpusersinuse, "inuse",
+ Blocksize, Bdusers, Qpusers, Busersinuse);
+ reamfile(Bdusersstaging, Qpusersstaging, "staging",
+ Blocksize, Bdusers, Qpusers, 0);
+
+ b = getbuf(Busersinuse, Bwritable, Bfreshalloc);
if(b == nil)
panic("cannot get Busers");
memset(b->io, 0, Rawblocksize);
- settag(b, Tdata, Qpusers);
+ settag(b, Tdata, Qpusersinuse);
strcpy((char*)b->io->buf, users);
putbuf(b);
}
@@ -326,7 +351,7 @@
Iobuf *b;
Dentry *d;
- b = getbuf(Broot, Bwritable, Bfreshalloc);
+ b = getbuf(Bdroot, Bwritable, Bfreshalloc);
if(b == nil)
panic("rootream b == nil");
memset(b->io, 0, Rawblocksize);
@@ -343,7 +368,7 @@
d->qid.path = Qproot;
d->qid.version = 0;
d->mtime = nsec();
- d->dblocks[0] = Badm;
+ d->dblocks[0] = Bdadm;
putbuf(b);
}
@@ -372,8 +397,8 @@
config.config.dest[1] = nbused+((nblocks-nbused)/2)-Bconfig;
config.super.dest[0] = nblocks-Bsuper;
config.super.dest[1] = nbused+((nblocks-nbused)/2)-Bsuper;
- config.root.dest[0] = nblocks-Broot;
- config.root.dest[1] = nbused+((nblocks-nbused)/2)-Broot;
+ config.root.dest[0] = nblocks-3;
+ config.root.dest[1] = nbused+((nblocks-nbused)/2)-3;
for(i=0; i<Nbkp; i++){
reamdata(config.config.dest[i], Qpconfig0+3*i);
reamdata(config.super.dest[i], Qpsuper0+3*i);
@@ -403,7 +428,7 @@
/* this will enable backups */
config.config.srcbno = Bconfig;
config.super.srcbno = Bsuper;
- config.root.srcbno = Broot;
+ config.root.srcbno = Bdroot;
strncpy(config.service, service, Namelen);
fsok(0);
--- a/used.c
+++ b/used.c
@@ -52,7 +52,7 @@
initextents(&useds);
checkblock(Bmagicb, Tmagic, Qpmagic);
- walkdentry(Broot);
+ walkdentry(Bdroot);
close(devfd);
showextents(1, "", &useds);
exits(0);
--- a/user.c
+++ b/user.c
@@ -1,8 +1,8 @@
#include "all.h"
-static User *users;
-static u16 nusers;
+static User *lruuser; /* least recently used user */
static RWLock userslock;
+char userserrmsg[Nuserserrmsg];
int
checkname9p2(char* name)
@@ -38,37 +38,33 @@
return 0;
}
-/* t should be rlock'ed */
User *
-lookupuser(char *name, int locked)
+leastid(User *us)
{
User *u;
- if(locked == 0)
- rlock(&userslock);
- for(u = users; u != nil; u = u->next)
- if(strcmp(u->name, name) == 0)
- return u;
- if(locked == 0)
- chkrunlock(&userslock);
- return nil;
+ if(us == nil)
+ return nil;
+ for(u = us; u->prev != nil; u = u->prev)
+ ;
+ return u;
}
s16
-lookupid(char *name, int locked)
+lookupid(char *name)
{
User *u;
s16 id;
- if(locked == 0)
- rlock(&userslock);
- u = lookupuser(name, 1);
+ rlock(&userslock);
+ for(u = leastid(lruuser); u != nil; u = u->next)
+ if(strcmp(u->name, name) == 0)
+ break;
if(u == nil)
id = 0;
else
id = u->id;
- if(locked == 0)
- chkrunlock(&userslock);
+ chkrunlock(&userslock);
return id;
}
@@ -77,15 +73,14 @@
Hence, always call this with an rlock(&userslock)
*/
char *
-username(s16 uid, int locked, char *username)
+username(s16 uid, char *username)
{
User *u;
char *ret;
ret = nil;
- if(locked == 0)
- rlock(&userslock);
- for(u = users; u != nil; u = u->next){
+ rlock(&userslock);
+ for(u = leastid(lruuser); u != nil; u = u->next){
if(u->id == uid){
if(username == nil)
username = emalloc9p(Userlen); /* potential for a leak */
@@ -94,8 +89,7 @@
break;
}
}
- if(locked == 0)
- chkrunlock(&userslock);
+ chkrunlock(&userslock);
return ret;
}
@@ -112,7 +106,7 @@
found = 1;
goto Found;
}
- for(u = users; u != nil; u = u->next){
+ for(u = leastid(lruuser); u != nil; u = u->next){
if(u->id == gid){
for(i = 0; i < u->nmembers; i++){
if(u->members[i] == uid){
@@ -139,7 +133,7 @@
if(uid == gid)
return 1;
rlock(&userslock);
- for(u = users; u != nil; u = u->next)
+ for(u = leastid(lruuser); u != nil; u = u->next)
if(u->id == gid){
if(u->lid == uid){
ret = 1;
@@ -158,20 +152,116 @@
return ret;
}
-/* should be called with a locked t */
void
-syncusers(Tree *)
+freeusers(User *us)
{
- /* TODO */
+ User *u, *tmp;
+
+ if(us == nil)
+ return;
+ u = leastid(us);
+ while(u != nil){
+ if(u->members != nil)
+ free(u->members);
+ tmp = u;
+ u = u->next;
+ free(tmp);
+ }
}
+/* used by the parseusers(). No locking needed. */
+s16
+lookforid(User *us, char *name)
+{
+ User *u;
+ s16 id;
+
+ for(u = leastid(us); u != nil; u = u->next)
+ if(strcmp(u->name, name) == 0)
+ break;
+ if(u == nil)
+ id = 0;
+ else
+ id = u->id;
+ return id;
+}
+
+User *
+lookforuser(User *us, s16 uid)
+{
+ User *u;
+
+ for(u = leastid(us); u != nil; u = u->next)
+ if(u->id == uid)
+ return u;
+ return nil;
+}
+
+char *
+lookforname(User *us, s16 uid)
+{
+ User *u;
+
+ for(u = leastid(us); u != nil; u = u->next)
+ if(u->id == uid)
+ return u->name;
+ return nil;
+}
+
+int
+adduser(User *us, int id, char *name, User **up)
+{
+ User *u, *prevu, *new;
+
+ if(name == nil)
+ return snprint(userserrmsg, Nuserserrmsg-1, "invalid name");
+ if(baduname(name))
+ return snprint(userserrmsg, Nuserserrmsg-1, "invalid name");
+
+ for(u = leastid(us); u != nil; u = u->next){
+ if(u->id == id){
+ return snprint(userserrmsg, Nuserserrmsg-1,
+ "mafs: duplicate user ID %d (name %q)\n", id, u->name);
+ }else if(strcmp(u->name, name) == 0){
+ return snprint(userserrmsg, Nuserserrmsg-1,
+ "mafs: duplicate user name %q (id %d)\n", name, u->id);
+ }
+ }
+
+ new = malloc(sizeof(User));
+ new->id = id;
+ new->nmembers = 0;
+ strncpy(new->name, name, Userlen);
+
+ *up = new;
+ if(us == nil)
+ return 0;
+ for(u = leastid(us); u != nil && u->id < id; u = u->next){
+ prevu = u;
+ }
+ /* at the top/last */
+ if(u == nil){
+ prevu->next = new;
+ new->prev = prevu;
+ return 0;
+ }
+ if(u->prev != nil)
+ u->prev->next = new;
+ new->next = u;
+ new->prev = u->prev;
+ u->prev = new;
+ return 0;
+}
+
void
-addmember(User *u, char *memname)
+addmember(User *us, User *u, char *memname)
{
s16 x;
int i;
- x = lookupid(memname, 1);
+ if(us == nil || u == nil || memname == nil)
+ return;
+ x = lookforid(us, memname);
if(x > 0){
/* check for duplicate members */
for(i=0; i<u->nmembers; i++)
@@ -178,129 +268,205 @@
if(x == u->members[i])
return;
if(i == u->nmembers){
+ if(u->members == nil){
+ u->nalloc = 1;
+ u->members = emalloc9p(u->nalloc*sizeof(s16));
+ }else if(u->nmembers == u->nalloc){
+ u->nalloc++;
+ u->members = erealloc9p(u->members, u->nalloc*sizeof(s16));
+ }
u->members[u->nmembers++] = x;
}
}
}
-void
-adduser(int id, char *name, char *leader, char *members)
+int
+addmembers(User *us, User *u, char *members)
{
char *p, *ep;
- User *u;
char memname[Userlen];
- if(name == nil)
- panic("invalid name");
- if(baduname(name))
- panic("invalid name");
+ if(u == nil)
+ return snprint(userserrmsg, Nuserserrmsg-1, "invalid user");
- for(u = users; u != nil; u = u->next){
- if(u->id == id){
- dprint("mafs: duplicate user ID %d (name %q)\n", id, u->name);
- panic("mafs: duplicate user ID");
- return;
- }else if(strcmp(u->name, name) == 0){
- dprint("mafs: duplicate user name %q (id %d)\n", name, u->id);
- panic("mafs: duplicate user name");
- return;
- }
- }
-
- u = malloc(sizeof(User));
- u->id = id;
- u->nmembers = 0;
- strcpy(u->name, name);
- u->next = users;
- users = u;
- nusers++;
-
- if(leader == nil || leader[0] == '\0' || baduname(leader))
- u->lid = 0;
- else if(strcmp(name, leader) == 0)
- u->lid = id;
- else
- u->lid = lookupid(leader, 1);
-
p = members;
while((ep = strchr(p, ',')) != nil){
if(ep-p >= Userlen)
- panic("invalid name");
+ return snprint(userserrmsg, Nuserserrmsg-1, "memname too long");
else if(ep-p > 0){
*ep = '\0';
strncpy(memname, p, ep-p);
memname[ep-p] = '\0';
- if(memname != nil && baduname(memname) == 0)
- addmember(u, memname);
+ if(memname != nil){
+ if(baduname(memname))
+ return snprint(userserrmsg, Nuserserrmsg-1, "bad memname");
+ addmember(us, u, memname);
+ }
}
p = ep+1;
}
- if(p != nil && p[0] != '\0' && baduname(p) == 0)
- addmember(u, p);
+ if(p != nil && p[0] != '\0'){
+ if(baduname(p))
+ return snprint(userserrmsg, Nuserserrmsg-1, "last memname bad");
+ addmember(us, u, p);
+ }
+ return 0;
}
-void
-parseusers(char *raw)
+int
+addleader(User *us, User *u, char *leader)
{
- char *p, *ep;
+ if(u == nil)
+ return snprint(userserrmsg, Nuserserrmsg-1, "invalid user");
+
+ if(leader == nil || leader[0] == '\0' || baduname(leader))
+ u->lid = 0;
+ else if(strcmp(u->name, leader) == 0)
+ u->lid = u->id;
+ else
+ u->lid = lookforid(us, leader);
+ return 0;
+}
+
+/*
+ (uid:name:leader:member1,member2,...\n)+
+ first parse are the names, then, parse again
+ to add the leader and members to the group.
+ */
+s32
+parseusers(User **usp, s8 *raw, u64 usize)
+{
+ char *p, *ep, *line;
char *flds[5];
- User *u;
+ User *u, *us;
s32 i;
- char name[Userlen];
+ s32 rv;
+ u = us = nil;
p = raw;
- /* (uid:name:leader:member1,member2,...\n)+ */
- while((ep = strchr(p, '\n')) != nil){
- if(ep-p > 502){
- p[100] = '\0';
- panic("name line %s too long\n", p);
- }else if(ep-p > 0){
- *ep = '\0';
- if(getfields(p, flds, 4, 0, ":") != 4){
+ while(p-raw <= usize && (ep = strchr(p, '\n')) != nil){
+ /* skip blank lines or empty lines of :::*/
+ if(ep-p > 4){
+ line = emalloc9p(ep-p+1);
+ memcpy(line, p, ep-p);
+ if(getfields(line, flds, 4, 0, ":") != 4){
+ free(line);
dprint("invalid user data");
- goto Next;
+ freeusers(us);
+ return Einvusers;
}
- wlock(&userslock);
- adduser(atoi(flds[0]), flds[1], flds[2], flds[3]);
- chkwunlock(&userslock);
+ if((rv = adduser(us, atoi(flds[0]), flds[1], &u)) != 0){
+ free(line);
+ dprint("invalid adduser");
+ freeusers(us);
+ return rv;
+
+ }
+ if(us == nil && u != nil)
+ *usp = us = u;
+ free(line);
}
-Next:
p = ep+1;
}
- if(chatty9p > 2)
- for(u = users; u != nil; u = u->next){
- dprint("%d:%s:%d(%s):", u->id, u->name, u->lid, username(u->lid, 1, name));
- for(i = 0; i<u->nmembers; i++)
- dprint(" %d(%s)", u->members[i], username(u->members[i], 1, name));
- dprint("\n");
+ if(us == nil)
+ return Enousers;
+
+ p = raw;
+ while((ep = strchr(p, '\n')) != nil){
+ /* skip blank lines or empty lines of ::::*/
+ if(ep-p > 4){
+ line = emalloc9p(ep-p+1);
+ memcpy(line, p, ep-p);
+ if(getfields(line, flds, 4, 0, ":") != 4){
+ free(line);
+ dprint("invalid user data");
+ freeusers(us);
+ return Einvusers;
+ }
+ u = lookforuser(us, atoi(flds[0]));
+ if((rv = addleader(us, u, flds[2])) != 0){
+ free(line);
+ dprint("invalid addmembers");
+ freeusers(us);
+ return rv;
+
+ }
+ if((rv = addmembers(us, u, flds[3])) != 0){
+ free(line);
+ dprint("invalid addmembers %s\n", Nuserserrmsg);
+ freeusers(us);
+ return rv;
+
+ }
+ free(line);
+ }
+ p = ep+1;
}
+ if(chatty9p > 2)
+ for(u = leastid(us); u != nil; u = u->next){
+ dprint("%d:%s:%d(%s):", u->id, u->name, u->lid, lookforname(us, u->lid));
+ for(i = 0; i<u->nmembers; i++)
+ dprint(" %d(%s)", u->members[i], lookforname(us, u->lid));
+ dprint("\n");
+ }
+ *usp = us;
+ return 0;
}
+void
+usersinit(void)
+{
+ Iobuf *ubuf;
+ s8 *buf;
+ u64 usize;
+ User *us;
+ int rv;
+
+ ubuf = getbufchk(Bdusersinuse, Breadonly, Tdentry, Qpusersinuse);
+ usize = ubuf->io->d.size+1;
+ buf = emalloc9p(usize);
+ putbuf(ubuf);
+
+ readfile(Bdusersinuse, Qpusersinuse, buf, usize, 0);
+ if((rv=parseusers(&us, buf, usize)) != 0)
+ panic("could not parse /adm/users/inuse\n");
+ free(buf);
+ lruuser = us;
+}
+
/*
- TODO not bothering when the users file > 502 bytes.
- Can add that stuff later
+ read from /adm/user/staging
+ check that the contents are valid
+ check that -1 is the first entry TODO
+ check that 0 is the next entry TODO
+ write the contents to /adm/users/inuse
+ lruuser points to these new contents
*/
void
-usersinit(void)
+syncusers(void)
{
- Iobuf *ubuf, *ucbuf;
- char rem[Blocksize*2];
- Dentry *du;
+ Iobuf *ubuf;
+ s8 *buf;
+ u64 usize;
+ User *us, *old;
- ubuf = getbufchk(Bdusers, Breadonly, Tdentry, Qpusers);
- du = &ubuf->io->d;
- /* for(i = 0; i < Ndblock; i++){ */
- if(du->dblocks[0] == 0){
- putbuf(ubuf);
- return;
- }
- ucbuf = getbufchk(du->dblocks[0], Breadonly, Tdata, Qpusers);
- /* fill(rem, ucbuf->iobuf); */
- strncpy(rem, (char*)ucbuf->io->buf, Blocksize);
- parseusers(rem);
- putbuf(ucbuf);
- /* } */
+ ubuf = getbufchk(Bdusersstaging, Breadonly, Tdentry, Qpusersstaging);
+ usize = ubuf->io->d.size+1;
+ buf = emalloc9p(usize);
putbuf(ubuf);
+
+ readfile(Bdusersstaging, Qpusersstaging, buf, usize, 0);
+ if(parseusers(&us, buf, usize) != 0)
+ panic("could not parse /adm/users/staging\n");
+
+ wlock(&userslock);
+ old = lruuser;
+ writefile(Bdusersinuse, Qpusersinuse, -1, buf, usize, 0);
+ lruuser = us;
+ wunlock(&userslock);
+
+ freeusers(old);
+ free(buf);
}