mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
updated for version 7.4.039
Problem: MS-Windows: MSCV10 and earlier can't handle symlinks to a directory properly. Solution: Add stat_symlink_aware() and wstat_symlink_aware(). (Ken Takata)
This commit is contained in:
parent
134bf07ca0
commit
2ee95f7d13
@ -498,6 +498,98 @@ slash_adjust(p)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
stat_symlink_aware(const char *name, struct stat *stp)
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||
/* Work around for VC10 or earlier. stat() can't handle symlinks properly.
|
||||
* VC9 or earlier: stat() doesn't support a symlink at all. It retrieves
|
||||
* status of a symlink itself.
|
||||
* VC10: stat() supports a symlink to a normal file, but it doesn't support
|
||||
* a symlink to a directory (always returns an error). */
|
||||
WIN32_FIND_DATA findData;
|
||||
HANDLE hFind, h;
|
||||
DWORD attr = 0;
|
||||
BOOL is_symlink = FALSE;
|
||||
|
||||
hFind = FindFirstFile(name, &findData);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
attr = findData.dwFileAttributes;
|
||||
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
&& (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
|
||||
is_symlink = TRUE;
|
||||
FindClose(hFind);
|
||||
}
|
||||
if (is_symlink)
|
||||
{
|
||||
h = CreateFile(name, FILE_READ_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING,
|
||||
(attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? FILE_FLAG_BACKUP_SEMANTICS : 0,
|
||||
NULL);
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int fd, n;
|
||||
|
||||
fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
|
||||
n = _fstat(fd, (struct _stat*)stp);
|
||||
_close(fd);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return stat(name, stp);
|
||||
}
|
||||
|
||||
#ifdef FEAT_MBYTE
|
||||
static int
|
||||
wstat_symlink_aware(const WCHAR *name, struct _stat *stp)
|
||||
{
|
||||
# if defined(_MSC_VER) && _MSC_VER < 1700
|
||||
/* Work around for VC10 or earlier. _wstat() can't handle symlinks properly.
|
||||
* VC9 or earlier: _wstat() doesn't support a symlink at all. It retrieves
|
||||
* status of a symlink itself.
|
||||
* VC10: _wstat() supports a symlink to a normal file, but it doesn't
|
||||
* support a symlink to a directory (always returns an error). */
|
||||
int n;
|
||||
BOOL is_symlink = FALSE;
|
||||
HANDLE hFind, h;
|
||||
DWORD attr = 0;
|
||||
WIN32_FIND_DATAW findDataW;
|
||||
|
||||
hFind = FindFirstFileW(name, &findDataW);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
attr = findDataW.dwFileAttributes;
|
||||
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
&& (findDataW.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
|
||||
is_symlink = TRUE;
|
||||
FindClose(hFind);
|
||||
}
|
||||
if (is_symlink)
|
||||
{
|
||||
h = CreateFileW(name, FILE_READ_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING,
|
||||
(attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? FILE_FLAG_BACKUP_SEMANTICS : 0,
|
||||
NULL);
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
|
||||
n = _fstat(fd, stp);
|
||||
_close(fd);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
return _wstat(name, stp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* stat() can't handle a trailing '/' or '\', remove it first.
|
||||
@ -534,7 +626,7 @@ vim_stat(const char *name, struct stat *stp)
|
||||
|
||||
if (wp != NULL)
|
||||
{
|
||||
n = _wstat(wp, (struct _stat *)stp);
|
||||
n = wstat_symlink_aware(wp, (struct _stat *)stp);
|
||||
vim_free(wp);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
@ -544,7 +636,7 @@ vim_stat(const char *name, struct stat *stp)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return stat(buf, stp);
|
||||
return stat_symlink_aware(buf, stp);
|
||||
}
|
||||
|
||||
#if defined(FEAT_GUI_MSWIN) || defined(PROTO)
|
||||
|
@ -78,16 +78,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reparse Point
|
||||
*/
|
||||
#ifndef FILE_ATTRIBUTE_REPARSE_POINT
|
||||
# define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||
# define IO_REPARSE_TAG_SYMLINK 0xA000000C
|
||||
#endif
|
||||
|
||||
/* Record all output and all keyboard & mouse input */
|
||||
/* #define MCH_WRITE_DUMP */
|
||||
|
||||
|
@ -130,6 +130,19 @@
|
||||
# define DFLT_MAXMEMTOT (5*1024) /* use up to 5 Mbyte for Vim */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reparse Point
|
||||
*/
|
||||
#ifndef FILE_ATTRIBUTE_REPARSE_POINT
|
||||
# define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_MOUNT_POINT
|
||||
# define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||
# define IO_REPARSE_TAG_SYMLINK 0xA000000C
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
/* Support for __try / __except. All versions of MSVC and Borland C are
|
||||
* expected to have this. Any other compilers that support it? */
|
||||
|
@ -738,6 +738,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
39,
|
||||
/**/
|
||||
38,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user