X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/fce810c27ad09dd73706100435a6e65af0a67604..0590cedca75c01811972b2f694f60f24028ee973:/lib/trackdb.c diff --git a/lib/trackdb.c b/lib/trackdb.c index e030665..8945ec3 100644 --- a/lib/trackdb.c +++ b/lib/trackdb.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder - * Copyright (C) 2005, 2006, 2007 Richard Kettlewell + * Copyright (C) 2005-2008 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 @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ -/** @file server/trackdb.c +/** @file lib/trackdb.c * @brief Track database * * This file is getting in desparate need of splitting up... @@ -113,7 +113,7 @@ DB *trackdb_prefsdb; * - Values are UTF-8(NFC(unicode(path name))) * - There can be more than one value per key * - Presence of key,value means that path matches the search terms - * - Only tracks fond in @ref tracks_tracksdb are represented here + * - Only tracks fond in @ref trackdb_tracksdb are represented here * - This database can be reconstructed, it contains no user data */ DB *trackdb_searchdb; @@ -259,10 +259,23 @@ static int reap_db_deadlock(ev_source attribute((unused)) *ev, return 0; } -static pid_t subprogram(ev_source *ev, const char *prog, - int outputfd) { +static pid_t subprogram(ev_source *ev, int outputfd, const char *prog, + ...) { pid_t pid; - + va_list ap; + const char *args[1024], **argp, *a; + + argp = args; + *argp++ = prog; + *argp++ = "--config"; + *argp++ = configfile; + *argp++ = debugging ? "--debug" : "--no-debug"; + *argp++ = log_default == &log_syslog ? "--syslog" : "--no-syslog"; + va_start(ap, prog); + while((a = va_arg(ap, const char *))) + *argp++ = a; + va_end(ap); + *argp = 0; /* If we're in the background then trap subprocess stdout/stderr */ if(!(pid = xfork())) { exitfn = _exit; @@ -279,10 +292,7 @@ static pid_t subprogram(ev_source *ev, const char *prog, /* If we were negatively niced, undo it. We don't bother checking for * error, it's not that important. */ setpriority(PRIO_PROCESS, 0, 0); - execlp(prog, prog, "--config", configfile, - debugging ? "--debug" : "--no-debug", - log_default == &log_syslog ? "--syslog" : "--no-syslog", - (char *)0); + execvp(prog, (char **)args); fatal(errno, "error invoking %s", prog); } return pid; @@ -291,7 +301,7 @@ static pid_t subprogram(ev_source *ev, const char *prog, /* start deadlock manager */ void trackdb_master(ev_source *ev) { assert(db_deadlock_pid == -1); - db_deadlock_pid = subprogram(ev, DEADLOCK, -1); + db_deadlock_pid = subprogram(ev, -1, DEADLOCK, (char *)0); ev_child(ev, db_deadlock_pid, 0, reap_db_deadlock, 0); D(("started deadlock manager")); } @@ -308,10 +318,18 @@ void trackdb_deinit(void) { if((err = trackdb_env->close(trackdb_env, 0))) fatal(0, "trackdb_env->close: %s", db_strerror(err)); - if(rescan_pid != -1 && kill(rescan_pid, SIGTERM) < 0) - fatal(errno, "error killing rescanner"); + if(rescan_pid != -1) { + /* shut down the rescanner */ + if(kill(rescan_pid, SIGTERM) < 0) + fatal(errno, "error killing rescanner"); + /* wait for the rescanner to finish */ + while(waitpid(rescan_pid, &err, 0) == -1 && errno == EINTR) + ; + } - /* terminate the deadlock manager */ + /* TODO kill any stats subprocesses */ + + /* finally terminate the deadlock manager */ if(db_deadlock_pid != -1 && kill(db_deadlock_pid, SIGTERM) < 0) fatal(errno, "error killing deadlock manager"); db_deadlock_pid = -1; @@ -349,7 +367,7 @@ static DB *open_db(const char *path, } /** @brief Open track databases - * @param Flags flags word + * @param flags Flags flags word * * @p flags should have one of: * - @p TRACKDB_NO_UPGRADE, if no upgrade should be attempted @@ -396,7 +414,7 @@ void trackdb_open(int flags) { /* This database needs upgrading */ info("invoking disorder-dbupgrade to upgrade from %ld to %ld", oldversion, config->dbversion); - pid = subprogram(0, "disorder-dbupgrade", -1); + pid = subprogram(0, -1, "disorder-dbupgrade", (char *)0); while(waitpid(pid, &err, 0) == -1 && errno == EINTR) ; if(err) @@ -423,6 +441,9 @@ void trackdb_open(int flags) { trackdb_existing_database = 0; } /* open the databases */ + if(!(trackdb_usersdb = open_db("users.db", + 0, DB_HASH, dbflags, 0600))) + fatal(0, "cannot open users.db"); trackdb_tracksdb = open_db("tracks.db", DB_RECNUM, DB_BTREE, dbflags, 0666); trackdb_searchdb = open_db("search.db", @@ -433,8 +454,6 @@ void trackdb_open(int flags) { trackdb_globaldb = open_db("global.db", 0, DB_HASH, dbflags, 0666); trackdb_noticeddb = open_db("noticed.db", DB_DUPSORT, DB_BTREE, dbflags, 0666); - trackdb_usersdb = open_db("users.db", - 0, DB_HASH, dbflags, 0600); if(!trackdb_existing_database) { /* Stash the database version */ char buf[32]; @@ -1353,7 +1372,7 @@ void trackdb_stats_subprocess(ev_source *ev, d->done = done; d->u = u; xpipe(p); - pid = subprogram(ev, "disorder-stats", p[1]); + pid = subprogram(ev, p[1], "disorder-stats", (char *)0); xclose(p[1]); ev_child(ev, pid, 0, stats_finished, d); ev_reader_new(ev, p[0], stats_read, stats_error, d, "disorder-stats reader"); @@ -2146,14 +2165,20 @@ static int reap_rescan(ev_source attribute((unused)) *ev, return 0; } -void trackdb_rescan(ev_source *ev) { +/** @brief Initiate a rescan + * @param ev Event loop or 0 to block + * @param recheck 1 to recheck lengths, 0 to suppress check + */ +void trackdb_rescan(ev_source *ev, int recheck) { int w; if(rescan_pid != -1) { error(0, "rescan already underway"); return; } - rescan_pid = subprogram(ev, RESCAN, -1); + rescan_pid = subprogram(ev, -1, RESCAN, + recheck ? "--check" : "--no-check", + (char *)0); if(ev) { ev_child(ev, rescan_pid, 0, reap_rescan, 0); D(("started rescanner")); @@ -2574,7 +2599,8 @@ const char *trackdb_get_password(const char *user) { * @param user Username * @param password Password or NULL * @param rights Initial rights - * @param email Email address + * @param email Email address or NULL + * @param confirmation Confirmation string or NULL * @return 0 on success, non-0 on error */ int trackdb_adduser(const char *user, @@ -2587,7 +2613,7 @@ int trackdb_adduser(const char *user, WITH_TRANSACTION(create_user(user, password, rights, email, confirmation, tid, DB_NOOVERWRITE)); if(e) { - error(0, "cannot created user '%s' because they already exist", user); + error(0, "cannot create user '%s' because they already exist", user); return -1; } else { if(email) @@ -2601,7 +2627,7 @@ int trackdb_adduser(const char *user, /** @brief Delete a user * @param user User to delete - * @param 0 on success, non-0 if the user didn't exist anyway + * @return 0 on success, non-0 if the user didn't exist anyway */ int trackdb_deluser(const char *user) { int e; @@ -2704,11 +2730,20 @@ char **trackdb_listusers(void) { return v->vec; } +/** @brief Confirm a user registration + * @param user Username + * @param confirmation Confirmation string + * @param rightsp Where to put user rights + * @param tid Transaction ID + * @return 0 on success, non-0 on error + */ static int trackdb_confirm_tid(const char *user, const char *confirmation, + rights_type *rightsp, DB_TXN *tid) { const char *stored_confirmation; struct kvp *k; int e; + const char *rights; if((e = trackdb_getdata(trackdb_usersdb, user, &k, tid))) return e; @@ -2717,6 +2752,12 @@ static int trackdb_confirm_tid(const char *user, const char *confirmation, /* DB claims -30,800 to -30,999 so -1 should be a safe bet */ return -1; } + if(!(rights = kvp_get(k, "rights"))) { + error(0, "no rights for unconfirmed user '%s'", user); + return -1; + } + if(parse_rights(rights, rightsp, 1)) + return -1; if(strcmp(confirmation, stored_confirmation)) { error(0, "wrong confirmation string for user '%s'", user); return -1; @@ -2729,12 +2770,14 @@ static int trackdb_confirm_tid(const char *user, const char *confirmation, /** @brief Confirm a user registration * @param user Username * @param confirmation Confirmation string + * @param rightsp Where to put user rights * @return 0 on success, non-0 on error */ -int trackdb_confirm(const char *user, const char *confirmation) { +int trackdb_confirm(const char *user, const char *confirmation, + rights_type *rightsp) { int e; - WITH_TRANSACTION(trackdb_confirm_tid(user, confirmation, tid)); + WITH_TRANSACTION(trackdb_confirm_tid(user, confirmation, rightsp, tid)); switch(e) { case 0: info("registration confirmed for user '%s'", user);