* 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.
This commit is contained in:
Corinna Vinschen 2014-08-22 09:21:33 +00:00
parent 33ed7bb5bc
commit 3f3bd10104
41 changed files with 6383 additions and 5924 deletions

View File

@ -1,3 +1,48 @@
2014-08-21 Corinna Vinschen <corinna@vinschen.de>
* 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-21 Corinna Vinschen <corinna@vinschen.de> 2014-08-21 Corinna Vinschen <corinna@vinschen.de>
* miscfuncs.cc (__import_address): Cover the first dereference to imp * miscfuncs.cc (__import_address): Cover the first dereference to imp

View File

@ -638,10 +638,7 @@ init_cygheap::find_tls (int sig, bool& issig_wait)
_cygtls *t = NULL; _cygtls *t = NULL;
issig_wait = false; issig_wait = false;
myfault efault; __try
if (efault.faulted ())
threadlist[ix]->remove (INFINITE);
else
{ {
ix = -1; ix = -1;
/* Scan thread list looking for valid signal-delivery candidates */ /* Scan thread list looking for valid signal-delivery candidates */
@ -652,11 +649,15 @@ init_cygheap::find_tls (int sig, bool& issig_wait)
{ {
t = cygheap->threadlist[ix]; t = cygheap->threadlist[ix];
issig_wait = true; issig_wait = true;
goto out; __leave;
} }
else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig)) else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig))
t = cygheap->threadlist[ix]; t = cygheap->threadlist[ix];
} }
out: __except (NO_ERROR)
{
threadlist[ix]->remove (INFINITE);
}
__endtry
return t; return t;
} }

View File

@ -193,7 +193,7 @@ _cygtls::remove (DWORD wait)
free_local (servent_buf); free_local (servent_buf);
free_local (hostent_buf); free_local (hostent_buf);
/* Free temporary TLS path buffers. */ /* Free temporary TLS path buffers. */
locals.pathbufs.destroy (); pathbufs.destroy ();
/* Close timer handle. */ /* Close timer handle. */
if (locals.cw_timer) if (locals.cw_timer)
NtClose (locals.cw_timer); NtClose (locals.cw_timer);

View File

@ -44,18 +44,21 @@ details. */
#else #else
#pragma pack(push,4) #pragma pack(push,4)
#endif #endif
/* Defined here to support auto rebuild of tlsoffsets.h. */ /* Defined here to support auto rebuild of tlsoffsets.h. */
class tls_pathbuf class tls_pathbuf
{ {
int c_cnt; /* Make sure that c_cnt and w_cnt are always the first two members of this
int w_cnt; class, and never change the size (32 bit), unless you also change the
mov statements in sigbe! */
uint32_t c_cnt;
uint32_t w_cnt;
char *c_buf[TP_NUM_C_BUFS]; char *c_buf[TP_NUM_C_BUFS];
WCHAR *w_buf[TP_NUM_W_BUFS]; WCHAR *w_buf[TP_NUM_W_BUFS];
public: public:
void destroy (); void destroy ();
friend class tmp_pathbuf; friend class tmp_pathbuf;
friend class _cygtls;
friend class san; friend class san;
}; };
@ -129,8 +132,6 @@ struct _local_storage
/* thread.cc */ /* thread.cc */
HANDLE cw_timer; HANDLE cw_timer;
/* All functions requiring temporary path buffers. */
tls_pathbuf pathbufs;
char ttybuf[32]; char ttybuf[32];
}; };
@ -188,6 +189,7 @@ public:
struct pthread *tid; struct pthread *tid;
class cygthread *_ctinfo; class cygthread *_ctinfo;
class san *andreas; class san *andreas;
tls_pathbuf pathbufs;
waitq wq; waitq wq;
int sig; int sig;
unsigned incyg; unsigned incyg;
@ -281,34 +283,25 @@ const int CYGTLS_PADSIZE = 12700;
extern PVOID _tlsbase __asm__ ("%fs:4"); extern PVOID _tlsbase __asm__ ("%fs:4");
extern PVOID _tlstop __asm__ ("%fs:8"); extern PVOID _tlstop __asm__ ("%fs:8");
#endif #endif
#define _my_tls (*((_cygtls *) ((char *)_tlsbase - CYGTLS_PADSIZE))) #define _my_tls (*((_cygtls *) ((char *)_tlsbase - CYGTLS_PADSIZE)))
extern _cygtls *_main_tls; extern _cygtls *_main_tls;
extern _cygtls *_sig_tls; extern _cygtls *_sig_tls;
#ifndef __x86_64__
class san class san
{ {
san *_clemente; san *_clemente;
jmp_buf _context; jmp_buf _context;
int _errno;
unsigned _c_cnt;
unsigned _w_cnt;
public: public:
int setup (int myerrno = 0) __attribute__ ((always_inline)) int setup () __attribute__ ((always_inline))
{ {
_clemente = _my_tls.andreas; _clemente = _my_tls.andreas;
_my_tls.andreas = this; _my_tls.andreas = this;
_errno = myerrno;
_c_cnt = _my_tls.locals.pathbufs.c_cnt;
_w_cnt = _my_tls.locals.pathbufs.w_cnt;
return __sjfault (_context); return __sjfault (_context);
} }
void leave () __attribute__ ((always_inline)) void leave () __attribute__ ((always_inline))
{ {
if (_errno)
set_errno (_errno);
/* Restore tls_pathbuf counters in case of error. */
_my_tls.locals.pathbufs.c_cnt = _c_cnt;
_my_tls.locals.pathbufs.w_cnt = _w_cnt;
__ljfault (_context, 1); __ljfault (_context, 1);
} }
void reset () __attribute__ ((always_inline)) void reset () __attribute__ ((always_inline))
@ -324,17 +317,73 @@ public:
~myfault () __attribute__ ((always_inline)) { sebastian.reset (); } ~myfault () __attribute__ ((always_inline)) { sebastian.reset (); }
inline int faulted () __attribute__ ((always_inline)) inline int faulted () __attribute__ ((always_inline))
{ {
return sebastian.setup (0); return sebastian.setup ();
}
inline int faulted (void const *obj, int myerrno = 0) __attribute__ ((always_inline))
{
return !obj || !(*(const char **) obj) || sebastian.setup (myerrno);
}
inline int faulted (int myerrno) __attribute__ ((always_inline))
{
return sebastian.setup (myerrno);
} }
}; };
#endif
/* Exception handling macros. These are required because SEH differs a lot
between 32 and 64 bit. Essentially, on 64 bit, we have to create compile
time SEH tables which define the handler and try/except labels, while on
32 bit we can simply set up an SJLJ handler within the myfault class. */
#define __mem_barrier __asm__ __volatile__ ("" ::: "memory")
#ifdef __x86_64__
#define __try \
{ \
__label__ __l_try, __l_except, __l_endtry; \
__mem_barrier; \
__asm__ goto ("\n" \
" .seh_handler _ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, @except \n" \
" .seh_handlerdata \n" \
" .long 1 \n" \
" .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n" \
" .seh_code \n" \
: : : : __l_try, __l_endtry, __l_except); \
{ \
__l_try: \
__mem_barrier;
#define __leave \
goto __l_endtry
#define __except(__errno) \
goto __l_endtry; \
} \
{ \
__l_except: \
__mem_barrier; \
if (__errno) \
set_errno (__errno);
#define __endtry \
} \
__l_endtry: \
__mem_barrier; \
}
#else /* !__x86_64__ */
#define __try \
{ \
myfault efault; \
if (!efault.faulted ()) \
{
#define __leave \
goto __l_endtry
#define __except(__errno) \
goto __l_endtry; \
} \
{ \
if (__errno) \
set_errno (__errno);
#define __endtry \
} \
__l_endtry: \
__mem_barrier; \
}
#endif /* __x86_64__ */
class set_signal_arrived class set_signal_arrived
{ {

View File

@ -796,10 +796,6 @@ dll_crt0_0 ()
_main_tls = &_my_tls; _main_tls = &_my_tls;
#ifdef __x86_64__
exception::install_myfault_handler ();
#endif
/* Initialize signal processing here, early, in the hopes that the creation /* Initialize signal processing here, early, in the hopes that the creation
of a thread early in the process will cause more predictability in memory of a thread early in the process will cause more predictability in memory
layout for the main thread. */ layout for the main thread. */

View File

@ -28,16 +28,16 @@ details. */
extern "C" int extern "C" int
dirfd (DIR *dir) dirfd (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
set_errno (EINVAL); if (dir->__d_cookie == __DIRENT_COOKIE)
return dir->__d_fd;
syscall_printf ("-1 = dirfd (%p)", dir); syscall_printf ("-1 = dirfd (%p)", dir);
return -1; set_errno (EINVAL);
} }
return dir->__d_fd; __except (EFAULT) {}
__endtry
return -1;
} }
/* Symbol kept for backward compatibility. Don't remove. Don't declare /* Symbol kept for backward compatibility. Don't remove. Don't declare
@ -93,79 +93,86 @@ fdopendir (int fd)
static int static int
readdir_worker (DIR *dir, dirent *de) readdir_worker (DIR *dir, dirent *de)
{ {
myfault efault; int res = 0;
if (efault.faulted ())
return EFAULT;
if (dir->__d_cookie != __DIRENT_COOKIE) __try
{ {
syscall_printf ("%p = readdir (%p)", NULL, dir); if (dir->__d_cookie != __DIRENT_COOKIE)
return EBADF;
}
de->d_ino = 0;
de->d_type = DT_UNKNOWN;
memset (&de->__d_unused1, 0, sizeof (de->__d_unused1));
int res = ((fhandler_base *) dir->__fh)->readdir (dir, de);
if (res == ENMFILE)
{
if (!(dir->__flags & dirent_saw_dot))
{ {
strcpy (de->d_name, "."); syscall_printf ("%p = readdir (%p)", NULL, dir);
dir->__flags |= dirent_saw_dot; res = EBADF;
dir->__d_position++; __leave;
res = 0;
}
else if (!(dir->__flags & dirent_saw_dot_dot))
{
strcpy (de->d_name, "..");
dir->__flags |= dirent_saw_dot_dot;
dir->__d_position++;
res = 0;
}
}
if (!res && !de->d_ino)
{
bool is_dot = false;
bool is_dot_dot = false;
if (de->d_name[0] == '.')
{
if (de->d_name[1] == '\0')
is_dot = true;
else if (de->d_name[1] == '.' && de->d_name[2] == '\0')
is_dot_dot = true;
} }
if (is_dot_dot && !(dir->__flags & dirent_isroot)) de->d_ino = 0;
de->d_ino = readdir_get_ino (((fhandler_base *) dir->__fh)->get_name (), de->d_type = DT_UNKNOWN;
true); memset (&de->__d_unused1, 0, sizeof (de->__d_unused1));
else
res = ((fhandler_base *) dir->__fh)->readdir (dir, de);
if (res == ENMFILE)
{ {
/* Compute d_ino by combining filename hash with directory hash. */ if (!(dir->__flags & dirent_saw_dot))
de->d_ino = ((fhandler_base *) dir->__fh)->get_ino ();
if (!is_dot && !is_dot_dot)
{ {
PUNICODE_STRING w32name = strcpy (de->d_name, ".");
((fhandler_base *) dir->__fh)->pc.get_nt_native_path (); dir->__flags |= dirent_saw_dot;
DWORD devn = ((fhandler_base *) dir->__fh)->get_device (); dir->__d_position++;
/* Paths below /proc don't have a Win32 pendant. */ res = 0;
if (isproc_dev (devn)) }
de->d_ino = hash_path_name (de->d_ino, L"/"); else if (!(dir->__flags & dirent_saw_dot_dot))
else if (w32name->Buffer[w32name->Length / sizeof (WCHAR) - 1] {
!= L'\\') strcpy (de->d_name, "..");
de->d_ino = hash_path_name (de->d_ino, L"\\"); dir->__flags |= dirent_saw_dot_dot;
de->d_ino = hash_path_name (de->d_ino, de->d_name); dir->__d_position++;
res = 0;
} }
} }
}
/* This fills out the old 32 bit d_ino field for old applications,
build under Cygwin before 1.5.x. */
de->__d_internal1 = de->d_ino;
if (!res && !de->d_ino)
{
bool is_dot = false;
bool is_dot_dot = false;
if (de->d_name[0] == '.')
{
if (de->d_name[1] == '\0')
is_dot = true;
else if (de->d_name[1] == '.' && de->d_name[2] == '\0')
is_dot_dot = true;
}
if (is_dot_dot && !(dir->__flags & dirent_isroot))
de->d_ino = readdir_get_ino (((fhandler_base *)
dir->__fh)->get_name (),
true);
else
{
/* Compute d_ino by combining filename hash with directory hash. */
de->d_ino = ((fhandler_base *) dir->__fh)->get_ino ();
if (!is_dot && !is_dot_dot)
{
PUNICODE_STRING w32name =
((fhandler_base *) dir->__fh)->pc.get_nt_native_path ();
DWORD devn = ((fhandler_base *) dir->__fh)->get_device ();
/* Paths below /proc don't have a Win32 pendant. */
if (isproc_dev (devn))
de->d_ino = hash_path_name (de->d_ino, L"/");
else if (w32name->Buffer[w32name->Length / sizeof (WCHAR) - 1]
!= L'\\')
de->d_ino = hash_path_name (de->d_ino, L"\\");
de->d_ino = hash_path_name (de->d_ino, de->d_name);
}
}
}
/* This fills out the old 32 bit d_ino field for old applications,
build under Cygwin before 1.5.x. */
de->__d_internal1 = de->d_ino;
}
__except (NO_ERROR)
{
res = EFAULT;
}
__endtry
return res; return res;
} }
@ -200,16 +207,15 @@ readdir_r (DIR *__restrict dir, dirent *__restrict de, dirent **__restrict ode)
extern "C" long extern "C" long
telldir (DIR *dir) telldir (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
if (dir->__d_cookie == __DIRENT_COOKIE)
return ((fhandler_base *) dir->__fh)->telldir (dir);
set_errno (EBADF); set_errno (EBADF);
return -1;
} }
return ((fhandler_base *) dir->__fh)->telldir (dir); __except (EFAULT) {}
__endtry
return -1;
} }
/* telldir was never defined using off_t in POSIX, only in early versions /* telldir was never defined using off_t in POSIX, only in early versions
@ -225,14 +231,17 @@ telldir64 (DIR *dir)
extern "C" void extern "C" void
seekdir (DIR *dir, long loc) seekdir (DIR *dir, long loc)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return; if (dir->__d_cookie == __DIRENT_COOKIE)
{
if (dir->__d_cookie != __DIRENT_COOKIE) dir->__flags &= dirent_info_mask;
return; ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
dir->__flags &= dirent_info_mask; }
return ((fhandler_base *) dir->__fh)->seekdir (dir, loc); set_errno (EINVAL); /* Diagnosis */
}
__except (EFAULT) {}
__endtry
} }
/* seekdir was never defined using off_t in POSIX, only in early versions /* seekdir was never defined using off_t in POSIX, only in early versions
@ -248,42 +257,45 @@ seekdir64 (DIR *dir, off_t loc)
extern "C" void extern "C" void
rewinddir (DIR *dir) rewinddir (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT)) {
return; if (dir->__d_cookie == __DIRENT_COOKIE)
{
if (dir->__d_cookie != __DIRENT_COOKIE) dir->__flags &= dirent_info_mask;
return; ((fhandler_base *) dir->__fh)->rewinddir (dir);
dir->__flags &= dirent_info_mask; }
return ((fhandler_base *) dir->__fh)->rewinddir (dir); set_errno (EINVAL); /* Diagnosis */
}
__except (EFAULT) {}
__endtry
} }
/* closedir: POSIX 5.1.2.1 */ /* closedir: POSIX 5.1.2.1 */
extern "C" int extern "C" int
closedir (DIR *dir) closedir (DIR *dir)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (dir->__d_cookie != __DIRENT_COOKIE)
{ {
if (dir->__d_cookie == __DIRENT_COOKIE)
{
/* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0;
int res = ((fhandler_base *) dir->__fh)->closedir (dir);
close (dir->__d_fd);
free (dir->__d_dirname);
free (dir->__d_dirent);
free (dir);
syscall_printf ("%R = closedir(%p)", res, dir);
return res;
}
set_errno (EBADF); set_errno (EBADF);
syscall_printf ("%R = closedir(%p)", -1, dir);
return -1;
} }
__except (EFAULT) {}
/* Reset the marker in case the caller tries to use `dir' again. */ __endtry
dir->__d_cookie = 0; syscall_printf ("%R = closedir(%p)", -1, dir);
return -1;
int res = ((fhandler_base *) dir->__fh)->closedir (dir);
close (dir->__d_fd);
free (dir->__d_dirname);
free (dir->__d_dirent);
free (dir);
syscall_printf ("%R = closedir(%p)", res, dir);
return res;
} }
/* mkdir: POSIX 5.4.1.1 */ /* mkdir: POSIX 5.4.1.1 */
@ -294,43 +306,42 @@ mkdir (const char *dir, mode_t mode)
fhandler_base *fh = NULL; fhandler_base *fh = NULL;
tmp_pathbuf tp; tmp_pathbuf tp;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
/* POSIX says mkdir("symlink-to-missing/") should create the
directory "missing", but Linux rejects it with EEXIST. Copy
Linux behavior for now. */
if (!*dir)
{ {
set_errno (ENOENT); /* POSIX says mkdir("symlink-to-missing/") should create the
goto done; directory "missing", but Linux rejects it with EEXIST. Copy
} Linux behavior for now. */
if (isdirsep (dir[strlen (dir) - 1]))
{
/* This converts // to /, but since both give EEXIST, we're okay. */
char *buf;
char *p = stpcpy (buf = tp.c_get (), dir) - 1;
dir = buf;
while (p > dir && isdirsep (*p))
*p-- = '\0';
}
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
goto done; /* errno already set */;
if (fh->error ()) if (!*dir)
{ {
debug_printf ("got %d error from build_fh_name", fh->error ()); set_errno (ENOENT);
set_errno (fh->error ()); __leave;
} }
else if (has_dot_last_component (dir, true)) if (isdirsep (dir[strlen (dir) - 1]))
set_errno (fh->exists () ? EEXIST : ENOENT); {
else if (!fh->mkdir (mode)) /* This converts // to /, but since both give EEXIST, we're okay. */
res = 0; char *buf;
delete fh; char *p = stpcpy (buf = tp.c_get (), dir) - 1;
dir = buf;
while (p > dir && isdirsep (*p))
*p-- = '\0';
}
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
__leave; /* errno already set */;
done: if (fh->error ())
{
debug_printf ("got %d error from build_fh_name", fh->error ());
set_errno (fh->error ());
}
else if (has_dot_last_component (dir, true))
set_errno (fh->exists () ? EEXIST : ENOENT);
else if (!fh->mkdir (mode))
res = 0;
delete fh;
}
__except (EFAULT) {}
__endtry
syscall_printf ("%R = mkdir(%s, %d)", res, dir, mode); syscall_printf ("%R = mkdir(%s, %d)", res, dir, mode);
return res; return res;
} }
@ -342,30 +353,28 @@ rmdir (const char *dir)
int res = -1; int res = -1;
fhandler_base *fh = NULL; fhandler_base *fh = NULL;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
goto done; /* errno already set */;
if (fh->error ())
{ {
debug_printf ("got %d error from build_fh_name", fh->error ()); if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
set_errno (fh->error ()); __leave; /* errno already set */;
if (fh->error ())
{
debug_printf ("got %d error from build_fh_name", fh->error ());
set_errno (fh->error ());
}
else if (!fh->exists ())
set_errno (ENOENT);
else if (has_dot_last_component (dir, false))
set_errno (EINVAL);
else if (isdev_dev (fh->dev ()))
set_errno (ENOTEMPTY);
else if (!fh->rmdir ())
res = 0;
delete fh;
} }
else if (!fh->exists ()) __except (EFAULT) {}
set_errno (ENOENT); __endtry
else if (has_dot_last_component (dir, false))
set_errno (EINVAL);
else if (isdev_dev (fh->dev ()))
set_errno (ENOTEMPTY);
else if (!fh->rmdir ())
res = 0;
delete fh;
done:
syscall_printf ("%R = rmdir(%s)", res, dir); syscall_printf ("%R = rmdir(%s)", res, dir);
return res; return res;
} }

