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.
This commit is contained in:
Christopher Faylor 2001-10-01 04:10:07 +00:00
parent c25c4c5ffc
commit 47063f00e4
37 changed files with 315 additions and 293 deletions

View File

@ -1,3 +1,43 @@
Sun Sep 30 22:51:41 2001 Christopher Faylor <cgf@cygnus.com>
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 <cgf@cygnus.com> Sun Sep 30 17:37:43 2001 Christopher Faylor <cgf@cygnus.com>
* environ.cc (winenv): Allocate exact amount of space needed for forced * environ.cc (winenv): Allocate exact amount of space needed for forced

View File

@ -15,8 +15,8 @@
#include <stdlib.h> #include <stdlib.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h"
#include "path.h" #include "path.h"
#include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "child_info.h" #include "child_info.h"
#include "heap.h" #include "heap.h"

View File

@ -26,8 +26,8 @@ details. */
#include "perprocess.h" #include "perprocess.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h"
#include "path.h" #include "path.h"
#include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "child_info.h" #include "child_info.h"
#include "perthread.h" #include "perthread.h"

View File

@ -367,34 +367,31 @@ rmdir (const char *dir)
if (real_dir.error) if (real_dir.error)
{ {
set_errno (real_dir.error); set_errno (real_dir.error);
goto done; res = -1;
} }
else if (!real_dir.exists ())
/* Does the file exist? */
if (real_dir.file_attributes () == (DWORD) -1)
{ {
set_errno (ENOENT); set_errno (ENOENT);
goto done; res = -1;
} }
else if (!real_dir.isdir ())
/* Is `dir' a directory? */
if (!(real_dir.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
{ {
set_errno (ENOTDIR); set_errno (ENOTDIR);
goto done; res = -1;
} }
else
{
/* Even own directories can't be removed if R/O attribute is set. */ /* Even own directories can't be removed if R/O attribute is set. */
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY) if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes () & SetFileAttributes (real_dir,
~FILE_ATTRIBUTE_READONLY); (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY);
if (RemoveDirectoryA (real_dir.get_win32 ())) if (RemoveDirectory (real_dir))
{ {
/* RemoveDirectory on a samba drive doesn't return an error if the /* RemoveDirectory on a samba drive doesn't return an error if the
directory can't be removed because it's not empty. Checking for directory can't be removed because it's not empty. Checking for
existence afterwards keeps us informed about success. */ existence afterwards keeps us informed about success. */
if (GetFileAttributesA (real_dir.get_win32 ()) != (DWORD) -1) if (GetFileAttributes (real_dir) != (DWORD) -1)
set_errno (ENOTEMPTY); set_errno (ENOTEMPTY);
else else
res = 0; res = 0;
@ -418,8 +415,8 @@ rmdir (const char *dir)
DWORD err = GetLastError (); DWORD err = GetLastError ();
if (!SetCurrentDirectory ("c:\\")) if (!SetCurrentDirectory ("c:\\"))
SetLastError (err); SetLastError (err);
else else if ((res = rmdir (dir)))
return rmdir (dir); SetCurrentDirectory (cygheap->cwd.win32);
} }
if (GetLastError () == ERROR_ACCESS_DENIED) if (GetLastError () == ERROR_ACCESS_DENIED)
{ {
@ -435,11 +432,11 @@ rmdir (const char *dir)
__seterrno (); __seterrno ();
/* If directory still exists, restore R/O attribute. */ /* If directory still exists, restore R/O attribute. */
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY) if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes ()); SetFileAttributes (real_dir, real_dir);
}
} }
done:
syscall_printf ("%d = rmdir (%s)", res, dir); syscall_printf ("%d = rmdir (%s)", res, dir);
return res; return res;
} }

View File

@ -15,6 +15,7 @@ details. */
#include "environ.h" #include "environ.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"

View File

