]> granicus.if.org Git - postgresql/blob - src/port/open.c
Update copyright for 2009.
[postgresql] / src / port / open.c
1 /*-------------------------------------------------------------------------
2  *
3  * open.c
4  *         Win32 open() replacement
5  *
6  *
7  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
8  *
9  * $PostgreSQL: pgsql/src/port/open.c,v 1.27 2009/01/01 17:24:04 momjian Exp $
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 seconds
99                  * before giving up.
100                  */
101                 DWORD err = GetLastError();
102                 if (err == ERROR_SHARING_VIOLATION || 
103                         err == ERROR_LOCK_VIOLATION)
104                 {
105                         pg_usleep(100000);
106                         loops++;
107
108 #ifndef FRONTEND
109                         if (loops == 50)
110                                 ereport(LOG,
111                                     (errmsg("could not open file \"%s\": %s", fileName, 
112                                           (err == ERROR_SHARING_VIOLATION)?_("sharing violation"):_("lock violation")),
113                                          errdetail("Continuing to retry for 30 seconds."),
114                                          errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
115 #endif
116
117                         if (loops < 300)
118                                 continue;
119                 }
120
121                 _dosmaperr(err);
122                 return -1;
123         }
124
125         /* _open_osfhandle will, on error, set errno accordingly */
126         if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0)
127                 CloseHandle(h);                 /* will not affect errno */
128         else if (fileFlags & (O_TEXT | O_BINARY) &&
129                          _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
130         {
131                 _close(fd);
132                 return -1;
133         }
134
135         return fd;
136 }
137
138 FILE *
139 pgwin32_fopen(const char *fileName, const char *mode)
140 {
141         int                     openmode = 0;
142         int                     fd;
143
144         if (strstr(mode, "r+"))
145                 openmode |= O_RDWR;
146         else if (strchr(mode, 'r'))
147                 openmode |= O_RDONLY;
148         if (strstr(mode, "w+"))
149                 openmode |= O_RDWR | O_CREAT | O_TRUNC;
150         else if (strchr(mode, 'w'))
151                 openmode |= O_WRONLY | O_CREAT | O_TRUNC;
152         if (strchr(mode, 'a'))
153                 openmode |= O_WRONLY | O_CREAT | O_APPEND;
154
155         if (strchr(mode, 'b'))
156                 openmode |= O_BINARY;
157         if (strchr(mode, 't'))
158                 openmode |= O_TEXT;
159
160         fd = pgwin32_open(fileName, openmode);
161         if (fd == -1)
162                 return NULL;
163         return _fdopen(fd, mode);
164 }
165
166 #endif