* fhandler_disk_file.cc (fhandler_disk_file::opendir): Only set d_cachepos

under NT or suffer memory corruption.
(fhandler_disk_file::readdir_helper): Avoid else with a return.  Just calculate
extension location once when doing symlink checks.
(fhandler_disk_file::readdir): Make debug output more useful.
(fhandler_disk_file::readdir_9x): Ditto.  Eliminate redundant variable.
This commit is contained in:
Christopher Faylor 2006-02-28 04:23:17 +00:00
parent 6a7a2f4bbe
commit 4f1558d132
2 changed files with 70 additions and 55 deletions

View File

@ -1,3 +1,12 @@
2006-02-27 Christopher Faylor <cgf@timesys.com>
* fhandler_disk_file.cc (fhandler_disk_file::opendir): Only set
d_cachepos under NT or suffer memory corruption.
(fhandler_disk_file::readdir_helper): Avoid else with a return. Just
calculate extension location once when doing symlink checks.
(fhandler_disk_file::readdir): Make debug output more useful.
(fhandler_disk_file::readdir_9x): Ditto. Eliminate redundant variable.
2006-02-27 Christopher Faylor <cgf@timesys.com> 2006-02-27 Christopher Faylor <cgf@timesys.com>
* include/sys/termios.h (cfsetispeed): Just define as a function rather * include/sys/termios.h (cfsetispeed): Just define as a function rather

View File

