aboutsummaryrefslogtreecommitdiff
path: root/src/userdb.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2016-01-02 18:40:29 -0500
committerFranklin Wei <git@fwei.tk>2016-01-02 18:40:29 -0500
commit2819d11ceeb1ac739ed5f17ccb0abab63f494299 (patch)
tree9041b1aa1212df0208f8f49b78101933ce7d4a3a /src/userdb.c
parent66cdb3d4f427a1978dad56a66c1bf1085939601c (diff)
downloadnetcosm-2819d11ceeb1ac739ed5f17ccb0abab63f494299.zip
netcosm-2819d11ceeb1ac739ed5f17ccb0abab63f494299.tar.gz
netcosm-2819d11ceeb1ac739ed5f17ccb0abab63f494299.tar.bz2
netcosm-2819d11ceeb1ac739ed5f17ccb0abab63f494299.tar.xz
preliminary refactor of user data management
Diffstat (limited to 'src/userdb.c')
-rw-r--r--src/userdb.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/userdb.c b/src/userdb.c
new file mode 100644
index 0000000..4315da4
--- /dev/null
+++ b/src/userdb.c
@@ -0,0 +1,111 @@
+#include "netcosm.h"
+
+static void *map = NULL;
+static char *db_file = NULL;
+static size_t entries = 0;
+
+#define DELIM ":"
+
+/*
+ * the user DB is stored on disk as an ASCII database
+ *
+ * this is then loaded into variable-sized hash map at init
+ * TODO: implement with B-tree
+ */
+void userdb_init(const char *file)
+{
+ db_file = strdup(file);
+ entries = 0;
+
+ /* FILE* for getline() */
+ FILE *f = fopen(file, "r");
+ map = hash_init(256, hash_djb, compare_strings);
+ hash_setfreekey_cb(map, free);
+ hash_setfreedata_cb(map, free);
+
+ char *format;
+ asprintf(&format, "%%ms:%%%d%%s:%%%d%%s:%%d\n",
+ SALT_LEN, AUTH_HASHLEN * 2);
+
+ if(f)
+ {
+ while(1)
+ {
+ struct userdata_t *data = calloc(1, sizeof(*data));
+
+ if(fscanf(f, format,
+ &data->username,
+ data->salt,
+ data->passhash,
+ &data->priv) != 6)
+ break;
+
+ hash_insert(map, data->username, data);
+ ++entries;
+ }
+
+ fclose(f);
+ }
+
+ free(format);
+}
+
+void userdb_write(const char *file)
+{
+ int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ void *save, *ptr = map;
+ while(1)
+ {
+ struct userdata_t *user = hash_iterate(ptr, &save, NULL);
+ ptr = NULL;
+ if(!user)
+ break;
+ dprintf(fd, "%s:%*s:%*s:%d\n", user->username,
+ SALT_LEN, user->salt,
+ AUTH_HASHLEN*2, user->passhash,
+ user->priv);
+ }
+ close(fd);
+}
+
+struct userdata_t *userdb_lookup(const char *key)
+{
+ return hash_lookup(map, key);
+}
+
+void userdb_remove(const char *key)
+{
+ if(hash_remove(map, key))
+ --entries;
+}
+
+struct userdata_t *userdb_add(struct userdata_t *data)
+{
+ struct userdata_t *new = calloc(1, sizeof(*new)); /* only in C! */
+ memcpy(new, data, sizeof(*new));
+ new->username = strdup(data->username);
+ struct userdata_t *ret;
+ if((ret = hash_insert(map, new->username, new))) /* failure */
+ {
+ hash_remove(map, new->username);
+ ret = hash_insert(map, new->username, new);
+ }
+
+ userdb_write(db_file);
+ if(!ret)
+ --entries;
+
+ return ret;
+}
+
+void userdb_shutdown(void)
+{
+ hash_free(map);
+ if(db_file)
+ free(db_file);
+}
+
+size_t userdb_size(void)
+{
+ return entries;
+}