View File

@ -2,7 +2,7 @@
process's environment. process's environment.
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@ -664,19 +664,22 @@ _addenv (const char *name, const char *value, int overwrite)
extern "C" int extern "C" int
putenv (char *str) putenv (char *str)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (*str)
{ {
char *eq = strchr (str, '='); if (*str)
if (eq) {
return _addenv (str, eq + 1, -1); char *eq = strchr (str, '=');
if (eq)
return _addenv (str, eq + 1, -1);
/* Remove str from the environment. */ /* Remove str from the environment. */
unsetenv (str); unsetenv (str);
}
return 0;
} }
return 0; __except (EFAULT) {}
__endtry
return -1;
} }
/* Set the value of the environment variable "name" to be /* Set the value of the environment variable "name" to be
@ -684,15 +687,18 @@ putenv (char *str)
extern "C" int extern "C" int
setenv (const char *name, const char *value, int overwrite) setenv (const char *name, const char *value, int overwrite)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (!name || !*name || strchr (name, '='))
{ {
set_errno (EINVAL); if (!name || !*name || strchr (name, '='))
return -1; {
set_errno (EINVAL);
__leave;
}
return _addenv (name, value, !!overwrite);
} }
return _addenv (name, value, !!overwrite); __except (EFAULT) {}
__endtry
return -1;
} }
/* Delete environment variable "name". */ /* Delete environment variable "name". */
@ -701,22 +707,26 @@ unsetenv (const char *name)
{ {
register char **e; register char **e;
int offset; int offset;
myfault efault;
if (efault.faulted (EFAULT)) __try
return -1;
if (!name || *name == '\0' || strchr (name, '='))
{ {
set_errno (EINVAL); if (!name || *name == '\0' || strchr (name, '='))
return -1; {
set_errno (EINVAL);
__leave;
}
while (my_findenv (name, &offset)) /* if set multiple times */
/* Move up the rest of the array */
for (e = cur_environ () + offset; ; e++)
if (!(*e = *(e + 1)))
break;
return 0;
} }
__except (EFAULT) {}
while (my_findenv (name, &offset)) /* if set multiple times */ __endtry
/* Move up the rest of the array */ return -1;
for (e = cur_environ () + offset; ; e++)
if (!(*e = *(e + 1)))
break;
return 0;
} }
/* Minimal list of Windows vars which must be converted to uppercase. /* Minimal list of Windows vars which must be converted to uppercase.
@ -822,96 +832,101 @@ environ_init (char **envp, int envc)
bool envp_passed_in; bool envp_passed_in;
bool got_something_from_registry; bool got_something_from_registry;
static char NO_COPY cygterm[] = "TERM=cygwin"; static char NO_COPY cygterm[] = "TERM=cygwin";
myfault efault;
tmp_pathbuf tp; tmp_pathbuf tp;
if (efault.faulted ()) __try
api_fatal ("internal error reading the windows environment - too many environment variables?");
char *tmpbuf = tp.t_get ();
got_something_from_registry = regopt (L"default", tmpbuf);
if (myself->progname[0])
got_something_from_registry = regopt (myself->progname, tmpbuf)
|| got_something_from_registry;
if (!envp)
envp_passed_in = 0;
else
{ {
envc++; char *tmpbuf = tp.t_get ();
envc *= sizeof (char *); got_something_from_registry = regopt (L"default", tmpbuf);
char **newenv = (char **) malloc (envc); if (myself->progname[0])
memcpy (newenv, envp, envc); got_something_from_registry = regopt (myself->progname, tmpbuf)
cfree (envp); || got_something_from_registry;
/* Older applications relied on the fact that cygwin malloced elements of the if (!envp)
environment list. */ envp_passed_in = 0;
envp = newenv; else
if (ENVMALLOC) {
for (char **e = newenv; *e; e++) envc++;
{ envc *= sizeof (char *);
char *p = *e; char **newenv = (char **) malloc (envc);
*e = strdup (p); memcpy (newenv, envp, envc);
cfree (p); cfree (envp);
}
envp_passed_in = 1; /* Older applications relied on the fact that cygwin malloced elements of the
goto out; environment list. */
envp = newenv;
if (ENVMALLOC)
for (char **e = newenv; *e; e++)
{
char *p = *e;
*e = strdup (p);
cfree (p);
}
envp_passed_in = 1;
goto out;
}
/* Allocate space for environment + trailing NULL + CYGWIN env. */
lastenviron = envp = (char **) malloc ((4 + (envc = 100)) * sizeof (char *));
rawenv = GetEnvironmentStringsW ();
if (!rawenv)
{
system_printf ("GetEnvironmentStrings returned NULL, %E");
return;
}
debug_printf ("GetEnvironmentStrings returned %p", rawenv);
/* Current directory information is recorded as variables of the
form "=X:=X:\foo\bar; these must be changed into something legal
(we could just ignore them but maybe an application will
eventually want to use them). */
for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++)
{
sys_wcstombs_alloc (&newp, HEAP_NOTHEAP, w);
if (i >= envc)
envp = (char **) realloc (envp, (4 + (envc += 100)) * sizeof (char *));
envp[i] = newp;
if (*newp == '=')
*newp = '!';
char *eq = strchrnul (newp, '=');
ucenv (newp, eq); /* uppercase env vars which need it */
if (*newp == 'T' && strncmp (newp, "TERM=", 5) == 0)
sawTERM = 1;
else if (*newp == 'C' && strncmp (newp, "CYGWIN=", 7) == 0)
parse_options (newp + 7);
if (*eq)
posify_maybe (envp + i, *++eq ? eq : --eq, tmpbuf);
debug_printf ("%p: %s", envp[i], envp[i]);
}
if (!sawTERM)
envp[i++] = strdup (cygterm);
envp[i] = NULL;
FreeEnvironmentStringsW (rawenv);
out:
findenv_func = (char * (*)(const char*, int*)) my_findenv;
__cygwin_environ = envp;
update_envptrs ();
if (envp_passed_in)
{
p = getenv ("CYGWIN");
if (p)
parse_options (p);
}
if (got_something_from_registry)
parse_options (NULL); /* possibly export registry settings to
environment */
MALLOC_CHECK;
} }
__except (NO_ERROR)
/* Allocate space for environment + trailing NULL + CYGWIN env. */
lastenviron = envp = (char **) malloc ((4 + (envc = 100)) * sizeof (char *));
rawenv = GetEnvironmentStringsW ();
if (!rawenv)
{ {
system_printf ("GetEnvironmentStrings returned NULL, %E"); api_fatal ("internal error reading the windows environment "
return; "- too many environment variables?");
} }
debug_printf ("GetEnvironmentStrings returned %p", rawenv); __endtry
/* Current directory information is recorded as variables of the
form "=X:=X:\foo\bar; these must be changed into something legal
(we could just ignore them but maybe an application will
eventually want to use them). */
for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++)
{
sys_wcstombs_alloc (&newp, HEAP_NOTHEAP, w);
if (i >= envc)
envp = (char **) realloc (envp, (4 + (envc += 100)) * sizeof (char *));
envp[i] = newp;
if (*newp == '=')
*newp = '!';
char *eq = strchrnul (newp, '=');
ucenv (newp, eq); /* uppercase env vars which need it */
if (*newp == 'T' && strncmp (newp, "TERM=", 5) == 0)
sawTERM = 1;
else if (*newp == 'C' && strncmp (newp, "CYGWIN=", 7) == 0)
parse_options (newp + 7);
if (*eq)
posify_maybe (envp + i, *++eq ? eq : --eq, tmpbuf);
debug_printf ("%p: %s", envp[i], envp[i]);
}
if (!sawTERM)
envp[i++] = strdup (cygterm);
envp[i] = NULL;
FreeEnvironmentStringsW (rawenv);
out:
findenv_func = (char * (*)(const char*, int*)) my_findenv;
__cygwin_environ = envp;
update_envptrs ();
if (envp_passed_in)
{
p = getenv ("CYGWIN");
if (p)
parse_options (p);
}
if (got_something_from_registry)
parse_options (NULL); /* possibly export registry settings to
environment */
MALLOC_CHECK;
} }
/* Function called by qsort to sort environment strings. */ /* Function called by qsort to sort environment strings. */

View File

