1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "fcall.h"
4 #include "local.h"
5
6 char *logfsisgroupnonename = "none";
7
8 char *
logfsisnew(LogfsIdentityStore ** isp)9 logfsisnew(LogfsIdentityStore **isp)
10 {
11 LogfsIdentityStore *is;
12 char *errmsg;
13
14 is = logfsrealloc(nil, sizeof(*is));
15 if(is == nil) {
16 memerror:
17 logfsisfree(&is);
18 return Enomem;
19 }
20 errmsg = logfsustnew(&is->ids);
21 if(errmsg)
22 goto memerror;
23 errmsg = logfsgroupmapnew(&is->groupmap, &is->unamemap);
24 if(errmsg)
25 goto memerror;
26 logfsisgroupnonename = logfsustadd(is->ids, logfsisgroupnonename);
27 *isp = is;
28 return nil;
29 }
30
31 void
logfsisfree(LogfsIdentityStore ** isp)32 logfsisfree(LogfsIdentityStore **isp)
33 {
34 LogfsIdentityStore *is = *isp;
35 if(is) {
36 logfsustfree(&is->ids);
37 logfsgroupmapfree(&is->groupmap);
38 logfsunamemapfree(&is->unamemap);
39 logfsfreemem(is);
40 *isp = nil;
41 }
42 }
43
44 char *
logfsisgroupcreate(LogfsIdentityStore * is,char * groupname,char * groupid)45 logfsisgroupcreate(LogfsIdentityStore *is, char *groupname, char *groupid)
46 {
47 Group *group;
48 Uname *uname;
49
50 if(strcmp(groupname, logfsisgroupnonename) == 0 || groupname[0] == '(')
51 return "group name reserved";
52 groupname = logfsisustadd(is, groupname);
53 groupid = logfsisustadd(is, groupid);
54 if(groupname == nil || groupid == nil)
55 return Enomem;
56 return logfsgroupmapnewentry(is->groupmap, is->unamemap, groupid, groupname, &group, &uname);
57 }
58
59 static Group *
findgroupfromuname(LogfsIdentityStore * is,char * groupname)60 findgroupfromuname(LogfsIdentityStore *is, char *groupname)
61 {
62 Uname *u = logfsunamemapfindentry(is->unamemap, groupname);
63 if(u == nil)
64 return nil;
65 return u->g;
66 }
67
68 char *
logfsisgrouprename(LogfsIdentityStore * is,char * oldgroupname,char * newgroupname)69 logfsisgrouprename(LogfsIdentityStore *is, char *oldgroupname, char *newgroupname)
70 {
71 Group *og, *ng;
72 oldgroupname = logfsisustadd(is, oldgroupname);
73 if(oldgroupname == nil)
74 return Enomem;
75 og =findgroupfromuname(is, oldgroupname);
76 if(og == nil)
77 return Enonexist;
78 newgroupname = logfsisustadd(is, newgroupname);
79 if(newgroupname == nil)
80 return Enomem;
81 ng = findgroupfromuname(is, newgroupname);
82 if(ng != nil)
83 return Eexist;
84 og->uname = newgroupname;
85 return nil;
86 }
87
88 char *
logfsisgroupsetleader(LogfsIdentityStore * is,char * groupname,char * leadername)89 logfsisgroupsetleader(LogfsIdentityStore *is, char *groupname, char *leadername)
90 {
91 Group *g, *lg;
92 groupname = logfsisustadd(is, groupname);
93 if(groupname == nil)
94 return Enomem;
95 g = findgroupfromuname(is, groupname);
96 if(g == nil)
97 return Enonexist;
98 if(leadername && leadername[0]) {
99 leadername = logfsisustadd(is, leadername);
100 if(leadername == nil)
101 return Enomem;
102 lg = findgroupfromuname(is, leadername);
103 if(lg == nil)
104 return Enonexist;
105 if(!logfsgroupsetismember(g->members, lg))
106 return "not a member of the group";
107 g->leader = lg;
108 }
109 else
110 g->leader = nil;
111 return nil;
112 }
113
114 char *
logfsisgroupaddmember(LogfsIdentityStore * is,char * groupname,char * membername)115 logfsisgroupaddmember(LogfsIdentityStore *is, char *groupname, char *membername)
116 {
117 Group *g, *mg;
118 groupname = logfsisustadd(is, groupname);
119 if(groupname == nil)
120 return Enomem;
121 g =findgroupfromuname(is, groupname);
122 if(g == nil)
123 return Enonexist;
124 membername = logfsisustadd(is, membername);
125 if(membername == nil)
126 return Enomem;
127 mg = findgroupfromuname(is, membername);
128 if(mg == nil)
129 return Enonexist;
130 if(!logfsgroupsetadd(g->members, mg))
131 return Enomem;
132 return nil;
133 }
134
135 char *
logfsisgroupremovemember(LogfsIdentityStore * is,char * groupname,char * nonmembername)136 logfsisgroupremovemember(LogfsIdentityStore *is, char *groupname, char *nonmembername)
137 {
138 Group *g, *nonmg;
139 groupname = logfsisustadd(is, groupname);
140 if(groupname == nil)
141 return Enomem;
142 g =findgroupfromuname(is, groupname);
143 if(g == nil)
144 return Enonexist;
145 nonmembername = logfsisustadd(is, nonmembername);
146 if(nonmembername == nil)
147 return Enomem;
148 nonmg = findgroupfromuname(is, nonmembername);
149 if(nonmg == nil)
150 return Enonexist;
151 if(!logfsgroupsetremove(g->members, nonmg))
152 return Enonexist;
153 if(g->leader == nonmg)
154 g->leader = nil;
155 return nil;
156 }
157
158 typedef struct DS {
159 char *printbuf;
160 long printbufsize;
161 void *buf;
162 ulong offset;
163 long n;
164 ulong printoffset;
165 int printn;
166 int comma;
167 } DS;
168
169 static int
printmember(void * magic,Group * member)170 printmember(void *magic, Group *member)
171 {
172 DS *ds = magic;
173 if(ds->comma) {
174 if(ds->printn < ds->printbufsize)
175 ds->printbuf[ds->printn++] = ',';
176 }
177 else
178 ds->comma = 1;
179 ds->printn += snprint(ds->printbuf + ds->printn, ds->printbufsize - ds->printn, "%s", member->uname);
180 return 1;
181 }
182
183 static int
printgroup(void * magic,Group * g)184 printgroup(void *magic, Group *g)
185 {
186 DS *ds = magic;
187 ds->printn = snprint(ds->printbuf, ds->printbufsize, "%s:%s:%s:",
188 g->uid, g->uname, g->leader ? g->leader->uname : "");
189 /* do members */
190 ds->comma = 0;
191 logfsgroupsetwalk(g->members, printmember, ds);
192 if(ds->printn < ds->printbufsize)
193 ds->printbuf[ds->printn++] = '\n';
194 /*
195 * copy the appropriate part of the buffer
196 */
197 if(ds->printoffset < ds->offset + ds->n && ds->printoffset + ds->printn > ds->offset) {
198 char *printbuf = ds->printbuf;
199 uchar *buf = ds->buf;
200 long trim = ds->offset - ds->printoffset;
201 if(trim >= 0) {
202 printbuf += trim;
203 ds->printn -= trim;
204 }
205 else
206 buf -= trim;
207 if(ds->printoffset + ds->printn > ds->offset + ds->n)
208 ds->printn = ds->offset + ds->n - ds->printoffset;
209 memmove(buf, printbuf, ds->printn);
210 }
211 /*
212 * advance print position
213 */
214 ds->printoffset += ds->printn;
215 /*
216 * stop if exceeding the buffer
217 */
218 if(ds->printoffset >= ds->offset + ds->n)
219 return 0;
220 return 1;
221 }
222
223 char *
logfsisusersread(LogfsIdentityStore * is,void * buf,long n,ulong offset,long * nr)224 logfsisusersread(LogfsIdentityStore *is, void *buf, long n, ulong offset, long *nr)
225 {
226 DS ds;
227 ds.buf = buf;
228 ds.n = n;
229 ds.printoffset = 0;
230 ds.offset = offset;
231 ds.printbufsize = 1024;
232 ds.printbuf = logfsrealloc(nil, ds.printbufsize);
233 if(ds.printbuf == nil)
234 return Enomem;
235 logfsmapwalk(is->groupmap, (LOGFSMAPWALKFN *)printgroup, &ds);
236 *nr = ds.printoffset - ds.offset;
237 logfsfreemem(ds.printbuf);
238 return nil;
239 }
240
241 int
logfsisgroupunameismember(LogfsIdentityStore * is,Group * g,char * uname)242 logfsisgroupunameismember(LogfsIdentityStore *is, Group *g, char *uname)
243 {
244 Group *ug;
245 if(g == nil)
246 return 0;
247 if(g->uname == uname)
248 return 1;
249 ug = logfsisfindgroupfromname(is, uname);
250 if(ug == nil)
251 return 0;
252 return logfsgroupsetismember(g->members, ug);
253 }
254
255 int
logfsisgroupuidismember(LogfsIdentityStore * is,Group * g,char * uid)256 logfsisgroupuidismember(LogfsIdentityStore *is, Group *g, char *uid)
257 {
258 Group *ug;
259 if(g == nil)
260 return 0;
261 if(g->uid == uid)
262 return 1;
263 ug = logfsisfindgroupfromid(is, uid);
264 if(ug == nil)
265 return 0;
266 return logfsgroupsetismember(g->members, ug);
267 }
268
269 int
logfsisgroupuidisleader(LogfsIdentityStore * is,Group * g,char * id)270 logfsisgroupuidisleader(LogfsIdentityStore *is, Group *g, char *id)
271 {
272 if(g->leader)
273 return g->leader->uid == id;
274 return logfsisgroupuidismember(is, g, id);
275 }
276
277 Group *
logfsisfindgroupfromname(LogfsIdentityStore * is,char * name)278 logfsisfindgroupfromname(LogfsIdentityStore *is, char *name)
279 {
280 Uname *u;
281 u = logfsunamemapfindentry(is->unamemap, name);
282 if(u == nil)
283 return nil;
284 return u->g;
285 }
286
287 char *
logfsisfindidfromname(LogfsIdentityStore * is,char * name)288 logfsisfindidfromname(LogfsIdentityStore *is, char *name)
289 {
290 char *id;
291 id = logfsunamemapfinduid(is->unamemap, name);
292 if(id == nil)
293 return logfsisgroupnonename;
294 return id;
295 }
296
297 char *
logfsisfindnamefromid(LogfsIdentityStore * is,char * id)298 logfsisfindnamefromid(LogfsIdentityStore *is, char *id)
299 {
300 Group *g;
301 g = logfsgroupmapfindentry(is->groupmap, id);
302 if(g == nil)
303 return nil;
304 return g->uname;
305 }
306