Add config option `windows.appendAtomically`

Atomic append on windows is only supported on local disk files, and it may
cause errors in other situations, e.g. network file system. If that is the
case, this config option should be used to turn atomic append off.

Co-Authored-By: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: 孙卓识 <sunzhuoshi@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
孙卓识 2022-01-16 03:38:33 +08:00 коммит произвёл Matthew John Cheetham
Родитель 4edc6a9300
Коммит 38c82cba8a
3 изменённых файлов: 37 добавлений и 2 удалений

Просмотреть файл

@ -543,4 +543,6 @@ include::config/versionsort.txt[]
include::config/web.txt[]
include::config/windows.txt[]
include::config/worktree.txt[]

Просмотреть файл

@ -0,0 +1,4 @@
windows.appendAtomically::
By default, append atomic API is used on windows. But it works only with
local disk files, if you're working on a network file system, you should
set it false to turn it off.

Просмотреть файл

@ -19,6 +19,7 @@
#include "gettext.h"
#define SECURITY_WIN32
#include <sspi.h>
#include "../repository.h"
#define HCAST(type, handle) ((type)(intptr_t)handle)
@ -545,6 +546,7 @@ static int is_local_named_pipe_path(const char *filename)
int mingw_open (const char *filename, int oflags, ...)
{
static int append_atomically = -1;
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
va_list args;
unsigned mode;
@ -561,7 +563,16 @@ int mingw_open (const char *filename, int oflags, ...)
return -1;
}
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
/*
* Only set append_atomically to default value(1) when repo is initialized
* and fail to get config value
*/
if (append_atomically < 0 && the_repository && the_repository->commondir &&
git_config_get_bool("windows.appendatomically", &append_atomically))
append_atomically = 1;
if (append_atomically && (oflags & O_APPEND) &&
!is_local_named_pipe_path(filename))
open_fn = mingw_open_append;
else
open_fn = _wopen;
@ -710,9 +721,27 @@ ssize_t mingw_write(int fd, const void *buf, size_t len)
HANDLE h = (HANDLE) _get_osfhandle(fd);
if (GetFileType(h) == FILE_TYPE_PIPE)
errno = EPIPE;
else
else {
wchar_t path[MAX_LONG_PATH];
DWORD ret = GetFinalPathNameByHandleW(h, path,
ARRAY_SIZE(path), 0);
UINT drive_type = ret > 0 && ret < ARRAY_SIZE(path) ?
GetDriveTypeW(path) : DRIVE_UNKNOWN;
/*
* The default atomic append causes such an error on
* network file systems, in such a case, it should be
* turned off via config.
*
* `drive_type` of UNC path: DRIVE_NO_ROOT_DIR
*/
if (DRIVE_NO_ROOT_DIR == drive_type || DRIVE_REMOTE == drive_type)
warning("invalid write operation detected; you may try:\n"
"\n\tgit config windows.appendAtomically false");
errno = EINVAL;
}
}
return result;
}