Update for 1.4.18
[xapian.git] / xapian-core / common / posixy_wrapper.cc
bloba11bb73c49e357fb19a00a137f9a3333a4bf0cd2
1 /** @file
2 * @brief Provides wrappers with POSIXy semantics.
3 */
4 /* Copyright (C) 2007 Lemur Consulting Ltd
5 * Copyright (C) 2007,2012,2018 Olly Betts
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.
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.
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
22 #include <config.h>
24 #include <cerrno>
26 #ifdef __CYGWIN__
27 # include "posixy_wrapper.h"
29 # include "filetests.h"
31 int
32 posixy_unlink(const char * filename)
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;
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;
51 errno = unlink_errno;
53 return r;
56 #elif defined __WIN32__
58 #include "posixy_wrapper.h"
60 #include <io.h>
62 #include "safefcntl.h"
63 #include "safewindows.h"
65 /** Call GetLastError() and set errno appropriately. */
66 static int
67 set_errno_from_getlasterror()
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;
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;
166 posixy_unlink(const char * filename)
168 /* We must use DeleteFile as this can delete files that are open. */
169 if (DeleteFile(filename) != 0) {
170 return 0;
173 return set_errno_from_getlasterror();
177 posixy_open(const char *filename, int flags)
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;
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;
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;
202 case O_CREAT:
203 dwCreationDisposition = OPEN_ALWAYS;
204 break;
206 case O_CREAT | O_TRUNC:
207 dwCreationDisposition = CREATE_ALWAYS;
208 break;
210 case O_CREAT | O_EXCL:
211 case O_CREAT | O_TRUNC | O_EXCL:
212 dwCreationDisposition = CREATE_NEW;
213 break;
215 case O_TRUNC:
216 case O_TRUNC | O_EXCL:
217 dwCreationDisposition = TRUNCATE_EXISTING;
218 break;
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();
233 /* Return a standard file descriptor. */
234 return _open_osfhandle(intptr_t(handleWin), flags|O_BINARY);
238 posixy_rename(const char *from, const char *to)
240 if (MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) != 0) {
241 return 0;
244 return set_errno_from_getlasterror();
247 #endif // __WIN32__