Blame SOURCES/7.4.039

d6ba96
To: vim_dev@googlegroups.com
d6ba96
Subject: Patch 7.4.039
d6ba96
Fcc: outbox
d6ba96
From: Bram Moolenaar <Bram@moolenaar.net>
d6ba96
Mime-Version: 1.0
d6ba96
Content-Type: text/plain; charset=UTF-8
d6ba96
Content-Transfer-Encoding: 8bit
d6ba96
------------
d6ba96
d6ba96
Patch 7.4.039
d6ba96
Problem:    MS-Windows: MSCV10 and earlier can't handle symlinks to a
d6ba96
	    directory properly.
d6ba96
Solution:   Add stat_symlink_aware() and wstat_symlink_aware(). (Ken Takata)
d6ba96
Files:	    src/os_mswin.c, src/os_win32.c, src/os_win32.h
d6ba96
d6ba96
d6ba96
*** ../vim-7.4.038/src/os_mswin.c	2013-08-30 16:51:15.000000000 +0200
d6ba96
--- src/os_mswin.c	2013-09-25 19:09:53.000000000 +0200
d6ba96
***************
d6ba96
*** 498,503 ****
d6ba96
--- 498,595 ----
d6ba96
      }
d6ba96
  }
d6ba96
  
d6ba96
+     static int
d6ba96
+ stat_symlink_aware(const char *name, struct stat *stp)
d6ba96
+ {
d6ba96
+ #if defined(_MSC_VER) && _MSC_VER < 1700
d6ba96
+     /* Work around for VC10 or earlier. stat() can't handle symlinks properly.
d6ba96
+      * VC9 or earlier: stat() doesn't support a symlink at all. It retrieves
d6ba96
+      * status of a symlink itself.
d6ba96
+      * VC10: stat() supports a symlink to a normal file, but it doesn't support
d6ba96
+      * a symlink to a directory (always returns an error). */
d6ba96
+     WIN32_FIND_DATA	findData;
d6ba96
+     HANDLE		hFind, h;
d6ba96
+     DWORD		attr = 0;
d6ba96
+     BOOL		is_symlink = FALSE;
d6ba96
+ 
d6ba96
+     hFind = FindFirstFile(name, &findData);
d6ba96
+     if (hFind != INVALID_HANDLE_VALUE)
d6ba96
+     {
d6ba96
+ 	attr = findData.dwFileAttributes;
d6ba96
+ 	if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
d6ba96
+ 		&& (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
d6ba96
+ 	    is_symlink = TRUE;
d6ba96
+ 	FindClose(hFind);
d6ba96
+     }
d6ba96
+     if (is_symlink)
d6ba96
+     {
d6ba96
+ 	h = CreateFile(name, FILE_READ_ATTRIBUTES,
d6ba96
+ 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
d6ba96
+ 		OPEN_EXISTING,
d6ba96
+ 		(attr & FILE_ATTRIBUTE_DIRECTORY)
d6ba96
+ 					    ? FILE_FLAG_BACKUP_SEMANTICS : 0,
d6ba96
+ 		NULL);
d6ba96
+ 	if (h != INVALID_HANDLE_VALUE)
d6ba96
+ 	{
d6ba96
+ 	    int	    fd, n;
d6ba96
+ 
d6ba96
+ 	    fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
d6ba96
+ 	    n = _fstat(fd, (struct _stat*)stp);
d6ba96
+ 	    _close(fd);
d6ba96
+ 	    return n;
d6ba96
+ 	}
d6ba96
+     }
d6ba96
+ #endif
d6ba96
+     return stat(name, stp);
d6ba96
+ }
d6ba96
+ 
d6ba96
+ #ifdef FEAT_MBYTE
d6ba96
+     static int
d6ba96
+ wstat_symlink_aware(const WCHAR *name, struct _stat *stp)
d6ba96
+ {
d6ba96
+ # if defined(_MSC_VER) && _MSC_VER < 1700
d6ba96
+     /* Work around for VC10 or earlier. _wstat() can't handle symlinks properly.
d6ba96
+      * VC9 or earlier: _wstat() doesn't support a symlink at all. It retrieves
d6ba96
+      * status of a symlink itself.
d6ba96
+      * VC10: _wstat() supports a symlink to a normal file, but it doesn't
d6ba96
+      * support a symlink to a directory (always returns an error). */
d6ba96
+     int			n;
d6ba96
+     BOOL		is_symlink = FALSE;
d6ba96
+     HANDLE		hFind, h;
d6ba96
+     DWORD		attr = 0;
d6ba96
+     WIN32_FIND_DATAW	findDataW;
d6ba96
+ 
d6ba96
+     hFind = FindFirstFileW(name, &findDataW);
d6ba96
+     if (hFind != INVALID_HANDLE_VALUE)
d6ba96
+     {
d6ba96
+ 	attr = findDataW.dwFileAttributes;
d6ba96
+ 	if ((attr & FILE_ATTRIBUTE_REPARSE_POINT)
d6ba96
+ 		&& (findDataW.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
d6ba96
+ 	    is_symlink = TRUE;
d6ba96
+ 	FindClose(hFind);
d6ba96
+     }
d6ba96
+     if (is_symlink)
d6ba96
+     {
d6ba96
+ 	h = CreateFileW(name, FILE_READ_ATTRIBUTES,
d6ba96
+ 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
d6ba96
+ 		OPEN_EXISTING,
d6ba96
+ 		(attr & FILE_ATTRIBUTE_DIRECTORY)
d6ba96
+ 					    ? FILE_FLAG_BACKUP_SEMANTICS : 0,
d6ba96
+ 		NULL);
d6ba96
+ 	if (h != INVALID_HANDLE_VALUE)
d6ba96
+ 	{
d6ba96
+ 	    int	    fd;
d6ba96
+ 
d6ba96
+ 	    fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
d6ba96
+ 	    n = _fstat(fd, stp);
d6ba96
+ 	    _close(fd);
d6ba96
+ 	    return n;
d6ba96
+ 	}
d6ba96
+     }
d6ba96
+ # endif
d6ba96
+     return _wstat(name, stp);
d6ba96
+ }
d6ba96
+ #endif
d6ba96
  
d6ba96
  /*
d6ba96
   * stat() can't handle a trailing '/' or '\', remove it first.
d6ba96
***************
d6ba96
*** 534,540 ****
d6ba96
  
d6ba96
  	if (wp != NULL)
d6ba96
  	{
d6ba96
! 	    n = _wstat(wp, (struct _stat *)stp);
d6ba96
  	    vim_free(wp);
d6ba96
  	    if (n >= 0)
d6ba96
  		return n;
d6ba96
--- 626,632 ----
d6ba96
  
d6ba96
  	if (wp != NULL)
d6ba96
  	{
d6ba96
! 	    n = wstat_symlink_aware(wp, (struct _stat *)stp);
d6ba96
  	    vim_free(wp);
d6ba96
  	    if (n >= 0)
d6ba96
  		return n;
d6ba96
***************
d6ba96
*** 544,550 ****
d6ba96
  	}
d6ba96
      }
d6ba96
  #endif
d6ba96
!     return stat(buf, stp);
d6ba96
  }
d6ba96
  
d6ba96
  #if defined(FEAT_GUI_MSWIN) || defined(PROTO)
d6ba96
--- 636,642 ----
d6ba96
  	}
d6ba96
      }
d6ba96
  #endif
d6ba96
!     return stat_symlink_aware(buf, stp);
d6ba96
  }
d6ba96
  
d6ba96
  #if defined(FEAT_GUI_MSWIN) || defined(PROTO)
d6ba96
*** ../vim-7.4.038/src/os_win32.c	2013-08-30 17:29:10.000000000 +0200
d6ba96
--- src/os_win32.c	2013-09-25 19:09:53.000000000 +0200
d6ba96
***************
d6ba96
*** 78,93 ****
d6ba96
  # endif
d6ba96
  #endif
d6ba96
  
d6ba96
- /*
d6ba96
-  * Reparse Point
d6ba96
-  */
d6ba96
- #ifndef FILE_ATTRIBUTE_REPARSE_POINT
d6ba96
- # define FILE_ATTRIBUTE_REPARSE_POINT	0x00000400
d6ba96
- #endif
d6ba96
- #ifndef IO_REPARSE_TAG_SYMLINK
d6ba96
- # define IO_REPARSE_TAG_SYMLINK		0xA000000C
d6ba96
- #endif
d6ba96
- 
d6ba96
  /* Record all output and all keyboard & mouse input */
d6ba96
  /* #define MCH_WRITE_DUMP */
d6ba96
  
d6ba96
--- 78,83 ----
d6ba96
*** ../vim-7.4.038/src/os_win32.h	2013-07-21 17:53:13.000000000 +0200
d6ba96
--- src/os_win32.h	2013-09-25 19:09:53.000000000 +0200
d6ba96
***************
d6ba96
*** 130,135 ****
d6ba96
--- 130,148 ----
d6ba96
  # define DFLT_MAXMEMTOT	(5*1024)    /* use up to 5 Mbyte for Vim */
d6ba96
  #endif
d6ba96
  
d6ba96
+ /*
d6ba96
+  * Reparse Point
d6ba96
+  */
d6ba96
+ #ifndef FILE_ATTRIBUTE_REPARSE_POINT
d6ba96
+ # define FILE_ATTRIBUTE_REPARSE_POINT	0x00000400
d6ba96
+ #endif
d6ba96
+ #ifndef IO_REPARSE_TAG_MOUNT_POINT
d6ba96
+ # define IO_REPARSE_TAG_MOUNT_POINT	0xA0000003
d6ba96
+ #endif
d6ba96
+ #ifndef IO_REPARSE_TAG_SYMLINK
d6ba96
+ # define IO_REPARSE_TAG_SYMLINK		0xA000000C
d6ba96
+ #endif
d6ba96
+ 
d6ba96
  #if defined(_MSC_VER) || defined(__BORLANDC__)
d6ba96
      /* Support for __try / __except.  All versions of MSVC and Borland C are
d6ba96
       * expected to have this.  Any other compilers that support it? */
d6ba96
*** ../vim-7.4.038/src/version.c	2013-09-25 18:54:20.000000000 +0200
d6ba96
--- src/version.c	2013-09-25 19:08:55.000000000 +0200
d6ba96
***************
d6ba96
*** 740,741 ****
d6ba96
--- 740,743 ----
d6ba96
  {   /* Add new patch number below this line */
d6ba96
+ /**/
d6ba96
+     39,
d6ba96
  /**/
d6ba96
d6ba96
-- 
d6ba96
   A cow comes flying over the battlements,  lowing aggressively.  The cow
d6ba96
   lands on GALAHAD'S PAGE, squashing him completely.
d6ba96
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
d6ba96
d6ba96
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
d6ba96
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
d6ba96
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
d6ba96
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///