@ -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); set_std_handle (fd);
paranoid_printf ("fd %d, handle %p", fd, handle); 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 * 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; int unit;
DWORD devn; 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); devn = get_device_number (name, unit);
else else
{ {
pc->check (name); pc->check (name, opt | PC_NULLEMPTY, si);
if (pc->error)
{
set_errno (pc->error);
return NULL;
}
devn = pc->get_devn (); devn = pc->get_devn ();
unit = pc->get_unitn (); 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); fh = build_fhandler (fd, devn, name, unit);
if (pc) if (pc)
fh->set_name (name, *pc); fh->set_name (name, *pc, unit);
return fh; return fh;
} }
@ -434,6 +441,14 @@ done:
return res; 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 * select_record *
dtable::select_read (int fd, select_record *s) dtable::select_read (int fd, select_record *s)
{ {

View File

@ -13,6 +13,7 @@ details. */
#include "thread.h" #include "thread.h"
class suffix_info;
class dtable class dtable
{ {
fhandler_base **fds; fhandler_base **fds;
@ -50,7 +51,8 @@ public:
fhandler_base *build_fhandler (int fd, DWORD dev, const char *name, fhandler_base *build_fhandler (int fd, DWORD dev, const char *name,
int unit = -1); int unit = -1);
fhandler_base *build_fhandler (int fd, const char *name, HANDLE h = NULL, 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) inline int not_open (int fd)
{ {
SetResourceLock (LOCK_FD_LIST, READ_LOCK, "not_open"); SetResourceLock (LOCK_FD_LIST, READ_LOCK, "not_open");
@ -60,6 +62,7 @@ public:
ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "not open"); ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "not open");
return res; return res;
} }
void reset_unix_path_name (int fd, const char *name);
int find_unused_handle (int start); int find_unused_handle (int start);
int find_unused_handle () { return find_unused_handle (first_fd_for_open);} int find_unused_handle () { return find_unused_handle (first_fd_for_open);}
void release (int fd); void release (int fd);

View File

@ -15,6 +15,7 @@ details. */
#include <unistd.h> #include <unistd.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "cygerrno.h" #include "cygerrno.h"

View File

@ -20,15 +20,14 @@ details. */
#include "security.h" #include "security.h"
#include "cygwin/version.h" #include "cygwin/version.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "path.h"
#include "shared_info.h" #include "shared_info.h"
#include <assert.h>
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ 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; struct __cygwin_perfile *perfile_table;
DWORD binmode; DWORD binmode;
@ -146,31 +145,13 @@ fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
/* Record the file name. /* Record the file name.
Filenames are used mostly for debugging messages, and it's hoped that 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 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 void
fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit) 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) if (unix_path == NULL || !*unix_path)
return; return;
unix_path_name = cstrdup (unix_path);
if (unix_path_name == NULL)
{
system_printf ("fatal error. strdup failed");
exit (ENOMEM);
}
if (win32_path) if (win32_path)
win32_path_name = cstrdup (win32_path); win32_path_name = cstrdup (win32_path);
else 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"); system_printf ("fatal error. strdup failed");
exit (ENOMEM); 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 /* 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: case ERROR_NOACCESS:
if (is_at_eof (get_handle (), errcode)) if (is_at_eof (get_handle (), errcode))
return 0; return 0;
case ERROR_INVALID_FUNCTION:
case ERROR_INVALID_PARAMETER:
if (openflags & O_DIROPEN)
{
set_errno (EISDIR);
return -1;
}
default: default:
syscall_printf ("ReadFile %s failed, %E", unix_path_name); syscall_printf ("ReadFile %s failed, %E", unix_path_name);
__seterrno_from_win_error (errcode); __seterrno_from_win_error (errcode);
@ -316,54 +332,36 @@ fhandler_base::open (int flags, mode_t mode)
} }
if (get_query_open ()) if (get_query_open ())
{
access = 0; access = 0;
}
else if (get_device () == FH_TAPE) 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) 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) else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
{
access = GENERIC_WRITE; access = GENERIC_WRITE;
}
else else
{
access = GENERIC_READ | GENERIC_WRITE; access = GENERIC_READ | GENERIC_WRITE;
}
/* Allow reliable lseek on disk devices. */ /* Allow reliable lseek on disk devices. */
if (get_device () == FH_FLOPPY) if (get_device () == FH_FLOPPY)
{
access |= GENERIC_READ; access |= GENERIC_READ;
}
/* FIXME: O_EXCL handling? */ /* FIXME: O_EXCL handling? */
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY)) if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
{ {
if (flags & O_CREAT) if (flags & O_CREAT)
{
creation_distribution = CREATE_ALWAYS; creation_distribution = CREATE_ALWAYS;
}
else else
{
creation_distribution = TRUNCATE_EXISTING; creation_distribution = TRUNCATE_EXISTING;
} }
}
else if (flags & O_CREAT) else if (flags & O_CREAT)
creation_distribution = OPEN_ALWAYS; creation_distribution = OPEN_ALWAYS;
else else
creation_distribution = OPEN_EXISTING; creation_distribution = OPEN_EXISTING;
if ((flags & O_EXCL) && (flags & O_CREAT)) if ((flags & O_EXCL) && (flags & O_CREAT))
{
creation_distribution = CREATE_NEW; creation_distribution = CREATE_NEW;
}
if (flags & O_APPEND) if (flags & O_APPEND)
set_append_p(); set_append_p();
@ -868,9 +866,6 @@ fhandler_disk_file::fstat (struct stat *buf)
memset (buf, 0, sizeof (*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 /* NT 3.51 seems to have a bug when attempting to get vol serial
numbers. This loop gets around this. */ numbers. This loop gets around this. */
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
@ -1199,6 +1194,8 @@ fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit):
raixget (0), raixget (0),
raixput (0), raixput (0),
rabuflen (0), rabuflen (0),
unix_path_name (NULL),
win32_path_name (NULL),
open_status (0) open_status (0)
{ {
status = devtype; status = devtype;
@ -1210,20 +1207,15 @@ fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit):
if (!get_w_binset ()) if (!get_w_binset ())
set_w_binary (bin); set_w_binary (bin);
} }
unix_path_name = win32_path_name = NULL;
set_name (name, NULL, unit);
} }
/* Normal I/O destructor */ /* Normal I/O destructor */
fhandler_base::~fhandler_base (void) fhandler_base::~fhandler_base (void)
{ {
if (!no_free_names ()) if (unix_path_name != NULL)
{
if (unix_path_name != NULL && unix_path_name != fhandler_disk_dummy_name)
cfree (unix_path_name); cfree (unix_path_name);
if (win32_path_name != NULL && win32_path_name != fhandler_disk_dummy_name) if (win32_path_name != NULL)
cfree (win32_path_name); cfree (win32_path_name);
}
if (rabuf) if (rabuf)
free (rabuf); free (rabuf);
unix_path_name = win32_path_name = NULL; 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) fhandler_base (FH_DISK, name)
{ {
set_cb (sizeof *this); set_cb (sizeof *this);
set_no_free_names ();
unix_path_name = win32_path_name = fhandler_disk_dummy_name;
} }
int 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_name (path, real_path.get_win32 ());
set_no_free_names (0);
return open (real_path, flags, mode); return open (real_path, flags, mode);
} }
int int
fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) 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 ()) if (real_path.isbinary ())
{ {
set_r_binary (1); 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_has_acls (real_path.has_acls ());
set_isremote (real_path.isremote ()); set_isremote (real_path.isremote ());
if (real_path.file_attributes () != (DWORD)-1 if (real_path.isdir ())
&& (real_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
flags |= O_DIROPEN; flags |= O_DIROPEN;
int res = this->fhandler_base::open (flags, mode); int res = this->fhandler_base::open (flags, mode);

View File

@ -65,8 +65,7 @@ enum
FH_W95LSBUG = 0x00400000, /* set when lseek is called as a flag that FH_W95LSBUG = 0x00400000, /* set when lseek is called as a flag that
* _write should check if we've moved beyond * _write should check if we've moved beyond
* EOF, zero filling if so. */ * EOF, zero filling if so. */
FH_NOFRNAME = 0x00800000, /* Set if shouldn't free unix_path_name and FH_UNUSED = 0x00800000, /* currently unused. */
windows_path_name_ on destruction. */
FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */ FH_NOEINTR = 0x01000000, /* Set if I/O should be uninterruptible. */
FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */ FH_FFIXUP = 0x02000000, /* Set if need to fixup after fork. */
FH_LOCAL = 0x04000000, /* File is unix domain socket */ 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, void set_name (const char * unix_path, const char * win32_path = NULL,
int unit = 0); int unit = 0);
void reset_unix_path_name (const char *);
virtual fhandler_base& operator =(fhandler_base &x); virtual fhandler_base& operator =(fhandler_base &x);
fhandler_base (DWORD dev, const char *name = 0, int unit = 0); fhandler_base (DWORD dev, const char *name = 0, int unit = 0);
virtual ~fhandler_base (); virtual ~fhandler_base ();
@ -301,10 +301,6 @@ public:
int isremote () { return FHISSETF (ISREMOTE); } int isremote () { return FHISSETF (ISREMOTE); }
void set_isremote (int val) { FHCONDSETF (val, 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_name () { return unix_path_name; }
const char *get_win32_name () { return win32_path_name; } const char *get_win32_name () { return win32_path_name; }
unsigned long get_namehash () { return namehash; } unsigned long get_namehash () { return namehash; }

View File

@ -24,6 +24,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "sync.h" #include "sync.h"

View File

@ -20,9 +20,9 @@
#include "perprocess.h" #include "perprocess.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "path.h"
/* static wrapper functions to hide the effect of media changes and /* static wrapper functions to hide the effect of media changes and
bus resets which occurs after a new media is inserted. This is bus resets which occurs after a new media is inserted. This is

View File

@ -27,6 +27,7 @@
#include "cygwin/version.h" #include "cygwin/version.h"
#include "perprocess.h" #include "perprocess.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "sigproc.h" #include "sigproc.h"

View File

@ -19,9 +19,9 @@ details. */
#include "perprocess.h" #include "perprocess.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "path.h"
/**********************************************************************/ /**********************************************************************/
/* fhandler_dev_tape */ /* fhandler_dev_tape */

View File

@ -19,6 +19,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
@ -441,11 +442,6 @@ fhandler_tty_slave::fhandler_tty_slave (int num, const char *name) :
{ {
set_cb (sizeof *this); set_cb (sizeof *this);
ttynum = num; 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); debug_printf ("unix '%s', win32 '%s'", unix_path_name, win32_path_name);
inuse = NULL; inuse = NULL;
} }

View File

@ -17,6 +17,7 @@ details. */
#include <errno.h> #include <errno.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "sync.h" #include "sync.h"

View File

@ -22,8 +22,8 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h"
#include "path.h" #include "path.h"
#include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "pwdgrp.h" #include "pwdgrp.h"

View File

@ -18,6 +18,7 @@ details. */
#include "shared_info.h" #include "shared_info.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"

View File

@ -17,6 +17,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include <sys/termios.h> #include <sys/termios.h>

View File

@ -16,6 +16,7 @@ details. */
#include <assert.h> #include <assert.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "heap.h" #include "heap.h"

View File

@ -16,6 +16,7 @@ details. */
#include <errno.h> #include <errno.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "cygheap.h" #include "cygheap.h"

View File

@ -16,8 +16,8 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "dtable.h"
#include "path.h" #include "path.h"
#include "dtable.h"
#include "sync.h" #include "sync.h"
#include "sigproc.h" #include "sigproc.h"
#include "pinfo.h" #include "pinfo.h"

View File

@ -2428,8 +2428,7 @@ symlink (const char *topath, const char *frompath)
syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ()); syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ());
if (win32_path.is_device () || if (win32_path.is_device () || win32_path.exists ())
win32_path.file_attributes () != (DWORD) -1)
{ {
set_errno (EEXIST); set_errno (EEXIST);
goto done; goto done;
@ -2897,7 +2896,7 @@ readlink (const char *path, char *buf, int buflen)
return -1; return -1;
} }
if (pathbuf.file_attributes () == (DWORD) -1) if (!pathbuf.exists ())
{ {
set_errno (ENOENT); set_errno (ENOENT);
return -1; return -1;
@ -3106,8 +3105,9 @@ fchdir (int fd)
set_errno (EBADF); set_errno (EBADF);
return -1; return -1;
} }
SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fchdir");
int ret = chdir (cygheap->fdtab[fd]->get_name ()); 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. /* The name in the fhandler is explicitely overwritten with the full path.
Otherwise fchmod() to a path originally given as a relative path could 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 The 2nd fchmod should chdir to the same dir as the first call, not
to it's parent dir. */ to it's parent dir. */
char path[MAX_PATH];
char posix_path[MAX_PATH]; char posix_path[MAX_PATH];
mount_table->conv_to_posix_path (cygheap->cwd.get (path, 0, 1), cygheap->fdtab.reset_unix_path_name (fd, cygheap->cwd.get (posix_path, 1, 1));
posix_path, 0);
cygheap->fdtab[fd]->set_name (path, posix_path);
} }
ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "fchdir");
syscall_printf ("%d = fchdir (%d)", ret, fd); syscall_printf ("%d = fchdir (%d)", ret, fd);
return ret; return ret;
} }

