From e5dcb6ada27fbc7c8ca6ec32c384ebe84cac8a75 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Fri, 20 Jan 2006 18:27:08 +0000 Subject: Only use name change patch in dir.cc. --- winsup/cygwin/ChangeLog | 4 +- winsup/cygwin/dir.cc | 333 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 winsup/cygwin/dir.cc diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 67023d1a7fe..c9ed800ffda 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -6,8 +6,8 @@ 2006-01-19 Christopher Faylor - * dir.cc (readdir_worker): Fill in invalid fields with -1. Accommodate - name change from __ino32 to __invalid_ino32. + * dir.cc (readdir_worker): Accommodate name change from __ino32 to + __invalid_ino32. * include/sys/dirent.h (__invalid_ino32): Rename from __ino32. Don't define unused d_type macros. diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc new file mode 100644 index 00000000000..44f0b05a6ad --- /dev/null +++ b/winsup/cygwin/dir.cc @@ -0,0 +1,333 @@ +/* dir.cc: Posix directory-related routines + + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006 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 +#include +#include + +#define _COMPILING_NEWLIB +#include + +#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_dirent->d_fd; +} + +/* 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 (); + else + { + set_errno (ENOENT); + res = NULL; + } + + if (res) + /* nothing */; + else if (fh) + delete fh; + 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; + } + + 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) + /* error return */; + else if (!CYGWIN_VERSION_CHECK_FOR_NEEDS_D_INO) + { + de->__invalid_d_ino = (ino_t) 0; + de->__invalid_ino32 = (uint32_t) 0; + if (de->d_name[0] == '.') + { + if (de->d_name[1] == '\0') + dir->__flags |= dirent_saw_dot; + else if (de->d_name[1] == '.' && de->d_name[2] == '\0') + dir->__flags |= dirent_saw_dot_dot; + } + } + else + { + /* Compute d_ino by combining filename hash with the directory hash + (which was stored in dir->__d_dirhash when opendir was called). */ + if (de->d_name[0] == '.') + { + if (de->d_name[1] == '\0') + { + de->__invalid_d_ino = dir->__d_dirhash; + dir->__flags |= dirent_saw_dot; + } + else if (de->d_name[1] != '.' || de->d_name[2] != '\0') + goto hashit; + else + { + dir->__flags |= dirent_saw_dot_dot; + char *p, up[strlen (dir->__d_dirname) + 1]; + strcpy (up, dir->__d_dirname); + if (!(p = strrchr (up, '\\'))) + goto hashit; + *p = '\0'; + if (!(p = strrchr (up, '\\'))) + de->__invalid_d_ino = hash_path_name (0, "."); + else + { + *p = '\0'; + de->__invalid_d_ino = hash_path_name (0, up); + } + } + } + else + { + hashit: + __ino64_t dino = hash_path_name (dir->__d_dirhash, "\\"); + de->__invalid_d_ino = hash_path_name (dino, de->d_name); + } + de->__invalid_ino32 = de->__invalid_d_ino; // for legacy applications + } + 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_isroot; + 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_isroot; + 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_dirent->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 (has_dot_last_component (dir)) + { + set_errno (ENOENT); + 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->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 (has_dot_last_component (dir)) + { + set_errno (EINVAL); + 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->rmdir ()) + res = 0; + delete fh; + + done: + syscall_printf ("%d = rmdir (%s)", res, dir); + return res; +} -- cgit v1.2.1