mirror of
https://github.com/vim/vim.git
synced 2025-09-06 21:53:38 -04:00
updated for version 7.3.1182
Problem: 'backupcopy' default on MS-Windows does not work for hard and soft links. Solution: Check for links. (David Pope, Ken Takata)
This commit is contained in:
parent
2a876e40ce
commit
12b559e7c3
14
src/fileio.c
14
src/fileio.c
@ -3780,12 +3780,12 @@ buf_write(buf, fname, sfname, start, end, eap, append, forceit,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef UNIX
|
|
||||||
/*
|
/*
|
||||||
* Break symlinks and/or hardlinks if we've been asked to.
|
* Break symlinks and/or hardlinks if we've been asked to.
|
||||||
*/
|
*/
|
||||||
if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
|
if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
|
||||||
{
|
{
|
||||||
|
# ifdef UNIX
|
||||||
int lstat_res;
|
int lstat_res;
|
||||||
|
|
||||||
lstat_res = mch_lstat((char *)fname, &st);
|
lstat_res = mch_lstat((char *)fname, &st);
|
||||||
@ -3801,8 +3801,18 @@ buf_write(buf, fname, sfname, start, end, eap, append, forceit,
|
|||||||
&& st_old.st_nlink > 1
|
&& st_old.st_nlink > 1
|
||||||
&& (lstat_res != 0 || st.st_ino == st_old.st_ino))
|
&& (lstat_res != 0 || st.st_ino == st_old.st_ino))
|
||||||
backup_copy = FALSE;
|
backup_copy = FALSE;
|
||||||
|
# else
|
||||||
|
# if defined(WIN32)
|
||||||
|
/* Symlinks. */
|
||||||
|
if ((bkc_flags & BKC_BREAKSYMLINK) && mch_is_symbolic_link(fname))
|
||||||
|
backup_copy = FALSE;
|
||||||
|
|
||||||
|
/* Hardlinks. */
|
||||||
|
if ((bkc_flags & BKC_BREAKHARDLINK) && mch_is_hard_link(fname))
|
||||||
|
backup_copy = FALSE;
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
276
src/os_win32.c
276
src/os_win32.c
@ -78,6 +78,16 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reparse Point
|
||||||
|
*/
|
||||||
|
#ifndef FILE_ATTRIBUTE_REPARSE_POINT
|
||||||
|
# define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
||||||
|
#endif
|
||||||
|
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||||
|
# define IO_REPARSE_TAG_SYMLINK 0xA000000C
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Record all output and all keyboard & mouse input */
|
/* Record all output and all keyboard & mouse input */
|
||||||
/* #define MCH_WRITE_DUMP */
|
/* #define MCH_WRITE_DUMP */
|
||||||
|
|
||||||
@ -219,6 +229,10 @@ static int need_vimrun_warning = FALSE;
|
|||||||
static char *vimrun_path = "vimrun ";
|
static char *vimrun_path = "vimrun ";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int win32_getattrs(char_u *name);
|
||||||
|
static int win32_setattrs(char_u *name, int attrs);
|
||||||
|
static int win32_set_archive(char_u *name);
|
||||||
|
|
||||||
#ifndef FEAT_GUI_W32
|
#ifndef FEAT_GUI_W32
|
||||||
static int suppress_winsize = 1; /* don't fiddle with console */
|
static int suppress_winsize = 1; /* don't fiddle with console */
|
||||||
#endif
|
#endif
|
||||||
@ -2623,57 +2637,54 @@ mch_dirname(
|
|||||||
/*
|
/*
|
||||||
* get file permissions for `name'
|
* get file permissions for `name'
|
||||||
* -1 : error
|
* -1 : error
|
||||||
* else FILE_ATTRIBUTE_* defined in winnt.h
|
* else mode_t
|
||||||
*/
|
*/
|
||||||
long
|
long
|
||||||
mch_getperm(char_u *name)
|
mch_getperm(char_u *name)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_MBYTE
|
struct stat st;
|
||||||
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
int n;
|
||||||
{
|
|
||||||
WCHAR *p = enc_to_utf16(name, NULL);
|
|
||||||
long n;
|
|
||||||
|
|
||||||
if (p != NULL)
|
n = mch_stat(name, &st);
|
||||||
{
|
return n == 0 ? (int)st.st_mode : -1;
|
||||||
n = (long)GetFileAttributesW(p);
|
|
||||||
vim_free(p);
|
|
||||||
if (n >= 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
|
|
||||||
return n;
|
|
||||||
/* Retry with non-wide function (for Windows 98). */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (long)GetFileAttributes((char *)name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set file permission for `name' to `perm'
|
* set file permission for `name' to `perm'
|
||||||
|
*
|
||||||
|
* return FAIL for failure, OK otherwise
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mch_setperm(
|
mch_setperm(
|
||||||
char_u *name,
|
char_u *name,
|
||||||
long perm)
|
long perm)
|
||||||
{
|
{
|
||||||
perm |= FILE_ATTRIBUTE_ARCHIVE; /* file has changed, set archive bit */
|
long n;
|
||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
|
WCHAR *p;
|
||||||
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
{
|
{
|
||||||
WCHAR *p = enc_to_utf16(name, NULL);
|
p = enc_to_utf16(name, NULL);
|
||||||
long n;
|
|
||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
{
|
{
|
||||||
n = (long)SetFileAttributesW(p, perm);
|
n = _wchmod(p, perm);
|
||||||
vim_free(p);
|
vim_free(p);
|
||||||
if (n || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
|
if (n == -1 && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
return n ? OK : FAIL;
|
return FAIL;
|
||||||
/* Retry with non-wide function (for Windows 98). */
|
/* Retry with non-wide function (for Windows 98). */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (p == NULL)
|
||||||
#endif
|
#endif
|
||||||
return SetFileAttributes((char *)name, perm) ? OK : FAIL;
|
n = _chmod(name, perm);
|
||||||
|
if (n == -1)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
win32_set_archive(name);
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2682,49 +2693,12 @@ mch_setperm(
|
|||||||
void
|
void
|
||||||
mch_hide(char_u *name)
|
mch_hide(char_u *name)
|
||||||
{
|
{
|
||||||
int perm;
|
int attrs = win32_getattrs(name);
|
||||||
#ifdef FEAT_MBYTE
|
if (attrs == -1)
|
||||||
WCHAR *p = NULL;
|
return;
|
||||||
|
|
||||||
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
attrs |= FILE_ATTRIBUTE_HIDDEN;
|
||||||
p = enc_to_utf16(name, NULL);
|
win32_setattrs(name, attrs);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FEAT_MBYTE
|
|
||||||
if (p != NULL)
|
|
||||||
{
|
|
||||||
perm = GetFileAttributesW(p);
|
|
||||||
if (perm < 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
/* Retry with non-wide function (for Windows 98). */
|
|
||||||
vim_free(p);
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p == NULL)
|
|
||||||
#endif
|
|
||||||
perm = GetFileAttributes((char *)name);
|
|
||||||
if (perm >= 0)
|
|
||||||
{
|
|
||||||
perm |= FILE_ATTRIBUTE_HIDDEN;
|
|
||||||
#ifdef FEAT_MBYTE
|
|
||||||
if (p != NULL)
|
|
||||||
{
|
|
||||||
if (SetFileAttributesW(p, perm) == 0
|
|
||||||
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
/* Retry with non-wide function (for Windows 98). */
|
|
||||||
vim_free(p);
|
|
||||||
p = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p == NULL)
|
|
||||||
#endif
|
|
||||||
SetFileAttributes((char *)name, perm);
|
|
||||||
}
|
|
||||||
#ifdef FEAT_MBYTE
|
|
||||||
vim_free(p);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2734,7 +2708,7 @@ mch_hide(char_u *name)
|
|||||||
int
|
int
|
||||||
mch_isdir(char_u *name)
|
mch_isdir(char_u *name)
|
||||||
{
|
{
|
||||||
int f = mch_getperm(name);
|
int f = win32_getattrs(name);
|
||||||
|
|
||||||
if (f == -1)
|
if (f == -1)
|
||||||
return FALSE; /* file does not exist at all */
|
return FALSE; /* file does not exist at all */
|
||||||
@ -2770,7 +2744,7 @@ mch_mkdir(char_u *name)
|
|||||||
* Return TRUE if file "fname" has more than one link.
|
* Return TRUE if file "fname" has more than one link.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mch_is_linked(char_u *fname)
|
mch_is_hard_link(char_u *fname)
|
||||||
{
|
{
|
||||||
BY_HANDLE_FILE_INFORMATION info;
|
BY_HANDLE_FILE_INFORMATION info;
|
||||||
|
|
||||||
@ -2778,6 +2752,74 @@ mch_is_linked(char_u *fname)
|
|||||||
&& info.nNumberOfLinks > 1;
|
&& info.nNumberOfLinks > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if file "fname" is a symbolic link.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mch_is_symbolic_link(char_u *fname)
|
||||||
|
{
|
||||||
|
HANDLE hFind;
|
||||||
|
int res = FALSE;
|
||||||
|
WIN32_FIND_DATAA findDataA;
|
||||||
|
DWORD fileFlags = 0, reparseTag = 0;
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
|
WCHAR *wn = NULL;
|
||||||
|
WIN32_FIND_DATAW findDataW;
|
||||||
|
|
||||||
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
|
wn = enc_to_utf16(fname, NULL);
|
||||||
|
if (wn != NULL)
|
||||||
|
{
|
||||||
|
hFind = FindFirstFileW(wn, &findDataW);
|
||||||
|
vim_free(wn);
|
||||||
|
if (hFind == INVALID_HANDLE_VALUE
|
||||||
|
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
/* Retry with non-wide function (for Windows 98). */
|
||||||
|
hFind = FindFirstFile(fname, &findDataA);
|
||||||
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
fileFlags = findDataA.dwFileAttributes;
|
||||||
|
reparseTag = findDataA.dwReserved0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileFlags = findDataW.dwFileAttributes;
|
||||||
|
reparseTag = findDataW.dwReserved0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
hFind = FindFirstFile(fname, &findDataA);
|
||||||
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
fileFlags = findDataA.dwFileAttributes;
|
||||||
|
reparseTag = findDataA.dwReserved0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
|
FindClose(hFind);
|
||||||
|
|
||||||
|
if ((fileFlags & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
|
&& reparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||||
|
res = TRUE;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if file "fname" has more than one link or if it is a symbolic
|
||||||
|
* link.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mch_is_linked(char_u *fname)
|
||||||
|
{
|
||||||
|
if (mch_is_hard_link(fname) || mch_is_symbolic_link(fname))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the by-handle-file-information for "fname".
|
* Get the by-handle-file-information for "fname".
|
||||||
* Returns FILEINFO_OK when OK.
|
* Returns FILEINFO_OK when OK.
|
||||||
@ -2841,6 +2883,92 @@ win32_fileinfo(char_u *fname, BY_HANDLE_FILE_INFORMATION *info)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get file attributes for `name'
|
||||||
|
* -1 : error
|
||||||
|
* else FILE_ATTRIBUTE_* defined in winnt.h
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int
|
||||||
|
win32_getattrs(char_u *name)
|
||||||
|
{
|
||||||
|
int attr;
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
|
WCHAR *p = NULL;
|
||||||
|
|
||||||
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
|
p = enc_to_utf16(name, NULL);
|
||||||
|
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
attr = GetFileAttributesW(p);
|
||||||
|
if (attr < 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
/* Retry with non-wide function (for Windows 98). */
|
||||||
|
vim_free(p);
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p == NULL)
|
||||||
|
#endif
|
||||||
|
attr = GetFileAttributes((char *)name);
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
|
vim_free(p);
|
||||||
|
#endif
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set file attributes for `name' to `attrs'
|
||||||
|
*
|
||||||
|
* return -1 for failure, 0 otherwise
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int
|
||||||
|
win32_setattrs(char_u *name, int attrs)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
|
WCHAR *p = NULL;
|
||||||
|
|
||||||
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
|
p = enc_to_utf16(name, NULL);
|
||||||
|
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
res = SetFileAttributesW(p, attrs);
|
||||||
|
if (res == FALSE
|
||||||
|
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
/* Retry with non-wide function (for Windows 98). */
|
||||||
|
vim_free(p);
|
||||||
|
p = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p == NULL)
|
||||||
|
#endif
|
||||||
|
res = SetFileAttributes((char *)name, attrs);
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
|
vim_free(p);
|
||||||
|
#endif
|
||||||
|
return res ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set archive flag for "name".
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int
|
||||||
|
win32_set_archive(char_u *name)
|
||||||
|
{
|
||||||
|
int attrs = win32_getattrs(name);
|
||||||
|
if (attrs == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
attrs |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
return win32_setattrs(name, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return TRUE if file or directory "name" is writable (not readonly).
|
* Return TRUE if file or directory "name" is writable (not readonly).
|
||||||
* Strange semantics of Win32: a readonly directory is writable, but you can't
|
* Strange semantics of Win32: a readonly directory is writable, but you can't
|
||||||
@ -2849,10 +2977,10 @@ win32_fileinfo(char_u *fname, BY_HANDLE_FILE_INFORMATION *info)
|
|||||||
int
|
int
|
||||||
mch_writable(char_u *name)
|
mch_writable(char_u *name)
|
||||||
{
|
{
|
||||||
int perm = mch_getperm(name);
|
int attrs = win32_getattrs(name);
|
||||||
|
|
||||||
return (perm != -1 && (!(perm & FILE_ATTRIBUTE_READONLY)
|
return (attrs != -1 && (!(attrs & FILE_ATTRIBUTE_READONLY)
|
||||||
|| (perm & FILE_ATTRIBUTE_DIRECTORY)));
|
|| (attrs & FILE_ATTRIBUTE_DIRECTORY)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5012,13 +5140,16 @@ mch_remove(char_u *name)
|
|||||||
#ifdef FEAT_MBYTE
|
#ifdef FEAT_MBYTE
|
||||||
WCHAR *wn = NULL;
|
WCHAR *wn = NULL;
|
||||||
int n;
|
int n;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
win32_setattrs(name, FILE_ATTRIBUTE_NORMAL);
|
||||||
|
|
||||||
|
#ifdef FEAT_MBYTE
|
||||||
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||||
{
|
{
|
||||||
wn = enc_to_utf16(name, NULL);
|
wn = enc_to_utf16(name, NULL);
|
||||||
if (wn != NULL)
|
if (wn != NULL)
|
||||||
{
|
{
|
||||||
SetFileAttributesW(wn, FILE_ATTRIBUTE_NORMAL);
|
|
||||||
n = DeleteFileW(wn) ? 0 : -1;
|
n = DeleteFileW(wn) ? 0 : -1;
|
||||||
vim_free(wn);
|
vim_free(wn);
|
||||||
if (n == 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
|
if (n == 0 || GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
@ -5027,7 +5158,6 @@ mch_remove(char_u *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SetFileAttributes(name, FILE_ATTRIBUTE_NORMAL);
|
|
||||||
return DeleteFile(name) ? 0 : -1;
|
return DeleteFile(name) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ int mch_setperm __ARGS((char_u *name, long perm));
|
|||||||
void mch_hide __ARGS((char_u *name));
|
void mch_hide __ARGS((char_u *name));
|
||||||
int mch_isdir __ARGS((char_u *name));
|
int mch_isdir __ARGS((char_u *name));
|
||||||
int mch_mkdir __ARGS((char_u *name));
|
int mch_mkdir __ARGS((char_u *name));
|
||||||
|
int mch_is_hard_link __ARGS((char_u *fname));
|
||||||
|
int mch_is_symbolic_link __ARGS((char_u *fname));
|
||||||
int mch_is_linked __ARGS((char_u *fname));
|
int mch_is_linked __ARGS((char_u *fname));
|
||||||
int win32_fileinfo __ARGS((char_u *fname, BY_HANDLE_FILE_INFORMATION *info));
|
int win32_fileinfo __ARGS((char_u *fname, BY_HANDLE_FILE_INFORMATION *info));
|
||||||
int mch_writable __ARGS((char_u *name));
|
int mch_writable __ARGS((char_u *name));
|
||||||
|
@ -728,6 +728,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1182,
|
||||||
/**/
|
/**/
|
||||||
1181,
|
1181,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user