diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c index a38019a1fa837849b02cd68c6b455926932a6e7b..da1801f7ba9f50ae40f13e471679f41a1913d730 100644 --- a/src/sbbs3/ftpsrvr.c +++ b/src/sbbs3/ftpsrvr.c @@ -2166,7 +2166,7 @@ static void ctrl_thread(void* arg) int curdir=-1; int orglib; int orgdir; - int mutex_file = -1; + fmutex_t mutex_file = {-1}; long filepos=0L; long timeleft; ulong l; @@ -2607,9 +2607,9 @@ static void ctrl_thread(void* arg) if(user.rest & FLAG('Q')) { // QWKnet accont char mutex_fname[MAX_PATH + 1]; snprintf(mutex_fname, sizeof mutex_fname, "%suser/%04u.ftp", scfg.data_dir, user.number); - if((mutex_file = fmutex_open(mutex_fname, startup->host_name, /* max_age: */60 * 60, &t, /* auto_remove: */true)) < 0) { + if(!fmutex_open(mutex_fname, startup->host_name, /* max_age: */60 * 60, /* auto_remove: */true, &mutex_file)) { lprintf(LOG_NOTICE, "%04d <%s> QWKnet account already logged-in to FTP server: %s (since %s)" - ,sock, user.alias, mutex_fname, time_as_hhmm(&scfg, t, str)); + ,sock, user.alias, mutex_fname, time_as_hhmm(&scfg, mutex_file.time, str)); sockprintf(sock, sess, "421 QWKnet accounts are limited to one concurrent FTP session"); user.number = 0; break; diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp index a3fa5924a2fc02df80088f0f23daddc94e17c934..1b0d511aeb734105254f7c62c99667a95f958ade 100644 --- a/src/sbbs3/main.cpp +++ b/src/sbbs3/main.cpp @@ -2918,12 +2918,11 @@ void event_thread(void* arg) sbbs->useron.number = atoi(fname+offset); getuserdat(&sbbs->cfg,&sbbs->useron); if(sbbs->useron.number != 0 && !(sbbs->useron.misc&(DELETED|INACTIVE))) { - time_t t; SAFEPRINTF(lockfname,"%s.lock",fname); - int lockfile = fmutex_open(lockfname,startup->host_name,TIMEOUT_MUTEX_FILE, &t, true); - if(lockfile < 0) { - if(difftime(time(NULL), t) > 60) - sbbs->lprintf(LOG_INFO," %s exists (unpack in progress?) since %s", lockfname, time_as_hhmm(&sbbs->cfg, t, str)); + fmutex_t lockfile; + if(!fmutex_open(lockfname, startup->host_name, TIMEOUT_MUTEX_FILE, true, &lockfile)) { + if(difftime(time(NULL), lockfile.time) > 60) + sbbs->lprintf(LOG_INFO," %s exists (unpack in progress?) since %s", lockfname, time_as_hhmm(&sbbs->cfg, lockfile.time, str)); continue; } sbbs->lprintf(LOG_DEBUG, "Opened %s", lockfname); @@ -2980,7 +2979,6 @@ void event_thread(void* arg) sbbs->useron.number = 0; sbbs->lprintf(LOG_INFO, "QWK pack semaphore signaled: %s", fname); int usernum = atoi(fname+offset); - time_t t; sbbs->useron.number = usernum; int retval = getuserdat(&sbbs->cfg,&sbbs->useron); if(retval != 0) { @@ -2989,10 +2987,10 @@ void event_thread(void* arg) continue; } SAFEPRINTF2(lockfname,"%spack%04u.lock",sbbs->cfg.data_dir,usernum); - int lockfile = fmutex_open(lockfname,startup->host_name,TIMEOUT_MUTEX_FILE, &t, true); - if(lockfile < 0) { - if(difftime(time(NULL), t) > 60) - sbbs->lprintf(LOG_INFO,"%s exists (pack in progress?) since %s", lockfname, time_as_hhmm(&sbbs->cfg, t, str)); + fmutex_t lockfile; + if(!fmutex_open(lockfname,startup->host_name,TIMEOUT_MUTEX_FILE, true, &lockfile)) { + if(difftime(time(NULL), lockfile.time) > 60) + sbbs->lprintf(LOG_INFO,"%s exists (pack in progress?) since %s", lockfname, time_as_hhmm(&sbbs->cfg, lockfile.time, str)); continue; } sbbs->lprintf(LOG_DEBUG, "Opened %s", lockfname); diff --git a/src/sbbs3/nopen.c b/src/sbbs3/nopen.c index cfc51fa4c71a94148cadde5e7c3b7f62599bfdd7..c176330ac3491d0a7b7ba675bde0ecb0574f0492 100644 --- a/src/sbbs3/nopen.c +++ b/src/sbbs3/nopen.c @@ -113,29 +113,30 @@ bool ftouch(const char* fname) } // Opens a mutex file and returns its file descriptor or -1 on failure -int fmutex_open(const char* fname, const char* text, long max_age, time_t* tp, bool auto_remove) +bool fmutex_open(const char* fname, const char* text, long max_age, bool auto_remove, fmutex_t* fm) { - int file; - time_t t; size_t len; #if !defined(NO_SOCKET_SUPPORT) char hostname[128]; #endif -#ifdef _WIN32 +#if defined _WIN32 DWORD attributes = FILE_ATTRIBUTE_NORMAL; HANDLE h; #endif - if(max_age > 0 || tp != NULL) { - if(tp == NULL) - tp = &t; - *tp = fdate(fname); - if(max_age > 0 && *tp != -1 && (time(NULL) - *tp) > max_age) { - if(remove(fname)!=0) - return -1; + if(fm == NULL) + return false; + memset(fm, 0, sizeof *fm); + snprintf(fm->name, sizeof fm->name, fname); + fm->remove = auto_remove; + if(max_age > 0) { + fm->time = fdate(fname); + if(max_age > 0 && fm->time != -1 && (time(NULL) - fm->time) > max_age) { + if(remove(fname) != 0) + return false; } } -#ifdef _WIN32 +#if defined _WIN32 if(auto_remove) attributes |= FILE_FLAG_DELETE_ON_CLOSE; h = CreateFileA(fname, @@ -147,21 +148,14 @@ int fmutex_open(const char* fname, const char* text, long max_age, time_t* tp, b NULL // hTemplateFile ); if(h == INVALID_HANDLE_VALUE) - return -1; - if((file = _open_osfhandle((intptr_t)h, O_WRONLY)) == -1) { + return false; + if((fm->fd = _open_osfhandle((intptr_t)h, O_WRONLY)) == -1) { CloseHandle(h); - return -1; + return false; } #else - if((file=sopen(fname, O_CREAT|O_WRONLY|O_EXCL, SH_DENYRW, DEFFILEMODE))<0) - return -1; - if(auto_remove) { - // the file will remain in existence until the last file descriptor referring to it is closed - if(remove(fname) != 0) { - close(file); - return -1; - } - } + if((fm->fd = sopen(fname, O_CREAT|O_WRONLY|O_EXCL, SH_DENYRW, DEFFILEMODE)) < 0) + return false; #endif #if !defined(NO_SOCKET_SUPPORT) if(text==NULL && gethostname(hostname,sizeof(hostname))==0) @@ -169,33 +163,43 @@ int fmutex_open(const char* fname, const char* text, long max_age, time_t* tp, b #endif if(text!=NULL) { len = strlen(text); - if(write(file, text, len) != len) { - close(file); - return -1; + if(write(fm->fd, text, len) != len) { + close(fm->fd); + return false; } } - return file; + return true; } -bool fmutex_close(int* file) +bool fmutex_close(fmutex_t* fm) { - if(file == NULL) + if(fm == NULL) return false; - if(*file < 0) // already closed (or never opened) + if(fm->fd < 0) // already closed (or never opened) return true; - if(close(*file) != 0) +#if !defined _WIN32 // should only be necessary (and possible) on *nix + if(fm->remove) { + if(unlink(fm->name) != 0) + return false; + } +#endif + if(close(fm->fd) != 0) return false; - *file = -1; + fm->fd = -1; return true; } // Opens and immediately closes a mutex file bool fmutex(const char* fname, const char* text, long max_age, time_t* tp) { - int file = fmutex_open(fname, text, max_age, tp, /* auto_remove: */false); - if(file < 0) + fmutex_t fm; + + if(!fmutex_open(fname, text, max_age, /* auto_remove: */false, &fm)) { + if(tp != NULL) + *tp = fm.time; return false; - return fmutex_close(&file); + } + return fmutex_close(&fm); } bool fcompare(const char* fn1, const char* fn2) diff --git a/src/sbbs3/nopen.h b/src/sbbs3/nopen.h index 466236d2a170941e1eca05cea32529f19bb51475..067acbd9de73ad1bf186ca5afb11cad51deb5b76 100644 --- a/src/sbbs3/nopen.h +++ b/src/sbbs3/nopen.h @@ -25,10 +25,18 @@ #include <stdio.h> /* FILE */ #include <fcntl.h> /* O_RDONLY */ #include "gen_defs.h" /* bool */ +#include "dirwrap.h" /* MAX_PATH */ #define FNOPEN_BUF_SIZE (2*1024) #define LOOP_NOPEN 100 /* Retries before file access denied */ +typedef struct { + int fd; + time_t time; + bool remove; + char name[MAX_PATH + 1]; +} fmutex_t; + #ifdef __cplusplus extern "C" { #endif @@ -37,8 +45,8 @@ int nopen(const char* str, uint access); FILE * fnopen(int* file, const char* str, uint access); bool ftouch(const char* fname); bool fmutex(const char* fname, const char* text, long max_age, time_t*); -int fmutex_open(const char* fname, const char* text, long max_age, time_t*, bool auto_remove); -bool fmutex_close(int* file); +bool fmutex_open(const char* fname, const char* text, long max_age, bool auto_remove, fmutex_t*); +bool fmutex_close(fmutex_t*); bool fcompare(const char* fn1, const char* fn2); bool backup(const char* org, int backup_level, bool ren);