NeoMutt  2024-04-25-92-gf10c0f
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
bdb.c
Go to the documentation of this file.
1
31#include "config.h"
32#include <db.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <stdbool.h>
36#include <stddef.h>
37#include <stdint.h>
38#include <sys/stat.h>
39#include <unistd.h>
40#include "mutt/lib.h"
41#include "lib.h"
42
47{
48 DB_ENV *env;
49 DB *db;
50 int fd;
52};
53
58static void bdb_sdata_free(struct BdbStoreData **ptr)
59{
60 if (!ptr || !*ptr)
61 return;
62
63 struct BdbStoreData *sdata = *ptr;
64 buf_dealloc(&sdata->lockfile);
65
66 FREE(ptr);
67}
68
73static struct BdbStoreData *bdb_sdata_new(void)
74{
75 struct BdbStoreData *sdata = mutt_mem_calloc(1, sizeof(struct BdbStoreData));
76
77 buf_alloc(&sdata->lockfile, 128);
78
79 return sdata;
80}
81
88static void dbt_init(DBT *dbt, void *data, size_t len)
89{
90 dbt->data = data;
91 dbt->size = len;
92 dbt->ulen = len;
93 dbt->dlen = 0;
94 dbt->doff = 0;
95 dbt->flags = DB_DBT_USERMEM;
96}
97
102static void dbt_empty_init(DBT *dbt)
103{
104 dbt->data = NULL;
105 dbt->size = 0;
106 dbt->ulen = 0;
107 dbt->dlen = 0;
108 dbt->doff = 0;
109 dbt->flags = 0;
110}
111
115static StoreHandle *store_bdb_open(const char *path, bool create)
116{
117 if (!path)
118 return NULL;
119
120 struct BdbStoreData *sdata = bdb_sdata_new();
121
122 const int pagesize = 512;
123
124 buf_printf(&sdata->lockfile, "%s-lock-hack", path);
125
126 sdata->fd = open(buf_string(&sdata->lockfile),
127 O_WRONLY | (create ? O_CREAT : 0), S_IRUSR | S_IWUSR);
128 if (sdata->fd < 0)
129 {
130 bdb_sdata_free(&sdata);
131 return NULL;
132 }
133
134 if (mutt_file_lock(sdata->fd, true, true))
135 goto fail_close;
136
137 int rc = db_env_create(&sdata->env, 0);
138 if (rc)
139 goto fail_unlock;
140
141 rc = (*sdata->env->open)(sdata->env, NULL, DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0600);
142 if (rc)
143 goto fail_env;
144
145 sdata->db = NULL;
146 rc = db_create(&sdata->db, sdata->env, 0);
147 if (rc)
148 goto fail_env;
149
150 uint32_t createflags = DB_CREATE;
151 struct stat st = { 0 };
152
153 if ((stat(path, &st) != 0) && (errno == ENOENT))
154 {
155 createflags |= DB_EXCL;
156 sdata->db->set_pagesize(sdata->db, pagesize);
157 }
158
159 rc = (*sdata->db->open)(sdata->db, NULL, path, NULL, DB_BTREE, createflags, 0600);
160 if (rc)
161 goto fail_db;
162
163 // Return an opaque pointer
164 return (StoreHandle *) sdata;
165
166fail_db:
167 sdata->db->close(sdata->db, 0);
168fail_env:
169 sdata->env->close(sdata->env, 0);
170fail_unlock:
171 mutt_file_unlock(sdata->fd);
172fail_close:
173 close(sdata->fd);
174 unlink(buf_string(&sdata->lockfile));
175 bdb_sdata_free(&sdata);
176
177 return NULL;
178}
179
183static void *store_bdb_fetch(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
184{
185 if (!store)
186 return NULL;
187
188 // Decloak an opaque pointer
189 struct BdbStoreData *sdata = store;
190
191 DBT dkey = { 0 };
192 DBT data = { 0 };
193
194 dbt_init(&dkey, (void *) key, klen);
195 dbt_empty_init(&data);
196 data.flags = DB_DBT_MALLOC;
197
198 sdata->db->get(sdata->db, NULL, &dkey, &data, 0);
199
200 *vlen = data.size;
201 return data.data;
202}
203
207static void store_bdb_free(StoreHandle *store, void **ptr)
208{
209 FREE(ptr);
210}
211
215static int store_bdb_store(StoreHandle *store, const char *key, size_t klen,
216 void *value, size_t vlen)
217{
218 if (!store)
219 return -1;
220
221 // Decloak an opaque pointer
222 struct BdbStoreData *sdata = store;
223
224 DBT dkey = { 0 };
225 DBT databuf = { 0 };
226
227 dbt_init(&dkey, (void *) key, klen);
228 dbt_empty_init(&databuf);
229 databuf.flags = DB_DBT_USERMEM;
230 databuf.data = value;
231 databuf.size = vlen;
232 databuf.ulen = vlen;
233
234 return sdata->db->put(sdata->db, NULL, &dkey, &databuf, 0);
235}
236
240static int store_bdb_delete_record(StoreHandle *store, const char *key, size_t klen)
241{
242 if (!store)
243 return -1;
244
245 // Decloak an opaque pointer
246 struct BdbStoreData *sdata = store;
247
248 DBT dkey = { 0 };
249 dbt_init(&dkey, (void *) key, klen);
250 return sdata->db->del(sdata->db, NULL, &dkey, 0);
251}
252
256static void store_bdb_close(StoreHandle **ptr)
257{
258 if (!ptr || !*ptr)
259 return;
260
261 // Decloak an opaque pointer
262 struct BdbStoreData *sdata = *ptr;
263
264 sdata->db->close(sdata->db, 0);
265 sdata->env->close(sdata->env, 0);
266 mutt_file_unlock(sdata->fd);
267 close(sdata->fd);
268 unlink(buf_string(&sdata->lockfile));
269
270 bdb_sdata_free((struct BdbStoreData **) ptr);
271}
272
276static const char *store_bdb_version(void)
277{
278 return DB_VERSION_STRING;
279}
280
static void dbt_empty_init(DBT *dbt)
Initialise an empty BDB thing.
Definition: bdb.c:102
static void dbt_init(DBT *dbt, void *data, size_t len)
Initialise a BDB thing.
Definition: bdb.c:88
static void bdb_sdata_free(struct BdbStoreData **ptr)
Free Bdb Store Data.
Definition: bdb.c:58
static struct BdbStoreData * bdb_sdata_new(void)
Create new Bdb Store Data.
Definition: bdb.c:73
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:377
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1202
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1249
static void store_bdb_close(StoreHandle **ptr)
Close a Store connection - Implements StoreOps::close() -.
Definition: bdb.c:256
static int store_bdb_delete_record(StoreHandle *store, const char *key, size_t klen)
Delete a record from the Store - Implements StoreOps::delete_record() -.
Definition: bdb.c:240
static void * store_bdb_fetch(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
Fetch a Value from the Store - Implements StoreOps::fetch() -.
Definition: bdb.c:183
static void store_bdb_free(StoreHandle *store, void **ptr)
Free a Value returned by fetch() - Implements StoreOps::free() -.
Definition: bdb.c:207
static StoreHandle * store_bdb_open(const char *path, bool create)
Open a connection to a Store - Implements StoreOps::open() -.
Definition: bdb.c:115
static int store_bdb_store(StoreHandle *store, const char *key, size_t klen, void *value, size_t vlen)
Write a Value to the Store - Implements StoreOps::store() -.
Definition: bdb.c:215
static const char * store_bdb_version(void)
Get a Store version string - Implements StoreOps::version() -.
Definition: bdb.c:276
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
Key value store.
void StoreHandle
Opaque type for store backend.
Definition: lib.h:61
#define STORE_BACKEND_OPS(_name)
Definition: lib.h:163
Berkeley DB Store.
Definition: bdb.c:47
DB * db
Definition: bdb.c:49
DB_ENV * env
Definition: bdb.c:48
int fd
Definition: bdb.c:50
struct Buffer lockfile
Definition: bdb.c:51
String manipulation buffer.
Definition: buffer.h:36