Mercurial > vim
changeset 2793:ee48b3da9d53 v7.3.172
updated for version 7.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)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Thu, 05 May 2011 16:41:24 +0200 |
parents | f8a458d9f368 |
children | 9107572d1602 |
files | src/fileio.c src/if_cscope.c src/os_win32.c src/proto/os_win32.pro src/version.c src/vim.h |
diffstat | 6 files changed, 59 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- 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)
--- a/src/if_cscope.c +++ b/src/if_cscope.c @@ -1412,17 +1412,15 @@ cs_insert_filelist(fname, ppath, flags, { 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, (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
--- 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); }
--- a/src/proto/os_win32.pro +++ b/src/proto/os_win32.pro @@ -21,6 +21,7 @@ int mch_setperm __ARGS((char_u *name, lo 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));
--- 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,
--- a/src/vim.h +++ b/src/vim.h @@ -2217,4 +2217,10 @@ typedef int VimClipboard; /* This is req #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 */