| To: vim_dev@googlegroups.com |
| Subject: Patch 7.3.172 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 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) |
| Files: src/if_cscope.c, src/fileio.c, src/os_win32.c, |
| src/proto/os_win32.pro, src/vim.h |
| |
| |
| |
| |
| |
| *** 1412,1428 **** |
| { |
| 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) |
| { |
| if (p_csverbose) |
| { |
| char *cant_msg = _("E625: cannot open cscope database: %s"); |
| --- 1412,1426 ---- |
| { |
| short i, j; |
| #ifndef UNIX |
| BY_HANDLE_FILE_INFORMATION bhfi; |
| |
| /* On windows 9x GetFileInformationByHandle doesn't work, so skip it */ |
| if (!mch_windows95()) |
| { |
| ! 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,1452 **** |
| (void)EMSG2(cant_msg, fname); |
| } |
| return -1; |
| ! } |
| ! if (!GetFileInformationByHandle(hFile, &bhfi)) |
| ! { |
| ! CloseHandle(hFile); |
| if (p_csverbose) |
| (void)EMSG(_("E626: cannot get cscope database information")); |
| return -1; |
| } |
| - CloseHandle(hFile); |
| } |
| #endif |
| |
| --- 1436,1447 ---- |
| (void)EMSG2(cant_msg, fname); |
| } |
| return -1; |
| ! |
| ! case FILEINFO_INFO_FAIL: /* GetFileInformationByHandle() failed */ |
| if (p_csverbose) |
| (void)EMSG(_("E626: cannot get cscope database information")); |
| return -1; |
| } |
| } |
| #endif |
| |
| |
| |
| |
| *** 6555,6560 **** |
| --- 6555,6575 ---- |
| 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) |
| |
| |
| |
| *** 2645,2669 **** |
| int |
| mch_is_linked(char_u *fname) |
| { |
| HANDLE hFile; |
| ! int res = 0; |
| ! BY_HANDLE_FILE_INFORMATION inf; |
| #ifdef FEAT_MBYTE |
| WCHAR *wn = NULL; |
| |
| if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) |
| wn = enc_to_utf16(fname, NULL); |
| if (wn != NULL) |
| { |
| hFile = CreateFileW(wn, /* file name */ |
| GENERIC_READ, /* access mode */ |
| ! 0, /* share mode */ |
| NULL, /* security descriptor */ |
| OPEN_EXISTING, /* creation disposition */ |
| ! 0, /* file attributes */ |
| NULL); /* handle to template file */ |
| if (hFile == INVALID_HANDLE_VALUE |
| ! && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) |
| { |
| /* Retry with non-wide function (for Windows 98). */ |
| vim_free(wn); |
| --- 2645,2688 ---- |
| 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 = 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 */ |
| ! FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */ |
| NULL, /* security descriptor */ |
| OPEN_EXISTING, /* creation disposition */ |
| ! FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */ |
| NULL); /* handle to template file */ |
| if (hFile == INVALID_HANDLE_VALUE |
| ! && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) |
| { |
| /* Retry with non-wide function (for Windows 98). */ |
| vim_free(wn); |
| |
| *** 2674,2690 **** |
| #endif |
| hFile = CreateFile(fname, /* file name */ |
| GENERIC_READ, /* access mode */ |
| ! 0, /* share mode */ |
| NULL, /* security descriptor */ |
| OPEN_EXISTING, /* creation disposition */ |
| ! 0, /* file attributes */ |
| NULL); /* handle to template file */ |
| |
| if (hFile != INVALID_HANDLE_VALUE) |
| { |
| ! if (GetFileInformationByHandle(hFile, &inf) != 0 |
| ! && inf.nNumberOfLinks > 1) |
| ! res = 1; |
| CloseHandle(hFile); |
| } |
| |
| --- 2693,2710 ---- |
| #endif |
| hFile = CreateFile(fname, /* file name */ |
| GENERIC_READ, /* access mode */ |
| ! FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */ |
| NULL, /* security descriptor */ |
| OPEN_EXISTING, /* creation disposition */ |
| ! FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */ |
| NULL); /* handle to template file */ |
| |
| if (hFile != INVALID_HANDLE_VALUE) |
| { |
| ! if (GetFileInformationByHandle(hFile, info) != 0) |
| ! res = FILEINFO_OK; |
| ! else |
| ! res = FILEINFO_INFO_FAIL; |
| CloseHandle(hFile); |
| } |
| |
| |
| |
| |
| *** 21,26 **** |
| --- 21,27 ---- |
| 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)); |
| |
| |
| |
| *** 2217,2220 **** |
| --- 2217,2226 ---- |
| #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 */ |
| |
| |
| |
| *** 716,717 **** |
| --- 716,719 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 172, |
| /**/ |
| |
| -- |
| Q: What is a patch 22? |
| A: A patch you need to include to make it possible to include patches. |
| |
| /// Bram Moolenaar -- Bram@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 /// |