summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ip/cifsd/idmap.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2020-05-02 16:53:52 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2020-05-02 16:53:52 +0200
commitd0c87bada6e1d3822a414a48c6ee75da68361a19 (patch)
tree32f8cd8e28b68e61e76b8c2412a71258417e5c2e /sys/src/cmd/ip/cifsd/idmap.c
parentbadbf50b0cc21c0faaae6daddf086f76bc871086 (diff)
ip/cifsd: implement primitive per-share unix id mapping for wstat()
Diffstat (limited to 'sys/src/cmd/ip/cifsd/idmap.c')
-rw-r--r--sys/src/cmd/ip/cifsd/idmap.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/sys/src/cmd/ip/cifsd/idmap.c b/sys/src/cmd/ip/cifsd/idmap.c
new file mode 100644
index 000000000..178d99b19
--- /dev/null
+++ b/sys/src/cmd/ip/cifsd/idmap.c
@@ -0,0 +1,175 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+#include <bio.h>
+
+enum {
+ NHASH = 251,
+};
+
+typedef struct Ident Ident;
+struct Ident
+{
+ Ident *nextid;
+ Ident *nextname;
+ int id;
+ char name[];
+};
+
+struct Idmap
+{
+ Ident *tab[NHASH];
+};
+
+static Ident**
+nametab(Idmap *map, char *name)
+{
+ return &map->tab[(uint)namehash(name) % NHASH];
+}
+static Ident**
+idtab(Idmap *map, int id)
+{
+ return &map->tab[(uint)id % NHASH];
+}
+
+static int
+name2id(Idmap *map, char *name)
+{
+ Ident *e;
+
+ for(e = *nametab(map, name); e != nil; e = e->nextid){
+ if(strcmp(e->name, name) == 0)
+ return e->id;
+ }
+ return -1;
+}
+
+static char*
+id2name(Idmap *map, int id)
+{
+ Ident *e;
+
+ for(e = *idtab(map, id); e != nil; e = e->nextname){
+ if(e->id == id)
+ return e->name;
+ }
+ return nil;
+}
+
+static void
+idmap(Idmap *map, char *name, int id)
+{
+ Ident *e, **h;
+ int n;
+
+ n = strlen(name)+1;
+ e = malloc(sizeof(Ident)+n);
+ if(e == nil)
+ return;
+
+ e->id = id;
+ h = idtab(map, e->id);
+ e->nextid = *h;
+ *h = e;
+
+ memmove(e->name, name, n);
+ h = nametab(map, e->name);
+ e->nextname = *h;
+ *h = e;
+}
+
+static Idmap*
+readidmap(char *file, int style)
+{
+ Biobuf *b;
+ Idmap *m;
+ char *l, *name;
+ int id;
+
+ if((b = Bopen(file, OREAD)) == nil)
+ return nil;
+
+ if((m = mallocz(sizeof(*m), 1)) == nil)
+ goto Out;
+
+ while((l = Brdline(b, '\n')) != nil){
+ l[Blinelen(b)-1] = 0;
+ switch(style){
+ case '9':
+ id = 9000000 + strtol(l, &l, 10);
+ if(*l != ':')
+ continue;
+ name = ++l;
+ l = strchr(l, ':');
+ if(l == 0)
+ continue;
+ *l = 0;
+ break;
+ default:
+ name = l;
+ l = strchr(l, ':');
+ if(l == 0)
+ continue;
+ *l++ = 0;
+ /* skip password */
+ l = strchr(l, ':');
+ if(l == 0)
+ continue;
+ id = strtol(l+1, 0, 10);
+ break;
+ }
+ idmap(m, name, id);
+ }
+Out:
+ Bterm(b);
+
+ return m;
+}
+
+void
+unixidmap(Share *share)
+{
+ static Idmap emptymap;
+ char *file;
+
+ if(share->stype != STYPE_DISKTREE)
+ goto Out;
+
+ file = smprint("%s/etc/passwd", share->root);
+ share->users = readidmap(file, 'u');
+ free(file);
+ file = smprint("%s/etc/group", share->root);
+ share->groups = readidmap(file, 'u');
+ free(file);
+ if(share->users != nil && share->groups != nil)
+ return;
+
+ file = smprint("%s/adm/users", share->root);
+ share->users = share->groups = readidmap(file, '9');
+ free(file);
+ if(share->users != nil && share->groups != nil)
+ return;
+
+Out:
+ share->users = share->groups = &emptymap;
+}
+
+char*
+unixname(Share *share, int id, int group)
+{
+ return id2name(group? share->groups: share->users, id);
+}
+
+int
+unixuid(Share *share, char *name)
+{
+ return name2id(share->users, name);
+}
+
+int
+unixgid(Share *share, char *name)
+{
+ return name2id(share->groups, name);
+}