xapian-core  1.4.27
posixy_wrapper.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2007 Lemur Consulting Ltd
5  * Copyright (C) 2007,2012,2018 Olly Betts
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <config.h>
23 
24 #include <cerrno>
25 
26 #ifdef __CYGWIN__
27 # include "posixy_wrapper.h"
28 
29 # include "filetests.h"
30 
31 int
32 posixy_unlink(const char * filename)
33 {
34  // On Cygwin we seem to inexplicably get ECHILD from unlink() sometimes.
35  // The path doesn't actually exists after the call when we get ECHILD, but
36  // the correct return value depends on whether it existed before so we
37  // need to check here as well.
38  if (!path_exists(filename)) {
39  errno = ENOENT;
40  return -1;
41  }
42 
43  int r = unlink(filename);
44  if (r < 0) {
45  int unlink_errno = errno;
46  if (unlink_errno == ECHILD && !path_exists(filename)) {
47  errno = 0;
48  return 0;
49  }
50 
51  errno = unlink_errno;
52  }
53  return r;
54 }
55 
56 #elif defined __WIN32__
57 
58 #include "posixy_wrapper.h"
59 
60 #include <io.h>
61 
62 #include "safefcntl.h"
63 #include "safewindows.h"
64 
66 static int
67 set_errno_from_getlasterror()
68 {
69  int e;
70  unsigned long winerr = GetLastError();
71  switch (winerr) {
72  case ERROR_FILENAME_EXCED_RANGE:
73  case ERROR_FILE_NOT_FOUND:
74  case ERROR_PATH_NOT_FOUND:
75  case ERROR_INVALID_DRIVE:
76  case ERROR_NO_MORE_FILES:
77  case ERROR_BAD_NETPATH:
78  case ERROR_BAD_NET_NAME:
79  case ERROR_BAD_PATHNAME:
80  e = ENOENT;
81  break;
82  case ERROR_ARENA_TRASHED:
83  case ERROR_NOT_ENOUGH_MEMORY:
84  case ERROR_INVALID_BLOCK:
85  case ERROR_NOT_ENOUGH_QUOTA:
86  e = ENOMEM;
87  break;
88  case ERROR_LOCK_VIOLATION:
89  case ERROR_LOCK_FAILED:
90  case ERROR_SEEK_ON_DEVICE:
91  case ERROR_NETWORK_ACCESS_DENIED:
92  case ERROR_NOT_LOCKED:
93  case ERROR_ACCESS_DENIED:
94  case ERROR_CANNOT_MAKE:
95  case ERROR_FAIL_I24:
96  case ERROR_DRIVE_LOCKED:
97  case ERROR_CURRENT_DIRECTORY:
98  e = EACCES;
99  break;
100  case ERROR_INVALID_FUNCTION:
101  case ERROR_INVALID_ACCESS:
102  case ERROR_NEGATIVE_SEEK:
103  case ERROR_INVALID_DATA:
104  case ERROR_INVALID_PARAMETER:
105  e = EINVAL;
106  break;
107  case ERROR_NO_PROC_SLOTS:
108  case ERROR_NESTING_NOT_ALLOWED:
109  case ERROR_MAX_THRDS_REACHED:
110  e = EAGAIN;
111  break;
112  case ERROR_INVALID_HANDLE:
113  case ERROR_INVALID_TARGET_HANDLE:
114  case ERROR_DIRECT_ACCESS_HANDLE:
115  e = EBADF;
116  break;
117  case ERROR_ALREADY_EXISTS:
118  case ERROR_FILE_EXISTS:
119  e = EEXIST;
120  break;
121  case ERROR_BROKEN_PIPE:
122  e = EPIPE;
123  break;
124  case ERROR_DISK_FULL:
125  e = ENOSPC;
126  break;
127  case ERROR_TOO_MANY_OPEN_FILES:
128  e = EMFILE;
129  break;
130  case ERROR_WAIT_NO_CHILDREN:
131  case ERROR_CHILD_NOT_COMPLETE:
132  e = ECHILD;
133  break;
134  case ERROR_DIR_NOT_EMPTY:
135  e = ENOTEMPTY;
136  break;
137  case ERROR_BAD_ENVIRONMENT:
138  e = E2BIG;
139  break;
140  case ERROR_BAD_FORMAT:
141  e = ENOEXEC;
142  break;
143  case ERROR_NOT_SAME_DEVICE:
144  e = EXDEV;
145  break;
146  default:
147  if (winerr >= ERROR_WRITE_PROTECT && winerr <= ERROR_SHARING_BUFFER_EXCEEDED)
148  e = EACCES;
149  else if (winerr >= ERROR_INVALID_STARTING_CODESEG && winerr <= ERROR_INFLOOP_IN_RELOC_CHAIN)
150  e = ENOEXEC;
151  else
152  e = EINVAL;
153  break;
154  }
155  /* Some versions of Microsoft's C++ compiler earlier than 2005 do not have
156  * _set_errno(). */
157 #ifdef _set_errno
158  _set_errno(e);
159 #else
160  errno = e;
161 #endif
162  return -1;
163 }
164 
165 int
166 posixy_unlink(const char * filename)
167 {
168  /* We must use DeleteFile as this can delete files that are open. */
169  if (DeleteFile(filename) != 0) {
170  return 0;
171  }
172 
173  return set_errno_from_getlasterror();
174 }
175 
176 int
177 posixy_open(const char *filename, int flags)
178 {
179  /* Translate POSIX read mode to Windows access mode */
180  DWORD dwDesiredAccess = GENERIC_READ;
181  switch (flags & (O_RDONLY | O_RDWR | O_WRONLY)) {
182  case O_RDONLY:
183  dwDesiredAccess = GENERIC_READ;
184  break;
185  case O_RDWR:
186  dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
187  break;
188  case O_WRONLY:
189  dwDesiredAccess = GENERIC_WRITE;
190  break;
191  }
192  /* Subsequent operations may open this file to read, write or delete it */
193  DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
194 
195  /* Translate POSIX creation mode to Windows creation mode */
196  DWORD dwCreationDisposition = OPEN_EXISTING;
197  switch (flags & (O_CREAT | O_TRUNC | O_EXCL)) {
198  case O_EXCL:
199  dwCreationDisposition = OPEN_EXISTING;
200  break;
201 
202  case O_CREAT:
203  dwCreationDisposition = OPEN_ALWAYS;
204  break;
205 
206  case O_CREAT | O_TRUNC:
207  dwCreationDisposition = CREATE_ALWAYS;
208  break;
209 
210  case O_CREAT | O_EXCL:
211  case O_CREAT | O_TRUNC | O_EXCL:
212  dwCreationDisposition = CREATE_NEW;
213  break;
214 
215  case O_TRUNC:
216  case O_TRUNC | O_EXCL:
217  dwCreationDisposition = TRUNCATE_EXISTING;
218  break;
219  }
220 
221  HANDLE handleWin =
222  CreateFile(filename,
223  dwDesiredAccess,
224  dwShareMode,
225  NULL,
226  dwCreationDisposition,
227  FILE_ATTRIBUTE_NORMAL,
228  NULL);
229  if (handleWin == INVALID_HANDLE_VALUE) {
230  return set_errno_from_getlasterror();
231  }
232 
233  /* Return a standard file descriptor. */
234  return _open_osfhandle(intptr_t(handleWin), flags|O_BINARY);
235 }
236 
237 int
238 posixy_rename(const char *from, const char *to)
239 {
240  if (MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) != 0) {
241  return 0;
242  }
243 
244  return set_errno_from_getlasterror();
245 }
246 
247 #endif // __WIN32__
Provides wrappers with POSIXy semantics.
#define posixy_rename(F, T)
#define O_BINARY
Definition: safefcntl.h:81
Utility functions for testing files.
#define posixy_unlink(F)
include <windows.h> without all the bloat and damage.
#define posixy_open
bool path_exists(const char *path)
Test if a path exists.
Definition: filetests.h:158
include <fcntl.h>, but working around broken platforms.