PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
open.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * open.c
4  * Win32 open() replacement
5  *
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  *
9  * src/port/open.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #ifdef WIN32
15 
16 #ifndef FRONTEND
17 #include "postgres.h"
18 #else
19 #include "postgres_fe.h"
20 #endif
21 
22 #include <windows.h>
23 #include <fcntl.h>
24 #include <assert.h>
25 
26 
27 static int
28 openFlagsToCreateFileFlags(int openFlags)
29 {
30  switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
31  {
32  /* O_EXCL is meaningless without O_CREAT */
33  case 0:
34  case O_EXCL:
35  return OPEN_EXISTING;
36 
37  case O_CREAT:
38  return OPEN_ALWAYS;
39 
40  /* O_EXCL is meaningless without O_CREAT */
41  case O_TRUNC:
42  case O_TRUNC | O_EXCL:
43  return TRUNCATE_EXISTING;
44 
45  case O_CREAT | O_TRUNC:
46  return CREATE_ALWAYS;
47 
48  /* O_TRUNC is meaningless with O_CREAT */
49  case O_CREAT | O_EXCL:
50  case O_CREAT | O_TRUNC | O_EXCL:
51  return CREATE_NEW;
52  }
53 
54  /* will never get here */
55  return 0;
56 }
57 
58 /*
59  * - file attribute setting, based on fileMode?
60  */
61 int
62 pgwin32_open(const char *fileName, int fileFlags,...)
63 {
64  int fd;
65  HANDLE h = INVALID_HANDLE_VALUE;
66  SECURITY_ATTRIBUTES sa;
67  int loops = 0;
68 
69  /* Check that we can handle the request */
70  assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
71  (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
72  _O_SHORT_LIVED | O_DSYNC | O_DIRECT |
73  (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
74 
75  sa.nLength = sizeof(sa);
76  sa.bInheritHandle = TRUE;
77  sa.lpSecurityDescriptor = NULL;
78 
79  while ((h = CreateFile(fileName,
80  /* cannot use O_RDONLY, as it == 0 */
81  (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
82  ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
83  /* These flags allow concurrent rename/unlink */
84  (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
85  &sa,
86  openFlagsToCreateFileFlags(fileFlags),
87  FILE_ATTRIBUTE_NORMAL |
88  ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
89  ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
90  ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
91  ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
92  ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
93  ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
94  NULL)) == INVALID_HANDLE_VALUE)
95  {
96  /*
97  * Sharing violation or locking error can indicate antivirus, backup
98  * or similar software that's locking the file. Try again for 30
99  * seconds before giving up.
100  */
101  DWORD err = GetLastError();
102 
103  if (err == ERROR_SHARING_VIOLATION ||
104  err == ERROR_LOCK_VIOLATION)
105  {
106  pg_usleep(100000);
107  loops++;
108 
109 #ifndef FRONTEND
110  if (loops == 50)
111  ereport(LOG,
112  (errmsg("could not open file \"%s\": %s", fileName,
113  (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
114  errdetail("Continuing to retry for 30 seconds."),
115  errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
116 #endif
117 
118  if (loops < 300)
119  continue;
120  }
121 
122  _dosmaperr(err);
123  return -1;
124  }
125 
126  /* _open_osfhandle will, on error, set errno accordingly */
127  if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
128  CloseHandle(h); /* will not affect errno */
129  else if (fileFlags & (O_TEXT | O_BINARY) &&
130  _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
131  {
132  _close(fd);
133  return -1;
134  }
135 
136  return fd;
137 }
138 
139 FILE *
140 pgwin32_fopen(const char *fileName, const char *mode)
141 {
142  int openmode = 0;
143  int fd;
144 
145  if (strstr(mode, "r+"))
146  openmode |= O_RDWR;
147  else if (strchr(mode, 'r'))
148  openmode |= O_RDONLY;
149  if (strstr(mode, "w+"))
150  openmode |= O_RDWR | O_CREAT | O_TRUNC;
151  else if (strchr(mode, 'w'))
152  openmode |= O_WRONLY | O_CREAT | O_TRUNC;
153  if (strchr(mode, 'a'))
154  openmode |= O_WRONLY | O_CREAT | O_APPEND;
155 
156  if (strchr(mode, 'b'))
157  openmode |= O_BINARY;
158  if (strchr(mode, 't'))
159  openmode |= O_TEXT;
160 
161  fd = pgwin32_open(fileName, openmode);
162  if (fd == -1)
163  return NULL;
164  return _fdopen(fd, mode);
165 }
166 
167 #endif
int errhint(const char *fmt,...)
Definition: elog.c:987
#define LOG
Definition: elog.h:26
static int fd(const char *x, int i)
Definition: preproc-init.c:105
void pg_usleep(long microsec)
Definition: signal.c:53
#define O_DSYNC
Definition: win32.h:280
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define assert(TEST)
Definition: imath.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:226
void _dosmaperr(unsigned long)
Definition: win32error.c:171
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define TRUE
Definition: c.h:214
#define _(x)
Definition: elog.c:84