Support: quest -f cjk_ngram
[xapian.git] / xapian-core / common / posixy_wrapper.cc
blob5a7181d3afdc935dc6b56f7c31f19a24432d79d4
1 /** @file posixy_wrapper.cc
2 * @brief Provides wrappers with POSIXy semantics.
3 */
4 /* Copyright (C) 2007 Lemur Consulting Ltd
5 * Copyright (C) 2007,2012 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 #ifdef __WIN32__ /* Ignore the whole file except for __WIN32__ */
26 #include "posixy_wrapper.h"
28 #include <io.h>
30 #include "safeerrno.h"
31 #include "safefcntl.h"
32 #include "safewindows.h"
34 /** Call GetLastError() and set errno appropriately. */
35 static int
36 set_errno_from_getlasterror()
38 int e;
39 unsigned long winerr = GetLastError();
40 switch (winerr) {
41 case ERROR_FILENAME_EXCED_RANGE:
42 case ERROR_FILE_NOT_FOUND:
43 case ERROR_PATH_NOT_FOUND:
44 case ERROR_INVALID_DRIVE:
45 case ERROR_NO_MORE_FILES:
46 case ERROR_BAD_NETPATH:
47 case ERROR_BAD_NET_NAME:
48 case ERROR_BAD_PATHNAME:
49 e = ENOENT;
50 break;
51 case ERROR_ARENA_TRASHED:
52 case ERROR_NOT_ENOUGH_MEMORY:
53 case ERROR_INVALID_BLOCK:
54 case ERROR_NOT_ENOUGH_QUOTA:
55 e = ENOMEM;
56 break;
57 case ERROR_LOCK_VIOLATION:
58 case ERROR_LOCK_FAILED:
59 case ERROR_SEEK_ON_DEVICE:
60 case ERROR_NETWORK_ACCESS_DENIED:
61 case ERROR_NOT_LOCKED:
62 case ERROR_ACCESS_DENIED:
63 case ERROR_CANNOT_MAKE:
64 case ERROR_FAIL_I24:
65 case ERROR_DRIVE_LOCKED:
66 case ERROR_CURRENT_DIRECTORY:
67 e = EACCES;
68 break;
69 case ERROR_INVALID_FUNCTION:
70 case ERROR_INVALID_ACCESS:
71 case ERROR_NEGATIVE_SEEK:
72 case ERROR_INVALID_DATA:
73 case ERROR_INVALID_PARAMETER:
74 e = EINVAL;
75 break;
76 case ERROR_NO_PROC_SLOTS:
77 case ERROR_NESTING_NOT_ALLOWED:
78 case ERROR_MAX_THRDS_REACHED:
79 e = EAGAIN;
80 break;
81 case ERROR_INVALID_HANDLE:
82 case ERROR_INVALID_TARGET_HANDLE:
83 case ERROR_DIRECT_ACCESS_HANDLE:
84 e = EBADF;
85 break;
86 case ERROR_ALREADY_EXISTS:
87 case ERROR_FILE_EXISTS:
88 e = EEXIST;
89 break;
90 case ERROR_BROKEN_PIPE:
91 e = EPIPE;
92 break;
93 case ERROR_DISK_FULL:
94 e = ENOSPC;
95 break;
96 case ERROR_TOO_MANY_OPEN_FILES:
97 e = EMFILE;
98 break;
99 case ERROR_WAIT_NO_CHILDREN:
100 case ERROR_CHILD_NOT_COMPLETE:
101 e = ECHILD;
102 break;
103 case ERROR_DIR_NOT_EMPTY:
104 e = ENOTEMPTY;
105 break;
106 case ERROR_BAD_ENVIRONMENT:
107 e = E2BIG;
108 break;
109 case ERROR_BAD_FORMAT:
110 e = ENOEXEC;
111 break;
112 case ERROR_NOT_SAME_DEVICE:
113 e = EXDEV;
114 break;
115 default:
116 if (winerr >= ERROR_WRITE_PROTECT && winerr <= ERROR_SHARING_BUFFER_EXCEEDED)
117 e = EACCES;
118 else if (winerr >= ERROR_INVALID_STARTING_CODESEG && winerr <= ERROR_INFLOOP_IN_RELOC_CHAIN)
119 e = ENOEXEC;
120 else
121 e = EINVAL;
122 break;
124 /* Some versions of Microsoft's C++ compiler earlier than 2005 do not have
125 * _set_errno(). */
126 #ifdef _set_errno
127 _set_errno(e);
128 #else
129 errno = e;
130 #endif
131 return -1;
135 posixy_unlink(const char * filename)
137 /* We must use DeleteFile as this can delete files that are open. */
138 if (DeleteFile(filename) != 0) {
139 return 0;
142 return set_errno_from_getlasterror();
146 posixy_open(const char *filename, int flags)
148 /* Translate POSIX read mode to Windows access mode */
149 DWORD dwDesiredAccess = GENERIC_READ;
150 switch (flags & (O_RDONLY | O_RDWR | O_WRONLY)) {
151 case O_RDONLY:
152 dwDesiredAccess = GENERIC_READ;
153 break;
154 case O_RDWR:
155 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
156 break;
157 case O_WRONLY:
158 dwDesiredAccess = GENERIC_WRITE;
159 break;
161 /* Subsequent operations may open this file to read, write or delete it */
162 DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
164 /* Translate POSIX creation mode to Windows creation mode */
165 DWORD dwCreationDisposition = OPEN_EXISTING;
166 switch (flags & (O_CREAT | O_TRUNC | O_EXCL)) {
167 case O_EXCL:
168 dwCreationDisposition = OPEN_EXISTING;
169 break;
171 case O_CREAT:
172 dwCreationDisposition = OPEN_ALWAYS;
173 break;
175 case O_CREAT | O_TRUNC:
176 dwCreationDisposition = CREATE_ALWAYS;
177 break;
179 case O_CREAT | O_EXCL:
180 case O_CREAT | O_TRUNC | O_EXCL:
181 dwCreationDisposition = CREATE_NEW;
182 break;
184 case O_TRUNC:
185 case O_TRUNC | O_EXCL:
186 dwCreationDisposition = TRUNCATE_EXISTING;
187 break;
190 HANDLE handleWin =
191 CreateFile(filename,
192 dwDesiredAccess,
193 dwShareMode,
194 NULL,
195 dwCreationDisposition,
196 FILE_ATTRIBUTE_NORMAL,
197 NULL);
198 if (handleWin == INVALID_HANDLE_VALUE) {
199 return set_errno_from_getlasterror();
202 /* Return a standard file descriptor. */
203 return _open_osfhandle((intptr_t)handleWin, flags|O_BINARY);
207 posixy_rename(const char *from, const char *to)
209 if (MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) != 0) {
210 return 0;
213 return set_errno_from_getlasterror();
216 #endif // __WIN32__