* path.cc (symlink_info::check_reparse_point): Use NtFsControlFile
to read reparse points. (enum shortcut_t): New type. (symlink_info::check): Convert sym_check to shortcut_t. Use shortcut_t enum values throughout. Check reparse point before checking for sysfile shortcut. Open reparse points with READ_CONTROL only to accommodate special Vista reparse points. Add comments.
This commit is contained in:
parent
5cb524ee7d
commit
3d0192def9
@ -1,3 +1,13 @@
|
|||||||
|
2008-04-02 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* path.cc (symlink_info::check_reparse_point): Use NtFsControlFile
|
||||||
|
to read reparse points.
|
||||||
|
(enum shortcut_t): New type.
|
||||||
|
(symlink_info::check): Convert sym_check to shortcut_t. Use shortcut_t
|
||||||
|
enum values throughout. Check reparse point before checking for
|
||||||
|
sysfile shortcut. Open reparse points with READ_CONTROL only to
|
||||||
|
accommodate special Vista reparse points. Add comments.
|
||||||
|
|
||||||
2008-04-02 Corinna Vinschen <corinna@vinschen.de>
|
2008-04-02 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* flock.cc (get_lock_parent_dir): Drop call to NtOpenDirectoryObject
|
* flock.cc (get_lock_parent_dir): Drop call to NtOpenDirectoryObject
|
||||||
|
@ -3487,15 +3487,19 @@ symlink_info::check_sysfile (HANDLE h)
|
|||||||
int
|
int
|
||||||
symlink_info::check_reparse_point (HANDLE h)
|
symlink_info::check_reparse_point (HANDLE h)
|
||||||
{
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
|
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
|
||||||
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||||
DWORD size;
|
|
||||||
char srcbuf[SYMLINK_MAX + 7];
|
char srcbuf[SYMLINK_MAX + 7];
|
||||||
|
|
||||||
if (!DeviceIoControl (h, FSCTL_GET_REPARSE_POINT, NULL, 0, (LPVOID) rp,
|
status = NtFsControlFile (h, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT,
|
||||||
MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, NULL))
|
NULL, 0, (LPVOID) rp,
|
||||||
|
MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
debug_printf ("DeviceIoControl(FSCTL_GET_REPARSE_POINT) failed, %E");
|
debug_printf ("NtFsControlFile(FSCTL_GET_REPARSE_POINT) failed, %p",
|
||||||
|
status);
|
||||||
set_error (EIO);
|
set_error (EIO);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3774,6 +3778,13 @@ symlink_info::parse_device (const char *contents)
|
|||||||
Return -1 on error, 0 if PATH is not a symlink, or the length
|
Return -1 on error, 0 if PATH is not a symlink, or the length
|
||||||
stored into BUF if PATH is a symlink. */
|
stored into BUF if PATH is a symlink. */
|
||||||
|
|
||||||
|
enum shortcut_t {
|
||||||
|
is_no_symlink,
|
||||||
|
is_shortcut_symlink,
|
||||||
|
is_reparse_symlink,
|
||||||
|
is_sysfile_symlink
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
||||||
{
|
{
|
||||||
@ -3896,9 +3907,9 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
|| (opt & PC_SYM_IGNORE))
|
|| (opt & PC_SYM_IGNORE))
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
int sym_check;
|
shortcut_t sym_check;
|
||||||
|
|
||||||
sym_check = 0;
|
sym_check = is_no_symlink;
|
||||||
|
|
||||||
if ((fileattr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))
|
if ((fileattr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))
|
||||||
== FILE_ATTRIBUTE_DIRECTORY)
|
== FILE_ATTRIBUTE_DIRECTORY)
|
||||||
@ -3907,35 +3918,45 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
/* Windows shortcuts are potentially treated as symlinks. */
|
/* Windows shortcuts are potentially treated as symlinks. */
|
||||||
/* Valid Cygwin & U/WIN shortcuts are R/O. */
|
/* Valid Cygwin & U/WIN shortcuts are R/O. */
|
||||||
if ((fileattr & FILE_ATTRIBUTE_READONLY) && suffix.lnk_match ())
|
if ((fileattr & FILE_ATTRIBUTE_READONLY) && suffix.lnk_match ())
|
||||||
sym_check = 1;
|
sym_check = is_shortcut_symlink;
|
||||||
|
|
||||||
|
/* Reparse points are potentially symlinks. This check must be
|
||||||
|
performed before checking the SYSTEM attribute for sysfile
|
||||||
|
symlinks, since reparse points can have this flag set, too.
|
||||||
|
For instance, Vista starts to create a couple of reparse points
|
||||||
|
with SYSTEM and HIDDEN flags set. */
|
||||||
|
else if (fileattr & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
|
sym_check = is_reparse_symlink;
|
||||||
|
|
||||||
/* 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). */
|
||||||
else if (fileattr & FILE_ATTRIBUTE_SYSTEM)
|
else if (fileattr & FILE_ATTRIBUTE_SYSTEM)
|
||||||
sym_check = 2;
|
sym_check = is_sysfile_symlink;
|
||||||
|
|
||||||
/* Reparse points are potentially symlinks. */
|
if (sym_check == is_no_symlink)
|
||||||
else if (fileattr & FILE_ATTRIBUTE_REPARSE_POINT)
|
|
||||||
sym_check = 3;
|
|
||||||
|
|
||||||
if (!sym_check)
|
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
res = -1;
|
res = -1;
|
||||||
|
|
||||||
/* Open the file. */
|
/* Open the file. Opening reparse points must not use GENERIC_READ.
|
||||||
status = NtOpenFile (&h, FILE_GENERIC_READ, &attr, &io,
|
The reason is that Vista starts to create a couple of reparse
|
||||||
FILE_SHARE_VALID_FLAGS,
|
points for backward compatibility, hidden system files, explicitely
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT
|
denying everyone FILE_READ_DATA access. */
|
||||||
| FILE_OPEN_FOR_BACKUP_INTENT
|
status = NtOpenFile (&h,
|
||||||
| (sym_check == 3 ? FILE_OPEN_REPARSE_POINT : 0));
|
sym_check == is_reparse_symlink
|
||||||
|
? READ_CONTROL : FILE_GENERIC_READ,
|
||||||
|
&attr, &io, FILE_SHARE_VALID_FLAGS,
|
||||||
|
FILE_OPEN_FOR_BACKUP_INTENT
|
||||||
|
| (sym_check == is_reparse_symlink
|
||||||
|
? FILE_OPEN_REPARSE_POINT
|
||||||
|
: FILE_SYNCHRONOUS_IO_NONALERT));
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
switch (sym_check)
|
switch (sym_check)
|
||||||
{
|
{
|
||||||
case 1:
|
case is_shortcut_symlink:
|
||||||
res = check_shortcut (h);
|
res = check_shortcut (h);
|
||||||
NtClose (h);
|
NtClose (h);
|
||||||
if (!res)
|
if (!res)
|
||||||
@ -3951,18 +3972,20 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
|
|
||||||
fileattr = INVALID_FILE_ATTRIBUTES;
|
fileattr = INVALID_FILE_ATTRIBUTES;
|
||||||
continue; /* in case we're going to tack *another* .lnk on this filename. */
|
continue; /* in case we're going to tack *another* .lnk on this filename. */
|
||||||
case 2:
|
case is_reparse_symlink:
|
||||||
res = check_sysfile (h);
|
|
||||||
NtClose (h);
|
|
||||||
if (!res)
|
|
||||||
goto file_not_symlink;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
res = check_reparse_point (h);
|
res = check_reparse_point (h);
|
||||||
NtClose (h);
|
NtClose (h);
|
||||||
if (!res)
|
if (!res)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
break;
|
break;
|
||||||
|
case is_sysfile_symlink:
|
||||||
|
res = check_sysfile (h);
|
||||||
|
NtClose (h);
|
||||||
|
if (!res)
|
||||||
|
goto file_not_symlink;
|
||||||
|
break;
|
||||||
|
default: /* Make gcc happy. Won't happen. */
|
||||||
|
goto file_not_symlink;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user