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:
@ -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);
|
||||
|
Reference in New Issue
Block a user