Patch 7.3.1182
Problem:    'backupcopy' default on MS-Windows does not work for hard and soft
            links.
Solution:   Check for links. (David Pope, Ken Takata)
Files:      src/fileio.c, src/os_win32.c, src/proto/os_win32.pro


*** ../vim-7.3.1181/src/fileio.c        2013-06-12 19:52:11.000000000 +0200
--- src/fileio.c        2013-06-12 22:31:34.000000000 +0200
***************
*** 3780,3791 ****
            }
        }
  
- # ifdef UNIX
        /*
         * Break symlinks and/or hardlinks if we've been asked to.
         */
        if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
        {
            int lstat_res;
  
            lstat_res = mch_lstat((char *)fname, &st);
--- 3780,3791 ----
            }
        }
  
        /*
         * Break symlinks and/or hardlinks if we've been asked to.
         */
        if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
        {
+ # ifdef UNIX
            int lstat_res;
  
            lstat_res = mch_lstat((char *)fname, &st);
***************
*** 3801,3808 ****
                    && st_old.st_nlink > 1
                    && (lstat_res != 0 || st.st_ino == st_old.st_ino))
                backup_copy = FALSE;
        }
- #endif
  
  #endif
  
--- 3801,3818 ----
                    && st_old.st_nlink > 1
                    && (lstat_res != 0 || st.st_ino == st_old.st_ino))
                backup_copy = FALSE;
+ # else
+ #  if defined(WIN32)
+           /* Symlinks. */
+           if ((bkc_flags & BKC_BREAKSYMLINK) && mch_is_symbolic_link(fname))
+               backup_copy = FALSE;
+ 
+           /* Hardlinks. */
+           if ((bkc_flags & BKC_BREAKHARDLINK) && mch_is_hard_link(fname))
+               backup_copy = FALSE;
+ #  endif
+ # endif
        }
  
  #endif
  
*** ../vim-7.3.1181/src/os_win32.c      2013-06-07 19:17:12.000000000 +0200
--- src/os_win32.c      2013-06-12 22:39:53.000000000 +0200
***************
*** 78,83 ****
--- 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 */
  
***************
*** 219,224 ****
--- 229,238 ----
  static char *vimrun_path = "vimrun ";
  #endif
  
+ static int win32_getattrs(char_u *name);
+ static int win32_setattrs(char_u *name, int attrs);
+ static int win32_set_archive(char_u *name);
+ 
  #ifndef FEAT_GUI_W32
  static int suppress_winsize = 1;      /* don't fiddle with console */
  #endif
