* dir.cc (readdir_worker): Drop dir parameter from call to

readdir_get_ino.
	* fhandler.h (fhandler_disk_file::readdir_helper): Switch file name
	parameter to PUNICODE_STRING.
	* fhandler_disk_file.cc: Drop including ntdef.h.
	(class __DIR_mounts): Store mount points in UNICODE.  Additionally
	store cygdrive prefix in unicode here.  Change methods accordingly.
	(__DIR_mounts::eval_ino): Call new stat_worker instead of lstat64.
	(__DIR_mounts::~__DIR_mounts): New destructor to free UNICODE buffers.
	(path_conv::ndisk_links): Rewrite using native NT functions.
	(fhandler_base::fstat_by_handle): Use NAME_MAX instead of CYG_MAX_PATH.
	Always set pfvi->VolumeSerialNumber to non-0.  Remove last resort
	code.
	(fhandler_base::fstat_by_name): Rewrite using native NT functions.
	(fhandler_base::fstat_fs): Always call fstat_by_name if fstat_by_handle
	fails.
	(fhandler_base::fstat_helper): Rely on dwVolumeSerialNumber.
	(fhandler_disk_file::facl): Call fstat_by_name if fstat_by_handle fails.
	(DIR_BUF_SIZE): Define using NAME_MAX instead of CYG_MAX_PATH.
	(__DIR_cache): Remove __name.
	(d_dirname): Remove.
	(fhandler_disk_file::opendir): Drop pathname length check.
	Remove outdated comment.  Use get_name method instead of accessing
	pc.normalized_path directly.
	(readdir_get_ino): Drop unused dir parameter.  Accomodate throughout.
	Allocate fname dynamically.  Call new stat_worker instead of lstat64.
	Call NtOpenFile instead of CreateFile.  Call NtClose instead of
	CloseHandle.
	(fhandler_disk_file::readdir_helper): Use native NT functions.
	Check for volume mount points and use correct inode number.
	(fhandler_disk_file::readdir): Simplify slightly.
	Use get_name instead of pc.normalized_path.
	(fhandler_disk_file::rewinddir): Use RtlInitUnicodeString.
	(fhandler_cygdrive::fstat): Ignore floppy drives.  Set st_nlink
	correctly.
	(fhandler_cygdrive::readdir): Ignore floppy drives.
	* fhandler_netdrive.cc (fhandler_netdrive::readdir): Accommodate
	change to readdir_get_ino.
	* fhandler_proc.cc (PROC_DIR_COUNT): Define.
	(fhandler_proc::fstat): Evaluate correct link count for /proc.
	* ntdll.h (struct _FILE_DIRECTORY_INFORMATION): Define.
	(NtFsControlFile): Declare.
	(RtlAppendUnicodeToString): Declare.
	(RtlAppendUnicodeStringToString): Declare.
	(RtlCompareUnicodeString): Declare.
	(RtlCopyUnicodeString): Declare.
	(RtlCreateUnicodeStringFromAsciiz): Declare.
	(RtlEqualUnicodeString): Declare.
	(RtlFreeUnicodeString): Declare.
	(RtlInitEmptyUnicodeString): Declare.
	(RtlSecondsSince1970ToTime): Declare.
	(RtlInitEmptyUnicodeString): Define as inline function.
	(RtlInitCountedUnicodeString): Define as inline function.
	* path.cc (path_conv::check): New method with PUNICODE_STRING as path,
	preliminary implementation.
	(mount_info::get_mounts_here): Change to create UNICODE_STRINGs.
	Also copy cygpath prefix into UNICODE_STRING.
	(is_floppy): Drop 9x consideration.
	* path.h: Drop including ntdef.h.
	(path_conv::check): Add declaration.
	(path_conv::path_conv): Add constructor for UNICODE_STRING paths.
	* shared_info.h (mount_info::get_mounts_here): Change declaration.
	* syscalls.cc: Drop forward declaration of stat_worker.
	(stat_worke): Take path_conv as parameter.  Drop nofollow flag.
	(stat64): Create matching path_conv and call stat_worker with it.
	(lstat64): Ditto.
	* winsup.h: Include ntdef.h.
	(stat_worker): Declare.
	(readdir_get_ino): Change declaration.
This commit is contained in:
Corinna Vinschen 2007-07-26 17:30:54 +00:00
parent 4b62a570de
commit 214c3a1167
12 changed files with 572 additions and 269 deletions

View File

@ -1,3 +1,75 @@
2007-07-26 Corinna Vinschen <corinna@vinschen.de>
* dir.cc (readdir_worker): Drop dir parameter from call to
readdir_get_ino.
* fhandler.h (fhandler_disk_file::readdir_helper): Switch file name
parameter to PUNICODE_STRING.
* fhandler_disk_file.cc: Drop including ntdef.h.
(class __DIR_mounts): Store mount points in UNICODE. Additionally
store cygdrive prefix in unicode here. Change methods accordingly.
(__DIR_mounts::eval_ino): Call new stat_worker instead of lstat64.
(__DIR_mounts::~__DIR_mounts): New destructor to free UNICODE buffers.
(path_conv::ndisk_links): Rewrite using native NT functions.
(fhandler_base::fstat_by_handle): Use NAME_MAX instead of CYG_MAX_PATH.
Always set pfvi->VolumeSerialNumber to non-0. Remove last resort
code.
(fhandler_base::fstat_by_name): Rewrite using native NT functions.
(fhandler_base::fstat_fs): Always call fstat_by_name if fstat_by_handle
fails.
(fhandler_base::fstat_helper): Rely on dwVolumeSerialNumber.
(fhandler_disk_file::facl): Call fstat_by_name if fstat_by_handle fails.
(DIR_BUF_SIZE): Define using NAME_MAX instead of CYG_MAX_PATH.
(__DIR_cache): Remove __name.
(d_dirname): Remove.
(fhandler_disk_file::opendir): Drop pathname length check.
Remove outdated comment. Use get_name method instead of accessing
pc.normalized_path directly.
(readdir_get_ino): Drop unused dir parameter. Accomodate throughout.
Allocate fname dynamically. Call new stat_worker instead of lstat64.
Call NtOpenFile instead of CreateFile. Call NtClose instead of
CloseHandle.
(fhandler_disk_file::readdir_helper): Use native NT functions.
Check for volume mount points and use correct inode number.
(fhandler_disk_file::readdir): Simplify slightly.
Use get_name instead of pc.normalized_path.
(fhandler_disk_file::rewinddir): Use RtlInitUnicodeString.
(fhandler_cygdrive::fstat): Ignore floppy drives. Set st_nlink
correctly.
(fhandler_cygdrive::readdir): Ignore floppy drives.
* fhandler_netdrive.cc (fhandler_netdrive::readdir): Accommodate
change to readdir_get_ino.
* fhandler_proc.cc (PROC_DIR_COUNT): Define.
(fhandler_proc::fstat): Evaluate correct link count for /proc.
* ntdll.h (struct _FILE_DIRECTORY_INFORMATION): Define.
(NtFsControlFile): Declare.
(RtlAppendUnicodeToString): Declare.
(RtlAppendUnicodeStringToString): Declare.
(RtlCompareUnicodeString): Declare.
(RtlCopyUnicodeString): Declare.
(RtlCreateUnicodeStringFromAsciiz): Declare.
(RtlEqualUnicodeString): Declare.
(RtlFreeUnicodeString): Declare.
(RtlInitEmptyUnicodeString): Declare.
(RtlSecondsSince1970ToTime): Declare.
(RtlInitEmptyUnicodeString): Define as inline function.
(RtlInitCountedUnicodeString): Define as inline function.
* path.cc (path_conv::check): New method with PUNICODE_STRING as path,
preliminary implementation.
(mount_info::get_mounts_here): Change to create UNICODE_STRINGs.
Also copy cygpath prefix into UNICODE_STRING.
(is_floppy): Drop 9x consideration.
* path.h: Drop including ntdef.h.
(path_conv::check): Add declaration.
(path_conv::path_conv): Add constructor for UNICODE_STRING paths.
* shared_info.h (mount_info::get_mounts_here): Change declaration.
* syscalls.cc: Drop forward declaration of stat_worker.
(stat_worke): Take path_conv as parameter. Drop nofollow flag.
(stat64): Create matching path_conv and call stat_worker with it.
(lstat64): Ditto.
* winsup.h: Include ntdef.h.
(stat_worker): Declare.
(readdir_get_ino): Change declaration.
2007-07-25 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (CreateToolhelp32Snapshot): Remove.
@ -172,8 +244,8 @@
2007-07-16 Corinna Vinschen <corinna@vinschen.de>
* cygheap.h (cygheap_user::curr_imp_token): Rename from current_token.
Accommodate changge throughout Cygwin.
(cygheap_user::imp_token): Rename from token. Accommodate changge
Accommodate change throughout Cygwin.
(cygheap_user::imp_token): Rename from token. Accommodate change
throughout Cygwin.
(rcygheap_user::eimpersonate): Use primary token for impersonation.
* grp.cc (internal_getgroups): Use primary impersonation token when