View File

@ -69,6 +69,12 @@ class path_conv
public: public:
unsigned path_flags; 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 isdisk () const { return path_flags & PATH_ISDISK;}
int isremote () const {return is_remote_drive;} int isremote () const {return is_remote_drive;}
@ -80,6 +86,9 @@ class path_conv
int issymlink () const {return path_flags & PATH_SYMLINK;} int issymlink () const {return path_flags & PATH_SYMLINK;}
int issocket () const {return path_flags & PATH_SOCKET;} int issocket () const {return path_flags & PATH_SOCKET;}
int iscygexec () const {return path_flags & PATH_CYGWIN_EXEC;} 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 () executable_states exec_state ()
{ {
extern int _check_for_executable; 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_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;} 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, void check (const char *src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3))); const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
@ -129,6 +128,8 @@ class path_conv
inline char *get_win32 () { return path; } inline char *get_win32 () { return path; }
operator char *() {return path; } operator char *() {return path; }
operator DWORD &() {return fileattr; }
operator int &() {return (int) fileattr; }
BOOL is_device () {return devn != FH_BAD;} BOOL is_device () {return devn != FH_BAD;}
DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;} DWORD get_devn () {return devn == FH_BAD ? (DWORD) FH_DISK : devn;}
short get_unitn () {return devn == FH_BAD ? 0 : unit;} short get_unitn () {return devn == FH_BAD ? 0 : unit;}

