Header And Logo

PostgreSQL
| The world's most advanced open source database.

open.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * open.c
00004  *     Win32 open() replacement
00005  *
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  *
00009  * src/port/open.c
00010  *
00011  *-------------------------------------------------------------------------
00012  */
00013 
00014 #ifdef WIN32
00015 
00016 #ifndef FRONTEND
00017 #include "postgres.h"
00018 #else
00019 #include "postgres_fe.h"
00020 #endif
00021 
00022 #include <windows.h>
00023 #include <fcntl.h>
00024 #include <assert.h>
00025 
00026 
00027 static int
00028 openFlagsToCreateFileFlags(int openFlags)
00029 {
00030     switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
00031     {
00032             /* O_EXCL is meaningless without O_CREAT */
00033         case 0:
00034         case O_EXCL:
00035             return OPEN_EXISTING;
00036 
00037         case O_CREAT:
00038             return OPEN_ALWAYS;
00039 
00040             /* O_EXCL is meaningless without O_CREAT */
00041         case O_TRUNC:
00042         case O_TRUNC | O_EXCL:
00043             return TRUNCATE_EXISTING;
00044 
00045         case O_CREAT | O_TRUNC:
00046             return CREATE_ALWAYS;
00047 
00048             /* O_TRUNC is meaningless with O_CREAT */
00049         case O_CREAT | O_EXCL:
00050         case O_CREAT | O_TRUNC | O_EXCL:
00051             return CREATE_NEW;
00052     }
00053 
00054     /* will never get here */
00055     return 0;
00056 }
00057 
00058 /*
00059  *   - file attribute setting, based on fileMode?
00060  */
00061 int
00062 pgwin32_open(const char *fileName, int fileFlags,...)
00063 {
00064     int         fd;
00065     HANDLE      h = INVALID_HANDLE_VALUE;
00066     SECURITY_ATTRIBUTES sa;
00067     int         loops = 0;
00068 
00069     /* Check that we can handle the request */
00070     assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
00071                          (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
00072                          _O_SHORT_LIVED | O_DSYNC | O_DIRECT |
00073           (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
00074 
00075     sa.nLength = sizeof(sa);
00076     sa.bInheritHandle = TRUE;
00077     sa.lpSecurityDescriptor = NULL;
00078 
00079     while ((h = CreateFile(fileName,
00080     /* cannot use O_RDONLY, as it == 0 */
00081                       (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
00082                      ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
00083     /* These flags allow concurrent rename/unlink */
00084                     (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
00085                            &sa,
00086                            openFlagsToCreateFileFlags(fileFlags),
00087                            FILE_ATTRIBUTE_NORMAL |
00088                      ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
00089                ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
00090               ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
00091                 ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
00092                       ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
00093                        ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
00094                            NULL)) == INVALID_HANDLE_VALUE)
00095     {
00096         /*
00097          * Sharing violation or locking error can indicate antivirus, backup
00098          * or similar software that's locking the file. Try again for 30
00099          * seconds before giving up.
00100          */
00101         DWORD       err = GetLastError();
00102 
00103         if (err == ERROR_SHARING_VIOLATION ||
00104             err == ERROR_LOCK_VIOLATION)
00105         {
00106             pg_usleep(100000);
00107             loops++;
00108 
00109 #ifndef FRONTEND
00110             if (loops == 50)
00111                 ereport(LOG,
00112                         (errmsg("could not open file \"%s\": %s", fileName,
00113                                 (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
00114                          errdetail("Continuing to retry for 30 seconds."),
00115                          errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
00116 #endif
00117 
00118             if (loops < 300)
00119                 continue;
00120         }
00121 
00122         _dosmaperr(err);
00123         return -1;
00124     }
00125 
00126     /* _open_osfhandle will, on error, set errno accordingly */
00127     if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
00128         CloseHandle(h);         /* will not affect errno */
00129     else if (fileFlags & (O_TEXT | O_BINARY) &&
00130              _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
00131     {
00132         _close(fd);
00133         return -1;
00134     }
00135 
00136     return fd;
00137 }
00138 
00139 FILE *
00140 pgwin32_fopen(const char *fileName, const char *mode)
00141 {
00142     int         openmode = 0;
00143     int         fd;
00144 
00145     if (strstr(mode, "r+"))
00146         openmode |= O_RDWR;
00147     else if (strchr(mode, 'r'))
00148         openmode |= O_RDONLY;
00149     if (strstr(mode, "w+"))
00150         openmode |= O_RDWR | O_CREAT | O_TRUNC;
00151     else if (strchr(mode, 'w'))
00152         openmode |= O_WRONLY | O_CREAT | O_TRUNC;
00153     if (strchr(mode, 'a'))
00154         openmode |= O_WRONLY | O_CREAT | O_APPEND;
00155 
00156     if (strchr(mode, 'b'))
00157         openmode |= O_BINARY;
00158     if (strchr(mode, 't'))
00159         openmode |= O_TEXT;
00160 
00161     fd = pgwin32_open(fileName, openmode);
00162     if (fd == -1)
00163         return NULL;
00164     return _fdopen(fd, mode);
00165 }
00166 
00167 #endif