--- file_not_specified_in_diff +++ file_not_specified_in_diff @@ -, +, @@ --- orig/src/internal.h +++ mod/src/internal.h @@ -5,6 +5,10 @@ # define LIBRCC_DATA_DIR "/usr/lib/rcc" #endif /* LIBRCC_DATA_DIR */ +#ifndef LIBRCC_LOCK_WAIT +# define LIBRCC_LOCK_WAIT 3000 /* ms */ +#endif /* LIBRCC_LOCK_WAIT */ + #define RCC_MAX_LANGUAGE_PARRENTS 4 #define RCC_MAX_RELATIONS RCC_MAX_LANGUAGES @@ -91,6 +95,9 @@ }; typedef struct rcc_context_t rcc_context_s; +int rccLock(); +void rccUnLock(); + int rccConfigure(rcc_context ctx); char *rccCreateResult(rcc_context ctx, size_t len); --- orig/src/librcc.c +++ mod/src/librcc.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "../config.h" @@ -19,6 +21,11 @@ # include #endif /* HAVE_PWD_H */ +#ifdef HAVE_SYS_FILE_H +# include +#endif /* HAVE_SYS_FILE_H */ + + #include "internal.h" #include "rccconfig.h" #include "rccenca.h" @@ -135,6 +142,89 @@ initialized = 0; } +static int lockfd = -1; + +int rccLock() { +# ifdef HAVE_SYS_FILE_H + int err, i; + int size; + char *stmp; + struct timespec wait = { 0, 10000000 }; + + if (lockfd>=0) return -1; + + size = strlen(rcc_home_dir) + 32; + stmp = (char*)malloc(size*sizeof(char)); + if (!stmp) return -1; + + sprintf(stmp,"%s/.rcc/", rcc_home_dir); + mkdir(stmp, 00755); + + sprintf(stmp,"%s/.rcc/locks/", rcc_home_dir); + mkdir(stmp, 00700); + + sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); + + lockfd = open(stmp, O_RDWR|O_CREAT, 0644); + if (lockfd >= 0) { + for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { + err = flock(lockfd, LOCK_EX|LOCK_NB); + if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); + else break; + } + + if (err) { + close(lockfd); + + // Removing invalid lock + if (i == (LIBRCC_LOCK_WAIT/10)) { + remove(stmp); + + lockfd = open(stmp, O_RDWR|O_CREAT, 0644); + if (lockfd >= 0) { + for (err = -1, i = 0; i < (LIBRCC_LOCK_WAIT/10); i++) { + err = flock(lockfd, LOCK_EX|LOCK_NB); + if ((err)&&(errno == EWOULDBLOCK)) nanosleep(&wait, NULL); + else break; + } + + if (err) close(lockfd); + else return 0; + } + } + + lockfd = -1; + return -1; + } + + return 0; + } + + return -1; +# else /* HAVE_SYS_FILE_H */ + return 0; +# endif /* HAVE_SYS_FILE_H */ +} + +void rccUnLock() { +#ifdef HAVE_SYS_FILE_H + int size; + char *stmp; + + if (lockfd<0) return; + + size = strlen(rcc_home_dir) + 32; + stmp = (char*)malloc(size*sizeof(char)); + if (!stmp) return; + + sprintf(stmp,"%s/.rcc/locks/rcc.lock", rcc_home_dir); + + flock(lockfd, LOCK_UN); + close(lockfd); + lockfd = -1; +#endif /* HAVE_SYS_FILE_H */ +} + rcc_context rccCreateContext(const char *locale_variable, unsigned int max_languages, unsigned int max_classes, rcc_class_ptr defclasses, rcc_init_flags flags) { unsigned int i; --- orig/src/rccdb4.c +++ mod/src/rccdb4.c @@ -15,11 +15,35 @@ #ifdef HAVE_DB_H DB_ENV *dbe; DB *db; + + char stmp[160]; err = db_env_create(&dbe, 0); if (err) return NULL; + + err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00644); + if (err == DB_VERSION_MISMATCH) { + + if (!rccLock()) { + err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_USE_ENVIRON|DB_PRIVATE|DB_RECOVER, 0); + rccUnLock(); + } else err = -1; + + dbe->close(dbe, 0); + if (err) return NULL; + + if (strlen(dbpath)<128) { + sprintf(stmp, "%s/log.0000000001", dbpath); + remove(stmp); + } + + err = db_env_create(&dbe, 0); + if (err) return NULL; + + err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00644); + + } - err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 00755); if (err) { dbe->close(dbe, 0); return NULL;