Skip to content

Commit 6fff088

Browse files
committed
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)
1 parent e5ad1c0 commit 6fff088

File tree

6 files changed

+59
-20
lines changed

6 files changed

+59
-20
lines changed

src/fileio.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6555,6 +6555,21 @@ vim_rename(from, to)
65556555
use_tmp_file = TRUE;
65566556
}
65576557
#endif
6558+
#ifdef WIN3264
6559+
{
6560+
BY_HANDLE_FILE_INFORMATION info1, info2;
6561+
6562+
/* It's possible for the source and destination to be the same file.
6563+
* In that case go through a temp file name. This makes rename("foo",
6564+
* "./foo") a no-op (in a complicated way). */
6565+
if (win32_fileinfo(from, &info1) == FILEINFO_OK
6566+
&& win32_fileinfo(to, &info2) == FILEINFO_OK
6567+
&& info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
6568+
&& info1.nFileIndexHigh == info2.nFileIndexHigh
6569+
&& info1.nFileIndexLow == info2.nFileIndexLow)
6570+
use_tmp_file = TRUE;
6571+
}
6572+
#endif
65586573

65596574
#if defined(UNIX) || defined(CASE_INSENSITIVE_FILENAME)
65606575
if (use_tmp_file)

src/if_cscope.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,17 +1412,15 @@ cs_insert_filelist(fname, ppath, flags, sb)
14121412
{
14131413
short i, j;
14141414
#ifndef UNIX
1415-
HANDLE hFile;
14161415
BY_HANDLE_FILE_INFORMATION bhfi;
14171416

1418-
vim_memset(&bhfi, 0, sizeof(bhfi));
14191417
/* On windows 9x GetFileInformationByHandle doesn't work, so skip it */
14201418
if (!mch_windows95())
14211419
{
1422-
hFile = CreateFile(fname, FILE_READ_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
1423-
FILE_ATTRIBUTE_NORMAL, NULL);
1424-
if (hFile == INVALID_HANDLE_VALUE)
1420+
switch (win32_fileinfo(fname, &bhfi))
14251421
{
1422+
case FILEINFO_ENC_FAIL: /* enc_to_utf16() failed */
1423+
case FILEINFO_READ_FAIL: /* CreateFile() failed */
14261424
if (p_csverbose)
14271425
{
14281426
char *cant_msg = _("E625: cannot open cscope database: %s");
@@ -1438,15 +1436,12 @@ cs_insert_filelist(fname, ppath, flags, sb)
14381436
(void)EMSG2(cant_msg, fname);
14391437
}
14401438
return -1;
1441-
}
1442-
if (!GetFileInformationByHandle(hFile, &bhfi))
1443-
{
1444-
CloseHandle(hFile);
1439+
1440+
case FILEINFO_INFO_FAIL: /* GetFileInformationByHandle() failed */
14451441
if (p_csverbose)
14461442
(void)EMSG(_("E626: cannot get cscope database information"));
14471443
return -1;
14481444
}
1449-
CloseHandle(hFile);
14501445
}
14511446
#endif
14521447

src/os_win32.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,26 +2644,45 @@ mch_isdir(char_u *name)
26442644
*/
26452645
int
26462646
mch_is_linked(char_u *fname)
2647+
{
2648+
BY_HANDLE_FILE_INFORMATION info;
2649+
2650+
return win32_fileinfo(fname, &info) == FILEINFO_OK
2651+
&& info.nNumberOfLinks > 1;
2652+
}
2653+
2654+
/*
2655+
* Get the by-handle-file-information for "fname".
2656+
* Returns FILEINFO_OK when OK.
2657+
* returns FILEINFO_ENC_FAIL when enc_to_utf16() failed.
2658+
* Returns FILEINFO_READ_FAIL when CreateFile() failed.
2659+
* Returns FILEINFO_INFO_FAIL when GetFileInformationByHandle() failed.
2660+
*/
2661+
int
2662+
win32_fileinfo(char_u *fname, BY_HANDLE_FILE_INFORMATION *info)
26472663
{
26482664
HANDLE hFile;
2649-
int res = 0;
2650-
BY_HANDLE_FILE_INFORMATION inf;
2665+
int res = FILEINFO_READ_FAIL;
26512666
#ifdef FEAT_MBYTE
26522667
WCHAR *wn = NULL;
26532668

26542669
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
2670+
{
26552671
wn = enc_to_utf16(fname, NULL);
2672+
if (wn == NULL)
2673+
res = FILEINFO_ENC_FAIL;
2674+
}
26562675
if (wn != NULL)
26572676
{
26582677
hFile = CreateFileW(wn, /* file name */
26592678
GENERIC_READ, /* access mode */
2660-
0, /* share mode */
2679+
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
26612680
NULL, /* security descriptor */
26622681
OPEN_EXISTING, /* creation disposition */
2663-
0, /* file attributes */
2682+
FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
26642683
NULL); /* handle to template file */
26652684
if (hFile == INVALID_HANDLE_VALUE
2666-
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2685+
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
26672686
{
26682687
/* Retry with non-wide function (for Windows 98). */
26692688
vim_free(wn);
@@ -2674,17 +2693,18 @@ mch_is_linked(char_u *fname)
26742693
#endif
26752694
hFile = CreateFile(fname, /* file name */
26762695
GENERIC_READ, /* access mode */
2677-
0, /* share mode */
2696+
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
26782697
NULL, /* security descriptor */
26792698
OPEN_EXISTING, /* creation disposition */
2680-
0, /* file attributes */
2699+
FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
26812700
NULL); /* handle to template file */
26822701

26832702
if (hFile != INVALID_HANDLE_VALUE)
26842703
{
2685-
if (GetFileInformationByHandle(hFile, &inf) != 0
2686-
&& inf.nNumberOfLinks > 1)
2687-
res = 1;
2704+
if (GetFileInformationByHandle(hFile, info) != 0)
2705+
res = FILEINFO_OK;
2706+
else
2707+
res = FILEINFO_INFO_FAIL;
26882708
CloseHandle(hFile);
26892709
}
26902710

src/proto/os_win32.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ int mch_setperm __ARGS((char_u *name, long perm));
2121
void mch_hide __ARGS((char_u *name));
2222
int mch_isdir __ARGS((char_u *name));
2323
int mch_is_linked __ARGS((char_u *fname));
24+
int win32_fileinfo __ARGS((char_u *name, BY_HANDLE_FILE_INFORMATION *lpFileInfo));
2425
int mch_writable __ARGS((char_u *name));
2526
int mch_can_exe __ARGS((char_u *name));
2627
int mch_nodetype __ARGS((char_u *name));

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ static char *(features[]) =
714714

715715
static int included_patches[] =
716716
{ /* Add new patch number below this line */
717+
/**/
718+
172,
717719
/**/
718720
171,
719721
/**/

src/vim.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,4 +2217,10 @@ typedef int VimClipboard; /* This is required for the prototypes. */
22172217
#define KEYLEN_PART_MAP -2 /* keylen value for incomplete mapping */
22182218
#define KEYLEN_REMOVED 9999 /* keylen value for removed sequence */
22192219

2220+
/* Return values from win32_fileinfo(). */
2221+
#define FILEINFO_OK 0
2222+
#define FILEINFO_ENC_FAIL 1 /* enc_to_utf16() failed */
2223+
#define FILEINFO_READ_FAIL 2 /* CreateFile() failed */
2224+
#define FILEINFO_INFO_FAIL 3 /* GetFileInformationByHandle() failed */
2225+
22202226
#endif /* VIM__H */

0 commit comments

Comments
 (0)