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