***************
*** 2623,2679 ****
  /*
   * get file permissions for `name'
   * -1 : error
!  * else FILE_ATTRIBUTE_* defined in winnt.h
   */
      long
  mch_getperm(char_u *name)
  {
! #ifdef FEAT_MBYTE
!     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
!     {
!       WCHAR   *p = enc_to_utf16(name, NULL);
!       long    n;
  
!       if (p != NULL)
!       {
!           n = (long)GetFileAttributesW(p);
!           vim_free(p);
!           if (n >= 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
!               return n;
!           /* Retry with non-wide function (for Windows 98). */
!       }
!     }
! #endif
!     return (long)GetFileAttributes((char *)name);
  }
  
  
  /*
   * set file permission for `name' to `perm'
   */
      int
  mch_setperm(
      char_u  *name,
      long    perm)
  {
!     perm |= FILE_ATTRIBUTE_ARCHIVE;   /* file has changed, set archive bit */
  #ifdef FEAT_MBYTE
      if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
      {
!       WCHAR   *p = enc_to_utf16(name, NULL);
!       long    n;
  
        if (p != NULL)
        {
!           n = (long)SetFileAttributesW(p, perm);
            vim_free(p);
!           if (n || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
!               return n ? OK : FAIL;
            /* Retry with non-wide function (for Windows 98). */
        }
      }
  #endif
!     return SetFileAttributes((char *)name, perm) ? OK : FAIL;
  }
  
  /*
--- 2637,2690 ----
  /*
   * get file permissions for `name'
   * -1 : error
!  * else mode_t
   */
      long
  mch_getperm(char_u *name)
  {
!     struct stat st;
!     int n;
  
!     n = mch_stat(name, &st);
!     return n == 0 ? (int)st.st_mode : -1;
  }
  
  
  /*
   * set file permission for `name' to `perm'
+  *
+  * return FAIL for failure, OK otherwise
   */
      int
  mch_setperm(
      char_u  *name,
      long    perm)
  {
!     long      n;
  #ifdef FEAT_MBYTE
+     WCHAR *p;
      if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
      {
!       p = enc_to_utf16(name, NULL);
  
        if (p != NULL)
        {
!           n = _wchmod(p, perm);
            vim_free(p);
!           if (n == -1 && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
!               return FAIL;
            /* Retry with non-wide function (for Windows 98). */
        }
      }
+     if (p == NULL)
  #endif
!       n = _chmod(name, perm);
!     if (n == -1)
!       return FAIL;
! 
!     win32_set_archive(name);
! 
!     return OK;
  }
  
  /*
***************
*** 2682,2730 ****
      void
  mch_hide(char_u *name)
  {
!     int               perm;
! #ifdef FEAT_MBYTE
!     WCHAR     *p = NULL;
! 
!     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
!       p = enc_to_utf16(name, NULL);
! #endif
  
! #ifdef FEAT_MBYTE
!     if (p != NULL)
!     {
!       perm = GetFileAttributesW(p);
!       if (perm < 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
!       {
!           /* Retry with non-wide function (for Windows 98). */
!           vim_free(p);
!           p = NULL;
!       }
!     }
!     if (p == NULL)
! #endif
!       perm = GetFileAttributes((char *)name);
!     if (perm >= 0)
!     {
!       perm |= FILE_ATTRIBUTE_HIDDEN;
! #ifdef FEAT_MBYTE
!       if (p != NULL)
!       {
!           if (SetFileAttributesW(p, perm) == 0
!                   && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
!           {
!               /* Retry with non-wide function (for Windows 98). */
!               vim_free(p);
!               p = NULL;
!           }
!       }
!       if (p == NULL)
! #endif
!           SetFileAttributes((char *)name, perm);
!     }
! #ifdef FEAT_MBYTE
!     vim_free(p);
! #endif
  }
  
  /*
--- 2693,2704 ----
      void
  mch_hide(char_u *name)
  {
!     int attrs = win32_getattrs(name);
!     if (attrs == -1)
!       return;
  
!     attrs |= FILE_ATTRIBUTE_HIDDEN;
!     win32_setattrs(name, attrs);
  }
  
  /*
***************
*** 2734,2740 ****
      int
  mch_isdir(char_u *name)
  {
!     int f = mch_getperm(name);
  
      if (f == -1)
        return FALSE;               /* file does not exist at all */
--- 2708,2714 ----
      int
  mch_isdir(char_u *name)
  {
!     int f = win32_getattrs(name);
  
      if (f == -1)
        return FALSE;               /* file does not exist at all */
***************
*** 2770,2776 ****
   * Return TRUE if file "fname" has more than one link.
   */
      int
! mch_is_linked(char_u *fname)
  {
      BY_HANDLE_FILE_INFORMATION info;
  
--- 2744,2750 ----
   * Return TRUE if file "fname" has more than one link.
   */
      int
! mch_is_hard_link(char_u *fname)
  {
      BY_HANDLE_FILE_INFORMATION info;
  
***************
*** 2779,2784 ****
--- 2753,2826 ----
  }
  
  /*
+  * Return TRUE if file "fname" is a symbolic link.
+  */
+     int
+ mch_is_symbolic_link(char_u *fname)
+ {
+     HANDLE            hFind;
+     int                       res = FALSE;
+     WIN32_FIND_DATAA  findDataA;
+     DWORD             fileFlags = 0, reparseTag = 0;
+ #ifdef FEAT_MBYTE
+     WCHAR             *wn = NULL;
+     WIN32_FIND_DATAW  findDataW;
+ 
+     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+       wn = enc_to_utf16(fname, NULL);
+     if (wn != NULL)
+     {
+       hFind = FindFirstFileW(wn, &findDataW);
+       vim_free(wn);
+       if (hFind == INVALID_HANDLE_VALUE
+               && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+       {
+           /* Retry with non-wide function (for Windows 98). */
+           hFind = FindFirstFile(fname, &findDataA);
+           if (hFind != INVALID_HANDLE_VALUE)
+           {
+               fileFlags = findDataA.dwFileAttributes;
+               reparseTag = findDataA.dwReserved0;
+           }
+       }
+       else
+       {
+           fileFlags = findDataW.dwFileAttributes;
+           reparseTag = findDataW.dwReserved0;
+       }
+     }
+ #else
+     hFind = FindFirstFile(fname, &findDataA);
+     if (hFind != INVALID_HANDLE_VALUE)
+     {
+       fileFlags = findDataA.dwFileAttributes;
+       reparseTag = findDataA.dwReserved0;
+     }
+ #endif
+ 
+     if (hFind != INVALID_HANDLE_VALUE)
+       FindClose(hFind);
+ 
+     if ((fileFlags & FILE_ATTRIBUTE_REPARSE_POINT)
+           && reparseTag == IO_REPARSE_TAG_SYMLINK)
+       res = TRUE;
+ 
+     return res;
+ }
+ 
+ /*
+  * Return TRUE if file "fname" has more than one link or if it is a symbolic
+  * link.
+  */
+     int
+ mch_is_linked(char_u *fname)
+ {
+     if (mch_is_hard_link(fname) || mch_is_symbolic_link(fname))
+       return TRUE;
+     return FALSE;
+ }
+ 
+ /*
   * Get the by-handle-file-information for "fname".
   * Returns FILEINFO_OK when OK.
   * returns FILEINFO_ENC_FAIL when enc_to_utf16() failed.
***************
*** 2842,2847 ****
--- 2884,2975 ----
  }
  
  /*
+  * get file attributes for `name'
+  * -1 : error
+  * else FILE_ATTRIBUTE_* defined in winnt.h
+  */
+     static
+     int
+ win32_getattrs(char_u *name)
+ {
+     int               attr;
+ #ifdef FEAT_MBYTE
+     WCHAR     *p = NULL;
+ 
+     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+       p = enc_to_utf16(name, NULL);
+ 
+     if (p != NULL)
+     {
+       attr = GetFileAttributesW(p);
+       if (attr < 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+       {
+           /* Retry with non-wide function (for Windows 98). */
+           vim_free(p);
+           p = NULL;
+       }
+     }
+     if (p == NULL)
+ #endif
+       attr = GetFileAttributes((char *)name);
+ #ifdef FEAT_MBYTE
+     vim_free(p);
+ #endif
+     return attr;
+ }
+ 
+ /*
+  * set file attributes for `name' to `attrs'
+  *
+  * return -1 for failure, 0 otherwise
+  */
+     static
+     int
+ win32_setattrs(char_u *name, int attrs)
+ {
+     int res;
+ #ifdef FEAT_MBYTE
+     WCHAR     *p = NULL;
+ 
+     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+       p = enc_to_utf16(name, NULL);
+ 
+     if (p != NULL)
+     {
+       res = SetFileAttributesW(p, attrs);
+       if (res == FALSE
+           && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+       {
+           /* Retry with non-wide function (for Windows 98). */
+           vim_free(p);
+           p = NULL;
+       }
+     }
+     if (p == NULL)
+ #endif
+       res = SetFileAttributes((char *)name, attrs);
+ #ifdef FEAT_MBYTE
+     vim_free(p);
+ #endif
+     return res ? 0 : -1;
+ }
+ 
+ /*
+  * Set archive flag for "name".
+  */
+     static
+     int
+ win32_set_archive(char_u *name)
+ {
+     int attrs = win32_getattrs(name);
+     if (attrs == -1)
+       return -1;
+ 
+     attrs |= FILE_ATTRIBUTE_ARCHIVE;
+     return win32_setattrs(name, attrs);
+ }
+ 
+ /*
   * Return TRUE if file or directory "name" is writable (not readonly).
   * Strange semantics of Win32: a readonly directory is writable, but you can't
   * delete a file.  Let's say this means it is writable.
***************
*** 2849,2858 ****
      int
  mch_writable(char_u *name)
  {
!     int perm = mch_getperm(name);
  
!     return (perm != -1 && (!(perm & FILE_ATTRIBUTE_READONLY)
!                                      || (perm & FILE_ATTRIBUTE_DIRECTORY)));
  }
  
  /*
--- 2977,2986 ----
      int
  mch_writable(char_u *name)
  {
!     int attrs = win32_getattrs(name);
  
!     return (attrs != -1 && (!(attrs & FILE_ATTRIBUTE_READONLY)
!                         || (attrs & FILE_ATTRIBUTE_DIRECTORY)));
  }
  
  /*
***************
*** 5012,5024 ****
  #ifdef FEAT_MBYTE
      WCHAR     *wn = NULL;
      int               n;
  
      if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
      {
        wn = enc_to_utf16(name, NULL);
        if (wn != NULL)
        {
-           SetFileAttributesW(wn, FILE_ATTRIBUTE_NORMAL);
            n = DeleteFileW(wn) ? 0 : -1;
            vim_free(wn);
            if (n == 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
--- 5140,5155 ----
  #ifdef FEAT_MBYTE
      WCHAR     *wn = NULL;
      int               n;
+ #endif
  
+     win32_setattrs(name, FILE_ATTRIBUTE_NORMAL);
+ 
+ #ifdef FEAT_MBYTE
      if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
      {
        wn = enc_to_utf16(name, NULL);
        if (wn != NULL)
        {
            n = DeleteFileW(wn) ? 0 : -1;
            vim_free(wn);
            if (n == 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
***************
*** 5027,5033 ****
        }
      }
  #endif
-     SetFileAttributes(name, FILE_ATTRIBUTE_NORMAL);
      return DeleteFile(name) ? 0 : -1;
  }
  
--- 5158,5163 ----
*** ../vim-7.3.1181/src/proto/os_win32.pro      2012-11-20 16:56:49.000000000 
+0100
--- src/proto/os_win32.pro      2013-06-12 22:29:53.000000000 +0200
***************
*** 21,26 ****
--- 21,28 ----
  void mch_hide __ARGS((char_u *name));
  int mch_isdir __ARGS((char_u *name));
  int mch_mkdir __ARGS((char_u *name));
+ int mch_is_hard_link __ARGS((char_u *fname));
+ int mch_is_symbolic_link __ARGS((char_u *fname));
  int mch_is_linked __ARGS((char_u *fname));
  int win32_fileinfo __ARGS((char_u *fname, BY_HANDLE_FILE_INFORMATION *info));
  int mch_writable __ARGS((char_u *name));
*** ../vim-7.3.1181/src/version.c       2013-06-12 22:08:54.000000000 +0200
--- src/version.c       2013-06-12 22:40:29.000000000 +0200
***************
*** 730,731 ****
--- 730,733 ----
  {   /* Add new patch number below this line */
+ /**/
+     1182,
  /**/

-- 
If Microsoft would build a car...
... You'd have to press the "Start" button to turn the engine off.

 /// Bram Moolenaar -- b...@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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Raspunde prin e-mail lui