View File

@ -15,6 +15,7 @@ details. */
#include <limits.h> #include <limits.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "sync.h" #include "sync.h"

View File

@ -15,6 +15,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "thread.h" #include "thread.h"

View File

@ -14,6 +14,7 @@
#include <errno.h> #include <errno.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "cygerrno.h" #include "cygerrno.h"

View File

@ -36,6 +36,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "sync.h" #include "sync.h"

View File

@ -19,6 +19,7 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "heap.h" #include "heap.h"

View File

@ -23,6 +23,7 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "child_info.h" #include "child_info.h"

View File

@ -63,10 +63,10 @@ perhaps_suffix (const char *prog, path_conv &buf)
debug_printf ("prog '%s'", prog); debug_printf ("prog '%s'", prog);
buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes); buf.check (prog, PC_SYM_FOLLOW | PC_FULL, std_suffixes);
if (buf.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) if (buf.isdir ())
ext = NULL; ext = NULL;
else if (buf.known_suffix) else if (buf.known_suffix)
ext = buf + (buf.known_suffix - buf.get_win32 ()); ext = (char *) buf + (buf.known_suffix - buf.get_win32 ());
else else
ext = strchr (buf, '\0'); ext = strchr (buf, '\0');

View File

@ -116,16 +116,13 @@ _unlink (const char *ourname)
syscall_printf ("_unlink (%s)", win32_name.get_win32 ()); syscall_printf ("_unlink (%s)", win32_name.get_win32 ());
DWORD atts; if (!win32_name.exists ())
atts = win32_name.file_attributes ();
if (atts == 0xffffffff)
{ {
syscall_printf ("unlinking a nonexistant file"); syscall_printf ("unlinking a nonexistent file");
set_errno (ENOENT); set_errno (ENOENT);
goto done; goto done;
} }
else if (win32_name.isdir ())
if (atts & FILE_ATTRIBUTE_DIRECTORY)
{ {
syscall_printf ("unlinking a directory"); syscall_printf ("unlinking a directory");
set_errno (EPERM); set_errno (EPERM);
@ -140,11 +137,11 @@ _unlink (const char *ourname)
} }
/* Check for shortcut as symlink condition. */ /* Check for shortcut as symlink condition. */
if (atts & FILE_ATTRIBUTE_READONLY) if (win32_name.has_attribute (FILE_ATTRIBUTE_READONLY))
{ {
int len = strlen (win32_name); int len = strlen (win32_name);
if (len > 4 && strcasematch (win32_name + len - 4, ".lnk")) if (len > 4 && strcasematch ((char *) win32_name + len - 4, ".lnk"))
SetFileAttributes (win32_name, atts & ~FILE_ATTRIBUTE_READONLY); SetFileAttributes (win32_name, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY);
} }
DWORD lasterr; DWORD lasterr;
@ -249,11 +246,7 @@ remove (const char *ourname)
return -1; return -1;
} }
DWORD atts = win32_name.file_attributes (); return win32_name.isdir () ? rmdir (ourname) : _unlink (ourname);
if (atts != 0xffffffff && atts & FILE_ATTRIBUTE_DIRECTORY)
return rmdir (ourname);
return _unlink (ourname);
} }
extern "C" pid_t extern "C" pid_t
@ -619,7 +612,7 @@ _link (const char *a, const char *b)
goto done; goto done;
} }
if (real_b.file_attributes () != (DWORD)-1) if (real_b.exists ())
{ {
syscall_printf ("file '%s' exists?", (char *)real_b); syscall_printf ("file '%s' exists?", (char *)real_b);
set_errno (EEXIST); set_errno (EEXIST);
@ -779,7 +772,7 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid)
} }
DWORD attrib = 0; DWORD attrib = 0;
if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) if (win32_path.isdir ())
attrib |= S_IFDIR; attrib |= S_IFDIR;
res = get_file_attribute (win32_path.has_acls (), res = get_file_attribute (win32_path.has_acls (),
win32_path.get_win32 (), win32_path.get_win32 (),
@ -792,12 +785,10 @@ chown_worker (const char *name, unsigned fmode, uid_t uid, gid_t gid)
uid = old_uid; uid = old_uid;
if (gid == (gid_t) -1) if (gid == (gid_t) -1)
gid = old_gid; gid = old_gid;
if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) if (win32_path.isdir())
attrib |= S_IFDIR; attrib |= S_IFDIR;
res = set_file_attribute (win32_path.has_acls (), res = set_file_attribute (win32_path.has_acls (), win32_path, uid,
win32_path.get_win32 (), gid, attrib, cygheap->user.logsrv ());
uid, gid, attrib,
cygheap->user.logsrv ());
} }
if (res != 0 && (!win32_path.has_acls () || !allow_ntsec)) if (res != 0 && (!win32_path.has_acls () || !allow_ntsec))
{ {
@ -886,28 +877,25 @@ chmod (const char *path, mode_t mode)
goto done; goto done;
} }
if (win32_path.file_attributes () == (DWORD)-1) if (!win32_path.exists ())
__seterrno (); __seterrno ();
else else
{ {
DWORD attr = win32_path.file_attributes ();
/* temporary erase read only bit, to be able to set file security */ /* temporary erase read only bit, to be able to set file security */
SetFileAttributesA (win32_path.get_win32 (), SetFileAttributes (win32_path, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY);
attr & ~FILE_ATTRIBUTE_READONLY);
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
if (win32_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY) if (win32_path.isdir ())
mode |= S_IFDIR; mode |= S_IFDIR;
get_file_attribute (win32_path.has_acls (), get_file_attribute (win32_path.has_acls (),
win32_path.get_win32 (), win32_path.get_win32 (),
NULL, &uid, &gid); 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; mode |= S_IFDIR;
if (!set_file_attribute (win32_path.has_acls (), if (!set_file_attribute (win32_path.has_acls (), win32_path, uid, gid,
win32_path.get_win32 (),
uid, gid,
mode, cygheap->user.logsrv ()) mode, cygheap->user.logsrv ())
&& allow_ntsec) && allow_ntsec)
res = 0; 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 /* if the mode we want has any write bits set, we can't
be read only. */ be read only. */
if (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) if (mode & (S_IWUSR | S_IWGRP | S_IWOTH))
attr &= ~FILE_ATTRIBUTE_READONLY; (DWORD) win32_path &= ~FILE_ATTRIBUTE_READONLY;
else else
attr |= FILE_ATTRIBUTE_READONLY; (DWORD) win32_path |= FILE_ATTRIBUTE_READONLY;
if (S_ISLNK (mode) || S_ISSOCK (mode)) 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 (); __seterrno ();
else else
{ {
@ -1084,22 +1072,24 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
int nofollow) int nofollow)
{ {
int res = -1; int res = -1;
int oret = 1; int oret;
int atts;
int attribute = 0;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
path_conv real_path;
UINT dtype; fhandler_base *fh = NULL;
fhandler_disk_file fh (NULL);
MALLOC_CHECK; MALLOC_CHECK;
int open_flags = O_RDONLY | O_BINARY | O_DIROPEN
| (nofollow ? O_NOSYMLINK : 0);
debug_printf ("%s (%s, %p)", caller, name, buf); debug_printf ("%s (%s, %p)", caller, name, buf);
path_conv real_path (name, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | if (check_null_invalid_struct_errno (buf))
PC_FULL, stat_suffixes); 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) if (real_path.error)
{ {
@ -1107,54 +1097,42 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
goto done; goto done;
} }
if (check_null_invalid_struct_errno (buf))
goto done;
memset (buf, 0, sizeof (struct stat)); memset (buf, 0, sizeof (struct stat));
if (real_path.is_device ()) if (real_path.is_device ())
return stat_dev (real_path.get_devn (), real_path.get_unitn (), return stat_dev (real_path.get_devn (), real_path.get_unitn (),
hash_path_name (0, real_path.get_win32 ()), buf); 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 ()); if ((oret = fh->open (real_path, open_flags, 0)))
/* ok */;
dtype = real_path.get_drive_type (); else
if ((atts == -1 || ! (atts & FILE_ATTRIBUTE_DIRECTORY) ||
(wincap.can_open_directories ()
&& dtype != DRIVE_NO_ROOT_DIR
&& dtype != DRIVE_UNKNOWN)))
{ {
oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | int ntsec_atts = 0;
(nofollow ? O_NOSYMLINK : 0), 0);
/* If we couldn't open the file, try a "query open" with no permissions. /* 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. */ This will allow us to determine *some* things about the file, at least. */
if (!oret) 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)
{ {
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 /* Check a special case here. If ntsec is ON it happens
that a process creates a file using mode 000 to disallow that a process creates a file using mode 000 to disallow
other processes access. In contrast to UNIX, this results other processes access. In contrast to UNIX, this results
in a failing open call in the same process. Check that in a failing open call in the same process. Check that
case. */ case. */
if (!oret && allow_ntsec && get_errno () == EACCES
&& !get_file_attribute (TRUE, real_path, &attribute, &uid, &gid)
&& !attribute && uid == myself->uid && gid == myself->gid)
{
set_file_attribute (TRUE, real_path, 0400); set_file_attribute (TRUE, real_path, 0400);
oret = fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | oret = fh->open (real_path, open_flags, 0);
(nofollow ? O_NOSYMLINK : 0), 0); set_file_attribute (TRUE, real_path, ntsec_atts);
set_file_attribute (TRUE, real_path.get_win32 (), 0); }
} }
if (oret) if (oret)
{ {
res = fh.fstat (buf); res = fh->fstat (buf);
fh.close ();
/* The number of links to a directory includes the /* The number of links to a directory includes the
number of subdirectories in the directory, since all number of subdirectories in the directory, since all
those subdirectories point to it. those subdirectories point to it.
@ -1162,28 +1140,23 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
set the number of links to 2. */ set the number of links to 2. */
/* Unfortunately the count of 2 confuses `find (1)' command. So /* Unfortunately the count of 2 confuses `find (1)' command. So
let's try it with `1' as link count. */ let's try it with `1' as link count. */
if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY)) if (real_path.isdir ())
buf->st_nlink = (dtype == DRIVE_REMOTE buf->st_nlink = (real_path.isremote ()
? 1 ? 1 : num_entries (real_path.get_win32 ()));
: num_entries (real_path.get_win32 ())); fh->close ();
goto done;
} }
} else if (real_path.exists ())
if (atts != -1 && (oret || (!oret && get_errno () != ENOENT
&& get_errno () != ENOSHARE)))
{ {
/* Unfortunately, the above open may fail if the file exists, though. /* Unfortunately, the above open may fail if the file exists, though.
So we have to care for this case here, too. */ So we have to care for this case here, too. */
WIN32_FIND_DATA wfd; WIN32_FIND_DATA wfd;
HANDLE handle; HANDLE handle;
buf->st_nlink = 1; buf->st_nlink = 1;
if (atts != -1 if (real_path.isdir () && real_path.isremote ())
&& (atts & FILE_ATTRIBUTE_DIRECTORY)
&& dtype != DRIVE_REMOTE)
buf->st_nlink = num_entries (real_path.get_win32 ()); buf->st_nlink = num_entries (real_path.get_win32 ());
buf->st_dev = FHDEVN (FH_DISK) << 8; buf->st_dev = FHDEVN (FH_DISK) << 8;
buf->st_ino = hash_path_name (0, real_path.get_win32 ()); 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; buf->st_mode = S_IFDIR;
else if (real_path.issymlink ()) else if (real_path.issymlink ())
buf->st_mode = S_IFLNK; 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_uid, &buf->st_gid))
{ {
buf->st_mode |= STD_RBITS | STD_XBITS; 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; buf->st_mode |= STD_WBITS;
if (real_path.issymlink ()) if (real_path.issymlink ())
buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO; 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: done:
if (fh)
delete fh;
MALLOC_CHECK; MALLOC_CHECK;
syscall_printf ("%d = %s (%s, %p)", res, caller, name, buf); syscall_printf ("%d = %s (%s, %p)", res, caller, name, buf);
return res; return res;
@ -1360,7 +1335,7 @@ _rename (const char *oldpath, const char *newpath)
return -1; 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"); syscall_printf ("file to move doesn't exist");
set_errno (ENOENT); 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 /* Destination file exists and is read only, change that or else
the rename won't work. */ the rename won't work. */
if (real_new.file_attributes () != (DWORD) -1 && if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY))
real_new.file_attributes () & FILE_ATTRIBUTE_READONLY) SetFileAttributes (real_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY);
SetFileAttributesA (real_new.get_win32 (),
real_new.file_attributes () & ~FILE_ATTRIBUTE_READONLY);
/* Shortcut hack No. 2, part 1 */ /* Shortcut hack No. 2, part 1 */
if (!real_old.issymlink () && !real_new.error && real_new.issymlink () && if (!real_old.issymlink () && !real_new.error && real_new.issymlink () &&
@ -1421,14 +1394,13 @@ done:
{ {
__seterrno (); __seterrno ();
/* Reset R/O attributes if neccessary. */ /* Reset R/O attributes if neccessary. */
if (real_new.file_attributes () != (DWORD) -1 && if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY))
real_new.file_attributes () & FILE_ATTRIBUTE_READONLY) SetFileAttributes (real_new, real_new);
SetFileAttributesA (real_new.get_win32 (), real_new.file_attributes ());
} }
else else
{ {
/* make the new file have the permissions of the old one */ /* 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 */ /* Shortcut hack, No. 2, part 2 */
/* if the new filename was an existing shortcut, remove it now if the /* if the new filename was an existing shortcut, remove it now if the
@ -1436,12 +1408,12 @@ done:
if (lnk_suffix) if (lnk_suffix)
{ {
*lnk_suffix = '.'; *lnk_suffix = '.';
DeleteFile (real_new.get_win32 ()); DeleteFile (real_new);
} }
} }
syscall_printf ("%d = rename (%s, %s)", res, real_old.get_win32 (), syscall_printf ("%d = rename (%s, %s)", res, (char *) real_old,
real_new.get_win32 ()); (char *) real_new);
return res; return res;
} }
@ -2317,27 +2289,29 @@ extern "C" int
chroot (const char *newroot) chroot (const char *newroot)
{ {
sigframe thisframe (mainthread); sigframe thisframe (mainthread);
int ret = -1;
path_conv path (newroot, PC_SYM_FOLLOW | PC_FULL); path_conv path (newroot, PC_SYM_FOLLOW | PC_FULL);
int ret;
if (path.error) if (path.error)
goto done; ret = -1;
if (path.file_attributes () == (DWORD)-1) else if (!path.exists ())
{ {
set_errno (ENOENT); set_errno (ENOENT);
goto done; ret = -1;
} }
if (!(path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY)) else if (!path.isdir ())
{ {
set_errno (ENOTDIR); set_errno (ENOTDIR);
goto done; ret = -1;
} }
else
{
char buf[MAX_PATH]; char buf[MAX_PATH];
normalize_posix_path (newroot, buf); normalize_posix_path (newroot, buf);
cygheap->root.set (buf, path); cygheap->root.set (buf, path);
ret = 0; ret = 0;
}
done:
syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0, syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0,
newroot ? newroot : "NULL"); newroot ? newroot : "NULL");
return ret; return ret;

View File

@ -16,6 +16,7 @@ details. */
#include <ntdef.h> #include <ntdef.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "cygerrno.h" #include "cygerrno.h"

View File

@ -16,6 +16,7 @@ details. */
#include <unistd.h> #include <unistd.h>
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygerrno.h" #include "cygerrno.h"
#include "cygheap.h" #include "cygheap.h"

View File

@ -17,6 +17,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "cygwin/version.h" #include "cygwin/version.h"

View File

@ -18,6 +18,7 @@ details. */
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "sync.h" #include "sync.h"

View File

@ -23,6 +23,7 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "security.h" #include "security.h"
#include "fhandler.h" #include "fhandler.h"
#include "path.h"
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "registry.h" #include "registry.h"