summaryrefslogtreecommitdiffstats
path: root/src/db.c
blob: a0443c9ffd267dff20bf1c5a99b6fcc0e7fb5a58 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* SPDX-License-Identifier: BSD-3-Clause */
/*
 * Copyright © 2020 rsiddharth <s@ricketyspace.net>
 */

#include <db.h>

static const char *DB_FILE = "nserver.db";

datum *mk_datum(char *data)
{
    datum *d = NULL;

    check(data != NULL, "data invalid");

    d = calloc(1, sizeof(datum));
    check(d != NULL, "datum mem alloc failed");

    d->dptr = data;
    d->dsize = strlen(data);

    return d;
 error:
    if (d) {
        free(d);
    }
    return NULL;
}

GDBM_FILE db_open(int flags)
{
   return gdbm_open(DB_FILE, 0,flags, S_IRUSR|S_IWUSR, NULL);
}

int db_init()
{
    // Create DB if it's not already created.
    GDBM_FILE  gf = db_open(GDBM_WRCREAT);
    check(gf != NULL, "unable to init db");

    // Close the DB.
    int rc = gdbm_close(gf);
    check(rc == 0,  "error closing db after init");

    return 0;
 error:
    return -1;
}

int db_store(char *key, char *value)
{
    datum *k_datum = NULL, *v_datum = NULL;
    GDBM_FILE gf = NULL;

    check(key != NULL && strlen(key) > 0, "key invalid");
    check(value != NULL && strlen(value) > 0, "data invalid");

    // make key value datum
    k_datum = mk_datum(key);
    check(k_datum != NULL, "key datum init failed");

    v_datum = mk_datum(value);
    check(v_datum != NULL, "value datum init failed");

    // init db.
    int rc = db_init();
    check(rc == 0, "db init failed");

    // open the gdbm data in write mode
    gf = db_open(GDBM_WRITER|GDBM_SYNC);
    check(gf != NULL, "unable to open db in write  mode");

    // write key -> data to db.
    rc = gdbm_store(gf, *k_datum, *v_datum, GDBM_REPLACE);
    check(rc == 0, "gdbm store failed");

    // close db
    rc = gdbm_close(gf);
    check(rc == 0, "gdbm close failed");

    // cleanup.
    free(k_datum);
    free(v_datum);

    return 0;
 error:
    if (k_datum) {
        free(k_datum);
    }
    if (v_datum)  {
        free(v_datum);
    }
    if (gf) {
        gdbm_close(gf);
    }
    return -1;
}

char *db_load(char *key)
{
    datum *k_datum = NULL;
    GDBM_FILE gf = NULL;

    check(key != NULL && strlen(key) > 0, "key invalid");

    // make key datum
    k_datum = mk_datum(key);
    check(k_datum != NULL, "key datum init failed");

    // init db.
    int rc = db_init();
    check(rc == 0, "db init failed");

    // open the gdbm data in read mode
    gf = db_open(GDBM_READER|GDBM_SYNC);
    check(gf != NULL, "unable to open db in read  mode");

    // try to fetch value for key.
    datum v_datum = gdbm_fetch(gf, *k_datum);
    check(v_datum.dptr != NULL, "key not found");

    // close db
    rc = gdbm_close(gf);
    check(rc == 0, "gdbm close failed");

    // clean up.
    free(k_datum);

    return v_datum.dptr;
 error:
    if (k_datum) {
        free(k_datum);
    }
    if (gf) {
        gdbm_close(gf);
    }
    return NULL;
}