summaryrefslogtreecommitdiff
path: root/src/port/open.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2004-03-24 03:54:16 +0000
committerBruce Momjian <bruce@momjian.us>2004-03-24 03:54:16 +0000
commitb8fd6756e28a27224c90d3e82ce9dc93af5951c2 (patch)
tree12bd13779d0f476cfab62d678a821b20a069cf9f /src/port/open.c
parentd6bc5944a06a322a36800cedd46f0bb4922a6332 (diff)
Allow unlink/rename of files open by another process on Win32, using a
special Win32 open flag FILE_SHARE_DELETE. Claudio Natoli
Diffstat (limited to 'src/port/open.c')
-rw-r--r--src/port/open.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/port/open.c b/src/port/open.c
new file mode 100644
index 00000000000..ccd2a15b1de
--- /dev/null
+++ b/src/port/open.c
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * open.c
+ * Win32 open() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ *
+ * $PostgreSQL: pgsql/src/port/open.c,v 1.1 2004/03/24 03:54:16 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#include <windows.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+
+int openFlagsToCreateFileFlags(int openFlags)
+{
+ switch (openFlags & (O_CREAT|O_TRUNC|O_EXCL))
+ {
+ case 0:
+ case O_EXCL: return OPEN_EXISTING;
+
+ case O_CREAT: return OPEN_ALWAYS;
+
+ case O_TRUNC:
+ case O_TRUNC|O_EXCL: return TRUNCATE_EXISTING;
+
+ case O_CREAT|O_TRUNC: return CREATE_ALWAYS;
+
+ case O_CREAT|O_EXCL:
+ case O_CREAT|O_TRUNC|O_EXCL: return CREATE_NEW;
+ }
+
+ /* will never get here */
+ return 0;
+}
+
+/*
+ * - file attribute setting, based on fileMode?
+ * - handle other flags? (eg FILE_FLAG_NO_BUFFERING/FILE_FLAG_WRITE_THROUGH)
+ */
+int win32_open(const char* fileName, int fileFlags, ...)
+{
+ int fd;
+ HANDLE h;
+ SECURITY_ATTRIBUTES sa;
+
+ /* Check that we can handle the request */
+ assert((fileFlags & ((O_RDONLY|O_WRONLY|O_RDWR) | O_APPEND |
+ (O_RANDOM|O_SEQUENTIAL|O_TEMPORARY) |
+ _O_SHORT_LIVED |
+ (O_CREAT|O_TRUNC|O_EXCL) | (O_TEXT|O_BINARY))) == fileFlags);
+
+ sa.nLength=sizeof(sa);
+ sa.bInheritHandle=TRUE;
+ sa.lpSecurityDescriptor=NULL;
+
+ if ((h = CreateFile(fileName,
+ /* cannot use O_RDONLY, as it == 0 */
+ (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
+ ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
+ (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE),
+ &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),
+ NULL)) == INVALID_HANDLE_VALUE)
+ {
+ switch (GetLastError())
+ {
+ /* 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;
+ }
+ return -1;
+ }
+
+ /* _open_osfhandle will, on error, set errno accordingly */
+ if ((fd = _open_osfhandle((long)h,fileFlags&O_APPEND)) < 0 ||
+ (fileFlags&(O_TEXT|O_BINARY) && (_setmode(fd,fileFlags&(O_TEXT|O_BINARY)) < 0)))
+ CloseHandle(h); /* will not affect errno */
+ return fd;
+}
+
+#endif