lkundrak / rpms / vim

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