newlib/winsup/cygwin/fhandler.cc

1667 lines
40 KiB
C++
Raw Normal View History

2000-02-17 20:38:33 +01:00
/* fhandler.cc. See console.cc for fhandler_console functions.
2001-09-11 22:01:02 +02:00
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
2000-02-17 20:38:33 +01:00
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
2000-02-17 20:38:33 +01:00
#include <sys/fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
#include <signal.h>
#include "cygerrno.h"
2001-03-05 07:28:25 +01:00
#include "perprocess.h"
#include "security.h"
#include "cygwin/version.h"
#include "fhandler.h"
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.
2001-10-01 06:10:07 +02:00
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
#include "shared_info.h"
#include "sigproc.h"
#include "pinfo.h"
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.
2001-10-01 06:10:07 +02:00
#include <assert.h>
2000-02-17 20:38:33 +01:00
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
struct __cygwin_perfile *perfile_table;
DWORD binmode;
* Makefile.in: Use variables rather than configure constructs where appropriate. (LIBCOS): Find additional stub library stuff in their own subdirectory. * dcrt0.cc: Convert user_data pointer to static __cygwin_user_data area. (do_global_ctors): Check magic_bisquit for initialization. (dll_crt0_1): First group of premain functions prior to fd initialization. Run second group before calling main. (dll_crt0 ()): New function, called from new initialization code. (dll_crt0 (per_process *uptr)): Call new dll_crt0 () function on initialization. * debug.cc (thread_stub): Initialize bottom of stack with per-thread info. * environ.cc (parse_thing): Use binmode global to control CYGWIN=binmode behavior. * fhandler.cc (fhandler_base::open): Allow explicit setting of __fmode to O_BINARY or O_TEXT to override disk mount settings. * libcmain.cc: Move to lib subdirectory. * libccrt0.cc: Ditto. * dll_main.cc: Ditto. * dll_entry.cc: Ditto. * getopt.c: Ditto. * thread.cc (thread_init_wrapper): Call ExitThread explicitly rather than returning, as a preliminary step towards placing per thread info at the bottom of the stack. * winsup.h: Move per_process class to include/sys/cygwin.h. Declare new dll_crt0(). * include/cygwin/version.h: Bump API minor version. * binmode.c: New file. * textmode.c: Ditto. * lib/_cygwin_crt0_common.cc: Ditto. * lib/crt0.h: Ditto. * lib/cygwin_attach_dll.c: Ditto. * lib/cygwin_crt0.c: Ditto. * lib/dll_entry.cc: Ditto. * lib/dll_main.cc: Ditto. * lib/getopt.c: Ditto. * lib/libcmain.c: Ditto. * lib/premain0.c: Ditto. * lib/premain1.c: Ditto. * lib/premain2.c: Ditto. * lib/premain3.c: Ditto.
2000-07-01 05:51:55 +02:00
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
inline fhandler_base&
fhandler_base::operator =(fhandler_base &x)
{
memcpy (this, &x, sizeof *this);
unix_path_name = x.unix_path_name ? cstrdup (x.unix_path_name) : NULL;
win32_path_name = x.win32_path_name ? cstrdup (x.win32_path_name) : NULL;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
rabuf = NULL;
ralen = 0;
raixget = 0;
raixput = 0;
rabuflen = 0;
return *this;
}
2000-02-17 20:38:33 +01:00
int
fhandler_base::puts_readahead (const char *s, size_t len = (size_t) -1)
{
int success = 1;
while ((*s || (len != (size_t) -1 && len--))
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
&& (success = put_readahead (*s++) > 0))
2000-02-17 20:38:33 +01:00
continue;
return success;
}
int
fhandler_base::put_readahead (char value)
{
char *newrabuf;
if (raixput < rabuflen)
/* Nothing to do */;
else if ((newrabuf = (char *) realloc (rabuf, rabuflen += 32)))
rabuf = newrabuf;
else
return 0;
rabuf[raixput++] = value;
ralen++;
return 1;
}
int
fhandler_base::get_readahead ()
{
int chret = -1;
if (raixget < ralen)
chret = ((unsigned char) rabuf[raixget++]) & 0xff;
2000-02-17 20:38:33 +01:00
/* FIXME - not thread safe */
if (raixget >= ralen)
raixget = raixput = ralen = 0;
return chret;
}
int
fhandler_base::peek_readahead (int queryput)
{
int chret = -1;
if (!queryput && raixget < ralen)
chret = ((unsigned char) rabuf[raixget]) & 0xff;
else if (queryput && raixput > 0)
chret = ((unsigned char) rabuf[raixput - 1]) & 0xff;
return chret;
}
void
fhandler_base::set_readahead_valid (int val, int ch = -1)
{
if (!val)
ralen = raixget = raixput = 0;
if (ch != -1)
put_readahead(ch);
}
int
fhandler_base::eat_readahead (int n)
{
int oralen = ralen;
if (n < 0)
n = ralen;
if (n > 0 && ralen)
{
if ((int) (ralen -= n) < 0)
2000-02-17 20:38:33 +01:00
ralen = 0;
if (raixget >= ralen)
raixget = raixput = ralen = 0;
else if (raixput > ralen)
raixput = ralen;
}
return oralen;
}
int
fhandler_base::get_readahead_into_buffer (char *buf, size_t buflen)
{
int ch;
int copied_chars = 0;
while (buflen)
if ((ch = get_readahead ()) < 0)
break;
else
{
buf[copied_chars++] = (unsigned char)(ch & 0xff);
buflen--;
}
return copied_chars;
}
2000-02-17 20:38:33 +01:00
/* 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
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.
2001-10-01 06:10:07 +02:00
be too long (e.g. devices or some such). */
2000-02-17 20:38:33 +01:00
void
fhandler_base::set_name (const char *unix_path, const char *win32_path, int unit)
2000-02-17 20:38:33 +01:00
{
if (unix_path == NULL || !*unix_path)
2000-02-17 20:38:33 +01:00
return;
if (win32_path)
win32_path_name = cstrdup (win32_path);
2000-02-17 20:38:33 +01:00
else
{
const char *fmt = get_native_name ();
win32_path_name = (char *) cmalloc (HEAP_STR, strlen(fmt) + 16);
__small_sprintf (win32_path_name, fmt, unit);
2000-02-17 20:38:33 +01:00
}
if (win32_path_name == NULL)
2000-02-17 20:38:33 +01:00
{
system_printf ("fatal error. strdup failed");
exit (ENOMEM);
}
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.
2001-10-01 06:10:07 +02:00
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);
2000-02-17 20:38:33 +01:00
}
/* Detect if we are sitting at EOF for conditions where Windows
returns an error but UNIX doesn't. */
static int __stdcall
is_at_eof (HANDLE h, DWORD err)
{
DWORD size, upper1, curr;
size = GetFileSize (h, &upper1);
if (upper1 != 0xffffffff || GetLastError () == NO_ERROR)
{
LONG upper2 = 0;
curr = SetFilePointer (h, 0, &upper2, FILE_CURRENT);
if (curr == size && upper1 == (DWORD) upper2)
return 1;
}
SetLastError (err);
return 0;
}
2000-02-17 20:38:33 +01:00
/* Normal file i/o handlers. */
/* Cover function to ReadFile to achieve (as much as possible) Posix style
semantics and use of errno. */
int
fhandler_base::raw_read (void *ptr, size_t ulen)
{
DWORD bytes_read;
if (!ReadFile (get_handle(), ptr, ulen, &bytes_read, 0))
{
int errcode;
/* Some errors are not really errors. Detect such cases here. */
errcode = GetLastError ();
switch (errcode)
{
case ERROR_BROKEN_PIPE:
/* This is really EOF. */
bytes_read = 0;
break;
case ERROR_MORE_DATA:
/* `bytes_read' is supposedly valid. */
break;
case ERROR_NOACCESS:
if (is_at_eof (get_handle (), errcode))
return 0;
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.
2001-10-01 06:10:07 +02:00
case ERROR_INVALID_FUNCTION:
case ERROR_INVALID_PARAMETER:
if (openflags & O_DIROPEN)
{
set_errno (EISDIR);
return -1;
}
2000-02-17 20:38:33 +01:00
default:
syscall_printf ("ReadFile %s failed, %E", unix_path_name);
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
__seterrno_from_win_error (errcode);
2000-02-17 20:38:33 +01:00
return -1;
break;
}
}
return bytes_read;
}
/* Cover function to WriteFile to provide Posix interface and semantics
(as much as possible). */
int
fhandler_base::raw_write (const void *ptr, size_t len)
{
DWORD bytes_written;
if (!WriteFile (get_handle(), ptr, len, &bytes_written, 0))
{
if (GetLastError () == ERROR_DISK_FULL && bytes_written > 0)
return bytes_written;
__seterrno ();
if (get_errno () == EPIPE)
raise (SIGPIPE);
return -1;
}
return bytes_written;
}
#define ACCFLAGS(x) (x & (O_RDONLY | O_WRONLY | O_RDWR))
int
fhandler_base::get_default_fmode (int flags)
{
if (perfile_table)
{
size_t nlen = strlen (get_name ());
unsigned accflags = ACCFLAGS (flags);
for (__cygwin_perfile *pf = perfile_table; pf->name; pf++)
if (!*pf->name && ACCFLAGS (pf->flags) == accflags)
return pf->flags & ~(O_RDONLY | O_WRONLY | O_RDWR);
else
{
size_t pflen = strlen (pf->name);
const char *stem = get_name () + nlen - pflen;
if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1])))
continue;
else if (ACCFLAGS (pf->flags) == accflags && strcasematch (stem, pf->name))
return pf->flags & ~(O_RDONLY | O_WRONLY | O_RDWR);
}
}
return __fmode;
}
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
/* Open system call handler function. */
int
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
fhandler_base::open (path_conv *, int flags, mode_t mode)
2000-02-17 20:38:33 +01:00
{
int res = 0;
HANDLE x;
int file_attributes;
int shared;
int creation_distribution;
SECURITY_ATTRIBUTES sa = sec_none;
2000-02-17 20:38:33 +01:00
syscall_printf ("(%s, %p)", get_win32_name (), flags);
if (get_win32_name () == NULL)
{
set_errno (ENOENT);
goto done;
}
if (get_query_open ())
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.
2001-10-01 06:10:07 +02:00
access = 0;
else if (get_device () == FH_TAPE)
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.
2001-10-01 06:10:07 +02:00
access = GENERIC_READ | GENERIC_WRITE;
2000-02-17 20:38:33 +01:00
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
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.
2001-10-01 06:10:07 +02:00
access = GENERIC_READ;
2000-02-17 20:38:33 +01:00
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
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.
2001-10-01 06:10:07 +02:00
access = GENERIC_WRITE;
2000-02-17 20:38:33 +01:00
else
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.
2001-10-01 06:10:07 +02:00
access = GENERIC_READ | GENERIC_WRITE;
2000-02-17 20:38:33 +01:00
/* Allow reliable lseek on disk devices. */
if (get_device () == FH_FLOPPY)
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.
2001-10-01 06:10:07 +02:00
access |= GENERIC_READ;
2000-02-17 20:38:33 +01:00
/* FIXME: O_EXCL handling? */
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
{
if (flags & O_CREAT)
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.
2001-10-01 06:10:07 +02:00
creation_distribution = CREATE_ALWAYS;
2000-02-17 20:38:33 +01:00
else
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.
2001-10-01 06:10:07 +02:00
creation_distribution = TRUNCATE_EXISTING;
2000-02-17 20:38:33 +01:00
}
else if (flags & O_CREAT)
creation_distribution = OPEN_ALWAYS;
else
creation_distribution = OPEN_EXISTING;
if ((flags & O_EXCL) && (flags & O_CREAT))
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.
2001-10-01 06:10:07 +02:00
creation_distribution = CREATE_NEW;
2000-02-17 20:38:33 +01:00
if (flags & O_APPEND)
set_append_p();
/* These flags are host dependent. */
shared = wincap.shared ();
2000-02-17 20:38:33 +01:00
file_attributes = FILE_ATTRIBUTE_NORMAL;
if (flags & O_DIROPEN)
file_attributes |= FILE_FLAG_BACKUP_SEMANTICS;
if (get_device () == FH_SERIAL)
file_attributes |= FILE_FLAG_OVERLAPPED;
/* CreateFile() with dwDesiredAccess == 0 when called on remote
share returns some handle, even if file doesn't exist. This code
works around this bug. */
if (get_query_open () &&
isremote () &&
creation_distribution == OPEN_EXISTING &&
GetFileAttributes (get_win32_name ()) == (DWORD) -1)
{
set_errno (ENOENT);
goto done;
}
/* If the file should actually be created and ntsec is on,
set files attributes. */
if (flags & O_CREAT && get_device () == FH_DISK && allow_ntsec && has_acls ())
set_security_attribute (mode, &sa, alloca (4096), 4096);
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
x = CreateFile (get_win32_name (), access, shared, &sa, creation_distribution,
file_attributes, 0);
2000-02-17 20:38:33 +01:00
syscall_printf ("%p = CreateFileA (%s, %p, %p, %p, %p, %p, 0)",
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
x, get_win32_name (), access, shared, &sa,
creation_distribution, file_attributes);
2000-02-17 20:38:33 +01:00
if (x == INVALID_HANDLE_VALUE)
{
if (GetLastError () == ERROR_INVALID_HANDLE)
set_errno (ENOENT);
else
__seterrno ();
goto done;
}
/* Attributes may be set only if a file is _really_ created.
This code is now only used for ntea here since the files
security attributes are set in CreateFile () now. */
if (flags & O_CREAT && get_device () == FH_DISK
&& GetLastError () != ERROR_ALREADY_EXISTS
&& !allow_ntsec && allow_ntea)
2000-02-17 20:38:33 +01:00
set_file_attribute (has_acls (), get_win32_name (), mode);
namehash = hash_path_name (0, get_win32_name ());
2000-02-17 20:38:33 +01:00
set_io_handle (x);
int bin;
int fmode;
if ((bin = flags & (O_BINARY | O_TEXT)))
/* nothing to do */;
else if ((fmode = get_default_fmode (flags)) & O_BINARY)
* Makefile.in: Use variables rather than configure constructs where appropriate. (LIBCOS): Find additional stub library stuff in their own subdirectory. * dcrt0.cc: Convert user_data pointer to static __cygwin_user_data area. (do_global_ctors): Check magic_bisquit for initialization. (dll_crt0_1): First group of premain functions prior to fd initialization. Run second group before calling main. (dll_crt0 ()): New function, called from new initialization code. (dll_crt0 (per_process *uptr)): Call new dll_crt0 () function on initialization. * debug.cc (thread_stub): Initialize bottom of stack with per-thread info. * environ.cc (parse_thing): Use binmode global to control CYGWIN=binmode behavior. * fhandler.cc (fhandler_base::open): Allow explicit setting of __fmode to O_BINARY or O_TEXT to override disk mount settings. * libcmain.cc: Move to lib subdirectory. * libccrt0.cc: Ditto. * dll_main.cc: Ditto. * dll_entry.cc: Ditto. * getopt.c: Ditto. * thread.cc (thread_init_wrapper): Call ExitThread explicitly rather than returning, as a preliminary step towards placing per thread info at the bottom of the stack. * winsup.h: Move per_process class to include/sys/cygwin.h. Declare new dll_crt0(). * include/cygwin/version.h: Bump API minor version. * binmode.c: New file. * textmode.c: Ditto. * lib/_cygwin_crt0_common.cc: Ditto. * lib/crt0.h: Ditto. * lib/cygwin_attach_dll.c: Ditto. * lib/cygwin_crt0.c: Ditto. * lib/dll_entry.cc: Ditto. * lib/dll_main.cc: Ditto. * lib/getopt.c: Ditto. * lib/libcmain.c: Ditto. * lib/premain0.c: Ditto. * lib/premain1.c: Ditto. * lib/premain2.c: Ditto. * lib/premain3.c: Ditto.
2000-07-01 05:51:55 +02:00
bin = O_BINARY;
else if (fmode & O_TEXT)
* Makefile.in: Use variables rather than configure constructs where appropriate. (LIBCOS): Find additional stub library stuff in their own subdirectory. * dcrt0.cc: Convert user_data pointer to static __cygwin_user_data area. (do_global_ctors): Check magic_bisquit for initialization. (dll_crt0_1): First group of premain functions prior to fd initialization. Run second group before calling main. (dll_crt0 ()): New function, called from new initialization code. (dll_crt0 (per_process *uptr)): Call new dll_crt0 () function on initialization. * debug.cc (thread_stub): Initialize bottom of stack with per-thread info. * environ.cc (parse_thing): Use binmode global to control CYGWIN=binmode behavior. * fhandler.cc (fhandler_base::open): Allow explicit setting of __fmode to O_BINARY or O_TEXT to override disk mount settings. * libcmain.cc: Move to lib subdirectory. * libccrt0.cc: Ditto. * dll_main.cc: Ditto. * dll_entry.cc: Ditto. * getopt.c: Ditto. * thread.cc (thread_init_wrapper): Call ExitThread explicitly rather than returning, as a preliminary step towards placing per thread info at the bottom of the stack. * winsup.h: Move per_process class to include/sys/cygwin.h. Declare new dll_crt0(). * include/cygwin/version.h: Bump API minor version. * binmode.c: New file. * textmode.c: Ditto. * lib/_cygwin_crt0_common.cc: Ditto. * lib/crt0.h: Ditto. * lib/cygwin_attach_dll.c: Ditto. * lib/cygwin_crt0.c: Ditto. * lib/dll_entry.cc: Ditto. * lib/dll_main.cc: Ditto. * lib/getopt.c: Ditto. * lib/libcmain.c: Ditto. * lib/premain0.c: Ditto. * lib/premain1.c: Ditto. * lib/premain2.c: Ditto. * lib/premain3.c: Ditto.
2000-07-01 05:51:55 +02:00
bin = O_TEXT;
2000-02-17 20:38:33 +01:00
else if (get_device () == FH_DISK)
bin = get_w_binary () || get_r_binary ();
else
bin = (binmode == O_BINARY) || get_w_binary () || get_r_binary ();
2000-02-17 20:38:33 +01:00
if (bin & O_TEXT)
bin = 0;
set_flags (flags | (bin ? O_BINARY : O_TEXT));
2000-02-17 20:38:33 +01:00
set_r_binary (bin);
set_w_binary (bin);
syscall_printf ("filemode set to %s", bin ? "binary" : "text");
if (get_device () != FH_TAPE
&& get_device () != FH_FLOPPY
&& get_device () != FH_SERIAL)
{
if (flags & O_APPEND)
SetFilePointer (get_handle(), 0, 0, FILE_END);
else
SetFilePointer (get_handle(), 0, 0, FILE_BEGIN);
}
res = 1;
set_open_status ();
2000-02-17 20:38:33 +01:00
done:
syscall_printf ("%d = fhandler_base::open (%s, %p)", res, get_win32_name (),
flags);
return res;
}
/* states:
open buffer in binary mode? Just do the read.
open buffer in text mode? Scan buffer for control zs and handle
the first one found. Then scan buffer, converting every \r\n into
an \n. If last char is an \r, look ahead one more char, if \n then
modify \r, if not, remember char.
*/
int
fhandler_base::read (void *in_ptr, size_t in_len)
{
int len = (int) in_len;
char *ptr = (char *) in_ptr;
int c;
int copied_chars = 0;
while (len)
if ((c = get_readahead ()) < 0)
break;
else
{
ptr[copied_chars++] = (unsigned char) (c & 0xff);
len--;
}
if (len)
{
int readlen = raw_read (ptr + copied_chars, len);
if (copied_chars == 0)
copied_chars = readlen; /* Propagate error or EOF */
else if (readlen > 0) /* FIXME: should flag EOF for next read */
copied_chars += readlen;
}
if (copied_chars <= 0)
2000-02-17 20:38:33 +01:00
return copied_chars;
if (get_r_binary ())
{
debug_printf ("returning %d chars, binary mode", copied_chars);
return copied_chars;
}
2000-02-17 20:38:33 +01:00
#if 0
char *ctrlzpos;
2000-02-17 20:38:33 +01:00
/* Scan buffer for a control-z and shorten the buffer to that length */
ctrlzpos = (char *) memchr ((char *) ptr, 0x1a, copied_chars);
if (ctrlzpos)
{
lseek ((ctrlzpos - ((char *) ptr + copied_chars)), SEEK_CUR);
copied_chars = ctrlzpos - (char *) ptr;
}
if (copied_chars == 0)
{
debug_printf ("returning 0 chars, text mode, CTRL-Z found");
return 0;
}
#endif
2000-02-17 20:38:33 +01:00
/* Scan buffer and turn \r\n into \n */
* Makefile.in: Remove some obsolete stuff. * dcrt0.cc (dll_crt0_1): Call signal_fixup_after_exec where appropriate. Set myself->uid from parent version. Just use ThreadItem Init method. Close or store hexec_proc as appropriate. (_dll_crt0): Store user_data->forkee here so that proper tests can be made subsequently. (do_exit): Remove hExeced stuff. * environ.cc (environ_init): Accept environ count as well as environ pointer. * environ.h: Reflect above change. * pinfo.cc (pinfo_init): Ditto. Accept environ count. (fixup_in_spawned_child): Remove. * spawn.cc (spawn_guts): Move signal code to dll_crt0_1. Don't suspend execing process since it is no longer necessary. Store envc. * exceptions.cc (signal_fixup_after_exec): New function. (call_handler): Remove hExeced test. * child_info.h (cygheap_exec_info): Store envc as well as envp. (child_info_spawn): Store hexec_proc so that it can be closed in child. * path.cc (normalize_posix_path): Avoid intermediate use of temporary cwd buf. (normalize_win32_path): Ditto. (cwdstuff::get_initial): Always set lock. * sigproc.h: Remove hExeced. * strace.cc (strace::vsprntf): Modify to accomodate for lack of hExeced. * thread.cc (MTinterface::Init): Merge Init1 and ClearReent into this method. (MTinterface::Init1): Eliminate. (MTinterface::ClearReent): Eliminate. * thread.h: Reflect above changes. * include/sys/strace.h (strace): Make microseconds() public. Make various functions 'regparm', throughout. * pinfo.h (_pinfo): Inline simple signal manipulation functions. Requires inclusion of thread.h which was removed from .cc files, where appropriate. throughout. * pinfo.cc: Eliminate signal manipulation functions. (_pinfo::exit): Calculate total rusage for exiting process here. * cygheap.cc (size2bucket): Eliminate. (init_buckets): Ditto. (_cmalloc): Calculate size and bits in a loop rather than going through a function call. (_crealloc): Use stored array index to calculate allocated size. * spawn.cc (spawn_guts): Use _pinfo exit method to exit, calculating cpu usage.
2000-10-17 01:55:58 +02:00
register char *src = (char *) ptr;
2000-02-17 20:38:33 +01:00
register char *dst = (char *) ptr;
register char *end = src + copied_chars - 1;
/* Read up to the last but one char - the last char needs special handling */
while (src < end)
{
*dst = *src++;
if (*dst != '\r' || *src != '\n')
dst++;
}
c = *src;
/* if last char is a '\r' then read one more to see if we should
translate this one too */
if (c == '\r')
{
char c1 = 0;
len = raw_read (&c1, 1);
if (len <= 0)
/* nothing */;
else if (c1 == '\n')
c = '\n';
else
set_readahead_valid (1, c1);
}
*dst++ = c;
copied_chars = dst - (char *) ptr;
#ifndef NOSTRACE
if (strace.active)
2000-02-17 20:38:33 +01:00
{
char buf[16 * 6 + 1];
char *p = buf;
for (int i = 0; i < copied_chars && i < 16; ++i)
{
unsigned char c = ((unsigned char *) ptr)[i];
/* >= 33 so space prints in hex */
__small_sprintf (p, c >= 33 && c <= 127 ? " %c" : " %p", c);
p += strlen (p);
}
debug_printf ("read %d bytes (%s%s)", copied_chars, buf,
copied_chars > 16 ? " ..." : "");
}
#endif
debug_printf ("returning %d chars, text mode", copied_chars);
2000-02-17 20:38:33 +01:00
return copied_chars;
}
int
fhandler_base::write (const void *ptr, size_t len)
{
int res;
if (get_append_p ())
SetFilePointer (get_handle(), 0, 0, FILE_END);
else if (wincap.has_lseek_bug () && get_check_win95_lseek_bug ())
2000-02-17 20:38:33 +01:00
{
/* Note: this bug doesn't happen on NT4, even though the documentation
for WriteFile() says that it *may* happen on any OS. */
int actual_length, current_position;
set_check_win95_lseek_bug (0); /* don't do it again */
actual_length = GetFileSize (get_handle (), NULL);
current_position = SetFilePointer (get_handle (), 0, 0, FILE_CURRENT);
if (current_position > actual_length)
{
/* Oops, this is the bug case - Win95 uses whatever is on the disk
instead of some known (safe) value, so we must seek back and
fill in the gap with zeros. - DJ */
char zeros[512];
int number_of_zeros_to_write = current_position - actual_length;
memset(zeros, 0, 512);
SetFilePointer (get_handle (), 0, 0, FILE_END);
while (number_of_zeros_to_write > 0)
{
DWORD zeros_this_time = (number_of_zeros_to_write > 512
? 512 : number_of_zeros_to_write);
DWORD written;
if (!WriteFile (get_handle (), zeros, zeros_this_time, &written,
NULL))
{
__seterrno ();
if (get_errno () == EPIPE)
raise (SIGPIPE);
/* This might fail, but it's the best we can hope for */
SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN);
return -1;
}
if (written < zeros_this_time) /* just in case */
{
set_errno (ENOSPC);
/* This might fail, but it's the best we can hope for */
SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN);
return -1;
}
number_of_zeros_to_write -= written;
}
}
}
if (get_w_binary ())
{
debug_printf ("binary write");
2000-02-17 20:38:33 +01:00
res = raw_write (ptr, len);
}
else
{
debug_printf ("text write");
2000-02-17 20:38:33 +01:00
/* This is the Microsoft/DJGPP way. Still not ideal, but it's
compatible.
Modified slightly by CGF 2000-10-07 */
2000-02-17 20:38:33 +01:00
int left_in_data = len;
char *data = (char *)ptr;
res = 0;
2000-02-17 20:38:33 +01:00
while (left_in_data > 0)
{
char buf[CHUNK_SIZE + 1], *buf_ptr = buf;
2000-02-17 20:38:33 +01:00
int left_in_buf = CHUNK_SIZE;
while (left_in_buf > 0 && left_in_data > 0)
{
char ch = *data++;
if (ch == '\n')
2000-02-17 20:38:33 +01:00
{
*buf_ptr++ = '\r';
left_in_buf--;
}
*buf_ptr++ = ch;
2000-02-17 20:38:33 +01:00
left_in_buf--;
left_in_data--;
if (left_in_data > 0 && ch == '\r' && *data == '\n')
{
*buf_ptr++ = *data++;
left_in_buf--;
left_in_data--;
}
2000-02-17 20:38:33 +01:00
}
/* We've got a buffer-full, or we're out of data. Write it out */
int nbytes;
2000-02-17 20:38:33 +01:00
int want = buf_ptr - buf;
if ((nbytes = raw_write (buf, want)) == want)
2000-02-17 20:38:33 +01:00
{
/* Keep track of how much written not counting additional \r's */
res = data - (char *)ptr;
continue;
2000-02-17 20:38:33 +01:00
}
if (nbytes == -1)
res = -1; /* Error */
else
res += nbytes; /* Partial write. Return total bytes written. */
break; /* All done */
}
2000-02-17 20:38:33 +01:00
}
debug_printf ("%d = write (%p, %d)", res, ptr, len);
2000-02-17 20:38:33 +01:00
return res;
}
off_t
fhandler_base::lseek (off_t offset, int whence)
{
off_t res;
/* Seeks on text files is tough, we rewind and read till we get to the
right place. */
if (whence != SEEK_CUR || offset != 0)
{
if (whence == SEEK_CUR)
offset -= ralen - raixget;
set_readahead_valid (0);
}
debug_printf ("lseek (%s, %d, %d)", unix_path_name, offset, whence);
2000-02-17 20:38:33 +01:00
#if 0 /* lseek has no business messing about with text-mode stuff */
if (!get_r_binary ())
{
int newplace;
if (whence == 0)
{
newplace = offset;
}
else if (whence ==1)
{
newplace = rpos + offset;
}
else
{
/* Seek from the end of a file.. */
if (rsize == -1)
{
/* Find the size of the file by reading till the end */
char b[CHUNK_SIZE];
while (read (b, sizeof (b)) > 0)
;
rsize = rpos;
}
newplace = rsize + offset;
}
if (rpos > newplace)
{
SetFilePointer (handle, 0, 0, 0);
rpos = 0;
}
/* You can never shrink something more than 50% by turning CRLF into LF,
so we binary chop looking for the right place */
while (rpos < newplace)
{
char b[CHUNK_SIZE];
size_t span = (newplace - rpos) / 2;
if (span == 0)
span = 1;
if (span > sizeof (b))
span = sizeof (b);
debug_printf ("lseek (%s, %d, %d) span %d, rpos %d newplace %d",
name, offset, whence,span,rpos, newplace);
read (b, span);
}
debug_printf ("Returning %d", newplace);
return newplace;
}
#endif /* end of deleted code dealing with text mode */
DWORD win32_whence = whence == SEEK_SET ? FILE_BEGIN
: (whence == SEEK_CUR ? FILE_CURRENT : FILE_END);
res = SetFilePointer (get_handle(), offset, 0, win32_whence);
if (res == -1)
{
__seterrno ();
}
else
{
/* When next we write(), we will check to see if *this* seek went beyond
the end of the file, and back-seek and fill with zeros if so - DJ */
set_check_win95_lseek_bug ();
/* If this was a SEEK_CUR with offset 0, we still might have
readahead that we have to take into account when calculating
the actual position for the application. */
if (whence == SEEK_CUR)
res -= ralen - raixget;
}
return res;
}
int
fhandler_base::close ()
2000-02-17 20:38:33 +01:00
{
int res = -1;
syscall_printf ("handle %p", get_handle());
if (CloseHandle (get_handle()))
res = 0;
else
{
paranoid_printf ("CloseHandle (%d <%s>) failed", get_handle(),
get_name ());
__seterrno ();
}
return res;
}
int
fhandler_base::ioctl (unsigned int cmd, void *buf)
{
if (cmd == FIONBIO)
syscall_printf ("ioctl (FIONBIO, %p)", buf);
else
syscall_printf ("ioctl (%x, %p)", cmd, buf);
set_errno (EINVAL);
return -1;
}
int
fhandler_base::lock (int, struct flock *)
{
set_errno (ENOSYS);
return -1;
}
extern "C" char * __stdcall
rootdir(char *full_path)
{
/* Possible choices:
* d:... -> d:/
* \\server\share... -> \\server\share\
* else current drive.
*/
* Makefile.in: Remove some obsolete stuff. * dcrt0.cc (dll_crt0_1): Call signal_fixup_after_exec where appropriate. Set myself->uid from parent version. Just use ThreadItem Init method. Close or store hexec_proc as appropriate. (_dll_crt0): Store user_data->forkee here so that proper tests can be made subsequently. (do_exit): Remove hExeced stuff. * environ.cc (environ_init): Accept environ count as well as environ pointer. * environ.h: Reflect above change. * pinfo.cc (pinfo_init): Ditto. Accept environ count. (fixup_in_spawned_child): Remove. * spawn.cc (spawn_guts): Move signal code to dll_crt0_1. Don't suspend execing process since it is no longer necessary. Store envc. * exceptions.cc (signal_fixup_after_exec): New function. (call_handler): Remove hExeced test. * child_info.h (cygheap_exec_info): Store envc as well as envp. (child_info_spawn): Store hexec_proc so that it can be closed in child. * path.cc (normalize_posix_path): Avoid intermediate use of temporary cwd buf. (normalize_win32_path): Ditto. (cwdstuff::get_initial): Always set lock. * sigproc.h: Remove hExeced. * strace.cc (strace::vsprntf): Modify to accomodate for lack of hExeced. * thread.cc (MTinterface::Init): Merge Init1 and ClearReent into this method. (MTinterface::Init1): Eliminate. (MTinterface::ClearReent): Eliminate. * thread.h: Reflect above changes. * include/sys/strace.h (strace): Make microseconds() public. Make various functions 'regparm', throughout. * pinfo.h (_pinfo): Inline simple signal manipulation functions. Requires inclusion of thread.h which was removed from .cc files, where appropriate. throughout. * pinfo.cc: Eliminate signal manipulation functions. (_pinfo::exit): Calculate total rusage for exiting process here. * cygheap.cc (size2bucket): Eliminate. (init_buckets): Ditto. (_cmalloc): Calculate size and bits in a loop rather than going through a function call. (_crealloc): Use stored array index to calculate allocated size. * spawn.cc (spawn_guts): Use _pinfo exit method to exit, calculating cpu usage.
2000-10-17 01:55:58 +02:00
char *root = full_path;
2000-02-17 20:38:33 +01:00
if (full_path[1] == ':')
strcpy (full_path + 2, "\\");
else if (full_path[0] == '\\' && full_path[1] == '\\')
{
char *cp = full_path + 2;
while (*cp && *cp != '\\')
cp++;
if (!*cp)
{
set_errno (ENOTDIR);
return NULL;
}
cp++;
while (*cp && *cp != '\\')
cp++;
strcpy (cp, "\\");
}
else
root = NULL;
return root;
}
int __stdcall
fhandler_base::fstat (struct stat *buf, path_conv *)
{
switch (get_device ())
{
case FH_PIPEW:
buf->st_mode = STD_WBITS | S_IWGRP | S_IWOTH;
break;
case FH_PIPER:
buf->st_mode = STD_RBITS;
break;
default:
buf->st_mode = STD_RBITS | STD_WBITS | S_IWGRP | S_IWOTH;
break;
}
buf->st_mode |= get_device () == FH_FLOPPY ? S_IFBLK : S_IFCHR;
buf->st_nlink = 1;
buf->st_blksize = S_BLKSIZE;
buf->st_dev = buf->st_rdev = FHDEVN (get_device ()) << 8 | (get_unit () & 0xff);
buf->st_ino = get_namehash ();
buf->st_atime = buf->st_mtime = buf->st_ctime = time (NULL);
return 0;
}
static int
num_entries (const char *win32_name)
{
WIN32_FIND_DATA buf;
HANDLE handle;
char buf1[MAX_PATH];
int count = 0;
strcpy (buf1, win32_name);
int len = strlen (buf1);
if (len == 0 || isdirsep (buf1[len - 1]))
strcat (buf1, "*");
else
strcat (buf1, "/*"); /* */
handle = FindFirstFileA (buf1, &buf);
if (handle == INVALID_HANDLE_VALUE)
return 0;
count ++;
while (FindNextFileA (handle, &buf))
{
if ((buf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
count ++;
}
FindClose (handle);
return count;
}
int
fhandler_disk_file::fstat (struct stat *buf, path_conv *pc)
{
int res = -1;
int oret;
uid_t uid;
gid_t gid;
int open_flags = O_RDONLY | O_BINARY | O_DIROPEN;
if (!pc)
return fstat_helper (buf);
if ((oret = open (pc, open_flags, 0)))
/* ok */;
else
{
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. */
set_query_open (TRUE);
if ((oret = open (pc, open_flags, 0)))
/* ok */;
else if (allow_ntsec && pc->has_acls () && get_errno () == EACCES
&& !get_file_attribute (TRUE, get_win32_name (), &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, get_win32_name (), 0400);
oret = open (pc, open_flags, 0);
set_file_attribute (TRUE, get_win32_name (), ntsec_atts);
}
}
if (oret)
{
res = fstat_helper (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 (pc->isdir ())
buf->st_nlink = (pc->isremote ()
? 1 : num_entries (pc->get_win32 ()));
close ();
}
else if (pc->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 (pc->isdir () && pc->isremote ())
buf->st_nlink = num_entries (pc->get_win32 ());
buf->st_dev = FHDEVN (FH_DISK) << 8;
buf->st_ino = hash_path_name (0, pc->get_win32 ());
if (pc->isdir ())
buf->st_mode = S_IFDIR;
else if (pc->issymlink ())
buf->st_mode = S_IFLNK;
else if (pc->issocket ())
buf->st_mode = S_IFSOCK;
else
buf->st_mode = S_IFREG;
if (!pc->has_acls ()
|| get_file_attribute (TRUE, pc->get_win32 (),
&buf->st_mode,
&buf->st_uid, &buf->st_gid))
{
buf->st_mode |= STD_RBITS | STD_XBITS;
if (!(pc->has_attribute (FILE_ATTRIBUTE_READONLY)))
buf->st_mode |= STD_WBITS;
if (pc->issymlink ())
buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO;
get_file_attribute (FALSE, pc->get_win32 (),
NULL, &buf->st_uid, &buf->st_gid);
}
if ((handle = FindFirstFile (pc->get_win32 (), &wfd))
!= INVALID_HANDLE_VALUE)
{
buf->st_atime = to_time_t (&wfd.ftLastAccessTime);
buf->st_mtime = to_time_t (&wfd.ftLastWriteTime);
buf->st_ctime = to_time_t (&wfd.ftCreationTime);
buf->st_size = wfd.nFileSizeLow;
buf->st_blksize = S_BLKSIZE;
buf->st_blocks = ((unsigned long) buf->st_size +
S_BLKSIZE-1) / S_BLKSIZE;
FindClose (handle);
}
res = 0;
}
return res;
}
2000-02-17 20:38:33 +01:00
int
fhandler_disk_file::fstat_helper (struct stat *buf)
2000-02-17 20:38:33 +01:00
{
int res = 0; // avoid a compiler warning
BY_HANDLE_FILE_INFORMATION local;
save_errno saved_errno;
2000-02-17 20:38:33 +01:00
/* 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++)
{
if (!(res = GetFileInformationByHandle (get_handle (), &local)))
break;
if (local.dwVolumeSerialNumber && (long) local.dwVolumeSerialNumber != -1)
break;
}
debug_printf ("%d = GetFileInformationByHandle (%s, %d)",
res, get_win32_name (), get_handle ());
if (res == 0)
{
/* GetFileInformationByHandle will fail if it's given stdin/out/err
or a pipe*/
DWORD lsize, hsize;
if (GetFileType (get_handle ()) != FILE_TYPE_DISK)
buf->st_mode = S_IFCHR;
lsize = GetFileSize (get_handle (), &hsize);
if (lsize == 0xffffffff && GetLastError () != NO_ERROR)
buf->st_mode = S_IFCHR;
else
buf->st_size = lsize;
/* We expect these to fail! */
buf->st_mode |= STD_RBITS | STD_WBITS;
buf->st_blksize = S_BLKSIZE;
buf->st_ino = get_namehash ();
syscall_printf ("0 = fstat (, %p)", buf);
return 0;
}
if (!get_win32_name ())
{
saved_errno.set (ENOENT);
2000-02-17 20:38:33 +01:00
return -1;
}
buf->st_atime = to_time_t (&local.ftLastAccessTime);
buf->st_mtime = to_time_t (&local.ftLastWriteTime);
buf->st_ctime = to_time_t (&local.ftCreationTime);
buf->st_nlink = local.nNumberOfLinks;
buf->st_dev = local.dwVolumeSerialNumber;
buf->st_size = local.nFileSizeLow;
/* This is for FAT filesystems, which don't support atime/ctime */
if (buf->st_atime == 0)
buf->st_atime = buf->st_mtime;
if (buf->st_ctime == 0)
buf->st_ctime = buf->st_mtime;
/* Allocate some place to determine the root directory. Need to allocate
enough so that rootdir can add a trailing slash if path starts with \\. */
char root[strlen (get_win32_name ()) + 3];
2000-02-17 20:38:33 +01:00
strcpy (root, get_win32_name ());
/* Assume that if a drive has ACL support it MAY have valid "inodes".
It definitely does not have valid inodes if it does not have ACL
support. */
switch (has_acls () ? GetDriveType (rootdir (root)) : DRIVE_UNKNOWN)
{
case DRIVE_FIXED:
case DRIVE_REMOVABLE:
case DRIVE_CDROM:
case DRIVE_RAMDISK:
/* Although the documentation indicates otherwise, it seems like
"inodes" on these devices are persistent, at least across reboots. */
buf->st_ino = local.nFileIndexHigh | local.nFileIndexLow;
break;
default:
/* Either the nFileIndex* fields are unreliable or unavailable. Use the
next best alternative. */
buf->st_ino = get_namehash ();
break;
}
buf->st_blksize = S_BLKSIZE;
buf->st_blocks = ((unsigned long) buf->st_size + S_BLKSIZE-1) / S_BLKSIZE;
2000-02-17 20:38:33 +01:00
buf->st_mode = 0;
2000-02-17 20:38:33 +01:00
/* Using a side effect: get_file_attibutes checks for
directory. This is used, to set S_ISVTX, if needed. */
if (local.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
buf->st_mode = S_IFDIR;
else if (get_symlink_p ())
buf->st_mode = S_IFLNK;
else if (get_socket_p ())
buf->st_mode = S_IFSOCK;
if (get_file_attribute (has_acls (), get_win32_name (), &buf->st_mode,
&buf->st_uid, &buf->st_gid) == 0)
2000-02-17 20:38:33 +01:00
{
2000-02-21 01:31:55 +01:00
/* If read-only attribute is set, modify ntsec return value */
* Makefile.in: Add `-lshell32 -luuid' to link pass for new-cygwin1.dll. * autoload.cc: Add LoadDLLinitfunc for ole32.dll. Add LoadDLLfuncEx statements for CoInitialize@4, CoUninitialize@0 and CoCreateInstance@20. * dir.cc (dir_suffixes): New datastructure. (readdir): Check for R/O *.lnk files to hide the suffix. (opendir): Use `dir_suffixes' in path conversion. (rmdir): Ditto. * fhandler.cc (fhandler_disk_file::fstat): Add S_IFLNK flag before calling `get_file_attribute'. Take FILE_ATTRIBUTE_READONLY into account only if the file is no symlink. * path.cc (inner_suffixes): New datastructure. (SYMLINKATTR): Eliminated. (path_conv::check): Use `inner_suffixes' on inner path components. (shortcut_header): New global static variable. (shortcut_initalized): Ditto. (create_shortcut_header): New function. (cmp_shortcut_header): Ditto. (symlink): Create symlinks by creating windows shortcuts. Preserve the old code. (symlink_info::check_shortcut): New method. (symlink_info::check_sysfile): Ditto. (symlink_info::check): Check for shortcuts. Move code reading old system attribute symlinks into symlink_info::check_sysfile(). (chdir): Use `dir_suffixes' in path conversion. * security.cc (get_file_attribute): Check for S_IFLNK flag. Force 0777 permissions then. * spawn.cc (std_suffixes): Add ".lnk" suffix. * syscalls.cc (_unlink): Use `inner_suffixes' in path conversion. Check for shortcut symlinks to eliminate R/O attribute before calling DeleteFile(). (stat_suffixes): Add ".lnk" suffix. (stat_worker): Force 0777 permissions if file is a symlink.
2001-02-21 22:49:37 +01:00
if ((local.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
&& !get_symlink_p ())
2000-02-21 01:31:55 +01:00
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
if (!(buf->st_mode & S_IFMT))
2000-02-17 20:38:33 +01:00
buf->st_mode |= S_IFREG;
}
else
{
buf->st_mode |= STD_RBITS;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
if (!(local.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
2000-02-17 20:38:33 +01:00
buf->st_mode |= STD_WBITS;
/* | S_IWGRP | S_IWOTH; we don't give write to group etc */
if (buf->st_mode & S_IFDIR)
buf->st_mode |= S_IFDIR | STD_XBITS;
else if (buf->st_mode & S_IFMT)
/* nothing */;
else if (get_socket_p ())
2000-02-17 20:38:33 +01:00
buf->st_mode |= S_IFSOCK;
else
switch (GetFileType (get_handle ()))
{
case FILE_TYPE_CHAR:
case FILE_TYPE_UNKNOWN:
buf->st_mode |= S_IFCHR;
break;
case FILE_TYPE_DISK:
buf->st_mode |= S_IFREG;
if (!dont_care_if_execable () && !get_execable_p ())
{
DWORD cur, done;
char magic[3];
/* First retrieve current position, set to beginning
of file if not already there. */
cur = SetFilePointer (get_handle(), 0, NULL, FILE_CURRENT);
if (cur != INVALID_SET_FILE_POINTER &&
(!cur ||
SetFilePointer (get_handle(), 0, NULL, FILE_BEGIN)
!= INVALID_SET_FILE_POINTER))
{
/* FIXME should we use /etc/magic ? */
magic[0] = magic[1] = magic[2] = '\0';
if (ReadFile (get_handle (), magic, 3, &done, NULL) &&
has_exec_chars (magic, done))
set_execable_p ();
SetFilePointer (get_handle(), cur, NULL, FILE_BEGIN);
}
}
if (get_execable_p ())
buf->st_mode |= STD_XBITS;
2000-02-17 20:38:33 +01:00
break;
case FILE_TYPE_PIPE:
buf->st_mode |= S_IFSOCK;
break;
}
}
syscall_printf ("0 = fstat (, %p) st_atime=%x st_size=%d, st_mode=%p, st_ino=%d, sizeof=%d",
buf, buf->st_atime, buf->st_size, buf->st_mode,
(int) buf->st_ino, sizeof (*buf));
return 0;
}
void
fhandler_base::init (HANDLE f, DWORD a, mode_t bin)
{
set_io_handle (f);
set_r_binary (bin);
set_w_binary (bin);
access = a;
2000-02-17 20:38:33 +01:00
a &= GENERIC_READ | GENERIC_WRITE;
if (a == GENERIC_READ)
set_flags (O_RDONLY);
if (a == GENERIC_WRITE)
set_flags (O_WRONLY);
if (a == (GENERIC_READ | GENERIC_WRITE))
set_flags (O_RDWR);
set_open_status ();
2000-02-17 20:38:33 +01:00
debug_printf ("created new fhandler_base for handle %p", f);
}
void
fhandler_base::dump (void)
{
paranoid_printf ("here");
}
int
fhandler_base::dup (fhandler_base *child)
{
debug_printf ("in fhandler_base dup");
HANDLE nh;
if (!DuplicateHandle (hMainProc, get_handle(), hMainProc, &nh, 0, TRUE,
DUPLICATE_SAME_ACCESS))
{
system_printf ("dup(%s) failed, handle %x, %E",
get_name (), get_handle());
__seterrno ();
return -1;
}
child->set_io_handle (nh);
return 0;
}
int fhandler_base::fcntl (int cmd, void *arg)
{
int res;
switch (cmd)
{
case F_GETFD:
res = get_close_on_exec () ? FD_CLOEXEC : 0;
break;
case F_SETFD:
set_close_on_exec ((int) arg);
res = 0;
break;
case F_GETFL:
res = get_flags ();
debug_printf ("GETFL: %d", res);
break;
case F_SETFL:
{
/*
* Only O_APPEND, O_ASYNC and O_NONBLOCK/O_NDELAY are allowed.
* Each other flag will be ignored.
* Since O_ASYNC isn't defined in fcntl.h it's currently
* ignored as well.
*/
const int allowed_flags = O_APPEND | O_NONBLOCK_MASK;
int new_flags = (int) arg & allowed_flags;
/* Carefully test for the O_NONBLOCK or deprecated OLD_O_NDELAY flag.
Set only the flag that has been passed in. If both are set, just
record O_NONBLOCK. */
if ((new_flags & OLD_O_NDELAY) && (new_flags & O_NONBLOCK))
new_flags = O_NONBLOCK;
set_flags ((get_flags () & ~allowed_flags) | new_flags);
}
res = 0;
break;
case F_GETLK:
case F_SETLK:
case F_SETLKW:
res = lock (cmd, (struct flock *) arg);
break;
default:
set_errno (EINVAL);
res = -1;
break;
}
return res;
}
2000-02-17 20:38:33 +01:00
/* Base terminal handlers. These just return errors. */
int
fhandler_base::tcflush (int)
2000-02-17 20:38:33 +01:00
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcsendbreak (int)
2000-02-17 20:38:33 +01:00
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcdrain (void)
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcflow (int)
2000-02-17 20:38:33 +01:00
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcsetattr (int, const struct termios *)
2000-02-17 20:38:33 +01:00
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcgetattr (struct termios *)
2000-02-17 20:38:33 +01:00
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcsetpgrp (const pid_t)
2000-02-17 20:38:33 +01:00
{
set_errno (ENOTTY);
return -1;
}
int
fhandler_base::tcgetpgrp (void)
{
set_errno (ENOTTY);
return -1;
}
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
void
fhandler_base::operator delete (void *p)
{
cfree (p);
return;
}
2000-02-17 20:38:33 +01:00
/* Normal I/O constructor */
fhandler_base::fhandler_base (DWORD devtype, const char *name, int unit):
access (0),
2000-02-17 20:38:33 +01:00
io_handle (NULL),
namehash (0),
openflags (0),
2000-02-17 20:38:33 +01:00
rabuf (NULL),
ralen (0),
raixget (0),
raixput (0),
rabuflen (0),
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.
2001-10-01 06:10:07 +02:00
unix_path_name (NULL),
win32_path_name (NULL),
open_status (0)
2000-02-17 20:38:33 +01:00
{
status = devtype;
int bin = __fmode & O_TEXT ? 0 : 1;
if (status != FH_DISK && status != FH_CONSOLE)
{
if (!get_r_binset ())
set_r_binary (bin);
if (!get_w_binset ())
set_w_binary (bin);
}
}
/* Normal I/O destructor */
fhandler_base::~fhandler_base (void)
{
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.
2001-10-01 06:10:07 +02:00
if (unix_path_name != NULL)
cfree (unix_path_name);
if (win32_path_name != NULL)
cfree (win32_path_name);
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
if (rabuf)
free (rabuf);
unix_path_name = win32_path_name = NULL;
2000-02-17 20:38:33 +01:00
}
/**********************************************************************/
/* fhandler_disk_file */
fhandler_disk_file::fhandler_disk_file (const char *name) :
fhandler_base (FH_DISK, name)
{
set_cb (sizeof *this);
}
int
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
fhandler_disk_file::open (path_conv *real_path, int flags, mode_t mode)
2000-02-17 20:38:33 +01:00
{
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
if (real_path->isbinary ())
2000-02-17 20:38:33 +01:00
{
set_r_binary (1);
set_w_binary (1);
}
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
set_has_acls (real_path->has_acls ());
set_isremote (real_path->isremote ());
2000-02-17 20:38:33 +01:00
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
if (real_path->isdir ())
flags |= O_DIROPEN;
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
int res = this->fhandler_base::open (real_path, flags, mode);
2000-02-17 20:38:33 +01:00
if (!res)
goto out;
/* This is for file systems known for having a buggy CreateFile call
which might return a valid HANDLE without having actually opened
the file.
The only known file system to date is the SUN NFS Solstice Client 3.1
which returns a valid handle when trying to open a file in a nonexistent
directory. */
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
if (real_path->has_buggy_open ()
&& GetFileAttributes (win32_path_name) == (DWORD) -1)
{
debug_printf ("Buggy open detected.");
close ();
set_errno (ENOENT);
return 0;
}
2000-02-17 20:38:33 +01:00
if (flags & O_APPEND)
SetFilePointer (get_handle(), 0, 0, FILE_END);
* dcrt0.cc (dll_crt0_1): Don't close hexec_proc if it is NULL. * fork.cc (vfork): Add debugging statements. * path.cc (get_device_number): Make static. Rewrite to inspect both unix and windows paths. (get_raw_device_number): Just check for parts of raw device that we care about. (get_devn): New function, pulled from get_device_number. (win32_device_name): Accomodate arg changes to get_device_number. (mount_info::get_device_number): Call get_device_number on translated Windows path. * spawn.cc (spawn_guts): Don't treat P_VFORK differently from P_NOWAIT. Add handle to child's shared region to child so that it will be preserved if the parent goes away. * fhandler.h: Throughout, simplify to one open method for all fhandler classes, requiring a path_conv first element. * fhandler.cc (fhandler_base::open): Remove obsolete method. Generalize to require path_conv * as first argument. (fhandler_disk_file::open): Remove obsolete method. (fhandler_disk_file::open): Use path_conv pointer rather than reference. * fhandler_clipboard.cc (fhandler_dev_clipboard::dup): Use new open method. (fhandler_dev_clipboard::open): Accomodate new argument for open methods. * fhandler_console.cc (fhandler_console::open): Ditto. (fhandler_console::dup): Use new open method. (fhandler_console::fixup_after_fork): Ditto. (fhandler_console::fixup_after_exec): Ditto. * fhandler_dsp.cc (fhandler_dev_dsp::open): Accomodate new argument for open methods. * fhandler_floppy.cc (fhandler_dev_floppy::open): Ditto. * fhandler_mem.cc (fhandler_dev_mem::open): Ditto. * fhandler_random (fhandler_dev_random::open): Ditto. * fhandler_raw.cc (fhandler_dev_raw::open): Ditto. * fhandler_serial.cc (fhandler_serial::open): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto. * fhandler_tty.cc (fhandler_tty_slave::open): Ditto. (fhandler_pty_master::open): Ditto. * fhandler_windows.cc (fhandler_windows::open): Ditto. * fhandler_zero.cc (fhandler_dev_zero::open): Ditto. * fhandler_socket.cc (fhandler_socket::set_connect_secret): Accomodate new argument for open methods. * syscalls.cc (_open): Ditto. (stat_worker): Ditto.
2001-10-04 04:34:20 +02:00
set_symlink_p (real_path->issymlink ());
set_execable_p (real_path->exec_state ());
set_socket_p (real_path->issocket ());
2000-02-17 20:38:33 +01:00
out:
syscall_printf ("%d = fhandler_disk_file::open (%s, %p)", res,
get_win32_name (), flags);
return res;
}
int
fhandler_disk_file::close ()
{
int res = this->fhandler_base::close ();
if (!res)
2000-02-17 20:38:33 +01:00
cygwin_shared->delqueue.process_queue ();
return res;
}
/*
* FIXME !!!
* The correct way to do this to get POSIX locking
* semantics is to keep a linked list of posix lock
* requests and map them into Win32 locks. The problem
* is that Win32 does not deal correctly with overlapping
* lock requests. Also another pain is that Win95 doesn't do
* non-blocking or non exclusive locks at all. For '95 just
* convert all lock requests into blocking,exclusive locks.
* This shouldn't break many apps but denying all locking
* would.
* For now just convert to Win32 locks and hope for the best.
*/
int
fhandler_disk_file::lock (int cmd, struct flock *fl)
{
int win32_start;
int win32_len;
2000-02-17 20:38:33 +01:00
DWORD win32_upper;
DWORD startpos;
/*
* We don't do getlck calls yet.
*/
if (cmd == F_GETLK)
{
set_errno (ENOSYS);
return -1;
}
/*
* Calculate where in the file to start from,
* then adjust this by fl->l_start.
*/
switch (fl->l_whence)
{
case SEEK_SET:
startpos = 0;
break;
case SEEK_CUR:
if ((off_t) (startpos = lseek (0, SEEK_CUR)) == (off_t)-1)
2000-02-17 20:38:33 +01:00
return -1;
break;
case SEEK_END:
{
BY_HANDLE_FILE_INFORMATION finfo;
if (GetFileInformationByHandle (get_handle(), &finfo) == 0)
{
__seterrno ();
return -1;
}
startpos = finfo.nFileSizeLow; /* Nowhere to keep high word */
break;
}
default:
set_errno (EINVAL);
return -1;
}
/*
* Now the fun starts. Adjust the start and length
* fields until they make sense.
*/
win32_start = startpos + fl->l_start;
if (fl->l_len < 0)
{
win32_start -= fl->l_len;
win32_len = -fl->l_len;
}
else
win32_len = fl->l_len;
if (win32_start < 0)
{
/* watch the signs! */
win32_len -= -win32_start;
2000-02-17 20:38:33 +01:00
if (win32_len <= 0)
{
/* Failure ! */
set_errno (EINVAL);
return -1;
}
win32_start = 0;
}
/*
* Special case if len == 0 for POSIX means lock
* to the end of the entire file (and all future extensions).
*/
if (win32_len == 0)
{
win32_len = 0xffffffff;
win32_upper = wincap.lock_file_highword ();
2000-02-17 20:38:33 +01:00
}
else
win32_upper = 0;
BOOL res;
if (wincap.has_lock_file_ex ())
2000-02-17 20:38:33 +01:00
{
DWORD lock_flags = (cmd == F_SETLK) ? LOCKFILE_FAIL_IMMEDIATELY : 0;
lock_flags |= (fl->l_type == F_WRLCK) ? LOCKFILE_EXCLUSIVE_LOCK : 0;
OVERLAPPED ov;
ov.Internal = 0;
ov.InternalHigh = 0;
ov.Offset = (DWORD)win32_start;
2000-02-17 20:38:33 +01:00
ov.OffsetHigh = 0;
ov.hEvent = (HANDLE) 0;
if (fl->l_type == F_UNLCK)
{
res = UnlockFileEx (get_handle (), 0, (DWORD)win32_len, win32_upper, &ov);
2000-02-17 20:38:33 +01:00
}
else
{
res = LockFileEx (get_handle (), lock_flags, 0, (DWORD)win32_len,
2000-02-17 20:38:33 +01:00
win32_upper, &ov);
/* Deal with the fail immediately case. */
/*
* FIXME !! I think this is the right error to check for
* but I must admit I haven't checked....
*/
if ((res == 0) && (lock_flags & LOCKFILE_FAIL_IMMEDIATELY) &&
(GetLastError () == ERROR_LOCK_FAILED))
{
set_errno (EAGAIN);
return -1;
}
}
}
else
{
/* Windows 95 -- use primitive lock call */
if (fl->l_type == F_UNLCK)
res = UnlockFile (get_handle (), (DWORD)win32_start, 0, (DWORD)win32_len,
2000-02-17 20:38:33 +01:00
win32_upper);
else
res = LockFile (get_handle (), (DWORD)win32_start, 0, (DWORD)win32_len, win32_upper);
2000-02-17 20:38:33 +01:00
}
if (res == 0)
{
__seterrno ();
return -1;
}
return 0;
}
/**********************************************************************/
/* /dev/null */
fhandler_dev_null::fhandler_dev_null (const char *name) :
fhandler_base (FH_NULL, name)
{
set_cb (sizeof *this);
}
void
fhandler_dev_null::dump (void)
{
paranoid_printf ("here");
}
void
fhandler_base::set_inheritance (HANDLE &h, int not_inheriting)
2000-02-17 20:38:33 +01:00
{
/* Note that we could use SetHandleInformation here but it is not available
on all platforms. Test cases seem to indicate that using DuplicateHandle
in this fashion does not actually close the original handle, which is
what we want. If this changes in the future, we may be forced to use
SetHandleInformation on newer OS's */
if (!DuplicateHandle (hMainProc, h, hMainProc, &h, 0, !not_inheriting,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
debug_printf ("DuplicateHandle failed, %E");
#ifdef DEBUGGING
setclexec_pid (h, not_inheriting);
2000-02-17 20:38:33 +01:00
#endif
}
void
fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
{
if (!get_close_on_exec ())
debug_printf ("handle %p already opened", h);
else if (!DuplicateHandle (parent, h, hMainProc, &h, 0, 0,
DUPLICATE_SAME_ACCESS))
2000-02-17 20:38:33 +01:00
system_printf ("%s - %E, handle %s<%p>", get_name (), name, h);
#ifdef DEBUG
else
{
ProtectHandle1 (h, name);
setclexec_pid (h, 0);
}
#endif
2000-02-17 20:38:33 +01:00
}
void
fhandler_base::set_close_on_exec (int val)
{
set_inheritance (io_handle, val);
set_close_on_exec_flag (val);
debug_printf ("set close_on_exec for %s to %d", get_name (), val);
}
void
fhandler_base::fixup_after_fork (HANDLE parent)
{
debug_printf ("inheriting '%s' from parent", get_name ());
fork_fixup (parent, io_handle, "io_handle");
}
int
fhandler_base::is_nonblocking ()
{
return (openflags & O_NONBLOCK_MASK) != 0;
}
void
fhandler_base::set_nonblocking (int yes)
{
int current = openflags & O_NONBLOCK_MASK;
int new_flags = yes ? (!current ? O_NONBLOCK : current) : 0;
openflags = (openflags & ~O_NONBLOCK_MASK) | new_flags;
}