4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-15 11:00:04 +08:00
Corinna Vinschen 214c3a1167 * 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-26 17:30:54 +00:00

333 lines
6.7 KiB
C++

/* dir.cc: Posix directory-related routines
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006, 2007 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#define _COMPILING_NEWLIB
#include <dirent.h>
#include "pinfo.h"
#include "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "cygtls.h"
#include "perprocess.h"
#include "cygwin/version.h"
extern "C" int
dirfd (DIR *dir)
{
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("-1 = dirfd (%p)", dir);
return -1;
}
return dir->__d_fd;
}
/* Symbol kept for backward compatibility. Don't remove. Don't declare
in public header file. */
extern "C" DIR *
__opendir_with_d_ino (const char *name)
{
return opendir (name);
}
/* opendir: POSIX 5.1.2.1 */
extern "C" DIR *
opendir (const char *name)
{
fhandler_base *fh;
DIR *res;
fh = build_fh_name (name, NULL, PC_SYM_FOLLOW);
if (!fh)
res = NULL;
else if (fh->exists ())
res = fh->opendir (-1);
else
{
set_errno (ENOENT);
res = NULL;
}
if (!res && fh)
delete fh;
return res;
}
extern "C" DIR *
fdopendir (int fd)
{
DIR *res = NULL;
cygheap_fdget cfd (fd);
if (cfd >= 0)
res = cfd->opendir (fd);
return res;
}
static int
readdir_worker (DIR *dir, dirent *de)
{
myfault efault;
if (efault.faulted ())
return EFAULT;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
syscall_printf ("%p = readdir (%p)", NULL, dir);
return EBADF;
}
de->d_ino = 0;
int res = ((fhandler_base *) dir->__fh)->readdir (dir, de);
if (res == ENMFILE)
{
if (!(dir->__flags & dirent_saw_dot))
{
strcpy (de->d_name, ".");
dir->__flags |= dirent_saw_dot;
dir->__d_position++;
res = 0;
}
else if (!(dir->__flags & dirent_saw_dot_dot))
{
strcpy (de->d_name, "..");
dir->__flags |= dirent_saw_dot_dot;
dir->__d_position++;
res = 0;
}
}
if (!res && !de->d_ino)
{
bool is_dot = false;
bool is_dot_dot = false;
if (de->d_name[0] == '.')
{
if (de->d_name[1] == '\0')
is_dot = true;
else if (de->d_name[1] == '.' && de->d_name[2] == '\0')
is_dot_dot = true;
}
if (is_dot_dot && !(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (((fhandler_base *) dir->__fh)->get_name (),
true);
else
{
/* Compute d_ino by combining filename hash with directory hash. */
de->d_ino = ((fhandler_base *) dir->__fh)->get_namehash ();
if (!is_dot && !is_dot_dot)
{
const char *w32name = ((fhandler_base *) dir->__fh)->get_win32_name ();
DWORD devn = ((fhandler_base *) dir->__fh)->get_device ();
/* Paths below /proc don't have a Win32 pendant. */
if (isproc_dev (devn))
de->d_ino = hash_path_name (de->d_ino, "/");
/* A drive's root dir has a trailing backslash already. */
else if (w32name[1] != ':' || w32name[2] != '\\' || w32name[3])
de->d_ino = hash_path_name (de->d_ino, "\\");
de->d_ino = hash_path_name (de->d_ino, de->d_name);
}
}
}
/* This fills out the old 32 bit d_ino field for old applications,
build under Cygwin before 1.5.x. */
de->__d_internal1 = de->d_ino;
return res;
}
/* readdir: POSIX 5.1.2.1 */
extern "C" struct dirent *
readdir (DIR *dir)
{
int res = readdir_worker (dir, dir->__d_dirent);
if (res == 0)
return dir->__d_dirent;
if (res != ENMFILE)
set_errno (res);
return NULL;
}
extern "C" int
readdir_r (DIR *dir, dirent *de, dirent **ode)
{
int res = readdir_worker (dir, de);
if (!res)
*ode = de;
else
{
*ode = NULL;
if (res == ENMFILE)
res = 0;
}
return res;
}
extern "C" _off64_t
telldir64 (DIR *dir)
{
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
return 0;
return ((fhandler_base *) dir->__fh)->telldir (dir);
}
/* telldir */
extern "C" _off_t
telldir (DIR *dir)
{
return telldir64 (dir);
}
extern "C" void
seekdir64 (DIR *dir, _off64_t loc)
{
myfault efault;
if (efault.faulted (EFAULT))
return;
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
dir->__flags &= dirent_info_mask;
return ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
}
/* seekdir */
extern "C" void
seekdir (DIR *dir, _off_t loc)
{
seekdir64 (dir, (_off64_t)loc);
}
/* rewinddir: POSIX 5.1.2.1 */
extern "C" void
rewinddir (DIR *dir)
{
myfault efault;
if (efault.faulted (EFAULT))
return;
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
dir->__flags &= dirent_info_mask;
return ((fhandler_base *) dir->__fh)->rewinddir (dir);
}
/* closedir: POSIX 5.1.2.1 */
extern "C" int
closedir (DIR *dir)
{
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("-1 = closedir (%p)", dir);
return -1;
}
/* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0;
int res = ((fhandler_base *) dir->__fh)->closedir (dir);
cygheap->fdtab.release (dir->__d_fd);
free (dir->__d_dirname);
free (dir->__d_dirent);
free (dir);
syscall_printf ("%d = closedir (%p)", res);
return res;
}
/* mkdir: POSIX 5.4.1.1 */
extern "C" int
mkdir (const char *dir, mode_t mode)
{
int res = -1;
fhandler_base *fh = NULL;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW)))
goto done; /* errno already set */;
if (fh->error ())
{
debug_printf ("got %d error from build_fh_name", fh->error ());
set_errno (fh->error ());
}
else if (has_dot_last_component (dir, true))
set_errno (fh->exists () ? EEXIST : ENOENT);
else if (!fh->mkdir (mode))
res = 0;
delete fh;
done:
syscall_printf ("%d = mkdir (%s, %d)", res, dir, mode);
return res;
}
/* rmdir: POSIX 5.5.2.1 */
extern "C" int
rmdir (const char *dir)
{
int res = -1;
fhandler_base *fh = NULL;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW)))
goto done; /* errno already set */;
if (fh->error ())
{
debug_printf ("got %d error from build_fh_name", fh->error ());
set_errno (fh->error ());
}
else if (!fh->exists ())
set_errno (ENOENT);
else if (has_dot_last_component (dir, false))
set_errno (EINVAL);
else if (!fh->rmdir ())
res = 0;
delete fh;
done:
syscall_printf ("%d = rmdir (%s)", res, dir);
return res;
}