@ -94,8 +94,10 @@ to install your own exception filter. This one is documented.
a teensy bit of detail of the innards of exception handling (i.e. what we a teensy bit of detail of the innards of exception handling (i.e. what we
have to do). */ have to do). */
typedef int (exception_handler) (EXCEPTION_RECORD *, struct _exception_list *, typedef EXCEPTION_DISPOSITION (exception_handler) (EXCEPTION_RECORD *,
CONTEXT *, void *); struct _exception_list *,
CONTEXT *,
void *);
typedef struct _exception_list typedef struct _exception_list
{ {
@ -104,70 +106,53 @@ typedef struct _exception_list
} exception_list; } exception_list;
extern exception_list *_except_list asm ("%fs:0"); extern exception_list *_except_list asm ("%fs:0");
#else typedef void *PDISPATCHER_CONTEXT;
typedef void exception_list;
#endif /* !__x86_64 */
class exception class exception
{ {
#ifdef __x86_64__
static LONG myfault_handle (LPEXCEPTION_POINTERS ep);
#else
exception_list el; exception_list el;
exception_list *save; exception_list *save;
#endif /* __x86_64__ */ static EXCEPTION_DISPOSITION handle (EXCEPTION_RECORD *, exception_list *,
static int handle (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *); CONTEXT *, PDISPATCHER_CONTEXT);
public: public:
exception () __attribute__ ((always_inline)) exception () __attribute__ ((always_inline))
{ {
/* Install SEH handler. */ /* Install SEH handler. */
save = _except_list;
el.handler = handle;
el.prev = _except_list;
_except_list = &el;
};
~exception () __attribute__ ((always_inline)) { _except_list = save; }
};
#else
#define exception_list void
typedef struct _DISPATCHER_CONTEXT *PDISPATCHER_CONTEXT;
class exception
{
#ifdef __x86_64__ #ifdef __x86_64__
static EXCEPTION_DISPOSITION myfault (EXCEPTION_RECORD *, exception_list *,
CONTEXT *, PDISPATCHER_CONTEXT);
#endif
static EXCEPTION_DISPOSITION handle (EXCEPTION_RECORD *, exception_list *,
CONTEXT *, PDISPATCHER_CONTEXT);
public:
exception () __attribute__ ((always_inline))
{
/* Install SEH handler. */
asm volatile ("\n\ asm volatile ("\n\
1: \n\ 1: \n\
.seh_handler \ .seh_handler \
_ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTS2_, \ _ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, \
@except \n\ @except \n\
.seh_handlerdata \n\ .seh_handlerdata \n\
.long 1 \n\ .long 1 \n\
.rva 1b, 2f, 2f, 2f \n\ .rva 1b, 2f, 2f, 2f \n\
.seh_code \n"); .seh_code \n");
#else
save = _except_list;
el.handler = handle;
el.prev = _except_list;
_except_list = &el;
#endif /* __x86_64__ */
}; };
#ifdef __x86_64__
static void install_myfault_handler () __attribute__ ((always_inline))
{
/* Install myfault exception handler as VEH. Here's what happens:
Some Windows DLLs (advapi32, for instance) are using SEH to catch
exceptions inside its own functions. If we install a VEH handler
to catch all exceptions, our Cygwin VEH handler would illegitimatly
handle exceptions inside of Windows DLLs which are usually handled
by its own SEH handler. So, for standard exceptions we use an SEH
handler as installed in the constructor above so as not to override
the SEH handlers in Windows DLLs.
But we have a special case, myfault handling. The myfault handling
catches exceptions inside of the Cygwin DLL, some of them entirely
expected as in verifyable_object_isvalid. The ultimately right thing
to do would be to install SEH handlers for each of these cases.
But there are two problems with that:
1. It would be a massive and, partially unreliable change in the
calling functions due to the incomplete SEH support in GCC.
2. It doesn't always work. Certain DLLs appear to call Cygwin
functions during DLL initialization while the SEH handler is
not installed in the active call frame. For these cases we
need a more generic approach.
So, what we do here is to install a myfault VEH handler. This
function is called from dll_crt0_0, so the myfault handler is
available very early. */
AddVectoredExceptionHandler (1, myfault_handle);
}
~exception () __attribute__ ((always_inline)) ~exception () __attribute__ ((always_inline))
{ {
asm volatile ("\n\ asm volatile ("\n\
@ -175,11 +160,10 @@ public:
2: \n\ 2: \n\
nop \n"); nop \n");
} }
#else
~exception () __attribute__ ((always_inline)) { _except_list = save; }
#endif /* !__x86_64__ */
}; };
#endif /* !__x86_64 */
class cygwin_exception class cygwin_exception
{ {
PUINT_PTR framep; PUINT_PTR framep;

View File

@ -341,38 +341,41 @@ void
cygwin_exception::dumpstack () cygwin_exception::dumpstack ()
{ {
static bool already_dumped; static bool already_dumped;
myfault efault;
if (efault.faulted ())
return;
if (already_dumped || cygheap->rlim_core == 0Ul) __try
return;
already_dumped = true;
open_stackdumpfile ();
if (e)
dump_exception ();
int i;
thestack.init (framep, 1, ctx); /* Initialize from the input CONTEXT */
#ifdef __x86_64__
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
#else
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
#endif
for (i = 0; i < 16 && thestack++; i++)
{ {
small_printf (_AFMT " " _AFMT, thestack.sf.AddrFrame.Offset, if (already_dumped || cygheap->rlim_core == 0Ul)
thestack.sf.AddrPC.Offset); return;
for (unsigned j = 0; j < NPARAMS; j++) already_dumped = true;
small_printf ("%s" _AFMT, j == 0 ? " (" : ", ", thestack.sf.Params[j]); open_stackdumpfile ();
small_printf (")\r\n");
if (e)
dump_exception ();
int i;
thestack.init (framep, 1, ctx); /* Initialize from the input CONTEXT */
#ifdef __x86_64__
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
#else
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
#endif
for (i = 0; i < 16 && thestack++; i++)
{
small_printf (_AFMT " " _AFMT, thestack.sf.AddrFrame.Offset,
thestack.sf.AddrPC.Offset);
for (unsigned j = 0; j < NPARAMS; j++)
small_printf ("%s" _AFMT, j == 0 ? " (" : ", ",
thestack.sf.Params[j]);
small_printf (")\r\n");
}
small_printf ("End of stack trace%s\n",
i == 16 ? " (more stack frames may be present)" : "");
if (h)
NtClose (h);
} }
small_printf ("End of stack trace%s\n", __except (NO_ERROR) {}
i == 16 ? " (more stack frames may be present)" : ""); __endtry
if (h)
NtClose (h);
} }
bool bool
@ -549,40 +552,24 @@ rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
#endif /* __x86_64 */ #endif /* __x86_64 */
#ifdef __x86_64__ #ifdef __x86_64__
/* myfault vectored exception handler */ /* myfault exception handler. */
LONG EXCEPTION_DISPOSITION
exception::myfault_handle (LPEXCEPTION_POINTERS ep) exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
PDISPATCHER_CONTEXT dispatch)
{ {
_cygtls& me = _my_tls; PSCOPE_TABLE table = (PSCOPE_TABLE) dispatch->HandlerData;
RtlUnwindEx (frame,
if (me.andreas) (char *) dispatch->ImageBase + table->ScopeRecord[0].JumpTarget,
{ e, 0, in, dispatch->HistoryTable);
/* Only handle the minimum amount of exceptions the myfault handler /* NOTREACHED, make gcc happy. */
was designed for. */ return ExceptionContinueSearch;
switch (ep->ExceptionRecord->ExceptionCode)
{
case STATUS_ACCESS_VIOLATION:
case STATUS_DATATYPE_MISALIGNMENT:
#if 0
/* PAGE_GUARD-based stack commits are based on structured exception
handling. Short-circuiting STATUS_STACK_OVERFLOW in a vectored
exception handler disables that, which can ultimately result in
a spurious SEGV. */
case STATUS_STACK_OVERFLOW:
#endif
case STATUS_ARRAY_BOUNDS_EXCEEDED:
me.andreas->leave (); /* Return from a "san" caught fault */
default:
break;
}
}
return EXCEPTION_CONTINUE_SEARCH;
} }
#endif /* __x86_64 */ #endif
/* Main exception handler. */ /* Main exception handler. */
int EXCEPTION_DISPOSITION
exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *) exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
PDISPATCHER_CONTEXT dispatch)
{ {
static bool NO_COPY debugging; static bool NO_COPY debugging;
_cygtls& me = _my_tls; _cygtls& me = _my_tls;

View File

@ -1,7 +1,7 @@
/* fcntl.cc: fcntl syscall /* fcntl.cc: fcntl syscall
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2008, 2009,
2010, 2011, 2012, 2013 Red Hat, Inc. 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -28,53 +28,54 @@ fcntl64 (int fd, int cmd, ...)
pthread_testcancel (); pthread_testcancel ();
debug_printf ("fcntl(%d, %d, ...)", fd, cmd); __try
myfault efault;
if (efault.faulted (EFAULT))
return -1;
cygheap_fdget cfd (fd, true);
if (cfd < 0)
goto done;
/* 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: debug_printf ("fcntl(%d, %d, ...)", fd, cmd);
if (arg >= 0 && arg < OPEN_MAX_MAX) 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)
{ {
int flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0; case F_DUPFD:
res = cygheap->fdtab.dup3 (fd, cygheap_fdnew ((arg) - 1), flags); 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;
} }
else
{
set_errno (EINVAL);
res = -1;
}
break;
default:
res = cfd->fcntl (cmd, arg);
break;
} }
done: __except (EFAULT) {}
__endtry
syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg); syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg);
return res; return res;
} }
@ -91,32 +92,34 @@ _fcntl (int fd, int cmd, ...)
struct __flock32 *src = NULL; struct __flock32 *src = NULL;
struct flock dst; struct flock dst;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
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; va_start (args, cmd);
dst.l_type = src->l_type; arg = va_arg (args, intptr_t);
dst.l_whence = src->l_whence; va_end (args);
dst.l_start = src->l_start; if (cmd == F_GETLK || cmd == F_SETLK || cmd == F_SETLKW)
dst.l_len = src->l_len; {
dst.l_pid = src->l_pid; src = (struct __flock32 *) arg;
arg = (intptr_t) &dst; 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;
} }
int res = fcntl64 (fd, cmd, arg); __except (EFAULT)
if (cmd == F_GETLK) __endtry
{ return -1;
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;
} }
#endif #endif

View File

@ -2293,14 +2293,17 @@ fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
return -1; return -1;
} }
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1; if (pid)
if (pid) *pid = sec_peer_pid;
*pid = sec_peer_pid; if (euid)
if (euid) *euid = sec_peer_uid;
*euid = sec_peer_uid; if (egid)
if (egid) *egid = sec_peer_gid;
*egid = sec_peer_gid; return 0;
return 0; }
__except (EFAULT) {}
__endtry
return -1;
} }

View File

@ -2,7 +2,7 @@
classes. classes.
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2012, 2013 Red Hat, Inc. 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -977,159 +977,163 @@ mtinfo_drive::set_options (HANDLE mt, int32_t options)
int int
mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf) mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf)
{ {
myfault efault; __try
if (efault.faulted ())
return ERROR_NOACCESS;
if (cmd == MTIOCTOP)
{ {
struct mtop *op = (struct mtop *) buf; if (cmd == MTIOCTOP)
if (lasterr == ERROR_BUS_RESET)
{ {
/* If a bus reset occurs, block further access to this device struct mtop *op = (struct mtop *) buf;
until the user rewinds, unloads or in any other way tries if (lasterr == ERROR_BUS_RESET)
to maintain a well-known tape position. */
if (op->mt_op != MTREW && op->mt_op != MTOFFL
&& op->mt_op != MTRETEN && op->mt_op != MTERASE
&& op->mt_op != MTSEEK && op->mt_op != MTEOM)
return ERROR_BUS_RESET;
/* Try to maintain last lock state after bus reset. */
if (lock >= auto_locked && PrepareTape (mt, TAPE_LOCK, FALSE))
{ {
debug_printf ("Couldn't relock drive after bus reset."); /* If a bus reset occurs, block further access to this device
lock = unlocked; until the user rewinds, unloads or in any other way tries
to maintain a well-known tape position. */
if (op->mt_op != MTREW && op->mt_op != MTOFFL
&& op->mt_op != MTRETEN && op->mt_op != MTERASE
&& op->mt_op != MTSEEK && op->mt_op != MTEOM)
return ERROR_BUS_RESET;
/* Try to maintain last lock state after bus reset. */
if (lock >= auto_locked && PrepareTape (mt, TAPE_LOCK, FALSE))
{
debug_printf ("Couldn't relock drive after bus reset.");
lock = unlocked;
}
} }
} switch (op->mt_op)
switch (op->mt_op) {
{ case MTRESET:
case MTRESET:
break;
case MTFSF:
set_pos (mt, TAPE_SPACE_FILEMARKS, op->mt_count, false);
break;
case MTBSF:
set_pos (mt, TAPE_SPACE_FILEMARKS, -op->mt_count, false);
break;
case MTFSR:
set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, op->mt_count, false);
break;
case MTBSR:
set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, -op->mt_count, false);
break;
case MTWEOF:
write_marks (mt, TAPE_FILEMARKS, op->mt_count);
break;
case MTREW:
set_pos (mt, TAPE_REWIND, 0, false);
break;
case MTOFFL:
case MTUNLOAD:
prepare (mt, TAPE_UNLOAD);
break;
case MTNOP:
lasterr = 0;
break;
case MTRETEN:
if (!get_feature (TAPE_DRIVE_TENSION))
lasterr = ERROR_INVALID_PARAMETER;
else if (!set_pos (mt, TAPE_REWIND, 0, false))
prepare (mt, TAPE_TENSION);
break;
case MTBSFM:
set_pos (mt, TAPE_SPACE_FILEMARKS, -op->mt_count, true);
break;
case MTFSFM:
set_pos (mt, TAPE_SPACE_FILEMARKS, op->mt_count, true);
break;
case MTEOM:
if (fast_eom () && get_feature (TAPE_DRIVE_END_OF_DATA))
set_pos (mt, TAPE_SPACE_END_OF_DATA, 0, false);
else
set_pos (mt, TAPE_SPACE_FILEMARKS, 32767, false);
break;
case MTERASE:
erase (mt, TAPE_ERASE_LONG);
break;
case MTRAS1:
case MTRAS2:
case MTRAS3:
lasterr = ERROR_INVALID_PARAMETER;
break;
case MTSETBLK:
if (!get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
{
lasterr = ERROR_INVALID_PARAMETER;
break; break;
} case MTFSF:
if ((DWORD) op->mt_count == mp ()->BlockSize) set_pos (mt, TAPE_SPACE_FILEMARKS, op->mt_count, false);
{ break;
/* Nothing has changed. */ case MTBSF:
set_pos (mt, TAPE_SPACE_FILEMARKS, -op->mt_count, false);
break;
case MTFSR:
set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, op->mt_count, false);
break;
case MTBSR:
set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, -op->mt_count, false);
break;
case MTWEOF:
write_marks (mt, TAPE_FILEMARKS, op->mt_count);
break;
case MTREW:
set_pos (mt, TAPE_REWIND, 0, false);
break;
case MTOFFL:
case MTUNLOAD:
prepare (mt, TAPE_UNLOAD);
break;
case MTNOP:
lasterr = 0; lasterr = 0;
break; break;
} case MTRETEN:
if ((op->mt_count == 0 && !get_feature (TAPE_DRIVE_VARIABLE_BLOCK)) if (!get_feature (TAPE_DRIVE_TENSION))
|| (op->mt_count > 0 lasterr = ERROR_INVALID_PARAMETER;
&& ((DWORD) op->mt_count < dp ()->MinimumBlockSize else if (!set_pos (mt, TAPE_REWIND, 0, false))
|| (DWORD) op->mt_count > dp ()->MaximumBlockSize))) prepare (mt, TAPE_TENSION);
{ break;
case MTBSFM:
set_pos (mt, TAPE_SPACE_FILEMARKS, -op->mt_count, true);
break;
case MTFSFM:
set_pos (mt, TAPE_SPACE_FILEMARKS, op->mt_count, true);
break;
case MTEOM:
if (fast_eom () && get_feature (TAPE_DRIVE_END_OF_DATA))
set_pos (mt, TAPE_SPACE_END_OF_DATA, 0, false);
else
set_pos (mt, TAPE_SPACE_FILEMARKS, 32767, false);
break;
case MTERASE:
erase (mt, TAPE_ERASE_LONG);
break;
case MTRAS1:
case MTRAS2:
case MTRAS3:
lasterr = ERROR_INVALID_PARAMETER; lasterr = ERROR_INVALID_PARAMETER;
break; break;
} case MTSETBLK:
if (set_blocksize (mt, op->mt_count) if (!get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
&& lasterr == ERROR_INVALID_FUNCTION) {
lasterr = ERROR_INVALID_BLOCK_LENGTH; lasterr = ERROR_INVALID_PARAMETER;
break; break;
case MTSEEK: }
if (get_feature (TAPE_DRIVE_LOGICAL_BLK)) if ((DWORD) op->mt_count == mp ()->BlockSize)
set_pos (mt, TAPE_LOGICAL_BLOCK, op->mt_count, false); {
else if (!get_pos (mt)) /* Nothing has changed. */
set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS, lasterr = 0;
op->mt_count - block, false); break;
break; }
case MTTELL: if ((op->mt_count == 0 && !get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
if (!get_pos (mt)) || (op->mt_count > 0
op->mt_count = (int) block; && ((DWORD) op->mt_count < dp ()->MinimumBlockSize
break; || (DWORD) op->mt_count > dp ()->MaximumBlockSize)))
case MTFSS: {
set_pos (mt, TAPE_SPACE_SETMARKS, op->mt_count, false); lasterr = ERROR_INVALID_PARAMETER;
break; break;
case MTBSS: }
set_pos (mt, TAPE_SPACE_SETMARKS, -op->mt_count, false); if (set_blocksize (mt, op->mt_count)
break; && lasterr == ERROR_INVALID_FUNCTION)
case MTWSM: lasterr = ERROR_INVALID_BLOCK_LENGTH;
write_marks (mt, TAPE_SETMARKS, op->mt_count); break;
break; case MTSEEK:
case MTLOCK: if (get_feature (TAPE_DRIVE_LOGICAL_BLK))
prepare (mt, TAPE_LOCK); set_pos (mt, TAPE_LOGICAL_BLOCK, op->mt_count, false);
break; else if (!get_pos (mt))
case MTUNLOCK: set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS,
prepare (mt, TAPE_UNLOCK); op->mt_count - block, false);
break; break;
case MTLOAD: case MTTELL:
prepare (mt, TAPE_LOAD); if (!get_pos (mt))
break; op->mt_count = (int) block;
case MTCOMPRESSION: break;
set_compression (mt, op->mt_count); case MTFSS:
break; set_pos (mt, TAPE_SPACE_SETMARKS, op->mt_count, false);
case MTSETPART: break;
set_partition (mt, op->mt_count); case MTBSS:
break; set_pos (mt, TAPE_SPACE_SETMARKS, -op->mt_count, false);
case MTMKPART: break;
create_partitions (mt, op->mt_count); case MTWSM:
break; write_marks (mt, TAPE_SETMARKS, op->mt_count);
case MTSETDRVBUFFER: break;
set_options (mt, op->mt_count); case MTLOCK:
break; prepare (mt, TAPE_LOCK);
case MTSETDENSITY: break;
default: case MTUNLOCK:
lasterr = ERROR_INVALID_PARAMETER; prepare (mt, TAPE_UNLOCK);
break; break;
case MTLOAD:
prepare (mt, TAPE_LOAD);
break;
case MTCOMPRESSION:
set_compression (mt, op->mt_count);
break;
case MTSETPART:
set_partition (mt, op->mt_count);
break;
case MTMKPART:
create_partitions (mt, op->mt_count);
break;
case MTSETDRVBUFFER:
set_options (mt, op->mt_count);
break;
case MTSETDENSITY:
default:
lasterr = ERROR_INVALID_PARAMETER;
break;
}
} }
else if (cmd == MTIOCGET)
get_status (mt, (struct mtget *) buf);
else if (cmd == MTIOCPOS && !get_pos (mt))
((struct mtpos *) buf)->mt_blkno = (long) block;
} }
else if (cmd == MTIOCGET) __except (NO_ERROR)
get_status (mt, (struct mtget *) buf); {
else if (cmd == MTIOCPOS && !get_pos (mt)) lasterr = ERROR_NOACCESS;
((struct mtpos *) buf)->mt_blkno = (long) block; }
__endtry
return lasterr; return lasterr;
} }

View File

@ -1761,37 +1761,37 @@ flock (int fd, int operation)
int cmd; int cmd;
struct flock fl = { 0, SEEK_SET, 0, 0, 0 }; struct flock fl = { 0, SEEK_SET, 0, 0, 0 };
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
cygheap_fdget cfd (fd, true);
if (cfd < 0)
goto done;
cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW;
switch (operation & (~LOCK_NB))
{ {
case LOCK_EX: cygheap_fdget cfd (fd, true);
fl.l_type = F_WRLCK; if (cfd < 0)
break; __leave;
case LOCK_SH:
fl.l_type = F_RDLCK; cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW;
break; switch (operation & (~LOCK_NB))
case LOCK_UN: {
fl.l_type = F_UNLCK; case LOCK_EX:
break; fl.l_type = F_WRLCK;
default: break;
set_errno (EINVAL); case LOCK_SH:
goto done; fl.l_type = F_RDLCK;
break;
case LOCK_UN:
fl.l_type = F_UNLCK;
break;
default:
set_errno (EINVAL);
__leave;
}
if (!cfd->mandatory_locking ())
fl.l_type |= F_FLOCK;
res = cfd->mandatory_locking () ? cfd->mand_lock (cmd, &fl)
: cfd->lock (cmd, &fl);
if ((res == -1) && ((get_errno () == EAGAIN) || (get_errno () == EACCES)))
set_errno (EWOULDBLOCK);
} }
if (!cfd->mandatory_locking ()) __except (EFAULT) {}
fl.l_type |= F_FLOCK; __endtry
res = cfd->mandatory_locking () ? cfd->mand_lock (cmd, &fl)
: cfd->lock (cmd, &fl);
if ((res == -1) && ((get_errno () == EAGAIN) || (get_errno () == EACCES)))
set_errno (EWOULDBLOCK);
done:
syscall_printf ("%R = flock(%d, %d)", res, fd, operation); syscall_printf ("%R = flock(%d, %d)", res, fd, operation);
return res; return res;
} }
@ -1805,50 +1805,50 @@ lockf (int filedes, int function, off_t size)
pthread_testcancel (); pthread_testcancel ();
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
cygheap_fdget cfd (filedes, true);
if (cfd < 0)
goto done;
fl.l_start = 0;
fl.l_len = size;
fl.l_whence = SEEK_CUR;
switch (function)
{ {
case F_ULOCK: cygheap_fdget cfd (filedes, true);
cmd = F_SETLK; if (cfd < 0)
fl.l_type = F_UNLCK; __leave;
break;
case F_LOCK: fl.l_start = 0;
cmd = F_SETLKW; fl.l_len = size;
fl.l_type = F_WRLCK; fl.l_whence = SEEK_CUR;
break;
case F_TLOCK: switch (function)
cmd = F_SETLK; {
fl.l_type = F_WRLCK; case F_ULOCK:
break; cmd = F_SETLK;
case F_TEST: fl.l_type = F_UNLCK;
fl.l_type = F_WRLCK; break;
if (cfd->lock (F_GETLK, &fl) == -1) case F_LOCK:
goto done; cmd = F_SETLKW;
if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) fl.l_type = F_WRLCK;
res = 0; break;
else case F_TLOCK:
errno = EAGAIN; cmd = F_SETLK;
goto done; fl.l_type = F_WRLCK;
/* NOTREACHED */ break;
default: case F_TEST:
errno = EINVAL; fl.l_type = F_WRLCK;
goto done; if (cfd->lock (F_GETLK, &fl) == -1)
/* NOTREACHED */ __leave;
if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
res = 0;
else
errno = EAGAIN;
__leave;
/* NOTREACHED */
default:
errno = EINVAL;
__leave;
/* NOTREACHED */
}
res = cfd->mandatory_locking () ? cfd->mand_lock (cmd, &fl)
: cfd->lock (cmd, &fl);
} }
res = cfd->mandatory_locking () ? cfd->mand_lock (cmd, &fl) __except (EFAULT) {}
: cfd->lock (cmd, &fl); __endtry
done:
syscall_printf ("%R = lockf(%d, %d, %D)", res, filedes, function, size); syscall_printf ("%R = lockf(%d, %d, %D)", res, filedes, function, size);
return res; return res;
} }

View File

