NeoMutt  2024-03-23-147-g885fbc
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 <stdint.h>
37#include <sys/stat.h>
38#include <unistd.h>
39#include "mutt/lib.h"
40#include "lib.h"
41
46{
47 DB_ENV *env;
48 DB *db;
49 int fd;
51};
52
57static void bdb_sdata_free(struct BdbStoreData **ptr)
58{
59 if (!ptr || !*ptr)
60 return;
61
62 struct BdbStoreData *sdata = *ptr;
63 buf_dealloc(&sdata->lockfile);
64
65 FREE(ptr);
66}
67
72static struct BdbStoreData *bdb_sdata_new(void)
73{
74 struct BdbStoreData *sdata = mutt_mem_calloc(1, sizeof(struct BdbStoreData));
75
76 buf_alloc(&sdata->lockfile, 128);
77
78 return sdata;
79}
80
87static void dbt_init(DBT *dbt, void *data, size_t len)
88{
89 dbt->data = data;
90 dbt->size = len;
91 dbt->ulen = len;
92 dbt->dlen = 0;
93 dbt->doff = 0;
94 dbt->flags = DB_DBT_USERMEM;
95}
96
101static void dbt_empty_init(DBT *dbt)
102{
103 dbt->data = NULL;
104 dbt->size = 0;
105 dbt->ulen = 0;
106 dbt->dlen = 0;
107 dbt->doff = 0;
108 dbt->flags = 0;
109}
110
114static StoreHandle *store_bdb_open(const char *path)
115{
116 if (!path)
117 return NULL;
118
119 struct BdbStoreData *sdata = bdb_sdata_new();
120
121 const int pagesize = 512;
122
123 buf_printf(&sdata->lockfile, "%s-lock-hack", path);
124
125 sdata->fd = open(buf_string(&sdata->lockfile), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
126 if (sdata->fd < 0)
127 {
128 bdb_sdata_free(&sdata);
129 return NULL;
130 }
131
132 if (mutt_file_lock(sdata->fd, true, true))
133 goto fail_close;
134
135 int rc = db_env_create(&sdata->env, 0);
136 if (rc)
137 goto fail_unlock;
138
139 rc = (*sdata->env->open)(sdata->env, NULL, DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0600);
140 if (rc)
141 goto fail_env;
142
143 sdata->db = NULL;
144 rc = db_create(&sdata->db, sdata->env, 0);
145 if (rc)
146 goto fail_env;
147
148 uint32_t createflags = DB_CREATE;
149 struct stat st = { 0 };
150
151 if ((stat(path, &st) != 0) && (errno == ENOENT))
152 {
153 createflags |= DB_EXCL;
154 sdata->db->set_pagesize(sdata->db, pagesize);
155 }
156
157 rc = (*sdata->db->open)(sdata->db, NULL, path, NULL, DB_BTREE, createflags, 0600);
158 if (rc)
159 goto fail_db;
160
161 // Return an opaque pointer
162 return (StoreHandle *) sdata;
163
164fail_db:
165 sdata->db->close(sdata->db, 0);
166fail_env:
167 sdata->env->close(sdata->env, 0);
168fail_unlock:
169 mutt_file_unlock(sdata->fd);
170fail_close:
171 close(sdata->fd);
172 unlink(buf_string(&sdata->lockfile));
173 bdb_sdata_free(&sdata);
174
175 return NULL;
176}
177
181static void *store_bdb_fetch(StoreHandle *store, const char *key, size_t klen, size_t *vlen)
182{
183 if (!store)
184 return NULL;
185
186 // Decloak an opaque pointer
187 struct BdbStoreData *sdata = store;
188
189 DBT dkey = { 0 };
190 DBT data = { 0 };
191
192 dbt_init(&dkey, (void *) key, klen);
193 dbt_empty_init(&data);
194 data.flags = DB_DBT_MALLOC;
195
196 sdata->db->get(sdata->db, NULL, &dkey, &data, 0);
197
198 *vlen = data.size;
199 return data.data;
200}
201
205static void store_bdb_free(StoreHandle *store, void **ptr)
206{
207 FREE(ptr);
208}
209
213static int store_bdb_store(StoreHandle *store, const char *key, size_t klen,
214 void *value, size_t vlen)
215{
216 if (!store)
217 return -1;
218
219 // Decloak an opaque pointer
220 struct BdbStoreData *sdata = store;
221
222 DBT dkey = { 0 };
223 DBT databuf = { 0 };
224
225 dbt_init(&dkey, (void *) key, klen);
226 dbt_empty_init(&databuf);
227 databuf.flags = DB_DBT_USERMEM;
228 databuf.data = value;
229 databuf.size = vlen;
230 databuf.ulen = vlen;
231
232 return sdata->db->put(sdata->db, NULL, &dkey, &databuf, 0);
233}
234
238static int store_bdb_delete_record(StoreHandle *store, const char *key, size_t klen)
239{
240 if (!store)
241 return -1;
242
243 // Decloak an opaque pointer
244 struct BdbStoreData *sdata = store;
245
246 DBT dkey = { 0 };
247 dbt_init(&dkey, (void *) key, klen);
248 return sdata->db->del(sdata->db, NULL, &dkey, 0);
249}
250
254static void store_bdb_close(StoreHandle **ptr)
255{
256 if (!ptr || !*ptr)
257 return;
258
259 // Decloak an opaque pointer
260 struct BdbStoreData *sdata = *ptr;
261
262 sdata->db->close(sdata->db, 0);
263 sdata->env->close(sdata->env, 0);
264 mutt_file_unlock(sdata->fd);
265 close(sdata->fd);
266 unlink(buf_string(&sdata->lockfile));
267
268 bdb_sdata_free((struct BdbStoreData **) ptr);
269}
270
274static const char *store_bdb_version(void)
275{
276 return DB_VERSION_STRING;
277}
278
static void dbt_empty_init(DBT *dbt)
Initialise an empty BDB thing.
Definition: bdb.c:101
static void dbt_init(DBT *dbt, void *data, size_t len)
Initialise a BDB thing.
Definition: bdb.c:87
static void bdb_sdata_free(struct BdbStoreData **ptr)
Free Bdb Store Data.
Definition: bdb.c:57
static struct BdbStoreData * bdb_sdata_new(void)
Create new Bdb Store Data.
Definition: bdb.c:72
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:376
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:336
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:1199
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1246
static void store_bdb_close(StoreHandle **ptr)
Close a Store connection - Implements StoreOps::close() -.
Definition: bdb.c:254
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:238
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:181
static void store_bdb_free(StoreHandle *store, void **ptr)
Free a Value returned by fetch() - Implements StoreOps::free() -.
Definition: bdb.c:205
static StoreHandle * store_bdb_open(const char *path)
Open a connection to a Store - Implements StoreOps::open() -.
Definition: bdb.c:114
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:213
static const char * store_bdb_version(void)
Get a Store version string - Implements StoreOps::version() -.
Definition: bdb.c:274
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#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:162
Berkeley DB Store.
Definition: bdb.c:46
DB * db
Definition: bdb.c:48
DB_ENV * env
Definition: bdb.c:47
int fd
Definition: bdb.c:49
struct Buffer lockfile
Definition: bdb.c:50
String manipulation buffer.
Definition: buffer.h:36