X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fcnid_dbd%2Fmain.c;h=55bbcddbb100c3b34fb34f5355d965c00bc6b3f0;hb=7be2a68aa70fa5641e944ad0aed6f699736d3de9;hp=ec0793cb9ceb2beebe4c1c350408fe19eb97ee38;hpb=4209e62c0346332dfe05efaec90f219abf1266e5;p=netatalk.git diff --git a/etc/cnid_dbd/main.c b/etc/cnid_dbd/main.c index ec0793cb..55bbcddb 100644 --- a/etc/cnid_dbd/main.c +++ b/etc/cnid_dbd/main.c @@ -8,28 +8,20 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ #include #include #include #include #include -#ifdef HAVE_SYS_TYPES_H #include -#endif /* HAVE_SYS_TYPES_H */ #include -#ifdef HAVE_SYS_STAT_H #include -#endif /* HAVE_SYS_STAT_H */ #include #include +#include -#include #include #include #include @@ -39,19 +31,18 @@ #include "dbd.h" #include "comm.h" -#define LOCKFILENAME "lock" - /* Note: DB_INIT_LOCK is here so we can run the db_* utilities while netatalk is running. It's a likey performance hit, but it might we worth it. */ -#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER) +#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN) /* Global, needed by pack.c:idxname() */ struct volinfo volinfo; static DBD *dbd; static int exit_sig = 0; +static int db_locked; static void sig_exit(int signo) { @@ -256,34 +247,6 @@ static void switch_to_user(char *dir) } } -/* ------------------------ */ -static int get_lock(void) -{ - int lockfd; - struct flock lock; - - if ((lockfd = open(LOCKFILENAME, O_RDWR | O_CREAT, 0644)) < 0) { - LOG(log_error, logtype_cnid, "main: error opening lockfile: %s", strerror(errno)); - exit(1); - } - - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - lock.l_type = F_WRLCK; - - if (fcntl(lockfd, F_SETLK, &lock) < 0) { - if (errno == EACCES || errno == EAGAIN) { - LOG(log_error, logtype_cnid, "get_lock: locked"); - exit(0); - } else { - LOG(log_error, logtype_cnid, "main: fcntl F_WRLCK lockfile: %s", strerror(errno)); - exit(1); - } - } - - return lockfd; -} /* ----------------------- */ static void set_signal(void) @@ -307,42 +270,35 @@ static void set_signal(void) } } -/* ----------------------- */ -static void free_lock(int lockfd) -{ - struct flock lock; - - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - lock.l_type = F_UNLCK; - fcntl(lockfd, F_SETLK, &lock); - close(lockfd); -} - /* ------------------------ */ int main(int argc, char *argv[]) { struct db_param *dbp; - int err = 0; - int lockfd, ctrlfd, clntfd; + int err = 0, ret, delete_bdb = 0; + int ctrlfd, clntfd; char *logconfig; set_processname("cnid_dbd"); - /* FIXME: implement -d from cnid_metad */ - if (argc != 5) { - LOG(log_error, logtype_cnid, "main: not enough arguments"); - exit(1); + while (( ret = getopt( argc, argv, "vVd")) != -1 ) { + switch (ret) { + case 'v': + case 'V': + printf("cnid_dbd (Netatalk %s)\n", VERSION); + return -1; + case 'd': + delete_bdb = 1; + break; + } } - ctrlfd = atoi(argv[2]); - clntfd = atoi(argv[3]); - logconfig = strdup(argv[4]); - setuplog(logconfig); + if (argc - optind != 4) { + LOG(log_error, logtype_cnid, "main: not enough arguments"); + exit(EXIT_FAILURE); + } /* Load .volinfo file */ - if (loadvolinfo(argv[1], &volinfo) == -1) { + if (loadvolinfo(argv[optind], &volinfo) == -1) { LOG(log_error, logtype_cnid, "Cant load volinfo for \"%s\"", argv[1]); exit(EXIT_FAILURE); } @@ -355,6 +311,11 @@ int main(int argc, char *argv[]) strncpy(dbpath, volinfo.v_dbpath, MAXPATHLEN - strlen("/.AppleDB")); strcat(dbpath, "/.AppleDB"); + ctrlfd = atoi(argv[optind + 1]); + clntfd = atoi(argv[optind + 2]); + logconfig = strdup(argv[optind + 3]); + setuplog(logconfig); + if (vol_load_charsets(&volinfo) == -1) { LOG(log_error, logtype_cnid, "Error loading charsets!"); exit(EXIT_FAILURE); @@ -363,9 +324,28 @@ int main(int argc, char *argv[]) switch_to_user(dbpath); - /* Before we do anything else, check if there is an instance of cnid_dbd - running already and silently exit if yes. */ - lockfd = get_lock(); + /* Get db lock */ + if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + exit(1); + } + if (db_locked != LOCK_EXCL) { + /* Couldn't get exclusive lock, try shared lock */ + if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + exit(1); + } + } + + if (delete_bdb && (db_locked == LOCK_EXCL)) { + LOG(log_warning, logtype_cnid, "main: too many CNID db opening attempts, wiping the slate clean"); + chdir(dbpath); + system("rm -f cnid2.db lock log.* __db.*"); + if ((db_locked = get_lock(LOCK_EXCL, dbpath)) != LOCK_EXCL) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + exit(EXIT_FAILURE); + } + } set_signal(); @@ -376,10 +356,13 @@ int main(int argc, char *argv[]) exit(1); LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file"); - if (NULL == (dbd = dbif_init(".", "cnid2.db"))) + if (NULL == (dbd = dbif_init(dbpath, "cnid2.db"))) exit(2); - if (dbif_env_open(dbd, dbp, DBOPTIONS) < 0) + /* Only recover if we got the lock */ + if (dbif_env_open(dbd, + dbp, + (db_locked == LOCK_EXCL) ? DBOPTIONS | DB_RECOVER : DBOPTIONS) < 0) exit(2); /* FIXME: same exit code as failure for dbif_open() */ LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment"); @@ -389,6 +372,19 @@ int main(int argc, char *argv[]) } LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases"); + /* Downgrade db lock */ + if (db_locked == LOCK_EXCL) { + if (get_lock(LOCK_UNLOCK, NULL) != 0) { + dbif_close(dbd); + exit(2); + } + if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) { + dbif_close(dbd); + exit(2); + } + } + + if (comm_init(dbp, ctrlfd, clntfd) < 0) { dbif_close(dbd); exit(3); @@ -403,8 +399,6 @@ int main(int argc, char *argv[]) if (dbif_env_remove(dbpath) < 0) err++; - free_lock(lockfd); - if (err) exit(4); else if (exit_sig)