newlib/winsup/cygwin/dir.cc

446 lines
11 KiB
C++
Raw Normal View History

2000-02-17 20:38:33 +01:00
/* dir.cc: Posix directory-related routines
2001-09-11 22:01:02 +02:00
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
2000-02-17 20:38:33 +01:00
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 <sys/fcntl.h>
2000-02-17 20:38:33 +01:00
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#define _COMPILING_NEWLIB
#include <dirent.h>
#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
2001-03-05 07:28:25 +01:00
#include "perprocess.h"
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
2000-02-17 20:38:33 +01:00
/* Cygwin internal */
/* Return whether the directory of a file is writable. Return 1 if it
is. Otherwise, return 0, and set errno appropriately. */
int __stdcall
writable_directory (const char *file)
{
#if 0
2000-02-17 20:38:33 +01:00
char dir[strlen (file) + 1];
strcpy (dir, file);
const char *usedir;
char *slash = strrchr (dir, '\\');
if (slash == NULL)
usedir = ".";
else if (slash == dir)
{
usedir = "\\";
}
2000-02-17 20:38:33 +01:00
else
{
*slash = '\0';
usedir = dir;
}
int acc = access (usedir, W_OK);
return acc == 0;
#else
return 1;
#endif
2000-02-17 20:38:33 +01:00
}
extern "C" int
dirfd (DIR *dir)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("-1 = dirfd (%p)", dir);
return -1;
}
return dir->__d_dirent->d_fd;
}
2000-02-17 20:38:33 +01:00
/* opendir: POSIX 5.1.2.1 */
extern "C" DIR *
opendir (const char *dirname)
{
int len;
DIR *dir;
DIR *res = 0;
struct stat statbuf;
path_conv real_dirname (dirname, PC_SYM_FOLLOW | PC_FULL);
2000-02-17 20:38:33 +01:00
if (real_dirname.error)
{
set_errno (real_dirname.error);
goto failed;
}
if (stat (real_dirname, &statbuf) == -1)
2000-02-17 20:38:33 +01:00
goto failed;
if (!(statbuf.st_mode & S_IFDIR))
{
set_errno (ENOTDIR);
goto failed;
}
len = strlen (real_dirname);
2000-02-17 20:38:33 +01:00
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);
2000-02-17 20:38:33 +01:00
/* 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);
return res;
}
/* readdir: POSIX 5.1.2.1 */
extern "C" struct dirent *
readdir (DIR * dir)
{
WIN32_FIND_DATA buf;
HANDLE handle;
struct dirent *res = NULL;
2000-02-17 20:38:33 +01:00
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("%p = readdir (%p)", res, dir);
return res;
}
if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE
&& dir->__d_position == 0)
2000-02-17 20:38:33 +01:00
{
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))
2000-02-17 20:38:33 +01:00
{
seterrno_from_win_error (__FILE__, __LINE__, lasterr);
2000-02-17 20:38:33 +01:00
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))
2000-02-17 20:38:33 +01:00
{
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;
2000-02-17 20:38:33 +01:00
}
/* 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. */
* Makefile.in: Add `-lshell32 -luuid' to link pass for new-cygwin1.dll. * autoload.cc: Add LoadDLLinitfunc for ole32.dll. Add LoadDLLfuncEx statements for CoInitialize@4, CoUninitialize@0 and CoCreateInstance@20. * dir.cc (dir_suffixes): New datastructure. (readdir): Check for R/O *.lnk files to hide the suffix. (opendir): Use `dir_suffixes' in path conversion. (rmdir): Ditto. * fhandler.cc (fhandler_disk_file::fstat): Add S_IFLNK flag before calling `get_file_attribute'. Take FILE_ATTRIBUTE_READONLY into account only if the file is no symlink. * path.cc (inner_suffixes): New datastructure. (SYMLINKATTR): Eliminated. (path_conv::check): Use `inner_suffixes' on inner path components. (shortcut_header): New global static variable. (shortcut_initalized): Ditto. (create_shortcut_header): New function. (cmp_shortcut_header): Ditto. (symlink): Create symlinks by creating windows shortcuts. Preserve the old code. (symlink_info::check_shortcut): New method. (symlink_info::check_sysfile): Ditto. (symlink_info::check): Check for shortcuts. Move code reading old system attribute symlinks into symlink_info::check_sysfile(). (chdir): Use `dir_suffixes' in path conversion. * security.cc (get_file_attribute): Check for S_IFLNK flag. Force 0777 permissions then. * spawn.cc (std_suffixes): Add ".lnk" suffix. * syscalls.cc (_unlink): Use `inner_suffixes' in path conversion. Check for shortcut symlinks to eliminate R/O attribute before calling DeleteFile(). (stat_suffixes): Add ".lnk" suffix. (stat_worker): Force 0777 permissions if file is a symlink.
2001-02-21 22:49:37 +01:00
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';
}
* Makefile.in: Add `-lshell32 -luuid' to link pass for new-cygwin1.dll. * autoload.cc: Add LoadDLLinitfunc for ole32.dll. Add LoadDLLfuncEx statements for CoInitialize@4, CoUninitialize@0 and CoCreateInstance@20. * dir.cc (dir_suffixes): New datastructure. (readdir): Check for R/O *.lnk files to hide the suffix. (opendir): Use `dir_suffixes' in path conversion. (rmdir): Ditto. * fhandler.cc (fhandler_disk_file::fstat): Add S_IFLNK flag before calling `get_file_attribute'. Take FILE_ATTRIBUTE_READONLY into account only if the file is no symlink. * path.cc (inner_suffixes): New datastructure. (SYMLINKATTR): Eliminated. (path_conv::check): Use `inner_suffixes' on inner path components. (shortcut_header): New global static variable. (shortcut_initalized): Ditto. (create_shortcut_header): New function. (cmp_shortcut_header): Ditto. (symlink): Create symlinks by creating windows shortcuts. Preserve the old code. (symlink_info::check_shortcut): New method. (symlink_info::check_sysfile): Ditto. (symlink_info::check): Check for shortcuts. Move code reading old system attribute symlinks into symlink_info::check_sysfile(). (chdir): Use `dir_suffixes' in path conversion. * security.cc (get_file_attribute): Check for S_IFLNK flag. Force 0777 permissions then. * spawn.cc (std_suffixes): Add ".lnk" suffix. * syscalls.cc (_unlink): Use `inner_suffixes' in path conversion. Check for shortcut symlinks to eliminate R/O attribute before calling DeleteFile(). (stat_suffixes): Add ".lnk" suffix. (stat_worker): Force 0777 permissions if file is a symlink.
2001-02-21 22:49:37 +01:00
}
2000-02-17 20:38:33 +01:00
/* 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;
}
/* telldir */
extern "C" off_t
telldir (DIR * dir)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
return 0;
return dir->__d_position;
}
/* seekdir */
extern "C" void
seekdir (DIR * dir, off_t loc)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
rewinddir (dir);
while (loc > dir->__d_position)
if (! readdir (dir))
break;
}
/* rewinddir: POSIX 5.1.2.1 */
extern "C" void
rewinddir (DIR * dir)
{
syscall_printf ("rewinddir (%p)", dir);
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;
2000-02-17 20:38:33 +01:00
}
/* closedir: POSIX 5.1.2.1 */
extern "C" int
closedir (DIR * dir)
{
if (dir->__d_cookie != __DIRENT_COOKIE)
{
set_errno (EBADF);
syscall_printf ("-1 = closedir (%p)", 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);
2000-02-17 20:38:33 +01:00
/* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0;
free (dir->__d_dirname);
free (dir->__d_dirent);
free (dir);
syscall_printf ("0 = closedir (%p)", dir);
return 0;
}
/* mkdir: POSIX 5.4.1.1 */
extern "C" int
mkdir (const char *dir, mode_t mode)
{
int res = -1;
SECURITY_ATTRIBUTES sa = sec_none_nih;
2000-02-17 20:38:33 +01:00
path_conv real_dir (dir, PC_SYM_NOFOLLOW);
2000-02-17 20:38:33 +01:00
if (real_dir.error)
{
set_errno (real_dir.case_clash ? ECASECLASH : real_dir.error);
2000-02-17 20:38:33 +01:00
goto done;
}
nofinalslash(real_dir.get_win32 (), real_dir.get_win32 ());
if (! writable_directory (real_dir.get_win32 ()))
goto done;
if (allow_ntsec && real_dir.has_acls ())
set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask),
&sa, alloca (4096), 4096);
if (CreateDirectoryA (real_dir.get_win32 (), &sa))
2000-02-17 20:38:33 +01:00
{
if (!allow_ntsec && allow_ntea)
set_file_attribute (real_dir.has_acls (), real_dir.get_win32 (),
S_IFDIR | ((mode & 07777) & ~cygheap->umask));
2000-02-17 20:38:33 +01:00
res = 0;
}
else
__seterrno ();
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;
path_conv real_dir (dir, PC_SYM_NOFOLLOW);
2000-02-17 20:38:33 +01:00
if (real_dir.error)
{
set_errno (real_dir.error);
goto done;
}
/* Does the file exist? */
if (real_dir.file_attributes () == (DWORD) -1)
{
set_errno (ENOENT);
goto done;
}
/* Is `dir' a directory? */
if (!(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
{
set_errno (ENOTDIR);
goto done;
}
/* Even own directories can't be removed if R/O attribute is set. */
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY)
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes () &
~FILE_ATTRIBUTE_READONLY);
2000-02-17 20:38:33 +01:00
if (RemoveDirectoryA (real_dir.get_win32 ()))
{
/* RemoveDirectory on a samba drive doesn't return an error if the
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
directory can't be removed because it's not empty. Checking for
existence afterwards keeps us informed about success. */
if (GetFileAttributesA (real_dir.get_win32 ()) != (DWORD) -1)
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
set_errno (ENOTEMPTY);
else
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
res = 0;
}
else
{
/* This kludge detects if we are attempting to remove the current working
directory. If so, we will move elsewhere to potentially allow the
rmdir to succeed. This means that cygwin's concept of the current working
directory != Windows concept but, hey, whaddaregonnado?
Note that this will not cause something like the following to work:
$ cd foo
$ rmdir .
since the shell will have foo "open" in the above case and so Windows will
not allow the deletion.
FIXME: A potential workaround for this is for cygwin apps to *never* call
SetCurrentDirectory. */
if (strcasematch (real_dir, cygheap->cwd.win32)
&& !strcasematch ("c:\\", cygheap->cwd.win32))
{
DWORD err = GetLastError ();
if (!SetCurrentDirectory ("c:\\"))
SetLastError (err);
else
return rmdir (dir);
}
if (GetLastError() == ERROR_ACCESS_DENIED)
{
/* On 9X ERROR_ACCESS_DENIED is returned if you try to remove
a non-empty directory. */
if (wincap.access_denied_on_delete ())
set_errno (ENOTEMPTY);
else
__seterrno ();
}
else
__seterrno ();
/* If directory still exists, restore R/O attribute. */
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY)
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes ());
2000-02-17 20:38:33 +01:00
}
done:
syscall_printf ("%d = rmdir (%s)", res, dir);
return res;
}