Skip to content

Commit a2e6991

Browse files
committed
fixup! mingw: lstat: compute correct size for symlinks
Proposed fixup for git-for-windows#2637 Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 698f46c commit a2e6991

File tree

1 file changed

+19
-41
lines changed

1 file changed

+19
-41
lines changed

compat/mingw.c

+19-41
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,8 @@ static int has_valid_directory_prefix(wchar_t *wfilename)
969969
return 1;
970970
}
971971

972-
static int get_reparse_point_link_len(const WCHAR *wpath, DWORD *ptag);
972+
static int readlink_1(const WCHAR *wpath, char *tmpbuf, int *plen, DWORD *ptag);
973+
973974
int mingw_lstat(const char *file_name, struct stat *buf)
974975
{
975976
WIN32_FILE_ATTRIBUTE_DATA fdata;
@@ -989,10 +990,12 @@ int mingw_lstat(const char *file_name, struct stat *buf)
989990
}
990991

991992
if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
992-
/* for reparse points, use get_reparse_point_link_len to get the link tag and length */
993+
/* for reparse points, get the link tag and length */
993994
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
994-
link_len = get_reparse_point_link_len(wfilename, &reparse_tag);
995-
if (link_len < 0)
995+
char tmpbuf[MAX_LONG_PATH];
996+
997+
if (readlink_1(wfilename, tmpbuf, &link_len,
998+
&reparse_tag) < 0)
996999
return -1;
9971000
}
9981001
buf->st_ino = 0;
@@ -2969,10 +2972,11 @@ typedef struct _REPARSE_DATA_BUFFER {
29692972
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
29702973
#endif
29712974

2972-
static int get_reparse_point(const WCHAR *wpath, REPARSE_DATA_BUFFER *b, size_t siz, WCHAR **pwbuf)
2975+
static int readlink_1(const WCHAR *wpath, char *tmpbuf, int *plen, DWORD *ptag)
29732976
{
29742977
HANDLE handle;
29752978
WCHAR *wbuf;
2979+
REPARSE_DATA_BUFFER *b = alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
29762980
DWORD dummy;
29772981

29782982
/* read reparse point data */
@@ -2985,15 +2989,15 @@ static int get_reparse_point(const WCHAR *wpath, REPARSE_DATA_BUFFER *b, size_t
29852989
return -1;
29862990
}
29872991
if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, b,
2988-
siz, &dummy, NULL)) {
2992+
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dummy, NULL)) {
29892993
errno = err_win_to_posix(GetLastError());
29902994
CloseHandle(handle);
29912995
return -1;
29922996
}
29932997
CloseHandle(handle);
29942998

29952999
/* get target path for symlinks or mount points (aka 'junctions') */
2996-
switch (b->ReparseTag) {
3000+
switch ((*ptag = b->ReparseTag)) {
29973001
case IO_REPARSE_TAG_SYMLINK:
29983002
wbuf = (WCHAR*) (((char*) b->SymbolicLinkReparseBuffer.PathBuffer)
29993003
+ b->SymbolicLinkReparseBuffer.SubstituteNameOffset);
@@ -3007,52 +3011,28 @@ static int get_reparse_point(const WCHAR *wpath, REPARSE_DATA_BUFFER *b, size_t
30073011
+ b->MountPointReparseBuffer.SubstituteNameLength) = 0;
30083012
break;
30093013
default:
3010-
wbuf = NULL;
3011-
break;
3012-
}
3013-
3014-
*pwbuf = wbuf;
3015-
return 0;
3016-
}
3017-
3018-
static int get_reparse_point_link_len(const WCHAR *wpath, DWORD *ptag)
3019-
{
3020-
WCHAR *wbuf;
3021-
REPARSE_DATA_BUFFER *b = alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
3022-
int len;
3023-
3024-
if (get_reparse_point(wpath, b, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &wbuf) < 0)
3014+
errno = EINVAL;
30253015
return -1;
3026-
if (wbuf == NULL) {
3027-
*ptag = b->ReparseTag;
3028-
return MAX_LONG_PATH; /* return value for compatibility */
30293016
}
30303017

3031-
len = WideCharToMultiByte(CP_UTF8, 0, normalize_ntpath(wbuf), -1, 0, 0, NULL, NULL);
3032-
if (len) {
3033-
*ptag = b->ReparseTag;
3034-
return len - 1;
3035-
}
3036-
errno = ERANGE;
3037-
return -1;
3018+
if ((*plen =
3019+
xwcstoutf(tmpbuf, normalize_ntpath(wbuf), MAX_LONG_PATH)) < 0)
3020+
return -1;
3021+
return 0;
30383022
}
30393023

30403024
int readlink(const char *path, char *buf, size_t bufsiz)
30413025
{
3042-
WCHAR wpath[MAX_LONG_PATH], *wbuf;
3043-
REPARSE_DATA_BUFFER *b = alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
3026+
WCHAR wpath[MAX_LONG_PATH];
30443027
char tmpbuf[MAX_LONG_PATH];
30453028
int len;
3029+
DWORD tag;
30463030

30473031
if (xutftowcs_long_path(wpath, path) < 0)
30483032
return -1;
30493033

3050-
if (get_reparse_point(wpath, b, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &wbuf) < 0)
3051-
return -1;
3052-
if (wbuf == NULL) {
3053-
errno = EINVAL;
3034+
if (readlink_1(wpath, tmpbuf, &len, &tag) < 0)
30543035
return -1;
3055-
}
30563036

30573037
/*
30583038
* Adapt to strange readlink() API: Copy up to bufsiz *bytes*, potentially
@@ -3061,8 +3041,6 @@ int readlink(const char *path, char *buf, size_t bufsiz)
30613041
* so convert to a (hopefully large enough) temporary buffer, then memcpy
30623042
* the requested number of bytes (including '\0' for robustness).
30633043
*/
3064-
if ((len = xwcstoutf(tmpbuf, normalize_ntpath(wbuf), MAX_LONG_PATH)) < 0)
3065-
return -1;
30663044
memcpy(buf, tmpbuf, min(bufsiz, len + 1));
30673045
return min(bufsiz, len);
30683046
}

0 commit comments

Comments
 (0)