@ -1434,7 +1434,6 @@ fhandler_disk_file::opendir ()
else else
{ {
strcpy (d_dirname (dir), get_win32_name ()); strcpy (d_dirname (dir), get_win32_name ());
d_cachepos (dir) = 0;
dir->__d_dirent->__d_version = __DIRENT_VERSION; dir->__d_dirent->__d_version = __DIRENT_VERSION;
cygheap_fdnew fd; cygheap_fdnew fd;
@ -1459,41 +1458,45 @@ fhandler_disk_file::opendir ()
dir->__d_position = 0; dir->__d_position = 0;
dir->__flags = (pc.normalized_path[0] == '/' && pc.normalized_path[1] == '\0') ? dirent_isroot : 0; dir->__flags = (pc.normalized_path[0] == '/' && pc.normalized_path[1] == '\0') ? dirent_isroot : 0;
if (!pc.isspecial () && wincap.is_winnt ()) if (wincap.is_winnt ())
{ {
OBJECT_ATTRIBUTES attr; d_cachepos (dir) = 0;
WCHAR wpath[CYG_MAX_PATH + 10]; if (!pc.isspecial ())
UNICODE_STRING upath = {0, sizeof (wpath), wpath};
IO_STATUS_BLOCK io;
NTSTATUS status;
SECURITY_ATTRIBUTES sa = sec_none;
pc.get_nt_native_path (upath);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL, sa.lpSecurityDescriptor);
status = NtOpenFile (&dir->__handle,
SYNCHRONIZE | FILE_LIST_DIRECTORY,
&attr, &io, wincap.shared (),
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
if (!NT_SUCCESS (status))
{ {
__seterrno_from_nt_status (status); OBJECT_ATTRIBUTES attr;
goto free_dirent; WCHAR wpath[CYG_MAX_PATH + 10];
} UNICODE_STRING upath = {0, sizeof (wpath), wpath};
IO_STATUS_BLOCK io;
NTSTATUS status;
SECURITY_ATTRIBUTES sa = sec_none;
pc.get_nt_native_path (upath);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL, sa.lpSecurityDescriptor);
/* FileIdBothDirectoryInformation is apparently unsupported on XP status = NtOpenFile (&dir->__handle,
when accessing directories on UDF. When trying to use it so, SYNCHRONIZE | FILE_LIST_DIRECTORY,
NtQueryDirectoryFile returns with STATUS_ACCESS_VIOLATION. It's &attr, &io, wincap.shared (),
not clear if the call isn't also unsupported on other OS/FS FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
combinations (say, Win2K/CDFS or so). Instead of testing in if (!NT_SUCCESS (status))
readdir for yet another error code, let's use {
FileIdBothDirectoryInformation only on filesystems supporting __seterrno_from_nt_status (status);
persistent ACLs, FileBothDirectoryInformation otherwise. */ goto free_dirent;
if (pc.hasgood_inode ()) }
{
dir->__flags |= dirent_set_d_ino; /* FileIdBothDirectoryInformation is apparently unsupported on XP
if (wincap.has_fileid_dirinfo () && !pc.is_samba ()) when accessing directories on UDF. When trying to use it so,
dir->__flags |= dirent_get_d_ino; NtQueryDirectoryFile returns with STATUS_ACCESS_VIOLATION. It's
not clear if the call isn't also unsupported on other OS/FS
combinations (say, Win2K/CDFS or so). Instead of testing in
readdir for yet another error code, let's use
FileIdBothDirectoryInformation only on filesystems supporting
persistent ACLs, FileBothDirectoryInformation otherwise. */
if (pc.hasgood_inode ())
{
dir->__flags |= dirent_set_d_ino;
if (wincap.has_fileid_dirinfo () && !pc.is_samba ())
dir->__flags |= dirent_get_d_ino;
}
} }
} }
res = dir; res = dir;
@ -1538,13 +1541,11 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
added = true; added = true;
} }
if (added) if (!added)
{
attr = 0;
dir->__flags &= ~dirent_set_d_ino;
}
else
return geterrno_from_win_error (w32_err); 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 /* Check for Windows shortcut. If it's a Cygwin or U/WIN
@ -1552,15 +1553,15 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
if (attr & FILE_ATTRIBUTE_READONLY) if (attr & FILE_ATTRIBUTE_READONLY)
{ {
char *c = fname; char *c = fname;
int len = strlen (c); char *e = strchr (fname, '\0') - 4;
if (strcasematch (c + len - 4, ".lnk")) if (e > c && strcasematch (e, ".lnk"))
{ {
char fbuf[CYG_MAX_PATH]; char fbuf[CYG_MAX_PATH];
strcpy (fbuf, d_dirname (dir)); strcpy (fbuf, d_dirname (dir));
strcat (fbuf, c); strcat (fbuf, c);
path_conv fpath (fbuf, PC_SYM_NOFOLLOW); path_conv fpath (fbuf, PC_SYM_NOFOLLOW);
if (fpath.issymlink () || fpath.is_fs_special ()) if (fpath.issymlink () || fpath.is_fs_special ())
c[len - 4] = '\0'; *e = '\0';
} }
} }
@ -1745,7 +1746,7 @@ fhandler_disk_file::readdir (DIR *dir, dirent *de)
res = 0; res = 0;
} }
syscall_printf ("%d = readdir (%p) (%s)", dir, &de, de->d_name); syscall_printf ("%d = readdir (%p, %p) (%s)", res, dir, &de, res ? "***" : de->d_name);
return res; return res;
} }
@ -1754,32 +1755,37 @@ fhandler_disk_file::readdir_9x (DIR *dir, dirent *de)
{ {
WIN32_FIND_DATA buf; WIN32_FIND_DATA buf;
int res = 0; int res = 0;
BOOL ret = TRUE;
if (!dir->__handle) if (!dir->__handle)
{ {
res = ENMFILE; res = ENMFILE;
goto out; goto out;
} }
DWORD lasterr;
if (dir->__handle == INVALID_HANDLE_VALUE && dir->__d_position == 0) if (dir->__d_position != 0)
lasterr = FindNextFileA (dir->__handle, &buf) ? 0 : GetLastError ();
else if (dir->__handle != INVALID_HANDLE_VALUE)
{
res = EBADF;
goto out;
}
else
{ {
int len = strlen (dir->__d_dirname); int len = strlen (dir->__d_dirname);
strcpy (dir->__d_dirname + len, "*"); strcpy (dir->__d_dirname + len, "*");
dir->__handle = FindFirstFile (dir->__d_dirname, &buf); dir->__handle = FindFirstFile (dir->__d_dirname, &buf);
dir->__d_dirname[len] = '\0'; dir->__d_dirname[len] = '\0';
DWORD lasterr = GetLastError (); if (dir->__handle != INVALID_HANDLE_VALUE)
if (dir->__handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) lasterr = 0;
else if ((lasterr = GetLastError ()) != ERROR_NO_MORE_FILES)
{ {
res = geterrno_from_win_error (); res = geterrno_from_win_error (lasterr);
goto out; goto out;
} }
} }
else
ret = FindNextFileA (dir->__handle, &buf);
if (!(res = readdir_helper (dir, de, ret ? 0 : GetLastError (), if (!(res = readdir_helper (dir, de, lasterr, buf.dwFileAttributes,
buf.dwFileAttributes, buf.cFileName))) buf.cFileName)))
dir->__d_position++; dir->__d_position++;
else else
{ {
@ -1788,7 +1794,7 @@ fhandler_disk_file::readdir_9x (DIR *dir, dirent *de)
} }
out: out:
syscall_printf ("%d = readdir (%p) (%s)", dir, &de, de->d_name); syscall_printf ("%d = readdir (%p, %p) (%s)", res, dir, &de, res ? "***" : de->d_name);
return res; return res;
} }