diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index bd8182737..bbc17fd69 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,43 @@ +Sun Sep 30 22:51:41 2001 Christopher Faylor + + Add "path.h" include throughout, where needed. Use new path_conv + methods and operators to simplify testing for directory and attributes, + throughout. + * path.h (path_conv::exists): New method. + (path_conv::has_attribute): Ditto. + (path_conv::isdir): Ditto. + (path_conv::DWORD &): New operator. + (path_conv::int &): Ditto. + * dir.cc (rmdir): Eliminate a goto. + * dtable.cc (dtable::build_fhandler): Accept opt and suffix info for + path_conv.check. Return fh == NULL on path_conv error. Pass unit to + set_name as appropriate. + (dtable::reset_unix_path_name): New method. + * dtable.h (dtable): Declare new method. Reflect arg changes to + build_fhandler. + * fhandler.cc (fhandler_disk_dummy_name): Eliminate. + (fhandler_base::set_name): Expect paths to be NULL. Build + unix_path_name from win32_path_name when it is a device. + (fhandler_base::reset_unix_path_name): New method. + (fhandler_base::raw_read): Report EISDIR when ERROR_INVALID_FUNCTION + or ERROR_INVALID_PARAMETER and reading a directory. + (fhandler_disk_file::fstat): Don't call stat_dev since we should now + never be calling fhandler_disk_file methods with devices. + (fhandler_base::fhandler_base): Clear {unix,win32}_path_name. + (fhandler_base::~fhandler_base): Always free {unix,win32}_path_name. + (fhandler_disk_file::fhandler_disk_file): Remove set_no_free_names + kludge. + (fhandler_disk_file::open): Ditto. + * fhandler.h (fhandler_base::no_free_names): Eliminate. + (fhandler_base::set_no_free_names): Ditto. + * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Don't set + unix_path_name here. + * path.cc (fchdir): Lock fd table throughout. Use new + dtable::reset_unix_path_name method to reset path. + * syscalls.cc (stat_worker): Reorganize to always call fstat method. + Pass path_conv method to fhandler_*::open. + (chroot): Elminate a goto. + Sun Sep 30 17:37:43 2001 Christopher Faylor * environ.cc (winenv): Allocate exact amount of space needed for forced diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index c5f6af776..a0e00d3c7 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -15,8 +15,8 @@ #include #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "cygheap.h" #include "child_info.h" #include "heap.h" diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index f347ade63..73c1b7245 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -26,8 +26,8 @@ details. */ #include "perprocess.h" #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "cygheap.h" #include "child_info.h" #include "perthread.h" diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 7b9b2d6b6..079c5c4fe 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -367,79 +367,76 @@ rmdir (const char *dir) if (real_dir.error) { set_errno (real_dir.error); - goto done; + res = -1; } - - /* Does the file exist? */ - if (real_dir.file_attributes () == (DWORD) -1) + else if (!real_dir.exists ()) { set_errno (ENOENT); - goto done; + res = -1; } - - /* Is `dir' a directory? */ - if (!(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) + else if (!real_dir.isdir ()) { 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); - - if (RemoveDirectoryA (real_dir.get_win32 ())) - { - /* RemoveDirectory on a samba drive doesn't return an error if the - 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) - set_errno (ENOTEMPTY); - else - res = 0; + res = -1; } 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) - { + /* Even own directories can't be removed if R/O attribute is set. */ + if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY)) + SetFileAttributes (real_dir, + (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY); - /* On 9X ERROR_ACCESS_DENIED is returned if you try to remove - a non-empty directory. */ - if (wincap.access_denied_on_delete ()) + if (RemoveDirectory (real_dir)) + { + /* RemoveDirectory on a samba drive doesn't return an error if the + directory can't be removed because it's not empty. Checking for + existence afterwards keeps us informed about success. */ + if (GetFileAttributes (real_dir) != (DWORD) -1) set_errno (ENOTEMPTY); else - __seterrno (); + res = 0; } else - __seterrno (); + { + /* 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 if ((res = rmdir (dir))) + SetCurrentDirectory (cygheap->cwd.win32); + } + if (GetLastError () == ERROR_ACCESS_DENIED) + { - /* 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 ()); + /* 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.has_attribute (FILE_ATTRIBUTE_READONLY)) + SetFileAttributes (real_dir, real_dir); + } } -done: syscall_printf ("%d = rmdir (%s)", res, dir); return res; } diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 96bf1bc18..d4dcca0e9 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -15,6 +15,7 @@ details. */ #include "environ.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index e08ed4209..9c8677241 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -210,7 +210,8 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle, } } - build_fhandler (fd, name, handle)->init (handle, myaccess, bin); + path_conv pc; + build_fhandler (fd, name, handle, &pc)->init (handle, myaccess, bin); set_std_handle (fd); paranoid_printf ("fd %d, handle %p", fd, handle); } @@ -228,7 +229,8 @@ cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin, } fhandler_base * -dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc) +dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc, + unsigned opt, suffix_info *si) { int unit; DWORD devn; @@ -238,7 +240,12 @@ dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc) devn = get_device_number (name, unit); else { - pc->check (name); + pc->check (name, opt | PC_NULLEMPTY, si); + if (pc->error) + { + set_errno (pc->error); + return NULL; + } devn = pc->get_devn (); unit = pc->get_unitn (); } @@ -268,7 +275,7 @@ dtable::build_fhandler (int fd, const char *name, HANDLE handle, path_conv *pc) fh = build_fhandler (fd, devn, name, unit); if (pc) - fh->set_name (name, *pc); + fh->set_name (name, *pc, unit); return fh; } @@ -434,6 +441,14 @@ done: return res; } +void +dtable::reset_unix_path_name (int fd, const char *name) +{ + SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "reset_unix_name"); + fds[fd]->reset_unix_path_name (name); + ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "reset_unix_name"); +} + select_record * dtable::select_read (int fd, select_record *s) { diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h index 7e27bf657..0f00bd060 100644 --- a/winsup/cygwin/dtable.h +++ b/winsup/cygwin/dtable.h @@ -13,6 +13,7 @@ details. */ #include "thread.h" +class suffix_info; class dtable { fhandler_base **fds; @@ -50,7 +51,8 @@ public: fhandler_base *build_fhandler (int fd, DWORD dev, const char *name, int unit = -1); fhandler_base *build_fhandler (int fd, const char *name, HANDLE h = NULL, - path_conv *pc = NULL); + path_conv *pc = NULL, + unsigned opts = PC_SYM_FOLLOW, suffix_info *si = NULL); inline int not_open (int fd) { SetResourceLock (LOCK_FD_LIST, READ_LOCK, "not_open"); @@ -60,6 +62,7 @@ public: ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "not open"); return res; } + void reset_unix_path_name (int fd, const char *name); int find_unused_handle (int start); int find_unused_handle () { return find_unused_handle (first_fd_for_open);} void release (int fd); diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc index 517cf6e6a..b531218f6 100644 --- a/winsup/cygwin/fcntl.cc +++ b/winsup/cygwin/fcntl.cc @@ -15,6 +15,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygerrno.h" diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index a670e7860..54adc8dc2 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -20,15 +20,14 @@ details. */ #include "security.h" #include "cygwin/version.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" -#include "path.h" #include "shared_info.h" +#include static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ -static NO_COPY char fhandler_disk_dummy_name[] = "some disk file"; - struct __cygwin_perfile *perfile_table; DWORD binmode; @@ -146,31 +145,13 @@ fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen) /* Record the file name. Filenames are used mostly for debugging messages, and it's hoped that in cases where the name is really required, the filename wouldn't ever - be too long (e.g. devices or some such). -*/ - + be too long (e.g. devices or some such). */ void fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit) { - if (!no_free_names ()) - { - if (unix_path_name != NULL && unix_path_name != fhandler_disk_dummy_name) - cfree (unix_path_name); - if (win32_path_name != NULL && unix_path_name != fhandler_disk_dummy_name) - cfree (win32_path_name); - } - - unix_path_name = win32_path_name = NULL; if (unix_path == NULL || !*unix_path) return; - unix_path_name = cstrdup (unix_path); - if (unix_path_name == NULL) - { - system_printf ("fatal error. strdup failed"); - exit (ENOMEM); - } - if (win32_path) win32_path_name = cstrdup (win32_path); else @@ -185,6 +166,34 @@ fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit system_printf ("fatal error. strdup failed"); exit (ENOMEM); } + + assert (unix_path_name == NULL); + /* FIXME: This isn't really right. It ignores the first argument if we're + building names for a device and just converts the device name from the + win32 name since it has theoretically been previously detected by + path_conv. Ideally, we should pass in a format string and build the + unix_path, too. */ + if (!is_device () || *win32_path_name != '\\') + unix_path_name = cstrdup (unix_path); + else + { + unix_path_name = cstrdup (win32_path_name); + for (char *p = unix_path_name; (p = strchr (p, '\\')); p++) + *p = '/'; + } + + if (unix_path_name == NULL) + { + system_printf ("fatal error. strdup failed"); + exit (ENOMEM); + } +} + +void +fhandler_base::reset_unix_path_name (const char *unix_path) +{ + cfree (unix_path_name); + unix_path_name = cstrdup (unix_path); } /* Detect if we are sitting at EOF for conditions where Windows @@ -235,6 +244,13 @@ fhandler_base::raw_read (void *ptr, size_t ulen) case ERROR_NOACCESS: if (is_at_eof (get_handle (), errcode)) return 0; + case ERROR_INVALID_FUNCTION: + case ERROR_INVALID_PARAMETER: + if (openflags & O_DIROPEN) + { + set_errno (EISDIR); + return -1; + } default: syscall_printf ("ReadFile %s failed, %E", unix_path_name); __seterrno_from_win_error (errcode); @@ -316,44 +332,28 @@ fhandler_base::open (int flags, mode_t mode) } if (get_query_open ()) - { - access = 0; - } + access = 0; else if (get_device () == FH_TAPE) - { - access = GENERIC_READ | GENERIC_WRITE; - } + access = GENERIC_READ | GENERIC_WRITE; else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) - { - access = GENERIC_READ; - } + access = GENERIC_READ; else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) - { - access = GENERIC_WRITE; - } + access = GENERIC_WRITE; else - { - access = GENERIC_READ | GENERIC_WRITE; - } + access = GENERIC_READ | GENERIC_WRITE; /* Allow reliable lseek on disk devices. */ if (get_device () == FH_FLOPPY) - { - access |= GENERIC_READ; - } + access |= GENERIC_READ; /* FIXME: O_EXCL handling? */ if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) { if (flags & O_CREAT) - { - creation_distribution = CREATE_ALWAYS; - } + creation_distribution = CREATE_ALWAYS; else - { - creation_distribution = TRUNCATE_EXISTING; - } + creation_distribution = TRUNCATE_EXISTING; } else if (flags & O_CREAT) creation_distribution = OPEN_ALWAYS; @@ -361,9 +361,7 @@ fhandler_base::open (int flags, mode_t mode) creation_distribution = OPEN_EXISTING; if ((flags & O_EXCL) && (flags & O_CREAT)) - { - creation_distribution = CREATE_NEW; - } + creation_distribution = CREATE_NEW; if (flags & O_APPEND) set_append_p(); @@ -868,9 +866,6 @@ fhandler_disk_file::fstat (struct stat *buf) memset (buf, 0, sizeof (*buf)); - if (is_device ()) - return stat_dev (get_device (), get_unit (), get_namehash (), buf); - /* NT 3.51 seems to have a bug when attempting to get vol serial numbers. This loop gets around this. */ for (int i = 0; i < 2; i++) @@ -1199,6 +1194,8 @@ fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit): raixget (0), raixput (0), rabuflen (0), + unix_path_name (NULL), + win32_path_name (NULL), open_status (0) { status = devtype; @@ -1210,20 +1207,15 @@ fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit): if (!get_w_binset ()) set_w_binary (bin); } - unix_path_name = win32_path_name = NULL; - set_name (name, NULL, unit); } /* Normal I/O destructor */ fhandler_base::~fhandler_base (void) { - if (!no_free_names ()) - { - if (unix_path_name != NULL && unix_path_name != fhandler_disk_dummy_name) - cfree (unix_path_name); - if (win32_path_name != NULL && win32_path_name != fhandler_disk_dummy_name) - cfree (win32_path_name); - } + if (unix_path_name != NULL) + cfree (unix_path_name); + if (win32_path_name != NULL) + cfree (win32_path_name); if (rabuf) free (rabuf); unix_path_name = win32_path_name = NULL; @@ -1236,8 +1228,6 @@ fhandler_disk_file::fhandler_disk_file (const char *name) : fhandler_base (FH_DISK, name) { set_cb (sizeof *this); - set_no_free_names (); - unix_path_name = win32_path_name = fhandler_disk_dummy_name; } int @@ -1260,19 +1250,12 @@ fhandler_disk_file::open (const char *path, int flags, mode_t mode) } set_name (path, real_path.get_win32 ()); - set_no_free_names (0); return open (real_path, flags, mode); } int fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) { - if (get_win32_name () == fhandler_disk_dummy_name) - { - win32_path_name = real_path.get_win32 (); - set_no_free_names (); - } - if (real_path.isbinary ()) { set_r_binary (1); @@ -1282,8 +1265,7 @@ fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) set_has_acls (real_path.has_acls ()); set_isremote (real_path.isremote ()); - if (real_path.file_attributes () != (DWORD)-1 - && (real_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) + if (real_path.isdir ()) flags |= O_DIROPEN; int res = this->fhandler_base::open (flags, mode); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 8f3368e78..59cf14f39 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -65,8 +65,7 @@ enum FH_W95LSBUG = 0x00400000, /* set when lseek is called as a flag that * _write should check if we've moved beyond * EOF, zero filling if so. */ - FH_NOFRNAME = 0x00800000, /* Set if shouldn't free unix_path_name and - windows_path_name_ on destruction. */ + FH_UNUSED = 0x00800000, /* currently unused. */ FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */ FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */ FH_LOCAL = 0x04000000, /* File is unix domain socket */ @@ -187,6 +186,7 @@ public: void set_name (const char * unix_path, const char * win32_path = NULL, int unit = 0); + void reset_unix_path_name (const char *); virtual fhandler_base& operator =(fhandler_base &x); fhandler_base (DWORD dev, const char *name = 0, int unit = 0); virtual ~fhandler_base (); @@ -301,10 +301,6 @@ public: int isremote () { return FHISSETF (ISREMOTE); } void set_isremote (int val) { FHCONDSETF (val, ISREMOTE); } - int no_free_names () { return FHISSETF (NOFRNAME); } - void set_no_free_names (int val) { FHCONDSETF (val, NOFRNAME); } - void set_no_free_names () { FHSETF (NOFRNAME); } - const char *get_name () { return unix_path_name; } const char *get_win32_name () { return win32_path_name; } unsigned long get_namehash () { return namehash; } diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index d061dee2f..9dd98e7f8 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -24,6 +24,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sync.h" diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc index 7ed439b52..20f2de513 100644 --- a/winsup/cygwin/fhandler_raw.cc +++ b/winsup/cygwin/fhandler_raw.cc @@ -20,9 +20,9 @@ #include "perprocess.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" -#include "path.h" /* static wrapper functions to hide the effect of media changes and bus resets which occurs after a new media is inserted. This is diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index dbf284ec5..a34272f6a 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -27,6 +27,7 @@ #include "cygwin/version.h" #include "perprocess.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sigproc.h" diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc index 5acbf0fb6..48561351a 100644 --- a/winsup/cygwin/fhandler_tape.cc +++ b/winsup/cygwin/fhandler_tape.cc @@ -19,9 +19,9 @@ details. */ #include "perprocess.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" -#include "path.h" /**********************************************************************/ /* fhandler_dev_tape */ diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 1a46ecb3b..03f7d8141 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -19,6 +19,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "sync.h" #include "sigproc.h" @@ -441,11 +442,6 @@ fhandler_tty_slave::fhandler_tty_slave (int num, const char *name) : { set_cb (sizeof *this); ttynum = num; - /* FIXME: This is wasteful. We should rewrite the set_name path to eliminate the - need for double allocates. */ - unix_path_name = (char *) crealloc (unix_path_name, strlen (win32_path_name) + 1); - strcpy (unix_path_name, win32_path_name); - unix_path_name[0] = unix_path_name[4] = '/'; debug_printf ("unix '%s', win32 '%s'", unix_path_name, win32_path_name); inuse = NULL; } diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index ffd48e47a..640ae27d3 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -17,6 +17,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "sync.h" diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index d9e7b02b4..87cc4b484 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -22,8 +22,8 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "cygheap.h" #include "cygerrno.h" #include "pwdgrp.h" diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index 1a3c2a8e9..eaa500c62 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -18,6 +18,7 @@ details. */ #include "shared_info.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" diff --git a/winsup/cygwin/ioctl.cc b/winsup/cygwin/ioctl.cc index f02c71ca0..93fe9ddf5 100644 --- a/winsup/cygwin/ioctl.cc +++ b/winsup/cygwin/ioctl.cc @@ -17,6 +17,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc index 1cbe43c61..2fa93b1a1 100644 --- a/winsup/cygwin/malloc_wrapper.cc +++ b/winsup/cygwin/malloc_wrapper.cc @@ -16,6 +16,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "heap.h" diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 4ebc017b1..c13a3f365 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -16,6 +16,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "cygheap.h" diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 092473b12..2f52473c7 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -16,8 +16,8 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" -#include "dtable.h" #include "path.h" +#include "dtable.h" #include "sync.h" #include "sigproc.h" #include "pinfo.h" diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 1c7c554af..2aa19e1aa 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2428,8 +2428,7 @@ symlink (const char *topath, const char *frompath) syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ()); - if (win32_path.is_device () || - win32_path.file_attributes () != (DWORD) -1) + if (win32_path.is_device () || win32_path.exists ()) { set_errno (EEXIST); goto done; @@ -2897,7 +2896,7 @@ readlink (const char *path, char *buf, int buflen) return -1; } - if (pathbuf.file_attributes () == (DWORD) -1) + if (!pathbuf.exists ()) { set_errno (ENOENT); return -1; @@ -3106,8 +3105,9 @@ fchdir (int fd) set_errno (EBADF); return -1; } + SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fchdir"); int ret = chdir (cygheap->fdtab[fd]->get_name ()); - if (!ret) + if (ret == 0) { /* The name in the fhandler is explicitely overwritten with the full path. Otherwise fchmod() to a path originally given as a relative path could @@ -3119,13 +3119,11 @@ fchdir (int fd) The 2nd fchmod should chdir to the same dir as the first call, not to it's parent dir. */ - char path[MAX_PATH]; char posix_path[MAX_PATH]; - mount_table->conv_to_posix_path (cygheap->cwd.get (path, 0, 1), - posix_path, 0); - cygheap->fdtab[fd]->set_name (path, posix_path); + cygheap->fdtab.reset_unix_path_name (fd, cygheap->cwd.get (posix_path, 1, 1)); } + ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fchdir"); syscall_printf ("%d = fchdir (%d)", ret, fd); return ret; } diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index a3e94c18f..17f5e2bcf 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -69,6 +69,12 @@ class path_conv public: unsigned path_flags; + char *known_suffix; + int error; + DWORD devn; + int unit; + DWORD fileattr; + BOOL case_clash; int isdisk () const { return path_flags & PATH_ISDISK;} int isremote () const {return is_remote_drive;} @@ -80,6 +86,9 @@ class path_conv int issymlink () const {return path_flags & PATH_SYMLINK;} int issocket () const {return path_flags & PATH_SOCKET;} int iscygexec () const {return path_flags & PATH_CYGWIN_EXEC;} + bool exists () const {return fileattr != (DWORD) -1;} + bool has_attribute (DWORD x) const {return exists () && (fileattr & x);} + int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);} executable_states exec_state () { extern int _check_for_executable; @@ -100,16 +109,6 @@ class path_conv void set_has_acls (int x = 1) {path_flags |= x ? PATH_HASACLS : PATH_NOTHING;} void set_has_buggy_open (int x = 1) {path_flags |= x ? PATH_HASBUGGYOPEN : PATH_NOTHING;} - char *known_suffix; - - int error; - DWORD devn; - int unit; - - DWORD fileattr; - - BOOL case_clash; - void check (const char *src, unsigned opt = PC_SYM_FOLLOW, const suffix_info *suffixes = NULL) __attribute__ ((regparm(3))); @@ -129,6 +128,8 @@ class path_conv inline char *get_win32 () { return path; } operator char *() {return path; } + operator DWORD &() {return fileattr; } + operator int &() {return (int) fileattr; } BOOL is_device () {return devn != FH_BAD;} DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;} short get_unitn () {return devn == FH_BAD ? 0 : unit;} diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 14eba9b92..6e66e47a1 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -15,6 +15,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "sync.h" diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index 03af86228..099aa37b3 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -15,6 +15,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "thread.h" diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc index 9b85f20ee..2ac606849 100644 --- a/winsup/cygwin/poll.cc +++ b/winsup/cygwin/poll.cc @@ -14,6 +14,7 @@ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygerrno.h" diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 2307e297e..e66d078c8 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -36,6 +36,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sync.h" diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 8ce88d240..81d39e3ed 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -19,6 +19,7 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "heap.h" diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 7f621d3ea..7b55487bb 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -23,6 +23,7 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "child_info.h" diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 248dd426e..0a0a84deb 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -63,10 +63,10 @@ perhaps_suffix (const char *prog, path_conv &buf) debug_printf ("prog '%s'", prog); buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes); - if (buf.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + if (buf.isdir ()) ext = NULL; else if (buf.known_suffix) - ext = buf + (buf.known_suffix - buf.get_win32 ()); + ext = (char *) buf + (buf.known_suffix - buf.get_win32 ()); else ext = strchr (buf, '\0'); diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 9f5c8ac88..9aa1dd739 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -116,16 +116,13 @@ _unlink (const char *ourname) syscall_printf ("_unlink (%s)", win32_name.get_win32 ()); - DWORD atts; - atts = win32_name.file_attributes (); - if (atts == 0xffffffff) + if (!win32_name.exists ()) { - syscall_printf ("unlinking a nonexistant file"); + syscall_printf ("unlinking a nonexistent file"); set_errno (ENOENT); goto done; } - - if (atts & FILE_ATTRIBUTE_DIRECTORY) + else if (win32_name.isdir ()) { syscall_printf ("unlinking a directory"); set_errno (EPERM); @@ -140,11 +137,11 @@ _unlink (const char *ourname) } /* Check for shortcut as symlink condition. */ - if (atts & FILE_ATTRIBUTE_READONLY) + if (win32_name.has_attribute (FILE_ATTRIBUTE_READONLY)) { int len = strlen (win32_name); - if (len > 4 && strcasematch (win32_name + len - 4, ".lnk")) - SetFileAttributes (win32_name, atts & ~FILE_ATTRIBUTE_READONLY); + if (len > 4 && strcasematch ((char *) win32_name + len - 4, ".lnk")) + SetFileAttributes (win32_name, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY); } DWORD lasterr; @@ -249,11 +246,7 @@ remove (const char *ourname) return -1; } - DWORD atts = win32_name.file_attributes (); - if (atts != 0xffffffff && atts & FILE_ATTRIBUTE_DIRECTORY) - return rmdir (ourname); - - return _unlink (ourname); + return win32_name.isdir () ? rmdir (ourname) : _unlink (ourname); } extern "C" pid_t @@ -619,7 +612,7 @@ _link (const char *a, const char *b) goto done; } - if (real_b.file_attributes () != (DWORD)-1) + if (real_b.exists ()) { syscall_printf ("file '%s' exists?", (char *)real_b); set_errno (EEXIST); @@ -779,7 +772,7 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid) } DWORD attrib = 0; - if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + if (win32_path.isdir ()) attrib |= S_IFDIR; res = get_file_attribute (win32_path.has_acls (), win32_path.get_win32 (), @@ -792,12 +785,10 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid) uid = old_uid; if (gid == (gid_t) -1) gid = old_gid; - if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + if (win32_path.isdir()) attrib |= S_IFDIR; - res = set_file_attribute (win32_path.has_acls (), - win32_path.get_win32 (), - uid, gid, attrib, - cygheap->user.logsrv ()); + res = set_file_attribute (win32_path.has_acls (), win32_path, uid, + gid, attrib, cygheap->user.logsrv ()); } if (res != 0 && (!win32_path.has_acls () || !allow_ntsec)) { @@ -886,28 +877,25 @@ chmod (const char *path, mode_t mode) goto done; } - if (win32_path.file_attributes () == (DWORD)-1) + if (!win32_path.exists ()) __seterrno (); else { - DWORD attr = win32_path.file_attributes (); /* temporary erase read only bit, to be able to set file security */ - SetFileAttributesA (win32_path.get_win32 (), - attr & ~FILE_ATTRIBUTE_READONLY); + SetFileAttributes (win32_path, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY); uid_t uid; gid_t gid; - if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + if (win32_path.isdir ()) mode |= S_IFDIR; get_file_attribute (win32_path.has_acls (), win32_path.get_win32 (), NULL, &uid, &gid); - if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) + /* FIXME: Do we really need this to be specified twice? */ + if (win32_path.isdir ()) mode |= S_IFDIR; - if (!set_file_attribute (win32_path.has_acls (), - win32_path.get_win32 (), - uid, gid, + if (!set_file_attribute (win32_path.has_acls (), win32_path, uid, gid, mode, cygheap->user.logsrv ()) && allow_ntsec) res = 0; @@ -915,14 +903,14 @@ chmod (const char *path, mode_t mode) /* if the mode we want has any write bits set, we can't be read only. */ if (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) - attr &= ~FILE_ATTRIBUTE_READONLY; + (DWORD) win32_path &= ~FILE_ATTRIBUTE_READONLY; else - attr |= FILE_ATTRIBUTE_READONLY; + (DWORD) win32_path |= FILE_ATTRIBUTE_READONLY; if (S_ISLNK (mode) || S_ISSOCK (mode)) - attr |= FILE_ATTRIBUTE_SYSTEM; + (DWORD) win32_path |= FILE_ATTRIBUTE_SYSTEM; - if (!SetFileAttributesA (win32_path.get_win32 (), attr)) + if (!SetFileAttributes (win32_path, win32_path)) __seterrno (); else { @@ -1084,22 +1072,24 @@ stat_worker (const char *caller, const char *name, struct stat *buf, int nofollow) { int res = -1; - int oret = 1; - int atts; - - int attribute = 0; + int oret; uid_t uid; gid_t gid; - - UINT dtype; - fhandler_disk_file fh (NULL); + path_conv real_path; + fhandler_base *fh = NULL; MALLOC_CHECK; + int open_flags = O_RDONLY | O_BINARY | O_DIROPEN + | (nofollow ? O_NOSYMLINK : 0); debug_printf ("%s (%s, %p)", caller, name, buf); - path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | - PC_FULL, stat_suffixes); + if (check_null_invalid_struct_errno (buf)) + goto done; + + fh = cygheap->fdtab.build_fhandler (-1, name, NULL, &real_path, + (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) + | PC_FULL, stat_suffixes); if (real_path.error) { @@ -1107,83 +1097,66 @@ stat_worker (const char *caller, const char *name, struct stat *buf, goto done; } - if (check_null_invalid_struct_errno (buf)) - goto done; - memset (buf, 0, sizeof (struct stat)); if (real_path.is_device ()) return stat_dev (real_path.get_devn (), real_path.get_unitn (), hash_path_name (0, real_path.get_win32 ()), buf); - atts = real_path.file_attributes (); + debug_printf ("%d = file_attributes for '%s'", (DWORD) real_path, + (char *) real_path); - debug_printf ("%d = file_attributes for '%s'", atts, real_path.get_win32 ()); - - dtype = real_path.get_drive_type (); - - if ((atts == -1 || ! (atts & FILE_ATTRIBUTE_DIRECTORY) || - (wincap.can_open_directories () - && dtype != DRIVE_NO_ROOT_DIR - && dtype != DRIVE_UNKNOWN))) + if ((oret = fh->open (real_path, open_flags, 0))) + /* ok */; + else { - oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | - (nofollow ? O_NOSYMLINK : 0), 0); + int ntsec_atts = 0; /* If we couldn't open the file, try a "query open" with no permissions. This will allow us to determine *some* things about the file, at least. */ - if (!oret) - { - fh.set_query_open (TRUE); - oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | - (nofollow ? O_NOSYMLINK : 0), 0); - } - /* Check a special case here. If ntsec is ON it happens - that a process creates a file using mode 000 to disallow - other processes access. In contrast to UNIX, this results - in a failing open call in the same process. Check that - case. */ - if (!oret && allow_ntsec && get_errno () == EACCES - && !get_file_attribute (TRUE, real_path, &attribute, &uid, &gid) - && !attribute && uid == myself->uid && gid == myself->gid) - { + fh->set_query_open (TRUE); + if ((oret = fh->open (real_path, open_flags, 0))) + /* ok */; + else if (allow_ntsec && real_path.has_acls () && get_errno () == EACCES + && !get_file_attribute (TRUE, real_path, &ntsec_atts, &uid, &gid) + && !ntsec_atts && uid == myself->uid && gid == myself->gid) + { + /* Check a special case here. If ntsec is ON it happens + that a process creates a file using mode 000 to disallow + other processes access. In contrast to UNIX, this results + in a failing open call in the same process. Check that + case. */ set_file_attribute (TRUE, real_path, 0400); - oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | - (nofollow ? O_NOSYMLINK : 0), 0); - set_file_attribute (TRUE, real_path.get_win32 (), 0); - } - if (oret) - { - res = fh.fstat (buf); - fh.close (); - /* The number of links to a directory includes the - number of subdirectories in the directory, since all - those subdirectories point to it. - This is too slow on remote drives, so we do without it and - set the number of links to 2. */ - /* Unfortunately the count of 2 confuses `find (1)' command. So - let's try it with `1' as link count. */ - if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY)) - buf->st_nlink = (dtype == DRIVE_REMOTE - ? 1 - : num_entries (real_path.get_win32 ())); - goto done; - } + oret = fh->open (real_path, open_flags, 0); + set_file_attribute (TRUE, real_path, ntsec_atts); + } } - if (atts != -1 && (oret || (!oret && get_errno () != ENOENT - && get_errno () != ENOSHARE))) + if (oret) + { + res = fh->fstat (buf); + /* The number of links to a directory includes the + number of subdirectories in the directory, since all + those subdirectories point to it. + This is too slow on remote drives, so we do without it and + set the number of links to 2. */ + /* Unfortunately the count of 2 confuses `find (1)' command. So + let's try it with `1' as link count. */ + if (real_path.isdir ()) + buf->st_nlink = (real_path.isremote () + ? 1 : num_entries (real_path.get_win32 ())); + fh->close (); + } + else if (real_path.exists ()) { /* Unfortunately, the above open may fail if the file exists, though. So we have to care for this case here, too. */ WIN32_FIND_DATA wfd; HANDLE handle; buf->st_nlink = 1; - if (atts != -1 - && (atts & FILE_ATTRIBUTE_DIRECTORY) - && dtype != DRIVE_REMOTE) + if (real_path.isdir () && real_path.isremote ()) buf->st_nlink = num_entries (real_path.get_win32 ()); buf->st_dev = FHDEVN (FH_DISK) << 8; buf->st_ino = hash_path_name (0, real_path.get_win32 ()); - if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY)) + if (real_path.isdir ()) buf->st_mode = S_IFDIR; else if (real_path.issymlink ()) buf->st_mode = S_IFLNK; @@ -1197,7 +1170,7 @@ stat_worker (const char *caller, const char *name, struct stat *buf, &buf->st_uid, &buf->st_gid)) { buf->st_mode |= STD_RBITS | STD_XBITS; - if ((atts & FILE_ATTRIBUTE_READONLY) == 0) + if (!(real_path.has_attribute (FILE_ATTRIBUTE_READONLY))) buf->st_mode |= STD_WBITS; if (real_path.issymlink ()) buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO; @@ -1220,6 +1193,8 @@ stat_worker (const char *caller, const char *name, struct stat *buf, } done: + if (fh) + delete fh; MALLOC_CHECK; syscall_printf ("%d = %s (%s, %p)", res, caller, name, buf); return res; @@ -1360,7 +1335,7 @@ _rename (const char *oldpath, const char *newpath) return -1; } - if (real_old.file_attributes () == (DWORD) -1) /* file to move doesn't exist */ + if (!real_old.exists ()) /* file to move doesn't exist */ { syscall_printf ("file to move doesn't exist"); set_errno (ENOENT); @@ -1369,10 +1344,8 @@ _rename (const char *oldpath, const char *newpath) /* Destination file exists and is read only, change that or else the rename won't work. */ - if (real_new.file_attributes () != (DWORD) -1 && - real_new.file_attributes () & FILE_ATTRIBUTE_READONLY) - SetFileAttributesA (real_new.get_win32 (), - real_new.file_attributes () & ~FILE_ATTRIBUTE_READONLY); + if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY)) + SetFileAttributes (real_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY); /* Shortcut hack No. 2, part 1 */ if (!real_old.issymlink () && !real_new.error && real_new.issymlink () && @@ -1421,14 +1394,13 @@ done: { __seterrno (); /* Reset R/O attributes if neccessary. */ - if (real_new.file_attributes () != (DWORD) -1 && - real_new.file_attributes () & FILE_ATTRIBUTE_READONLY) - SetFileAttributesA (real_new.get_win32 (), real_new.file_attributes ()); + if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY)) + SetFileAttributes (real_new, real_new); } else { /* make the new file have the permissions of the old one */ - SetFileAttributesA (real_new.get_win32 (), real_old.file_attributes ()); + SetFileAttributes (real_new, real_old); /* Shortcut hack, No. 2, part 2 */ /* if the new filename was an existing shortcut, remove it now if the @@ -1436,12 +1408,12 @@ done: if (lnk_suffix) { *lnk_suffix = '.'; - DeleteFile (real_new.get_win32 ()); + DeleteFile (real_new); } } - syscall_printf ("%d = rename (%s, %s)", res, real_old.get_win32 (), - real_new.get_win32 ()); + syscall_printf ("%d = rename (%s, %s)", res, (char *) real_old, + (char *) real_new); return res; } @@ -2317,27 +2289,29 @@ extern "C" int chroot (const char *newroot) { sigframe thisframe (mainthread); - int ret = -1; path_conv path (newroot, PC_SYM_FOLLOW | PC_FULL); + int ret; if (path.error) - goto done; - if (path.file_attributes () == (DWORD)-1) + ret = -1; + else if (!path.exists ()) { set_errno (ENOENT); - goto done; + ret = -1; } - if (!(path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) + else if (!path.isdir ()) { set_errno (ENOTDIR); - goto done; + ret = -1; + } + else + { + char buf[MAX_PATH]; + normalize_posix_path (newroot, buf); + cygheap->root.set (buf, path); + ret = 0; } - char buf[MAX_PATH]; - normalize_posix_path (newroot, buf); - cygheap->root.set (buf, path); - ret = 0; -done: syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0, newroot ? newroot : "NULL"); return ret; diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc index aa1909141..5e1d91ba6 100644 --- a/winsup/cygwin/sysconf.cc +++ b/winsup/cygwin/sysconf.cc @@ -16,6 +16,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygerrno.h" diff --git a/winsup/cygwin/syslog.cc b/winsup/cygwin/syslog.cc index c11ff1170..66e9ed1cc 100644 --- a/winsup/cygwin/syslog.cc +++ b/winsup/cygwin/syslog.cc @@ -16,6 +16,7 @@ details. */ #include #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygerrno.h" #include "cygheap.h" diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc index a2674aae7..5488185c4 100644 --- a/winsup/cygwin/termios.cc +++ b/winsup/cygwin/termios.cc @@ -17,6 +17,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "cygwin/version.h" diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc index b3d753c8d..ec3f95ebf 100644 --- a/winsup/cygwin/tty.cc +++ b/winsup/cygwin/tty.cc @@ -18,6 +18,7 @@ details. */ #include "cygerrno.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "sync.h" diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index a6b94c803..9bbbe9e9c 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -23,6 +23,7 @@ details. */ #include "pinfo.h" #include "security.h" #include "fhandler.h" +#include "path.h" #include "dtable.h" #include "cygheap.h" #include "registry.h"