1 // Copyright (c) 1987-2024 by the citadel.org team
2 // This program is open source software. Use, duplication, or disclosure is subject to the GNU General Public License version 3.
4 // The functions in this file handle the selection and activation of a storage backend for Citadel Server.
5 // Right now, it simply activates Berkeley DB because that's the only one we have.
7 #include "../../sysdep.h"
13 #include <libcitadel.h>
14 #include "../../ctdl_module.h"
15 #include "../../control.h"
16 #include "../../citserver.h"
17 #include "../../config.h"
19 void cdb_chmod_data(void);
21 // Header files for all available backends must be included here.
22 #include "../berkeley_db/berkeley_db.h"
24 // Backends must include implementations of all these functions, but with their own prefix instead of "cdb_".
25 // The initialization function of the selected backend will map them.
26 void (*cdb_open_databases)(void) = NULL;
27 void (*cdb_close_databases)(void) = NULL;
28 struct cdbdata (*cdb_fetch)(int, const void *, int) = NULL;
29 int (*cdb_store)(int, const void *, int, void *, int) = NULL;
30 int (*cdb_delete)(int, void *, int) = NULL;
31 struct cdbkeyval (*cdb_next_item)(int) = NULL;
32 void (*cdb_close_cursor)(int) = NULL;
33 void (*cdb_begin_transaction)(void) = NULL;
34 void (*cdb_end_transaction)(void) = NULL;
35 void (*cdb_check_handles)(void) = NULL;
36 void (*cdb_trunc)(int) = NULL;
37 void (*check_handles)(void *) = NULL;
38 void (*cdb_compact)(void) = NULL;
39 void (*cdb_checkpoint)(void) = NULL;
40 void (*cdb_rewind)(int) = NULL;
41 void (*cdb_tick)(void) = NULL;
43 // This function is responsible for choosing and initializing a back end.
44 void cdb_init_backends(void) {
46 cdb_chmod_data(); // Set file level permissions so we can actually access the data files
48 // Test for Berkeley DB (this does nothing yet -- we're preparing to test for multiple back ends in the future)
49 int fd = open(ctdl_db_dir"/cdb.00", O_RDONLY);
53 read(fd, junk, 12); // throw the first 12 bytes away
54 read(fd, &magic, sizeof(magic));
55 if (magic == 0x00053162) {
56 syslog(LOG_DEBUG, "db: found existing Citadel database in Berkeley DB format");
61 bdb_init_backend(); // for now, this is the only one, so we select it always.
65 // Make sure we own all the files, because in a few milliseconds we're going to drop root privs.
66 void cdb_chmod_data(void) {
69 char filename[PATH_MAX];
71 // Silently try to create the database subdirectory. If it's already there, no problem.
72 if ((mkdir(ctdl_db_dir, 0700) != 0) && (errno != EEXIST)) {
73 syslog(LOG_ERR, "db: database directory [%s] does not exist and could not be created: %m", ctdl_db_dir);
76 if (chmod(ctdl_db_dir, 0700) != 0) {
77 syslog(LOG_ERR, "db: unable to set database directory permissions [%s]: %m", ctdl_db_dir);
80 if (chown(ctdl_db_dir, ctdluid, (-1)) != 0) {
81 syslog(LOG_ERR, "db: unable to set the owner for [%s]: %m", ctdl_db_dir);
84 dp = opendir(ctdl_db_dir);
86 while (d = readdir(dp), d != NULL) {
87 if (d->d_name[0] != '.') {
89 snprintf(filename, sizeof filename, "%s/%s", ctdl_db_dir, d->d_name);
90 ret = chmod(filename, 0600);
92 syslog(LOG_DEBUG, "db: chmod(%s, 0600) returned %d", filename, ret);
94 ret = chown(filename, ctdluid, (-1));
96 syslog(LOG_DEBUG, "db: chown(%s, ctdluid, -1) returned %d", filename, ret);