about summary refs log tree commit diff
path: root/src/libstore/pathlocks.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-06-19T14·43+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-06-19T14·43+0000
commitb35735d8b28af206fa0b293c796bf44c62dde678 (patch)
treef0ba3807a5de3ced6d83a76a1ef07e5029604e3f /src/libstore/pathlocks.cc
parent0e783e557941f77d5b4bcf2a6c6423ed583991a2 (diff)
* On Windows we cannot delete open (lock) files, so we delete lock
  files after we've closed them.  Since this only succeeds if the lock
  is no longer opened by any process, the token trick used on Unix is
  not necessary.

Diffstat (limited to 'src/libstore/pathlocks.cc')
-rw-r--r--src/libstore/pathlocks.cc51
1 files changed, 47 insertions, 4 deletions
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index 7f7cbdf15a68..bb1644a9a9fd 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -6,6 +6,11 @@
 
 #include "pathlocks.hh"
 
+#ifdef __CYGWIN__
+#include <windows.h>
+#include <sys/cygwin.h>
+#endif
+
 
 bool lockFile(int fd, LockType lockType, bool wait)
 {
@@ -87,11 +92,28 @@ void PathLocks::lockPaths(const PathSet & _paths, const string & waitMsg)
         AutoCloseFD fd;
         
         while (1) {
-        
+
             /* Open/create the lock file. */
+#ifdef __CYGWIN__
+	    char win32Path[MAX_PATH];
+	    cygwin_conv_to_full_win32_path(lockPath.c_str(), win32Path);
+
+	    SECURITY_ATTRIBUTES sa;
+	    sa.nLength = sizeof sa;
+	    sa.lpSecurityDescriptor = 0;
+	    sa.bInheritHandle = TRUE;
+	    HANDLE h = CreateFile(win32Path, GENERIC_READ, 
+	        FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_ALWAYS, 
+                FILE_ATTRIBUTE_NORMAL, 0);
+	    if (h == INVALID_HANDLE_VALUE)
+		throw Error(format("opening lock file `%1%'") % lockPath);
+
+	    fd = cygwin_attach_handle_to_fd((char *) lockPath.c_str(), -1, h, 1, O_RDWR);
+#else        
             fd = open(lockPath.c_str(), O_WRONLY | O_CREAT, 0666);
             if (fd == -1)
                 throw SysError(format("opening lock file `%1%'") % lockPath);
+#endif
 
             /* Acquire an exclusive lock. */
             if (!lockFile(fd, ltWrite, false)) {
@@ -126,19 +148,40 @@ void PathLocks::lockPaths(const PathSet & _paths, const string & waitMsg)
 PathLocks::~PathLocks()
 {
     for (list<FDPair>::iterator i = fds.begin(); i != fds.end(); i++) {
+#ifndef __CYGWIN__
         if (deletePaths) {
-            /* Write a (meaningless) token to the file to indicate to
-               other processes waiting on this lock that the lock is
-               stale (deleted). */
+	    /* Get rid of the lock file.  Have to be careful not to
+	       introduce races. */
+            /* On Unix, write a (meaningless) token to the file to
+               indicate to other processes waiting on this lock that
+               the lock is stale (deleted). */
             unlink(i->second.c_str());
             writeFull(i->first, (const unsigned char *) "d", 1);
             /* Note that the result of unlink() is ignored; removing
                the lock file is an optimisation, not a necessity. */
         }
+#endif
         lockedPaths.erase(i->second);
         if (close(i->first) == -1)
             printMsg(lvlError,
                 format("error (ignored): cannot close lock file on `%1%'") % i->second);
+#ifdef __CYGWIN__
+	if (deletePaths) {
+	    /* On Windows, just try to delete the lock file.  This
+	       will fail if anybody still has the file open.  We
+	       cannot use unlink() here, because Cygwin emulates Unix
+	       semantics of allowing an open file to be deleted (but
+	       fakes it - the file isn't actually deleted until later,
+	       so a file with the same name cannot be created in the
+	       meantime). */
+	    char win32Path[MAX_PATH];
+	    cygwin_conv_to_full_win32_path(i->second.c_str(), win32Path);
+	    if (DeleteFile(win32Path))
+		debug(format("delete of `%1%' succeeded") % i->second.c_str());
+	    else
+		debug(format("delete of `%1%' failed: %2%") % i->second.c_str() % GetLastError());
+	}
+#endif
         debug(format("lock released on `%1%'") % i->second);
     }
 }