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:
parent
c25c4c5ffc
commit
47063f00e4
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -367,34 +367,31 @@ 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;
|
||||
res = -1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* 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 (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
|
||||
SetFileAttributes (real_dir,
|
||||
(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
|
||||
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)
|
||||
if (GetFileAttributes (real_dir) != (DWORD) -1)
|
||||
set_errno (ENOTEMPTY);
|
||||
else
|
||||
res = 0;
|
||||
|
@ -418,8 +415,8 @@ rmdir (const char *dir)
|
|||
DWORD err = GetLastError ();
|
||||
if (!SetCurrentDirectory ("c:\\"))
|
||||
SetLastError (err);
|
||||
else
|
||||
return rmdir (dir);
|
||||
else if ((res = rmdir (dir)))
|
||||
SetCurrentDirectory (cygheap->cwd.win32);
|
||||
}
|
||||
if (GetLastError () == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
|
@ -435,11 +432,11 @@ rmdir (const char *dir)
|
|||
__seterrno ();
|
||||
|
||||
/* If directory still exists, restore R/O attribute. */
|
||||
if (real_dir.file_attributes () & FILE_ATTRIBUTE_READONLY)
|
||||
SetFileAttributes (real_dir.get_win32 (), real_dir.file_attributes ());
|
||||
if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
|
||||
SetFileAttributes (real_dir, real_dir);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
syscall_printf ("%d = rmdir (%s)", res, dir);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ details. */
|
|||
#include "environ.h"
|
||||
#include "security.h"
|
||||
#include "fhandler.h"
|
||||
#include "path.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,54 +332,36 @@ fhandler_base::open (int flags, mode_t mode)
|
|||
}
|
||||
|
||||
if (get_query_open ())
|
||||
{
|
||||
access = 0;
|
||||
}
|
||||
else if (get_device () == FH_TAPE)
|
||||
{
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
|
||||
{
|
||||
access = GENERIC_READ;
|
||||
}
|
||||
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
|
||||
{
|
||||
access = GENERIC_WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
|
||||
/* Allow reliable lseek on disk devices. */
|
||||
if (get_device () == FH_FLOPPY)
|
||||
{
|
||||
access |= GENERIC_READ;
|
||||
}
|
||||
|
||||
/* FIXME: O_EXCL handling? */
|
||||
|
||||
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
|
||||
{
|
||||
if (flags & O_CREAT)
|
||||
{
|
||||
creation_distribution = CREATE_ALWAYS;
|
||||
}
|
||||
else
|
||||
{
|
||||
creation_distribution = TRUNCATE_EXISTING;
|
||||
}
|
||||
}
|
||||
else if (flags & O_CREAT)
|
||||
creation_distribution = OPEN_ALWAYS;
|
||||
else
|
||||
creation_distribution = OPEN_EXISTING;
|
||||
|
||||
if ((flags & O_EXCL) && (flags & O_CREAT))
|
||||
{
|
||||
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)
|
||||
if (unix_path_name != NULL)
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -18,6 +18,7 @@ details. */
|
|||
#include "shared_info.h"
|
||||
#include "security.h"
|
||||
#include "fhandler.h"
|
||||
#include "path.h"
|
||||
#include "dtable.h"
|
||||
#include "cygheap.h"
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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,54 +1097,42 @@ 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);
|
||||
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
|
||||
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)
|
||||
{
|
||||
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);
|
||||
oret = fh->open (real_path, open_flags, 0);
|
||||
set_file_attribute (TRUE, real_path, ntsec_atts);
|
||||
}
|
||||
}
|
||||
if (oret)
|
||||
{
|
||||
res = fh.fstat (buf);
|
||||
fh.close ();
|
||||
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.
|
||||
|
@ -1162,28 +1140,23 @@ stat_worker (const char *caller, const char *name, struct stat *buf,
|
|||
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;
|
||||
if (real_path.isdir ())
|
||||
buf->st_nlink = (real_path.isremote ()
|
||||
? 1 : num_entries (real_path.get_win32 ()));
|
||||
fh->close ();
|
||||
}
|
||||
}
|
||||
if (atts != -1 && (oret || (!oret && get_errno () != ENOENT
|
||||
&& get_errno () != ENOSHARE)))
|
||||
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;
|
||||
}
|
||||
|
||||
done:
|
||||
syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0,
|
||||
newroot ? newroot : "NULL");
|
||||
return ret;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue