|
|
@ -341,6 +341,19 @@ int mingw_mkdir(const char *path, int mode) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* Calling CreateFile() using FILE_APPEND_DATA and without FILE_WRITE_DATA |
|
|
|
|
|
|
|
* is documented in [1] as opening a writable file handle in append mode. |
|
|
|
|
|
|
|
* (It is believed that) this is atomic since it is maintained by the |
|
|
|
|
|
|
|
* kernel unlike the O_APPEND flag which is racily maintained by the CRT. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* [1] https://docs.microsoft.com/en-us/windows/desktop/fileio/file-access-rights-constants |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* This trick does not appear to work for named pipes. Instead it creates |
|
|
|
|
|
|
|
* a named pipe client handle that cannot be written to. Callers should |
|
|
|
|
|
|
|
* just use the regular _wopen() for them. (And since client handle gets |
|
|
|
|
|
|
|
* bound to a unique server handle, it isn't really an issue.) |
|
|
|
|
|
|
|
*/ |
|
|
|
static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) |
|
|
|
static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) |
|
|
|
{ |
|
|
|
{ |
|
|
|
HANDLE handle; |
|
|
|
HANDLE handle; |
|
|
@ -360,10 +373,12 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) |
|
|
|
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); |
|
|
|
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); |
|
|
|
if (handle == INVALID_HANDLE_VALUE) |
|
|
|
if (handle == INVALID_HANDLE_VALUE) |
|
|
|
return errno = err_win_to_posix(GetLastError()), -1; |
|
|
|
return errno = err_win_to_posix(GetLastError()), -1; |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
/* |
|
|
|
* No O_APPEND here, because the CRT uses it only to reset the |
|
|
|
* No O_APPEND here, because the CRT uses it only to reset the |
|
|
|
* file pointer to EOF on write(); but that is not necessary |
|
|
|
* file pointer to EOF before each write(); but that is not |
|
|
|
* for a file created with FILE_APPEND_DATA. |
|
|
|
* necessary (and may lead to races) for a file created with |
|
|
|
|
|
|
|
* FILE_APPEND_DATA. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
fd = _open_osfhandle((intptr_t)handle, O_BINARY); |
|
|
|
fd = _open_osfhandle((intptr_t)handle, O_BINARY); |
|
|
|
if (fd < 0) |
|
|
|
if (fd < 0) |
|
|
@ -371,6 +386,21 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) |
|
|
|
return fd; |
|
|
|
return fd; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
* Does the pathname map to the local named pipe filesystem? |
|
|
|
|
|
|
|
* That is, does it have a "//./pipe/" prefix? |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
static int is_local_named_pipe_path(const char *filename) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return (is_dir_sep(filename[0]) && |
|
|
|
|
|
|
|
is_dir_sep(filename[1]) && |
|
|
|
|
|
|
|
filename[2] == '.' && |
|
|
|
|
|
|
|
is_dir_sep(filename[3]) && |
|
|
|
|
|
|
|
!strncasecmp(filename+4, "pipe", 4) && |
|
|
|
|
|
|
|
is_dir_sep(filename[8]) && |
|
|
|
|
|
|
|
filename[9]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int mingw_open (const char *filename, int oflags, ...) |
|
|
|
int mingw_open (const char *filename, int oflags, ...) |
|
|
|
{ |
|
|
|
{ |
|
|
|
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...); |
|
|
|
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...); |
|
|
@ -387,7 +417,7 @@ int mingw_open (const char *filename, int oflags, ...) |
|
|
|
if (filename && !strcmp(filename, "/dev/null")) |
|
|
|
if (filename && !strcmp(filename, "/dev/null")) |
|
|
|
filename = "nul"; |
|
|
|
filename = "nul"; |
|
|
|
|
|
|
|
|
|
|
|
if (oflags & O_APPEND) |
|
|
|
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename)) |
|
|
|
open_fn = mingw_open_append; |
|
|
|
open_fn = mingw_open_append; |
|
|
|
else |
|
|
|
else |
|
|
|
open_fn = _wopen; |
|
|
|
open_fn = _wopen; |
|
|
|