]> granicus.if.org Git - postgresql/blobdiff - src/port/open.c
Centralize single quote escaping in src/port/quotes.c
[postgresql] / src / port / open.c
index 88fedc8475c59de1cb0fff19b3db96153af540ef..e91641d2a7c3c08edb34786baa4fb7e2c5e54ff0 100644 (file)
@@ -4,16 +4,20 @@
  *        Win32 open() replacement
  *
  *
- * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/port/open.c,v 1.20 2007/04/13 10:30:30 mha Exp $
+ * src/port/open.c
  *
  *-------------------------------------------------------------------------
  */
 
 #ifdef WIN32
 
-#include "c.h"
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
 
 #include <windows.h>
 #include <fcntl.h>
@@ -25,7 +29,7 @@ openFlagsToCreateFileFlags(int openFlags)
 {
        switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
        {
-               /* O_EXCL is meaningless without O_CREAT */
+                       /* O_EXCL is meaningless without O_CREAT */
                case 0:
                case O_EXCL:
                        return OPEN_EXISTING;
@@ -33,7 +37,7 @@ openFlagsToCreateFileFlags(int openFlags)
                case O_CREAT:
                        return OPEN_ALWAYS;
 
-               /* O_EXCL is meaningless without O_CREAT */
+                       /* O_EXCL is meaningless without O_CREAT */
                case O_TRUNC:
                case O_TRUNC | O_EXCL:
                        return TRUNCATE_EXISTING;
@@ -41,7 +45,7 @@ openFlagsToCreateFileFlags(int openFlags)
                case O_CREAT | O_TRUNC:
                        return CREATE_ALWAYS;
 
-               /* O_TRUNC is meaningless with O_CREAT */
+                       /* O_TRUNC is meaningless with O_CREAT */
                case O_CREAT | O_EXCL:
                case O_CREAT | O_TRUNC | O_EXCL:
                        return CREATE_NEW;
@@ -58,8 +62,9 @@ int
 pgwin32_open(const char *fileName, int fileFlags,...)
 {
        int                     fd;
-       HANDLE          h;
+       HANDLE          h = INVALID_HANDLE_VALUE;
        SECURITY_ATTRIBUTES sa;
+       int                     loops = 0;
 
        /* Check that we can handle the request */
        assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
@@ -71,44 +76,55 @@ pgwin32_open(const char *fileName, int fileFlags,...)
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;
 
-       if ((h = CreateFile(fileName,
+       while ((h = CreateFile(fileName,
        /* cannot use O_RDONLY, as it == 0 */
                                          (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
                                         ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
        /* These flags allow concurrent rename/unlink */
                                        (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
-                                               &sa,
-                                               openFlagsToCreateFileFlags(fileFlags),
-                                               FILE_ATTRIBUTE_NORMAL |
+                                                  &sa,
+                                                  openFlagsToCreateFileFlags(fileFlags),
+                                                  FILE_ATTRIBUTE_NORMAL |
                                         ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
                           ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
                          ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
                                ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
                                          ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
-                                         ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
-                                               NULL)) == INVALID_HANDLE_VALUE)
+                                          ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
+                                                  NULL)) == INVALID_HANDLE_VALUE)
        {
-               switch (GetLastError())
+               /*
+                * Sharing violation or locking error can indicate antivirus, backup
+                * or similar software that's locking the file. Try again for 30
+                * seconds before giving up.
+                */
+               DWORD           err = GetLastError();
+
+               if (err == ERROR_SHARING_VIOLATION ||
+                       err == ERROR_LOCK_VIOLATION)
                {
-                               /* EMFILE, ENFILE should not occur from CreateFile. */
-                       case ERROR_PATH_NOT_FOUND:
-                       case ERROR_FILE_NOT_FOUND:
-                               errno = ENOENT;
-                               break;
-                       case ERROR_FILE_EXISTS:
-                               errno = EEXIST;
-                               break;
-                       case ERROR_ACCESS_DENIED:
-                               errno = EACCES;
-                               break;
-                       default:
-                               errno = EINVAL;
+                       pg_usleep(100000);
+                       loops++;
+
+#ifndef FRONTEND
+                       if (loops == 50)
+                               ereport(LOG,
+                                               (errmsg("could not open file \"%s\": %s", fileName,
+                                                               (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
+                                                errdetail("Continuing to retry for 30 seconds."),
+                                                errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
+#endif
+
+                       if (loops < 300)
+                               continue;
                }
+
+               _dosmaperr(err);
                return -1;
        }
 
        /* _open_osfhandle will, on error, set errno accordingly */
-       if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0)
+       if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
                CloseHandle(h);                 /* will not affect errno */
        else if (fileFlags & (O_TEXT | O_BINARY) &&
                         _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)