@ -1,5 +1,5 @@
#!/usr/bin/perl #!/usr/bin/perl
# Copyright 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013 # Copyright 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013, 2014
# Red Hat, Inc. # Red Hat, Inc.
# #
# This file is part of Cygwin. # This file is part of Cygwin.
@ -181,6 +181,8 @@ _sigbe: # return here after cygwin syscall
movq -8(%r11),%r11 # get return address from signal stack movq -8(%r11),%r11 # get return address from signal stack
decl $tls::incyg(%r10) decl $tls::incyg(%r10)
decl $tls::stacklock(%r10) # release lock decl $tls::stacklock(%r10) # release lock
leaq $tls::pathbufs(%r10),%r10 # Address of tls_pathbufs
movq \$0,(%r10) # Set c_cnt and w_cnt to 0
jmp *%r11 # "return" to caller jmp *%r11 # "return" to caller
.seh_endproc .seh_endproc
@ -366,7 +368,7 @@ stabilize_sig_stack:
movq %gs:8,%r12 movq %gs:8,%r12
1: movl \$1,%r10d 1: movl \$1,%r10d
xchgl %r10d,$tls::stacklock(%r12) xchgl %r10d,$tls::stacklock(%r12)
movl %r10d,$tls::spinning(%r12) # flag if we are waiting for lock movl %r10d,$tls::spinning(%r12) # flag if we are waiting for lock
testl %r10d,%r10d testl %r10d,%r10d
jz 2f jz 2f
pause pause
@ -374,14 +376,14 @@ stabilize_sig_stack:
2: incl $tls::incyg(%r12) 2: incl $tls::incyg(%r12)
cmpl \$0,$tls::sig(%r12) cmpl \$0,$tls::sig(%r12)
jz 3f jz 3f
decl $tls::stacklock(%r12) # unlock decl $tls::stacklock(%r12) # unlock
movq \$$tls::start_offset,%rcx # point to beginning movq \$$tls::start_offset,%rcx # point to beginning
addq %r12,%rcx # of tls block addq %r12,%rcx # of tls block
call _ZN7_cygtls19call_signal_handlerEv call _ZN7_cygtls19call_signal_handlerEv
jmp 1b jmp 1b
3: decl $tls::incyg(%r12) 3: decl $tls::incyg(%r12)
addq \$0x20,%rsp addq \$0x20,%rsp
movq %r12,%r11 # return tls addr in r11 movq %r12,%r11 # return tls addr in r11
popq %r12 popq %r12
ret ret
.seh_endproc .seh_endproc
@ -393,13 +395,13 @@ EOF
__sigfe_maybe: __sigfe_maybe:
pushl %ebx pushl %ebx
pushl %edx pushl %edx
movl %fs:4,%ebx # location of bottom of stack movl %fs:4,%ebx # location of bottom of stack
addl \$$tls::initialized,%ebx # where we will be looking addl \$$tls::initialized,%ebx # where we will be looking
cmpl %ebx,%esp # stack loc > than tls cmpl %ebx,%esp # stack loc > than tls
jge 0f # yep. we don't have a tls. jge 0f # yep. we don't have a tls.
subl \$$tls::initialized,%ebx # where we will be looking subl \$$tls::initialized,%ebx # where we will be looking
movl $tls::initialized(%ebx),%eax movl $tls::initialized(%ebx),%eax
cmpl \$0xc763173f,%eax # initialized? cmpl \$0xc763173f,%eax # initialized?
je 1f je 1f
0: popl %edx 0: popl %edx
popl %ebx popl %ebx
@ -408,43 +410,46 @@ __sigfe_maybe:
__sigfe: __sigfe:
pushl %ebx pushl %ebx
pushl %edx pushl %edx
movl %fs:4,%ebx # location of bottom of stack movl %fs:4,%ebx # location of bottom of stack
1: movl \$1,%eax # potential lock value 1: movl \$1,%eax # potential lock value
xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it
movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock
testl %eax,%eax # it will be zero testl %eax,%eax # it will be zero
jz 2f # if so jz 2f # if so
call _yield # should be a short-time thing, so call _yield # should be a short-time thing, so
jmp 1b # sleep and loop jmp 1b # sleep and loop
2: movl \$4,%eax # have the lock, now increment the 2: movl \$4,%eax # have the lock, now increment the
xadd %eax,$tls::stackptr(%ebx) # stack pointer and get pointer xadd %eax,$tls::stackptr(%ebx) # stack pointer and get pointer
leal __sigbe,%edx # new place to return to leal __sigbe,%edx # new place to return to
xchgl %edx,12(%esp) # exchange with real return value xchgl %edx,12(%esp) # exchange with real return value
movl %edx,(%eax) # store real return value on alt stack movl %edx,(%eax) # store real return value on alt stack
incl $tls::incyg(%ebx) incl $tls::incyg(%ebx)
decl $tls::stacklock(%ebx) # remove lock decl $tls::stacklock(%ebx) # remove lock
popl %edx # restore saved value popl %edx # restore saved value
popl %ebx popl %ebx
ret ret
.global __sigbe .global __sigbe
__sigbe: # return here after cygwin syscall __sigbe: # return here after cygwin syscall
pushl %eax # don't clobber pushl %eax # don't clobber
pushl %ebx # tls pointer pushl %ebx # tls pointer
1: movl %fs:4,%ebx # address of bottom of tls 1: movl %fs:4,%ebx # address of bottom of tls
movl \$1,%eax # potential lock value movl \$1,%eax # potential lock value
xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it
movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock
testl %eax,%eax # it will be zero testl %eax,%eax # it will be zero
jz 2f # if so jz 2f # if so
call _yield # sleep call _yield # sleep
jmp 1b # and loop jmp 1b # and loop
2: movl \$-4,%eax # now decrement aux stack 2: movl \$-4,%eax # now decrement aux stack
xadd %eax,$tls::stackptr(%ebx) # and get pointer xadd %eax,$tls::stackptr(%ebx) # and get pointer
movl -4(%eax),%eax # get return address from signal stack movl -4(%eax),%eax # get return address from signal stack
xchgl %eax,4(%esp) # swap return address with saved eax xchgl %eax,4(%esp) # swap return address with saved eax
decl $tls::incyg(%ebx) decl $tls::incyg(%ebx)
decl $tls::stacklock(%ebx) # release lock decl $tls::stacklock(%ebx) # release lock
leal $tls::pathbufs(%ebx),%ebx # Address of tls_pathbufs
movl \$0,(%ebx) # Set c_cnt to 0
movl \$0,4(%ebx) # Set w_cnt to 0
popl %ebx popl %ebx
ret ret

View File

@ -249,8 +249,7 @@ getprogname (void)
extern "C" void extern "C" void
setprogname (const char *newprogname) setprogname (const char *newprogname)
{ {
myfault efault; __try
if (!efault.faulted (EFAULT))
{ {
/* Per BSD man page, setprogname keeps a pointer to the last /* Per BSD man page, setprogname keeps a pointer to the last
path component of the argument. It does *not* copy the path component of the argument. It does *not* copy the
@ -261,6 +260,8 @@ setprogname (const char *newprogname)
else else
__progname = (char *)newprogname; __progname = (char *)newprogname;
} }
__except (EFAULT) {}
__endtry
} }
extern "C" void extern "C" void

View File

@ -312,100 +312,101 @@ extern "C" int
cygwin_rexec (char **ahost, unsigned short rport, char *name, char *pass, cygwin_rexec (char **ahost, unsigned short rport, char *name, char *pass,
char *cmd, int *fd2p) char *cmd, int *fd2p)
{ {
struct sockaddr_in sin, sin2, from; struct sockaddr_in sin, sin2, from;
struct hostent *hp; struct hostent *hp;
u_short port = 0; u_short port = 0;
int s, timo = 1, s3; int s, timo = 1, s3;
char c; char c;
static char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1]; static char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1; hp = cygwin_gethostbyname(*ahost);
if (hp == 0) {
hp = cygwin_gethostbyname(*ahost); cygwin_herror(*ahost);
if (hp == 0) { return (-1);
cygwin_herror(*ahost); }
return (-1); *ahost = strcpy (ahostbuf, hp->h_name);
} ruserpass(hp->h_name, &name, &pass, NULL);
*ahost = strcpy (ahostbuf, hp->h_name); if (!name)
ruserpass(hp->h_name, &name, &pass, NULL); name = getlogin ();
if (!name) if (!pass)
name = getlogin (); pass = almost_null;
if (!pass)
pass = almost_null;
retry: retry:
s = cygwin_socket(AF_INET, SOCK_STREAM, 0); s = cygwin_socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) { if (s < 0) {
perror("rexec: socket"); perror("rexec: socket");
return (-1); return (-1);
} }
sin.sin_family = hp->h_addrtype; sin.sin_family = hp->h_addrtype;
sin.sin_port = rport; sin.sin_port = rport;
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
if (cygwin_connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { if (cygwin_connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
if (errno == ECONNREFUSED && timo <= 16) { if (errno == ECONNREFUSED && timo <= 16) {
(void) close(s); (void) close(s);
sleep(timo); sleep(timo);
timo *= 2; timo *= 2;
goto retry; goto retry;
} }
perror(hp->h_name); perror(hp->h_name);
return (-1); return (-1);
} }
if (fd2p == 0) { if (fd2p == 0) {
(void) write(s, "", 1); (void) write(s, "", 1);
} else { } else {
char num[8]; char num[8];
int s2, sin2len; int s2, sin2len;
s2 = cygwin_socket(AF_INET, SOCK_STREAM, 0); s2 = cygwin_socket(AF_INET, SOCK_STREAM, 0);
if (s2 < 0) { if (s2 < 0) {
(void) close(s); (void) close(s);
return (-1); return (-1);
}
cygwin_listen(s2, 1);
sin2len = sizeof (sin2);
if (cygwin_getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 ||
sin2len != sizeof (sin2)) {
perror("getsockname");
(void) close(s2);
goto bad;
}
port = ntohs((u_short)sin2.sin_port);
(void) sprintf(num, "%u", port);
(void) write(s, num, strlen(num)+1);
{ int len = sizeof (from);
s3 = cygwin_accept(s2, (struct sockaddr *)&from, &len);
close(s2);
if (s3 < 0) {
perror("accept");
port = 0;
goto bad;
} }
cygwin_listen(s2, 1); }
sin2len = sizeof (sin2); *fd2p = s3;
if (cygwin_getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 || }
sin2len != sizeof (sin2)) { (void) write(s, name, strlen(name) + 1);
perror("getsockname"); /* should public key encypt the password here */
(void) close(s2); (void) write(s, pass, strlen(pass) + 1);
goto bad; (void) write(s, cmd, strlen(cmd) + 1);
} if (read(s, &c, 1) != 1) {
port = ntohs((u_short)sin2.sin_port); perror(*ahost);
(void) sprintf(num, "%u", port); goto bad;
(void) write(s, num, strlen(num)+1); }
{ int len = sizeof (from); if (c != 0) {
s3 = cygwin_accept(s2, (struct sockaddr *)&from, &len); while (read(s, &c, 1) == 1) {
close(s2); (void) write(2, &c, 1);
if (s3 < 0) { if (c == '\n')
perror("accept"); break;
port = 0; }
goto bad; goto bad;
} }
} return (s);
*fd2p = s3;
}
(void) write(s, name, strlen(name) + 1);
/* should public key encypt the password here */
(void) write(s, pass, strlen(pass) + 1);
(void) write(s, cmd, strlen(cmd) + 1);
if (read(s, &c, 1) != 1) {
perror(*ahost);
goto bad;
}
if (c != 0) {
while (read(s, &c, 1) == 1) {
(void) write(2, &c, 1);
if (c == '\n')
break;
}
goto bad;
}
return (s);
bad: bad:
if (port) if (port)
(void) close(*fd2p); (void) close(*fd2p);
(void) close(s); (void) close(s);
return (-1); }
__except (EFAULT) {}
__endtry
return (-1);
} }

View File

