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