summaryrefslogtreecommitdiff
path: root/liblogfs/is.c
diff options
context:
space:
mode:
Diffstat (limited to 'liblogfs/is.c')
-rw-r--r--liblogfs/is.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/liblogfs/is.c b/liblogfs/is.c
new file mode 100644
index 00000000..dfd6f95f
--- /dev/null
+++ b/liblogfs/is.c
@@ -0,0 +1,305 @@
+#include "lib9.h"
+#include "logfs.h"
+#include "fcall.h"
+#include "local.h"
+
+char *logfsisgroupnonename = "none";
+
+char *
+logfsisnew(LogfsIdentityStore **isp)
+{
+ LogfsIdentityStore *is;
+ char *errmsg;
+
+ is = logfsrealloc(nil, sizeof(*is));
+ if(is == nil) {
+ memerror:
+ logfsisfree(&is);
+ return Enomem;
+ }
+ errmsg = logfsustnew(&is->ids);
+ if(errmsg)
+ goto memerror;
+ errmsg = logfsgroupmapnew(&is->groupmap, &is->unamemap);
+ if(errmsg)
+ goto memerror;
+ logfsisgroupnonename = logfsustadd(is->ids, logfsisgroupnonename);
+ *isp = is;
+ return nil;
+}
+
+void
+logfsisfree(LogfsIdentityStore **isp)
+{
+ LogfsIdentityStore *is = *isp;
+ if(is) {
+ logfsustfree(&is->ids);
+ logfsgroupmapfree(&is->groupmap);
+ logfsunamemapfree(&is->unamemap);
+ logfsfreemem(is);
+ *isp = nil;
+ }
+}
+
+char *
+logfsisgroupcreate(LogfsIdentityStore *is, char *groupname, char *groupid)
+{
+ Group *group;
+ Uname *uname;
+
+ if(strcmp(groupname, logfsisgroupnonename) == 0 || groupname[0] == '(')
+ return "group name reserved";
+ groupname = logfsisustadd(is, groupname);
+ groupid = logfsisustadd(is, groupid);
+ if(groupname == nil || groupid == nil)
+ return Enomem;
+ return logfsgroupmapnewentry(is->groupmap, is->unamemap, groupid, groupname, &group, &uname);
+}
+
+static Group *
+findgroupfromuname(LogfsIdentityStore *is, char *groupname)
+{
+ Uname *u = logfsunamemapfindentry(is->unamemap, groupname);
+ if(u == nil)
+ return nil;
+ return u->g;
+}
+
+char *
+logfsisgrouprename(LogfsIdentityStore *is, char *oldgroupname, char *newgroupname)
+{
+ Group *og, *ng;
+ oldgroupname = logfsisustadd(is, oldgroupname);
+ if(oldgroupname == nil)
+ return Enomem;
+ og =findgroupfromuname(is, oldgroupname);
+ if(og == nil)
+ return Enonexist;
+ newgroupname = logfsisustadd(is, newgroupname);
+ if(newgroupname == nil)
+ return Enomem;
+ ng = findgroupfromuname(is, newgroupname);
+ if(ng != nil)
+ return Eexist;
+ og->uname = newgroupname;
+ return nil;
+}
+
+char *
+logfsisgroupsetleader(LogfsIdentityStore *is, char *groupname, char *leadername)
+{
+ Group *g, *lg;
+ groupname = logfsisustadd(is, groupname);
+ if(groupname == nil)
+ return Enomem;
+ g = findgroupfromuname(is, groupname);
+ if(g == nil)
+ return Enonexist;
+ if(leadername && leadername[0]) {
+ leadername = logfsisustadd(is, leadername);
+ if(leadername == nil)
+ return Enomem;
+ lg = findgroupfromuname(is, leadername);
+ if(lg == nil)
+ return Enonexist;
+ if(!logfsgroupsetismember(g->members, lg))
+ return "not a member of the group";
+ g->leader = lg;
+ }
+ else
+ g->leader = nil;
+ return nil;
+}
+
+char *
+logfsisgroupaddmember(LogfsIdentityStore *is, char *groupname, char *membername)
+{
+ Group *g, *mg;
+ groupname = logfsisustadd(is, groupname);
+ if(groupname == nil)
+ return Enomem;
+ g =findgroupfromuname(is, groupname);
+ if(g == nil)
+ return Enonexist;
+ membername = logfsisustadd(is, membername);
+ if(membername == nil)
+ return Enomem;
+ mg = findgroupfromuname(is, membername);
+ if(mg == nil)
+ return Enonexist;
+ if(!logfsgroupsetadd(g->members, mg))
+ return Enomem;
+ return nil;
+}
+
+char *
+logfsisgroupremovemember(LogfsIdentityStore *is, char *groupname, char *nonmembername)
+{
+ Group *g, *nonmg;
+ groupname = logfsisustadd(is, groupname);
+ if(groupname == nil)
+ return Enomem;
+ g =findgroupfromuname(is, groupname);
+ if(g == nil)
+ return Enonexist;
+ nonmembername = logfsisustadd(is, nonmembername);
+ if(nonmembername == nil)
+ return Enomem;
+ nonmg = findgroupfromuname(is, nonmembername);
+ if(nonmg == nil)
+ return Enonexist;
+ if(!logfsgroupsetremove(g->members, nonmg))
+ return Enonexist;
+ if(g->leader == nonmg)
+ g->leader = nil;
+ return nil;
+}
+
+typedef struct DS {
+ char *printbuf;
+ long printbufsize;
+ void *buf;
+ ulong offset;
+ long n;
+ ulong printoffset;
+ int printn;
+ int comma;
+} DS;
+
+static int
+printmember(void *magic, Group *member)
+{
+ DS *ds = magic;
+ if(ds->comma) {
+ if(ds->printn < ds->printbufsize)
+ ds->printbuf[ds->printn++] = ',';
+ }
+ else
+ ds->comma = 1;
+ ds->printn += snprint(ds->printbuf + ds->printn, ds->printbufsize - ds->printn, "%s", member->uname);
+ return 1;
+}
+
+static int
+printgroup(void *magic, Group *g)
+{
+ DS *ds = magic;
+ ds->printn = snprint(ds->printbuf, ds->printbufsize, "%s:%s:%s:",
+ g->uid, g->uname, g->leader ? g->leader->uname : "");
+ /* do members */
+ ds->comma = 0;
+ logfsgroupsetwalk(g->members, printmember, ds);
+ if(ds->printn < ds->printbufsize)
+ ds->printbuf[ds->printn++] = '\n';
+ /*
+ * copy the appropriate part of the buffer
+ */
+ if(ds->printoffset < ds->offset + ds->n && ds->printoffset + ds->printn > ds->offset) {
+ char *printbuf = ds->printbuf;
+ uchar *buf = ds->buf;
+ long trim = ds->offset - ds->printoffset;
+ if(trim >= 0) {
+ printbuf += trim;
+ ds->printn -= trim;
+ }
+ else
+ buf -= trim;
+ if(ds->printoffset + ds->printn > ds->offset + ds->n)
+ ds->printn = ds->offset + ds->n - ds->printoffset;
+ memcpy(buf, printbuf, ds->printn);
+ }
+ /*
+ * advance print position
+ */
+ ds->printoffset += ds->printn;
+ /*
+ * stop if exceeding the buffer
+ */
+ if(ds->printoffset >= ds->offset + ds->n)
+ return 0;
+ return 1;
+}
+
+char *
+logfsisusersread(LogfsIdentityStore *is, void *buf, long n, ulong offset, long *nr)
+{
+ DS ds;
+ ds.buf = buf;
+ ds.n = n;
+ ds.printoffset = 0;
+ ds.offset = offset;
+ ds.printbufsize = 1024;
+ ds.printbuf = logfsrealloc(nil, ds.printbufsize);
+ if(ds.printbuf == nil)
+ return Enomem;
+ logfsmapwalk(is->groupmap, (LOGFSMAPWALKFN *)printgroup, &ds);
+ *nr = ds.printoffset - ds.offset;
+ logfsfreemem(ds.printbuf);
+ return nil;
+}
+
+int
+logfsisgroupunameismember(LogfsIdentityStore *is, Group *g, char *uname)
+{
+ Group *ug;
+ if(g == nil)
+ return 0;
+ if(g->uname == uname)
+ return 1;
+ ug = logfsisfindgroupfromname(is, uname);
+ if(ug == nil)
+ return 0;
+ return logfsgroupsetismember(g->members, ug);
+}
+
+int
+logfsisgroupuidismember(LogfsIdentityStore *is, Group *g, char *uid)
+{
+ Group *ug;
+ if(g == nil)
+ return 0;
+ if(g->uid == uid)
+ return 1;
+ ug = logfsisfindgroupfromid(is, uid);
+ if(ug == nil)
+ return 0;
+ return logfsgroupsetismember(g->members, ug);
+}
+
+int
+logfsisgroupuidisleader(LogfsIdentityStore *is, Group *g, char *id)
+{
+ if(g->leader)
+ return g->leader->uid == id;
+ return logfsisgroupuidismember(is, g, id);
+}
+
+Group *
+logfsisfindgroupfromname(LogfsIdentityStore *is, char *name)
+{
+ Uname *u;
+ u = logfsunamemapfindentry(is->unamemap, name);
+ if(u == nil)
+ return nil;
+ return u->g;
+}
+
+char *
+logfsisfindidfromname(LogfsIdentityStore *is, char *name)
+{
+ char *id;
+ id = logfsunamemapfinduid(is->unamemap, name);
+ if(id == nil)
+ return logfsisgroupnonename;
+ return id;
+}
+
+char *
+logfsisfindnamefromid(LogfsIdentityStore *is, char *id)
+{
+ Group *g;
+ g = logfsgroupmapfindentry(is->groupmap, id);
+ if(g == nil)
+ return nil;
+ return g->uname;
+}