Merge branch 'js/mingw-o-append'
Among the three codepaths we use O_APPEND to open a file for appending, one used for writing GIT_TRACE output requires O_APPEND implementation that behaves sensibly when multiple processes are writing to the same file. POSIX emulation used in the Windows port has been updated to improve in this area. * js/mingw-o-append: mingw: enable atomic O_APPEND
This commit is contained in:
@ -341,12 +341,44 @@ int mingw_mkdir(const char *path, int mode)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
int fd;
|
||||||
|
DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
|
||||||
|
|
||||||
|
/* only these flags are supported */
|
||||||
|
if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND))
|
||||||
|
return errno = ENOSYS, -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FILE_SHARE_WRITE is required to permit child processes
|
||||||
|
* to append to the file.
|
||||||
|
*/
|
||||||
|
handle = CreateFileW(wfilename, FILE_APPEND_DATA,
|
||||||
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||||||
|
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return errno = err_win_to_posix(GetLastError()), -1;
|
||||||
|
/*
|
||||||
|
* No O_APPEND here, because the CRT uses it only to reset the
|
||||||
|
* file pointer to EOF on write(); but that is not necessary
|
||||||
|
* for a file created with FILE_APPEND_DATA.
|
||||||
|
*/
|
||||||
|
fd = _open_osfhandle((intptr_t)handle, O_BINARY);
|
||||||
|
if (fd < 0)
|
||||||
|
CloseHandle(handle);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
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, ...);
|
||||||
va_list args;
|
va_list args;
|
||||||
unsigned mode;
|
unsigned mode;
|
||||||
int fd;
|
int fd;
|
||||||
wchar_t wfilename[MAX_PATH];
|
wchar_t wfilename[MAX_PATH];
|
||||||
|
open_fn_t open_fn;
|
||||||
|
|
||||||
va_start(args, oflags);
|
va_start(args, oflags);
|
||||||
mode = va_arg(args, int);
|
mode = va_arg(args, int);
|
||||||
@ -355,9 +387,14 @@ 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)
|
||||||
|
open_fn = mingw_open_append;
|
||||||
|
else
|
||||||
|
open_fn = _wopen;
|
||||||
|
|
||||||
if (xutftowcs_path(wfilename, filename) < 0)
|
if (xutftowcs_path(wfilename, filename) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
fd = _wopen(wfilename, oflags, mode);
|
fd = open_fn(wfilename, oflags, mode);
|
||||||
|
|
||||||
if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
|
if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
|
||||||
DWORD attrs = GetFileAttributesW(wfilename);
|
DWORD attrs = GetFileAttributesW(wfilename);
|
||||||
@ -375,7 +412,7 @@ int mingw_open (const char *filename, int oflags, ...)
|
|||||||
* CREATE_ALWAYS flag of CreateFile()).
|
* CREATE_ALWAYS flag of CreateFile()).
|
||||||
*/
|
*/
|
||||||
if (fd < 0 && errno == EACCES)
|
if (fd < 0 && errno == EACCES)
|
||||||
fd = _wopen(wfilename, oflags & ~O_CREAT, mode);
|
fd = open_fn(wfilename, oflags & ~O_CREAT, mode);
|
||||||
if (fd >= 0 && set_hidden_flag(wfilename, 1))
|
if (fd >= 0 && set_hidden_flag(wfilename, 1))
|
||||||
warning("could not mark '%s' as hidden.", filename);
|
warning("could not mark '%s' as hidden.", filename);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user