2 * @brief Provides wrappers with POSIXy semantics.
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
27 # include "posixy_wrapper.h"
29 # include "filetests.h"
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
)) {
43 int r
= unlink(filename
);
45 int unlink_errno
= errno
;
46 if (unlink_errno
== ECHILD
&& !path_exists(filename
)) {
56 #elif defined __WIN32__
58 #include "posixy_wrapper.h"
62 #include "safefcntl.h"
63 #include "safewindows.h"
65 /** Call GetLastError() and set errno appropriately. */
67 set_errno_from_getlasterror()
70 unsigned long winerr
= GetLastError();
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
:
82 case ERROR_ARENA_TRASHED
:
83 case ERROR_NOT_ENOUGH_MEMORY
:
84 case ERROR_INVALID_BLOCK
:
85 case ERROR_NOT_ENOUGH_QUOTA
:
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
:
96 case ERROR_DRIVE_LOCKED
:
97 case ERROR_CURRENT_DIRECTORY
:
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
:
107 case ERROR_NO_PROC_SLOTS
:
108 case ERROR_NESTING_NOT_ALLOWED
:
109 case ERROR_MAX_THRDS_REACHED
:
112 case ERROR_INVALID_HANDLE
:
113 case ERROR_INVALID_TARGET_HANDLE
:
114 case ERROR_DIRECT_ACCESS_HANDLE
:
117 case ERROR_ALREADY_EXISTS
:
118 case ERROR_FILE_EXISTS
:
121 case ERROR_BROKEN_PIPE
:
124 case ERROR_DISK_FULL
:
127 case ERROR_TOO_MANY_OPEN_FILES
:
130 case ERROR_WAIT_NO_CHILDREN
:
131 case ERROR_CHILD_NOT_COMPLETE
:
134 case ERROR_DIR_NOT_EMPTY
:
137 case ERROR_BAD_ENVIRONMENT
:
140 case ERROR_BAD_FORMAT
:
143 case ERROR_NOT_SAME_DEVICE
:
147 if (winerr
>= ERROR_WRITE_PROTECT
&& winerr
<= ERROR_SHARING_BUFFER_EXCEEDED
)
149 else if (winerr
>= ERROR_INVALID_STARTING_CODESEG
&& winerr
<= ERROR_INFLOOP_IN_RELOC_CHAIN
)
155 /* Some versions of Microsoft's C++ compiler earlier than 2005 do not have
166 posixy_unlink(const char * filename
)
168 /* We must use DeleteFile as this can delete files that are open. */
169 if (DeleteFile(filename
) != 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
)) {
183 dwDesiredAccess
= GENERIC_READ
;
186 dwDesiredAccess
= GENERIC_READ
| GENERIC_WRITE
;
189 dwDesiredAccess
= GENERIC_WRITE
;
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
)) {
199 dwCreationDisposition
= OPEN_EXISTING
;
203 dwCreationDisposition
= OPEN_ALWAYS
;
206 case O_CREAT
| O_TRUNC
:
207 dwCreationDisposition
= CREATE_ALWAYS
;
210 case O_CREAT
| O_EXCL
:
211 case O_CREAT
| O_TRUNC
| O_EXCL
:
212 dwCreationDisposition
= CREATE_NEW
;
216 case O_TRUNC
| O_EXCL
:
217 dwCreationDisposition
= TRUNCATE_EXISTING
;
226 dwCreationDisposition
,
227 FILE_ATTRIBUTE_NORMAL
,
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) {
244 return set_errno_from_getlasterror();