To: vim_dev@googlegroups.com
Subject: Patch 7.4.039
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------
Patch 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)
Files: src/os_mswin.c, src/os_win32.c, src/os_win32.h
*** ../vim-7.4.038/src/os_mswin.c 2013-08-30 16:51:15.000000000 +0200
--- src/os_mswin.c 2013-09-25 19:09:53.000000000 +0200
***************
*** 498,503 ****
--- 498,595 ----
}
}
+ 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,540 ****
if (wp != NULL)
{
! n = _wstat(wp, (struct _stat *)stp);
vim_free(wp);
if (n >= 0)
return n;
--- 626,632 ----
if (wp != NULL)
{
! n = wstat_symlink_aware(wp, (struct _stat *)stp);
vim_free(wp);
if (n >= 0)
return n;
***************
*** 544,550 ****
}
}
#endif
! return stat(buf, stp);
}
#if defined(FEAT_GUI_MSWIN) || defined(PROTO)
--- 636,642 ----
}
}
#endif
! return stat_symlink_aware(buf, stp);
}
#if defined(FEAT_GUI_MSWIN) || defined(PROTO)
*** ../vim-7.4.038/src/os_win32.c 2013-08-30 17:29:10.000000000 +0200
--- src/os_win32.c 2013-09-25 19:09:53.000000000 +0200
***************
*** 78,93 ****
# 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 */
--- 78,83 ----
*** ../vim-7.4.038/src/os_win32.h 2013-07-21 17:53:13.000000000 +0200
--- src/os_win32.h 2013-09-25 19:09:53.000000000 +0200
***************
*** 130,135 ****
--- 130,148 ----
# 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? */
*** ../vim-7.4.038/src/version.c 2013-09-25 18:54:20.000000000 +0200
--- src/version.c 2013-09-25 19:08:55.000000000 +0200
***************
*** 740,741 ****
--- 740,743 ----
{ /* Add new patch number below this line */
+ /**/
+ 39,
/**/
--
A cow comes flying over the battlements, lowing aggressively. The cow
lands on GALAHAD'S PAGE, squashing him completely.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///