* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop
directory attribute for reparse points to avoid mistreating. (fhandler_base::fstat_by_name): Ditto. * path.cc (symlink_info::check_reparse_point): New method testing reparse points for symbolic links. (symlink_info::check_shortcut): Move file attribute tesat to calling function. (symlink_info::check): Add handling for reparse points. * path.h (enum path_types): Add PATH_REP to denote reparse point based symlinks. (path_conv::is_rep_symlink): New method. * syscalls.cc (unlink): Handle reparse points.
This commit is contained in:
parent
3ddf69712b
commit
9740f34d11
@ -1,3 +1,18 @@
|
|||||||
|
2006-10-31 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop
|
||||||
|
directory attribute for reparse points to avoid mistreating.
|
||||||
|
(fhandler_base::fstat_by_name): Ditto.
|
||||||
|
* path.cc (symlink_info::check_reparse_point): New method testing
|
||||||
|
reparse points for symbolic links.
|
||||||
|
(symlink_info::check_shortcut): Move file attribute tesat to calling
|
||||||
|
function.
|
||||||
|
(symlink_info::check): Add handling for reparse points.
|
||||||
|
* path.h (enum path_types): Add PATH_REP to denote reparse point based
|
||||||
|
symlinks.
|
||||||
|
(path_conv::is_rep_symlink): New method.
|
||||||
|
* syscalls.cc (unlink): Handle reparse points.
|
||||||
|
|
||||||
2006-10-27 Corinna Vinschen <corinna@vinschen.de>
|
2006-10-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* shared.cc (open_shared): Drop useless attempt from 2006-08-11.
|
* shared.cc (open_shared): Drop useless attempt from 2006-08-11.
|
||||||
|
@ -240,6 +240,8 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
|
|||||||
/* If the change time is 0, it's a file system which doesn't
|
/* If the change time is 0, it's a file system which doesn't
|
||||||
support a change timestamp. In that case use the LastWriteTime
|
support a change timestamp. In that case use the LastWriteTime
|
||||||
entry, as in other calls to fstat_helper. */
|
entry, as in other calls to fstat_helper. */
|
||||||
|
if (pc.is_rep_symlink ())
|
||||||
|
pfai->BasicInformation.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
pc.file_attributes (pfai->BasicInformation.FileAttributes);
|
pc.file_attributes (pfai->BasicInformation.FileAttributes);
|
||||||
return fstat_helper (buf,
|
return fstat_helper (buf,
|
||||||
pfai->BasicInformation.ChangeTime.QuadPart ?
|
pfai->BasicInformation.ChangeTime.QuadPart ?
|
||||||
@ -275,7 +277,11 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
|
|||||||
local.dwFileAttributes = DWORD (pc);
|
local.dwFileAttributes = DWORD (pc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pc.file_attributes (local.dwFileAttributes);
|
{
|
||||||
|
if (pc.is_rep_symlink ())
|
||||||
|
local.dwFileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
pc.file_attributes (local.dwFileAttributes);
|
||||||
|
}
|
||||||
return fstat_helper (buf,
|
return fstat_helper (buf,
|
||||||
local.ftLastWriteTime, /* see fstat_helper comment */
|
local.ftLastWriteTime, /* see fstat_helper comment */
|
||||||
local.ftLastAccessTime,
|
local.ftLastAccessTime,
|
||||||
@ -306,6 +312,8 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
|
|||||||
else if ((handle = FindFirstFile (pc, &local)) != INVALID_HANDLE_VALUE)
|
else if ((handle = FindFirstFile (pc, &local)) != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
FindClose (handle);
|
FindClose (handle);
|
||||||
|
if (pc.is_rep_symlink ())
|
||||||
|
local.dwFileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
pc.file_attributes (local.dwFileAttributes);
|
pc.file_attributes (local.dwFileAttributes);
|
||||||
res = fstat_helper (buf,
|
res = fstat_helper (buf,
|
||||||
local.ftLastWriteTime, /* see fstat_helper comment */
|
local.ftLastWriteTime, /* see fstat_helper comment */
|
||||||
|
@ -104,6 +104,7 @@ struct symlink_info
|
|||||||
bool case_check (char *path);
|
bool case_check (char *path);
|
||||||
int check_sysfile (const char *path, HANDLE h);
|
int check_sysfile (const char *path, HANDLE h);
|
||||||
int check_shortcut (const char *path, HANDLE h);
|
int check_shortcut (const char *path, HANDLE h);
|
||||||
|
int check_reparse_point (const char *path, HANDLE h);
|
||||||
bool set_error (int);
|
bool set_error (int);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2996,10 +2997,6 @@ symlink_info::check_shortcut (const char *path, HANDLE h)
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
DWORD size, got = 0;
|
DWORD size, got = 0;
|
||||||
|
|
||||||
/* Valid Cygwin & U/WIN shortcuts are R/O. */
|
|
||||||
if (!(fileattr & FILE_ATTRIBUTE_READONLY))
|
|
||||||
goto file_not_symlink;
|
|
||||||
|
|
||||||
if ((size = GetFileSize (h, NULL)) > 8192) /* Not a Cygwin symlink. */
|
if ((size = GetFileSize (h, NULL)) > 8192) /* Not a Cygwin symlink. */
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
buf = (char *) alloca (size);
|
buf = (char *) alloca (size);
|
||||||
@ -3033,7 +3030,6 @@ close_it:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
symlink_info::check_sysfile (const char *path, HANDLE h)
|
symlink_info::check_sysfile (const char *path, HANDLE h)
|
||||||
{
|
{
|
||||||
@ -3093,6 +3089,61 @@ symlink_info::check_sysfile (const char *path, HANDLE h)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
symlink_info::check_reparse_point (const char *path, HANDLE h)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
|
||||||
|
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
if (!DeviceIoControl (h, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID) rp,
|
||||||
|
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, NULL))
|
||||||
|
{
|
||||||
|
debug_printf ("DeviceIoControl(FSCTL_GET_REPARSE_POINT) failed, %E");
|
||||||
|
set_error (EIO);
|
||||||
|
goto close_it;
|
||||||
|
}
|
||||||
|
if (rp->ReparseTag == IO_REPARSE_TAG_SYMLINK)
|
||||||
|
{
|
||||||
|
if (rp->SymbolicLinkReparseBuffer.PrintNameLength > 2 * CYG_MAX_PATH)
|
||||||
|
{
|
||||||
|
debug_printf ("Symlink name too long");
|
||||||
|
set_error (EIO);
|
||||||
|
goto close_it;
|
||||||
|
}
|
||||||
|
res = sys_wcstombs (contents, CYG_MAX_PATH,
|
||||||
|
(WCHAR *)((char *)rp->SymbolicLinkReparseBuffer.PathBuffer
|
||||||
|
+ rp->SymbolicLinkReparseBuffer.PrintNameOffset),
|
||||||
|
rp->SymbolicLinkReparseBuffer.PrintNameLength / 2);
|
||||||
|
pflags = PATH_SYMLINK | PATH_REP;
|
||||||
|
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
}
|
||||||
|
else if (rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
|
||||||
|
{
|
||||||
|
if (rp->SymbolicLinkReparseBuffer.PrintNameLength == 0)
|
||||||
|
{
|
||||||
|
/* Likely a volume mount point. Not treated as symlink. */
|
||||||
|
goto close_it;
|
||||||
|
}
|
||||||
|
if (rp->MountPointReparseBuffer.PrintNameLength > 2 * CYG_MAX_PATH)
|
||||||
|
{
|
||||||
|
debug_printf ("Symlink name too long");
|
||||||
|
set_error (EIO);
|
||||||
|
goto close_it;
|
||||||
|
}
|
||||||
|
res = sys_wcstombs (contents, CYG_MAX_PATH,
|
||||||
|
(WCHAR *)((char *)rp->MountPointReparseBuffer.PathBuffer
|
||||||
|
+ rp->MountPointReparseBuffer.PrintNameOffset),
|
||||||
|
rp->MountPointReparseBuffer.PrintNameLength / 2);
|
||||||
|
pflags = PATH_SYMLINK | PATH_REP;
|
||||||
|
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
}
|
||||||
|
close_it:
|
||||||
|
CloseHandle (h);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SCAN_BEG,
|
SCAN_BEG,
|
||||||
@ -3337,26 +3388,35 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
|
|
||||||
sym_check = 0;
|
sym_check = 0;
|
||||||
|
|
||||||
if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
|
if ((fileattr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))
|
||||||
|
== FILE_ATTRIBUTE_DIRECTORY)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
/* Windows shortcuts are treated as symlinks. */
|
/* Reparse points are potentially symlinks. */
|
||||||
if (suffix.lnk_match ())
|
if (fileattr & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
sym_check = 1;
|
sym_check = 3;
|
||||||
|
|
||||||
/* This is the old Cygwin method creating symlinks: */
|
/* This is the old Cygwin method creating symlinks: */
|
||||||
/* A symlink will have the `system' file attribute. */
|
/* A symlink will have the `system' file attribute. */
|
||||||
/* Only files can be symlinks (which can be symlinks to directories). */
|
/* Only files can be symlinks (which can be symlinks to directories). */
|
||||||
if (fileattr & FILE_ATTRIBUTE_SYSTEM)
|
else if (fileattr & FILE_ATTRIBUTE_SYSTEM)
|
||||||
sym_check = 2;
|
sym_check = 2;
|
||||||
|
|
||||||
|
/* Windows shortcuts are potentially treated as symlinks. */
|
||||||
|
/* Valid Cygwin & U/WIN shortcuts are R/O. */
|
||||||
|
else if ((fileattr & FILE_ATTRIBUTE_READONLY) && suffix.lnk_match ())
|
||||||
|
sym_check = 1;
|
||||||
|
|
||||||
if (!sym_check)
|
if (!sym_check)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
/* Open the file. */
|
/* Open the file. */
|
||||||
|
|
||||||
h = CreateFile (suffix.path, GENERIC_READ, FILE_SHARE_READ,
|
h = CreateFile (suffix.path, GENERIC_READ, FILE_SHARE_READ,
|
||||||
&sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
&sec_none_nih, OPEN_EXISTING,
|
||||||
|
sym_check == 3 ? FILE_FLAG_OPEN_REPARSE_POINT
|
||||||
|
| FILE_FLAG_BACKUP_SEMANTICS
|
||||||
|
: FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
res = -1;
|
res = -1;
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
@ -3383,6 +3443,11 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
if (!res)
|
if (!res)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
res = check_reparse_point (suffix.path, h);
|
||||||
|
if (!res)
|
||||||
|
goto file_not_symlink;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ enum path_types
|
|||||||
PATH_NO_ACCESS_CHECK = PC_NO_ACCESS_CHECK,
|
PATH_NO_ACCESS_CHECK = PC_NO_ACCESS_CHECK,
|
||||||
PATH_LNK = 0x01000000,
|
PATH_LNK = 0x01000000,
|
||||||
PATH_TEXT = 0x02000000,
|
PATH_TEXT = 0x02000000,
|
||||||
|
PATH_REP = 0x04000000,
|
||||||
PATH_HAS_SYMLINKS = 0x10000000,
|
PATH_HAS_SYMLINKS = 0x10000000,
|
||||||
PATH_SOCKET = 0x40000000
|
PATH_SOCKET = 0x40000000
|
||||||
};
|
};
|
||||||
@ -163,6 +164,7 @@ class path_conv
|
|||||||
}
|
}
|
||||||
int issymlink () const {return path_flags & PATH_SYMLINK;}
|
int issymlink () const {return path_flags & PATH_SYMLINK;}
|
||||||
int is_lnk_symlink () const {return path_flags & PATH_LNK;}
|
int is_lnk_symlink () const {return path_flags & PATH_LNK;}
|
||||||
|
int is_rep_symlink () const {return path_flags & PATH_REP;}
|
||||||
int isdevice () const {return dev.devn && dev.devn != FH_FS && dev.devn != FH_FIFO;}
|
int isdevice () const {return dev.devn && dev.devn != FH_FS && dev.devn != FH_FIFO;}
|
||||||
int isfifo () const {return dev == FH_FIFO;}
|
int isfifo () const {return dev == FH_FIFO;}
|
||||||
int isspecial () const {return dev.devn && dev.devn != FH_FS;}
|
int isspecial () const {return dev.devn && dev.devn != FH_FS;}
|
||||||
|
@ -205,8 +205,11 @@ unlink (const char *ourname)
|
|||||||
if (!win32_name.isremote () && wincap.has_delete_on_close ())
|
if (!win32_name.isremote () && wincap.has_delete_on_close ())
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
DWORD flags = FILE_FLAG_DELETE_ON_CLOSE;
|
||||||
|
if (win32_name.is_rep_symlink ())
|
||||||
|
flags |= FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS;
|
||||||
h = CreateFile (win32_name, 0, FILE_SHARE_READ, &sec_none_nih,
|
h = CreateFile (win32_name, 0, FILE_SHARE_READ, &sec_none_nih,
|
||||||
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
OPEN_EXISTING, flags, 0);
|
||||||
if (h != INVALID_HANDLE_VALUE)
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
if (wincap.has_hard_links () && setattrs)
|
if (wincap.has_hard_links () && setattrs)
|
||||||
@ -229,7 +232,12 @@ unlink (const char *ourname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try a delete with attributes reset */
|
/* Try a delete with attributes reset */
|
||||||
if (DeleteFile (win32_name))
|
if (win32_name.is_rep_symlink () && RemoveDirectory (win32_name))
|
||||||
|
{
|
||||||
|
syscall_printf ("RemoveDirectory after CreateFile/CloseHandle succeeded");
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
else if (DeleteFile (win32_name))
|
||||||
{
|
{
|
||||||
syscall_printf ("DeleteFile after CreateFile/CloseHandle succeeded");
|
syscall_printf ("DeleteFile after CreateFile/CloseHandle succeeded");
|
||||||
goto ok;
|
goto ok;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user