To: vim_dev@googlegroups.com Subject: Patch 7.3.172 Fcc: outbox From: Bram Moolenaar 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 *** ../vim-7.3.171/src/if_cscope.c 2011-03-03 15:01:25.000000000 +0100 --- src/if_cscope.c 2011-05-05 16:16:38.000000000 +0200 *************** *** 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 *** ../vim-7.3.171/src/fileio.c 2011-04-11 21:35:03.000000000 +0200 --- src/fileio.c 2011-05-05 16:22:22.000000000 +0200 *************** *** 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) *** ../vim-7.3.171/src/os_win32.c 2011-02-01 13:48:47.000000000 +0100 --- src/os_win32.c 2011-05-05 16:24:17.000000000 +0200 *************** *** 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); } *** ../vim-7.3.171/src/proto/os_win32.pro 2010-10-23 14:02:48.000000000 +0200 --- src/proto/os_win32.pro 2011-05-05 16:17:42.000000000 +0200 *************** *** 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)); *** ../vim-7.3.171/src/vim.h 2011-04-11 21:35:03.000000000 +0200 --- src/vim.h 2011-05-05 16:16:57.000000000 +0200 *************** *** 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 */ *** ../vim-7.3.171/src/version.c 2011-05-05 14:26:37.000000000 +0200 --- src/version.c 2011-05-05 16:39:35.000000000 +0200 *************** *** 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 ///