From 2697615bd343b96e60bf65042478c9d3cb0593af Mon Sep 17 00:00:00 2001 From: "nethack.allison" Date: Wed, 21 Aug 2002 15:21:56 +0000 Subject: [PATCH] win32: hold .0 file open exclusively -prevents problems with internal recover if second copy of game is started up with the same player name. --- include/extern.h | 6 +-- include/ntconf.h | 2 + src/files.c | 96 +++++++++++++++++++++++++++++++++++++++++----- sys/share/pcunix.c | 12 ++++++ sys/winnt/winnt.c | 47 ----------------------- util/makedefs.c | 3 ++ 6 files changed, 107 insertions(+), 59 deletions(-) diff --git a/include/extern.h b/include/extern.h index 42df9d61f..0915fe706 100644 --- a/include/extern.h +++ b/include/extern.h @@ -647,6 +647,9 @@ E void FDECL(free_saved_games, (char**)); #ifdef SELF_RECOVER E boolean NDECL(recover_savefile); #endif +#ifdef HOLD_LOCKFILE_OPEN +E void NDECL(really_close); +#endif /* ### fountain.c ### */ @@ -1236,9 +1239,6 @@ E char *FDECL(get_username, (int *)); E void FDECL(nt_regularize, (char *)); E int NDECL((*nt_kbhit)); E void FDECL(Delay, (int)); -# if !defined(WIN_CE) -E boolean FDECL(is_NetHack_process, (int)); -# endif /* !WIN_CE */ # endif /* WIN32 */ #endif /* MICRO || WIN32 */ diff --git a/include/ntconf.h b/include/ntconf.h index 840b15c50..4dec2eb00 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -19,6 +19,8 @@ #define PC_LOCKING /* Prevent overwrites of aborted or in-progress games */ /* without first receiving confirmation. */ +#define HOLD_LOCKFILE_OPEN /* Keep an exclusive lock on the .0 file */ + #define SELF_RECOVER /* Allow the game itself to recover from an aborted game */ /* diff --git a/src/files.c b/src/files.c index 5d89e26d8..dce5f8c50 100644 --- a/src/files.c +++ b/src/files.c @@ -84,6 +84,17 @@ char SAVEF[SAVESIZE]; /* holds relative path of save file from playground */ char SAVEP[SAVESIZE]; /* holds path of directory for save file */ #endif +#ifdef HOLD_LOCKFILE_OPEN +struct level_ftrack { +int fd; /* file descriptor for level file */ +int oflag; /* open flags */ +boolean nethack_thinks_it_is_open; /* Does NetHack think it's open? */ +} lftrack; +# if defined(WIN32) +#include +# endif +#endif /*HOLD_LOCKFILE_OPEN*/ + #ifdef WIZARD #define WIZKIT_MAX 128 static char wizkit[WIZKIT_MAX]; @@ -135,7 +146,9 @@ STATIC_DCL void FDECL(adjust_prefix, (char *, int)); #ifdef SELF_RECOVER STATIC_DCL boolean FDECL(copy_bytes, (int, int)); #endif - +#ifdef HOLD_LOCKFILE_OPEN +STATIC_DCL int FDECL(open_levelfile_exclusively, (const char *, int, int)); +#endif /* * fname_encode() @@ -404,6 +417,12 @@ int lev; /* Use O_TRUNC to force the file to be shortened if it already * exists and is currently longer. */ +# ifdef HOLD_LOCKFILE_OPEN + if (lev == 0) + fd = open_levelfile_exclusively(fq_lock, lev, + O_WRONLY |O_CREAT | O_TRUNC | O_BINARY); + else +# endif fd = open(fq_lock, O_WRONLY |O_CREAT | O_TRUNC | O_BINARY, FCMASK); #else # ifdef MAC @@ -437,6 +456,11 @@ int lev; #ifdef MAC fd = macopen(fq_lock, O_RDONLY | O_BINARY, LEVL_TYPE); #else +# ifdef HOLD_LOCKFILE_OPEN + if (lev == 0) + fd = open_levelfile_exclusively(fq_lock, lev, O_RDONLY | O_BINARY ); + else +# endif fd = open(fq_lock, O_RDONLY | O_BINARY, 0); #endif return fd; @@ -453,6 +477,9 @@ int lev; */ if (lev == 0 || (level_info[lev].flags & LFILE_EXISTS)) { set_levelfile_name(lock, lev); +#ifdef HOLD_LOCKFILE_OPEN + if (lev == 0) really_close(); +#endif (void) unlink(fqname(lock, LEVELPREFIX, 0)); level_info[lev].flags &= ~LFILE_EXISTS; } @@ -478,6 +505,62 @@ clearlocks() #endif } +#ifdef HOLD_LOCKFILE_OPEN +STATIC_OVL int +open_levelfile_exclusively(name, lev, oflag) +const char *name; +int lev, oflag; +{ + int reslt, fd; + if (lftrack.fd) { + /* check for compatible access */ + if (lftrack.oflag == oflag) { + fd = lftrack.fd; + reslt = lseek(fd, 0L, SEEK_SET); + if (reslt == -1L) + panic("open_levelfile_exclusively: lseek failed %d", reslt); + lftrack.nethack_thinks_it_is_open = TRUE; + } else { + really_close(); + fd = sopen(name, oflag,_SH_DENYRW, FCMASK); + lftrack.fd = fd; + lftrack.oflag = oflag; + lftrack.nethack_thinks_it_is_open = TRUE; + } + } else { + fd = sopen(name, oflag,_SH_DENYRW, FCMASK); + lftrack.fd = fd; + lftrack.oflag = oflag; + if (fd) + lftrack.nethack_thinks_it_is_open = TRUE; + } + return fd; +} + +void +really_close() +{ + int fd = lftrack.fd; + lftrack.nethack_thinks_it_is_open = FALSE; + lftrack.fd = 0; + lftrack.oflag = 0; + (void)_close(fd); + return; +} + +close(fd) +int fd; +{ + if (lftrack.fd == fd) { + really_close(); /* close it, but reopen it to hold it */ + fd = open_levelfile(0); + lftrack.nethack_thinks_it_is_open = FALSE; + return 0; + } + return _close(fd); +} +#endif + /* ---------- END LEVEL FILE HANDLING ----------- */ @@ -2119,14 +2202,6 @@ recover_savefile() (void)close(gfd); return FALSE; } -#if defined(WIN32) && !defined(WIN_CE) - if (is_NetHack_process(hpid)) { - raw_printf( - "\nThe level files belong to an active NetHack process and cannot be recovered."); - (void)close(gfd); - return FALSE; - } -#endif if (read(gfd, (genericptr_t) &savelev, sizeof(savelev)) != sizeof(savelev)) { raw_printf("\nCheckpointing was not in effect for %s -- recovery impossible.\n", @@ -2216,6 +2291,9 @@ recover_savefile() } (void)close(sfd); +#ifdef HOLD_LOCKFILE_OPEN + really_close(); +#endif /* * We have a successful savefile! * Only now do we erase the level files. diff --git a/sys/share/pcunix.c b/sys/share/pcunix.c index 7c2b70aab..1076487e1 100644 --- a/sys/share/pcunix.c +++ b/sys/share/pcunix.c @@ -88,6 +88,9 @@ eraseoldlocks() (void) unlink(fqname(lock, LEVELPREFIX, 0)); } set_levelfile_name(lock, 0); +#ifdef HOLD_LOCKFILE_OPEN + really_close(); +#endif if(unlink(fqname(lock, LEVELPREFIX, 0))) return 0; /* cannot remove it */ return(1); /* success! */ @@ -122,6 +125,15 @@ getlock() chdirx(orgdir, 0); # endif # if defined(WIN32) +# if defined(HOLD_LOCKFILE_OPEN) + if(errno == EACCES) { + msmsg("\nThere are files from a game in progress under your name."); + msmsg( + "\nThe files are locked or inaccessible. Is the other game still running?"); + unlock_file(HLOCK); + error("Cannot open %s", fq_lock); + } else +# endif error("Bad directory or name: %s\n%s\n", fq_lock, strerror(errno)); # else diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 3b711a0e8..64783509d 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -233,53 +233,6 @@ void win32_abort() #endif abort(); } - -#if !defined(WIN_CE) -#include -boolean -is_NetHack_process(pid) -int pid; -{ - HANDLE hProcessSnap = NULL; - PROCESSENTRY32 pe32 = {0}; - boolean bRet = FALSE; - HINSTANCE hinstLib; - genericptr_t ProcTest; - BOOL fFreeResult; - - hinstLib = LoadLibrary("KERNEL32"); - if (hinstLib != NULL) { - ProcTest = (genericptr_t) GetProcAddress(hinstLib, "Process32Next"); - if (!ProcTest) { - fFreeResult = FreeLibrary(hinstLib); - return FALSE; - } - fFreeResult = FreeLibrary(hinstLib); - } - - hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (hProcessSnap == INVALID_HANDLE_VALUE) - return FALSE; - - /* Set size of the processentry32 structure before using it. */ - pe32.dwSize = sizeof(PROCESSENTRY32); - if (Process32First(hProcessSnap, &pe32)) { - do { - if (pe32.th32ProcessID == (unsigned)pid && pe32.szExeFile && - ((strlen(pe32.szExeFile) >= 12 && - !strcmpi(&pe32.szExeFile[strlen(pe32.szExeFile) - 12], "nethackw.exe")) || - (strlen(pe32.szExeFile) >= 11 && - !strcmpi(&pe32.szExeFile[strlen(pe32.szExeFile) - 11], "nethack.exe")))) - bRet = TRUE; - } - while (Process32Next(hProcessSnap, &pe32)); - } - else - bRet = FALSE; - CloseHandle(hProcessSnap); - return bRet; -} -#endif /* WIN_CE*/ #endif /* WIN32 */ /*winnt.c*/ diff --git a/util/makedefs.c b/util/makedefs.c index 0c27da698..7d8928841 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -644,6 +644,9 @@ static const char *build_opts[] = { #ifdef KOPS "Keystone Kops", #endif +#ifdef HOLD_LOCKFILE_OPEN + "exlusive lock on level 0 file", +#endif #ifdef LOGFILE "log file", #endif