]> granicus.if.org Git - postgresql/blob - src/port/open.c
Add comment to explain why O_EXCL and O_TRUNC can be ignored in
[postgresql] / src / port / open.c
1 /*-------------------------------------------------------------------------
2  *
3  * open.c
4  *         Win32 open() replacement
5  *
6  *
7  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
8  *
9  * $PostgreSQL: pgsql/src/port/open.c,v 1.19 2007/02/13 02:06:22 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #ifdef WIN32
15
16 #include "c.h"
17
18 #include <windows.h>
19 #include <fcntl.h>
20 #include <assert.h>
21
22
23 static int
24 openFlagsToCreateFileFlags(int openFlags)
25 {
26         switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
27         {
28                 /* O_EXCL is meaningless without O_CREAT */
29                 case 0:
30                 case O_EXCL:
31                         return OPEN_EXISTING;
32
33                 case O_CREAT:
34                         return OPEN_ALWAYS;
35
36                 /* O_EXCL is meaningless without O_CREAT */
37                 case O_TRUNC:
38                 case O_TRUNC | O_EXCL:
39                         return TRUNCATE_EXISTING;
40
41                 case O_CREAT | O_TRUNC:
42                         return CREATE_ALWAYS;
43
44                 /* O_TRUNC is meaningless with O_CREAT */
45                 case O_CREAT | O_EXCL:
46                 case O_CREAT | O_TRUNC | O_EXCL:
47                         return CREATE_NEW;
48         }
49
50         /* will never get here */
51         return 0;
52 }
53
54 /*
55  *       - file attribute setting, based on fileMode?
56  *       - handle other flags? (eg FILE_FLAG_NO_BUFFERING/FILE_FLAG_WRITE_THROUGH)
57  */
58 int
59 pgwin32_open(const char *fileName, int fileFlags,...)
60 {
61         int                     fd;
62         HANDLE          h;
63         SECURITY_ATTRIBUTES sa;
64
65         /* Check that we can handle the request */
66         assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
67                                                  (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
68                                                  _O_SHORT_LIVED | O_DSYNC |
69                   (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
70
71         sa.nLength = sizeof(sa);
72         sa.bInheritHandle = TRUE;
73         sa.lpSecurityDescriptor = NULL;
74
75         if ((h = CreateFile(fileName,
76         /* cannot use O_RDONLY, as it == 0 */
77                                           (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
78                                          ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
79         /* These flags allow concurrent rename/unlink */
80                                         (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
81                                                 &sa,
82                                                 openFlagsToCreateFileFlags(fileFlags),
83                                                 FILE_ATTRIBUTE_NORMAL |
84                                          ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
85                            ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
86                           ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
87                                 ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
88                                                 ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
89                                                 NULL)) == INVALID_HANDLE_VALUE)
90         {
91                 switch (GetLastError())
92                 {
93                                 /* EMFILE, ENFILE should not occur from CreateFile. */
94                         case ERROR_PATH_NOT_FOUND:
95                         case ERROR_FILE_NOT_FOUND:
96                                 errno = ENOENT;
97                                 break;
98                         case ERROR_FILE_EXISTS:
99                                 errno = EEXIST;
100                                 break;
101                         case ERROR_ACCESS_DENIED:
102                                 errno = EACCES;
103                                 break;
104                         default:
105                                 errno = EINVAL;
106                 }
107                 return -1;
108         }
109
110         /* _open_osfhandle will, on error, set errno accordingly */
111         if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0)
112                 CloseHandle(h);                 /* will not affect errno */
113         else if (fileFlags & (O_TEXT | O_BINARY) &&
114                          _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
115         {
116                 _close(fd);
117                 return -1;
118         }
119
120         return fd;
121 }
122
123 FILE *
124 pgwin32_fopen(const char *fileName, const char *mode)
125 {
126         int                     openmode = 0;
127         int                     fd;
128
129         if (strstr(mode, "r+"))
130                 openmode |= O_RDWR;
131         else if (strchr(mode, 'r'))
132                 openmode |= O_RDONLY;
133         if (strstr(mode, "w+"))
134                 openmode |= O_RDWR | O_CREAT | O_TRUNC;
135         else if (strchr(mode, 'w'))
136                 openmode |= O_WRONLY | O_CREAT | O_TRUNC;
137         if (strchr(mode, 'a'))
138                 openmode |= O_WRONLY | O_CREAT | O_APPEND;
139
140         if (strchr(mode, 'b'))
141                 openmode |= O_BINARY;
142         if (strchr(mode, 't'))
143                 openmode |= O_TEXT;
144
145         fd = pgwin32_open(fileName, openmode);
146         if (fd == -1)
147                 return NULL;
148         return _fdopen(fd, mode);
149 }
150
151 #endif