newlib/winsup/cygwin/dir.cc
Christopher Faylor 893ac8e03c Replace valid memory checks with new myfault class "exception handling", almost
everywhere.  Leave some thread.cc stuff alone for now.
* cygtls.h: Kludge some definitions to avoid including a problematic windows
header.
(_cygtls::_myfault): New entry.
(_cygtls::_myfault_errno): Ditto.
(_cygtls::fault_guarded): New function.
(_cygtls::setup_fault): Ditto.
(_cygtls::return_from_fault): Ditto.
(_cygtls::clear_fault): Ditto.
(myfault): New class.
* exceptions.cc (handle_exceptions): Handle case of guarded fault in system
routine.
* gendef: Add another entry point for setjmp that the compiler doesn't know
about and won't complain about.
* gentls_offsets: Just include windows.h rather than kludging a HANDLE def.
* miscfuncs.cc (check_null_str): Delete.
(check_null_empty_str): Ditto.
(check_null_empty_str_errno): Ditto.
(check_null_str_errno): Ditto.
(__check_null_invalid_struct): Ditto.
(__check_null_invalid_struct_errno): Ditto.
(__check_invalid_read_ptr): Ditto.
(__check_invalid_read_ptr_errno): Ditto.
(dummytest): New function.
(check_iovec_for_read): Delete.
(chec_iovec): Rename from check_iovec_for_write.  Take a read/write parameter.
* tlsoffsets.h: Regenerate.
* winsup.h: Remove check_* declarations.
(check_iovec_for_read): Delete declaration.  Turn into a define instead.
(check_iovec_for_write): Ditto.
(check_iovec): New declaration.
* thread.h: Use ifdef guard name consistent with other header files.
2005-07-03 02:40:30 +00:00

273 lines
5.4 KiB
C++

/* dir.cc: Posix directory-related routines
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 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"
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)
res->__flags = 0;
else if (fh)
delete fh;
return res;
}
/* readdir: POSIX 5.1.2.1 */
extern "C" struct dirent *
readdir (DIR *dir)
{
myfault efault;
if (efault.faulted (EFAULT))
return NULL;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("%p = readdir (%p)", NULL, dir);
return NULL;
}
dirent *res = ((fhandler_base *) dir->__fh)->readdir (dir);
if (!res)
{
if (!(dir->__flags & dirent_saw_dot))
{
res = dir->__d_dirent;
strcpy (res->d_name, ".");
dir->__flags |= dirent_saw_dot;
dir->__d_position++;
}
else if (!(dir->__flags & dirent_saw_dot_dot))
{
res = dir->__d_dirent;
strcpy (res->d_name, "..");
dir->__flags |= dirent_saw_dot_dot;
dir->__d_position++;
}
}
if (res)
{
/* Compute d_ino by combining filename hash with the directory hash
(which was stored in dir->__d_dirhash when opendir was called). */
if (res->d_name[0] == '.')
{
if (res->d_name[1] == '\0')
{
dir->__d_dirent->d_ino = dir->__d_dirhash;
dir->__flags |= dirent_saw_dot;
}
else if (res->d_name[1] != '.' || res->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, '\\')))
dir->__d_dirent->d_ino = hash_path_name (0, ".");
else
{
*p = '\0';
dir->__d_dirent->d_ino = hash_path_name (0, up);
}
}
}
else
{
hashit:
__ino64_t dino = hash_path_name (dir->__d_dirhash, "\\");
dir->__d_dirent->d_ino = hash_path_name (dino, res->d_name);
}
res->__ino32 = dir->__d_dirent->d_ino; // for legacy applications
}
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 = 0;
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 = 0;
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;
if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW | PC_WRITABLE)))
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;
if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW | PC_WRITABLE)))
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;
}