]> granicus.if.org Git - vim/commitdiff
updated for version 7.3.172 v7.3.172
authorBram Moolenaar <Bram@vim.org>
Thu, 5 May 2011 14:41:24 +0000 (16:41 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 5 May 2011 14:41:24 +0000 (16:41 +0200)
Problem:    MS-Windows: rename() might delete the file if the name differs but
            it's actually the same file.
Solution:   Use the file handle to check if it's the same file. (Yukihiro
            Nakadaira)

src/fileio.c
src/if_cscope.c
src/os_win32.c
src/proto/os_win32.pro
src/version.c
src/vim.h

index 62adf72dc50f1b9336cd34a4e666e3a1aaca8b0f..11b5045a4410dc8c5d7cb3a475c21b051ff8f62a 100644 (file)
@@ -6555,6 +6555,21 @@ vim_rename(from, to)
            use_tmp_file = TRUE;
     }
 #endif
+#ifdef WIN3264
+    {
+       BY_HANDLE_FILE_INFORMATION info1, info2;
+
+       /* It's possible for the source and destination to be the same file.
+        * In that case go through a temp file name.  This makes rename("foo",
+        * "./foo") a no-op (in a complicated way). */
+       if (win32_fileinfo(from, &info1) == FILEINFO_OK
+               && win32_fileinfo(to, &info2) == FILEINFO_OK
+               && info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
+               && info1.nFileIndexHigh == info2.nFileIndexHigh
+               && info1.nFileIndexLow == info2.nFileIndexLow)
+           use_tmp_file = TRUE;
+    }
+#endif
 
 #if defined(UNIX) || defined(CASE_INSENSITIVE_FILENAME)
     if (use_tmp_file)
