]> granicus.if.org Git - nethack/commitdiff
win32: hold .0 file open exclusively
authornethack.allison <nethack.allison>
Wed, 21 Aug 2002 15:21:56 +0000 (15:21 +0000)
committernethack.allison <nethack.allison>
Wed, 21 Aug 2002 15:21:56 +0000 (15:21 +0000)
-prevents problems with internal recover
if second copy of game is started up with
the same player name.

include/extern.h
include/ntconf.h
src/files.c
sys/share/pcunix.c
sys/winnt/winnt.c
util/makedefs.c

index 42df9d61ff14652ef4c7365d7358026eec4b79c0..0915fe706d24c8cafa92bf2e2883532e43d3a608 100644 (file)
@@ -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 */
 
index 840b15c507ff12ab977146daae1dd74ae8a5b70d..4dec2eb00875f2f2bf0f333264552cdc90eafd3f 100644 (file)
@@ -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 */
 
 /*
index 5d89e26d822940df32bfe45dc95dcaf05ba7a9d1..dce5f8c5048dd46e1b305f416f99419adbdcab80 100644 (file)
@@ -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 <share.h>
+# 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.
index 7c2b70aab81038cda38e21bdce0c05b357ef88e8..1076487e1baab20ef6ffae555af820cbd0ac0136 100644 (file)
@@ -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
index 3b711a0e8f88842428477e6daed41b09456d9394..64783509d90bdd771021e1fd47c91083985f7bfc 100644 (file)
@@ -233,53 +233,6 @@ void win32_abort()
 #endif
        abort();
 }
-
-#if !defined(WIN_CE)
-#include <tlhelp32.h>
-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*/
index 0c27da698b0a5ada130eb3d4c32d6669c724c01e..7d89288416f015517a41c24fd63e36e84459e6e1 100644 (file)
@@ -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