summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2011-05-05 16:41:24 +0200
committerBram Moolenaar <Bram@vim.org>2011-05-05 16:41:24 +0200
commit1c32dff7d6b4cf00d1e63ac79968e9deb8b90e2e (patch)
tree2d78aad10e6cfc81acfcac846501a99d719933d5
parent85de20665f3ed48345b79cd0920af41397544141 (diff)
downloadvim-git-1c32dff7d6b4cf00d1e63ac79968e9deb8b90e2e.tar.gz
updated for version 7.3.172v7.3.172
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)
-rw-r--r--src/fileio.c15
-rw-r--r--src/if_cscope.c15
-rw-r--r--src/os_win32.c40
-rw-r--r--src/proto/os_win32.pro1
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h6
6 files changed, 59 insertions, 20 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 62adf72dc..11b5045a4 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -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)
diff --git a/src/if_cscope.c b/src/if_cscope.c
index 82c517371..a96622684 100644
--- a/src/if_cscope.c
+++ b/src/if_cscope.c
@@ -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
diff --git a/src/os_win32.c b/src/os_win32.c
index 90664e626..bf51d2473 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -2645,25 +2645,44 @@ 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);
}
diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro
index 31aa269ae..a3f5b3ecd 100644
--- a/src/proto/os_win32.pro
+++ b/src/proto/os_win32.pro
@@ -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));
diff --git a/src/version.c b/src/version.c
index b99456a53..d4edf67ce 100644
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 172,
+/**/
171,
/**/
170,
diff --git a/src/vim.h b/src/vim.h
index 95260a221..229e6dc41 100644
--- 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 */