Consistently use "superuser" instead of "super user"
[pgsql.git] / src / port / open.c
blob14c6debba915cff31219758e0d228588db999766
1 /*-------------------------------------------------------------------------
3 * open.c
4 * Win32 open() replacement
7 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
9 * src/port/open.c
11 *-------------------------------------------------------------------------
14 #ifdef WIN32
16 #ifndef FRONTEND
17 #include "postgres.h"
18 #else
19 #include "postgres_fe.h"
20 #endif
22 #include <fcntl.h>
23 #include <assert.h>
24 #include <sys/stat.h>
27 static int
28 openFlagsToCreateFileFlags(int openFlags)
30 switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
32 /* O_EXCL is meaningless without O_CREAT */
33 case 0:
34 case O_EXCL:
35 return OPEN_EXISTING;
37 case O_CREAT:
38 return OPEN_ALWAYS;
40 /* O_EXCL is meaningless without O_CREAT */
41 case O_TRUNC:
42 case O_TRUNC | O_EXCL:
43 return TRUNCATE_EXISTING;
45 case O_CREAT | O_TRUNC:
46 return CREATE_ALWAYS;
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;
54 /* will never get here */
55 return 0;
59 * - file attribute setting, based on fileMode?
61 int
62 pgwin32_open(const char *fileName, int fileFlags,...)
64 int fd;
65 HANDLE h = INVALID_HANDLE_VALUE;
66 SECURITY_ATTRIBUTES sa;
67 int loops = 0;
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 #ifndef FRONTEND
75 Assert(pgwin32_signal_event != NULL); /* small chance of pg_usleep() */
76 #endif
78 #ifdef FRONTEND
81 * Since PostgreSQL 12, those concurrent-safe versions of open() and
82 * fopen() can be used by frontends, having as side-effect to switch the
83 * file-translation mode from O_TEXT to O_BINARY if none is specified.
84 * Caller may want to enforce the binary or text mode, but if nothing is
85 * defined make sure that the default mode maps with what versions older
86 * than 12 have been doing.
88 if ((fileFlags & O_BINARY) == 0)
89 fileFlags |= O_TEXT;
90 #endif
92 sa.nLength = sizeof(sa);
93 sa.bInheritHandle = TRUE;
94 sa.lpSecurityDescriptor = NULL;
96 while ((h = CreateFile(fileName,
97 /* cannot use O_RDONLY, as it == 0 */
98 (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
99 ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
100 /* These flags allow concurrent rename/unlink */
101 (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
102 &sa,
103 openFlagsToCreateFileFlags(fileFlags),
104 FILE_ATTRIBUTE_NORMAL |
105 ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
106 ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
107 ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
108 ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
109 ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
110 ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
111 NULL)) == INVALID_HANDLE_VALUE)
114 * Sharing violation or locking error can indicate antivirus, backup
115 * or similar software that's locking the file. Wait a bit and try
116 * again, giving up after 30 seconds.
118 DWORD err = GetLastError();
120 if (err == ERROR_SHARING_VIOLATION ||
121 err == ERROR_LOCK_VIOLATION)
123 #ifndef FRONTEND
124 if (loops == 50)
125 ereport(LOG,
126 (errmsg("could not open file \"%s\": %s", fileName,
127 (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
128 errdetail("Continuing to retry for 30 seconds."),
129 errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
130 #endif
132 if (loops < 300)
134 pg_usleep(100000);
135 loops++;
136 continue;
141 * ERROR_ACCESS_DENIED is returned if the file is deleted but not yet
142 * gone (Windows NT status code is STATUS_DELETE_PENDING). In that
143 * case we want to wait a bit and try again, giving up after 1 second
144 * (since this condition should never persist very long). However,
145 * there are other commonly-hit cases that return ERROR_ACCESS_DENIED,
146 * so care is needed. In particular that happens if we try to open a
147 * directory, or of course if there's an actual file-permissions
148 * problem. To distinguish these cases, try a stat(). In the
149 * delete-pending case, it will either also get STATUS_DELETE_PENDING,
150 * or it will see the file as gone and fail with ENOENT. In other
151 * cases it will usually succeed. The only somewhat-likely case where
152 * this coding will uselessly wait is if there's a permissions problem
153 * with a containing directory, which we hope will never happen in any
154 * performance-critical code paths.
156 if (err == ERROR_ACCESS_DENIED)
158 if (loops < 10)
160 struct stat st;
162 if (stat(fileName, &st) != 0)
164 pg_usleep(100000);
165 loops++;
166 continue;
171 _dosmaperr(err);
172 return -1;
175 /* _open_osfhandle will, on error, set errno accordingly */
176 if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
177 CloseHandle(h); /* will not affect errno */
178 else if (fileFlags & (O_TEXT | O_BINARY) &&
179 _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
181 _close(fd);
182 return -1;
185 return fd;
188 FILE *
189 pgwin32_fopen(const char *fileName, const char *mode)
191 int openmode = 0;
192 int fd;
194 if (strstr(mode, "r+"))
195 openmode |= O_RDWR;
196 else if (strchr(mode, 'r'))
197 openmode |= O_RDONLY;
198 if (strstr(mode, "w+"))
199 openmode |= O_RDWR | O_CREAT | O_TRUNC;
200 else if (strchr(mode, 'w'))
201 openmode |= O_WRONLY | O_CREAT | O_TRUNC;
202 if (strchr(mode, 'a'))
203 openmode |= O_WRONLY | O_CREAT | O_APPEND;
205 if (strchr(mode, 'b'))
206 openmode |= O_BINARY;
207 if (strchr(mode, 't'))
208 openmode |= O_TEXT;
210 fd = pgwin32_open(fileName, openmode);
211 if (fd == -1)
212 return NULL;
213 return _fdopen(fd, mode);
216 #endif