View File

@ -132,8 +132,7 @@ readdir_worker (DIR *dir, dirent *de)
}
if (is_dot_dot && !(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (dir,
((fhandler_base *) dir->__fh)->get_name (),
de->d_ino = readdir_get_ino (((fhandler_base *) dir->__fh)->get_name (),
true);
else
{

View File

@ -671,7 +671,7 @@ class fhandler_dev_tape: public fhandler_dev_raw
class fhandler_disk_file: public fhandler_base
{
int readdir_helper (DIR *, dirent *, DWORD, DWORD, char *) __attribute__ ((regparm (3)));
int readdir_helper (DIR *, dirent *, DWORD, DWORD, PUNICODE_STRING fname) __attribute__ ((regparm (3)));
public:
fhandler_disk_file ();

View File

@ -26,7 +26,6 @@ details. */
#include "cygheap.h"
#include "shared_info.h"
#include "pinfo.h"
#include <ntdef.h>
#include "ntdll.h"
#include <assert.h>
#include <ctype.h>
@ -37,11 +36,12 @@ details. */
class __DIR_mounts
{
int count;
const char *parent_dir;
int parent_dir_len;
char *mounts[MAX_MOUNTS];
bool found[MAX_MOUNTS + 2];
int count;
const char *parent_dir;
int parent_dir_len;
UNICODE_STRING mounts[MAX_MOUNTS];
bool found[MAX_MOUNTS + 2];
UNICODE_STRING cygdrive;
#define __DIR_PROC (MAX_MOUNTS)
#define __DIR_CYGDRIVE (MAX_MOUNTS+1)
@ -49,15 +49,16 @@ class __DIR_mounts
__ino64_t eval_ino (int idx)
{
__ino64_t ino = 0;
char fname[CYG_MAX_PATH];
char fname[parent_dir_len + mounts[idx].Length / sizeof (WCHAR) + 2];
struct __stat64 st;
int len = parent_dir_len;
strcpy (fname, parent_dir);
if (fname[len - 1] != '/')
fname[len++] = '/';
strcpy (fname + len, mounts[idx]);
if (!lstat64 (fname, &st))
char *c = stpcpy (fname, parent_dir);
if (c[- 1] != '/')
*c++ = '/';
sys_wcstombs (c, mounts[idx].Length / sizeof (WCHAR) + 1,
mounts[idx].Buffer, mounts[idx].Length / sizeof (WCHAR));
path_conv pc (fname, PC_SYM_NOFOLLOW | PC_POSIX);
if (!stat_worker (pc, &st))
ino = st.st_ino;
return ino;
}
@ -67,59 +68,73 @@ public:
: parent_dir (posix_path)
{
parent_dir_len = strlen (parent_dir);
count = mount_table->get_mounts_here (parent_dir, parent_dir_len, mounts);
count = mount_table->get_mounts_here (parent_dir, parent_dir_len, mounts,
&cygdrive);
rewind ();
}
__ino64_t check_mount (const char *name, __ino64_t ino, bool eval = true)
~__DIR_mounts ()
{
for (int i = 0; i < count; ++i)
RtlFreeUnicodeString (&mounts[i]);
RtlFreeUnicodeString (&cygdrive);
}
__ino64_t check_mount (PUNICODE_STRING fname, __ino64_t ino,
bool eval = true)
{
if (parent_dir_len == 1) /* root dir */
{
if (strcasematch (name, "proc"))
UNICODE_STRING proc;
RtlInitUnicodeString (&proc, L"proc");
if (RtlEqualUnicodeString (fname, &proc, TRUE))
{
found[__DIR_PROC] = true;
return hash_path_name (0, "/proc");
return 2;
}
if (strlen (name) == mount_table->cygdrive_len - 2
&& strncasematch (name, mount_table->cygdrive + 1,
mount_table->cygdrive_len - 2))
if (fname->Length / sizeof (WCHAR) == mount_table->cygdrive_len - 2
&& RtlEqualUnicodeString (fname, &cygdrive, TRUE))
{
found[__DIR_CYGDRIVE] = true;
return 2;
}
}
for (int i = 0; i < count; ++i)
if (strcasematch (name, mounts[i]))
if (RtlEqualUnicodeString (fname, &mounts[i], TRUE))
{
found[i] = true;
return eval ? eval_ino (i) : 1;
}
return ino;
}
__ino64_t check_missing_mount (char *ret_name, bool eval = true)
__ino64_t check_missing_mount (PUNICODE_STRING retname = NULL)
{
for (int i = 0; i < count; ++i)
if (!found[i])
{
found[i] = true;
strcpy (ret_name, mounts[i]);
return eval ? eval_ino (i) : 1;
if (retname)
{
*retname = mounts[i];
return eval_ino (i);
}
return 1;
}
if (parent_dir_len == 1) /* root dir */
{
if (!found[__DIR_PROC])
{
found[__DIR_PROC] = true;
strcpy (ret_name, "proc");
return hash_path_name (0, "/proc");
if (retname)
RtlInitUnicodeString (retname, L"proc");
return 2;
}
if (!found[__DIR_CYGDRIVE])
{
found[__DIR_CYGDRIVE] = true;
if (mount_table->cygdrive_len > 1)
if (cygdrive.Length > 0)
{
strncpy (ret_name, mount_table->cygdrive + 1,
mount_table->cygdrive_len - 2);
ret_name[mount_table->cygdrive_len - 2] = '\0';
if (retname)
*retname = cygdrive;
return 2;
}
}
@ -135,66 +150,91 @@ path_conv::ndisk_links (DWORD nNumberOfLinks)
if (!isdir () || isremote ())
return nNumberOfLinks;
int len = strlen (*this);
char fn[len + 3];
strcpy (fn, *this);
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
HANDLE fh;
const char *s;
unsigned count;
if (!NT_SUCCESS (NtOpenFile (&fh, SYNCHRONIZE | FILE_LIST_DIRECTORY,
get_object_attr (attr, sec_none_nih),
&io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE)))
return nNumberOfLinks;
unsigned count = 0;
bool first = true;
NTSTATUS status;
PFILE_DIRECTORY_INFORMATION fdibuf = (PFILE_DIRECTORY_INFORMATION)
alloca (65536);
__DIR_mounts *dir = new __DIR_mounts (normalized_path);
if (nNumberOfLinks <= 1)
while (NT_SUCCESS (NtQueryDirectoryFile (fh, NULL, NULL, 0, &io, fdibuf,
65536, FileDirectoryInformation,
FALSE, NULL, first)))
{
s = "\\*";
count = 0;
}
else
{
s = "\\..";
count = nNumberOfLinks;
}
if (first)
{
first = false;
/* All directories have . and .. as their first entries.
If . is not present as first entry, we're on a drive's
root direcotry, which doesn't have these entries. */
if (fdibuf->FileNameLength != 2 || fdibuf->FileName[0] != L'.')
count = 2;
}
for (PFILE_DIRECTORY_INFORMATION pfdi = fdibuf;
pfdi;
pfdi = (PFILE_DIRECTORY_INFORMATION)
(pfdi->NextEntryOffset ? (PBYTE) pfdi + pfdi->NextEntryOffset
: NULL))
{
switch (pfdi->FileAttributes
& (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))
{
case FILE_ATTRIBUTE_DIRECTORY:
/* Just a directory */
++count;
break;
case FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT:
/* Volume mount point or symlink to directory */
{
HANDLE reph;
UNICODE_STRING fname;
if (len == 0 || isdirsep (fn[len - 1]))
strcpy (fn + len, s + 1);
else
strcpy (fn + len, s);
WIN32_FIND_DATA buf;
HANDLE h = FindFirstFile (fn, &buf);
int saw_dot = 2;
if (h != INVALID_HANDLE_VALUE)
{
if (nNumberOfLinks > 1)
saw_dot--;
else
do
{
if (buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
count++;
if (buf.cFileName[0] == '.'
&& (buf.cFileName[1] == '\0'
|| (buf.cFileName[1] == '.' && buf.cFileName[2] == '\0')))
saw_dot--;
dir->check_mount (buf.cFileName, 0, false);
}
while (FindNextFileA (h, &buf));
FindClose (h);
RtlInitCountedUnicodeString (&fname, pfdi->FileNameLength,
pfdi->FileName);
InitializeObjectAttributes (&attr, &fname,
OBJ_CASE_INSENSITIVE, fh, NULL);
if (NT_SUCCESS (status = NtOpenFile (&reph, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REPARSE_POINT)))
{
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
if (NT_SUCCESS (NtFsControlFile (reph, NULL, NULL, NULL,
&io, FSCTL_GET_REPARSE_POINT, NULL, 0,
(LPVOID) rp, MAXIMUM_REPARSE_DATA_BUFFER_SIZE))
&& rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT
&& rp->SymbolicLinkReparseBuffer.PrintNameLength == 0)
++count;
NtClose (reph);
}
}
break;
default:
break;
}
UNICODE_STRING fname;
RtlInitCountedUnicodeString (&fname, pfdi->FileNameLength,
pfdi->FileName);
dir->check_mount (&fname, 0, false);
}
}
if (nNumberOfLinks > 1)
{
fn[len + 2] = '\0';
h = FindFirstFile (fn, &buf);
if (h)
saw_dot--;
FindClose (h);
}
while (dir->check_missing_mount (buf.cFileName, false))
while (dir->check_missing_mount ())
++count;
NtClose (dir);
delete dir;
return count + saw_dot;
return count;
}
inline bool
@ -214,9 +254,10 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
NTSTATUS status;
IO_STATUS_BLOCK io;
/* The entries potentially contain a name of MAX_PATH wide characters. */
const DWORD fvi_size = 2 * CYG_MAX_PATH
const DWORD fvi_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_FS_VOLUME_INFORMATION);
const DWORD fai_size = 2 * CYG_MAX_PATH + sizeof (FILE_ALL_INFORMATION);
const DWORD fai_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_ALL_INFORMATION);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
@ -228,7 +269,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
{
debug_printf ("%u = NtQueryVolumeInformationFile)",
RtlNtStatusToDosError (status));
pfvi->VolumeSerialNumber = 0; /* Set to pc.volser () in helper. */
pfvi->VolumeSerialNumber = pc.volser ();
}
status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
FileAllInformation);
@ -241,9 +282,9 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
pfai->BasicInformation.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (pfai->BasicInformation.FileAttributes);
return fstat_helper (buf,
pfai->BasicInformation.ChangeTime.QuadPart ?
*(FILETIME *) &pfai->BasicInformation.ChangeTime :
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
pfai->BasicInformation.ChangeTime.QuadPart
? *(FILETIME *) &pfai->BasicInformation.ChangeTime
: *(FILETIME *) &pfai->BasicInformation.LastWriteTime,
*(FILETIME *) &pfai->BasicInformation.LastAccessTime,
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
*(FILETIME *) &pfai->BasicInformation.CreationTime,
@ -254,66 +295,119 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
pfai->StandardInformation.NumberOfLinks,
pfai->BasicInformation.FileAttributes);
}
debug_printf ("%u = NtQueryInformationFile)",
RtlNtStatusToDosError (status));
/* Last resort */
FILETIME ft = { 0, 0 };
DWORD lowfs, highfs;
lowfs = GetFileSize (get_handle (), &highfs);
if (lowfs == 0xffffffff && GetLastError ())
lowfs = highfs = 0;
return fstat_helper (buf, ft, ft, ft, ft, 0, (ULONGLONG) highfs << 32 | lowfs,
-1LL, 0ULL, 1, DWORD (pc));
return -1;
}
int __stdcall
fhandler_base::fstat_by_name (struct __stat64 *buf)
{
int res = -1;
NTSTATUS status;
OBJECT_ATTRIBUTES attr;
FILE_NETWORK_OPEN_INFORMATION fnoi;
IO_STATUS_BLOCK io;
UNICODE_STRING dirname;
UNICODE_STRING basename;
HANDLE dir;
const DWORD fdi_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_ID_BOTH_DIR_INFORMATION);
const DWORD fvi_size = (NAME_MAX + 1) * sizeof (WCHAR)
+ sizeof (FILE_FS_VOLUME_INFORMATION);
PFILE_ID_BOTH_DIR_INFORMATION pfdi = (PFILE_ID_BOTH_DIR_INFORMATION)
alloca (fdi_size);
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
alloca (fvi_size);
LARGE_INTEGER FileId;
if (!pc.exists ())
{
debug_printf ("already determined that pc does not exist");
set_errno (ENOENT);
return -1;
}
else if (NT_SUCCESS (status = NtQueryFullAttributesFile (
pc.get_object_attr (attr, sec_none_nih), &fnoi)))
/* Split path in dirname and basename */
dirname = *pc.get_nt_native_path ();
USHORT len = dirname.Length / sizeof (WCHAR);
while (len > 0 && dirname.Buffer[--len] != L'\\')
;
++len;
RtlInitCountedUnicodeString (&basename,
dirname.Length - len * sizeof (WCHAR),
&dirname.Buffer[len]);
dirname.Length = len * sizeof (WCHAR);
InitializeObjectAttributes (&attr, &dirname, OBJ_CASE_INSENSITIVE,
NULL, NULL);
if (!NT_SUCCESS (status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, FILE_SHARE_VALID_FLAGS,
FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
| FILE_DIRECTORY_FILE)))
{
if (pc.is_rep_symlink ())
fnoi.FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (fnoi.FileAttributes);
res = fstat_helper (buf,
*(FILETIME *) (fnoi.ChangeTime.QuadPart
? &fnoi.ChangeTime
: &fnoi.LastWriteTime),
*(FILETIME *) &fnoi.LastAccessTime,
*(FILETIME *) &fnoi.LastWriteTime,
*(FILETIME *) &fnoi.CreationTime,
debug_printf ("%u = NtOpenFile)", RtlNtStatusToDosError (status));
goto too_bad;
}
if (wincap.has_fileid_dirinfo ()
&& NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
pfdi, fdi_size,
FileIdBothDirectoryInformation,
TRUE, &basename, TRUE)))
FileId = pfdi->FileId;
else if (NT_SUCCESS (status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io,
pfdi, fdi_size,
FileBothDirectoryInformation,
TRUE, &basename, TRUE)))
FileId.QuadPart = 0; /* get_namehash is called in fstat_helper. */
if (!NT_SUCCESS (status))
{
debug_printf ("%u = NtQueryDirectoryFile)",
RtlNtStatusToDosError (status));
NtClose (dir);
goto too_bad;
}
status = NtQueryVolumeInformationFile (dir, &io, pfvi, fvi_size,
FileFsVolumeInformation);
if (!NT_SUCCESS (status))
{
debug_printf ("%u = NtQueryVolumeInformationFile)",
RtlNtStatusToDosError (status));
pfvi->VolumeSerialNumber = pc.volser ();
}
NtClose (dir);
/* If the change time is 0, it's a file system which doesn't
support a change timestamp. In that case use the LastWriteTime
entry, as in other calls to fstat_helper. */
if (pc.is_rep_symlink ())
pfdi->FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY;
pc.file_attributes (pfdi->FileAttributes);
return fstat_helper (buf,
pfdi->ChangeTime.QuadPart ?
*(FILETIME *) &pfdi->ChangeTime :
*(FILETIME *) &pfdi->LastWriteTime,
*(FILETIME *) &pfdi->LastAccessTime,
*(FILETIME *) &pfdi->LastWriteTime,
*(FILETIME *) &pfdi->CreationTime,
pfvi->VolumeSerialNumber,
pfdi->EndOfFile.QuadPart,
pfdi->AllocationSize.QuadPart,
pfdi->FileId.QuadPart,
1,
pfdi->FileAttributes);
too_bad:
LARGE_INTEGER ft;
/* Arbitrary value: 2006-12-01 */
RtlSecondsSince1970ToTime (1164931200L, &ft);
return fstat_helper (buf,
*(FILETIME *) &ft,
*(FILETIME *) &ft,
*(FILETIME *) &ft,
*(FILETIME *) &ft,
pc.volser (),
fnoi.EndOfFile.QuadPart,
fnoi.AllocationSize.QuadPart,
0ULL,
-1LL,
0ULL,
1,
fnoi.FileAttributes);
}
else if (pc.isdir ())
{
FILETIME ft = {};
res = fstat_helper (buf, ft, ft, ft, ft, pc.volser (), 0ULL, -1LL, 0ULL,
1, FILE_ATTRIBUTE_DIRECTORY);
}
else
{
__seterrno_from_nt_status (status);
res = -1;
}
return res;
pc.file_attributes ());
}
int __stdcall
@ -325,10 +419,11 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
if (get_io_handle ())
{
if (nohandle () || is_fs_special ())
return fstat_by_name (buf);
else
return fstat_by_handle (buf);
if (!nohandle () && !is_fs_special ())
res = fstat_by_handle (buf);
if (res)
res = fstat_by_name (buf);
return res;
}
query_open (query_stat_control);
if (!(oret = open_fs (open_flags, 0)) && get_errno () == EACCES)
@ -353,7 +448,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
nohandle (no_handle);
set_io_handle (NULL);
}
else
if (res)
res = fstat_by_name (buf);
return res;
@ -389,7 +484,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
to_timestruc_t (&ftLastWriteTime, &buf->st_mtim);
to_timestruc_t (&ftChangeTime, &buf->st_ctim);
to_timestruc_t (&ftCreationTime, &buf->st_birthtim);
buf->st_dev = dwVolumeSerialNumber ?: pc.volser ();
buf->st_dev = dwVolumeSerialNumber;
buf->st_size = (_off64_t) nFileSize;
/* The number of links to a directory includes the
number of subdirectories in the directory, since all
@ -753,10 +848,10 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
if (!get_io_handle ())
{
query_open (query_read_attributes);
if (!(oret = open (O_BINARY, 0)))
return -1;
oret = open (O_BINARY, 0);
}
if (!fstat_by_handle (&st))
if ((!oret && !fstat_by_handle (&st))
|| !fstat_by_name (&st))
{
aclbufp[0].a_type = USER_OBJ;
aclbufp[0].a_id = st.st_uid;
@ -1482,22 +1577,20 @@ fhandler_disk_file::rmdir ()
/* This is the minimal number of entries which fit into the readdir cache.
The number of bytes allocated by the cache is determined by this number,
To tune caching, just tweak this number. To get a feeling for the size,
the size of the readdir cache is DIR_NUM_ENTRIES * 632 + 264 bytes. */
the size of the readdir cache is DIR_NUM_ENTRIES * 624 + 4 bytes. */
#define DIR_NUM_ENTRIES 100 /* Cache size 63464 bytes */
#define DIR_NUM_ENTRIES 100 /* Cache size 62404 bytes */
#define DIR_BUF_SIZE (DIR_NUM_ENTRIES \
* (sizeof (FILE_ID_BOTH_DIR_INFORMATION) \
+ 2 * CYG_MAX_PATH))
+ 2 * (NAME_MAX + 1)))
struct __DIR_cache
{
char __name[CYG_MAX_PATH];
ULONG __pos;
char __cache[DIR_BUF_SIZE];
};
#define d_dirname(d) (((__DIR_cache *) (d)->__d_dirname)->__name)
#define d_cachepos(d) (((__DIR_cache *) (d)->__d_dirname)->__pos)
#define d_cache(d) (((__DIR_cache *) (d)->__d_dirname)->__cache)
@ -1508,12 +1601,9 @@ fhandler_disk_file::opendir (int fd)
{
DIR *dir;
DIR *res = NULL;
size_t len;
if (!pc.isdir ())
set_errno (ENOTDIR);
else if ((len = strlen (pc)) > CYG_MAX_PATH - 3)
set_errno (ENAMETOOLONG);
else if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL)
set_errno (ENOMEM);
else if ((dir->__d_dirname = (char *) malloc ( sizeof (struct __DIR_cache)))
@ -1530,30 +1620,17 @@ fhandler_disk_file::opendir (int fd)
}
else
{
strcpy (d_dirname (dir), get_win32_name ());
dir->__d_dirent->__d_version = __DIRENT_VERSION;
cygheap_fdnew cfd;
if (cfd < 0 && fd < 0)
goto free_dirent;
/* FindFirstFile doesn't seem to like duplicate /'s.
The dirname is generated with trailing backslash here which
simplifies later usage of dirname for checking symlinks.
Appending a "*" is moved right before calling FindFirstFile.
Since FindFirstFile is only called once, this should even be a
teeny little bit faster. */
len = strlen (d_dirname (dir));
if (len && !isdirsep (d_dirname (dir)[len - 1]))
strcpy (d_dirname (dir) + len, "\\");
dir->__d_dirent->__d_version = __DIRENT_VERSION;
dir->__d_cookie = __DIRENT_COOKIE;
dir->__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
dir->__flags = (pc.normalized_path[0] == '/'
&& pc.normalized_path[1] == '\0')
dir->__flags = (get_name ()[0] == '/' && get_name ()[1] == '\0')
? dirent_isroot : 0;
dir->__d_internal = (unsigned) new __DIR_mounts (pc.normalized_path);
dir->__d_internal = (unsigned) new __DIR_mounts (get_name ());
d_cachepos (dir) = 0;
if (!pc.iscygdrive ())
@ -1628,50 +1705,6 @@ free_dir:
return res;
}
int
fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
DWORD attr, char *fname)
{
if (w32_err)
{
bool added = false;
if ((de->d_ino = d_mounts (dir)->check_missing_mount (fname)))
added = true;
if (!added)
return geterrno_from_win_error (w32_err);
attr = 0;
dir->__flags &= ~dirent_set_d_ino;
}
/* Check for Windows shortcut. If it's a Cygwin or U/WIN
symlink, drop the .lnk suffix. */
if (attr & FILE_ATTRIBUTE_READONLY)
{
char *c = fname;
char *e = strchr (fname, '\0') - 4;
if (e > c && strcasematch (e, ".lnk"))
{
char fbuf[CYG_MAX_PATH];
strcpy (fbuf, d_dirname (dir));
strcat (fbuf, c);
path_conv fpath (fbuf, PC_SYM_NOFOLLOW);
if (fpath.issymlink () || fpath.is_fs_special ())
*e = '\0';
}
}
if (pc.isencoded ())
fnunmunge (de->d_name, fname);
else
strcpy (de->d_name, fname);
if (dir->__d_position == 0 && !strcmp (fname, "."))
dir->__flags |= dirent_saw_dot;
else if (dir->__d_position == 1 && !strcmp (fname, ".."))
dir->__flags |= dirent_saw_dot_dot;
return 0;
}
static inline __ino64_t
readdir_get_ino_by_handle (HANDLE hdl)
{
@ -1685,45 +1718,150 @@ readdir_get_ino_by_handle (HANDLE hdl)
}
__ino64_t __stdcall
readdir_get_ino (DIR *dir, const char *path, bool dot_dot)
readdir_get_ino (const char *path, bool dot_dot)
{
char fname[CYG_MAX_PATH];
char *fname;
struct __stat64 st;
HANDLE hdl;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
__ino64_t ino = 0;
strcpy (fname, path);
if (dot_dot)
strcat (fname, (*fname && fname[strlen (fname) - 1] == '/')
? ".." : "/..");
path_conv pc (fname, PC_SYM_NOFOLLOW);
{
fname = (char *) alloca (strlen (path) + 4);
char *c = stpcpy (fname, path);
if (c[-1] != '/')
*c++ = '/';
strcpy (c, "..");
path = fname;
}
path_conv pc (path, PC_SYM_NOFOLLOW | PC_POSIX);
if (pc.isspecial ())
{
if (!lstat64 (fname, &st))
if (!stat_worker (pc, &st))
ino = st.st_ino;
}
else if (!pc.hasgood_inode ())
ino = hash_path_name (0, pc);
else if ((hdl = CreateFile (pc, GENERIC_READ, FILE_SHARE_VALID_FLAGS,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL))
!= INVALID_HANDLE_VALUE)
else if (NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL,
pc.get_object_attr (attr, sec_none_nih),
&io, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT)))
{
ino = readdir_get_ino_by_handle (hdl);
CloseHandle (hdl);
NtClose (hdl);
}
return ino;
}
int
fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
DWORD attr, PUNICODE_STRING fname)
{
if (w32_err)
{
bool added = false;
if ((de->d_ino = d_mounts (dir)->check_missing_mount (fname)))
added = true;
if (!added)
return geterrno_from_win_error (w32_err);
attr = 0;
dir->__flags &= ~dirent_set_d_ino;
}
/* Check for directory reparse point. These are potential volume mount
points which have another inode than the underlying directory. */
if ((attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))
== (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT))
{
HANDLE reph;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
InitializeObjectAttributes (&attr, fname, OBJ_CASE_INSENSITIVE,
get_handle (), NULL);
if (NT_SUCCESS (NtOpenFile (&reph, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT
| FILE_OPEN_REPARSE_POINT)))
{
PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER)
alloca (MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
if (NT_SUCCESS (NtFsControlFile (reph, NULL, NULL, NULL,
&io, FSCTL_GET_REPARSE_POINT, NULL, 0,
(LPVOID) rp, MAXIMUM_REPARSE_DATA_BUFFER_SIZE))
&& rp->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT
&& rp->SymbolicLinkReparseBuffer.PrintNameLength == 0)
{
NtClose (reph);
if (NT_SUCCESS (NtOpenFile (&reph, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT)))
{
de->d_ino = readdir_get_ino_by_handle (reph);
NtClose (reph);
}
}
else
NtClose (reph);
}
}
/* Check for Windows shortcut. If it's a Cygwin or U/WIN
symlink, drop the .lnk suffix. */
if ((attr & FILE_ATTRIBUTE_READONLY) && fname->Length > 4 * sizeof (WCHAR))
{
UNICODE_STRING uname;
UNICODE_STRING lname;
RtlInitCountedUnicodeString (&uname, 4 * sizeof (WCHAR),
fname->Buffer +
fname->Length / sizeof (WCHAR) - 4);
RtlInitCountedUnicodeString (&lname, 4 * sizeof (WCHAR),
(PWCHAR) L".lnk");
if (RtlEqualUnicodeString (&uname, &lname, TRUE))
{
UNICODE_STRING dirname = *pc.get_nt_native_path ();
dirname.Buffer += 4; /* Skip leading \??\ */
dirname.Length -= 4 * sizeof (WCHAR);
UNICODE_STRING fbuf;
ULONG len = dirname.Length + fname->Length + 2 * sizeof (WCHAR);
RtlInitEmptyUnicodeString (&fbuf, (PCWSTR) alloca (len), len);
RtlCopyUnicodeString (&fbuf, &dirname);
RtlAppendUnicodeToString (&fbuf, L"\\");
RtlAppendUnicodeStringToString (&fbuf, fname);
path_conv fpath (&fbuf, PC_SYM_NOFOLLOW);
if (fpath.issymlink () || fpath.is_fs_special ())
fname->Length -= 4 * sizeof (WCHAR);
}
}
char tmp[NAME_MAX + 1];
sys_wcstombs (tmp, NAME_MAX, fname->Buffer, fname->Length / sizeof (WCHAR));
if (pc.isencoded ())
fnunmunge (de->d_name, tmp);
else
strcpy (de->d_name, tmp);
if (dir->__d_position == 0 && !strcmp (tmp, "."))
dir->__flags |= dirent_saw_dot;
else if (dir->__d_position == 1 && !strcmp (tmp, ".."))
dir->__flags |= dirent_saw_dot_dot;
return 0;
}
int
fhandler_disk_file::readdir (DIR *dir, dirent *de)
{
int res = 0;
NTSTATUS status = STATUS_SUCCESS;
PFILE_ID_BOTH_DIR_INFORMATION buf = NULL;
wchar_t *FileName;
char fname[CYG_MAX_PATH];
PWCHAR FileName;
IO_STATUS_BLOCK io;
UNICODE_STRING fname;
/* d_cachepos always refers to the next cache entry to use. If it's 0
we must reload the cache. */
@ -1818,9 +1956,8 @@ go_ahead:
}
else
FileName = ((PFILE_BOTH_DIR_INFORMATION) buf)->FileName;
sys_wcstombs (fname, CYG_MAX_PATH - 1, FileName, buf->FileNameLength / 2);
de->d_ino = d_mounts (dir)->check_mount (fname, de->d_ino);
RtlInitCountedUnicodeString (&fname, buf->FileNameLength, FileName);
de->d_ino = d_mounts (dir)->check_mount (&fname, de->d_ino);
if (de->d_ino == 0 && (dir->__flags & dirent_set_d_ino))
{
OBJECT_ATTRIBUTES attr;
@ -1829,24 +1966,23 @@ go_ahead:
&& FileName[0] == '.')
de->d_ino = readdir_get_ino_by_handle (get_handle ());
else if (dir->__d_position == 1 && buf->FileNameLength == 4
&& FileName[0] == '.' && FileName[1] == '.')
&& FileName[0] == L'.' && FileName[1] == L'.')
if (!(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (dir, pc.normalized_path, true);
de->d_ino = readdir_get_ino (get_name (), true);
else
de->d_ino = readdir_get_ino_by_handle (get_handle ());
else
{
HANDLE hdl;
UNICODE_STRING upath = {buf->FileNameLength, CYG_MAX_PATH * 2,
FileName};
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
get_handle () , NULL);
if (!NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT))
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
get_handle (), NULL);
if (NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT)))
{
de->d_ino = readdir_get_ino_by_handle (hdl);
CloseHandle (hdl);
NtClose (hdl);
}
}
/* Enforce namehash as inode number on untrusted file systems. */
@ -1859,7 +1995,7 @@ go_ahead:
}
if (!(res = readdir_helper (dir, de, RtlNtStatusToDosError (status),
buf ? buf->FileAttributes : 0, fname)))
buf ? buf->FileAttributes : 0, &fname)))
dir->__d_position++;
else if (!(dir->__flags & dirent_saw_dot))
{
@ -1873,7 +2009,7 @@ go_ahead:
{
strcpy (de->d_name , "..");
if (!(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (dir, pc.normalized_path, true);
de->d_ino = readdir_get_ino (get_name (), true);
else
de->d_ino = readdir_get_ino_by_handle (get_handle ());
dir->__d_position++;
@ -1910,12 +2046,13 @@ fhandler_disk_file::rewinddir (DIR *dir)
to NtQueryDirectoryFile on remote shares is ignored, thus
resulting in not being able to rewind on remote shares. By
reopening the directory, we get a fresh new directory pointer. */
UNICODE_STRING fname = {0, CYG_MAX_PATH * 2, (WCHAR *) L""};
UNICODE_STRING fname;
OBJECT_ATTRIBUTES attr;
NTSTATUS status;
IO_STATUS_BLOCK io;
HANDLE new_dir;
RtlInitUnicodeString (&fname, L"");
InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
get_handle (), NULL);
status = NtOpenFile (&new_dir, SYNCHRONIZE | FILE_LIST_DIRECTORY,
@ -2003,9 +2140,18 @@ fhandler_cygdrive::set_drives ()
int
fhandler_cygdrive::fstat (struct __stat64 *buf)
{
buf->st_mode = S_IFDIR | 0555;
fhandler_base::fstat (buf);
buf->st_ino = 2;
buf->st_nlink = 1;
buf->st_mode = S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
if (!ndrives)
set_drives ();
char flptst[] = "X:";
int n = ndrives;
for (const char *p = pdrive; p && *p; p = strchr (p, '\0') + 1)
if (is_floppy ((flptst[0] = *p, flptst))
|| GetFileAttributes (p) == INVALID_FILE_ATTRIBUTES)
--n;
buf->st_nlink = n + 2;
return 0;
}
@ -2024,6 +2170,8 @@ fhandler_cygdrive::opendir (int fd)
int
fhandler_cygdrive::readdir (DIR *dir, dirent *de)
{
char flptst[] = "X:";
while (true)
{
if (!pdrive || !*pdrive)
@ -2036,13 +2184,15 @@ fhandler_cygdrive::readdir (DIR *dir, dirent *de)
}
return ENMFILE;
}
if (GetFileAttributes (pdrive) != INVALID_FILE_ATTRIBUTES)
if (!is_floppy ((flptst[0] = *pdrive, flptst))
&& GetFileAttributes (pdrive) != INVALID_FILE_ATTRIBUTES)
break;
pdrive = strchr (pdrive, '\0') + 1;
}
*de->d_name = cyg_tolower (*pdrive);
de->d_name[1] = '\0';
de->d_ino = readdir_get_ino (dir, pdrive, false);
user_shared->warned_msdos = true;
de->d_ino = readdir_get_ino (pdrive, false);
dir->__d_position++;
pdrive = strchr (pdrive, '\0') + 1;
syscall_printf ("%p = readdir (%p) (%s)", &de, dir, de->d_name);

View File

@ -210,7 +210,7 @@ fhandler_netdrive::readdir (DIR *dir, dirent *de)
de->d_ino = hash_path_name (get_namehash (), de->d_name);
else
{
de->d_ino = readdir_get_ino (dir, nro->lpRemoteName, false);
de->d_ino = readdir_get_ino (nro->lpRemoteName, false);
/* We can't trust remote inode numbers of only 32 bit. That means,
all remote inode numbers when running under NT4, as well as
remote NT4 NTFS, as well as shares of Samba version < 3.0. */

View File

@ -65,6 +65,8 @@ static const char *proc_listing[] = {
NULL
};
#define PROC_DIR_COUNT 4
static const int PROC_LINK_COUNT = (sizeof (proc_listing) / sizeof (const char *)) - 1;
/* FH_PROC in the table below means the file/directory is handles by
@ -178,8 +180,10 @@ fhandler_proc::fstat (struct __stat64 *buf)
if (!*path)
{
buf->st_nlink = 1;
winpids pids ((DWORD) 0);
buf->st_ino = 2;
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = PROC_DIR_COUNT + 2 + pids.npids;
return 0;
}
else

View File

@ -88,6 +88,20 @@ typedef struct _FILE_NAMES_INFORMATION
WCHAR FileName[1];
} FILE_NAMES_INFORMATION, *PFILE_NAMES_INFORMATION;
typedef struct _FILE_DIRECTORY_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
typedef struct _FILE_BOTH_DIR_INFORMATION
{
ULONG NextEntryOffset;
@ -709,6 +723,9 @@ extern "C"
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
PTOKEN_PRIMARY_GROUP, PTOKEN_DEFAULT_DACL,
PTOKEN_SOURCE);
NTSTATUS NTAPI NtFsControlFile (HANDLE, HANDLE, PVOID, PVOID,
PIO_STATUS_BLOCK, ULONG, PVOID, ULONG,
PVOID, ULONG);
NTSTATUS NTAPI NtLockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG,
PLARGE_INTEGER, PULONG, SECTION_INHERIT,
@ -750,11 +767,42 @@ extern "C"
PSECURITY_DESCRIPTOR);
NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);
NTSTATUS NTAPI RtlAppendUnicodeToString (PUNICODE_STRING, PCWSTR);
NTSTATUS NTAPI RtlAppendUnicodeStringToString (PUNICODE_STRING,
PUNICODE_STRING);
NTSTATUS NTAPI RtlAnsiStringToUnicodeString (PUNICODE_STRING, PANSI_STRING,
BOOLEAN);
LONG NTAPI RtlCompareUnicodeString (PUNICODE_STRING, PUNICODE_STRING,
BOOLEAN);
VOID NTAPI RtlCopyUnicodeString (PUNICODE_STRING, PUNICODE_STRING);
ULONG WINAPI RtlCreateUnicodeStringFromAsciiz (PUNICODE_STRING, PCSTR);
BOOLEAN NTAPI RtlEqualUnicodeString (PUNICODE_STRING, PUNICODE_STRING,
BOOLEAN);
VOID NTAPI RtlFreeUnicodeString (PUNICODE_STRING);
VOID NTAPI RtlInitEmptyUnicodeString (PUNICODE_STRING, PCWSTR, USHORT);
VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
ULONG NTAPI RtlIsDosDeviceName_U (PCWSTR);
ULONG NTAPI RtlNtStatusToDosError (NTSTATUS);
NTSTATUS NTAPI RtlOemStringToUnicodeString (PUNICODE_STRING, POEM_STRING,
BOOLEAN);
VOID NTAPI RtlSecondsSince1970ToTime (ULONG, PLARGE_INTEGER);
/* A few Rtl functions are either actually macros, or they just don't
exist even though they would be a big help. We implement them here
as inline functions. */
inline
VOID NTAPI RtlInitEmptyUnicodeString(PUNICODE_STRING dest, PCWSTR buf,
USHORT len)
{
dest->Length = 0;
dest->MaximumLength = len;
dest->Buffer = (PWSTR) buf;
}
inline
VOID NTAPI RtlInitCountedUnicodeString (PUNICODE_STRING dest, USHORT len,
PCWSTR buf)
{
dest->Length = dest->MaximumLength = len;
dest->Buffer = (PWSTR) buf;
}
}

View File

@ -637,6 +637,23 @@ warn_msdos (const char *src)
SYMLINK_CONTENTS - just return symlink contents
*/
/* TODO: This implementation is only preliminary. For internal
purposes it's necessary to have a path_conv::check function which
takes a UNICODE_STRING src path, otherwise we waste a lot of time
for converting back and forth. The below implementation does
realy nothing but converting to char *, until path_conv handles
wide-char paths directly. */
void
path_conv::check (PUNICODE_STRING src, unsigned opt,
const suffix_info *suffixes)
{
char path[CYG_MAX_PATH];
user_shared->warned_msdos = true;
sys_wcstombs (path, CYG_MAX_PATH, src->Buffer, src->Length / 2);
path_conv::check (path, opt, suffixes);
}
void
path_conv::check (const char *src, unsigned opt,
const suffix_info *suffixes)
@ -1840,7 +1857,8 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev,
int
mount_info::get_mounts_here (const char *parent_dir, int parent_dir_len,
char **mount_points)
PUNICODE_STRING mount_points,
PUNICODE_STRING cygd)
{
int n_mounts = 0;
@ -1853,12 +1871,16 @@ mount_info::get_mounts_here (const char *parent_dir, int parent_dir_len,
if (last_slash == mi->posix_path)
{
if (parent_dir_len == 1 && mi->posix_pathlen > 1)
mount_points[n_mounts++] = last_slash + 1;
RtlCreateUnicodeStringFromAsciiz (&mount_points[n_mounts++],
last_slash + 1);
}
else if (parent_dir_len == last_slash - mi->posix_path
&& strncasematch (parent_dir, mi->posix_path, parent_dir_len))
mount_points[n_mounts++] = last_slash + 1;
RtlCreateUnicodeStringFromAsciiz (&mount_points[n_mounts++],
last_slash + 1);
}
RtlCreateUnicodeStringFromAsciiz (cygd, cygdrive + 1);
cygd->Length -= 2; // Strip trailing slash
return n_mounts;
}
@ -2794,8 +2816,7 @@ is_floppy (const char *dos)
char dev[256];
if (!QueryDosDevice (dos, dev, 256))
return false;
return strncasematch (dev, "\\Device\\Floppy", 14)
|| strcasematch (dev, "A:");
return strncasematch (dev, "\\Device\\Floppy", 14);
}
extern "C" FILE *

View File

@ -13,7 +13,6 @@ details. */
#include <sys/ioctl.h>
#include <fcntl.h>
#include <ntdef.h>
#define isproc_dev(devn) \
(devn == FH_PROC || devn == FH_REGISTRY || devn == FH_PROCESS || \
@ -234,8 +233,10 @@ class path_conv
void set_has_symlinks () {path_flags |= PATH_HAS_SYMLINKS;}
void set_exec (int x = 1) {path_flags |= x ? PATH_EXEC : PATH_NOTEXEC;}
void check (PUNICODE_STRING upath, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
void check (const char *src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
path_conv (const device& in_dev): fileattr (INVALID_FILE_ATTRIBUTES),
wide_path (NULL), path_flags (0), known_suffix (NULL), error (0),
@ -250,6 +251,12 @@ class path_conv
check (src, opt, suffixes);
}
path_conv (PUNICODE_STRING src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL)
{
check (src, opt | PC_NULLEMPTY, suffixes);
}
path_conv (const char *src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL)
{

View File

@ -91,7 +91,9 @@ class mount_info
int get_cygdrive_info (char *user, char *system, char* user_flags,
char* system_flags);
void cygdrive_posix_path (const char *src, char *dst, int trailing_slash_p);
int get_mounts_here (const char *parent_dir, int, char **mount_points);
int get_mounts_here (const char *parent_dir, int,
PUNICODE_STRING mount_points,
PUNICODE_STRING cygd);
private:

View File

@ -96,9 +96,6 @@ SYSTEM_INFO system_info;
static int __stdcall mknod_worker (const char *, mode_t, mode_t, _major_t,
_minor_t);
static int __stdcall stat_worker (const char *name, struct __stat64 *buf,
int nofollow) __attribute__ ((regparm (3)));
/* Close all files and process any queued deletions.
Lots of unix style applications will open a tmp file, unlink it,
but never call close. This function is called by _exit to
@ -1225,8 +1222,8 @@ sync ()
}
/* Cygwin internal */
static int __stdcall
stat_worker (const char *name, struct __stat64 *buf, int nofollow)
int __stdcall
stat_worker (path_conv &pc, struct __stat64 *buf)
{
int res = -1;
fhandler_base *fh = NULL;
@ -1235,8 +1232,7 @@ stat_worker (const char *name, struct __stat64 *buf, int nofollow)
if (efault.faulted (EFAULT))
goto error;
if (!(fh = build_fh_name (name, NULL, nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW,
stat_suffixes)))
if (!(fh = build_fh_pc (pc)))
goto error;
if (fh->error ())
@ -1246,8 +1242,8 @@ stat_worker (const char *name, struct __stat64 *buf, int nofollow)
}
else if (fh->exists ())
{
debug_printf ("(%s, %p, %d, %p), file_attributes %d", name, buf, nofollow,
fh, (DWORD) *fh);
debug_printf ("(%s, %p, %p), file_attributes %d",
pc.normalized_path, buf, fh, (DWORD) *fh);
memset (buf, 0, sizeof (*buf));
res = fh->fstat (buf);
if (!res)
@ -1266,7 +1262,7 @@ stat_worker (const char *name, struct __stat64 *buf, int nofollow)
delete fh;
error:
MALLOC_CHECK;
syscall_printf ("%d = (%s, %p)", res, name, buf);
syscall_printf ("%d = (%s, %p)", res, pc.normalized_path, buf);
return res;
}
@ -1274,7 +1270,8 @@ extern "C" int
stat64 (const char *name, struct __stat64 *buf)
{
syscall_printf ("entering");
return stat_worker (name, buf, 0);
path_conv pc (name, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
return stat_worker (pc, buf);
}
extern "C" int
@ -1312,7 +1309,8 @@ extern "C" int
lstat64 (const char *name, struct __stat64 *buf)
{
syscall_printf ("entering");
return stat_worker (name, buf, 1);
path_conv pc (name, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
return stat_worker (pc, buf);
}
/* lstat: Provided by SVR4 and 4.3+BSD, POSIX? */

View File

@ -97,6 +97,7 @@ extern const char case_folded_upper[];
#include <windows.h>
#include <wincrypt.h>
#include <lmcons.h>
#include <ntdef.h>
#undef _WINGDI_H
#undef _WINUSER_H
#undef _WINNLS_H
@ -290,8 +291,9 @@ int symlink_worker (const char *, const char *, bool, bool)
class path_conv;
int fcntl_worker (int fd, int cmd, void *arg);
int __stdcall stat_worker (path_conv &pc, struct __stat64 *buf) __attribute__ ((regparm (2)));
__ino64_t __stdcall readdir_get_ino (struct __DIR *dir, const char *path, bool dot_dot) __attribute__ ((regparm (3)));
__ino64_t __stdcall readdir_get_ino (const char *path, bool dot_dot) __attribute__ ((regparm (2)));
extern "C" int low_priority_sleep (DWORD) __attribute__ ((regparm (1)));
#define SLEEP_0_STAY_LOW INFINITE