index 82c51737198f0064d0cb186504e26e9bbeb21998..a966226848e071dd6bc848a4142236fc4008d509 100644 (file)
@@ -1412,17 +1412,15 @@ cs_insert_filelist(fname, ppath, flags, sb)
 {
     short      i, j;
 #ifndef UNIX
-    HANDLE     hFile;
     BY_HANDLE_FILE_INFORMATION bhfi;
 
-    vim_memset(&bhfi, 0, sizeof(bhfi));
     /* On windows 9x GetFileInformationByHandle doesn't work, so skip it */
     if (!mch_windows95())
     {
-       hFile = CreateFile(fname, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
-                                                FILE_ATTRIBUTE_NORMAL, NULL);
-       if (hFile == INVALID_HANDLE_VALUE)
+       switch (win32_fileinfo(fname, &bhfi))
        {
+       case FILEINFO_ENC_FAIL:         /* enc_to_utf16() failed */
+       case FILEINFO_READ_FAIL:        /* CreateFile() failed */
            if (p_csverbose)
            {
                char *cant_msg = _("E625: cannot open cscope database: %s");
@@ -1438,15 +1436,12 @@ cs_insert_filelist(fname, ppath, flags, sb)
                    (void)EMSG2(cant_msg, fname);
            }
            return -1;
-       }
-       if (!GetFileInformationByHandle(hFile, &bhfi))
-       {
-           CloseHandle(hFile);
+
+       case FILEINFO_INFO_FAIL:    /* GetFileInformationByHandle() failed */
            if (p_csverbose)
                (void)EMSG(_("E626: cannot get cscope database information"));
            return -1;
        }
-       CloseHandle(hFile);
     }
 #endif
 
index 90664e626cb90575321b1ff84601237806771f5f..bf51d247316ee4010bd0969adf6cbaf06f78b01a 100644 (file)
@@ -2644,26 +2644,45 @@ mch_isdir(char_u *name)
  */
     int
 mch_is_linked(char_u *fname)
+{
+    BY_HANDLE_FILE_INFORMATION info;
+
+    return win32_fileinfo(fname, &info) == FILEINFO_OK
+                                                  && info.nNumberOfLinks > 1;
+}
+
+/*
+ * Get the by-handle-file-information for "fname".
+ * Returns FILEINFO_OK when OK.
+ * returns FILEINFO_ENC_FAIL when enc_to_utf16() failed.
+ * Returns FILEINFO_READ_FAIL when CreateFile() failed.
+ * Returns FILEINFO_INFO_FAIL when GetFileInformationByHandle() failed.
+ */
+    int
+win32_fileinfo(char_u *fname, BY_HANDLE_FILE_INFORMATION *info)
 {
     HANDLE     hFile;
-    int                res = 0;
-    BY_HANDLE_FILE_INFORMATION inf;
+    int                res = FILEINFO_READ_FAIL;
 #ifdef FEAT_MBYTE
     WCHAR      *wn = NULL;
 
     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
        wn = enc_to_utf16(fname, NULL);
+       if (wn == NULL)
+           res = FILEINFO_ENC_FAIL;
+    }
     if (wn != NULL)
     {
        hFile = CreateFileW(wn,         /* file name */
                    GENERIC_READ,       /* access mode */
-                   0,                  /* share mode */
+                   FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
                    NULL,               /* security descriptor */
                    OPEN_EXISTING,      /* creation disposition */
-                   0,                  /* file attributes */
+                   FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
                    NULL);              /* handle to template file */
        if (hFile == INVALID_HANDLE_VALUE
-               && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+                             && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
        {
            /* Retry with non-wide function (for Windows 98). */
            vim_free(wn);
@@ -2674,17 +2693,18 @@ mch_is_linked(char_u *fname)
 #endif
        hFile = CreateFile(fname,       /* file name */
                    GENERIC_READ,       /* access mode */
-                   0,                  /* share mode */
+                   FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
                    NULL,               /* security descriptor */
                    OPEN_EXISTING,      /* creation disposition */
-                   0,                  /* file attributes */
+                   FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
                    NULL);              /* handle to template file */
 
     if (hFile != INVALID_HANDLE_VALUE)
     {
-       if (GetFileInformationByHandle(hFile, &inf) != 0
-               && inf.nNumberOfLinks > 1)
-           res = 1;
+       if (GetFileInformationByHandle(hFile, info) != 0)
+           res = FILEINFO_OK;
+       else
+           res = FILEINFO_INFO_FAIL;
        CloseHandle(hFile);
     }
 
index 31aa269ae6e93028fd4d55f0d99365bb7bb45f0f..a3f5b3ecde015dc21a862e6f674eedf772236528 100644 (file)
@@ -21,6 +21,7 @@ int mch_setperm __ARGS((char_u *name, long perm));
 void mch_hide __ARGS((char_u *name));
 int mch_isdir __ARGS((char_u *name));
 int mch_is_linked __ARGS((char_u *fname));
+int win32_fileinfo __ARGS((char_u *name, BY_HANDLE_FILE_INFORMATION *lpFileInfo));
 int mch_writable __ARGS((char_u *name));
 int mch_can_exe __ARGS((char_u *name));
 int mch_nodetype __ARGS((char_u *name));
index b99456a539183f2f176fdfef316b194383356095..d4edf67ce3c699272f9461063eef39003626342a 100644 (file)
@@ -714,6 +714,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    172,
 /**/
     171,
 /**/
index 95260a221f0ed951019f83b655a72e6c499f1a35..229e6dc41f7ebcfcd0bdbb9baaa5dfa2d81c1c51 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2217,4 +2217,10 @@ typedef int VimClipboard;        /* This is required for the prototypes. */
 #define KEYLEN_PART_MAP -2     /* keylen value for incomplete mapping */
 #define KEYLEN_REMOVED  9999   /* keylen value for removed sequence */
 
+/* Return values from win32_fileinfo(). */
+#define FILEINFO_OK         0
+#define FILEINFO_ENC_FAIL    1 /* enc_to_utf16() failed */
+#define FILEINFO_READ_FAIL   2 /* CreateFile() failed */
+#define FILEINFO_INFO_FAIL   3 /* GetFileInformationByHandle() failed */
+
 #endif /* VIM__H */