* Makefile.in (DLL_OFILES): Add fhandler_disk_file.o.

* cygheap.h (cygheap_fdnew::operator =): New operator.
* dir.cc: Add invalid struct checking throughout.  Use methods for all
directory manipulation throughout.
* fhandler.cc: Move fhandler_disk_file stuff to own file.
(fhandler_base::opendir): New method.
(fhandler_base::readdir): New method.
(fhandler_base::telldir): New method.
(fhandler_base::seekdir): New method.
(fhandler_base::rewinddir): New method.
(fhandler_base::closedir): New method.
* fhandler_disk_file.cc: New file.
* fhandler.h (fhandler_base): Declare new virtual methods.
(fhandler_disk_file): Ditto.
(fhandler_cygdrive): New class.
* path.cc (conv_path_list): Use strccpy to break apart path.
This commit is contained in:
Christopher Faylor
2001-11-21 06:47:57 +00:00
parent f6a6c2a358
commit 7903ee6955
8 changed files with 895 additions and 743 deletions

View File

@@ -65,6 +65,8 @@ writable_directory (const char *file)
extern "C" int
dirfd (DIR *dir)
{
if (check_null_invalid_struct_errno (dir))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
@@ -76,214 +78,80 @@ dirfd (DIR *dir)
/* opendir: POSIX 5.1.2.1 */
extern "C" DIR *
opendir (const char *dirname)
opendir (const char *name)
{
int len;
DIR *dir;
DIR *res = 0;
struct stat statbuf;
fhandler_base *fh;
path_conv pc;
DIR *res = NULL;
path_conv real_dirname;
if (stat_worker (dirname, &statbuf, 0, &real_dirname) == -1)
goto failed;
if (!(statbuf.st_mode & S_IFDIR))
{
set_errno (ENOTDIR);
goto failed;
}
len = strlen (real_dirname);
if (len > MAX_PATH - 3)
{
set_errno (ENAMETOOLONG);
goto failed;
}
if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL)
{
set_errno (ENOMEM);
goto failed;
}
if ((dir->__d_dirname = (char *) malloc (len + 3)) == NULL)
{
free (dir);
set_errno (ENOMEM);
goto failed;
}
if ((dir->__d_dirent =
(struct dirent *) malloc (sizeof (struct dirent))) == NULL)
{
free (dir->__d_dirname);
free (dir);
set_errno (ENOMEM);
goto failed;
}
strcpy (dir->__d_dirname, real_dirname.get_win32 ());
dir->__d_dirent->d_version = __DIRENT_VERSION;
dir->__d_dirent->d_fd = open (dir->__d_dirname, O_RDONLY | O_DIROPEN);
/* FindFirstFile doesn't seem to like duplicate /'s. */
len = strlen (dir->__d_dirname);
if (len == 0 || SLASH_P (dir->__d_dirname[len - 1]))
strcat (dir->__d_dirname, "*");
else
strcat (dir->__d_dirname, "\\*"); /**/
dir->__d_cookie = __DIRENT_COOKIE;
dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
dir->__d_dirhash = statbuf.st_ino;
res = dir;
failed:
syscall_printf ("%p = opendir (%s)", res, dirname);
fh = cygheap->fdtab.build_fhandler_from_name (-1, name, NULL, pc,
PC_SYM_FOLLOW | PC_FULL, NULL);
res = fh->opendir (name, pc);
if (!res)
delete fh;
return res;
}
/* readdir: POSIX 5.1.2.1 */
extern "C" struct dirent *
readdir (DIR * dir)
readdir (DIR *dir)
{
WIN32_FIND_DATA buf;
HANDLE handle;
struct dirent *res = NULL;
if (check_null_invalid_struct_errno (dir))
return NULL;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("%p = readdir (%p)", res, dir);
return res;
syscall_printf ("%p = readdir (%p)", NULL, dir);
return NULL;
}
if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE
&& dir->__d_position == 0)
{
handle = FindFirstFileA (dir->__d_dirname, &buf);
DWORD lasterr = GetLastError ();
dir->__d_u.__d_data.__handle = handle;
if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES))
{
seterrno_from_win_error (__FILE__, __LINE__, lasterr);
return res;
}
}
else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
{
return res;
}
else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf))
{
DWORD lasterr = GetLastError ();
(void) FindClose (dir->__d_u.__d_data.__handle);
dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
/* POSIX says you shouldn't set errno when readdir can't
find any more files; so, if another error we leave it set. */
if (lasterr != ERROR_NO_MORE_FILES)
seterrno_from_win_error (__FILE__, __LINE__, lasterr);
syscall_printf ("%p = readdir (%p)", res, dir);
return res;
}
/* We get here if `buf' contains valid data. */
strcpy (dir->__d_dirent->d_name, buf.cFileName);
/* Check for Windows shortcut. If it's a Cygwin or U/WIN
symlink, drop the .lnk suffix. */
if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
{
char *c = dir->__d_dirent->d_name;
int len = strlen (c);
if (strcasematch (c + len - 4, ".lnk"))
{
char fbuf[MAX_PATH + 1];
strcpy (fbuf, dir->__d_dirname);
strcpy (fbuf + strlen (fbuf) - 1, dir->__d_dirent->d_name);
path_conv fpath (fbuf, PC_SYM_NOFOLLOW);
if (fpath.issymlink ())
c[len - 4] = '\0';
}
}
/* Compute d_ino by combining filename hash with the directory hash
(which was stored in dir->__d_dirhash when opendir was called). */
if (buf.cFileName[0] == '.')
{
if (buf.cFileName[1] == '\0')
dir->__d_dirent->d_ino = dir->__d_dirhash;
else if (buf.cFileName[1] != '.' || buf.cFileName[2] != '\0')
goto hashit;
else
{
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:
ino_t dino = hash_path_name (dir->__d_dirhash, "\\");
dir->__d_dirent->d_ino = hash_path_name (dino, buf.cFileName);
}
++dir->__d_position;
res = dir->__d_dirent;
syscall_printf ("%p = readdir (%p) (%s)",
&dir->__d_dirent, dir, buf.cFileName);
return res;
return ((fhandler_base *) dir->__d_u.__d_data.__fh)->readdir (dir);
}
/* telldir */
extern "C" off_t
telldir (DIR * dir)
telldir (DIR *dir)
{
if (check_null_invalid_struct_errno (dir))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
return 0;
return dir->__d_position;
return ((fhandler_base *) dir->__d_u.__d_data.__fh)->telldir (dir);
}
/* seekdir */
extern "C" void
seekdir (DIR * dir, off_t loc)
seekdir (DIR *dir, off_t loc)
{
if (check_null_invalid_struct_errno (dir))
return;
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
rewinddir (dir);
while (loc > dir->__d_position)
if (! readdir (dir))
break;
return ((fhandler_base *) dir->__d_u.__d_data.__fh)->seekdir (dir, loc);
}
/* rewinddir: POSIX 5.1.2.1 */
extern "C" void
rewinddir (DIR * dir)
rewinddir (DIR *dir)
{
syscall_printf ("rewinddir (%p)", dir);
if (check_null_invalid_struct_errno (dir))
return;
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE)
{
(void) FindClose (dir->__d_u.__d_data.__handle);
dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
}
dir->__d_position = 0;
return ((fhandler_base *) dir->__d_u.__d_data.__fh)->rewinddir (dir);
}
/* closedir: POSIX 5.1.2.1 */
extern "C" int
closedir (DIR * dir)
closedir (DIR *dir)
{
if (check_null_invalid_struct_errno (dir))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
@@ -291,25 +159,18 @@ closedir (DIR * dir)
return -1;
}
if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE &&
FindClose (dir->__d_u.__d_data.__handle) == 0)
{
__seterrno ();
syscall_printf ("-1 = closedir (%p)", dir);
return -1;
}
if (dir->__d_dirent->d_fd >= 0)
close (dir->__d_dirent->d_fd);
/* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0;
int res = ((fhandler_base *) dir->__d_u.__d_data.__fh)->closedir (dir);
cygheap->fdtab.release (dir->__d_dirent->d_fd);
free (dir->__d_dirname);
free (dir->__d_dirent);
free (dir);
syscall_printf ("0 = closedir (%p)", dir);
return 0;
syscall_printf ("%d = closedir (%p)", res);
return res;
}
/* mkdir: POSIX 5.4.1.1 */