]> granicus.if.org Git - postgresql/blob - src/port/open.c
Better document win32_open and its ability to allow concurrent
[postgresql] / src / port / open.c
1 /*-------------------------------------------------------------------------
2  *
3  * open.c
4  *         Win32 open() replacement
5  *
6  *
7  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
8  *
9  * $PostgreSQL: pgsql/src/port/open.c,v 1.5 2004/10/17 23:53:30 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #ifdef WIN32
15
16 #include <windows.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 #include <assert.h>
20
21 static int
22 openFlagsToCreateFileFlags(int openFlags)
23 {
24         switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
25         {
26                 case 0:
27                 case O_EXCL:
28                         return OPEN_EXISTING;
29
30                 case O_CREAT:
31                         return OPEN_ALWAYS;
32
33                 case O_TRUNC:
34                 case O_TRUNC | O_EXCL:
35                         return TRUNCATE_EXISTING;
36
37                 case O_CREAT | O_TRUNC:
38                         return CREATE_ALWAYS;
39
40                 case O_CREAT | O_EXCL:
41                 case O_CREAT | O_TRUNC | O_EXCL:
42                         return CREATE_NEW;
43         }
44
45         /* will never get here */
46         return 0;
47 }
48
49 /*
50  *       - file attribute setting, based on fileMode?
51  *       - handle other flags? (eg FILE_FLAG_NO_BUFFERING/FILE_FLAG_WRITE_THROUGH)
52  */
53 int
54 win32_open(const char *fileName, int fileFlags,...)
55 {
56         int                     fd;
57         HANDLE          h;
58         SECURITY_ATTRIBUTES sa;
59
60         /* Check that we can handle the request */
61         assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
62                                                  (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
63                                                  _O_SHORT_LIVED |
64           (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
65
66         sa.nLength = sizeof(sa);
67         sa.bInheritHandle = TRUE;
68         sa.lpSecurityDescriptor = NULL;
69
70         if ((h = CreateFile(fileName,
71         /* cannot use O_RDONLY, as it == 0 */
72                                   (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
73                                  ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
74                                 /* These flags allow concurrent rename/unlink */
75                                 (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
76                                                 &sa,
77                                                 openFlagsToCreateFileFlags(fileFlags),
78                                                 FILE_ATTRIBUTE_NORMAL |
79                                  ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
80                    ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
81                   ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
82                          ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0),
83                                                 NULL)) == INVALID_HANDLE_VALUE)
84         {
85                 switch (GetLastError())
86                 {
87                                 /* EMFILE, ENFILE should not occur from CreateFile. */
88                         case ERROR_PATH_NOT_FOUND:
89                         case ERROR_FILE_NOT_FOUND:
90                                 errno = ENOENT;
91                                 break;
92                         case ERROR_FILE_EXISTS:
93                                 errno = EEXIST;
94                                 break;
95                         case ERROR_ACCESS_DENIED:
96                                 errno = EACCES;
97                                 break;
98                         default:
99                                 errno = EINVAL;
100                 }
101                 return -1;
102         }
103
104         /* _open_osfhandle will, on error, set errno accordingly */
105         if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0 ||
106                 (fileFlags & (O_TEXT | O_BINARY) && (_setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)))
107                 CloseHandle(h);                 /* will not affect errno */
108         return fd;
109 }
110
111 #endif