xref: /inferno-os/liblogfs/is.c (revision 28942ead413418b56c5be78e8c4c400881fba72e)
1*28942eadSforsyth #include "logfsos.h"
237da2899SCharles.Forsyth #include "logfs.h"
337da2899SCharles.Forsyth #include "fcall.h"
437da2899SCharles.Forsyth #include "local.h"
537da2899SCharles.Forsyth 
637da2899SCharles.Forsyth char *logfsisgroupnonename = "none";
737da2899SCharles.Forsyth 
837da2899SCharles.Forsyth char *
logfsisnew(LogfsIdentityStore ** isp)937da2899SCharles.Forsyth logfsisnew(LogfsIdentityStore **isp)
1037da2899SCharles.Forsyth {
1137da2899SCharles.Forsyth 	LogfsIdentityStore *is;
1237da2899SCharles.Forsyth 	char *errmsg;
1337da2899SCharles.Forsyth 
1437da2899SCharles.Forsyth 	is = logfsrealloc(nil, sizeof(*is));
1537da2899SCharles.Forsyth 	if(is == nil) {
1637da2899SCharles.Forsyth 	memerror:
1737da2899SCharles.Forsyth 		logfsisfree(&is);
1837da2899SCharles.Forsyth 		return Enomem;
1937da2899SCharles.Forsyth 	}
2037da2899SCharles.Forsyth 	errmsg = logfsustnew(&is->ids);
2137da2899SCharles.Forsyth 	if(errmsg)
2237da2899SCharles.Forsyth 		goto memerror;
2337da2899SCharles.Forsyth 	errmsg = logfsgroupmapnew(&is->groupmap, &is->unamemap);
2437da2899SCharles.Forsyth 	if(errmsg)
2537da2899SCharles.Forsyth 		goto memerror;
2637da2899SCharles.Forsyth 	logfsisgroupnonename = logfsustadd(is->ids, logfsisgroupnonename);
2737da2899SCharles.Forsyth 	*isp = is;
2837da2899SCharles.Forsyth 	return nil;
2937da2899SCharles.Forsyth }
3037da2899SCharles.Forsyth 
3137da2899SCharles.Forsyth void
logfsisfree(LogfsIdentityStore ** isp)3237da2899SCharles.Forsyth logfsisfree(LogfsIdentityStore **isp)
3337da2899SCharles.Forsyth {
3437da2899SCharles.Forsyth 	LogfsIdentityStore *is = *isp;
3537da2899SCharles.Forsyth 	if(is) {
3637da2899SCharles.Forsyth 		logfsustfree(&is->ids);
3737da2899SCharles.Forsyth 		logfsgroupmapfree(&is->groupmap);
3837da2899SCharles.Forsyth 		logfsunamemapfree(&is->unamemap);
3937da2899SCharles.Forsyth 		logfsfreemem(is);
4037da2899SCharles.Forsyth 		*isp = nil;
4137da2899SCharles.Forsyth 	}
4237da2899SCharles.Forsyth }
4337da2899SCharles.Forsyth 
4437da2899SCharles.Forsyth char *
logfsisgroupcreate(LogfsIdentityStore * is,char * groupname,char * groupid)4537da2899SCharles.Forsyth logfsisgroupcreate(LogfsIdentityStore *is, char *groupname, char *groupid)
4637da2899SCharles.Forsyth {
4737da2899SCharles.Forsyth 	Group *group;
4837da2899SCharles.Forsyth 	Uname *uname;
4937da2899SCharles.Forsyth 
5037da2899SCharles.Forsyth 	if(strcmp(groupname, logfsisgroupnonename) == 0 || groupname[0] == '(')
5137da2899SCharles.Forsyth 		return "group name reserved";
5237da2899SCharles.Forsyth 	groupname = logfsisustadd(is, groupname);
5337da2899SCharles.Forsyth 	groupid = logfsisustadd(is, groupid);
5437da2899SCharles.Forsyth 	if(groupname == nil || groupid == nil)
5537da2899SCharles.Forsyth 		return Enomem;
5637da2899SCharles.Forsyth 	return logfsgroupmapnewentry(is->groupmap, is->unamemap, groupid, groupname, &group, &uname);
5737da2899SCharles.Forsyth }
5837da2899SCharles.Forsyth 
5937da2899SCharles.Forsyth static Group *
findgroupfromuname(LogfsIdentityStore * is,char * groupname)6037da2899SCharles.Forsyth findgroupfromuname(LogfsIdentityStore *is, char *groupname)
6137da2899SCharles.Forsyth {
6237da2899SCharles.Forsyth 	Uname *u = logfsunamemapfindentry(is->unamemap, groupname);
6337da2899SCharles.Forsyth 	if(u == nil)
6437da2899SCharles.Forsyth 		return nil;
6537da2899SCharles.Forsyth 	return u->g;
6637da2899SCharles.Forsyth }
6737da2899SCharles.Forsyth 
6837da2899SCharles.Forsyth char *
logfsisgrouprename(LogfsIdentityStore * is,char * oldgroupname,char * newgroupname)6937da2899SCharles.Forsyth logfsisgrouprename(LogfsIdentityStore *is, char *oldgroupname, char *newgroupname)
7037da2899SCharles.Forsyth {
7137da2899SCharles.Forsyth 	Group *og, *ng;
7237da2899SCharles.Forsyth 	oldgroupname = logfsisustadd(is, oldgroupname);
7337da2899SCharles.Forsyth 	if(oldgroupname == nil)
7437da2899SCharles.Forsyth 		return Enomem;
7537da2899SCharles.Forsyth 	og =findgroupfromuname(is, oldgroupname);
7637da2899SCharles.Forsyth 	if(og == nil)
7737da2899SCharles.Forsyth 		return Enonexist;
7837da2899SCharles.Forsyth 	newgroupname = logfsisustadd(is, newgroupname);
7937da2899SCharles.Forsyth 	if(newgroupname == nil)
8037da2899SCharles.Forsyth 		return Enomem;
8137da2899SCharles.Forsyth 	ng = findgroupfromuname(is, newgroupname);
8237da2899SCharles.Forsyth 	if(ng != nil)
8337da2899SCharles.Forsyth 		return Eexist;
8437da2899SCharles.Forsyth 	og->uname = newgroupname;
8537da2899SCharles.Forsyth 	return nil;
8637da2899SCharles.Forsyth }
8737da2899SCharles.Forsyth 
8837da2899SCharles.Forsyth char *
logfsisgroupsetleader(LogfsIdentityStore * is,char * groupname,char * leadername)8937da2899SCharles.Forsyth logfsisgroupsetleader(LogfsIdentityStore *is, char *groupname, char *leadername)
9037da2899SCharles.Forsyth {
9137da2899SCharles.Forsyth 	Group *g, *lg;
9237da2899SCharles.Forsyth 	groupname = logfsisustadd(is, groupname);
9337da2899SCharles.Forsyth 	if(groupname == nil)
9437da2899SCharles.Forsyth 		return Enomem;
9537da2899SCharles.Forsyth 	g = findgroupfromuname(is, groupname);
9637da2899SCharles.Forsyth 	if(g == nil)
9737da2899SCharles.Forsyth 		return Enonexist;
9837da2899SCharles.Forsyth 	if(leadername && leadername[0]) {
9937da2899SCharles.Forsyth 		leadername = logfsisustadd(is, leadername);
10037da2899SCharles.Forsyth 		if(leadername == nil)
10137da2899SCharles.Forsyth 			return Enomem;
10237da2899SCharles.Forsyth 		lg = findgroupfromuname(is, leadername);
10337da2899SCharles.Forsyth 		if(lg == nil)
10437da2899SCharles.Forsyth 			return Enonexist;
10537da2899SCharles.Forsyth 		if(!logfsgroupsetismember(g->members, lg))
10637da2899SCharles.Forsyth 			return "not a member of the group";
10737da2899SCharles.Forsyth 		g->leader = lg;
10837da2899SCharles.Forsyth 	}
10937da2899SCharles.Forsyth 	else
11037da2899SCharles.Forsyth 		g->leader = nil;
11137da2899SCharles.Forsyth 	return nil;
11237da2899SCharles.Forsyth }
11337da2899SCharles.Forsyth 
11437da2899SCharles.Forsyth char *
logfsisgroupaddmember(LogfsIdentityStore * is,char * groupname,char * membername)11537da2899SCharles.Forsyth logfsisgroupaddmember(LogfsIdentityStore *is, char *groupname, char *membername)
11637da2899SCharles.Forsyth {
11737da2899SCharles.Forsyth 	Group *g, *mg;
11837da2899SCharles.Forsyth 	groupname = logfsisustadd(is, groupname);
11937da2899SCharles.Forsyth 	if(groupname == nil)
12037da2899SCharles.Forsyth 		return Enomem;
12137da2899SCharles.Forsyth 	g =findgroupfromuname(is, groupname);
12237da2899SCharles.Forsyth 	if(g == nil)
12337da2899SCharles.Forsyth 		return Enonexist;
12437da2899SCharles.Forsyth 	membername = logfsisustadd(is, membername);
12537da2899SCharles.Forsyth 	if(membername == nil)
12637da2899SCharles.Forsyth 		return Enomem;
12737da2899SCharles.Forsyth 	mg = findgroupfromuname(is, membername);
12837da2899SCharles.Forsyth 	if(mg == nil)
12937da2899SCharles.Forsyth 		return Enonexist;
13037da2899SCharles.Forsyth 	if(!logfsgroupsetadd(g->members, mg))
13137da2899SCharles.Forsyth 		return Enomem;
13237da2899SCharles.Forsyth 	return nil;
13337da2899SCharles.Forsyth }
13437da2899SCharles.Forsyth 
13537da2899SCharles.Forsyth char *
logfsisgroupremovemember(LogfsIdentityStore * is,char * groupname,char * nonmembername)13637da2899SCharles.Forsyth logfsisgroupremovemember(LogfsIdentityStore *is, char *groupname, char *nonmembername)
13737da2899SCharles.Forsyth {
13837da2899SCharles.Forsyth 	Group *g, *nonmg;
13937da2899SCharles.Forsyth 	groupname = logfsisustadd(is, groupname);
14037da2899SCharles.Forsyth 	if(groupname == nil)
14137da2899SCharles.Forsyth 		return Enomem;
14237da2899SCharles.Forsyth 	g =findgroupfromuname(is, groupname);
14337da2899SCharles.Forsyth 	if(g == nil)
14437da2899SCharles.Forsyth 		return Enonexist;
14537da2899SCharles.Forsyth 	nonmembername = logfsisustadd(is, nonmembername);
14637da2899SCharles.Forsyth 	if(nonmembername == nil)
14737da2899SCharles.Forsyth 		return Enomem;
14837da2899SCharles.Forsyth 	nonmg = findgroupfromuname(is, nonmembername);
14937da2899SCharles.Forsyth 	if(nonmg == nil)
15037da2899SCharles.Forsyth 		return Enonexist;
15137da2899SCharles.Forsyth 	if(!logfsgroupsetremove(g->members, nonmg))
15237da2899SCharles.Forsyth 		return Enonexist;
15337da2899SCharles.Forsyth 	if(g->leader == nonmg)
15437da2899SCharles.Forsyth 		g->leader = nil;
15537da2899SCharles.Forsyth 	return nil;
15637da2899SCharles.Forsyth }
15737da2899SCharles.Forsyth 
15837da2899SCharles.Forsyth typedef struct DS {
15937da2899SCharles.Forsyth 	char *printbuf;
16037da2899SCharles.Forsyth 	long printbufsize;
16137da2899SCharles.Forsyth 	void *buf;
16237da2899SCharles.Forsyth 	ulong offset;
16337da2899SCharles.Forsyth 	long n;
16437da2899SCharles.Forsyth 	ulong printoffset;
16537da2899SCharles.Forsyth 	int printn;
16637da2899SCharles.Forsyth 	int comma;
16737da2899SCharles.Forsyth } DS;
16837da2899SCharles.Forsyth 
16937da2899SCharles.Forsyth static int
printmember(void * magic,Group * member)17037da2899SCharles.Forsyth printmember(void *magic, Group *member)
17137da2899SCharles.Forsyth {
17237da2899SCharles.Forsyth 	DS *ds = magic;
17337da2899SCharles.Forsyth 	if(ds->comma) {
17437da2899SCharles.Forsyth 		if(ds->printn < ds->printbufsize)
17537da2899SCharles.Forsyth 			ds->printbuf[ds->printn++] = ',';
17637da2899SCharles.Forsyth 	}
17737da2899SCharles.Forsyth 	else
17837da2899SCharles.Forsyth 		ds->comma = 1;
17937da2899SCharles.Forsyth 	ds->printn += snprint(ds->printbuf + ds->printn, ds->printbufsize - ds->printn, "%s", member->uname);
18037da2899SCharles.Forsyth 	return 1;
18137da2899SCharles.Forsyth }
18237da2899SCharles.Forsyth 
18337da2899SCharles.Forsyth static int
printgroup(void * magic,Group * g)18437da2899SCharles.Forsyth printgroup(void *magic, Group *g)
18537da2899SCharles.Forsyth {
18637da2899SCharles.Forsyth 	DS *ds = magic;
18737da2899SCharles.Forsyth 	ds->printn = snprint(ds->printbuf, ds->printbufsize, "%s:%s:%s:",
18837da2899SCharles.Forsyth 		g->uid, g->uname, g->leader ? g->leader->uname : "");
18937da2899SCharles.Forsyth 	/* do members */
19037da2899SCharles.Forsyth 	ds->comma = 0;
19137da2899SCharles.Forsyth 	logfsgroupsetwalk(g->members, printmember, ds);
19237da2899SCharles.Forsyth 	if(ds->printn < ds->printbufsize)
19337da2899SCharles.Forsyth 		ds->printbuf[ds->printn++] = '\n';
19437da2899SCharles.Forsyth 	/*
19537da2899SCharles.Forsyth 	 * copy the appropriate part of the buffer
19637da2899SCharles.Forsyth 	 */
19737da2899SCharles.Forsyth 	if(ds->printoffset < ds->offset + ds->n && ds->printoffset + ds->printn > ds->offset) {
19837da2899SCharles.Forsyth 		char *printbuf = ds->printbuf;
19937da2899SCharles.Forsyth 		uchar *buf = ds->buf;
20037da2899SCharles.Forsyth 		long trim = ds->offset - ds->printoffset;
20137da2899SCharles.Forsyth 		if(trim >= 0) {
20237da2899SCharles.Forsyth 			printbuf += trim;
20337da2899SCharles.Forsyth 			ds->printn -= trim;
20437da2899SCharles.Forsyth 		}
20537da2899SCharles.Forsyth 		else
20637da2899SCharles.Forsyth 			buf -= trim;
20737da2899SCharles.Forsyth 		if(ds->printoffset + ds->printn > ds->offset + ds->n)
20837da2899SCharles.Forsyth 			ds->printn = ds->offset + ds->n - ds->printoffset;
209*28942eadSforsyth 		memmove(buf, printbuf, ds->printn);
21037da2899SCharles.Forsyth 	}
21137da2899SCharles.Forsyth 	/*
21237da2899SCharles.Forsyth 	 * advance print position
21337da2899SCharles.Forsyth 	 */
21437da2899SCharles.Forsyth 	ds->printoffset += ds->printn;
21537da2899SCharles.Forsyth 	/*
21637da2899SCharles.Forsyth 	 * stop if exceeding the buffer
21737da2899SCharles.Forsyth 	 */
21837da2899SCharles.Forsyth 	if(ds->printoffset >= ds->offset + ds->n)
21937da2899SCharles.Forsyth 		return 0;
22037da2899SCharles.Forsyth 	return 1;
22137da2899SCharles.Forsyth }
22237da2899SCharles.Forsyth 
22337da2899SCharles.Forsyth char *
logfsisusersread(LogfsIdentityStore * is,void * buf,long n,ulong offset,long * nr)22437da2899SCharles.Forsyth logfsisusersread(LogfsIdentityStore *is, void *buf, long n, ulong offset, long *nr)
22537da2899SCharles.Forsyth {
22637da2899SCharles.Forsyth 	DS ds;
22737da2899SCharles.Forsyth 	ds.buf = buf;
22837da2899SCharles.Forsyth 	ds.n = n;
22937da2899SCharles.Forsyth 	ds.printoffset = 0;
23037da2899SCharles.Forsyth 	ds.offset = offset;
23137da2899SCharles.Forsyth 	ds.printbufsize = 1024;
23237da2899SCharles.Forsyth 	ds.printbuf = logfsrealloc(nil, ds.printbufsize);
23337da2899SCharles.Forsyth 	if(ds.printbuf == nil)
23437da2899SCharles.Forsyth 		return Enomem;
23537da2899SCharles.Forsyth 	logfsmapwalk(is->groupmap, (LOGFSMAPWALKFN *)printgroup, &ds);
23637da2899SCharles.Forsyth 	*nr = ds.printoffset - ds.offset;
23737da2899SCharles.Forsyth 	logfsfreemem(ds.printbuf);
23837da2899SCharles.Forsyth 	return nil;
23937da2899SCharles.Forsyth }
24037da2899SCharles.Forsyth 
24137da2899SCharles.Forsyth int
logfsisgroupunameismember(LogfsIdentityStore * is,Group * g,char * uname)24237da2899SCharles.Forsyth logfsisgroupunameismember(LogfsIdentityStore *is, Group *g, char *uname)
24337da2899SCharles.Forsyth {
24437da2899SCharles.Forsyth 	Group *ug;
24537da2899SCharles.Forsyth 	if(g == nil)
24637da2899SCharles.Forsyth 		return 0;
24737da2899SCharles.Forsyth 	if(g->uname == uname)
24837da2899SCharles.Forsyth 		return 1;
24937da2899SCharles.Forsyth 	ug = logfsisfindgroupfromname(is, uname);
25037da2899SCharles.Forsyth 	if(ug == nil)
25137da2899SCharles.Forsyth 		return 0;
25237da2899SCharles.Forsyth 	return logfsgroupsetismember(g->members, ug);
25337da2899SCharles.Forsyth }
25437da2899SCharles.Forsyth 
25537da2899SCharles.Forsyth int
logfsisgroupuidismember(LogfsIdentityStore * is,Group * g,char * uid)25637da2899SCharles.Forsyth logfsisgroupuidismember(LogfsIdentityStore *is, Group *g, char *uid)
25737da2899SCharles.Forsyth {
25837da2899SCharles.Forsyth 	Group *ug;
25937da2899SCharles.Forsyth 	if(g == nil)
26037da2899SCharles.Forsyth 		return 0;
26137da2899SCharles.Forsyth 	if(g->uid == uid)
26237da2899SCharles.Forsyth 		return 1;
26337da2899SCharles.Forsyth 	ug = logfsisfindgroupfromid(is, uid);
26437da2899SCharles.Forsyth 	if(ug == nil)
26537da2899SCharles.Forsyth 		return 0;
26637da2899SCharles.Forsyth 	return logfsgroupsetismember(g->members, ug);
26737da2899SCharles.Forsyth }
26837da2899SCharles.Forsyth 
26937da2899SCharles.Forsyth int
logfsisgroupuidisleader(LogfsIdentityStore * is,Group * g,char * id)27037da2899SCharles.Forsyth logfsisgroupuidisleader(LogfsIdentityStore *is, Group *g, char *id)
27137da2899SCharles.Forsyth {
27237da2899SCharles.Forsyth 	if(g->leader)
27337da2899SCharles.Forsyth 		return g->leader->uid == id;
27437da2899SCharles.Forsyth 	return logfsisgroupuidismember(is, g, id);
27537da2899SCharles.Forsyth }
27637da2899SCharles.Forsyth 
27737da2899SCharles.Forsyth Group *
logfsisfindgroupfromname(LogfsIdentityStore * is,char * name)27837da2899SCharles.Forsyth logfsisfindgroupfromname(LogfsIdentityStore *is, char *name)
27937da2899SCharles.Forsyth {
28037da2899SCharles.Forsyth 	Uname *u;
28137da2899SCharles.Forsyth 	u = logfsunamemapfindentry(is->unamemap, name);
28237da2899SCharles.Forsyth 	if(u == nil)
28337da2899SCharles.Forsyth 		return nil;
28437da2899SCharles.Forsyth 	return u->g;
28537da2899SCharles.Forsyth }
28637da2899SCharles.Forsyth 
28737da2899SCharles.Forsyth char *
logfsisfindidfromname(LogfsIdentityStore * is,char * name)28837da2899SCharles.Forsyth logfsisfindidfromname(LogfsIdentityStore *is, char *name)
28937da2899SCharles.Forsyth {
29037da2899SCharles.Forsyth 	char *id;
29137da2899SCharles.Forsyth 	id = logfsunamemapfinduid(is->unamemap, name);
29237da2899SCharles.Forsyth 	if(id == nil)
29337da2899SCharles.Forsyth 		return logfsisgroupnonename;
29437da2899SCharles.Forsyth 	return id;
29537da2899SCharles.Forsyth }
29637da2899SCharles.Forsyth 
29737da2899SCharles.Forsyth char *
logfsisfindnamefromid(LogfsIdentityStore * is,char * id)29837da2899SCharles.Forsyth logfsisfindnamefromid(LogfsIdentityStore *is, char *id)
29937da2899SCharles.Forsyth {
30037da2899SCharles.Forsyth 	Group *g;
30137da2899SCharles.Forsyth 	g = logfsgroupmapfindentry(is->groupmap, id);
30237da2899SCharles.Forsyth 	if(g == nil)
30337da2899SCharles.Forsyth 		return nil;
30437da2899SCharles.Forsyth 	return g->uname;
30537da2899SCharles.Forsyth }
306