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>
* environ.cc (winenv): Allocate exact amount of space needed for forced

View File

@ -15,8 +15,8 @@
#include <stdlib.h>
#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"

View File

@ -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"

View File

@ -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;
}

View File

@ -15,6 +15,7 @@ details. */
#include "environ.h"
#include "security.h"
#include "fhandler.h"
#include "path.h"
#include "dtable.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);
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)
{

View File

@ -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);

View File

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

View File

@ -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 <assert.h>
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);

View File

@ -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; }

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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 */

View File

@ -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;
}

View File

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

View File

@ -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"

View File

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

View File

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

View File

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

View File

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

View File

@ -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"

View File

@ -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;
}

View File

@ -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;}

View File

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

View File

@ -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"

View File

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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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');

View File

@ -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;

View File

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

View File

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

View File

@ -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"

View File

@ -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"

View File

@ -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"