summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler.cc')
-rw-r--r--winsup/cygwin/fhandler.cc126
1 files changed, 54 insertions, 72 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index a670e7860..54adc8dc2 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -20,15 +20,14 @@ details. */
#include "security.h"
#include "cygwin/version.h"
#include "fhandler.h"
+#include "path.h"
#include "dtable.h"
#include "cygheap.h"
-#include "path.h"
#include "shared_info.h"
+#include <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);