libc/winsup/cygwin/fcntl.cc
Corinna Vinschen 3f3bd10104 * Throughout, use __try/__except/__endtry blocks, rather than myfault
handler.
	* cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs
	has been moved from _local_storage to _cygtls.
	* cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage
	of counters.  Change type of counters to uint32_t for clarity.
	Remove _cygtls as friend class.
	(struct _local_storage): Move pathbufs from here...
	(struct _cygtls): ...to here, allowing to access it from _sigbe.
	(class san): Only define on 32 bit.  Remove errno, _c_cnt and _w_cnt
	members.
	(san::setup): Drop parameter.  Don't initialize removed members.
	(san::leave): Don't set removed members.
	(class myfault): Only define on 32 bit.
	(myfault::faulted): Only keep implementation not taking any parameter.
	Drop argument in call to sebastian.setup.
	(__try/__leave/__except/__endtry): Implement to support real SEH.  For
	now stick to SJLJ on 32 bit.
	* dcrt0.cc (dll_crt0_0): Drop 64 bit call to
	exception::install_myfault_handler.
	* exception.h (exception_handler): Define with EXCEPTION_DISPOSITION
	as return type.
	(PDISPATCHER_CONTEXT): Define as void * on 32 bit.  Define as pointer
	to _DISPATCHER_CONTEXT on 64 bit.
	(class exception): Define separately for 32 and 64 bit.
	(exception::myfault): Add handler for myfault SEH handling on 64 bit.
	(exception::exception): Fix mangled method name to account for change
	in type of last parameter.
	(exception::install_myfault_handler): Remove.
	* exceptions.cc (exception::myfault_handle): Remove.
	(exception::myfault): New SEH handler for 64 bit.
	* gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when
	returning to the caller.
	* ntdll.h: Move a comment to a better place.
	(struct _SCOPE_TABLE): Define on 64 bit.
	* thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround.
	* tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs.
	(tls_pathbuf::destroy): Change type of loop variables to uint32_t.
	* tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to
	uint32_t.  Accommodate new place of pathbufs.
	* tlsoffsets.h: Regenerate.
	* tlsoffsets64.h: Regenerate.
2014-08-22 09:21:33 +00:00

126 lines
3 KiB
C++

/* fcntl.cc: fcntl syscall
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009,
2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
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"
#include <unistd.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "cygtls.h"
extern "C" int
fcntl64 (int fd, int cmd, ...)
{
int res = -1;
intptr_t arg = 0;
va_list args;
pthread_testcancel ();
__try
{
debug_printf ("fcntl(%d, %d, ...)", fd, cmd);
cygheap_fdget cfd (fd, true);
if (cfd < 0)
__leave;
/* FIXME? All numerical args to fcntl are defined as long on Linux.
This relies on a really dirty trick on x86_64: A 32 bit mov to
a register (e.g. mov $1, %edx) always sets the high 32 bit to 0.
We're following the Linux lead here since the third arg to any
function is in a register anyway (%r8 in MS ABI). That's the easy
case which is covered here by always reading the arg with
sizeof (intptr_t) == sizeof (long) == sizeof (void*) which matches
all targets.
However, the POSIX standard defines all numerical args as type int.
If we take that literally, we had a (small) problem on 64 bit, since
sizeof (void*) != sizeof (int). If we would like to follow POSIX more
closely than Linux, we'd have to call va_arg on a per cmd basis. */
va_start (args, cmd);
arg = va_arg (args, intptr_t);
va_end (args);
switch (cmd)
{
case F_DUPFD:
case F_DUPFD_CLOEXEC:
if (arg >= 0 && arg < OPEN_MAX_MAX)
{
int flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
res = cygheap->fdtab.dup3 (fd, cygheap_fdnew ((arg) - 1), flags);
}
else
{
set_errno (EINVAL);
res = -1;
}
break;
default:
res = cfd->fcntl (cmd, arg);
break;
}
}
__except (EFAULT) {}
__endtry
syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg);
return res;
}
#ifdef __x86_64__
EXPORT_ALIAS (fcntl64, fcntl)
EXPORT_ALIAS (fcntl64, _fcntl)
#else
extern "C" int
_fcntl (int fd, int cmd, ...)
{
intptr_t arg = 0;
va_list args;
struct __flock32 *src = NULL;
struct flock dst;
__try
{
va_start (args, cmd);
arg = va_arg (args, intptr_t);
va_end (args);
if (cmd == F_GETLK || cmd == F_SETLK || cmd == F_SETLKW)
{
src = (struct __flock32 *) arg;
dst.l_type = src->l_type;
dst.l_whence = src->l_whence;
dst.l_start = src->l_start;
dst.l_len = src->l_len;
dst.l_pid = src->l_pid;
arg = (intptr_t) &dst;
}
int res = fcntl64 (fd, cmd, arg);
if (cmd == F_GETLK)
{
src->l_type = dst.l_type;
src->l_whence = dst.l_whence;
src->l_start = dst.l_start;
src->l_len = dst.l_len;
src->l_pid = (short) dst.l_pid;
}
return res;
}
__except (EFAULT)
__endtry
return -1;
}
#endif