@ -202,35 +202,38 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
return -1; return -1;
} }
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
size_t tot = 0;
while (iovcnt != 0)
{ {
if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
size_t tot = 0;
while (iovcnt != 0)
{ {
set_errno (EINVAL); if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
return -1; {
set_errno (EINVAL);
__leave;
}
volatile char *p = ((char *) iov->iov_base) + iov->iov_len - 1;
if (!iov->iov_len)
/* nothing to do */;
else if (!forwrite)
*p = dummytest (p);
else
dummytest (p);
iov++;
iovcnt--;
} }
volatile char *p = ((char *) iov->iov_base) + iov->iov_len - 1; assert (tot <= SSIZE_MAX);
if (!iov->iov_len)
/* nothing to do */;
else if (!forwrite)
*p = dummytest (p);
else
dummytest (p);
iov++; return (ssize_t) tot;
iovcnt--;
} }
__except (EFAULT)
assert (tot <= SSIZE_MAX); __endtry
return -1;
return (ssize_t) tot;
} }
/* Try hard to schedule another thread. /* Try hard to schedule another thread.
@ -512,18 +515,23 @@ slashify (const char *src, char *dst, bool trailing_slash_p)
void * __reg1 void * __reg1
__import_address (void *imp) __import_address (void *imp)
{ {
myfault efault; __try
if (efault.faulted ()) {
return NULL; if (*((uint16_t *) imp) == 0x25ff)
if (*((uint16_t *) imp) != 0x25ff) {
return NULL; const char *ptr = (const char *) imp;
const char *ptr = (const char *) imp;
#ifdef __x86_64__ #ifdef __x86_64__
const uintptr_t *jmpto = (uintptr_t *) (ptr + 6 + *(int32_t *)(ptr + 2)); const uintptr_t *jmpto = (uintptr_t *)
(ptr + 6 + *(int32_t *)(ptr + 2));
#else #else
const uintptr_t *jmpto = (uintptr_t *) *((uintptr_t *) (ptr + 2)); const uintptr_t *jmpto = (uintptr_t *) *((uintptr_t *) (ptr + 2));
#endif #endif
return (void *) *jmpto; return (void *) *jmpto;
}
}
__except (NO_ERROR) {}
__endtry
return NULL;
} }
/* CygwinCreateThread. /* CygwinCreateThread.

View File

@ -1700,50 +1700,54 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
isn't really supported except from fstab? */ isn't really supported except from fstab? */
int res = -1; int res = -1;
myfault efault; __try
if (efault.faulted (EFAULT))
/* errno set */;
else if (!*posix_path)
set_errno (EINVAL);
else if (strpbrk (posix_path, "\\:"))
set_errno (EINVAL);
else if (flags & MOUNT_CYGDRIVE) /* normal mount */
{ {
/* When flags include MOUNT_CYGDRIVE, take this to mean that if (!*posix_path)
we actually want to change the cygdrive prefix and flags set_errno (EINVAL);
without actually mounting anything. */ else if (strpbrk (posix_path, "\\:"))
res = mount_table->write_cygdrive_info (posix_path, flags); set_errno (EINVAL);
win32_path = NULL; else if (flags & MOUNT_CYGDRIVE) /* normal mount */
}
else if (!*win32_path)
set_errno (EINVAL);
else
{
char *w32_path = (char *) win32_path;
if (flags & MOUNT_BIND)
{ {
/* Prepend root path to bound path. */ /* When flags include MOUNT_CYGDRIVE, take this to mean that
tmp_pathbuf tp; we actually want to change the cygdrive prefix and flags
device dev; without actually mounting anything. */
res = mount_table->write_cygdrive_info (posix_path, flags);
unsigned conv_flags = 0; win32_path = NULL;
const char *bound_path = w32_path;
w32_path = tp.c_get ();
int error = mount_table->conv_to_win32_path (bound_path, w32_path,
dev, &conv_flags);
if (error || strlen (w32_path) >= MAX_PATH)
return true;
if ((flags & ~MOUNT_SYSTEM) == (MOUNT_BIND | MOUNT_BINARY))
flags = (MOUNT_BIND | conv_flags)
& ~(MOUNT_IMMUTABLE | MOUNT_AUTOMATIC);
} }
/* Make sure all mounts are user mounts, even those added via mount -a. */ else if (!*win32_path)
flags &= ~MOUNT_SYSTEM; set_errno (EINVAL);
res = mount_table->add_item (w32_path, posix_path, flags); else
} {
char *w32_path = (char *) win32_path;
if (flags & MOUNT_BIND)
{
/* Prepend root path to bound path. */
tmp_pathbuf tp;
device dev;
syscall_printf ("%R = mount(%s, %s, %y)", res, win32_path, posix_path, flags); unsigned conv_flags = 0;
const char *bound_path = w32_path;
w32_path = tp.c_get ();
int error = mount_table->conv_to_win32_path (bound_path, w32_path,
dev, &conv_flags);
if (error || strlen (w32_path) >= MAX_PATH)
return true;
if ((flags & ~MOUNT_SYSTEM) == (MOUNT_BIND | MOUNT_BINARY))
flags = (MOUNT_BIND | conv_flags)
& ~(MOUNT_IMMUTABLE | MOUNT_AUTOMATIC);
}
/* Make sure all mounts are user mounts, even those added via
mount -a. */
flags &= ~MOUNT_SYSTEM;
res = mount_table->add_item (w32_path, posix_path, flags);
}
syscall_printf ("%R = mount(%s, %s, %y)",
res, win32_path, posix_path, flags);
}
__except (EFAULT) {}
__endtry
return res; return res;
} }
@ -1755,15 +1759,18 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
extern "C" int extern "C" int
umount (const char *path) umount (const char *path)
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (!*path)
{ {
set_errno (EINVAL); if (!*path)
return -1; {
set_errno (EINVAL);
__leave;
}
return cygwin_umount (path, 0);
} }
return cygwin_umount (path, 0); __except (EFAULT) {}
__endtry
return -1;
} }
/* cygwin_umount: This is like umount but takes an additional flags /* cygwin_umount: This is like umount but takes an additional flags

View File

@ -1,6 +1,6 @@
/* msg.cc: XSI IPC interface for Cygwin. /* msg.cc: XSI IPC interface for Cygwin.
Copyright 2002, 2003, 2004, 2005, 2008, 2009 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2008, 2009, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -91,38 +91,40 @@ client_request_msg::client_request_msg (int msqid,
extern "C" int extern "C" int
msgctl (int msqid, int cmd, struct msqid_ds *buf) msgctl (int msqid, int cmd, struct msqid_ds *buf)
{ {
syscall_printf ("msgctl (msqid = %d, cmd = %y, buf = %p)", syscall_printf ("msgctl (msqid = %d, cmd = %y, buf = %p)", msqid, cmd, buf);
msqid, cmd, buf); __try
myfault efault;
if (efault.faulted (EFAULT))
return -1;
switch (cmd)
{ {
case IPC_STAT: switch (cmd)
break; {
case IPC_SET: case IPC_STAT:
break; break;
case IPC_RMID: case IPC_SET:
break; break;
case IPC_INFO: case IPC_RMID:
break; break;
case MSG_INFO: case IPC_INFO:
break; break;
default: case MSG_INFO:
syscall_printf ("-1 [%d] = msgctl ()", EINVAL); break;
set_errno (EINVAL); default:
return -1; syscall_printf ("-1 [%d] = msgctl ()", EINVAL);
set_errno (EINVAL);
__leave;
}
client_request_msg request (msqid, cmd, buf);
if (request.make_request () == -1 || request.retval () == -1)
{
syscall_printf ("-1 [%d] = msgctl ()", request.error_code ());
set_errno (request.error_code ());
if (request.error_code () == ENOSYS)
raise (SIGSYS);
__leave;
}
return request.retval ();
} }
client_request_msg request (msqid, cmd, buf); __except (EFAULT) {}
if (request.make_request () == -1 || request.retval () == -1) __endtry
{ return -1;
syscall_printf ("-1 [%d] = msgctl ()", request.error_code ());
set_errno (request.error_code ());
if (request.error_code () == ENOSYS)
raise (SIGSYS);
return -1;
}
return request.retval ();
} }
extern "C" int extern "C" int
@ -147,19 +149,22 @@ msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
syscall_printf ("msgrcv (msqid = %d, msgp = %p, msgsz = %ld, " syscall_printf ("msgrcv (msqid = %d, msgp = %p, msgsz = %ld, "
"msgtyp = %d, msgflg = %y)", "msgtyp = %d, msgflg = %y)",
msqid, msgp, msgsz, msgtyp, msgflg); msqid, msgp, msgsz, msgtyp, msgflg);
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
client_request_msg request (msqid, msgp, msgsz, msgtyp, msgflg);
if (request.make_request () == -1 || request.rcvval () == -1)
{ {
syscall_printf ("-1 [%d] = msgrcv ()", request.error_code ()); client_request_msg request (msqid, msgp, msgsz, msgtyp, msgflg);
set_errno (request.error_code ()); if (request.make_request () == -1 || request.rcvval () == -1)
if (request.error_code () == ENOSYS) {
raise (SIGSYS); syscall_printf ("-1 [%d] = msgrcv ()", request.error_code ());
return -1; set_errno (request.error_code ());
if (request.error_code () == ENOSYS)
raise (SIGSYS);
__leave;
}
return request.rcvval ();
} }
return request.rcvval (); __except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -167,17 +172,20 @@ msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
{ {
syscall_printf ("msgsnd (msqid = %d, msgp = %p, msgsz = %ld, msgflg = %y)", syscall_printf ("msgsnd (msqid = %d, msgp = %p, msgsz = %ld, msgflg = %y)",
msqid, msgp, msgsz, msgflg); msqid, msgp, msgsz, msgflg);
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
client_request_msg request (msqid, msgp, msgsz, msgflg);
if (request.make_request () == -1 || request.retval () == -1)
{ {
syscall_printf ("-1 [%d] = msgsnd ()", request.error_code ()); client_request_msg request (msqid, msgp, msgsz, msgflg);
set_errno (request.error_code ()); if (request.make_request () == -1 || request.retval () == -1)
if (request.error_code () == ENOSYS) {
raise (SIGSYS); syscall_printf ("-1 [%d] = msgsnd ()", request.error_code ());
return -1; set_errno (request.error_code ());
if (request.error_code () == ENOSYS)
raise (SIGSYS);
__leave;
}
return request.retval ();
} }
return request.retval (); __except (EFAULT) {}
__endtry
return -1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* ntdll.h. Contains ntdll specific stuff not defined elsewhere. /* ntdll.h. Contains ntdll specific stuff not defined elsewhere.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013 Red Hat, Inc. 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -1180,8 +1180,19 @@ typedef enum _SECTION_INHERIT
typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG); typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG);
/* Function declarations for ntdll.dll. These don't appear in any #ifdef __x86_64__
standard Win32 header. */ typedef struct _SCOPE_TABLE
{
ULONG Count;
struct
{
ULONG BeginAddress;
ULONG EndAddress;
ULONG HandlerAddress;
ULONG JumpTarget;
} ScopeRecord[1];
} SCOPE_TABLE, *PSCOPE_TABLE;
#endif
#ifdef __cplusplus #ifdef __cplusplus
/* This is the mapping of the KUSER_SHARED_DATA structure into the user /* This is the mapping of the KUSER_SHARED_DATA structure into the user
@ -1190,6 +1201,9 @@ typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG);
static volatile KUSER_SHARED_DATA &SharedUserData static volatile KUSER_SHARED_DATA &SharedUserData
= *(volatile KUSER_SHARED_DATA *) 0x7ffe0000; = *(volatile KUSER_SHARED_DATA *) 0x7ffe0000;
/* Function declarations for ntdll.dll. These don't appear in any
standard Win32 header. */
extern "C" extern "C"
{ {
#endif #endif

View File

@ -60,167 +60,171 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
EA in the file is returned twice. */ EA in the file is returned twice. */
char lastname[MAX_EA_NAME_LEN]; char lastname[MAX_EA_NAME_LEN];
myfault efault; __try
if (efault.faulted (EFAULT))
goto out;
pc.get_object_attr (attr, sec_none_nih);
debug_printf ("read_ea (%S, %s, %p, %lu)",
attr.ObjectName, name, value, size);
/* Early open if handle is NULL. This allows to return error codes like
ENOENT before we actually check for the correctness of the EA name and
stuff like that. */
if (!hdl)
{ {
status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io, pc.get_object_attr (attr, sec_none_nih);
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
goto out;
}
hdl = NULL;
}
fea = (PFILE_FULL_EA_INFORMATION) tp.w_get (); debug_printf ("read_ea (%S, %s, %p, %lu)",
attr.ObjectName, name, value, size);
if (name) /* Early open if handle is NULL. This allows to return error codes like
{ ENOENT before we actually check for the correctness of the EA name and
size_t nlen; stuff like that. */
if (!hdl)
/* For compatibility with Linux, we only allow user xattrs and
return ENOTSUP otherwise. */
if (ascii_strncasematch (name, "user.", 5))
name += 5;
else
{ {
set_errno (ENOTSUP); status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
goto out; FILE_SHARE_VALID_FLAGS,
} FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
{
set_errno (EINVAL);
return -1;
}
glen = sizeof (FILE_GET_EA_INFORMATION) + nlen;
gea = (PFILE_GET_EA_INFORMATION) alloca (glen);
gea->NextEntryOffset = 0;
gea->EaNameLength = nlen;
strcpy (gea->EaName, name);
}
while (true)
{
if (h)
{
status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, gea, glen,
NULL, TRUE);
if (status != STATUS_ACCESS_DENIED || !hdl)
break;
}
status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
break;
hdl = NULL;
}
if (!NT_SUCCESS (status))
{
switch (status)
{
case STATUS_NO_EAS_ON_FILE:
ret = 0;
break;
case STATUS_INVALID_DEVICE_REQUEST:
set_errno (ENOTSUP);
break;
case STATUS_NOT_FOUND:
/* STATUS_NOT_FOUND is returned when calling NtQueryEaFile on NFS.
In theory this should mean that the file just has no EAs, but in
fact NFS doesn't support EAs, other than the EAs which are used
for NFS requests. We're playing safe and convert STATUS_NOT_FOUND
to ENOATTR, unless we're on NFS, where we convert it to ENOTSUP. */
set_errno (pc.fs_is_nfs () ? ENOTSUP : ENOATTR);
break;
case STATUS_NONEXISTENT_EA_ENTRY:
/* Actually STATUS_NONEXISTENT_EA_ENTRY is either never generated, or
it was only generated in some old and long forgotton NT version.
See below. For safty reasons, we handle it here, nevertheless. */
set_errno (ENOATTR);
break;
default:
__seterrno_from_nt_status (status);
break;
}
goto out;
}
if (name)
{
/* Another weird behaviour of NtQueryEaFile. If you ask for a
specific EA which is not present in the file's EA list, you don't
get a useful error code like STATUS_NONEXISTENT_EA_ENTRY. Rather
NtQueryEaFile returns success with the entry's EaValueLength
set to 0. */
if (!fea->EaValueLength)
{
set_errno (ENOATTR);
goto out;
}
if (size > 0)
{
if (size < fea->EaValueLength)
{ {
set_errno (ERANGE); __seterrno_from_nt_status (status);
goto out; __leave;
} }
memcpy (value, fea->EaName + fea->EaNameLength + 1, hdl = NULL;
fea->EaValueLength);
} }
ret = fea->EaValueLength;
} fea = (PFILE_FULL_EA_INFORMATION) tp.w_get ();
else
{ if (name)
ret = 0;
do
{ {
fea->EaNameLength += 5; /* "user." */ size_t nlen;
/* For compatibility with Linux, we only allow user xattrs and
return ENOTSUP otherwise. */
if (ascii_strncasematch (name, "user.", 5))
name += 5;
else
{
set_errno (ENOTSUP);
__leave;
}
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
{
set_errno (EINVAL);
return -1;
}
glen = sizeof (FILE_GET_EA_INFORMATION) + nlen;
gea = (PFILE_GET_EA_INFORMATION) alloca (glen);
gea->NextEntryOffset = 0;
gea->EaNameLength = nlen;
strcpy (gea->EaName, name);
}
while (true)
{
if (h)
{
status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, gea, glen,
NULL, TRUE);
if (status != STATUS_ACCESS_DENIED || !hdl)
break;
}
status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
break;
hdl = NULL;
}
if (!NT_SUCCESS (status))
{
switch (status)
{
case STATUS_NO_EAS_ON_FILE:
ret = 0;
break;
case STATUS_INVALID_DEVICE_REQUEST:
set_errno (ENOTSUP);
break;
case STATUS_NOT_FOUND:
/* STATUS_NOT_FOUND is returned when calling NtQueryEaFile on NFS.
In theory this should mean that the file just has no EAs, but
in fact NFS doesn't support EAs, other than the EAs which are
used for NFS requests. We're playing safe and convert
STATUS_NOT_FOUND to ENOATTR, unless we're on NFS, where we
convert it to ENOTSUP. */
set_errno (pc.fs_is_nfs () ? ENOTSUP : ENOATTR);
break;
case STATUS_NONEXISTENT_EA_ENTRY:
/* Actually STATUS_NONEXISTENT_EA_ENTRY is either never generated,
or it was only generated in some old and long forgotton NT
version. See below. For safty reasons, we handle it here,
nevertheless. */
set_errno (ENOATTR);
break;
default:
__seterrno_from_nt_status (status);
break;
}
__leave;
}
if (name)
{
/* Another weird behaviour of NtQueryEaFile. If you ask for a
specific EA which is not present in the file's EA list, you don't
get a useful error code like STATUS_NONEXISTENT_EA_ENTRY. Rather
NtQueryEaFile returns success with the entry's EaValueLength
set to 0. */
if (!fea->EaValueLength)
{
set_errno (ENOATTR);
__leave;
}
if (size > 0) if (size > 0)
{ {
if ((size_t) ret + fea->EaNameLength + 1 > size) if (size < fea->EaValueLength)
{ {
set_errno (ERANGE); set_errno (ERANGE);
goto out; __leave;
} }
/* For compatibility with Linux, we always prepend "user." to memcpy (value, fea->EaName + fea->EaNameLength + 1,
the attribute name, so effectively we only support user fea->EaValueLength);
attributes from a application point of view. */
char tmpbuf[MAX_EA_NAME_LEN * 2];
char *tp = stpcpy (tmpbuf, "user.");
stpcpy (tp, fea->EaName);
/* NTFS stores all EA names in uppercase unfortunately. To keep
compatibility with ext/xfs EA namespaces and accompanying
tools, which expect the namespaces to be lower case, we return
EA names in lowercase if the file is on a native NTFS. */
if (pc.fs_is_ntfs ())
strlwr (tp);
tp = stpcpy (value, tmpbuf) + 1;
ret += tp - value;
value = tp;
} }
else ret = fea->EaValueLength;
ret += fea->EaNameLength + 1; }
strcpy (lastname, fea->EaName); else
status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, NULL, 0, {
NULL, FALSE); ret = 0;
do
{
fea->EaNameLength += 5; /* "user." */
if (size > 0)
{
if ((size_t) ret + fea->EaNameLength + 1 > size)
{
set_errno (ERANGE);
__leave;
}
/* For compatibility with Linux, we always prepend "user." to
the attribute name, so effectively we only support user
attributes from a application point of view. */
char tmpbuf[MAX_EA_NAME_LEN * 2];
char *tp = stpcpy (tmpbuf, "user.");
stpcpy (tp, fea->EaName);
/* NTFS stores all EA names in uppercase unfortunately. To
keep compatibility with ext/xfs EA namespaces and
accompanying tools, which expect the namespaces to be
lower case, we return EA names in lowercase if the file
is on a native NTFS. */
if (pc.fs_is_ntfs ())
strlwr (tp);
tp = stpcpy (value, tmpbuf) + 1;
ret += tp - value;
value = tp;
}
else
ret += fea->EaNameLength + 1;
strcpy (lastname, fea->EaName);
status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, NULL, 0,
NULL, FALSE);
}
while (NT_SUCCESS (status) && strcmp (lastname, fea->EaName) != 0);
} }
while (NT_SUCCESS (status) && strcmp (lastname, fea->EaName) != 0);
} }
__except (EFAULT) {}
out: __endtry
if (!hdl) if (!hdl)
CloseHandle (h); CloseHandle (h);
debug_printf ("%d = read_ea(%S, %s, %p, %lu)", debug_printf ("%d = read_ea(%S, %s, %p, %lu)",
@ -241,120 +245,121 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
ULONG flen; ULONG flen;
size_t nlen; size_t nlen;
myfault efault; __try
if (efault.faulted (EFAULT))
goto out;
pc.get_object_attr (attr, sec_none_nih);
debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
attr.ObjectName, name, value, size, flags);
/* Early open if handle is NULL. This allows to return error codes like
ENOENT before we actually check for the correctness of the EA name and
stuff like that. */
if (!hdl)
{ {
status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io, pc.get_object_attr (attr, sec_none_nih);
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
attr.ObjectName, name, value, size, flags);
/* Early open if handle is NULL. This allows to return error codes like
ENOENT before we actually check for the correctness of the EA name and
stuff like that. */
if (!hdl)
{ {
__seterrno_from_nt_status (status); status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
goto out; FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
__leave;
}
hdl = NULL;
} }
hdl = NULL;
}
/* For compatibility with Linux, we only allow user xattrs and /* For compatibility with Linux, we only allow user xattrs and
return ENOTSUP otherwise. */ return ENOTSUP otherwise. */
if (!ascii_strncasematch (name, "user.", 5)) if (!ascii_strncasematch (name, "user.", 5))
{ {
set_errno (ENOTSUP); set_errno (ENOTSUP);
goto out; __leave;
} }
/* removexattr is supposed to fail with ENOATTR if the requested EA is not /* removexattr is supposed to fail with ENOATTR if the requested EA is
available. This is equivalent to the XATTR_REPLACE flag for setxattr. */ not available. This is equivalent to XATTR_REPLACE for setxattr. */
if (!value) if (!value)
flags = XATTR_REPLACE; flags = XATTR_REPLACE;
if (flags) if (flags)
{ {
if (flags != XATTR_CREATE && flags != XATTR_REPLACE) if (flags != XATTR_CREATE && flags != XATTR_REPLACE)
{
set_errno (EINVAL);
__leave;
}
ssize_t rret = read_ea (hdl, pc, name, NULL, 0);
if (flags == XATTR_CREATE && rret > 0)
{
set_errno (EEXIST);
__leave;
}
if (flags == XATTR_REPLACE && rret < 0)
__leave;
}
/* Skip "user." prefix. */
name += 5;
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
{ {
set_errno (EINVAL); set_errno (EINVAL);
goto out; __leave;
} }
ssize_t rret = read_ea (hdl, pc, name, NULL, 0); flen = sizeof (FILE_FULL_EA_INFORMATION) + nlen + 1 + size;
if (flags == XATTR_CREATE && rret > 0) fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
fea->NextEntryOffset = 0;
fea->Flags = 0;
fea->EaNameLength = nlen;
fea->EaValueLength = size;
strcpy (fea->EaName, name);
if (value)
memcpy (fea->EaName + fea->EaNameLength + 1, value, size);
while (true)
{ {
set_errno (EEXIST); if (h)
goto out; {
} status = NtSetEaFile (h, &io, fea, flen);
if (flags == XATTR_REPLACE && rret < 0) if (status != STATUS_ACCESS_DENIED || !hdl)
goto out; break;
} }
status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
/* Skip "user." prefix. */ FILE_SHARE_VALID_FLAGS,
name += 5; FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status))
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
{
set_errno (EINVAL);
goto out;
}
flen = sizeof (FILE_FULL_EA_INFORMATION) + nlen + 1 + size;
fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
fea->NextEntryOffset = 0;
fea->Flags = 0;
fea->EaNameLength = nlen;
fea->EaValueLength = size;
strcpy (fea->EaName, name);
if (value)
memcpy (fea->EaName + fea->EaNameLength + 1, value, size);
while (true)
{
if (h)
{
status = NtSetEaFile (h, &io, fea, flen);
if (status != STATUS_ACCESS_DENIED || !hdl)
break; break;
hdl = NULL;
} }
status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
break;
hdl = NULL;
}
if (!NT_SUCCESS (status))
{
switch (status)
{ {
case STATUS_EA_TOO_LARGE: switch (status)
/* STATUS_EA_TOO_LARGE has a matching Win32 error ERROR_EA_TABLE_FULL. {
For some unknown reason RtlNtStatusToDosError does not translate case STATUS_EA_TOO_LARGE:
STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL, but instead to /* STATUS_EA_TOO_LARGE has a matching Win32 error code
ERROR_EA_LIST_INCONSISTENT. This error code is also returned for ERROR_EA_TABLE_FULL. For some reason RtlNtStatusToDosError
STATUS_EA_LIST_INCONSISTENT, which means the incoming EA list is... does not translate STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL,
inconsistent. For obvious reasons we translate but instead to ERROR_EA_LIST_INCONSISTENT. This error code is
ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to handle also returned for STATUS_EA_LIST_INCONSISTENT, which means the
STATUS_EA_TOO_LARGE explicitely here, to get the correct mapping incoming EA list is... inconsistent. For obvious reasons we
to ENOSPC. */ translate ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to
set_errno (ENOSPC); handle STATUS_EA_TOO_LARGE explicitely here, to get the correct
break; mapping to ENOSPC. */
case STATUS_INVALID_DEVICE_REQUEST: set_errno (ENOSPC);
set_errno (ENOTSUP); break;
break; case STATUS_INVALID_DEVICE_REQUEST:
default: set_errno (ENOTSUP);
__seterrno_from_nt_status (status); break;
break; default:
__seterrno_from_nt_status (status);
break;
}
} }
else
ret = 0;
} }
else __except (EFAULT) {}
ret = 0; __endtry
out:
if (!hdl) if (!hdl)
CloseHandle (h); CloseHandle (h);
debug_printf ("%d = write_ea(%S, %s, %p, %lu, %d)", debug_printf ("%d = write_ea(%S, %s, %p, %lu, %d)",

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* poll.cc. Implements poll(2) via usage of select(2) call. /* poll.cc. Implements poll(2) via usage of select(2) call.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
2012 Red Hat, Inc. 2012, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -143,16 +143,19 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts,
int timeout; int timeout;
sigset_t oldset = _my_tls.sigmask; sigset_t oldset = _my_tls.sigmask;
myfault efault; __try
if (efault.faulted (EFAULT)) {
return -1; timeout = (timeout_ts == NULL)
timeout = (timeout_ts == NULL) ? -1
? -1 : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
: (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000); if (sigmask)
if (sigmask) set_signal_mask (_my_tls.sigmask, *sigmask);
set_signal_mask (_my_tls.sigmask, *sigmask); int ret = poll (fds, nfds, timeout);
int ret = poll (fds, nfds, timeout); if (sigmask)
if (sigmask) set_signal_mask (_my_tls.sigmask, oldset);
set_signal_mask (_my_tls.sigmask, oldset); return ret;
return ret; }
__except (EFAULT) {}
__endtry
return -1;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* resource.cc: getrusage () and friends. /* resource.cc: getrusage () and friends.
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010, Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2008, 2009, 2010,
2011, 2012, 2013 Red Hat, Inc. 2011, 2012, 2013, 2014 Red Hat, Inc.
Written by Steve Chamberlain (sac@cygnus.com), Doug Evans (dje@cygnus.com), Written by Steve Chamberlain (sac@cygnus.com), Doug Evans (dje@cygnus.com),
Geoffrey Noer (noer@cygnus.com) of Cygnus Support. Geoffrey Noer (noer@cygnus.com) of Cygnus Support.
@ -116,53 +116,51 @@ getrlimit (int resource, struct rlimit *rlp)
{ {
MEMORY_BASIC_INFORMATION m; MEMORY_BASIC_INFORMATION m;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
rlp->rlim_cur = RLIM_INFINITY;
rlp->rlim_max = RLIM_INFINITY;
switch (resource)
{ {
case RLIMIT_CPU: rlp->rlim_cur = RLIM_INFINITY;
case RLIMIT_FSIZE: rlp->rlim_max = RLIM_INFINITY;
case RLIMIT_DATA:
case RLIMIT_AS: switch (resource)
break;
case RLIMIT_STACK:
if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
debug_printf ("couldn't get stack info, returning def.values. %E");
else
{ {
rlp->rlim_cur = (rlim_t) &m - (rlim_t) m.AllocationBase; case RLIMIT_CPU:
rlp->rlim_max = (rlim_t) m.BaseAddress + m.RegionSize case RLIMIT_FSIZE:
- (rlim_t) m.AllocationBase; case RLIMIT_DATA:
case RLIMIT_AS:
break;
case RLIMIT_STACK:
if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
debug_printf ("couldn't get stack info, returning def.values. %E");
else
{
rlp->rlim_cur = (rlim_t) &m - (rlim_t) m.AllocationBase;
rlp->rlim_max = (rlim_t) m.BaseAddress + m.RegionSize
- (rlim_t) m.AllocationBase;
}
break;
case RLIMIT_NOFILE:
rlp->rlim_cur = getdtablesize ();
if (rlp->rlim_cur < OPEN_MAX)
rlp->rlim_cur = OPEN_MAX;
rlp->rlim_max = OPEN_MAX_MAX;
break;
case RLIMIT_CORE:
rlp->rlim_cur = cygheap->rlim_core;
break;
default:
set_errno (EINVAL);
__leave;
} }
break; return 0;
case RLIMIT_NOFILE:
rlp->rlim_cur = getdtablesize ();
if (rlp->rlim_cur < OPEN_MAX)
rlp->rlim_cur = OPEN_MAX;
rlp->rlim_max = OPEN_MAX_MAX;
break;
case RLIMIT_CORE:
rlp->rlim_cur = cygheap->rlim_core;
break;
default:
set_errno (EINVAL);
return -1;
} }
return 0; __except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
setrlimit (int resource, const struct rlimit *rlp) setrlimit (int resource, const struct rlimit *rlp)
{ {
myfault efault;
if (efault.faulted (EFAULT))
return -1;
struct rlimit oldlimits; struct rlimit oldlimits;
/* Check if the request is to actually change the resource settings. /* Check if the request is to actually change the resource settings.
@ -170,29 +168,35 @@ setrlimit (int resource, const struct rlimit *rlp)
if (getrlimit (resource, &oldlimits) < 0) if (getrlimit (resource, &oldlimits) < 0)
return -1; return -1;
if (oldlimits.rlim_cur == rlp->rlim_cur && __try
oldlimits.rlim_max == rlp->rlim_max)
/* No change in resource requirements, succeed immediately */
return 0;
if (rlp->rlim_cur > rlp->rlim_max)
{ {
set_errno (EINVAL); if (oldlimits.rlim_cur == rlp->rlim_cur &&
return -1; oldlimits.rlim_max == rlp->rlim_max)
} /* No change in resource requirements, succeed immediately */
return 0;
switch (resource) if (rlp->rlim_cur > rlp->rlim_max)
{ {
case RLIMIT_CORE: set_errno (EINVAL);
cygheap->rlim_core = rlp->rlim_cur; __leave;
break; }
case RLIMIT_NOFILE:
if (rlp->rlim_cur != RLIM_INFINITY) switch (resource)
return setdtablesize (rlp->rlim_cur); {
break; case RLIMIT_CORE:
default: cygheap->rlim_core = rlp->rlim_cur;
set_errno (EINVAL); break;
return -1; case RLIMIT_NOFILE:
if (rlp->rlim_cur != RLIM_INFINITY)
return setdtablesize (rlp->rlim_cur);
break;
default:
set_errno (EINVAL);
__leave;
}
return 0;
} }
return 0; __except (EFAULT)
__endtry
return -1;
} }

