xref: /inferno-os/liblogfs/is.c (revision 1981fff245dfce579ef416fa767eb69d462039e9)
1 #include "logfsos.h"
2 #include "logfs.h"
3 #include "fcall.h"
4 #include "local.h"
5 
6 char *logfsisgroupnonename = "none";
7 
8 char *
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
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 *
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 *
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 *
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 *
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 *
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 *
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
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
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 *
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
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
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
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 *
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 *
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 *
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