In FindNextFileExW don't report directory symlinks that point to one
of the parent directories, to avoid infinite recursions.
This commit is contained in:
parent
f8fef6ea94
commit
a51f2becf6
@ -25,6 +25,9 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
# include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NONAMELESSUNION
|
#define NONAMELESSUNION
|
||||||
#define NONAMELESSSTRUCT
|
#define NONAMELESSSTRUCT
|
||||||
@ -56,6 +59,7 @@ typedef struct
|
|||||||
HANDLE handle; /* handle to directory */
|
HANDLE handle; /* handle to directory */
|
||||||
CRITICAL_SECTION cs; /* crit section protecting this structure */
|
CRITICAL_SECTION cs; /* crit section protecting this structure */
|
||||||
UNICODE_STRING mask; /* file mask */
|
UNICODE_STRING mask; /* file mask */
|
||||||
|
UNICODE_STRING path; /* NT path used to open the directory */
|
||||||
BOOL is_root; /* is directory the root of the drive? */
|
BOOL is_root; /* is directory the root of the drive? */
|
||||||
UINT data_pos; /* current position in dir data */
|
UINT data_pos; /* current position in dir data */
|
||||||
UINT data_len; /* length of dir data */
|
UINT data_len; /* length of dir data */
|
||||||
@ -113,6 +117,58 @@ static HANDLE create_file_OF( LPCSTR path, INT mode )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* check_dir_symlink
|
||||||
|
*
|
||||||
|
* Check if a dir symlink should be returned by FindNextFile.
|
||||||
|
*/
|
||||||
|
static BOOL check_dir_symlink( FIND_FIRST_INFO *info, const FILE_BOTH_DIR_INFORMATION *file_info )
|
||||||
|
{
|
||||||
|
UNICODE_STRING str;
|
||||||
|
ANSI_STRING unix_name;
|
||||||
|
struct stat st, parent_st;
|
||||||
|
BOOL ret = TRUE;
|
||||||
|
DWORD len;
|
||||||
|
|
||||||
|
str.MaximumLength = info->path.Length + sizeof(WCHAR) + file_info->FileNameLength;
|
||||||
|
if (!(str.Buffer = HeapAlloc( GetProcessHeap(), 0, str.MaximumLength ))) return TRUE;
|
||||||
|
memcpy( str.Buffer, info->path.Buffer, info->path.Length );
|
||||||
|
len = info->path.Length / sizeof(WCHAR);
|
||||||
|
if (!len || str.Buffer[len-1] != '\\') str.Buffer[len++] = '\\';
|
||||||
|
memcpy( str.Buffer + len, file_info->FileName, file_info->FileNameLength );
|
||||||
|
str.Length = len * sizeof(WCHAR) + file_info->FileNameLength;
|
||||||
|
|
||||||
|
unix_name.Buffer = NULL;
|
||||||
|
if (!wine_nt_to_unix_file_name( &str, &unix_name, OPEN_EXISTING, FALSE ) &&
|
||||||
|
!stat( unix_name.Buffer, &st ))
|
||||||
|
{
|
||||||
|
char *p = unix_name.Buffer + unix_name.Length - 1;
|
||||||
|
|
||||||
|
/* skip trailing slashes */
|
||||||
|
while (p > unix_name.Buffer && *p == '/') p--;
|
||||||
|
|
||||||
|
while (ret && p > unix_name.Buffer)
|
||||||
|
{
|
||||||
|
while (p > unix_name.Buffer && *p != '/') p--;
|
||||||
|
while (p > unix_name.Buffer && *p == '/') p--;
|
||||||
|
p[1] = 0;
|
||||||
|
if (!stat( unix_name.Buffer, &parent_st ) &&
|
||||||
|
parent_st.st_dev == st.st_dev &&
|
||||||
|
parent_st.st_ino == st.st_ino)
|
||||||
|
{
|
||||||
|
WARN( "suppressing dir symlink %s pointing to parent %s\n",
|
||||||
|
debugstr_wn( str.Buffer, str.Length/sizeof(WCHAR) ),
|
||||||
|
debugstr_a( unix_name.Buffer ));
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RtlFreeAnsiString( &unix_name );
|
||||||
|
RtlFreeUnicodeString( &str );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* FILE_SetDosError
|
* FILE_SetDosError
|
||||||
*
|
*
|
||||||
@ -1510,9 +1566,9 @@ HANDLE WINAPI FindFirstFileExW( LPCWSTR filename, FINDEX_INFO_LEVELS level,
|
|||||||
SetLastError( RtlNtStatusToDosError(status) );
|
SetLastError( RtlNtStatusToDosError(status) );
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
RtlFreeUnicodeString( &nt_name );
|
|
||||||
|
|
||||||
RtlInitializeCriticalSection( &info->cs );
|
RtlInitializeCriticalSection( &info->cs );
|
||||||
|
info->path = nt_name;
|
||||||
info->magic = FIND_FIRST_MAGIC;
|
info->magic = FIND_FIRST_MAGIC;
|
||||||
info->data_pos = 0;
|
info->data_pos = 0;
|
||||||
info->data_len = 0;
|
info->data_len = 0;
|
||||||
@ -1588,6 +1644,13 @@ BOOL WINAPI FindNextFileW( HANDLE handle, WIN32_FIND_DATAW *data )
|
|||||||
dir_info->FileName[0] == '.' && dir_info->FileName[1] == '.') continue;
|
dir_info->FileName[0] == '.' && dir_info->FileName[1] == '.') continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for dir symlink */
|
||||||
|
if ((dir_info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
|
(dir_info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||||
|
{
|
||||||
|
if (!check_dir_symlink( info, dir_info )) continue;
|
||||||
|
}
|
||||||
|
|
||||||
data->dwFileAttributes = dir_info->FileAttributes;
|
data->dwFileAttributes = dir_info->FileAttributes;
|
||||||
data->ftCreationTime = *(FILETIME *)&dir_info->CreationTime;
|
data->ftCreationTime = *(FILETIME *)&dir_info->CreationTime;
|
||||||
data->ftLastAccessTime = *(FILETIME *)&dir_info->LastAccessTime;
|
data->ftLastAccessTime = *(FILETIME *)&dir_info->LastAccessTime;
|
||||||
@ -1639,6 +1702,7 @@ BOOL WINAPI FindClose( HANDLE handle )
|
|||||||
info->handle = 0;
|
info->handle = 0;
|
||||||
RtlFreeUnicodeString( &info->mask );
|
RtlFreeUnicodeString( &info->mask );
|
||||||
info->mask.Buffer = NULL;
|
info->mask.Buffer = NULL;
|
||||||
|
RtlFreeUnicodeString( &info->path );
|
||||||
info->data_pos = 0;
|
info->data_pos = 0;
|
||||||
info->data_len = 0;
|
info->data_len = 0;
|
||||||
RtlLeaveCriticalSection( &info->cs );
|
RtlLeaveCriticalSection( &info->cs );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user