View File

@ -1,7 +1,7 @@
/* select.cc /* select.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -230,21 +230,24 @@ pselect(int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval tv; struct timeval tv;
sigset_t oldset = _my_tls.sigmask; sigset_t oldset = _my_tls.sigmask;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (ts)
{ {
tv.tv_sec = ts->tv_sec; if (ts)
tv.tv_usec = ts->tv_nsec / 1000; {
tv.tv_sec = ts->tv_sec;
tv.tv_usec = ts->tv_nsec / 1000;
}
if (set)
set_signal_mask (_my_tls.sigmask, *set);
int ret = cygwin_select (maxfds, readfds, writefds, exceptfds,
ts ? &tv : NULL);
if (set)
set_signal_mask (_my_tls.sigmask, oldset);
return ret;
} }
if (set) __except (EFAULT) {}
set_signal_mask (_my_tls.sigmask, *set); __endtry
int ret = cygwin_select (maxfds, readfds, writefds, exceptfds, return -1;
ts ? &tv : NULL);
if (set)
set_signal_mask (_my_tls.sigmask, oldset);
return ret;
} }
/* Call cleanup functions for all inspected fds. Gets rid of any /* Call cleanup functions for all inspected fds. Gets rid of any

View File

@ -1,6 +1,6 @@
/* sem.cc: XSI IPC interface for Cygwin. /* sem.cc: XSI IPC interface for Cygwin.
Copyright 2002, 2003, 2004, 2005, 2008, 2009, 2012 Red Hat, Inc. Copyright 2002, 2003, 2004, 2005, 2008, 2009, 2012, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -85,19 +85,22 @@ semctl (int semid, int semnum, int cmd, ...)
} }
syscall_printf ("semctl (semid = %d, semnum = %d, cmd = %d, arg = %p)", syscall_printf ("semctl (semid = %d, semnum = %d, cmd = %d, arg = %p)",
semid, semnum, cmd, arg.buf); semid, semnum, cmd, arg.buf);
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
client_request_sem request (semid, semnum, cmd, &arg);
if (request.make_request () == -1 || request.retval () == -1)
{ {
syscall_printf ("-1 [%d] = semctl ()", request.error_code ()); client_request_sem request (semid, semnum, cmd, &arg);
set_errno (request.error_code ()); if (request.make_request () == -1 || request.retval () == -1)
if (request.error_code () == ENOSYS) {
raise (SIGSYS); syscall_printf ("-1 [%d] = semctl ()", request.error_code ());
return -1; set_errno (request.error_code ());
if (request.error_code () == ENOSYS)
raise (SIGSYS);
__leave;
}
return request.retval ();
} }
return request.retval (); __except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int
@ -122,17 +125,20 @@ semop (int semid, struct sembuf *sops, size_t nsops)
{ {
syscall_printf ("semop (semid = %d, sops = %p, nsops = %ld)", syscall_printf ("semop (semid = %d, sops = %p, nsops = %ld)",
semid, sops, nsops); semid, sops, nsops);
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
client_request_sem request (semid, sops, nsops);
if (request.make_request () == -1 || request.retval () == -1)
{ {
syscall_printf ("-1 [%d] = semop ()", request.error_code ()); client_request_sem request (semid, sops, nsops);
set_errno (request.error_code ()); if (request.make_request () == -1 || request.retval () == -1)
if (request.error_code () == ENOSYS) {
raise (SIGSYS); syscall_printf ("-1 [%d] = semop ()", request.error_code ());
return -1; set_errno (request.error_code ());
if (request.error_code () == ENOSYS)
raise (SIGSYS);
__leave;
}
return request.retval ();
} }
return request.retval (); __except (EFAULT) {}
__endtry
return -1;
} }

View File

@ -260,41 +260,45 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
{ {
syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = %p)", syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = %p)",
shmid, cmd, buf); shmid, cmd, buf);
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
client_request_shm request (shmid, cmd, buf);
if (request.make_request () == -1 || request.retval () == -1)
{ {
syscall_printf ("-1 [%d] = shmctl ()", request.error_code ()); client_request_shm request (shmid, cmd, buf);
set_errno (request.error_code ()); if (request.make_request () == -1 || request.retval () == -1)
if (request.error_code () == ENOSYS)
raise (SIGSYS);
return -1;
}
if (cmd == IPC_RMID)
{
/* Cleanup */
shm_shmid_list *ssh_entry, *ssh_next_entry;
SLIST_LOCK ();
SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry)
{ {
if (ssh_entry->shmid == shmid) syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
{ set_errno (request.error_code ());
/* Remove this entry from the list and close the handle if (request.error_code () == ENOSYS)
only if it's not in use anymore. */ raise (SIGSYS);
if (ssh_entry->ref_count <= 0) __leave;
{
SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next);
CloseHandle (ssh_entry->hdl);
delete ssh_entry;
}
break;
}
} }
SLIST_UNLOCK (); if (cmd == IPC_RMID)
{
/* Cleanup */
shm_shmid_list *ssh_entry, *ssh_next_entry;
SLIST_LOCK ();
SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry)
{
if (ssh_entry->shmid == shmid)
{
/* Remove this entry from the list and close the handle
only if it's not in use anymore. */
if (ssh_entry->ref_count <= 0)
{
SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list,
ssh_next);
CloseHandle (ssh_entry->hdl);
delete ssh_entry;
}
break;
}
}
SLIST_UNLOCK ();
}
return request.retval ();
} }
return request.retval (); __except (EFAULT) {}
__endtry
return -1;
} }
extern "C" int extern "C" int

View File

@ -1,7 +1,7 @@
/* signal.cc /* signal.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
Significant changes by Sergey Okhapkin <sos@prospect.com.ru> Significant changes by Sergey Okhapkin <sos@prospect.com.ru>
@ -197,33 +197,37 @@ handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& op
return EINVAL; return EINVAL;
} }
myfault efault; __try
if (efault.faulted (EFAULT))
return EFAULT;
if (oldset)
*oldset = opmask;
if (set)
{
sigset_t newmask = opmask;
switch (how)
{ {
case SIG_BLOCK: if (oldset)
/* add set to current mask */ *oldset = opmask;
newmask |= *set;
break; if (set)
case SIG_UNBLOCK: {
/* remove set from current mask */ sigset_t newmask = opmask;
newmask &= ~*set; switch (how)
break; {
case SIG_SETMASK: case SIG_BLOCK:
/* just set it */ /* add set to current mask */
newmask = *set; newmask |= *set;
break; break;
case SIG_UNBLOCK:
/* remove set from current mask */
newmask &= ~*set;
break;
case SIG_SETMASK:
/* just set it */
newmask = *set;
break;
}
set_signal_mask (opmask, newmask);
} }
set_signal_mask (opmask, newmask);
} }
__except (EFAULT)
{
return EFAULT;
}
__endtry
return 0; return 0;
} }
@ -382,8 +386,7 @@ sigaction_worker (int sig, const struct sigaction *newact,
struct sigaction *oldact, bool isinternal) struct sigaction *oldact, bool isinternal)
{ {
int res = -1; int res = -1;
myfault efault; __try
if (!efault.faulted (EFAULT))
{ {
sig_dispatch_pending (); sig_dispatch_pending ();
/* check that sig is in right range */ /* check that sig is in right range */
@ -394,14 +397,17 @@ sigaction_worker (int sig, const struct sigaction *newact,
struct sigaction oa = global_sigs[sig]; struct sigaction oa = global_sigs[sig];
if (!newact) if (!newact)
sigproc_printf ("signal %d, newact %p, oa %p", sig, newact, oa, oa.sa_handler); sigproc_printf ("signal %d, newact %p, oa %p",
sig, newact, oa, oa.sa_handler);
else else
{ {
sigproc_printf ("signal %d, newact %p (handler %p), oa %p", sig, newact, newact->sa_handler, oa, oa.sa_handler); sigproc_printf ("signal %d, newact %p (handler %p), oa %p",
sig, newact, newact->sa_handler, oa,
oa.sa_handler);
if (sig == SIGKILL || sig == SIGSTOP) if (sig == SIGKILL || sig == SIGSTOP)
{ {
set_errno (EINVAL); set_errno (EINVAL);
goto out; __leave;
} }
struct sigaction na = *newact; struct sigaction na = *newact;
struct sigaction& gs = global_sigs[sig]; struct sigaction& gs = global_sigs[sig];
@ -430,8 +436,8 @@ sigaction_worker (int sig, const struct sigaction *newact,
res = 0; res = 0;
} }
} }
__except (EFAULT) {}
out: __endtry
return res; return res;
} }
@ -560,41 +566,41 @@ sigwait (const sigset_t *set, int *sig_ptr)
extern "C" int extern "C" int
sigwaitinfo (const sigset_t *set, siginfo_t *info) sigwaitinfo (const sigset_t *set, siginfo_t *info)
{ {
int res = -1;
pthread_testcancel (); pthread_testcancel ();
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
set_signal_mask (_my_tls.sigwait_mask, *set);
sig_dispatch_pending (true);
int res;
switch (cygwait (NULL, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
{ {
case WAIT_SIGNALED: set_signal_mask (_my_tls.sigwait_mask, *set);
if (!sigismember (set, _my_tls.infodata.si_signo)) sig_dispatch_pending (true);
{
set_errno (EINTR);
res = -1;
}
else
{
_my_tls.lock ();
if (info)
*info = _my_tls.infodata;
res = _my_tls.infodata.si_signo;
_my_tls.sig = 0;
if (_my_tls.retaddr () == (__stack_t) sigdelayed)
_my_tls.pop ();
_my_tls.unlock ();
}
break;
default:
__seterrno ();
res = -1;
}
switch (cygwait (NULL, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
{
case WAIT_SIGNALED:
if (!sigismember (set, _my_tls.infodata.si_signo))
set_errno (EINTR);
else
{
_my_tls.lock ();
if (info)
*info = _my_tls.infodata;
res = _my_tls.infodata.si_signo;
_my_tls.sig = 0;
if (_my_tls.retaddr () == (__stack_t) sigdelayed)
_my_tls.pop ();
_my_tls.unlock ();
}
break;
default:
__seterrno ();
break;
}
}
__except (EFAULT) {
res = -1;
}
__endtry
sigproc_printf ("returning signal %d", res); sigproc_printf ("returning signal %d", res);
return res; return res;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* thread.cc: Locking and threading module functions /* thread.cc: Locking and threading module functions
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -122,28 +122,29 @@ __cygwin_lock_unlock (_LOCK_T *lock)
paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE->threadcount); paranoid_printf ("threadcount %d. unlocked", MT_INTERFACE->threadcount);
} }
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 7
/* FIXME: Temporarily workaround gcc 4.7+ bug. */
static verifyable_object_state
#else
static inline verifyable_object_state static inline verifyable_object_state
#endif
verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *static_ptr1, verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *static_ptr1,
void *static_ptr2, void *static_ptr3) void *static_ptr2, void *static_ptr3)
{ {
myfault efault; verifyable_object_state state = INVALID_OBJECT;
if (efault.faulted (objectptr))
return INVALID_OBJECT;
verifyable_object **object = (verifyable_object **) objectptr; __try
{
if (!objectptr || !(*(const char **) objectptr))
__leave;
if ((static_ptr1 && *object == static_ptr1) || verifyable_object **object = (verifyable_object **) objectptr;
(static_ptr2 && *object == static_ptr2) ||
(static_ptr3 && *object == static_ptr3)) if ((static_ptr1 && *object == static_ptr1) ||
return VALID_STATIC_OBJECT; (static_ptr2 && *object == static_ptr2) ||
if ((*object)->magic != magic) (static_ptr3 && *object == static_ptr3))
return INVALID_OBJECT; state = VALID_STATIC_OBJECT;
return VALID_OBJECT; else if ((*object)->magic == magic)
state = VALID_OBJECT;
}
__except (NO_ERROR) {}
__endtry
return state;
} }
/* static members */ /* static members */
@ -2684,18 +2685,20 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
return EAGAIN; return EAGAIN;
} }
myfault efault; int ret = 0;
if (efault.faulted ())
__try
{
*cond = new_cond;
}
__except (NO_ERROR)
{ {
delete new_cond; delete new_cond;
cond_initialization_lock.unlock (); ret = EINVAL;
return EINVAL;
} }
__endtry
*cond = new_cond;
cond_initialization_lock.unlock (); cond_initialization_lock.unlock ();
return ret;
return 0;
} }
extern "C" int extern "C" int
@ -2747,45 +2750,47 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec tp; struct timespec tp;
LARGE_INTEGER timeout; LARGE_INTEGER timeout;
myfault efault;
if (efault.faulted ())
return EINVAL;
pthread_testcancel (); pthread_testcancel ();
int err = __pthread_cond_wait_init (cond, mutex); __try
if (err)
return err;
/* According to SUSv3, the abstime value must be checked for validity. */
if (abstime->tv_sec < 0
|| abstime->tv_nsec < 0
|| abstime->tv_nsec > 999999999)
return EINVAL;
clock_gettime ((*cond)->clock_id, &tp);
/* Check for immediate timeout before converting */
if (tp.tv_sec > abstime->tv_sec
|| (tp.tv_sec == abstime->tv_sec
&& tp.tv_nsec > abstime->tv_nsec))
return ETIMEDOUT;
timeout.QuadPart = abstime->tv_sec * NSPERSEC
+ (abstime->tv_nsec + 99LL) / 100LL;
switch ((*cond)->clock_id)
{ {
case CLOCK_REALTIME: int err = __pthread_cond_wait_init (cond, mutex);
timeout.QuadPart += FACTOR; if (err)
break; return err;
default:
/* other clocks must be handled as relative timeout */ /* According to SUSv3, the abstime value must be checked for validity. */
timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL; if (abstime->tv_sec < 0
timeout.QuadPart *= -1LL; || abstime->tv_nsec < 0
break; || abstime->tv_nsec > 999999999)
__leave;
clock_gettime ((*cond)->clock_id, &tp);
/* Check for immediate timeout before converting */
if (tp.tv_sec > abstime->tv_sec
|| (tp.tv_sec == abstime->tv_sec
&& tp.tv_nsec > abstime->tv_nsec))
return ETIMEDOUT;
timeout.QuadPart = abstime->tv_sec * NSPERSEC
+ (abstime->tv_nsec + 99LL) / 100LL;
switch ((*cond)->clock_id)
{
case CLOCK_REALTIME:
timeout.QuadPart += FACTOR;
break;
default:
/* other clocks must be handled as relative timeout */
timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL;
timeout.QuadPart *= -1LL;
break;
}
return (*cond)->wait (*mutex, &timeout);
} }
return (*cond)->wait (*mutex, &timeout); __except (NO_ERROR) {}
__endtry
return EINVAL;
} }
extern "C" int extern "C" int
@ -2910,18 +2915,20 @@ pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr
return EAGAIN; return EAGAIN;
} }
myfault efault; int ret = 0;
if (efault.faulted ())
__try
{
*rwlock = new_rwlock;
}
__except (NO_ERROR)
{ {
delete new_rwlock; delete new_rwlock;
rwlock_initialization_lock.unlock (); ret = EINVAL;
return EINVAL;
} }
__endtry
*rwlock = new_rwlock;
rwlock_initialization_lock.unlock (); rwlock_initialization_lock.unlock ();
return ret;
return 0;
} }
extern "C" int extern "C" int
@ -3133,15 +3140,17 @@ pthread_mutex::init (pthread_mutex_t *mutex,
new_mutex->type = PTHREAD_MUTEX_ERRORCHECK; new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
} }
myfault efault; __try
if (efault.faulted ()) {
*mutex = new_mutex;
}
__except (NO_ERROR)
{ {
delete new_mutex; delete new_mutex;
mutex_initialization_lock.unlock (); mutex_initialization_lock.unlock ();
return EINVAL; return EINVAL;
} }
__endtry
*mutex = new_mutex;
} }
mutex_initialization_lock.unlock (); mutex_initialization_lock.unlock ();
pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer); pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer);
@ -3230,16 +3239,17 @@ pthread_spinlock::init (pthread_spinlock_t *spinlock, int pshared)
return EAGAIN; return EAGAIN;
} }
myfault efault; __try
if (efault.faulted ()) {
*spinlock = new_spinlock;
}
__except (NO_ERROR)
{ {
delete new_spinlock; delete new_spinlock;
return EINVAL; return EINVAL;
} }
__endtry
*spinlock = new_spinlock;
pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared); pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared);
return 0; return 0;
} }
@ -3502,35 +3512,38 @@ semaphore::_timedwait (const struct timespec *abstime)
{ {
LARGE_INTEGER timeout; LARGE_INTEGER timeout;
myfault efault; __try
if (efault.faulted ()) {
timeout.QuadPart = abstime->tv_sec * NSPERSEC
+ (abstime->tv_nsec + 99) / 100 + FACTOR;
switch (cygwait (win32_obj_id, &timeout, cw_cancel | cw_cancel_self | cw_sig_eintr))
{
case WAIT_OBJECT_0:
break;
case WAIT_SIGNALED:
set_errno (EINTR);
return -1;
case WAIT_TIMEOUT:
set_errno (ETIMEDOUT);
return -1;
default:
pthread_printf ("cygwait failed. %E");
__seterrno ();
return -1;
}
}
__except (NO_ERROR)
{ {
/* According to SUSv3, abstime need not be checked for validity, /* According to SUSv3, abstime need not be checked for validity,
if the semaphore can be locked immediately. */ if the semaphore can be locked immediately. */
if (!_trywait ()) if (_trywait ())
return 0; {
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
timeout.QuadPart = abstime->tv_sec * NSPERSEC
+ (abstime->tv_nsec + 99) / 100 + FACTOR;
switch (cygwait (win32_obj_id, &timeout, cw_cancel | cw_cancel_self | cw_sig_eintr))
{
case WAIT_OBJECT_0:
break;
case WAIT_SIGNALED:
set_errno (EINTR);
return -1;
case WAIT_TIMEOUT:
set_errno (ETIMEDOUT);
return -1;
default:
pthread_printf ("cygwait failed. %E");
__seterrno ();
return -1;
} }
__endtry
return 0; return 0;
} }
@ -3761,36 +3774,38 @@ semaphore::post (sem_t *sem)
int int
semaphore::getvalue (sem_t *sem, int *sval) semaphore::getvalue (sem_t *sem, int *sval)
{ {
myfault efault; __try
if (efault.faulted () || !is_good_object (sem))
{ {
set_errno (EINVAL); if (is_good_object (sem))
return -1; return (*sem)->_getvalue (sval);
} }
__except (NO_ERROR) {}
return (*sem)->_getvalue (sval); __endtry
set_errno (EINVAL);
return -1;
} }
int int
semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash, semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
LUID *sluid, unsigned int *sval) LUID *sluid, unsigned int *sval)
{ {
myfault efault; __try
if (efault.faulted () || !is_good_object (sem))
{ {
set_errno (EINVAL); if (!is_good_object (sem))
return -1; __leave;
if ((*sfd = (*sem)->fd) < 0)
__leave;
*shash = (*sem)->hash;
*sluid = (*sem)->luid;
/* POSIX defines the value in calls to sem_init/sem_open as unsigned,
but the sem_getvalue gets a pointer to int to return the value.
Go figure! */
return (*sem)->_getvalue ((int *)sval);
} }
if ((*sfd = (*sem)->fd) < 0) __except (NO_ERROR) {}
{ __endtry
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
}
*shash = (*sem)->hash;
*sluid = (*sem)->luid;
/* POSIX defines the value in calls to sem_init/sem_open as unsigned, but
the sem_getvalue gets a pointer to int to return the value. Go figure! */
return (*sem)->_getvalue ((int *)sval);
} }
/* pthread_null */ /* pthread_null */

