fatal(errno, "error locking %s", lockfile);
}
/* initialize database environment */
- trackdb_init(TRACKDB_NORMAL_RECOVER);
+ trackdb_init(TRACKDB_NORMAL_RECOVER|TRACKDB_MAY_CREATE);
trackdb_master(ev);
/* install new config */
reconfigure(ev, 0);
/*
* This file is part of DisOrder.
- * Copyright (C) 2004, 2005 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2007 Richard Kettlewell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <pcre.h>
#include <unistd.h>
#include <db.h>
+#include <fcntl.h>
#include "configuration.h"
#include "syscalls.h"
if(trackdb_closecursor(cursor)) { cursor = 0; goto fail; }
cursor = 0;
+ /* dump the users */
+ cursor = trackdb_opencursor(trackdb_usersdb, tid);
+ err = cursor->c_get(cursor, prepare_data(&k), prepare_data(&d),
+ DB_FIRST);
+ while(err == 0) {
+ if(fputc('U', fp) < 0
+ || urlencode(s, k.data, k.size)
+ || fputc('\n', fp) < 0
+ || urlencode(s, d.data, d.size)
+ || fputc('\n', fp) < 0)
+ fatal(errno, "error writing to %s", tag);
+ err = cursor->c_get(cursor, prepare_data(&k), prepare_data(&d),
+ DB_NEXT);
+ }
+ if(trackdb_closecursor(cursor)) { cursor = 0; goto fail; }
+ cursor = 0;
+
if(tracksdb) {
cursor = trackdb_opencursor(trackdb_tracksdb, tid);
err = cursor->c_get(cursor, prepare_data(&k), prepare_data(&d),
if((err = truncdb(tid, trackdb_globaldb))) return err;
if((err = truncdb(tid, trackdb_searchdb))) return err;
if((err = truncdb(tid, trackdb_tagsdb))) return err;
+ if((err = truncdb(tid, trackdb_usersdb))) return err;
c = getc(fp);
while(!ferror(fp) && !feof(fp)) {
switch(c) {
return 0;
case 'P':
case 'G':
- if(c == 'P') {
+ case 'U':
+ switch(c) {
+ case 'P':
which_db = trackdb_prefsdb;
which_name = "prefs.db";
- } else {
+ break;
+ case 'G':
which_db = trackdb_globaldb;
which_name = "global.db";
+ break;
+ case 'U':
+ which_db = trackdb_usersdb;
+ which_name = "users.db";
+ break;
+ default:
+ abort();
}
if(undump_dbt(fp, tag, prepare_data(&k))
|| undump_dbt(fp, tag, prepare_data(&d)))
int main(int argc, char **argv) {
int n, dump = 0, undump = 0, recover = TRACKDB_NO_RECOVER, recompute = 0;
- int tracksdb = 0, searchdb = 0, remove_pathless = 0;
+ int tracksdb = 0, searchdb = 0, remove_pathless = 0, fd;
const char *path;
char *tmp;
FILE *fp;
path = argv[optind];
}
if(config_read(0)) fatal(0, "cannot read configuration");
- trackdb_init(recover);
+ trackdb_init(recover|TRACKDB_MAY_CREATE);
trackdb_open(TRACKDB_NO_UPGRADE);
if(dump) {
- /* we write to a temporary file and rename into place */
+ /* We write to a temporary file and rename into place. We make
+ * sure the permissions are tight from the start. */
byte_xasprintf(&tmp, "%s.%lx.tmp", path, (unsigned long)getpid());
- if(!(fp = fopen(tmp, "w"))) fatal(errno, "error opening %s", tmp);
+ if((fd = open(tmp, O_CREAT|O_TRUNC|O_WRONLY, 0600)) < 0)
+ fatal(errno, "error opening %s", tmp);
+ if(!(fp = fdopen(fd, "w")))
+ fatal(errno, "fdopen on %s", tmp);
do_dump(fp, tmp, tracksdb, searchdb);
if(fclose(fp) < 0) fatal(errno, "error closing %s", tmp);
if(rename(tmp, path) < 0)
extern DB *trackdb_tagsdb;
extern DB *trackdb_noticeddb;
extern DB *trackdb_globaldb;
+extern DB *trackdb_usersdb;
DBC *trackdb_opencursor(DB *db, DB_TXN *tid);
/* open a transaction */
#include <time.h>
#include <arpa/inet.h>
#include <sys/wait.h>
+#include <dirent.h>
+#include <sys/stat.h>
#include "event.h"
#include "mem.h"
* - Data cannot be reconstructed (but isn't THAT important)
*/
DB *trackdb_noticeddb; /* when track noticed */
+
+/** @brief The user database
+ * - Keys are usernames
+ * - Values are encoded key-value pairs
+ * - Data is user data and cannot be reconstructed
+ */
+DB *trackdb_usersdb;
+
static pid_t db_deadlock_pid = -1; /* deadlock manager PID */
static pid_t rescan_pid = -1; /* rescanner PID */
static int initialized, opened; /* state */
* - @ref TRACKDB_NO_RECOVER
* - @ref TRACKDB_NORMAL_RECOVER
* - @ref TRACKDB_FATAL_RECOVER
+ * - @ref TRACKDB_MAY_CREATE
*/
void trackdb_init(int flags) {
int err;
home = config->home;
}
+ if(flags & TRACKDB_MAY_CREATE) {
+ DIR *dp;
+ struct dirent *de;
+ struct stat st;
+ char *p;
+
+ /* create home directory if it does not exist */
+ mkdir(config->home, 0755);
+ /* Remove world/group permissions on any regular files already in the
+ * database directory. Actually we don't care about all of them but it's
+ * easier to just do the lot. This can be revisited if it's a serious
+ * practical inconvenience for anyone.
+ *
+ * The socket, not being a regular file, is excepted.
+ */
+ if(!(dp = opendir(config->home)))
+ fatal(errno, "error reading %s", config->home);
+ while((de = readdir(dp))) {
+ byte_xasprintf(&p, "%s/%s", config->home, de->d_name);
+ if(lstat(p, &st) == 0
+ && S_ISREG(st.st_mode)
+ && (st.st_mode & 077)) {
+ if(chmod(p, st.st_mode & (~(mode_t)077) & 07777) < 0)
+ fatal(errno, "cannot chmod %s", p);
+ }
+ xfree(p);
+ }
+ closedir(dp);
+ }
+
/* create environment */
if((err = db_env_create(&trackdb_env, 0))) fatal(0, "db_env_create: %s",
db_strerror(err));
|DB_INIT_TXN
|DB_CREATE
|recover_type[recover],
- 0666)))
+ 0600)))
fatal(0, "trackdb_env->open %s: %s", config->home, db_strerror(err));
trackdb_env->set_errpfx(trackdb_env, "DB");
trackdb_env->set_errfile(trackdb_env, stderr);
trackdb_globaldb = open_db("global.db", 0, DB_HASH, DB_CREATE, 0666);
trackdb_noticeddb = open_db("noticed.db",
DB_DUPSORT, DB_BTREE, DB_CREATE, 0666);
+ trackdb_usersdb = open_db("users.db",
+ 0, DB_HASH, DB_CREATE, 0600);
if(!trackdb_existing_database) {
/* Stash the database version */
char buf[32];
fatal(0, "error closing global.db: %s", db_strerror(err));
if((err = trackdb_noticeddb->close(trackdb_noticeddb, 0)))
fatal(0, "error closing noticed.db: %s", db_strerror(err));
+ if((err = trackdb_usersdb->close(trackdb_usersdb, 0)))
+ fatal(0, "error closing users.db: %s", db_strerror(err));
trackdb_tracksdb = trackdb_searchdb = trackdb_prefsdb = 0;
trackdb_tagsdb = trackdb_globaldb = 0;
D(("closed databases"));
/** @brief Mask of upgrade bits (trackdb_open()) */
#define TRACKDB_UPGRADE_MASK 0x000C
+/** @brief May create database environment (trackdb_init()) */
+#define TRACKDB_MAY_CREATE 0x0010
+
void trackdb_init(int flags);
void trackdb_deinit(void);
/* close/close environment */