ref: 3866717cbb020199d58171c1c0cdd7382a74ee82
dir: /liblogfs/is.c/
#include "logfsos.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;
memmove(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;
}