View File

@ -1,6 +1,6 @@
/* timer.cc /* timer.cc
Copyright 2004, 2005, 2006, 2008, 2010, 2011, 2012, 2013 Red Hat, Inc. Copyright 2004, 2005, 2006, 2008, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -219,45 +219,49 @@ it_bad (const timespec& t)
int int
timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue) timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue)
{ {
if (!value) int ret = -1;
__try
{ {
set_errno (EINVAL); if (!value)
return -1; {
} set_errno (EINVAL);
__leave;
}
myfault efault; if (it_bad (value->it_value) || it_bad (value->it_interval))
if (efault.faulted (EFAULT) __leave;
|| it_bad (value->it_value)
|| it_bad (value->it_interval))
return -1;
long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs (); long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs ();
lock_timer_tracker here; lock_timer_tracker here;
cancel (); cancel ();
if (ovalue) if (ovalue)
gettime (ovalue); gettime (ovalue);
if (!value->it_value.tv_sec && !value->it_value.tv_nsec) if (!value->it_value.tv_sec && !value->it_value.tv_nsec)
interval_us = sleepto_us = 0; interval_us = sleepto_us = 0;
else
{
sleepto_us = now + to_us (value->it_value);
interval_us = to_us (value->it_interval);
it_interval = value->it_interval;
if (!hcancel)
hcancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
else else
ResetEvent (hcancel); {
if (!syncthread) sleepto_us = now + to_us (value->it_value);
syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL); interval_us = to_us (value->it_interval);
else it_interval = value->it_interval;
ResetEvent (syncthread); if (!hcancel)
new cygthread (timer_thread, this, "itimer", syncthread); hcancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
else
ResetEvent (hcancel);
if (!syncthread)
syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
else
ResetEvent (syncthread);
new cygthread (timer_thread, this, "itimer", syncthread);
}
ret = 0;
} }
__except (EFAULT) {}
return 0; __endtry
return ret;
} }
void void
@ -280,43 +284,51 @@ timer_tracker::gettime (itimerspec *ovalue)
extern "C" int extern "C" int
timer_gettime (timer_t timerid, struct itimerspec *ovalue) timer_gettime (timer_t timerid, struct itimerspec *ovalue)
{ {
myfault efault; int ret = -1;
if (efault.faulted (EFAULT))
return -1;
timer_tracker *tt = (timer_tracker *) timerid; __try
if (tt->magic != TT_MAGIC)
{ {
set_errno (EINVAL); timer_tracker *tt = (timer_tracker *) timerid;
return -1; if (tt->magic != TT_MAGIC)
} {
set_errno (EINVAL);
return -1;
}
tt->gettime (ovalue); tt->gettime (ovalue);
return 0; ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" int extern "C" int
timer_create (clockid_t clock_id, struct sigevent *__restrict evp, timer_create (clockid_t clock_id, struct sigevent *__restrict evp,
timer_t *__restrict timerid) timer_t *__restrict timerid)
{ {
myfault efault; int ret = -1;
if (efault.faulted (EFAULT))
return -1;
if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id)) __try
{ {
set_errno (ENOTSUP); if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id))
return -1; {
} set_errno (ENOTSUP);
return -1;
}
if (clock_id != CLOCK_REALTIME) if (clock_id != CLOCK_REALTIME)
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
*timerid = (timer_t) new timer_tracker (clock_id, evp); *timerid = (timer_t) new timer_tracker (clock_id, evp);
return 0; ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" int extern "C" int
@ -324,42 +336,52 @@ timer_settime (timer_t timerid, int flags,
const struct itimerspec *__restrict value, const struct itimerspec *__restrict value,
struct itimerspec *__restrict ovalue) struct itimerspec *__restrict ovalue)
{ {
timer_tracker *tt = (timer_tracker *) timerid; int ret = -1;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (tt->magic != TT_MAGIC)
{
set_errno (EINVAL);
return -1;
}
return tt->settime (flags, value, ovalue); __try
{
timer_tracker *tt = (timer_tracker *) timerid;
if (tt->magic != TT_MAGIC)
{
set_errno (EINVAL);
__leave;
}
ret = tt->settime (flags, value, ovalue);
}
__except (EFAULT) {}
__endtry
return ret;
} }
extern "C" int extern "C" int
timer_delete (timer_t timerid) timer_delete (timer_t timerid)
{ {
timer_tracker *in_tt = (timer_tracker *) timerid; int ret = -1;
myfault efault;
if (efault.faulted (EFAULT))
return -1;
if (in_tt->magic != TT_MAGIC)
{
set_errno (EINVAL);
return -1;
}
lock_timer_tracker here; __try
for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next) {
if (tt->next == in_tt) timer_tracker *in_tt = (timer_tracker *) timerid;
{ if (in_tt->magic != TT_MAGIC)
tt->next = in_tt->next; {
delete in_tt; set_errno (EINVAL);
return 0; __leave;
} }
set_errno (EINVAL);
return 0; lock_timer_tracker here;
for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next)
if (tt->next == in_tt)
{
tt->next = in_tt->next;
delete in_tt;
ret = 0;
__leave;
}
set_errno (EINVAL);
ret = 0;
}
__except (EFAULT) {}
__endtry
return ret;
} }
void void
@ -412,18 +434,13 @@ setitimer (int which, const struct itimerval *__restrict value,
extern "C" int extern "C" int
getitimer (int which, struct itimerval *ovalue) getitimer (int which, struct itimerval *ovalue)
{ {
int ret; int ret = -1;
if (which != ITIMER_REAL) if (which != ITIMER_REAL)
{ set_errno (EINVAL);
set_errno (EINVAL);
ret = -1;
}
else else
{ {
myfault efault; __try
if (efault.faulted (EFAULT))
ret = -1;
else
{ {
struct itimerspec spec_ovalue; struct itimerspec spec_ovalue;
ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue); ret = timer_gettime ((timer_t) &ttstart, &spec_ovalue);
@ -435,6 +452,8 @@ getitimer (int which, struct itimerval *ovalue)
ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000; ovalue->it_value.tv_usec = spec_ovalue.it_value.tv_nsec / 1000;
} }
} }
__except (EFAULT) {}
__endtry
} }
syscall_printf ("%R = getitimer()", ret); syscall_printf ("%R = getitimer()", ret);
return ret; return ret;

View File

@ -1,7 +1,7 @@
/* times.cc /* times.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -59,35 +59,39 @@ __to_clock_t (PLARGE_INTEGER src, int flag)
extern "C" clock_t extern "C" clock_t
times (struct tms *buf) times (struct tms *buf)
{ {
myfault efault;
if (efault.faulted (EFAULT))
return ((clock_t) -1);
static SYSTEM_TIMEOFDAY_INFORMATION stodi; static SYSTEM_TIMEOFDAY_INFORMATION stodi;
KERNEL_USER_TIMES kut; KERNEL_USER_TIMES kut;
LARGE_INTEGER ticks; LARGE_INTEGER ticks;
clock_t tc = (clock_t) -1;
/* Fetch boot time if we haven't already. */ __try
if (!stodi.BootTime.QuadPart) {
NtQuerySystemInformation (SystemTimeOfDayInformation, /* Fetch boot time if we haven't already. */
&stodi, sizeof stodi, NULL); if (!stodi.BootTime.QuadPart)
NtQuerySystemInformation (SystemTimeOfDayInformation,
&stodi, sizeof stodi, NULL);
NtQueryInformationProcess (NtCurrentProcess (), ProcessTimes, NtQueryInformationProcess (NtCurrentProcess (), ProcessTimes,
&kut, sizeof kut, NULL); &kut, sizeof kut, NULL);
get_system_time (&ticks); get_system_time (&ticks);
/* uptime */ /* uptime */
ticks.QuadPart -= stodi.BootTime.QuadPart; ticks.QuadPart -= stodi.BootTime.QuadPart;
/* ticks is in in 100ns, convert to clock ticks. */ /* ticks is in in 100ns, convert to clock ticks. */
clock_t tc = (clock_t) (ticks.QuadPart * CLOCKS_PER_SEC / NSPERSEC); tc = (clock_t) (ticks.QuadPart * CLOCKS_PER_SEC / NSPERSEC);
buf->tms_stime = __to_clock_t (&kut.KernelTime, 0);
buf->tms_utime = __to_clock_t (&kut.UserTime, 0);
timeval_to_filetime (&myself->rusage_children.ru_stime, &kut.KernelTime);
buf->tms_cstime = __to_clock_t (&kut.KernelTime, 1);
timeval_to_filetime (&myself->rusage_children.ru_utime, &kut.UserTime);
buf->tms_cutime = __to_clock_t (&kut.UserTime, 1);
buf->tms_stime = __to_clock_t (&kut.KernelTime, 0);
buf->tms_utime = __to_clock_t (&kut.UserTime, 0);
timeval_to_filetime (&myself->rusage_children.ru_stime, &kut.KernelTime);
buf->tms_cstime = __to_clock_t (&kut.KernelTime, 1);
timeval_to_filetime (&myself->rusage_children.ru_utime, &kut.UserTime);
buf->tms_cutime = __to_clock_t (&kut.UserTime, 1);
}
__except (EFAULT)
{
tc = (clock_t) -1;
}
__endtry
syscall_printf ("%D = times(%p)", tc, buf); syscall_printf ("%D = times(%p)", tc, buf);
return tc; return tc;
} }
@ -100,34 +104,37 @@ settimeofday (const struct timeval *tv, const struct timezone *tz)
{ {
SYSTEMTIME st; SYSTEMTIME st;
struct tm *ptm; struct tm *ptm;
int res; int res = -1;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
{ {
set_errno (EINVAL); if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
return -1; {
set_errno (EINVAL);
return -1;
}
ptm = gmtime (&tv->tv_sec);
st.wYear = ptm->tm_year + 1900;
st.wMonth = ptm->tm_mon + 1;
st.wDayOfWeek = ptm->tm_wday;
st.wDay = ptm->tm_mday;
st.wHour = ptm->tm_hour;
st.wMinute = ptm->tm_min;
st.wSecond = ptm->tm_sec;
st.wMilliseconds = tv->tv_usec / 1000;
res = -!SetSystemTime (&st);
gtod.reset ();
if (res)
set_errno (EPERM);
} }
__except (EFAULT)
ptm = gmtime (&tv->tv_sec); {
st.wYear = ptm->tm_year + 1900; res = -1;
st.wMonth = ptm->tm_mon + 1; }
st.wDayOfWeek = ptm->tm_wday; __endtry
st.wDay = ptm->tm_mday;
st.wHour = ptm->tm_hour;
st.wMinute = ptm->tm_min;
st.wSecond = ptm->tm_sec;
st.wMilliseconds = tv->tv_usec / 1000;
res = -!SetSystemTime (&st);
gtod.reset ();
if (res)
set_errno (EPERM);
syscall_printf ("%R = settimeofday(%p, %p)", res, tv, tz); syscall_printf ("%R = settimeofday(%p, %p)", res, tv, tz);
return res; return res;
} }

View File

@ -8,17 +8,16 @@ details. */
#include <winsup.h> #include <winsup.h>
#include <malloc.h> #include <malloc.h>
#include "cygtls.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#define tls_pbuf _my_tls.locals.pathbufs #define tls_pbuf _my_tls.pathbufs
void void
tls_pathbuf::destroy () tls_pathbuf::destroy ()
{ {
for (unsigned i = 0; i < TP_NUM_C_BUFS && c_buf[i]; ++i) for (uint32_t i = 0; i < TP_NUM_C_BUFS && c_buf[i]; ++i)
free (c_buf[i]); free (c_buf[i]);
for (unsigned i = 0; i < TP_NUM_W_BUFS && w_buf[i]; ++i) for (uint32_t i = 0; i < TP_NUM_W_BUFS && w_buf[i]; ++i)
free (w_buf[i]); free (w_buf[i]);
} }

View File

@ -10,20 +10,20 @@ details. */
class tmp_pathbuf class tmp_pathbuf
{ {
unsigned c_buf_old; uint32_t c_buf_old;
unsigned w_buf_old; uint32_t w_buf_old;
public: public:
tmp_pathbuf () __attribute__ ((always_inline)) tmp_pathbuf () __attribute__ ((always_inline))
: c_buf_old (_my_tls.locals.pathbufs.c_cnt), : c_buf_old (_my_tls.pathbufs.c_cnt),
w_buf_old (_my_tls.locals.pathbufs.w_cnt) w_buf_old (_my_tls.pathbufs.w_cnt)
{} {}
~tmp_pathbuf () __attribute__ ((always_inline)) ~tmp_pathbuf () __attribute__ ((always_inline))
{ {
_my_tls.locals.pathbufs.c_cnt = c_buf_old; _my_tls.pathbufs.c_cnt = c_buf_old;
_my_tls.locals.pathbufs.w_cnt = w_buf_old; _my_tls.pathbufs.w_cnt = w_buf_old;
} }
inline bool check_usage (unsigned c_need, unsigned w_need) inline bool check_usage (uint32_t c_need, uint32_t w_need)
{ {
return c_need + c_buf_old < TP_NUM_C_BUFS return c_need + c_buf_old < TP_NUM_C_BUFS
&& w_need + w_buf_old < TP_NUM_W_BUFS; && w_need + w_buf_old < TP_NUM_W_BUFS;

View File

@ -3,44 +3,46 @@
//; $tls::start_offset = -12700; //; $tls::start_offset = -12700;
//; $tls::locals = -12700; //; $tls::locals = -12700;
//; $tls::plocals = 0; //; $tls::plocals = 0;
//; $tls::local_clib = -10980; //; $tls::local_clib = -11388;
//; $tls::plocal_clib = 1720; //; $tls::plocal_clib = 1312;
//; $tls::__dontuse = -10980; //; $tls::__dontuse = -11388;
//; $tls::p__dontuse = 1720; //; $tls::p__dontuse = 1312;
//; $tls::func = -9892; //; $tls::func = -10300;
//; $tls::pfunc = 2808; //; $tls::pfunc = 2400;
//; $tls::saved_errno = -9888; //; $tls::saved_errno = -10296;
//; $tls::psaved_errno = 2812; //; $tls::psaved_errno = 2404;
//; $tls::sa_flags = -9884; //; $tls::sa_flags = -10292;
//; $tls::psa_flags = 2816; //; $tls::psa_flags = 2408;
//; $tls::oldmask = -9880; //; $tls::oldmask = -10288;
//; $tls::poldmask = 2820; //; $tls::poldmask = 2412;
//; $tls::deltamask = -9876; //; $tls::deltamask = -10284;
//; $tls::pdeltamask = 2824; //; $tls::pdeltamask = 2416;
//; $tls::errno_addr = -9872; //; $tls::errno_addr = -10280;
//; $tls::perrno_addr = 2828; //; $tls::perrno_addr = 2420;
//; $tls::sigmask = -9868; //; $tls::sigmask = -10276;
//; $tls::psigmask = 2832; //; $tls::psigmask = 2424;
//; $tls::sigwait_mask = -9864; //; $tls::sigwait_mask = -10272;
//; $tls::psigwait_mask = 2836; //; $tls::psigwait_mask = 2428;
//; $tls::sigwait_info = -9860; //; $tls::sigwait_info = -10268;
//; $tls::psigwait_info = 2840; //; $tls::psigwait_info = 2432;
//; $tls::signal_arrived = -9856; //; $tls::signal_arrived = -10264;
//; $tls::psignal_arrived = 2844; //; $tls::psignal_arrived = 2436;
//; $tls::will_wait_for_signal = -9852; //; $tls::will_wait_for_signal = -10260;
//; $tls::pwill_wait_for_signal = 2848; //; $tls::pwill_wait_for_signal = 2440;
//; $tls::thread_context = -9848; //; $tls::thread_context = -10256;
//; $tls::pthread_context = 2852; //; $tls::pthread_context = 2444;
//; $tls::thread_id = -9636; //; $tls::thread_id = -10044;
//; $tls::pthread_id = 3064; //; $tls::pthread_id = 2656;
//; $tls::infodata = -9632; //; $tls::infodata = -10040;
//; $tls::pinfodata = 3068; //; $tls::pinfodata = 2660;
//; $tls::tid = -9484; //; $tls::tid = -9892;
//; $tls::ptid = 3216; //; $tls::ptid = 2808;
//; $tls::_ctinfo = -9480; //; $tls::_ctinfo = -9888;
//; $tls::p_ctinfo = 3220; //; $tls::p_ctinfo = 2812;
//; $tls::andreas = -9476; //; $tls::andreas = -9884;
//; $tls::pandreas = 3224; //; $tls::pandreas = 2816;
//; $tls::pathbufs = -9880;
//; $tls::ppathbufs = 2820;
//; $tls::wq = -9472; //; $tls::wq = -9472;
//; $tls::pwq = 3228; //; $tls::pwq = 3228;
//; $tls::sig = -9444; //; $tls::sig = -9444;
@ -61,44 +63,46 @@
#define tls_locals (-12700) #define tls_locals (-12700)
#define tls_plocals (0) #define tls_plocals (0)
#define tls_local_clib (-10980) #define tls_local_clib (-11388)
#define tls_plocal_clib (1720) #define tls_plocal_clib (1312)
#define tls___dontuse (-10980) #define tls___dontuse (-11388)
#define tls_p__dontuse (1720) #define tls_p__dontuse (1312)
#define tls_func (-9892) #define tls_func (-10300)
#define tls_pfunc (2808) #define tls_pfunc (2400)
#define tls_saved_errno (-9888) #define tls_saved_errno (-10296)
#define tls_psaved_errno (2812) #define tls_psaved_errno (2404)
#define tls_sa_flags (-9884) #define tls_sa_flags (-10292)
#define tls_psa_flags (2816) #define tls_psa_flags (2408)
#define tls_oldmask (-9880) #define tls_oldmask (-10288)
#define tls_poldmask (2820) #define tls_poldmask (2412)
#define tls_deltamask (-9876) #define tls_deltamask (-10284)
#define tls_pdeltamask (2824) #define tls_pdeltamask (2416)
#define tls_errno_addr (-9872) #define tls_errno_addr (-10280)
#define tls_perrno_addr (2828) #define tls_perrno_addr (2420)
#define tls_sigmask (-9868) #define tls_sigmask (-10276)
#define tls_psigmask (2832) #define tls_psigmask (2424)
#define tls_sigwait_mask (-9864) #define tls_sigwait_mask (-10272)
#define tls_psigwait_mask (2836) #define tls_psigwait_mask (2428)
#define tls_sigwait_info (-9860) #define tls_sigwait_info (-10268)
#define tls_psigwait_info (2840) #define tls_psigwait_info (2432)
#define tls_signal_arrived (-9856) #define tls_signal_arrived (-10264)
#define tls_psignal_arrived (2844) #define tls_psignal_arrived (2436)
#define tls_will_wait_for_signal (-9852) #define tls_will_wait_for_signal (-10260)
#define tls_pwill_wait_for_signal (2848) #define tls_pwill_wait_for_signal (2440)
#define tls_thread_context (-9848) #define tls_thread_context (-10256)
#define tls_pthread_context (2852) #define tls_pthread_context (2444)
#define tls_thread_id (-9636) #define tls_thread_id (-10044)
#define tls_pthread_id (3064) #define tls_pthread_id (2656)
#define tls_infodata (-9632) #define tls_infodata (-10040)
#define tls_pinfodata (3068) #define tls_pinfodata (2660)
#define tls_tid (-9484) #define tls_tid (-9892)
#define tls_ptid (3216) #define tls_ptid (2808)
#define tls__ctinfo (-9480) #define tls__ctinfo (-9888)
#define tls_p_ctinfo (3220) #define tls_p_ctinfo (2812)
#define tls_andreas (-9476) #define tls_andreas (-9884)
#define tls_pandreas (3224) #define tls_pandreas (2816)
#define tls_pathbufs (-9880)
#define tls_ppathbufs (2820)
#define tls_wq (-9472) #define tls_wq (-9472)
#define tls_pwq (3228) #define tls_pwq (3228)
#define tls_sig (-9444) #define tls_sig (-9444)

View File

@ -3,44 +3,46 @@
//; $tls::start_offset = -12800; //; $tls::start_offset = -12800;
//; $tls::locals = -12800; //; $tls::locals = -12800;
//; $tls::plocals = 0; //; $tls::plocals = 0;
//; $tls::local_clib = -10624; //; $tls::local_clib = -11432;
//; $tls::plocal_clib = 2176; //; $tls::plocal_clib = 1368;
//; $tls::__dontuse = -10624; //; $tls::__dontuse = -11432;
//; $tls::p__dontuse = 2176; //; $tls::p__dontuse = 1368;
//; $tls::func = -8736; //; $tls::func = -9544;
//; $tls::pfunc = 4064; //; $tls::pfunc = 3256;
//; $tls::saved_errno = -8728; //; $tls::saved_errno = -9536;
//; $tls::psaved_errno = 4072; //; $tls::psaved_errno = 3264;
//; $tls::sa_flags = -8724; //; $tls::sa_flags = -9532;
//; $tls::psa_flags = 4076; //; $tls::psa_flags = 3268;
//; $tls::oldmask = -8720; //; $tls::oldmask = -9528;
//; $tls::poldmask = 4080; //; $tls::poldmask = 3272;
//; $tls::deltamask = -8712; //; $tls::deltamask = -9520;
//; $tls::pdeltamask = 4088; //; $tls::pdeltamask = 3280;
//; $tls::errno_addr = -8704; //; $tls::errno_addr = -9512;
//; $tls::perrno_addr = 4096; //; $tls::perrno_addr = 3288;
//; $tls::sigmask = -8696; //; $tls::sigmask = -9504;
//; $tls::psigmask = 4104; //; $tls::psigmask = 3296;
//; $tls::sigwait_mask = -8688; //; $tls::sigwait_mask = -9496;
//; $tls::psigwait_mask = 4112; //; $tls::psigwait_mask = 3304;
//; $tls::sigwait_info = -8680; //; $tls::sigwait_info = -9488;
//; $tls::psigwait_info = 4120; //; $tls::psigwait_info = 3312;
//; $tls::signal_arrived = -8672; //; $tls::signal_arrived = -9480;
//; $tls::psignal_arrived = 4128; //; $tls::psignal_arrived = 3320;
//; $tls::will_wait_for_signal = -8664; //; $tls::will_wait_for_signal = -9472;
//; $tls::pwill_wait_for_signal = 4136; //; $tls::pwill_wait_for_signal = 3328;
//; $tls::thread_context = -8656; //; $tls::thread_context = -9464;
//; $tls::pthread_context = 4144; //; $tls::pthread_context = 3336;
//; $tls::thread_id = -7824; //; $tls::thread_id = -8632;
//; $tls::pthread_id = 4976; //; $tls::pthread_id = 4168;
//; $tls::infodata = -7820; //; $tls::infodata = -8628;
//; $tls::pinfodata = 4980; //; $tls::pinfodata = 4172;
//; $tls::tid = -7672; //; $tls::tid = -8480;
//; $tls::ptid = 5128; //; $tls::ptid = 4320;
//; $tls::_ctinfo = -7664; //; $tls::_ctinfo = -8472;
//; $tls::p_ctinfo = 5136; //; $tls::p_ctinfo = 4328;
//; $tls::andreas = -7656; //; $tls::andreas = -8464;
//; $tls::pandreas = 5144; //; $tls::pandreas = 4336;
//; $tls::pathbufs = -8456;
//; $tls::ppathbufs = 4344;
//; $tls::wq = -7648; //; $tls::wq = -7648;
//; $tls::pwq = 5152; //; $tls::pwq = 5152;
//; $tls::sig = -7600; //; $tls::sig = -7600;
@ -61,44 +63,46 @@
#define tls_locals (-12800) #define tls_locals (-12800)
#define tls_plocals (0) #define tls_plocals (0)
#define tls_local_clib (-10624) #define tls_local_clib (-11432)
#define tls_plocal_clib (2176) #define tls_plocal_clib (1368)
#define tls___dontuse (-10624) #define tls___dontuse (-11432)
#define tls_p__dontuse (2176) #define tls_p__dontuse (1368)
#define tls_func (-8736) #define tls_func (-9544)
#define tls_pfunc (4064) #define tls_pfunc (3256)
#define tls_saved_errno (-8728) #define tls_saved_errno (-9536)
#define tls_psaved_errno (4072) #define tls_psaved_errno (3264)
#define tls_sa_flags (-8724) #define tls_sa_flags (-9532)
#define tls_psa_flags (4076) #define tls_psa_flags (3268)
#define tls_oldmask (-8720) #define tls_oldmask (-9528)
#define tls_poldmask (4080) #define tls_poldmask (3272)
#define tls_deltamask (-8712) #define tls_deltamask (-9520)
#define tls_pdeltamask (4088) #define tls_pdeltamask (3280)
#define tls_errno_addr (-8704) #define tls_errno_addr (-9512)
#define tls_perrno_addr (4096) #define tls_perrno_addr (3288)
#define tls_sigmask (-8696) #define tls_sigmask (-9504)
#define tls_psigmask (4104) #define tls_psigmask (3296)
#define tls_sigwait_mask (-8688) #define tls_sigwait_mask (-9496)
#define tls_psigwait_mask (4112) #define tls_psigwait_mask (3304)
#define tls_sigwait_info (-8680) #define tls_sigwait_info (-9488)
#define tls_psigwait_info (4120) #define tls_psigwait_info (3312)
#define tls_signal_arrived (-8672) #define tls_signal_arrived (-9480)
#define tls_psignal_arrived (4128) #define tls_psignal_arrived (3320)
#define tls_will_wait_for_signal (-8664) #define tls_will_wait_for_signal (-9472)
#define tls_pwill_wait_for_signal (4136) #define tls_pwill_wait_for_signal (3328)
#define tls_thread_context (-8656) #define tls_thread_context (-9464)
#define tls_pthread_context (4144) #define tls_pthread_context (3336)
#define tls_thread_id (-7824) #define tls_thread_id (-8632)
#define tls_pthread_id (4976) #define tls_pthread_id (4168)
#define tls_infodata (-7820) #define tls_infodata (-8628)
#define tls_pinfodata (4980) #define tls_pinfodata (4172)
#define tls_tid (-7672) #define tls_tid (-8480)
#define tls_ptid (5128) #define tls_ptid (4320)
#define tls__ctinfo (-7664) #define tls__ctinfo (-8472)
#define tls_p_ctinfo (5136) #define tls_p_ctinfo (4328)
#define tls_andreas (-7656) #define tls_andreas (-8464)
#define tls_pandreas (5144) #define tls_pandreas (4336)
#define tls_pathbufs (-8456)
#define tls_ppathbufs (4344)
#define tls_wq (-7648) #define tls_wq (-7648)
#define tls_pwq (5152) #define tls_pwq (5152)
#define tls_sig (-7600) #define tls_sig (-7600)

View File

@ -217,10 +217,15 @@ getlogin_r (char *name, size_t namesize)
size_t len = strlen (login) + 1; size_t len = strlen (login) + 1;
if (len > namesize) if (len > namesize)
return ERANGE; return ERANGE;
myfault efault; __try
if (efault.faulted ()) {
return EFAULT; strncpy (name, login, len);
strncpy (name, login, len); }
__except (NO_ERROR)
{
return EFAULT;
}
__endtry
return 0; return 0;
} }

View File

@ -1,7 +1,7 @@
/* uname.cc /* uname.cc
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2013 Red Hat, Inc. 2006, 2007, 2008, 2013, 2014 Red Hat, Inc.
Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
Rewritten by Geoffrey Noer of Cygnus Solutions, noer@cygnus.com Rewritten by Geoffrey Noer of Cygnus Solutions, noer@cygnus.com
@ -22,74 +22,77 @@ uname (struct utsname *name)
{ {
SYSTEM_INFO sysinfo; SYSTEM_INFO sysinfo;
myfault efault; __try
if (efault.faulted (EFAULT))
return -1;
char *snp = strstr (cygwin_version.dll_build_date, "SNP");
memset (name, 0, sizeof (*name));
__small_sprintf (name->sysname, "CYGWIN_%s", wincap.osname ());
/* Add a hint to the sysname, that we're running under WOW64. This might
give an early clue if somebody encounters problems. */
if (wincap.is_wow64 ())
strncat (name->sysname, "-WOW64",
sizeof name->sysname - strlen (name->sysname) - 1);
GetSystemInfo (&sysinfo);
/* Computer name */
cygwin_gethostname (name->nodename, sizeof (name->nodename) - 1);
/* Cygwin dll release */
__small_sprintf (name->release, "%d.%d.%d%s(%d.%d/%d/%d)",
cygwin_version.dll_major / 1000,
cygwin_version.dll_major % 1000,
cygwin_version.dll_minor,
snp ? "s" : "",
cygwin_version.api_major,
cygwin_version.api_minor,
cygwin_version.shared_data,
cygwin_version.mount_registry);
/* Cygwin "version" aka build date */
strcpy (name->version, cygwin_version.dll_build_date);
if (snp)
name->version[snp - cygwin_version.dll_build_date] = '\0';
/* CPU type */
switch (sysinfo.wProcessorArchitecture)
{ {
case PROCESSOR_ARCHITECTURE_INTEL: char *snp = strstr (cygwin_version.dll_build_date, "SNP");
unsigned int ptype;
if (sysinfo.wProcessorLevel < 3) /* Shouldn't happen. */
ptype = 3;
else if (sysinfo.wProcessorLevel > 9) /* P4 */
ptype = 6;
else
ptype = sysinfo.wProcessorLevel;
__small_sprintf (name->machine, "i%d86", ptype);
break;
case PROCESSOR_ARCHITECTURE_IA64:
strcpy (name->machine, "ia64");
break;
case PROCESSOR_ARCHITECTURE_AMD64:
strcpy (name->machine, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
strcpy (name->machine, "ia32-win64");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
strcpy (name->machine, "alpha");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
strcpy (name->machine, "mips");
break;
default:
strcpy (name->machine, "unknown");
break;
}
memset (name, 0, sizeof (*name));
__small_sprintf (name->sysname, "CYGWIN_%s", wincap.osname ());
/* Add a hint to the sysname, that we're running under WOW64. This might
give an early clue if somebody encounters problems. */
if (wincap.is_wow64 ())
strncat (name->sysname, "-WOW64",
sizeof name->sysname - strlen (name->sysname) - 1);
GetSystemInfo (&sysinfo);
/* Computer name */
cygwin_gethostname (name->nodename, sizeof (name->nodename) - 1);
/* Cygwin dll release */
__small_sprintf (name->release, "%d.%d.%d%s(%d.%d/%d/%d)",
cygwin_version.dll_major / 1000,
cygwin_version.dll_major % 1000,
cygwin_version.dll_minor,
snp ? "s" : "",
cygwin_version.api_major,
cygwin_version.api_minor,
cygwin_version.shared_data,
cygwin_version.mount_registry);
/* Cygwin "version" aka build date */
strcpy (name->version, cygwin_version.dll_build_date);
if (snp)
name->version[snp - cygwin_version.dll_build_date] = '\0';
/* CPU type */
switch (sysinfo.wProcessorArchitecture)
{
case PROCESSOR_ARCHITECTURE_INTEL:
unsigned int ptype;
if (sysinfo.wProcessorLevel < 3) /* Shouldn't happen. */
ptype = 3;
else if (sysinfo.wProcessorLevel > 9) /* P4 */
ptype = 6;
else
ptype = sysinfo.wProcessorLevel;
__small_sprintf (name->machine, "i%d86", ptype);
break;
case PROCESSOR_ARCHITECTURE_IA64:
strcpy (name->machine, "ia64");
break;
case PROCESSOR_ARCHITECTURE_AMD64:
strcpy (name->machine, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
strcpy (name->machine, "ia32-win64");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
strcpy (name->machine, "alpha");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
strcpy (name->machine, "mips");
break;
default:
strcpy (name->machine, "unknown");
break;
}
}
__except (EFAULT)
{
return -1;
}
__endtry
return 0; return 0;
} }