Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog45
-rw-r--r--winsup/cygwin/cygheap.cc13
-rw-r--r--winsup/cygwin/cygtls.cc2
-rw-r--r--winsup/cygwin/cygtls.h99
-rw-r--r--winsup/cygwin/dcrt0.cc4
-rw-r--r--winsup/cygwin/dir.cc337
-rw-r--r--winsup/cygwin/environ.cc237
-rw-r--r--winsup/cygwin/exception.h84
-rw-r--r--winsup/cygwin/exceptions.cc95
-rw-r--r--winsup/cygwin/fcntl.cc135
-rw-r--r--winsup/cygwin/fhandler_socket.cc23
-rw-r--r--winsup/cygwin/fhandler_tape.cc290
-rw-r--r--winsup/cygwin/flock.cc140
-rwxr-xr-xwinsup/cygwin/gendef91
-rw-r--r--winsup/cygwin/libc/bsdlib.cc5
-rw-r--r--winsup/cygwin/libc/rexec.cc183
-rw-r--r--winsup/cygwin/miscfuncs.cc70
-rw-r--r--winsup/cygwin/mount.cc101
-rw-r--r--winsup/cygwin/msg.cc114
-rw-r--r--winsup/cygwin/net.cc1773
-rw-r--r--winsup/cygwin/ntdll.h20
-rw-r--r--winsup/cygwin/ntea.cc465
-rw-r--r--winsup/cygwin/path.cc2020
-rw-r--r--winsup/cygwin/poll.cc29
-rw-r--r--winsup/cygwin/posix_ipc.cc1010
-rw-r--r--winsup/cygwin/resource.cc126
-rw-r--r--winsup/cygwin/select.cc31
-rw-r--r--winsup/cygwin/sem.cc52
-rw-r--r--winsup/cygwin/shm.cc58
-rw-r--r--winsup/cygwin/signal.cc126
-rw-r--r--winsup/cygwin/spawn.cc991
-rw-r--r--winsup/cygwin/syscalls.cc2014
-rw-r--r--winsup/cygwin/thread.cc255
-rw-r--r--winsup/cygwin/timer.cc201
-rw-r--r--winsup/cygwin/times.cc105
-rw-r--r--winsup/cygwin/tls_pbuf.cc7
-rw-r--r--winsup/cygwin/tls_pbuf.h14
-rw-r--r--winsup/cygwin/tlsoffsets.h156
-rw-r--r--winsup/cygwin/tlsoffsets64.h156
-rw-r--r--winsup/cygwin/uinfo.cc13
-rw-r--r--winsup/cygwin/uname.cc125
41 files changed, 6137 insertions, 5678 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 51ebe5489..7bd689c3c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,50 @@
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>
+
* miscfuncs.cc (__import_address): Cover the first dereference to imp
under the fault handler.
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index 1ccbbaf5f..067aa68dd 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -638,10 +638,7 @@ init_cygheap::find_tls (int sig, bool& issig_wait)
_cygtls *t = NULL;
issig_wait = false;
- myfault efault;
- if (efault.faulted ())
- threadlist[ix]->remove (INFINITE);
- else
+ __try
{
ix = -1;
/* 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];
issig_wait = true;
- goto out;
+ __leave;
}
else if (!t && !sigismember (&(threadlist[ix]->sigmask), sig))
t = cygheap->threadlist[ix];
}
-out:
+ __except (NO_ERROR)
+ {
+ threadlist[ix]->remove (INFINITE);
+ }
+ __endtry
return t;
}
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index 5cc9405eb..234882130 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -193,7 +193,7 @@ _cygtls::remove (DWORD wait)
free_local (servent_buf);
free_local (hostent_buf);
/* Free temporary TLS path buffers. */
- locals.pathbufs.destroy ();
+ pathbufs.destroy ();
/* Close timer handle. */
if (locals.cw_timer)
NtClose (locals.cw_timer);
diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h
index 32838744d..c05c19563 100644
--- a/winsup/cygwin/cygtls.h
+++ b/winsup/cygwin/cygtls.h
@@ -44,18 +44,21 @@ details. */
#else
#pragma pack(push,4)
#endif
+
/* Defined here to support auto rebuild of tlsoffsets.h. */
class tls_pathbuf
{
- int c_cnt;
- int w_cnt;
+ /* Make sure that c_cnt and w_cnt are always the first two members of this
+ 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];
WCHAR *w_buf[TP_NUM_W_BUFS];
public:
void destroy ();
friend class tmp_pathbuf;
- friend class _cygtls;
friend class san;
};
@@ -129,8 +132,6 @@ struct _local_storage
/* thread.cc */
HANDLE cw_timer;
- /* All functions requiring temporary path buffers. */
- tls_pathbuf pathbufs;
char ttybuf[32];
};
@@ -188,6 +189,7 @@ public:
struct pthread *tid;
class cygthread *_ctinfo;
class san *andreas;
+ tls_pathbuf pathbufs;
waitq wq;
int sig;
unsigned incyg;
@@ -281,34 +283,25 @@ const int CYGTLS_PADSIZE = 12700;
extern PVOID _tlsbase __asm__ ("%fs:4");
extern PVOID _tlstop __asm__ ("%fs:8");
#endif
+
#define _my_tls (*((_cygtls *) ((char *)_tlsbase - CYGTLS_PADSIZE)))
extern _cygtls *_main_tls;
extern _cygtls *_sig_tls;
+#ifndef __x86_64__
class san
{
san *_clemente;
jmp_buf _context;
- int _errno;
- unsigned _c_cnt;
- unsigned _w_cnt;
public:
- int setup (int myerrno = 0) __attribute__ ((always_inline))
+ int setup () __attribute__ ((always_inline))
{
_clemente = _my_tls.andreas;
_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);
}
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);
}
void reset () __attribute__ ((always_inline))
@@ -324,17 +317,73 @@ public:
~myfault () __attribute__ ((always_inline)) { sebastian.reset (); }
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);
+};
+#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; \
}
- inline int faulted (int myerrno) __attribute__ ((always_inline))
- {
- return sebastian.setup (myerrno);
+
+#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
{
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 5150107e8..02c0ad11d 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -796,10 +796,6 @@ dll_crt0_0 ()
_main_tls = &_my_tls;
-#ifdef __x86_64__
- exception::install_myfault_handler ();
-#endif
-
/* Initialize signal processing here, early, in the hopes that the creation
of a thread early in the process will cause more predictability in memory
layout for the main thread. */
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index bdc1a859b..a8eeb2327 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -28,16 +28,16 @@ details. */
extern "C" int
dirfd (DIR *dir)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (dir->__d_cookie != __DIRENT_COOKIE)
+ __try
{
- set_errno (EINVAL);
+ if (dir->__d_cookie == __DIRENT_COOKIE)
+ return dir->__d_fd;
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
@@ -93,79 +93,86 @@ fdopendir (int fd)
static int
readdir_worker (DIR *dir, dirent *de)
{
- myfault efault;
- if (efault.faulted ())
- return EFAULT;
+ int res = 0;
- if (dir->__d_cookie != __DIRENT_COOKIE)
+ __try
{
- syscall_printf ("%p = readdir (%p)", NULL, dir);
- 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, ".");
- dir->__flags |= dirent_saw_dot;
- dir->__d_position++;
- res = 0;
- }
- else if (!(dir->__flags & dirent_saw_dot_dot))
+ if (dir->__d_cookie != __DIRENT_COOKIE)
{
- strcpy (de->d_name, "..");
- dir->__flags |= dirent_saw_dot_dot;
- dir->__d_position++;
- res = 0;
+ syscall_printf ("%p = readdir (%p)", NULL, dir);
+ res = EBADF;
+ __leave;
}
- }
- if (!res && !de->d_ino)
- {
- bool is_dot = false;
- bool is_dot_dot = false;
+ de->d_ino = 0;
+ de->d_type = DT_UNKNOWN;
+ memset (&de->__d_unused1, 0, sizeof (de->__d_unused1));
- if (de->d_name[0] == '.')
+ res = ((fhandler_base *) dir->__fh)->readdir (dir, de);
+
+ if (res == ENMFILE)
{
- 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 (!(dir->__flags & dirent_saw_dot))
+ {
+ strcpy (de->d_name, ".");
+ dir->__flags |= dirent_saw_dot;
+ dir->__d_position++;
+ 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 (is_dot_dot && !(dir->__flags & dirent_isroot))
- de->d_ino = readdir_get_ino (((fhandler_base *) dir->__fh)->get_name (),
- true);
- else
+ if (!res && !de->d_ino)
{
- /* 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)
+ 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
{
- 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);
+ /* 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;
}
- /* 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;
}
@@ -200,16 +207,15 @@ readdir_r (DIR *__restrict dir, dirent *__restrict de, dirent **__restrict ode)
extern "C" long
telldir (DIR *dir)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- if (dir->__d_cookie != __DIRENT_COOKIE)
+ __try
{
+ if (dir->__d_cookie == __DIRENT_COOKIE)
+ return ((fhandler_base *) dir->__fh)->telldir (dir);
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
@@ -225,14 +231,17 @@ telldir64 (DIR *dir)
extern "C" void
seekdir (DIR *dir, long loc)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return;
-
- if (dir->__d_cookie != __DIRENT_COOKIE)
- return;
- dir->__flags &= dirent_info_mask;
- return ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
+ __try
+ {
+ if (dir->__d_cookie == __DIRENT_COOKIE)
+ {
+ dir->__flags &= dirent_info_mask;
+ ((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
@@ -248,42 +257,45 @@ seekdir64 (DIR *dir, off_t loc)
extern "C" void
rewinddir (DIR *dir)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return;
-
- if (dir->__d_cookie != __DIRENT_COOKIE)
- return;
- dir->__flags &= dirent_info_mask;
- return ((fhandler_base *) dir->__fh)->rewinddir (dir);
+ __try
+ {
+ if (dir->__d_cookie == __DIRENT_COOKIE)
+ {
+ dir->__flags &= dirent_info_mask;
+ ((fhandler_base *) dir->__fh)->rewinddir (dir);
+ }
+ set_errno (EINVAL); /* Diagnosis */
+ }
+ __except (EFAULT) {}
+ __endtry
}
/* closedir: POSIX 5.1.2.1 */
extern "C" int
closedir (DIR *dir)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- if (dir->__d_cookie != __DIRENT_COOKIE)
+ __try
{
- set_errno (EBADF);
- syscall_printf ("%R = closedir(%p)", -1, dir);
- return -1;
- }
-
- /* Reset the marker in case the caller tries to use `dir' again. */
- dir->__d_cookie = 0;
+ 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);
+ 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;
+ 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);
+ }
+ __except (EFAULT) {}
+ __endtry
+ syscall_printf ("%R = closedir(%p)", -1, dir);
+ return -1;
}
/* mkdir: POSIX 5.4.1.1 */
@@ -294,43 +306,42 @@ mkdir (const char *dir, mode_t mode)
fhandler_base *fh = NULL;
tmp_pathbuf tp;
- myfault efault;
- 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);
- goto done;
- }
- if (isdirsep (dir[strlen (dir) - 1]))
+ __try
{
- /* 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 */;
+ /* POSIX says mkdir("symlink-to-missing/") should create the
+ directory "missing", but Linux rejects it with EEXIST. Copy
+ Linux behavior for now. */
- 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;
+ if (!*dir)
+ {
+ set_errno (ENOENT);
+ __leave;
+ }
+ 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)))
+ __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);
return res;
}
@@ -342,30 +353,28 @@ rmdir (const char *dir)
int res = -1;
fhandler_base *fh = NULL;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
- goto done; /* errno already set */;
-
- if (fh->error ())
+ __try
{
- debug_printf ("got %d error from build_fh_name", fh->error ());
- set_errno (fh->error ());
+ if (!(fh = build_fh_name (dir, PC_SYM_NOFOLLOW)))
+ __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 ())
- 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;
-
- done:
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = rmdir(%s)", res, dir);
return res;
}
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index f56d19517..817439b0a 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -2,7 +2,7 @@
process's environment.
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
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
putenv (char *str)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (*str)
+ __try
{
- char *eq = strchr (str, '=');
- if (eq)
- return _addenv (str, eq + 1, -1);
+ if (*str)
+ {
+ char *eq = strchr (str, '=');
+ if (eq)
+ return _addenv (str, eq + 1, -1);
- /* Remove str from the environment. */
- unsetenv (str);
+ /* Remove str from the environment. */
+ unsetenv (str);
+ }
+ return 0;
}
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
/* Set the value of the environment variable "name" to be
@@ -684,15 +687,18 @@ putenv (char *str)
extern "C" int
setenv (const char *name, const char *value, int overwrite)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (!name || !*name || strchr (name, '='))
+ __try
{
- set_errno (EINVAL);
- return -1;
+ if (!name || !*name || strchr (name, '='))
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ return _addenv (name, value, !!overwrite);
}
- return _addenv (name, value, !!overwrite);
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
/* Delete environment variable "name". */
@@ -701,22 +707,26 @@ unsetenv (const char *name)
{
register char **e;
int offset;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (!name || *name == '\0' || strchr (name, '='))
+
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
+ if (!name || *name == '\0' || strchr (name, '='))
+ {
+ 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;
+ 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;
+ return 0;
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
/* 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 got_something_from_registry;
static char NO_COPY cygterm[] = "TERM=cygwin";
- myfault efault;
tmp_pathbuf tp;
- if (efault.faulted ())
- 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
+ __try
{
- envc++;
- envc *= sizeof (char *);
- char **newenv = (char **) malloc (envc);
- memcpy (newenv, envp, envc);
- cfree (envp);
-
- /* Older applications relied on the fact that cygwin malloced elements of the
- 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;
- }
+ 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++;
+ envc *= sizeof (char *);
+ char **newenv = (char **) malloc (envc);
+ memcpy (newenv, envp, envc);
+ cfree (envp);
+
+ /* Older applications relied on the fact that cygwin malloced elements of the
+ 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 *));
+ /* 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);
+ 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]);
- }
+ /* 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);
+ 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)
+ 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)
{
- p = getenv ("CYGWIN");
- if (p)
- parse_options (p);
+ api_fatal ("internal error reading the windows environment "
+ "- too many environment variables?");
}
-
- if (got_something_from_registry)
- parse_options (NULL); /* possibly export registry settings to
- environment */
- MALLOC_CHECK;
+ __endtry
}
/* Function called by qsort to sort environment strings. */
diff --git a/winsup/cygwin/exception.h b/winsup/cygwin/exception.h
index 83cb21fcf..9e34799fe 100644
--- a/winsup/cygwin/exception.h
+++ b/winsup/cygwin/exception.h
@@ -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
have to do). */
-typedef int (exception_handler) (EXCEPTION_RECORD *, struct _exception_list *,
- CONTEXT *, void *);
+typedef EXCEPTION_DISPOSITION (exception_handler) (EXCEPTION_RECORD *,
+ struct _exception_list *,
+ CONTEXT *,
+ void *);
typedef struct _exception_list
{
@@ -104,70 +106,53 @@ typedef struct _exception_list
} exception_list;
extern exception_list *_except_list asm ("%fs:0");
-#else
-typedef void exception_list;
-#endif /* !__x86_64 */
+typedef void *PDISPATCHER_CONTEXT;
class exception
{
-#ifdef __x86_64__
- static LONG myfault_handle (LPEXCEPTION_POINTERS ep);
-#else
exception_list el;
exception_list *save;
-#endif /* __x86_64__ */
- static int handle (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *);
+ static EXCEPTION_DISPOSITION handle (EXCEPTION_RECORD *, exception_list *,
+ CONTEXT *, PDISPATCHER_CONTEXT);
public:
exception () __attribute__ ((always_inline))
{
/* 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__
+ 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\
1: \n\
.seh_handler \
- _ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTS2_, \
+ _ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, \
@except \n\
.seh_handlerdata \n\
.long 1 \n\
.rva 1b, 2f, 2f, 2f \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))
{
asm volatile ("\n\
@@ -175,11 +160,10 @@ public:
2: \n\
nop \n");
}
-#else
- ~exception () __attribute__ ((always_inline)) { _except_list = save; }
-#endif /* !__x86_64__ */
};
+#endif /* !__x86_64 */
+
class cygwin_exception
{
PUINT_PTR framep;
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 0e8a977d4..4e9c77036 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -341,38 +341,41 @@ void
cygwin_exception::dumpstack ()
{
static bool already_dumped;
- myfault efault;
- if (efault.faulted ())
- return;
- if (already_dumped || cygheap->rlim_core == 0Ul)
- return;
- already_dumped = true;
- open_stackdumpfile ();
+ __try
+ {
+ if (already_dumped || cygheap->rlim_core == 0Ul)
+ return;
+ already_dumped = true;
+ open_stackdumpfile ();
- if (e)
- dump_exception ();
+ if (e)
+ dump_exception ();
- int i;
+ int i;
- thestack.init (framep, 1, ctx); /* Initialize from the input CONTEXT */
+ thestack.init (framep, 1, ctx); /* Initialize from the input CONTEXT */
#ifdef __x86_64__
- small_printf ("Stack trace:\r\nFrame Function Args\r\n");
+ small_printf ("Stack trace:\r\nFrame Function Args\r\n");
#else
- small_printf ("Stack trace:\r\nFrame Function Args\r\n");
+ 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");
+ 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",
- i == 16 ? " (more stack frames may be present)" : "");
- if (h)
- NtClose (h);
+ __except (NO_ERROR) {}
+ __endtry
}
bool
@@ -549,40 +552,24 @@ rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
#endif /* __x86_64 */
#ifdef __x86_64__
-/* myfault vectored exception handler */
-LONG
-exception::myfault_handle (LPEXCEPTION_POINTERS ep)
+/* myfault exception handler. */
+EXCEPTION_DISPOSITION
+exception::myfault (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
+ PDISPATCHER_CONTEXT dispatch)
{
- _cygtls& me = _my_tls;
-
- if (me.andreas)
- {
- /* Only handle the minimum amount of exceptions the myfault handler
- was designed for. */
- 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;
+ PSCOPE_TABLE table = (PSCOPE_TABLE) dispatch->HandlerData;
+ RtlUnwindEx (frame,
+ (char *) dispatch->ImageBase + table->ScopeRecord[0].JumpTarget,
+ e, 0, in, dispatch->HistoryTable);
+ /* NOTREACHED, make gcc happy. */
+ return ExceptionContinueSearch;
}
-#endif /* __x86_64 */
+#endif
/* Main exception handler. */
-int
-exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
+EXCEPTION_DISPOSITION
+exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
+ PDISPATCHER_CONTEXT dispatch)
{
static bool NO_COPY debugging;
_cygtls& me = _my_tls;
diff --git a/winsup/cygwin/fcntl.cc b/winsup/cygwin/fcntl.cc
index ea9a71a5e..babb06424 100644
--- a/winsup/cygwin/fcntl.cc
+++ b/winsup/cygwin/fcntl.cc
@@ -1,7 +1,7 @@
/* fcntl.cc: fcntl syscall
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.
@@ -28,53 +28,54 @@ fcntl64 (int fd, int cmd, ...)
pthread_testcancel ();
- debug_printf ("fcntl(%d, %d, ...)", fd, cmd);
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ __try
+ {
- cygheap_fdget cfd (fd, true);
- if (cfd < 0)
- goto done;
+ debug_printf ("fcntl(%d, %d, ...)", fd, cmd);
+ cygheap_fdget cfd (fd, true);
+ if (cfd < 0)
+ __leave;
- /* FIXME? All numerical args to fcntl are defined as long on Linux.
- This relies on a really dirty trick on x86_64: A 32 bit mov to
- a register (e.g. mov $1, %edx) always sets the high 32 bit to 0.
- We're following the Linux lead here since the third arg to any
- function is in a register anyway (%r8 in MS ABI). That's the easy
- case which is covered here by always reading the arg with
- sizeof (intptr_t) == sizeof (long) == sizeof (void*) which matches
- all targets.
-
- However, the POSIX standard defines all numerical args as type int.
- If we take that literally, we had a (small) problem on 64 bit, since
- sizeof (void*) != sizeof (int). If we would like to follow POSIX
- more closely than Linux, we'd have to call va_arg on a per cmd basis. */
+ /* 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);
+ va_start (args, cmd);
+ arg = va_arg (args, intptr_t);
+ va_end (args);
- switch (cmd)
- {
- case F_DUPFD:
- case F_DUPFD_CLOEXEC:
- if (arg >= 0 && arg < OPEN_MAX_MAX)
- {
- int flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
- res = cygheap->fdtab.dup3 (fd, cygheap_fdnew ((arg) - 1), flags);
- }
- else
+ switch (cmd)
{
- set_errno (EINVAL);
- res = -1;
+ case F_DUPFD:
+ case F_DUPFD_CLOEXEC:
+ if (arg >= 0 && arg < OPEN_MAX_MAX)
+ {
+ int flags = cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0;
+ res = cygheap->fdtab.dup3 (fd, cygheap_fdnew ((arg) - 1), flags);
+ }
+ else
+ {
+ set_errno (EINVAL);
+ res = -1;
+ }
+ break;
+ default:
+ res = cfd->fcntl (cmd, arg);
+ break;
}
- break;
- default:
- res = cfd->fcntl (cmd, arg);
- break;
}
-done:
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = fcntl(%d, %d, %ly)", res, fd, cmd, arg);
return res;
}
@@ -91,32 +92,34 @@ _fcntl (int fd, int cmd, ...)
struct __flock32 *src = NULL;
struct flock dst;
- myfault efault;
- 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;
- 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)
+ __try
{
- 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;
+ va_start (args, cmd);
+ arg = va_arg (args, intptr_t);
+ va_end (args);
+ if (cmd == F_GETLK || cmd == F_SETLK || cmd == F_SETLKW)
+ {
+ src = (struct __flock32 *) arg;
+ dst.l_type = src->l_type;
+ dst.l_whence = src->l_whence;
+ dst.l_start = src->l_start;
+ dst.l_len = src->l_len;
+ dst.l_pid = src->l_pid;
+ arg = (intptr_t) &dst;
+ }
+ int res = fcntl64 (fd, cmd, arg);
+ if (cmd == F_GETLK)
+ {
+ src->l_type = dst.l_type;
+ src->l_whence = dst.l_whence;
+ src->l_start = dst.l_start;
+ src->l_len = dst.l_len;
+ src->l_pid = (short) dst.l_pid;
+ }
+ return res;
}
- return res;
+ __except (EFAULT)
+ __endtry
+ return -1;
}
#endif
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 59c002c03..0354ee246 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -2293,14 +2293,17 @@ fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
return -1;
}
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (pid)
- *pid = sec_peer_pid;
- if (euid)
- *euid = sec_peer_uid;
- if (egid)
- *egid = sec_peer_gid;
- return 0;
+ __try
+ {
+ if (pid)
+ *pid = sec_peer_pid;
+ if (euid)
+ *euid = sec_peer_uid;
+ if (egid)
+ *egid = sec_peer_gid;
+ return 0;
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index 91d5b12aa..5b09e4262 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -2,7 +2,7 @@
classes.
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.
@@ -977,159 +977,163 @@ mtinfo_drive::set_options (HANDLE mt, int32_t options)
int
mtinfo_drive::ioctl (HANDLE mt, unsigned int cmd, void *buf)
{
- myfault efault;
- if (efault.faulted ())
- return ERROR_NOACCESS;
- if (cmd == MTIOCTOP)
+ __try
{
- struct mtop *op = (struct mtop *) buf;
- if (lasterr == ERROR_BUS_RESET)
+ if (cmd == MTIOCTOP)
{
- /* If a bus reset occurs, block further access to this device
- 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))
+ struct mtop *op = (struct mtop *) buf;
+ if (lasterr == ERROR_BUS_RESET)
{
- debug_printf ("Couldn't relock drive after bus reset.");
- lock = unlocked;
+ /* If a bus reset occurs, block further access to this device
+ 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)
- {
- 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;
+ switch (op->mt_op)
+ {
+ case MTRESET:
break;
- }
- if ((DWORD) op->mt_count == mp ()->BlockSize)
- {
- /* Nothing has changed. */
+ 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;
- }
- if ((op->mt_count == 0 && !get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
- || (op->mt_count > 0
- && ((DWORD) op->mt_count < dp ()->MinimumBlockSize
- || (DWORD) op->mt_count > dp ()->MaximumBlockSize)))
- {
+ 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;
- }
- if (set_blocksize (mt, op->mt_count)
- && lasterr == ERROR_INVALID_FUNCTION)
- lasterr = ERROR_INVALID_BLOCK_LENGTH;
- break;
- case MTSEEK:
- if (get_feature (TAPE_DRIVE_LOGICAL_BLK))
- set_pos (mt, TAPE_LOGICAL_BLOCK, op->mt_count, false);
- else if (!get_pos (mt))
- set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS,
- op->mt_count - block, false);
- break;
- case MTTELL:
- if (!get_pos (mt))
- op->mt_count = (int) block;
- break;
- case MTFSS:
- set_pos (mt, TAPE_SPACE_SETMARKS, op->mt_count, false);
- break;
- case MTBSS:
- set_pos (mt, TAPE_SPACE_SETMARKS, -op->mt_count, false);
- break;
- case MTWSM:
- write_marks (mt, TAPE_SETMARKS, op->mt_count);
- break;
- case MTLOCK:
- prepare (mt, TAPE_LOCK);
- break;
- case MTUNLOCK:
- prepare (mt, TAPE_UNLOCK);
- 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;
+ case MTSETBLK:
+ if (!get_feature (TAPE_DRIVE_SET_BLOCK_SIZE))
+ {
+ lasterr = ERROR_INVALID_PARAMETER;
+ break;
+ }
+ if ((DWORD) op->mt_count == mp ()->BlockSize)
+ {
+ /* Nothing has changed. */
+ lasterr = 0;
+ break;
+ }
+ if ((op->mt_count == 0 && !get_feature (TAPE_DRIVE_VARIABLE_BLOCK))
+ || (op->mt_count > 0
+ && ((DWORD) op->mt_count < dp ()->MinimumBlockSize
+ || (DWORD) op->mt_count > dp ()->MaximumBlockSize)))
+ {
+ lasterr = ERROR_INVALID_PARAMETER;
+ break;
+ }
+ if (set_blocksize (mt, op->mt_count)
+ && lasterr == ERROR_INVALID_FUNCTION)
+ lasterr = ERROR_INVALID_BLOCK_LENGTH;
+ break;
+ case MTSEEK:
+ if (get_feature (TAPE_DRIVE_LOGICAL_BLK))
+ set_pos (mt, TAPE_LOGICAL_BLOCK, op->mt_count, false);
+ else if (!get_pos (mt))
+ set_pos (mt, TAPE_SPACE_RELATIVE_BLOCKS,
+ op->mt_count - block, false);
+ break;
+ case MTTELL:
+ if (!get_pos (mt))
+ op->mt_count = (int) block;
+ break;
+ case MTFSS:
+ set_pos (mt, TAPE_SPACE_SETMARKS, op->mt_count, false);
+ break;
+ case MTBSS:
+ set_pos (mt, TAPE_SPACE_SETMARKS, -op->mt_count, false);
+ break;
+ case MTWSM:
+ write_marks (mt, TAPE_SETMARKS, op->mt_count);
+ break;
+ case MTLOCK:
+ prepare (mt, TAPE_LOCK);
+ break;
+ case MTUNLOCK:
+ prepare (mt, TAPE_UNLOCK);
+ 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)
- get_status (mt, (struct mtget *) buf);
- else if (cmd == MTIOCPOS && !get_pos (mt))
- ((struct mtpos *) buf)->mt_blkno = (long) block;
-
+ __except (NO_ERROR)
+ {
+ lasterr = ERROR_NOACCESS;
+ }
+ __endtry
return lasterr;
}
diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc
index 4250aba3f..540d914e3 100644
--- a/winsup/cygwin/flock.cc
+++ b/winsup/cygwin/flock.cc
@@ -1761,37 +1761,37 @@ flock (int fd, int operation)
int cmd;
struct flock fl = { 0, SEEK_SET, 0, 0, 0 };
- myfault efault;
- 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))
+ __try
{
- case LOCK_EX:
- fl.l_type = F_WRLCK;
- break;
- case LOCK_SH:
- fl.l_type = F_RDLCK;
- break;
- case LOCK_UN:
- fl.l_type = F_UNLCK;
- break;
- default:
- set_errno (EINVAL);
- goto done;
+ cygheap_fdget cfd (fd, true);
+ if (cfd < 0)
+ __leave;
+
+ cmd = (operation & LOCK_NB) ? F_SETLK : F_SETLKW;
+ switch (operation & (~LOCK_NB))
+ {
+ case LOCK_EX:
+ fl.l_type = F_WRLCK;
+ break;
+ case LOCK_SH:
+ 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 ())
- 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);
-done:
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = flock(%d, %d)", res, fd, operation);
return res;
}
@@ -1805,50 +1805,50 @@ lockf (int filedes, int function, off_t size)
pthread_testcancel ();
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- cygheap_fdget cfd (filedes, true);
- if (cfd < 0)
- goto done;
+ __try
+ {
+ cygheap_fdget cfd (filedes, true);
+ if (cfd < 0)
+ __leave;
- fl.l_start = 0;
- fl.l_len = size;
- fl.l_whence = SEEK_CUR;
+ fl.l_start = 0;
+ fl.l_len = size;
+ fl.l_whence = SEEK_CUR;
- switch (function)
- {
- case F_ULOCK:
- cmd = F_SETLK;
- fl.l_type = F_UNLCK;
- break;
- case F_LOCK:
- cmd = F_SETLKW;
- fl.l_type = F_WRLCK;
- break;
- case F_TLOCK:
- cmd = F_SETLK;
- fl.l_type = F_WRLCK;
- break;
- case F_TEST:
- fl.l_type = F_WRLCK;
- if (cfd->lock (F_GETLK, &fl) == -1)
- goto done;
- if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
- res = 0;
- else
- errno = EAGAIN;
- goto done;
- /* NOTREACHED */
- default:
- errno = EINVAL;
- goto done;
- /* NOTREACHED */
+ switch (function)
+ {
+ case F_ULOCK:
+ cmd = F_SETLK;
+ fl.l_type = F_UNLCK;
+ break;
+ case F_LOCK:
+ cmd = F_SETLKW;
+ fl.l_type = F_WRLCK;
+ break;
+ case F_TLOCK:
+ cmd = F_SETLK;
+ fl.l_type = F_WRLCK;
+ break;
+ case F_TEST:
+ fl.l_type = F_WRLCK;
+ if (cfd->lock (F_GETLK, &fl) == -1)
+ __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)
- : cfd->lock (cmd, &fl);
-done:
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = lockf(%d, %d, %D)", res, filedes, function, size);
return res;
}
diff --git a/winsup/cygwin/gendef b/winsup/cygwin/gendef
index cef34a5ab..150bd3531 100755
--- a/winsup/cygwin/gendef
+++ b/winsup/cygwin/gendef
@@ -1,5 +1,5 @@
#!/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.
#
# 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
decl $tls::incyg(%r10)
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
.seh_endproc
@@ -366,7 +368,7 @@ stabilize_sig_stack:
movq %gs:8,%r12
1: movl \$1,%r10d
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
jz 2f
pause
@@ -374,14 +376,14 @@ stabilize_sig_stack:
2: incl $tls::incyg(%r12)
cmpl \$0,$tls::sig(%r12)
jz 3f
- decl $tls::stacklock(%r12) # unlock
- movq \$$tls::start_offset,%rcx # point to beginning
- addq %r12,%rcx # of tls block
+ decl $tls::stacklock(%r12) # unlock
+ movq \$$tls::start_offset,%rcx # point to beginning
+ addq %r12,%rcx # of tls block
call _ZN7_cygtls19call_signal_handlerEv
jmp 1b
3: decl $tls::incyg(%r12)
addq \$0x20,%rsp
- movq %r12,%r11 # return tls addr in r11
+ movq %r12,%r11 # return tls addr in r11
popq %r12
ret
.seh_endproc
@@ -393,13 +395,13 @@ EOF
__sigfe_maybe:
pushl %ebx
pushl %edx
- movl %fs:4,%ebx # location of bottom of stack
- addl \$$tls::initialized,%ebx # where we will be looking
- cmpl %ebx,%esp # stack loc > than tls
- jge 0f # yep. we don't have a tls.
- subl \$$tls::initialized,%ebx # where we will be looking
+ movl %fs:4,%ebx # location of bottom of stack
+ addl \$$tls::initialized,%ebx # where we will be looking
+ cmpl %ebx,%esp # stack loc > than tls
+ jge 0f # yep. we don't have a tls.
+ subl \$$tls::initialized,%ebx # where we will be looking
movl $tls::initialized(%ebx),%eax
- cmpl \$0xc763173f,%eax # initialized?
+ cmpl \$0xc763173f,%eax # initialized?
je 1f
0: popl %edx
popl %ebx
@@ -408,43 +410,46 @@ __sigfe_maybe:
__sigfe:
pushl %ebx
pushl %edx
- movl %fs:4,%ebx # location of bottom of stack
-1: movl \$1,%eax # potential lock value
- xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it
- movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock
- testl %eax,%eax # it will be zero
- jz 2f # if so
- call _yield # should be a short-time thing, so
- jmp 1b # sleep and loop
-2: movl \$4,%eax # have the lock, now increment the
- xadd %eax,$tls::stackptr(%ebx) # stack pointer and get pointer
- leal __sigbe,%edx # new place to return to
- xchgl %edx,12(%esp) # exchange with real return value
- movl %edx,(%eax) # store real return value on alt stack
+ movl %fs:4,%ebx # location of bottom of stack
+1: movl \$1,%eax # potential lock value
+ xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it
+ movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock
+ testl %eax,%eax # it will be zero
+ jz 2f # if so
+ call _yield # should be a short-time thing, so
+ jmp 1b # sleep and loop
+2: movl \$4,%eax # have the lock, now increment the
+ xadd %eax,$tls::stackptr(%ebx) # stack pointer and get pointer
+ leal __sigbe,%edx # new place to return to
+ xchgl %edx,12(%esp) # exchange with real return value
+ movl %edx,(%eax) # store real return value on alt stack
incl $tls::incyg(%ebx)
- decl $tls::stacklock(%ebx) # remove lock
- popl %edx # restore saved value
+ decl $tls::stacklock(%ebx) # remove lock
+ popl %edx # restore saved value
popl %ebx
ret
.global __sigbe
-__sigbe: # return here after cygwin syscall
- pushl %eax # don't clobber
- pushl %ebx # tls pointer
-1: movl %fs:4,%ebx # address of bottom of tls
- movl \$1,%eax # potential lock value
- xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it
- movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock
- testl %eax,%eax # it will be zero
- jz 2f # if so
- call _yield # sleep
- jmp 1b # and loop
-2: movl \$-4,%eax # now decrement aux stack
- xadd %eax,$tls::stackptr(%ebx) # and get pointer
- movl -4(%eax),%eax # get return address from signal stack
- xchgl %eax,4(%esp) # swap return address with saved eax
+__sigbe: # return here after cygwin syscall
+ pushl %eax # don't clobber
+ pushl %ebx # tls pointer
+1: movl %fs:4,%ebx # address of bottom of tls
+ movl \$1,%eax # potential lock value
+ xchgl %eax,$tls::stacklock(%ebx) # see if we can grab it
+ movl %eax,$tls::spinning(%ebx) # flag if we are waiting for lock
+ testl %eax,%eax # it will be zero
+ jz 2f # if so
+ call _yield # sleep
+ jmp 1b # and loop
+2: movl \$-4,%eax # now decrement aux stack
+ xadd %eax,$tls::stackptr(%ebx) # and get pointer
+ movl -4(%eax),%eax # get return address from signal stack
+ xchgl %eax,4(%esp) # swap return address with saved eax
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
ret
diff --git a/winsup/cygwin/libc/bsdlib.cc b/winsup/cygwin/libc/bsdlib.cc
index 696a9f856..89bc9431c 100644
--- a/winsup/cygwin/libc/bsdlib.cc
+++ b/winsup/cygwin/libc/bsdlib.cc
@@ -249,8 +249,7 @@ getprogname (void)
extern "C" void
setprogname (const char *newprogname)
{
- myfault efault;
- if (!efault.faulted (EFAULT))
+ __try
{
/* Per BSD man page, setprogname keeps a pointer to the last
path component of the argument. It does *not* copy the
@@ -261,6 +260,8 @@ setprogname (const char *newprogname)
else
__progname = (char *)newprogname;
}
+ __except (EFAULT) {}
+ __endtry
}
extern "C" void
diff --git a/winsup/cygwin/libc/rexec.cc b/winsup/cygwin/libc/rexec.cc
index c3074d381..f9be2231a 100644
--- a/winsup/cygwin/libc/rexec.cc
+++ b/winsup/cygwin/libc/rexec.cc
@@ -312,100 +312,101 @@ extern "C" int
cygwin_rexec (char **ahost, unsigned short rport, char *name, char *pass,
char *cmd, int *fd2p)
{
- struct sockaddr_in sin, sin2, from;
- struct hostent *hp;
- u_short port = 0;
- int s, timo = 1, s3;
- char c;
- static char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ struct sockaddr_in sin, sin2, from;
+ struct hostent *hp;
+ u_short port = 0;
+ int s, timo = 1, s3;
+ char c;
+ static char ahostbuf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- hp = cygwin_gethostbyname(*ahost);
- if (hp == 0) {
- cygwin_herror(*ahost);
- return (-1);
- }
- *ahost = strcpy (ahostbuf, hp->h_name);
- ruserpass(hp->h_name, &name, &pass, NULL);
- if (!name)
- name = getlogin ();
- if (!pass)
- pass = almost_null;
+ __try
+ {
+ hp = cygwin_gethostbyname(*ahost);
+ if (hp == 0) {
+ cygwin_herror(*ahost);
+ return (-1);
+ }
+ *ahost = strcpy (ahostbuf, hp->h_name);
+ ruserpass(hp->h_name, &name, &pass, NULL);
+ if (!name)
+ name = getlogin ();
+ if (!pass)
+ pass = almost_null;
retry:
- s = cygwin_socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0) {
- perror("rexec: socket");
- return (-1);
- }
- sin.sin_family = hp->h_addrtype;
- sin.sin_port = rport;
- bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
- if (cygwin_connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- if (errno == ECONNREFUSED && timo <= 16) {
- (void) close(s);
- sleep(timo);
- timo *= 2;
- goto retry;
- }
- perror(hp->h_name);
- return (-1);
- }
- if (fd2p == 0) {
- (void) write(s, "", 1);
- } else {
- char num[8];
- int s2, sin2len;
+ s = cygwin_socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ perror("rexec: socket");
+ return (-1);
+ }
+ sin.sin_family = hp->h_addrtype;
+ sin.sin_port = rport;
+ bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
+ if (cygwin_connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ if (errno == ECONNREFUSED && timo <= 16) {
+ (void) close(s);
+ sleep(timo);
+ timo *= 2;
+ goto retry;
+ }
+ perror(hp->h_name);
+ return (-1);
+ }
+ if (fd2p == 0) {
+ (void) write(s, "", 1);
+ } else {
+ char num[8];
+ int s2, sin2len;
- s2 = cygwin_socket(AF_INET, SOCK_STREAM, 0);
- if (s2 < 0) {
- (void) close(s);
- 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;
+ s2 = cygwin_socket(AF_INET, SOCK_STREAM, 0);
+ if (s2 < 0) {
+ (void) close(s);
+ 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;
}
- 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;
- }
- }
- *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);
+ }
+ *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:
- if (port)
- (void) close(*fd2p);
- (void) close(s);
- return (-1);
+ if (port)
+ (void) close(*fd2p);
+ (void) close(s);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return (-1);
}
diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc
index 741e6726b..eee47a53a 100644
--- a/winsup/cygwin/miscfuncs.cc
+++ b/winsup/cygwin/miscfuncs.cc
@@ -202,35 +202,38 @@ check_iovec (const struct iovec *iov, int iovcnt, bool forwrite)
return -1;
}
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ __try
+ {
- size_t tot = 0;
+ size_t tot = 0;
- while (iovcnt != 0)
- {
- if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
+ while (iovcnt != 0)
{
- set_errno (EINVAL);
- return -1;
- }
+ if (iov->iov_len > SSIZE_MAX || (tot += iov->iov_len) > SSIZE_MAX)
+ {
+ 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);
+ 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--;
- }
+ iov++;
+ iovcnt--;
+ }
- assert (tot <= SSIZE_MAX);
+ assert (tot <= SSIZE_MAX);
- return (ssize_t) tot;
+ return (ssize_t) tot;
+ }
+ __except (EFAULT)
+ __endtry
+ return -1;
}
/* Try hard to schedule another thread.
@@ -512,18 +515,23 @@ slashify (const char *src, char *dst, bool trailing_slash_p)
void * __reg1
__import_address (void *imp)
{
- myfault efault;
- if (efault.faulted ())
- return NULL;
- if (*((uint16_t *) imp) != 0x25ff)
- return NULL;
- const char *ptr = (const char *) imp;
+ __try
+ {
+ if (*((uint16_t *) imp) == 0x25ff)
+ {
+ const char *ptr = (const char *) imp;
#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
- const uintptr_t *jmpto = (uintptr_t *) *((uintptr_t *) (ptr + 2));
+ const uintptr_t *jmpto = (uintptr_t *) *((uintptr_t *) (ptr + 2));
#endif
- return (void *) *jmpto;
+ return (void *) *jmpto;
+ }
+ }
+ __except (NO_ERROR) {}
+ __endtry
+ return NULL;
}
/* CygwinCreateThread.
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index eecd72692..94e305489 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -1700,50 +1700,54 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
isn't really supported except from fstab? */
int res = -1;
- myfault efault;
- 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 */
+ __try
{
- /* When flags include MOUNT_CYGDRIVE, take this to mean that
- we actually want to change the cygdrive prefix and flags
- without actually mounting anything. */
- res = mount_table->write_cygdrive_info (posix_path, flags);
- win32_path = NULL;
- }
- else if (!*win32_path)
- set_errno (EINVAL);
- else
- {
- char *w32_path = (char *) win32_path;
- if (flags & MOUNT_BIND)
+ if (!*posix_path)
+ set_errno (EINVAL);
+ else if (strpbrk (posix_path, "\\:"))
+ set_errno (EINVAL);
+ else if (flags & MOUNT_CYGDRIVE) /* normal mount */
{
- /* Prepend root path to bound path. */
- tmp_pathbuf tp;
- device dev;
-
- 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);
+ /* When flags include MOUNT_CYGDRIVE, take this to mean that
+ we actually want to change the cygdrive prefix and flags
+ without actually mounting anything. */
+ res = mount_table->write_cygdrive_info (posix_path, flags);
+ win32_path = NULL;
+ }
+ else if (!*win32_path)
+ set_errno (EINVAL);
+ else
+ {
+ char *w32_path = (char *) win32_path;
+ if (flags & MOUNT_BIND)
+ {
+ /* Prepend root path to bound path. */
+ tmp_pathbuf tp;
+ device dev;
+
+ 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);
}
- /* 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);
+ syscall_printf ("%R = mount(%s, %s, %y)",
+ res, win32_path, posix_path, flags);
+ }
+ __except (EFAULT) {}
+ __endtry
return res;
}
@@ -1755,15 +1759,18 @@ mount (const char *win32_path, const char *posix_path, unsigned flags)
extern "C" int
umount (const char *path)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (!*path)
+ __try
{
- set_errno (EINVAL);
- return -1;
+ if (!*path)
+ {
+ 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
diff --git a/winsup/cygwin/msg.cc b/winsup/cygwin/msg.cc
index f970121c9..5505dc453 100644
--- a/winsup/cygwin/msg.cc
+++ b/winsup/cygwin/msg.cc
@@ -1,6 +1,6 @@
/* 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.
@@ -91,38 +91,40 @@ client_request_msg::client_request_msg (int msqid,
extern "C" int
msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
- syscall_printf ("msgctl (msqid = %d, cmd = %y, buf = %p)",
- msqid, cmd, buf);
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- switch (cmd)
+ syscall_printf ("msgctl (msqid = %d, cmd = %y, buf = %p)", msqid, cmd, buf);
+ __try
{
- case IPC_STAT:
- break;
- case IPC_SET:
- break;
- case IPC_RMID:
- break;
- case IPC_INFO:
- break;
- case MSG_INFO:
- break;
- default:
- syscall_printf ("-1 [%d] = msgctl ()", EINVAL);
- set_errno (EINVAL);
- return -1;
+ switch (cmd)
+ {
+ case IPC_STAT:
+ break;
+ case IPC_SET:
+ break;
+ case IPC_RMID:
+ break;
+ case IPC_INFO:
+ break;
+ case MSG_INFO:
+ break;
+ default:
+ 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);
- 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);
- return -1;
- }
- return request.retval ();
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
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, "
"msgtyp = %d, msgflg = %y)",
msqid, msgp, msgsz, msgtyp, msgflg);
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- client_request_msg request (msqid, msgp, msgsz, msgtyp, msgflg);
- if (request.make_request () == -1 || request.rcvval () == -1)
+ __try
{
- syscall_printf ("-1 [%d] = msgrcv ()", request.error_code ());
- set_errno (request.error_code ());
- if (request.error_code () == ENOSYS)
- raise (SIGSYS);
- 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 ());
+ 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
@@ -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)",
msqid, msgp, msgsz, msgflg);
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- client_request_msg request (msqid, msgp, msgsz, msgflg);
- if (request.make_request () == -1 || request.retval () == -1)
+ __try
{
- syscall_printf ("-1 [%d] = msgsnd ()", request.error_code ());
- set_errno (request.error_code ());
- if (request.error_code () == ENOSYS)
- raise (SIGSYS);
- 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 ());
+ set_errno (request.error_code ());
+ if (request.error_code () == ENOSYS)
+ raise (SIGSYS);
+ __leave;
+ }
+ return request.retval ();
}
- return request.retval ();
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index aed92fd9f..b6c0f7257 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -500,10 +500,13 @@ dup_ent (servent *src)
extern "C" struct protoent *
cygwin_getprotobyname (const char *p)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- return dup_ent (getprotobyname (p));
+ __try
+ {
+ return dup_ent (getprotobyname (p));
+ }
+ __except (EFAULT) {}
+ __endtry
+ return NULL;
}
/* exported as getprotobynumber: standards? */
@@ -731,18 +734,18 @@ extern "C" ssize_t
cygwin_sendto (int fd, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
- ssize_t res;
+ ssize_t res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->sendto (buf, len, flags, to, tolen);
-
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->sendto (buf, len, flags, to, tolen);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%lR = sendto(%d, %p, %ld, %y, %p, %d)",
res, fd, buf, len, flags, to, tolen);
return res;
@@ -753,22 +756,22 @@ extern "C" ssize_t
cygwin_recvfrom (int fd, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
- ssize_t res;
+ ssize_t res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- /* Originally we shortcircuited here if res == 0.
- Allow 0 bytes buffer. This is valid in POSIX and handled in
- fhandler_socket::recv_internal. If we shortcircuit, we fail
- to deliver valid error conditions and peer address. */
- res = fh->recvfrom (buf, len, flags, from, fromlen);
-
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ /* Originally we shortcircuited here if res == 0.
+ Allow 0 bytes buffer. This is valid in POSIX and handled in
+ fhandler_socket::recv_internal. If we shortcircuit, we fail
+ to deliver valid error conditions and peer address. */
+ res = fh->recvfrom (buf, len, flags, from, fromlen);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%lR = recvfrom(%d, %p, %ld, %y, %p, %p)",
res, fd, buf, len, flags, from, fromlen);
return res;
@@ -800,14 +803,13 @@ extern "C" int
cygwin_setsockopt (int fd, int level, int optname, const void *optval,
socklen_t optlen)
{
- int res;
- fhandler_socket *fh = get (fd);
+ int res = -1;
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
+ __try
{
+ fhandler_socket *fh = get (fd);
+ if (!fh)
+ __leave;
/* Old applications still use the old WinSock1 IPPROTO_IP values. */
if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
optname = convert_ws1_ip_optname (optname);
@@ -892,7 +894,11 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
break;
}
}
-
+ __except (EFAULT)
+ {
+ res = -1;
+ }
+ __endtry
syscall_printf ("%R = setsockopt(%d, %d, %y, %p, %d)",
res, fd, level, optname, optval, optlen);
return res;
@@ -903,19 +909,19 @@ extern "C" int
cygwin_getsockopt (int fd, int level, int optname, void *optval,
socklen_t *optlen)
{
- int res;
- fhandler_socket *fh = get (fd);
+ int res = -1;
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else if (optname == SO_PEERCRED && level == SOL_SOCKET)
- {
- struct ucred *cred = (struct ucred *) optval;
- res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
- }
- else
+ __try
{
+ fhandler_socket *fh = get (fd);
+ if (!fh)
+ __leave;
+ if (optname == SO_PEERCRED && level == SOL_SOCKET)
+ {
+ struct ucred *cred = (struct ucred *) optval;
+ res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
+ __leave;
+ }
/* Old applications still use the old WinSock1 IPPROTO_IP values. */
if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
optname = convert_ws1_ip_optname (optname);
@@ -930,7 +936,7 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval,
*e = find_winsock_errno (*e);
}
else if (*optlen == 1)
- {
+ {
/* Regression in Vista and later: instead of a 4 byte BOOL value,
a 1 byte BOOLEAN value is returned, in contrast to older systems
and the documentation. Since an int type is expected by the
@@ -947,7 +953,11 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval,
}
}
}
-
+ __except (EFAULT)
+ {
+ res = -1;
+ }
+ __endtry
syscall_printf ("%R = getsockopt(%d, %d, %y, %p, %p)",
res, fd, level, optname, optval, optlen);
return res;
@@ -966,20 +976,19 @@ getpeereid (int fd, uid_t *euid, gid_t *egid)
extern "C" int
cygwin_connect (int fd, const struct sockaddr *name, socklen_t namelen)
{
- int res;
+ int res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->connect (name, namelen);
-
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->connect (name, namelen);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = connect(%d, %p, %d)", res, fd, name, namelen);
-
return res;
}
@@ -987,11 +996,14 @@ cygwin_connect (int fd, const struct sockaddr *name, socklen_t namelen)
extern "C" struct servent *
cygwin_getservbyname (const char *name, const char *proto)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
+ servent *res = NULL;
- servent *res = dup_ent (getservbyname (name, proto));
+ __try
+ {
+ res = dup_ent (getservbyname (name, proto));
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%p = getservbyname (%s, %s)", res, name, proto);
return res;
}
@@ -1000,11 +1012,14 @@ cygwin_getservbyname (const char *name, const char *proto)
extern "C" struct servent *
cygwin_getservbyport (int port, const char *proto)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
+ servent *res = NULL;
- servent *res = dup_ent (getservbyport (port, proto));
+ __try
+ {
+ res = dup_ent (getservbyport (port, proto));
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%p = getservbyport (%d, %s)", res, port, proto);
return res;
}
@@ -1012,67 +1027,77 @@ cygwin_getservbyport (int port, const char *proto)
extern "C" int
cygwin_gethostname (char *name, size_t len)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ int res = -1;
- if (gethostname (name, len))
+ __try
{
- DWORD local_len = len;
-
- if (!GetComputerNameExA (ComputerNameDnsFullyQualified, name, &local_len))
+ if (gethostname (name, len))
{
- set_winsock_errno ();
- return -1;
+ DWORD local_len = len;
+
+ if (!GetComputerNameExA (ComputerNameDnsFullyQualified, name,
+ &local_len))
+ {
+ set_winsock_errno ();
+ __leave;
+ }
}
+ debug_printf ("name %s", name);
+ res = 0;
}
- debug_printf ("name %s", name);
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return res;
}
/* exported as gethostbyname: standards? */
extern "C" struct hostent *
cygwin_gethostbyname (const char *name)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
-
unsigned char tmp_addr[4];
struct hostent tmp, *h;
char *tmp_aliases[1] = {0};
char *tmp_addr_list[2] = {0,0};
unsigned int a, b, c, d;
char dummy;
+ hostent *res = NULL;
- if (sscanf (name, "%u.%u.%u.%u%c", &a, &b, &c, &d, &dummy) != 4
- || a >= 256 || b >= 256 || c >= 256 || d >= 256)
- h = gethostbyname (name);
- else
+ __try
{
- /* In case you don't have DNS, at least x.x.x.x still works */
- memset (&tmp, 0, sizeof (tmp));
- tmp_addr[0] = a;
- tmp_addr[1] = b;
- tmp_addr[2] = c;
- tmp_addr[3] = d;
- tmp_addr_list[0] = (char *) tmp_addr;
- tmp.h_name = name;
- tmp.h_aliases = tmp_aliases;
- tmp.h_addrtype = 2;
- tmp.h_length = 4;
- tmp.h_addr_list = tmp_addr_list;
- h = &tmp;
- }
-
- hostent *res = dup_ent (h);
- if (res)
- debug_printf ("h_name %s", res->h_name);
- else
+ if (sscanf (name, "%u.%u.%u.%u%c", &a, &b, &c, &d, &dummy) != 4
+ || a >= 256 || b >= 256 || c >= 256 || d >= 256)
+ h = gethostbyname (name);
+ else
+ {
+ /* In case you don't have DNS, at least x.x.x.x still works */
+ memset (&tmp, 0, sizeof (tmp));
+ tmp_addr[0] = a;
+ tmp_addr[1] = b;
+ tmp_addr[2] = c;
+ tmp_addr[3] = d;
+ tmp_addr_list[0] = (char *) tmp_addr;
+ tmp.h_name = name;
+ tmp.h_aliases = tmp_aliases;
+ tmp.h_addrtype = 2;
+ tmp.h_length = 4;
+ tmp.h_addr_list = tmp_addr_list;
+ h = &tmp;
+ }
+
+ res = dup_ent (h);
+ if (res)
+ debug_printf ("h_name %s", res->h_name);
+ else
+ {
+ debug_printf ("dup_ent returned NULL for name %s, h %p", name, h);
+ set_host_errno ();
+ }
+ }
+ __except (EFAULT)
{
- debug_printf ("dup_ent returned NULL for name %s, h %p", name, h);
- set_host_errno ();
+ res = NULL;
}
+ __endtry
return res;
}
@@ -1080,15 +1105,21 @@ cygwin_gethostbyname (const char *name)
extern "C" struct hostent *
cygwin_gethostbyaddr (const char *addr, int len, int type)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
+ hostent *res = NULL;
- hostent *res = dup_ent (gethostbyaddr (addr, len, type));
- if (res)
- debug_printf ("h_name %s", res->h_name);
- else
- set_host_errno ();
+ __try
+ {
+ res = dup_ent (gethostbyaddr (addr, len, type));
+ if (res)
+ debug_printf ("h_name %s", res->h_name);
+ else
+ set_host_errno ();
+ }
+ __except (EFAULT)
+ {
+ res = NULL;
+ }
+ __endtry
return res;
}
@@ -1311,51 +1342,56 @@ gethostby_helper (const char *name, const int af, const int type,
extern "C" struct hostent *
gethostbyname2 (const char *name, int af)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
-
- if (!(_res.options & RES_INIT))
- res_init();
- bool v4to6 = _res.options & RES_USE_INET6;
+ hostent *res = NULL;
- int type, addrsize_in, addrsize_out;
- switch (af)
+ __try
{
- case AF_INET:
- addrsize_in = NS_INADDRSZ;
- addrsize_out = (v4to6) ? NS_IN6ADDRSZ : NS_INADDRSZ;
- type = ns_t_a;
- break;
- case AF_INET6:
- addrsize_in = addrsize_out = NS_IN6ADDRSZ;
- type = ns_t_aaaa;
- break;
- default:
- set_errno (EAFNOSUPPORT);
- h_errno = NETDB_INTERNAL;
- return NULL;
- }
+ if (!(_res.options & RES_INIT))
+ res_init();
+ bool v4to6 = _res.options & RES_USE_INET6;
+
+ int type, addrsize_in, addrsize_out;
+ switch (af)
+ {
+ case AF_INET:
+ addrsize_in = NS_INADDRSZ;
+ addrsize_out = (v4to6) ? NS_IN6ADDRSZ : NS_INADDRSZ;
+ type = ns_t_a;
+ break;
+ case AF_INET6:
+ addrsize_in = addrsize_out = NS_IN6ADDRSZ;
+ type = ns_t_aaaa;
+ break;
+ default:
+ set_errno (EAFNOSUPPORT);
+ h_errno = NETDB_INTERNAL;
+ __leave;
+ }
- return gethostby_helper (name, af, type, addrsize_in, addrsize_out);
+ res = gethostby_helper (name, af, type, addrsize_in, addrsize_out);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return res;
}
/* exported as accept: standards? */
extern "C" int
cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
{
- int res;
+ int res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->accept4 (peer, len, fh->is_nonblocking () ? SOCK_NONBLOCK : 0);
-
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->accept4 (peer, len,
+ fh->is_nonblocking () ? SOCK_NONBLOCK : 0);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = accept(%d, %p, %p)", res, fd, peer, len);
return res;
}
@@ -1363,23 +1399,22 @@ cygwin_accept (int fd, struct sockaddr *peer, socklen_t *len)
extern "C" int
accept4 (int fd, struct sockaddr *peer, socklen_t *len, int flags)
{
- int res;
+ int res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
+ __try
{
- set_errno (EINVAL);
- res = -1;
+ fhandler_socket *fh = get (fd);
+ if (!fh)
+ __leave;
+ if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
+ set_errno (EINVAL);
+ else
+ res = fh->accept4 (peer, len, flags);
}
- else
- res = fh->accept4 (peer, len, flags);
-
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = accept4(%d, %p, %p, %y)", res, fd, peer, len, flags);
return res;
}
@@ -1388,15 +1423,16 @@ accept4 (int fd, struct sockaddr *peer, socklen_t *len, int flags)
extern "C" int
cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen)
{
- int res;
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->bind (my_addr, addrlen);
+ int res = -1;
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->bind (my_addr, addrlen);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = bind(%d, %p, %d)", res, fd, my_addr, addrlen);
return res;
}
@@ -1405,16 +1441,16 @@ cygwin_bind (int fd, const struct sockaddr *my_addr, socklen_t addrlen)
extern "C" int
cygwin_getsockname (int fd, struct sockaddr *addr, socklen_t *namelen)
{
- int res;
-
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->getsockname (addr, namelen);
+ int res = -1;
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->getsockname (addr, namelen);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R =getsockname (%d, %p, %p)", res, fd, addr, namelen);
return res;
}
@@ -1423,14 +1459,16 @@ cygwin_getsockname (int fd, struct sockaddr *addr, socklen_t *namelen)
extern "C" int
cygwin_listen (int fd, int backlog)
{
- int res;
- fhandler_socket *fh = get (fd);
-
- if (!fh)
- res = -1;
- else
- res = fh->listen (backlog);
+ int res = -1;
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->listen (backlog);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = listen(%d, %d)", res, fd, backlog);
return res;
}
@@ -1439,15 +1477,11 @@ cygwin_listen (int fd, int backlog)
extern "C" int
cygwin_shutdown (int fd, int how)
{
- int res;
+ int res = -1;
fhandler_socket *fh = get (fd);
-
- if (!fh)
- res = -1;
- else
+ if (fh)
res = fh->shutdown (how);
-
syscall_printf ("%R = shutdown(%d, %d)", res, fd, how);
return res;
}
@@ -1469,51 +1503,54 @@ cygwin_hstrerror (int err)
extern "C" void
cygwin_herror (const char *s)
{
- myfault efault;
- if (efault.faulted ())
- return;
- if (cygheap->fdtab.not_open (2))
- return;
-
- if (s)
+ __try
{
- write (2, s, strlen (s));
- write (2, ": ", 2);
- }
+ if (cygheap->fdtab.not_open (2))
+ return;
- const char *h_errstr = cygwin_hstrerror (h_errno);
+ if (s)
+ {
+ write (2, s, strlen (s));
+ write (2, ": ", 2);
+ }
- if (!h_errstr)
- switch (h_errno)
- {
- case NETDB_INTERNAL:
- h_errstr = "Resolver internal error";
- break;
- case NETDB_SUCCESS:
- h_errstr = "Resolver error 0 (no error)";
- break;
- default:
- h_errstr = "Unknown resolver error";
- break;
- }
- write (2, h_errstr, strlen (h_errstr));
- write (2, "\n", 1);
+ const char *h_errstr = cygwin_hstrerror (h_errno);
+
+ if (!h_errstr)
+ switch (h_errno)
+ {
+ case NETDB_INTERNAL:
+ h_errstr = "Resolver internal error";
+ break;
+ case NETDB_SUCCESS:
+ h_errstr = "Resolver error 0 (no error)";
+ break;
+ default:
+ h_errstr = "Unknown resolver error";
+ break;
+ }
+ write (2, h_errstr, strlen (h_errstr));
+ write (2, "\n", 1);
+ }
+ __except (NO_ERROR) {}
+ __endtry
}
/* exported as getpeername: standards? */
extern "C" int
cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
{
- int res;
-
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->getpeername (name, len);
+ int res = -1;
+ fhandler_socket *fh = NULL;
+ __try
+ {
+ fh = get (fd);
+ if (fh)
+ res = fh->getpeername (name, len);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%R = getpeername(%d) %p", res, fd,
(fh ? fh->get_socket () : (SOCKET) -1));
return res;
@@ -1523,22 +1560,22 @@ cygwin_getpeername (int fd, struct sockaddr *name, socklen_t *len)
extern "C" ssize_t
cygwin_recv (int fd, void *buf, size_t len, int flags)
{
- ssize_t res;
+ ssize_t res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- /* Originally we shortcircuited here if res == 0.
- Allow 0 bytes buffer. This is valid in POSIX and handled in
- fhandler_socket::recv_internal. If we shortcircuit, we fail
- to deliver valid error conditions. */
- res = fh->recvfrom (buf, len, flags, NULL, NULL);
-
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ /* Originally we shortcircuited here if res == 0.
+ Allow 0 bytes buffer. This is valid in POSIX and handled in
+ fhandler_socket::recv_internal. If we shortcircuit, we fail
+ to deliver valid error conditions. */
+ res = fh->recvfrom (buf, len, flags, NULL, NULL);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%lR = recv(%d, %p, %ld, %y)", res, fd, buf, len, flags);
return res;
}
@@ -1547,18 +1584,18 @@ cygwin_recv (int fd, void *buf, size_t len, int flags)
extern "C" ssize_t
cygwin_send (int fd, const void *buf, size_t len, int flags)
{
- ssize_t res;
+ ssize_t res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
- res = fh->sendto (buf, len, flags, NULL, 0);
-
+ __try
+ {
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ res = fh->sendto (buf, len, flags, NULL, 0);
+ }
+ __except (EFAULT)
+ __endtry
syscall_printf ("%lR = send(%d, %p, %ld, %y)", res, fd, buf, len, flags);
return res;
}
@@ -1567,21 +1604,22 @@ cygwin_send (int fd, const void *buf, size_t len, int flags)
extern "C" int
getdomainname (char *domain, size_t len)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- PFIXED_INFO info = NULL;
- ULONG size = 0;
-
- if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
- && (info = (PFIXED_INFO) alloca(size))
- && GetNetworkParams(info, &size) == ERROR_SUCCESS)
+ __try
{
- strncpy(domain, info->DomainName, len);
- return 0;
+ PFIXED_INFO info = NULL;
+ ULONG size = 0;
+
+ if (GetNetworkParams(info, &size) == ERROR_BUFFER_OVERFLOW
+ && (info = (PFIXED_INFO) alloca(size))
+ && GetNetworkParams(info, &size) == ERROR_SUCCESS)
+ {
+ strncpy(domain, info->DomainName, len);
+ return 0;
+ }
+ __seterrno ();
}
- __seterrno ();
+ __except (EFAULT)
+ __endtry
return -1;
}
@@ -2176,85 +2214,88 @@ freeifaddrs (struct ifaddrs *ifp)
int
get_ifconf (struct ifconf *ifc, int what)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- /* Ensure we have space for at least one struct ifreqs, fail if not. */
- if (ifc->ifc_len < (int) sizeof (struct ifreq))
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
+ /* Ensure we have space for at least one struct ifreqs, fail if not. */
+ if (ifc->ifc_len < (int) sizeof (struct ifreq))
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
- struct ifall *ifret, *ifp;
- ifret = get_ifs (AF_INET);
- if (!ifret)
- return -1;
+ struct ifall *ifret, *ifp;
+ ifret = get_ifs (AF_INET);
+ if (!ifret)
+ __leave;
- struct sockaddr_in *sin;
- struct ifreq *ifr = ifc->ifc_req;
- int cnt = 0;
- for (ifp = ifret; ifp; ifp = (struct ifall *) ifp->ifa_ifa.ifa_next)
- {
- ++cnt;
- strcpy (ifr->ifr_name, ifp->ifa_name);
- switch (what)
+ struct sockaddr_in *sin;
+ struct ifreq *ifr = ifc->ifc_req;
+ int cnt = 0;
+ for (ifp = ifret; ifp; ifp = (struct ifall *) ifp->ifa_ifa.ifa_next)
{
- case SIOCGIFFLAGS:
- ifr->ifr_flags = ifp->ifa_ifa.ifa_flags;
- break;
- case SIOCGIFCONF:
- case SIOCGIFADDR:
- sin = (struct sockaddr_in *) &ifr->ifr_addr;
- memcpy (sin, &ifp->ifa_addr, sizeof *sin);
- break;
- case SIOCGIFNETMASK:
- sin = (struct sockaddr_in *) &ifr->ifr_netmask;
- memcpy (sin, &ifp->ifa_netmask, sizeof *sin);
- break;
- case SIOCGIFDSTADDR:
- sin = (struct sockaddr_in *) &ifr->ifr_dstaddr;
- if (ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT)
- memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
- else /* Return addr as on Linux. */
- memcpy (sin, &ifp->ifa_addr, sizeof *sin);
- break;
- case SIOCGIFBRDADDR:
- sin = (struct sockaddr_in *) &ifr->ifr_broadaddr;
- if (!(ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT))
- memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
- else
+ ++cnt;
+ strcpy (ifr->ifr_name, ifp->ifa_name);
+ switch (what)
{
- sin->sin_addr.s_addr = INADDR_ANY;
- sin->sin_family = AF_INET;
- sin->sin_port = 0;
+ case SIOCGIFFLAGS:
+ ifr->ifr_flags = ifp->ifa_ifa.ifa_flags;
+ break;
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ sin = (struct sockaddr_in *) &ifr->ifr_addr;
+ memcpy (sin, &ifp->ifa_addr, sizeof *sin);
+ break;
+ case SIOCGIFNETMASK:
+ sin = (struct sockaddr_in *) &ifr->ifr_netmask;
+ memcpy (sin, &ifp->ifa_netmask, sizeof *sin);
+ break;
+ case SIOCGIFDSTADDR:
+ sin = (struct sockaddr_in *) &ifr->ifr_dstaddr;
+ if (ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT)
+ memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
+ else /* Return addr as on Linux. */
+ memcpy (sin, &ifp->ifa_addr, sizeof *sin);
+ break;
+ case SIOCGIFBRDADDR:
+ sin = (struct sockaddr_in *) &ifr->ifr_broadaddr;
+ if (!(ifp->ifa_ifa.ifa_flags & IFF_POINTOPOINT))
+ memcpy (sin, &ifp->ifa_brddstaddr, sizeof *sin);
+ else
+ {
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_family = AF_INET;
+ sin->sin_port = 0;
+ }
+ break;
+ case SIOCGIFHWADDR:
+ memcpy (&ifr->ifr_hwaddr, &ifp->ifa_hwaddr,
+ sizeof ifr->ifr_hwaddr);
+ break;
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = ifp->ifa_metric;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = ifp->ifa_mtu;
+ break;
+ case SIOCGIFINDEX:
+ ifr->ifr_ifindex = ifp->ifa_ifindex;
+ break;
+ case SIOCGIFFRNDLYNAM:
+ memcpy (ifr->ifr_frndlyname, &ifp->ifa_frndlyname,
+ sizeof (struct ifreq_frndlyname));
}
- break;
- case SIOCGIFHWADDR:
- memcpy (&ifr->ifr_hwaddr, &ifp->ifa_hwaddr, sizeof ifr->ifr_hwaddr);
- break;
- case SIOCGIFMETRIC:
- ifr->ifr_metric = ifp->ifa_metric;
- break;
- case SIOCGIFMTU:
- ifr->ifr_mtu = ifp->ifa_mtu;
- break;
- case SIOCGIFINDEX:
- ifr->ifr_ifindex = ifp->ifa_ifindex;
- break;
- case SIOCGIFFRNDLYNAM:
- memcpy (ifr->ifr_frndlyname, &ifp->ifa_frndlyname,
- sizeof (struct ifreq_frndlyname));
+ if ((caddr_t) ++ifr >
+ ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
+ break;
}
- if ((caddr_t) ++ifr >
- ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
- break;
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+ free (ifret);
+ return 0;
}
- /* Set the correct length */
- ifc->ifc_len = cnt * sizeof (struct ifreq);
- free (ifret);
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" unsigned
@@ -2263,26 +2304,30 @@ if_nametoindex (const char *name)
PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
unsigned index = 0;
- myfault efault;
- if (efault.faulted (EFAULT))
- return 0;
-
- if (get_adapters_addresses (&pa0, AF_UNSPEC))
+ __try
{
- char lname[IF_NAMESIZE], *c;
-
- lname[0] = '\0';
- strncat (lname, name, IF_NAMESIZE - 1);
- if (lname[0] == '{' && (c = strchr (lname, ':')))
- *c = '\0';
- for (pap = pa0; pap; pap = pap->Next)
- if (strcasematch (lname, pap->AdapterName))
- {
- index = pap->Ipv6IfIndex ?: pap->IfIndex;
- break;
- }
- free (pa0);
+ if (get_adapters_addresses (&pa0, AF_UNSPEC))
+ {
+ char lname[IF_NAMESIZE], *c;
+
+ lname[0] = '\0';
+ strncat (lname, name, IF_NAMESIZE - 1);
+ if (lname[0] == '{' && (c = strchr (lname, ':')))
+ *c = '\0';
+ for (pap = pa0; pap; pap = pap->Next)
+ if (strcasematch (lname, pap->AdapterName))
+ {
+ index = pap->Ipv6IfIndex ?: pap->IfIndex;
+ break;
+ }
+ free (pa0);
+ }
+ }
+ __except (EFAULT)
+ {
+ index = 0;
}
+ __endtry
return index;
}
@@ -2292,35 +2337,38 @@ if_indextoname (unsigned ifindex, char *ifname)
PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
char *name = NULL;
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
-
- if (get_adapters_addresses (&pa0, AF_UNSPEC))
+ __try
{
- for (pap = pa0; pap; pap = pap->Next)
- if (ifindex == (pap->Ipv6IfIndex ?: pap->IfIndex))
- {
- /* Unfortunately the pre-Vista IPv6 stack has a distinct loopback
- device with the same Ipv6IfIndex as the IfIndex of the IPv4
- loopback device, but with a different adapter name.
- For consistency with /proc/net/if_inet6, try to find the
- IPv6 loopback device and use that adapter name instead.
- We identify the loopback device by its IfIndex of 1. */
- if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
- for (PIP_ADAPTER_ADDRESSES pap2 = pa0; pap2; pap2 = pap2->Next)
- if (pap2->Ipv6IfIndex == 1)
- {
- pap = pap2;
- break;
- }
- name = strcpy (ifname, pap->AdapterName);
- break;
- }
- free (pa0);
+ if (get_adapters_addresses (&pa0, AF_UNSPEC))
+ {
+ for (pap = pa0; pap; pap = pap->Next)
+ if (ifindex == (pap->Ipv6IfIndex ?: pap->IfIndex))
+ {
+ /* Unfortunately the pre-Vista IPv6 stack has a distinct
+ loopback device with the same Ipv6IfIndex as the IfIndex
+ of the IPv4 loopback device, but with a different adapter
+ name. For consistency with /proc/net/if_inet6, try to find
+ the IPv6 loopback device and use that adapter name instead.
+ We identify the loopback device by its IfIndex of 1. */
+ if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
+ for (PIP_ADAPTER_ADDRESSES pap2 = pa0;
+ pap2;
+ pap2 = pap2->Next)
+ if (pap2->Ipv6IfIndex == 1)
+ {
+ pap = pap2;
+ break;
+ }
+ name = strcpy (ifname, pap->AdapterName);
+ break;
+ }
+ free (pa0);
+ }
+ else
+ set_errno (ENXIO);
}
- else
- set_errno (ENXIO);
+ __except (EFAULT) {}
+ __endtry
return name;
}
@@ -2331,49 +2379,54 @@ if_nameindex (void)
struct if_nameindex *iflist = NULL;
char (*ifnamelist)[IF_NAMESIZE];
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
-
- if (get_adapters_addresses (&pa0, AF_UNSPEC))
+ __try
{
- int cnt = 0;
- for (pap = pa0; pap; pap = pap->Next)
- ++cnt;
- iflist = (struct if_nameindex *)
- malloc ((cnt + 1) * sizeof (struct if_nameindex)
- + cnt * IF_NAMESIZE);
- if (!iflist)
- set_errno (ENOBUFS);
- else
+ if (get_adapters_addresses (&pa0, AF_UNSPEC))
{
- ifnamelist = (char (*)[IF_NAMESIZE]) (iflist + cnt + 1);
- for (pap = pa0, cnt = 0; pap; pap = pap->Next)
+ int cnt = 0;
+ for (pap = pa0; pap; pap = pap->Next)
+ ++cnt;
+ iflist = (struct if_nameindex *)
+ malloc ((cnt + 1) * sizeof (struct if_nameindex)
+ + cnt * IF_NAMESIZE);
+ if (!iflist)
+ set_errno (ENOBUFS);
+ else
{
- for (int i = 0; i < cnt; ++i)
- if (iflist[i].if_index == (pap->Ipv6IfIndex ?: pap->IfIndex))
- goto outer_loop;
- iflist[cnt].if_index = pap->Ipv6IfIndex ?: pap->IfIndex;
- strcpy (iflist[cnt].if_name = ifnamelist[cnt], pap->AdapterName);
- /* See comment in if_indextoname. */
- if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
- for (PIP_ADAPTER_ADDRESSES pap2 = pa0; pap2; pap2 = pap2->Next)
- if (pap2->Ipv6IfIndex == 1)
- {
- strcpy (ifnamelist[cnt], pap2->AdapterName);
- break;
- }
- ++cnt;
- outer_loop:
- ;
+ ifnamelist = (char (*)[IF_NAMESIZE]) (iflist + cnt + 1);
+ for (pap = pa0, cnt = 0; pap; pap = pap->Next)
+ {
+ for (int i = 0; i < cnt; ++i)
+ if (iflist[i].if_index
+ == (pap->Ipv6IfIndex ?: pap->IfIndex))
+ goto outer_loop;
+ iflist[cnt].if_index = pap->Ipv6IfIndex ?: pap->IfIndex;
+ strcpy (iflist[cnt].if_name = ifnamelist[cnt],
+ pap->AdapterName);
+ /* See comment in if_indextoname. */
+ if (pap->IfIndex == 1 && pap->Ipv6IfIndex == 0)
+ for (PIP_ADAPTER_ADDRESSES pap2 = pa0;
+ pap2;
+ pap2 = pap2->Next)
+ if (pap2->Ipv6IfIndex == 1)
+ {
+ strcpy (ifnamelist[cnt], pap2->AdapterName);
+ break;
+ }
+ ++cnt;
+ outer_loop:
+ ;
+ }
+ iflist[cnt].if_index = 0;
+ iflist[cnt].if_name = NULL;
}
- iflist[cnt].if_index = 0;
- iflist[cnt].if_name = NULL;
+ free (pa0);
}
- free (pa0);
+ else
+ set_errno (ENXIO);
}
- else
- set_errno (ENXIO);
+ __except (EFAULT) {}
+ __endtry
return iflist;
}
@@ -2395,72 +2448,75 @@ cygwin_bindresvport_sa (int fd, struct sockaddr *sa)
struct sockaddr_in6 *sin6 = NULL;
in_port_t port;
socklen_t salen;
- int ret;
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- fhandler_socket *fh = get (fd);
- if (!fh)
- return -1;
+ int ret = -1;
- if (!sa)
+ __try
{
- sa = (struct sockaddr *) &sst;
- memset (&sst, 0, sizeof sst);
- sa->sa_family = fh->get_addr_family ();
- }
+ fhandler_socket *fh = get (fd);
+ if (!fh)
+ __leave;
- switch (sa->sa_family)
- {
- case AF_INET:
- salen = sizeof (struct sockaddr_in);
- sin = (struct sockaddr_in *) sa;
- port = sin->sin_port;
- break;
- case AF_INET6:
- salen = sizeof (struct sockaddr_in6);
- sin6 = (struct sockaddr_in6 *) sa;
- port = sin6->sin6_port;
- break;
- default:
- set_errno (EPFNOSUPPORT);
- return -1;
- }
+ if (!sa)
+ {
+ sa = (struct sockaddr *) &sst;
+ memset (&sst, 0, sizeof sst);
+ sa->sa_family = fh->get_addr_family ();
+ }
- /* If a non-zero port number is given, try this first. If that succeeds,
- or if the error message is serious, return. */
- if (port)
- {
- ret = fh->bind (sa, salen);
- if (!ret || (get_errno () != EADDRINUSE && get_errno () != EINVAL))
- return ret;
- }
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ salen = sizeof (struct sockaddr_in);
+ sin = (struct sockaddr_in *) sa;
+ port = sin->sin_port;
+ break;
+ case AF_INET6:
+ salen = sizeof (struct sockaddr_in6);
+ sin6 = (struct sockaddr_in6 *) sa;
+ port = sin6->sin6_port;
+ break;
+ default:
+ set_errno (EPFNOSUPPORT);
+ __leave;
+ }
- LONG myport;
+ /* If a non-zero port number is given, try this first. If that succeeds,
+ or if the error message is serious, return. */
+ if (port)
+ {
+ ret = fh->bind (sa, salen);
+ if (!ret || (get_errno () != EADDRINUSE && get_errno () != EINVAL))
+ __leave;
+ }
- for (int i = 0; i < NUM_PORTS; i++)
- {
- while ((myport = InterlockedExchange (&cygwin_shared->last_used_bindresvport, -1)) == -1)
- yield ();
- if (myport == 0 || --myport < PORT_LOW)
- myport = PORT_HIGH;
- InterlockedExchange (&cygwin_shared->last_used_bindresvport, myport);
+ LONG myport;
- if (sa->sa_family == AF_INET6)
- sin6->sin6_port = htons (myport);
- else
- sin->sin_port = htons (myport);
- if (!(ret = fh->bind (sa, salen)))
- break;
- if (get_errno () != EADDRINUSE && get_errno () != EINVAL)
- break;
- }
+ for (int i = 0; i < NUM_PORTS; i++)
+ {
+ while ((myport = InterlockedExchange (
+ &cygwin_shared->last_used_bindresvport, -1)) == -1)
+ yield ();
+ if (myport == 0 || --myport < PORT_LOW)
+ myport = PORT_HIGH;
+ InterlockedExchange (&cygwin_shared->last_used_bindresvport, myport);
+
+ if (sa->sa_family == AF_INET6)
+ sin6->sin6_port = htons (myport);
+ else
+ sin->sin_port = htons (myport);
+ if (!(ret = fh->bind (sa, salen)))
+ break;
+ if (get_errno () != EADDRINUSE && get_errno () != EINVAL)
+ break;
+ }
+ }
+ __except (EFAULT) {}
+ __endtry
return ret;
}
+
extern "C" int
cygwin_bindresvport (int fd, struct sockaddr_in *sin)
{
@@ -2473,204 +2529,195 @@ extern "C" int
socketpair (int family, int type, int protocol, int *sb)
{
int res = -1;
- SOCKET insock, outsock, newsock;
+ SOCKET insock = INVALID_SOCKET;
+ SOCKET outsock = INVALID_SOCKET;
+ SOCKET newsock = INVALID_SOCKET;
struct sockaddr_in sock_in, sock_out;
int len;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- int flags = type & _SOCK_FLAG_MASK;
- type &= ~_SOCK_FLAG_MASK;
-
- if (family != AF_LOCAL && family != AF_INET)
- {
- set_errno (EAFNOSUPPORT);
- goto done;
- }
- if (type != SOCK_STREAM && type != SOCK_DGRAM)
- {
- set_errno (EPROTOTYPE);
- goto done;
- }
- if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
+ __try
{
- set_errno (EINVAL);
- goto done;
- }
- if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
- || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
- {
- set_errno (EPROTONOSUPPORT);
- goto done;
- }
+ int flags = type & _SOCK_FLAG_MASK;
+ type &= ~_SOCK_FLAG_MASK;
- /* create the first socket */
- newsock = socket (AF_INET, type, 0);
- if (newsock == INVALID_SOCKET)
- {
- debug_printf ("first socket call failed");
- set_winsock_errno ();
- goto done;
- }
-
- /* bind the socket to any unused port */
- sock_in.sin_family = AF_INET;
- sock_in.sin_port = 0;
- sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
- {
- debug_printf ("bind failed");
- set_winsock_errno ();
- closesocket (newsock);
- goto done;
- }
- len = sizeof (sock_in);
- if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
- {
- debug_printf ("getsockname error");
- set_winsock_errno ();
- closesocket (newsock);
- goto done;
- }
-
- /* For stream sockets, create a listener */
- if (type == SOCK_STREAM)
- listen (newsock, 2);
+ if (family != AF_LOCAL && family != AF_INET)
+ {
+ set_errno (EAFNOSUPPORT);
+ __leave;
+ }
+ if (type != SOCK_STREAM && type != SOCK_DGRAM)
+ {
+ set_errno (EPROTOTYPE);
+ __leave;
+ }
+ if ((flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) != 0)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ if ((family == AF_LOCAL && protocol != PF_UNSPEC && protocol != PF_LOCAL)
+ || (family == AF_INET && protocol != PF_UNSPEC && protocol != PF_INET))
+ {
+ set_errno (EPROTONOSUPPORT);
+ __leave;
+ }
- /* create a connecting socket */
- outsock = socket (AF_INET, type, 0);
- if (outsock == INVALID_SOCKET)
- {
- debug_printf ("second socket call failed");
- set_winsock_errno ();
- closesocket (newsock);
- goto done;
- }
+ /* create the first socket */
+ newsock = socket (AF_INET, type, 0);
+ if (newsock == INVALID_SOCKET)
+ {
+ debug_printf ("first socket call failed");
+ set_winsock_errno ();
+ __leave;
+ }
- /* For datagram sockets, bind the 2nd socket to an unused address, too */
- if (type == SOCK_DGRAM)
- {
- sock_out.sin_family = AF_INET;
- sock_out.sin_port = 0;
- sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
+ /* bind the socket to any unused port */
+ sock_in.sin_family = AF_INET;
+ sock_in.sin_port = 0;
+ sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
{
debug_printf ("bind failed");
set_winsock_errno ();
- closesocket (newsock);
- closesocket (outsock);
- goto done;
+ __leave;
}
- len = sizeof (sock_out);
- if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
+ len = sizeof (sock_in);
+ if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
{
debug_printf ("getsockname error");
set_winsock_errno ();
- closesocket (newsock);
- closesocket (outsock);
- goto done;
+ __leave;
}
- }
- /* Force IP address to loopback */
- sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- if (type == SOCK_DGRAM)
- sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ /* For stream sockets, create a listener */
+ if (type == SOCK_STREAM)
+ listen (newsock, 2);
- /* Do a connect */
- if (connect (outsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
- {
- debug_printf ("connect error");
- set_winsock_errno ();
- closesocket (newsock);
- closesocket (outsock);
- goto done;
- }
-
- if (type == SOCK_STREAM)
- {
- /* For stream sockets, accept the connection and close the listener */
- len = sizeof (sock_in);
- insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
- if (insock == INVALID_SOCKET)
+ /* create a connecting socket */
+ outsock = socket (AF_INET, type, 0);
+ if (outsock == INVALID_SOCKET)
{
- debug_printf ("accept error");
+ debug_printf ("second socket call failed");
set_winsock_errno ();
- closesocket (newsock);
- closesocket (outsock);
- goto done;
+ __leave;
}
- closesocket (newsock);
- }
- else
- {
- /* For datagram sockets, connect the 2nd socket */
- if (connect (newsock, (struct sockaddr *) &sock_out,
- sizeof (sock_out)) < 0)
+
+ /* For datagram sockets, bind the 2nd socket to an unused address, too */
+ if (type == SOCK_DGRAM)
{
- debug_printf ("connect error");
- set_winsock_errno ();
- closesocket (newsock);
- closesocket (outsock);
- goto done;
+ sock_out.sin_family = AF_INET;
+ sock_out.sin_port = 0;
+ sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (bind (outsock, (struct sockaddr *) &sock_out, sizeof (sock_out)) < 0)
+ {
+ debug_printf ("bind failed");
+ set_winsock_errno ();
+ __leave;
+ }
+ len = sizeof (sock_out);
+ if (getsockname (outsock, (struct sockaddr *) &sock_out, &len) < 0)
+ {
+ debug_printf ("getsockname error");
+ set_winsock_errno ();
+ __leave;
+ }
}
- insock = newsock;
- }
- {
- cygheap_fdnew sb0;
- const device *dev;
+ /* Force IP address to loopback */
+ sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+ if (type == SOCK_DGRAM)
+ sock_out.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
- if (family == AF_INET)
- dev = (type == SOCK_STREAM ? tcp_dev : udp_dev);
- else
- dev = (type == SOCK_STREAM ? stream_dev : dgram_dev);
+ /* Do a connect */
+ if (connect (outsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
+ {
+ debug_printf ("connect error");
+ set_winsock_errno ();
+ __leave;
+ }
- if (sb0 >= 0 && fdsock (sb0, dev, insock))
- {
- ((fhandler_socket *) sb0)->set_addr_family (family);
- ((fhandler_socket *) sb0)->set_socket_type (type);
- ((fhandler_socket *) sb0)->connect_state (connected);
- if (flags & SOCK_NONBLOCK)
- ((fhandler_socket *) sb0)->set_nonblocking (true);
- if (flags & SOCK_CLOEXEC)
- ((fhandler_socket *) sb0)->set_close_on_exec (true);
- if (family == AF_LOCAL && type == SOCK_STREAM)
- ((fhandler_socket *) sb0)->af_local_set_sockpair_cred ();
+ if (type == SOCK_STREAM)
+ {
+ /* For stream sockets, accept the connection and close the listener */
+ len = sizeof (sock_in);
+ insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
+ if (insock == INVALID_SOCKET)
+ {
+ debug_printf ("accept error");
+ set_winsock_errno ();
+ __leave;
+ }
+ closesocket (newsock);
+ newsock = INVALID_SOCKET;
+ }
+ else
+ {
+ /* For datagram sockets, connect the 2nd socket */
+ if (connect (newsock, (struct sockaddr *) &sock_out,
+ sizeof (sock_out)) < 0)
+ {
+ debug_printf ("connect error");
+ set_winsock_errno ();
+ __leave;
+ }
+ insock = newsock;
+ newsock = INVALID_SOCKET;
+ }
- cygheap_fdnew sb1 (sb0, false);
+ cygheap_fdnew sb0;
+ const device *dev;
- if (sb1 >= 0 && fdsock (sb1, dev, outsock))
- {
- ((fhandler_socket *) sb1)->set_addr_family (family);
- ((fhandler_socket *) sb1)->set_socket_type (type);
- ((fhandler_socket *) sb1)->connect_state (connected);
- if (flags & SOCK_NONBLOCK)
- ((fhandler_socket *) sb1)->set_nonblocking (true);
- if (flags & SOCK_CLOEXEC)
- ((fhandler_socket *) sb1)->set_close_on_exec (true);
- if (family == AF_LOCAL && type == SOCK_STREAM)
- ((fhandler_socket *) sb1)->af_local_set_sockpair_cred ();
-
- sb[0] = sb0;
- sb[1] = sb1;
- res = 0;
- }
- else
- sb0.release ();
- }
+ if (family == AF_INET)
+ dev = (type == SOCK_STREAM ? tcp_dev : udp_dev);
+ else
+ dev = (type == SOCK_STREAM ? stream_dev : dgram_dev);
- if (res == -1)
- {
+ if (sb0 >= 0 && fdsock (sb0, dev, insock))
+ {
+ ((fhandler_socket *) sb0)->set_addr_family (family);
+ ((fhandler_socket *) sb0)->set_socket_type (type);
+ ((fhandler_socket *) sb0)->connect_state (connected);
+ if (flags & SOCK_NONBLOCK)
+ ((fhandler_socket *) sb0)->set_nonblocking (true);
+ if (flags & SOCK_CLOEXEC)
+ ((fhandler_socket *) sb0)->set_close_on_exec (true);
+ if (family == AF_LOCAL && type == SOCK_STREAM)
+ ((fhandler_socket *) sb0)->af_local_set_sockpair_cred ();
+
+ cygheap_fdnew sb1 (sb0, false);
+
+ if (sb1 >= 0 && fdsock (sb1, dev, outsock))
+ {
+ ((fhandler_socket *) sb1)->set_addr_family (family);
+ ((fhandler_socket *) sb1)->set_socket_type (type);
+ ((fhandler_socket *) sb1)->connect_state (connected);
+ if (flags & SOCK_NONBLOCK)
+ ((fhandler_socket *) sb1)->set_nonblocking (true);
+ if (flags & SOCK_CLOEXEC)
+ ((fhandler_socket *) sb1)->set_close_on_exec (true);
+ if (family == AF_LOCAL && type == SOCK_STREAM)
+ ((fhandler_socket *) sb1)->af_local_set_sockpair_cred ();
+
+ sb[0] = sb0;
+ sb[1] = sb1;
+ res = 0;
+ }
+ else
+ sb0.release ();
+ }
+ }
+ __except (EFAULT) {}
+ __endtry
+ syscall_printf ("%R = socketpair(...)", res);
+ if (res == -1)
+ {
+ if (insock != INVALID_SOCKET)
closesocket (insock);
+ if (outsock != INVALID_SOCKET)
closesocket (outsock);
- }
- }
-
-done:
- syscall_printf ("%R = socketpair(...)", res);
+ if (newsock != INVALID_SOCKET)
+ closesocket (newsock);
+ }
return res;
}
@@ -2690,26 +2737,29 @@ endhostent (void)
extern "C" ssize_t
cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
{
- ssize_t res;
+ ssize_t res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
+ __try
{
- res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
- /* Originally we shortcircuited here if res == 0.
- Allow 0 bytes buffer. This is valid in POSIX and handled in
- fhandler_socket::recv_internal. If we shortcircuit, we fail
- to deliver valid error conditions and peer address. */
- if (res >= 0)
- res = fh->recvmsg (msg, flags);
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ {
+ res = check_iovec_for_read (msg->msg_iov, msg->msg_iovlen);
+ /* Originally we shortcircuited here if res == 0.
+ Allow 0 bytes buffer. This is valid in POSIX and handled in
+ fhandler_socket::recv_internal. If we shortcircuit, we fail
+ to deliver valid error conditions and peer address. */
+ if (res >= 0)
+ res = fh->recvmsg (msg, flags);
+ }
}
-
+ __except (EFAULT)
+ {
+ res = -1;
+ }
+ __endtry
syscall_printf ("%lR = recvmsg(%d, %p, %y)", res, fd, msg, flags);
return res;
}
@@ -2718,22 +2768,25 @@ cygwin_recvmsg (int fd, struct msghdr *msg, int flags)
extern "C" ssize_t
cygwin_sendmsg (int fd, const struct msghdr *msg, int flags)
{
- ssize_t res;
+ ssize_t res = -1;
pthread_testcancel ();
- fhandler_socket *fh = get (fd);
-
- myfault efault;
- if (efault.faulted (EFAULT) || !fh)
- res = -1;
- else
+ __try
{
- res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
- if (res >= 0)
- res = fh->sendmsg (msg, flags);
+ fhandler_socket *fh = get (fd);
+ if (fh)
+ {
+ res = check_iovec_for_write (msg->msg_iov, msg->msg_iovlen);
+ if (res >= 0)
+ res = fh->sendmsg (msg, flags);
+ }
}
-
+ __except (EFAULT)
+ {
+ res = -1;
+ }
+ __endtry
syscall_printf ("%lR = sendmsg(%d, %p, %y)", res, fd, msg, flags);
return res;
}
@@ -3108,10 +3161,6 @@ cygwin_freeaddrinfo (struct addrinfo *addr)
{
struct addrinfo *ai, *ainext;
- myfault efault;
- if (efault.faulted (EFAULT))
- return;
-
for (ai = addr; ai != NULL; ai = ainext)
{
if (ai->ai_addr != NULL)
@@ -3287,9 +3336,8 @@ extern "C" int
cygwin_getaddrinfo (const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return EAI_SYSTEM;
+ int ret = 0;
+
/* Windows' getaddrinfo implementations lets all possible values
in ai_flags slip through and just ignores unknown values. So we
check manually here. */
@@ -3300,140 +3348,148 @@ cygwin_getaddrinfo (const char *hostname, const char *servname,
#ifndef AI_DISABLE_IDN_ENCODING
#define AI_DISABLE_IDN_ENCODING 0x80000
#endif
- if (hints && (hints->ai_flags
- & ~(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_ALL
- | AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED
- | AI_IDN_MASK)))
- return EAI_BADFLAGS;
- /* AI_NUMERICSERV is not supported prior to Windows Vista. We just check
- the servname parameter by ourselves here. */
- if (hints && (hints->ai_flags & AI_NUMERICSERV))
- {
- char *p;
- if (servname && *servname && (strtoul (servname, &p, 10), *p))
- return EAI_NONAME;
- }
-
- int idn_flags = hints ? (hints->ai_flags & AI_IDN_MASK) : 0;
- const char *src;
- mbstate_t ps;
- tmp_pathbuf tp;
- wchar_t *whost = NULL, *wserv = NULL;
- struct addrinfoW whints, *wres;
-
- if (hostname)
- {
- memset (&ps, 0, sizeof ps);
- src = hostname;
- whost = tp.w_get ();
- if (mbsrtowcs (whost, &src, NT_MAX_PATH, &ps) == (size_t) -1)
- return EAI_IDN_ENCODE;
- if (src)
- return EAI_MEMORY;
- if (idn_flags & AI_IDN)
+ __try
+ {
+ if (hints && (hints->ai_flags
+ & ~(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_ALL
+ | AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED
+ | AI_IDN_MASK)))
+ return EAI_BADFLAGS;
+ /* AI_NUMERICSERV is not supported prior to Windows Vista. We just check
+ the servname parameter by ourselves here. */
+ if (hints && (hints->ai_flags & AI_NUMERICSERV))
{
- /* Map flags to equivalent IDN_* flags. */
- wchar_t *ascbuf = tp.w_get ();
- if (IdnToAscii (idn_flags >> 16, whost, -1, ascbuf, NT_MAX_PATH))
- whost = ascbuf;
- else if (GetLastError () != ERROR_PROC_NOT_FOUND)
+ char *p;
+ if (servname && *servname && (strtoul (servname, &p, 10), *p))
+ return EAI_NONAME;
+ }
+
+ int idn_flags = hints ? (hints->ai_flags & AI_IDN_MASK) : 0;
+ const char *src;
+ mbstate_t ps;
+ tmp_pathbuf tp;
+ wchar_t *whost = NULL, *wserv = NULL;
+ struct addrinfoW whints, *wres;
+
+ if (hostname)
+ {
+ memset (&ps, 0, sizeof ps);
+ src = hostname;
+ whost = tp.w_get ();
+ if (mbsrtowcs (whost, &src, NT_MAX_PATH, &ps) == (size_t) -1)
return EAI_IDN_ENCODE;
+ if (src)
+ return EAI_MEMORY;
+ if (idn_flags & AI_IDN)
+ {
+ /* Map flags to equivalent IDN_* flags. */
+ wchar_t *ascbuf = tp.w_get ();
+ if (IdnToAscii (idn_flags >> 16, whost, -1, ascbuf, NT_MAX_PATH))
+ whost = ascbuf;
+ else if (GetLastError () != ERROR_PROC_NOT_FOUND)
+ return EAI_IDN_ENCODE;
+ }
+ }
+ if (servname)
+ {
+ memset (&ps, 0, sizeof ps);
+ src = servname;
+ wserv = tp.w_get ();
+ if (mbsrtowcs (wserv, &src, NT_MAX_PATH, &ps) == (size_t) -1)
+ return EAI_IDN_ENCODE;
+ if (src)
+ return EAI_MEMORY;
}
- }
- if (servname)
- {
- memset (&ps, 0, sizeof ps);
- src = servname;
- wserv = tp.w_get ();
- if (mbsrtowcs (wserv, &src, NT_MAX_PATH, &ps) == (size_t) -1)
- return EAI_IDN_ENCODE;
- if (src)
- return EAI_MEMORY;
- }
- if (!hints)
- {
- /* Default settings per glibc man page. */
- memset (&whints, 0, sizeof whints);
- whints.ai_family = PF_UNSPEC;
- whints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
- }
- else
- {
- /* sizeof addrinfo == sizeof addrinfoW */
- memcpy (&whints, hints, sizeof whints);
- whints.ai_flags &= ~AI_IDN_MASK;
-#ifdef __x86_64__
- /* ai_addrlen is socklen_t (4 bytes) in POSIX but size_t (8 bytes) in
- Winsock. Sert upper 4 bytes explicitely to 0 to avoid EAI_FAIL. */
- whints.ai_addrlen &= UINT32_MAX;
-#endif
- /* AI_ADDRCONFIG is not supported prior to Vista. Rather it's
- the default and only possible setting.
- On Vista, the default behaviour is as if AI_ADDRCONFIG is set,
- apparently for performance reasons. To get the POSIX default
- behaviour, the AI_ALL flag has to be set. */
- if (wincap.supports_all_posix_ai_flags ()
- && whints.ai_family == PF_UNSPEC
- && !(whints.ai_flags & AI_ADDRCONFIG))
- whints.ai_flags |= AI_ALL;
- }
- /* Disable automatic IDN conversion on W8 and later. */
- whints.ai_flags |= AI_DISABLE_IDN_ENCODING;
- int ret = w32_to_gai_err (GetAddrInfoW (whost, wserv, &whints, &wres));
- /* Always copy over to self-allocated memory. */
- if (!ret)
- {
- *res = ga_duplist (wres, false, idn_flags, ret);
- FreeAddrInfoW (wres);
- if (!*res)
- return ret;
- }
- /* AI_V4MAPPED and AI_ALL are not supported prior to Vista. So, what
- we do here is to emulate AI_V4MAPPED. If no IPv6 addresses are
- returned, or the AI_ALL flag is set, we try with AF_INET again, and
- convert the returned IPv4 addresses into v4-in-v6 entries. This
- is done in ga_dup if the v4mapped flag is set. */
- if (!wincap.supports_all_posix_ai_flags ()
- && hints
- && hints->ai_family == AF_INET6
- && (hints->ai_flags & AI_V4MAPPED)
- && (ret == EAI_NODATA || ret == EAI_NONAME
- || (hints->ai_flags & AI_ALL)))
- {
- /* sizeof addrinfo == sizeof addrinfoW */
- memcpy (&whints, hints, sizeof whints);
- whints.ai_family = AF_INET;
+ if (!hints)
+ {
+ /* Default settings per glibc man page. */
+ memset (&whints, 0, sizeof whints);
+ whints.ai_family = PF_UNSPEC;
+ whints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
+ }
+ else
+ {
+ /* sizeof addrinfo == sizeof addrinfoW */
+ memcpy (&whints, hints, sizeof whints);
+ whints.ai_flags &= ~AI_IDN_MASK;
#ifdef __x86_64__
- /* ai_addrlen is socklen_t (4 bytes) in POSIX but size_t (8 bytes) in
- Winsock. Sert upper 4 bytes explicitely to 0 to avoid EAI_FAIL. */
- whints.ai_addrlen &= UINT32_MAX;
+ /* ai_addrlen is socklen_t (4 bytes) in POSIX but size_t (8 bytes) in
+ Winsock. Sert upper 4 bytes explicitely to 0 to avoid EAI_FAIL. */
+ whints.ai_addrlen &= UINT32_MAX;
#endif
- int ret2 = w32_to_gai_err (GetAddrInfoW (whost, wserv, &whints, &wres));
- if (!ret2)
+ /* AI_ADDRCONFIG is not supported prior to Vista. Rather it's
+ the default and only possible setting.
+ On Vista, the default behaviour is as if AI_ADDRCONFIG is set,
+ apparently for performance reasons. To get the POSIX default
+ behaviour, the AI_ALL flag has to be set. */
+ if (wincap.supports_all_posix_ai_flags ()
+ && whints.ai_family == PF_UNSPEC
+ && !(whints.ai_flags & AI_ADDRCONFIG))
+ whints.ai_flags |= AI_ALL;
+ }
+ /* Disable automatic IDN conversion on W8 and later. */
+ whints.ai_flags |= AI_DISABLE_IDN_ENCODING;
+ ret = w32_to_gai_err (GetAddrInfoW (whost, wserv, &whints, &wres));
+ /* Always copy over to self-allocated memory. */
+ if (!ret)
{
- struct addrinfo *v4res = ga_duplist (wres, true, idn_flags, ret);
+ *res = ga_duplist (wres, false, idn_flags, ret);
FreeAddrInfoW (wres);
- if (!v4res)
+ if (!*res)
+ __leave;
+ }
+ /* AI_V4MAPPED and AI_ALL are not supported prior to Vista. So, what
+ we do here is to emulate AI_V4MAPPED. If no IPv6 addresses are
+ returned, or the AI_ALL flag is set, we try with AF_INET again, and
+ convert the returned IPv4 addresses into v4-in-v6 entries. This
+ is done in ga_dup if the v4mapped flag is set. */
+ if (!wincap.supports_all_posix_ai_flags ()
+ && hints
+ && hints->ai_family == AF_INET6
+ && (hints->ai_flags & AI_V4MAPPED)
+ && (ret == EAI_NODATA || ret == EAI_NONAME
+ || (hints->ai_flags & AI_ALL)))
+ {
+ /* sizeof addrinfo == sizeof addrinfoW */
+ memcpy (&whints, hints, sizeof whints);
+ whints.ai_family = AF_INET;
+#ifdef __x86_64__
+ /* ai_addrlen is socklen_t (4 bytes) in POSIX but size_t (8 bytes) in
+ Winsock. Sert upper 4 bytes explicitely to 0 to avoid EAI_FAIL. */
+ whints.ai_addrlen &= UINT32_MAX;
+#endif
+ int ret2 = w32_to_gai_err (GetAddrInfoW (whost, wserv, &whints, &wres));
+ if (!ret2)
{
+ struct addrinfo *v4res = ga_duplist (wres, true, idn_flags, ret);
+ FreeAddrInfoW (wres);
+ if (!v4res)
+ {
+ if (!ret)
+ cygwin_freeaddrinfo (*res);
+ __leave;
+ }
+ /* If a list of v6 addresses exists, append the v4-in-v6 address
+ list. Otherwise just return the v4-in-v6 address list. */
if (!ret)
- cygwin_freeaddrinfo (*res);
- return ret;
- }
- /* If a list of v6 addresses exists, append the v4-in-v6 address
- list. Otherwise just return the v4-in-v6 address list. */
- if (!ret)
- {
- struct addrinfo *ptr;
- for (ptr = *res; ptr->ai_next; ptr = ptr->ai_next)
- ;
- ptr->ai_next = v4res;
+ {
+ struct addrinfo *ptr;
+ for (ptr = *res; ptr->ai_next; ptr = ptr->ai_next)
+ ;
+ ptr->ai_next = v4res;
+ }
+ else
+ *res = v4res;
+ ret = 0;
}
- else
- *res = v4res;
- ret = 0;
}
}
+ __except (EFAULT)
+ {
+ ret = EAI_SYSTEM;
+ }
+ __endtry
return ret;
}
@@ -3442,89 +3498,98 @@ cygwin_getnameinfo (const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen, char *serv,
size_t servlen, int flags)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return EAI_SYSTEM;
+ int ret = 0;
- /* When the incoming port number does not resolve to a well-known service,
- WinSock's getnameinfo up to Windows 2003 returns with error WSANO_DATA
- instead of setting `serv' to the numeric port number string, as required
- by RFC 3493. This is fixed on Vista and later. To avoid the error on
- systems up to Windows 2003, we check if the port number resolves
- to a well-known service. If not, we set the NI_NUMERICSERV flag. */
- if (!wincap.supports_all_posix_ai_flags ())
+ __try
{
- int port = 0;
-
- switch (sa->sa_family)
+ /* When the incoming port number does not resolve to a well-known service,
+ WinSock's getnameinfo up to Windows 2003 returns with error WSANO_DATA
+ instead of setting `serv' to the numeric port number string, as
+ required by RFC 3493. This is fixed on Vista and later. To avoid the
+ error on systems up to Windows 2003, we check if the port number
+ resolves to a well-known service. If not, we set the NI_NUMERICSERV
+ flag. */
+ if (!wincap.supports_all_posix_ai_flags ())
{
- case AF_INET:
- port = ((struct sockaddr_in *) sa)->sin_port;
- break;
- case AF_INET6:
- port = ((struct sockaddr_in6 *) sa)->sin6_port;
- break;
+ int port = 0;
+
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ port = ((struct sockaddr_in *) sa)->sin_port;
+ break;
+ case AF_INET6:
+ port = ((struct sockaddr_in6 *) sa)->sin6_port;
+ break;
+ default:
+ return EAI_FAMILY;
+ }
+ if (!port || !getservbyport (port, flags & NI_DGRAM ? "udp" : "tcp"))
+ flags |= NI_NUMERICSERV;
}
- if (!port || !getservbyport (port, flags & NI_DGRAM ? "udp" : "tcp"))
- flags |= NI_NUMERICSERV;
- }
- /* We call GetNameInfoW with local buffers and convert to locale
- charset to allow RFC 3490 IDNs like glibc 2.3.4 and later. */
+ /* We call GetNameInfoW with local buffers and convert to locale
+ charset to allow RFC 3490 IDNs like glibc 2.3.4 and later. */
#define NI_IDN_MASK (NI_IDN | \
NI_IDN_ALLOW_UNASSIGNED | \
NI_IDN_USE_STD3_ASCII_RULES)
- int idn_flags = flags & NI_IDN_MASK;
- flags &= ~NI_IDN_MASK;
- tmp_pathbuf tp;
- wchar_t *whost = NULL, *wserv = NULL;
- DWORD whlen = 0, wslen = 0;
+ int idn_flags = flags & NI_IDN_MASK;
+ flags &= ~NI_IDN_MASK;
+ tmp_pathbuf tp;
+ wchar_t *whost = NULL, *wserv = NULL;
+ DWORD whlen = 0, wslen = 0;
- if (host && hostlen)
- {
- whost = tp.w_get ();
- whlen = NT_MAX_PATH;
- }
- if (serv && servlen)
- {
- wserv = tp.w_get ();
- wslen = NT_MAX_PATH;
- }
+ if (host && hostlen)
+ {
+ whost = tp.w_get ();
+ whlen = NT_MAX_PATH;
+ }
+ if (serv && servlen)
+ {
+ wserv = tp.w_get ();
+ wslen = NT_MAX_PATH;
+ }
- int ret = w32_to_gai_err (GetNameInfoW (sa, salen, whost, whlen,
+ ret = w32_to_gai_err (GetNameInfoW (sa, salen, whost, whlen,
wserv, wslen, flags));
- if (!ret)
- {
- const wchar_t *src;
-
- if (whost)
+ if (!ret)
{
- if (idn_flags & NI_IDN)
+ const wchar_t *src;
+
+ if (whost)
{
- /* Map flags to equivalent IDN_* flags. */
- wchar_t *idnbuf = tp.w_get ();
- if (IdnToUnicode (idn_flags >> 16, whost, -1,
- idnbuf, NT_MAX_PATH))
- whost = idnbuf;
- else if (GetLastError () != ERROR_PROC_NOT_FOUND)
+ if (idn_flags & NI_IDN)
+ {
+ /* Map flags to equivalent IDN_* flags. */
+ wchar_t *idnbuf = tp.w_get ();
+ if (IdnToUnicode (idn_flags >> 16, whost, -1,
+ idnbuf, NT_MAX_PATH))
+ whost = idnbuf;
+ else if (GetLastError () != ERROR_PROC_NOT_FOUND)
+ return EAI_IDN_ENCODE;
+ }
+ src = whost;
+ if (wcsrtombs (host, &src, hostlen, NULL) == (size_t) -1)
return EAI_IDN_ENCODE;
+ if (src)
+ return EAI_OVERFLOW;
+ }
+ if (wserv)
+ {
+ src = wserv;
+ if (wcsrtombs (serv, &src, servlen, NULL) == (size_t) -1)
+ return EAI_IDN_ENCODE;
+ if (src)
+ return EAI_OVERFLOW;
}
- src = whost;
- if (wcsrtombs (host, &src, hostlen, NULL) == (size_t) -1)
- return EAI_IDN_ENCODE;
- if (src)
- return EAI_OVERFLOW;
- }
- if (wserv)
- {
- src = wserv;
- if (wcsrtombs (serv, &src, servlen, NULL) == (size_t) -1)
- return EAI_IDN_ENCODE;
- if (src)
- return EAI_OVERFLOW;
}
+ else if (ret == EAI_SYSTEM)
+ set_winsock_errno ();
+ }
+ __except (EFAULT)
+ {
+ ret = EAI_SYSTEM;
}
- else if (ret == EAI_SYSTEM)
- set_winsock_errno ();
+ __endtry
return ret;
}
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 89752cb46..f644b407b 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -1,7 +1,7 @@
/* ntdll.h. Contains ntdll specific stuff not defined elsewhere.
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.
@@ -1180,8 +1180,19 @@ typedef enum _SECTION_INHERIT
typedef VOID (APIENTRY *PTIMER_APC_ROUTINE)(PVOID, ULONG, ULONG);
-/* Function declarations for ntdll.dll. These don't appear in any
- standard Win32 header. */
+#ifdef __x86_64__
+typedef struct _SCOPE_TABLE
+{
+ ULONG Count;
+ struct
+ {
+ ULONG BeginAddress;
+ ULONG EndAddress;
+ ULONG HandlerAddress;
+ ULONG JumpTarget;
+ } ScopeRecord[1];
+} SCOPE_TABLE, *PSCOPE_TABLE;
+#endif
#ifdef __cplusplus
/* 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
= *(volatile KUSER_SHARED_DATA *) 0x7ffe0000;
+/* Function declarations for ntdll.dll. These don't appear in any
+ standard Win32 header. */
+
extern "C"
{
#endif
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
index 2fb205a04..d0c50775e 100644
--- a/winsup/cygwin/ntea.cc
+++ b/winsup/cygwin/ntea.cc
@@ -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. */
char lastname[MAX_EA_NAME_LEN];
- myfault efault;
- if (efault.faulted (EFAULT))
- goto out;
-
- pc.get_object_attr (attr, sec_none_nih);
+ __try
+ {
+ pc.get_object_attr (attr, sec_none_nih);
- debug_printf ("read_ea (%S, %s, %p, %lu)",
- attr.ObjectName, name, value, size);
+ 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,
- FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
+ /* 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);
- goto out;
+ status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ __leave;
+ }
+ hdl = NULL;
}
- hdl = NULL;
- }
-
- fea = (PFILE_FULL_EA_INFORMATION) tp.w_get ();
- if (name)
- {
- size_t nlen;
+ fea = (PFILE_FULL_EA_INFORMATION) tp.w_get ();
- /* For compatibility with Linux, we only allow user xattrs and
- return ENOTSUP otherwise. */
- if (ascii_strncasematch (name, "user.", 5))
- name += 5;
- else
+ if (name)
{
- set_errno (ENOTSUP);
- goto out;
- }
+ size_t nlen;
- 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);
+ /* 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;
+ }
- gea->NextEntryOffset = 0;
- gea->EaNameLength = nlen;
- strcpy (gea->EaName, name);
- }
+ 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);
- while (true)
- {
- if (h)
+ gea->NextEntryOffset = 0;
+ gea->EaNameLength = nlen;
+ strcpy (gea->EaName, name);
+ }
+
+ while (true)
{
- status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, gea, glen,
- NULL, TRUE);
- if (status != STATUS_ACCESS_DENIED || !hdl)
+ 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;
}
- 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)
+ switch (status)
{
- set_errno (ERANGE);
- goto out;
+ 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;
}
- memcpy (value, fea->EaName + fea->EaNameLength + 1,
- fea->EaValueLength);
+ __leave;
}
- ret = fea->EaValueLength;
- }
- else
- {
- ret = 0;
- do
+ if (name)
{
- fea->EaNameLength += 5; /* "user." */
+ /* 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_t) ret + fea->EaNameLength + 1 > size)
+ if (size < fea->EaValueLength)
{
set_errno (ERANGE);
- goto out;
+ __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;
+ memcpy (value, fea->EaName + fea->EaNameLength + 1,
+ fea->EaValueLength);
}
- else
- ret += fea->EaNameLength + 1;
- strcpy (lastname, fea->EaName);
- status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, NULL, 0,
- NULL, FALSE);
+ ret = fea->EaValueLength;
+ }
+ else
+ {
+ 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);
}
-
-out:
+ __except (EFAULT) {}
+ __endtry
if (!hdl)
CloseHandle (h);
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;
size_t nlen;
- myfault efault;
- if (efault.faulted (EFAULT))
- goto out;
-
- pc.get_object_attr (attr, sec_none_nih);
+ __try
+ {
+ pc.get_object_attr (attr, sec_none_nih);
- debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
- attr.ObjectName, name, value, size, flags);
+ 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,
- FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
+ /* 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);
- goto out;
+ status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
+ 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
- return ENOTSUP otherwise. */
- if (!ascii_strncasematch (name, "user.", 5))
- {
- set_errno (ENOTSUP);
- goto out;
- }
-
- /* removexattr is supposed to fail with ENOATTR if the requested EA is not
- available. This is equivalent to the XATTR_REPLACE flag for setxattr. */
- if (!value)
- flags = XATTR_REPLACE;
- if (flags)
- {
- if (flags != XATTR_CREATE && flags != XATTR_REPLACE)
+ /* For compatibility with Linux, we only allow user xattrs and
+ return ENOTSUP otherwise. */
+ if (!ascii_strncasematch (name, "user.", 5))
{
- set_errno (EINVAL);
- goto out;
+ set_errno (ENOTSUP);
+ __leave;
}
- ssize_t rret = read_ea (hdl, pc, name, NULL, 0);
- if (flags == XATTR_CREATE && rret > 0)
+
+ /* removexattr is supposed to fail with ENOATTR if the requested EA is
+ not available. This is equivalent to XATTR_REPLACE for setxattr. */
+ if (!value)
+ flags = XATTR_REPLACE;
+
+ if (flags)
{
- set_errno (EEXIST);
- goto out;
+ 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;
}
- if (flags == XATTR_REPLACE && rret < 0)
- goto out;
- }
- /* Skip "user." prefix. */
- name += 5;
+ /* Skip "user." prefix. */
+ name += 5;
- 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)
+ if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ 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)
{
- status = NtSetEaFile (h, &io, fea, flen);
- if (status != STATUS_ACCESS_DENIED || !hdl)
+ if (h)
+ {
+ status = NtSetEaFile (h, &io, fea, flen);
+ if (status != STATUS_ACCESS_DENIED || !hdl)
+ break;
+ }
+ status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS (status))
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))
- break;
- hdl = NULL;
- }
- if (!NT_SUCCESS (status))
- {
- switch (status)
{
- case STATUS_EA_TOO_LARGE:
- /* STATUS_EA_TOO_LARGE has a matching Win32 error ERROR_EA_TABLE_FULL.
- For some unknown reason RtlNtStatusToDosError does not translate
- STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL, but instead to
- ERROR_EA_LIST_INCONSISTENT. This error code is also returned for
- STATUS_EA_LIST_INCONSISTENT, which means the incoming EA list is...
- inconsistent. For obvious reasons we translate
- ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to handle
- STATUS_EA_TOO_LARGE explicitely here, to get the correct mapping
- to ENOSPC. */
- set_errno (ENOSPC);
- break;
- case STATUS_INVALID_DEVICE_REQUEST:
- set_errno (ENOTSUP);
- break;
- default:
- __seterrno_from_nt_status (status);
- break;
+ switch (status)
+ {
+ case STATUS_EA_TOO_LARGE:
+ /* STATUS_EA_TOO_LARGE has a matching Win32 error code
+ ERROR_EA_TABLE_FULL. For some reason RtlNtStatusToDosError
+ does not translate STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL,
+ but instead to ERROR_EA_LIST_INCONSISTENT. This error code is
+ also returned for STATUS_EA_LIST_INCONSISTENT, which means the
+ incoming EA list is... inconsistent. For obvious reasons we
+ translate ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to
+ handle STATUS_EA_TOO_LARGE explicitely here, to get the correct
+ mapping to ENOSPC. */
+ set_errno (ENOSPC);
+ break;
+ case STATUS_INVALID_DEVICE_REQUEST:
+ set_errno (ENOTSUP);
+ break;
+ default:
+ __seterrno_from_nt_status (status);
+ break;
+ }
}
+ else
+ ret = 0;
}
- else
- ret = 0;
-
-out:
+ __except (EFAULT) {}
+ __endtry
if (!hdl)
CloseHandle (h);
debug_printf ("%d = write_ea(%S, %s, %p, %lu, %d)",
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 631b169a0..e5ce312ed 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -651,561 +651,574 @@ path_conv::check (const char *src, unsigned opt,
}
#endif
- myfault efault;
- if (efault.faulted ())
- {
- error = EFAULT;
- return;
- }
- int loop = 0;
- path_flags = 0;
- known_suffix = NULL;
- fileattr = INVALID_FILE_ATTRIBUTES;
- caseinsensitive = OBJ_CASE_INSENSITIVE;
- if (wide_path)
- cfree (wide_path);
- wide_path = NULL;
- if (path)
- {
- cfree (modifiable_path ());
- path = NULL;
- }
- close_conv_handle ();
- memset (&dev, 0, sizeof (dev));
- fs.clear ();
- if (normalized_path)
- {
- cfree ((void *) normalized_path);
- normalized_path = NULL;
- }
- int component = 0; // Number of translated components
-
- if (!(opt & PC_NULLEMPTY))
- error = 0;
- else if (!*src)
- {
- error = ENOENT;
- return;
- }
-
- bool is_msdos = false;
- /* This loop handles symlink expansion. */
- for (;;)
- {
- MALLOC_CHECK;
- assert (src);
-
- is_relpath = !isabspath (src);
- error = normalize_posix_path (src, path_copy, tail);
- if (error > 0)
- return;
- if (error < 0)
+ __try
+ {
+ int loop = 0;
+ path_flags = 0;
+ known_suffix = NULL;
+ fileattr = INVALID_FILE_ATTRIBUTES;
+ caseinsensitive = OBJ_CASE_INSENSITIVE;
+ if (wide_path)
+ cfree (wide_path);
+ wide_path = NULL;
+ if (path)
{
- if (component == 0)
- is_msdos = true;
- error = 0;
+ cfree (modifiable_path ());
+ path = NULL;
}
+ close_conv_handle ();
+ memset (&dev, 0, sizeof (dev));
+ fs.clear ();
+ if (normalized_path)
+ {
+ cfree ((void *) normalized_path);
+ normalized_path = NULL;
+ }
+ int component = 0; // Number of translated components
- /* Detect if the user was looking for a directory. We have to strip the
- trailing slash initially while trying to add extensions but take it
- into account during processing */
- if (tail > path_copy + 2 && isslash (tail[-1]))
+ if (!(opt & PC_NULLEMPTY))
+ error = 0;
+ else if (!*src)
{
- need_directory = 1;
- *--tail = '\0';
+ error = ENOENT;
+ return;
}
- path_end = tail;
-
- /* Scan path_copy from right to left looking either for a symlink
- or an actual existing file. If an existing file is found, just
- return. If a symlink is found, exit the for loop.
- Also: be careful to preserve the errno returned from
- symlink.check as the caller may need it. */
- /* FIXME: Do we have to worry about multiple \'s here? */
- component = 0; // Number of translated components
- sym.contents[0] = '\0';
-
- int symlen = 0;
-
- for (unsigned pflags_or = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE);
- ;
- pflags_or = 0)
+
+ bool is_msdos = false;
+ /* This loop handles symlink expansion. */
+ for (;;)
{
- const suffix_info *suff;
- char *full_path;
+ MALLOC_CHECK;
+ assert (src);
- /* Don't allow symlink.check to set anything in the path_conv
- class if we're working on an inner component of the path */
- if (component)
+ is_relpath = !isabspath (src);
+ error = normalize_posix_path (src, path_copy, tail);
+ if (error > 0)
+ return;
+ if (error < 0)
{
- suff = NULL;
- full_path = pathbuf;
+ if (component == 0)
+ is_msdos = true;
+ error = 0;
}
- else
+
+ /* Detect if the user was looking for a directory. We have to strip
+ the trailing slash initially while trying to add extensions but
+ take it into account during processing */
+ if (tail > path_copy + 2 && isslash (tail[-1]))
{
- suff = suffixes;
- full_path = THIS_path;
+ need_directory = 1;
+ *--tail = '\0';
}
+ path_end = tail;
+
+ /* Scan path_copy from right to left looking either for a symlink
+ or an actual existing file. If an existing file is found, just
+ return. If a symlink is found, exit the for loop.
+ Also: be careful to preserve the errno returned from
+ symlink.check as the caller may need it. */
+ /* FIXME: Do we have to worry about multiple \'s here? */
+ component = 0; // Number of translated components
+ sym.contents[0] = '\0';
+
+ int symlen = 0;
+
+ for (unsigned pflags_or = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE);
+ ;
+ pflags_or = 0)
+ {
+ const suffix_info *suff;
+ char *full_path;
- /* Convert to native path spec sans symbolic link info. */
- error = mount_table->conv_to_win32_path (path_copy, full_path, dev,
- &sym.pflags);
+ /* Don't allow symlink.check to set anything in the path_conv
+ class if we're working on an inner component of the path */
+ if (component)
+ {
+ suff = NULL;
+ full_path = pathbuf;
+ }
+ else
+ {
+ suff = suffixes;
+ full_path = THIS_path;
+ }
- if (error)
- return;
+ /* Convert to native path spec sans symbolic link info. */
+ error = mount_table->conv_to_win32_path (path_copy, full_path,
+ dev, &sym.pflags);
- sym.pflags |= pflags_or;
+ if (error)
+ return;
- if (!dev.exists ())
- {
- error = ENXIO;
- return;
- }
+ sym.pflags |= pflags_or;
- if (iscygdrive_dev (dev))
- {
- if (!component)
- fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY;
- else
+ if (!dev.exists ())
{
- fileattr = getfileattr (THIS_path,
- sym.pflags & MOUNT_NOPOSIX);
- dev = FH_FS;
+ error = ENXIO;
+ return;
}
- goto out;
- }
- else if (isdev_dev (dev))
- {
- /* Just make sure that the path handling goes on as with FH_FS. */
- }
- else if (isvirtual_dev (dev))
- {
- /* FIXME: Calling build_fhandler here is not the right way to handle this. */
- fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy);
- virtual_ftype_t file_type;
- if (!fh)
- file_type = virt_none;
- else
+
+ if (iscygdrive_dev (dev))
{
- file_type = fh->exists ();
- if (file_type == virt_symlink)
+ if (!component)
+ fileattr = FILE_ATTRIBUTE_DIRECTORY
+ | FILE_ATTRIBUTE_READONLY;
+ else
{
- fh->fill_filebuf ();
- symlen = sym.set (fh->get_filebuf ());
+ fileattr = getfileattr (THIS_path,
+ sym.pflags & MOUNT_NOPOSIX);
+ dev = FH_FS;
}
- delete fh;
+ goto out;
}
- switch (file_type)
+ else if (isdev_dev (dev))
{
- case virt_directory:
- case virt_rootdir:
- if (component == 0)
- fileattr = FILE_ATTRIBUTE_DIRECTORY;
- break;
- case virt_file:
- if (component == 0)
- fileattr = 0;
- break;
- case virt_symlink:
- goto is_virtual_symlink;
- case virt_pipe:
- if (component == 0)
- {
- fileattr = 0;
- dev.parse (FH_PIPE);
- }
- break;
- case virt_socket:
- if (component == 0)
- {
- fileattr = 0;
- dev.parse (FH_TCP);
- }
- break;
- case virt_fsdir:
- case virt_fsfile:
- /* Access to real file or directory via block device
- entry in /proc/sys. Convert to real file and go with
- the flow. */
- dev.parse (FH_FS);
- goto is_fs_via_procsys;
- case virt_blk:
- /* Block special device. If the trailing slash has been
- requested, the target is the root directory of the
- filesystem on this block device. So we convert this to
- a real file and attach the backslash. */
- if (component == 0 && need_directory)
- {
+ /* Make sure that the path handling goes on as with FH_FS. */
+ }
+ else if (isvirtual_dev (dev))
+ {
+ /* FIXME: Calling build_fhandler here is not the right way to
+ handle this. */
+ fhandler_virtual *fh = (fhandler_virtual *)
+ build_fh_dev (dev, path_copy);
+ virtual_ftype_t file_type;
+ if (!fh)
+ file_type = virt_none;
+ else
+ {
+ file_type = fh->exists ();
+ if (file_type == virt_symlink)
+ {
+ fh->fill_filebuf ();
+ symlen = sym.set (fh->get_filebuf ());
+ }
+ delete fh;
+ }
+ switch (file_type)
+ {
+ case virt_directory:
+ case virt_rootdir:
+ if (component == 0)
+ fileattr = FILE_ATTRIBUTE_DIRECTORY;
+ break;
+ case virt_file:
+ if (component == 0)
+ fileattr = 0;
+ break;
+ case virt_symlink:
+ goto is_virtual_symlink;
+ case virt_pipe:
+ if (component == 0)
+ {
+ fileattr = 0;
+ dev.parse (FH_PIPE);
+ }
+ break;
+ case virt_socket:
+ if (component == 0)
+ {
+ fileattr = 0;
+ dev.parse (FH_TCP);
+ }
+ break;
+ case virt_fsdir:
+ case virt_fsfile:
+ /* Access to real file or directory via block device
+ entry in /proc/sys. Convert to real file and go with
+ the flow. */
dev.parse (FH_FS);
- strcat (full_path, "\\");
- fileattr = FILE_ATTRIBUTE_DIRECTORY
- | FILE_ATTRIBUTE_DEVICE;
- goto out;
- }
- /*FALLTHRU*/
- case virt_chr:
- if (component == 0)
- fileattr = FILE_ATTRIBUTE_DEVICE;
- break;
- default:
- if (component == 0)
- fileattr = INVALID_FILE_ATTRIBUTES;
- goto virtual_component_retry;
+ goto is_fs_via_procsys;
+ case virt_blk:
+ /* Block special device. If the trailing slash has been
+ requested, the target is the root directory of the
+ filesystem on this block device. So we convert this
+ to a real file and attach the backslash. */
+ if (component == 0 && need_directory)
+ {
+ dev.parse (FH_FS);
+ strcat (full_path, "\\");
+ fileattr = FILE_ATTRIBUTE_DIRECTORY
+ | FILE_ATTRIBUTE_DEVICE;
+ goto out;
+ }
+ /*FALLTHRU*/
+ case virt_chr:
+ if (component == 0)
+ fileattr = FILE_ATTRIBUTE_DEVICE;
+ break;
+ default:
+ if (component == 0)
+ fileattr = INVALID_FILE_ATTRIBUTES;
+ goto virtual_component_retry;
+ }
+ if (component == 0 || dev != FH_NETDRIVE)
+ path_flags |= PATH_RO;
+ goto out;
}
- if (component == 0 || dev != FH_NETDRIVE)
- path_flags |= PATH_RO;
- goto out;
- }
- /* devn should not be a device. If it is, then stop parsing now. */
- else if (dev != FH_FS)
- {
- fileattr = 0;
- path_flags = sym.pflags;
- if (component)
+ /* devn should not be a device. If it is, then stop parsing. */
+ else if (dev != FH_FS)
{
- error = ENOTDIR;
- return;
+ fileattr = 0;
+ path_flags = sym.pflags;
+ if (component)
+ {
+ error = ENOTDIR;
+ return;
+ }
+ goto out; /* Found a device. Stop parsing. */
}
- goto out; /* Found a device. Stop parsing. */
- }
- /* If path is only a drivename, Windows interprets it as the
- current working directory on this drive instead of the root
- dir which is what we want. So we need the trailing backslash
- in this case. */
- if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
- {
- full_path[2] = '\\';
- full_path[3] = '\0';
- }
+ /* If path is only a drivename, Windows interprets it as the
+ current working directory on this drive instead of the root
+ dir which is what we want. So we need the trailing backslash
+ in this case. */
+ if (full_path[0] && full_path[1] == ':' && full_path[2] == '\0')
+ {
+ full_path[2] = '\\';
+ full_path[3] = '\0';
+ }
- /* If the incoming path was given in DOS notation, always treat
- it as caseinsensitive,noacl path. This must be set before
- calling sym.check, otherwise the path is potentially treated
- casesensitive. */
- if (is_msdos)
- sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
+ /* If the incoming path was given in DOS notation, always treat
+ it as caseinsensitive,noacl path. This must be set before
+ calling sym.check, otherwise the path is potentially treated
+ casesensitive. */
+ if (is_msdos)
+ sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
-is_fs_via_procsys:
+ is_fs_via_procsys:
- symlen = sym.check (full_path, suff, fs, conv_handle);
+ symlen = sym.check (full_path, suff, fs, conv_handle);
-is_virtual_symlink:
+ is_virtual_symlink:
- if (sym.isdevice)
- {
- if (component)
+ if (sym.isdevice)
{
- error = ENOTDIR;
- return;
+ if (component)
+ {
+ error = ENOTDIR;
+ return;
+ }
+ dev.parse (sym.major, sym.minor);
+ dev.setfs (1);
+ dev.mode = sym.mode;
+ fileattr = sym.fileattr;
+ goto out;
}
- dev.parse (sym.major, sym.minor);
- dev.setfs (1);
- dev.mode = sym.mode;
- fileattr = sym.fileattr;
- goto out;
- }
- if (sym.pflags & PATH_SOCKET)
- {
- if (component)
+ if (sym.pflags & PATH_SOCKET)
{
- error = ENOTDIR;
- return;
+ if (component)
+ {
+ error = ENOTDIR;
+ return;
+ }
+ fileattr = sym.fileattr;
+ dev.parse (FH_UNIX);
+ dev.setfs (1);
+ goto out;
}
- fileattr = sym.fileattr;
- dev.parse (FH_UNIX);
- dev.setfs (1);
- goto out;
- }
- if (!component)
- {
- /* Make sure that /dev always exists. */
- fileattr = isdev_dev (dev) ? FILE_ATTRIBUTE_DIRECTORY
- : sym.fileattr;
- path_flags = sym.pflags;
- }
- else if (isdev_dev (dev))
- {
- /* If we're looking for a file below /dev, which doesn't exist,
- make sure that the device type is converted to FH_FS, so that
- subsequent code handles the file correctly.
- Unless /dev itself doesn't exist on disk. In that case /dev
- is handled as virtual filesystem, and virtual filesystems are
- read-only. The PC_KEEP_HANDLE check allows to check for
- a call from an informational system call. In that case we
- just stick to ENOENT, and the device type doesn't matter
- anyway. */
- if (sym.error == ENOENT && !(opt & PC_KEEP_HANDLE))
- sym.error = EROFS;
- else
- dev = FH_FS;
- }
+ if (!component)
+ {
+ /* Make sure that /dev always exists. */
+ fileattr = isdev_dev (dev) ? FILE_ATTRIBUTE_DIRECTORY
+ : sym.fileattr;
+ path_flags = sym.pflags;
+ }
+ else if (isdev_dev (dev))
+ {
+ /* If we're looking for a non-existing file below /dev,
+ make sure that the device type is converted to FH_FS, so
+ that subsequent code handles the file correctly. Unless
+ /dev itself doesn't exist on disk. In that case /dev
+ is handled as virtual filesystem, and virtual filesystems
+ are read-only. The PC_KEEP_HANDLE check allows to check
+ for a call from an informational system call. In that
+ case we just stick to ENOENT, and the device type doesn't
+ matter anyway. */
+ if (sym.error == ENOENT && !(opt & PC_KEEP_HANDLE))
+ sym.error = EROFS;
+ else
+ dev = FH_FS;
+ }
- /* If symlink.check found an existing non-symlink file, then
- it sets the appropriate flag. It also sets any suffix found
- into `ext_here'. */
- if (!sym.issymlink && sym.fileattr != INVALID_FILE_ATTRIBUTES)
- {
- error = sym.error;
- if (component == 0)
- add_ext = true;
- else if (!(sym.fileattr & FILE_ATTRIBUTE_DIRECTORY))
+ /* If symlink.check found an existing non-symlink file, then
+ it sets the appropriate flag. It also sets any suffix found
+ into `ext_here'. */
+ if (!sym.issymlink && sym.fileattr != INVALID_FILE_ATTRIBUTES)
{
- error = ENOTDIR;
- goto out;
+ error = sym.error;
+ if (component == 0)
+ add_ext = true;
+ else if (!(sym.fileattr & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ error = ENOTDIR;
+ goto out;
+ }
+ goto out; // file found
}
- goto out; // file found
- }
- /* Found a symlink if symlen > 0. If component == 0, then the
- src path itself was a symlink. If !follow_mode then
- we're done. Otherwise we have to insert the path found
- into the full path that we are building and perform all of
- these operations again on the newly derived path. */
- else if (symlen > 0)
- {
- saw_symlinks = 1;
- if (component == 0 && !need_directory
- && (!(opt & PC_SYM_FOLLOW)
- || (is_rep_symlink () && (opt & PC_SYM_NOFOLLOW_REP))))
+ /* Found a symlink if symlen > 0. If component == 0, then the
+ src path itself was a symlink. If !follow_mode then
+ we're done. Otherwise we have to insert the path found
+ into the full path that we are building and perform all of
+ these operations again on the newly derived path. */
+ else if (symlen > 0)
{
- set_symlink (symlen); // last component of path is a symlink.
- if (opt & PC_SYM_CONTENTS)
+ saw_symlinks = 1;
+ if (component == 0 && !need_directory
+ && (!(opt & PC_SYM_FOLLOW)
+ || (is_rep_symlink ()
+ && (opt & PC_SYM_NOFOLLOW_REP))))
{
- strcpy (THIS_path, sym.contents);
+ /* last component of path is a symlink. */
+ set_symlink (symlen);
+ if (opt & PC_SYM_CONTENTS)
+ {
+ strcpy (THIS_path, sym.contents);
+ goto out;
+ }
+ add_ext = true;
goto out;
}
- add_ext = true;
+ /* Following a symlink we can't trust the collected
+ filesystem information any longer. */
+ fs.clear ();
+ /* Close handle, if we have any. Otherwise we're collecting
+ handles while following symlinks. */
+ conv_handle.close ();
+ break;
+ }
+ else if (sym.error && sym.error != ENOENT)
+ {
+ error = sym.error;
goto out;
}
- /* Following a symlink we can't trust the collected filesystem
- information any longer. */
- fs.clear ();
- /* Close handle, if we have any. Otherwise we're collecting
- handles while following symlinks. */
- conv_handle.close ();
- break;
+ /* No existing file found. */
+
+ virtual_component_retry:
+ /* Find the new "tail" of the path, e.g. in '/for/bar/baz',
+ /baz is the tail. */
+ if (tail != path_end)
+ *tail = '/';
+ while (--tail > path_copy + 1 && *tail != '/') {}
+ /* Exit loop if there is no tail or we are at the
+ beginning of a UNC path */
+ if (tail <= path_copy + 1)
+ goto out; // all done
+
+ /* Haven't found an existing pathname component yet.
+ Pinch off the tail and try again. */
+ *tail = '\0';
+ component++;
}
- else if (sym.error && sym.error != ENOENT)
+
+ /* Arrive here if above loop detected a symlink. */
+ if (++loop > SYMLOOP_MAX)
{
- error = sym.error;
- goto out;
+ error = ELOOP; // Eep.
+ return;
}
- /* No existing file found. */
-virtual_component_retry:
- /* Find the new "tail" of the path, e.g. in '/for/bar/baz',
- /baz is the tail. */
- if (tail != path_end)
- *tail = '/';
- while (--tail > path_copy + 1 && *tail != '/') {}
- /* Exit loop if there is no tail or we are at the
- beginning of a UNC path */
- if (tail <= path_copy + 1)
- goto out; // all done
-
- /* Haven't found an existing pathname component yet.
- Pinch off the tail and try again. */
- *tail = '\0';
- component++;
- }
+ MALLOC_CHECK;
- /* Arrive here if above loop detected a symlink. */
- if (++loop > SYMLOOP_MAX)
- {
- error = ELOOP; // Eep.
- return;
- }
- MALLOC_CHECK;
+ /* Place the link content, possibly with head and/or tail,
+ in tmp_buf */
+
+ char *headptr;
+ if (isabspath (sym.contents))
+ headptr = tmp_buf; /* absolute path */
+ else
+ {
+ /* Copy the first part of the path (with ending /) and point to
+ the end. */
+ char *prevtail = tail;
+ while (--prevtail > path_copy && *prevtail != '/') {}
+ int headlen = prevtail - path_copy + 1;;
+ memcpy (tmp_buf, path_copy, headlen);
+ headptr = &tmp_buf[headlen];
+ }
+ /* Make sure there is enough space */
+ if (headptr + symlen >= tmp_buf + (2 * NT_MAX_PATH))
+ {
+ too_long:
+ error = ENAMETOOLONG;
+ set_path ("::ENAMETOOLONG::");
+ return;
+ }
- /* Place the link content, possibly with head and/or tail, in tmp_buf */
+ /* Copy the symlink contents to the end of tmp_buf.
+ Convert slashes. */
+ for (char *p = sym.contents; *p; p++)
+ *headptr++ = *p == '\\' ? '/' : *p;
+ *headptr = '\0';
- char *headptr;
- if (isabspath (sym.contents))
- headptr = tmp_buf; /* absolute path */
- else
- {
- /* Copy the first part of the path (with ending /) and point to the end. */
- char *prevtail = tail;
- while (--prevtail > path_copy && *prevtail != '/') {}
- int headlen = prevtail - path_copy + 1;;
- memcpy (tmp_buf, path_copy, headlen);
- headptr = &tmp_buf[headlen];
+ /* Copy any tail component (with the 0) */
+ if (tail++ < path_end)
+ {
+ /* Add a slash if needed. There is space. */
+ if (*(headptr - 1) != '/')
+ *headptr++ = '/';
+ int taillen = path_end - tail + 1;
+ if (headptr + taillen > tmp_buf + (2 * NT_MAX_PATH))
+ goto too_long;
+ memcpy (headptr, tail, taillen);
+ }
+
+ /* Evaluate everything all over again. */
+ src = tmp_buf;
}
- /* Make sure there is enough space */
- if (headptr + symlen >= tmp_buf + (2 * NT_MAX_PATH))
+ if (!(opt & PC_SYM_CONTENTS))
+ add_ext = true;
+
+ out:
+ set_path (THIS_path);
+ if (add_ext)
+ add_ext_from_sym (sym);
+ if (dev == FH_NETDRIVE && component)
{
- too_long:
- error = ENAMETOOLONG;
- set_path ("::ENAMETOOLONG::");
+ /* This case indicates a non-existant resp. a non-retrievable
+ share. This happens for instance if the share is a printer.
+ In this case the path must not be treated like a FH_NETDRIVE,
+ but like a FH_FS instead, so the usual open call for files
+ is used on it. */
+ dev.parse (FH_FS);
+ }
+ else if (isproc_dev (dev) && fileattr == INVALID_FILE_ATTRIBUTES)
+ {
+ /* FIXME: Usually we don't set error to ENOENT if a file doesn't
+ exist. This is typically indicated by the fileattr content.
+ So, why here? The downside is that cygwin_conv_path just gets
+ an error for these paths so it reports the error back to the
+ application. Unlike in all other cases of non-existant files,
+ for which check doesn't set error, so cygwin_conv_path just
+ returns the path, as intended. */
+ error = ENOENT;
return;
}
-
- /* Copy the symlink contents to the end of tmp_buf.
- Convert slashes. */
- for (char *p = sym.contents; *p; p++)
- *headptr++ = *p == '\\' ? '/' : *p;
- *headptr = '\0';
-
- /* Copy any tail component (with the 0) */
- if (tail++ < path_end)
+ else if (!need_directory || error)
+ /* nothing to do */;
+ else if (fileattr == INVALID_FILE_ATTRIBUTES)
+ /* Reattach trailing dirsep in native path. */
+ strcat (modifiable_path (), "\\");
+ else if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
+ path_flags &= ~PATH_SYMLINK;
+ else
{
- /* Add a slash if needed. There is space. */
- if (*(headptr - 1) != '/')
- *headptr++ = '/';
- int taillen = path_end - tail + 1;
- if (headptr + taillen > tmp_buf + (2 * NT_MAX_PATH))
- goto too_long;
- memcpy (headptr, tail, taillen);
+ debug_printf ("%s is a non-directory", path);
+ error = ENOTDIR;
+ return;
}
- /* Evaluate everything all over again. */
- src = tmp_buf;
- }
-
- if (!(opt & PC_SYM_CONTENTS))
- add_ext = true;
-
-out:
- set_path (THIS_path);
- if (add_ext)
- add_ext_from_sym (sym);
- if (dev == FH_NETDRIVE && component)
- {
- /* This case indicates a non-existant resp. a non-retrievable
- share. This happens for instance if the share is a printer.
- In this case the path must not be treated like a FH_NETDRIVE,
- but like a FH_FS instead, so the usual open call for files
- is used on it. */
- dev.parse (FH_FS);
- }
- else if (isproc_dev (dev) && fileattr == INVALID_FILE_ATTRIBUTES)
- {
- /* FIXME: Usually we don't set error to ENOENT if a file doesn't
- exist. This is typically indicated by the fileattr content.
- So, why here? The downside is that cygwin_conv_path just gets
- an error for these paths so it reports the error back to the
- application. Unlike in all other cases of non-existant files,
- for which check doesn't set error, so cygwin_conv_path just
- returns the path, as intended. */
- error = ENOENT;
- return;
- }
- else if (!need_directory || error)
- /* nothing to do */;
- else if (fileattr == INVALID_FILE_ATTRIBUTES)
- strcat (modifiable_path (), "\\"); /* Reattach trailing dirsep in native path. */
- else if (fileattr & FILE_ATTRIBUTE_DIRECTORY)
- path_flags &= ~PATH_SYMLINK;
- else
- {
- debug_printf ("%s is a non-directory", path);
- error = ENOTDIR;
- return;
- }
-
- if (dev.isfs ())
- {
- if (strncmp (path, "\\\\.\\", 4))
+ if (dev.isfs ())
{
- if (!tail || tail == path)
- /* nothing */;
- else if (tail[-1] != '\\')
- *tail = '\0';
- else
+ if (strncmp (path, "\\\\.\\", 4))
{
- error = ENOENT;
- return;
+ if (!tail || tail == path)
+ /* nothing */;
+ else if (tail[-1] != '\\')
+ *tail = '\0';
+ else
+ {
+ error = ENOENT;
+ return;
+ }
}
- }
- /* If FS hasn't been checked already in symlink_info::check, do so now. */
- if (fs.inited ()|| fs.update (get_nt_native_path (), NULL))
- {
- /* Incoming DOS paths are treated like DOS paths in native
- Windows applications. No ACLs, just default settings. */
- if (is_msdos)
- fs.has_acls (false);
- debug_printf ("this->path(%s), has_acls(%d)", path, fs.has_acls ());
- /* CV: We could use this->has_acls() but I want to make sure that
- we don't forget that the PATH_NOACL flag must be taken into
- account here. */
- if (!(path_flags & PATH_NOACL) && fs.has_acls ())
- set_exec (0); /* We really don't know if this is executable or not here
- but set it to not executable since it will be figured out
- later by anything which cares about this. */
+ /* If FS hasn't been checked already in symlink_info::check,
+ do so now. */
+ if (fs.inited ()|| fs.update (get_nt_native_path (), NULL))
+ {
+ /* Incoming DOS paths are treated like DOS paths in native
+ Windows applications. No ACLs, just default settings. */
+ if (is_msdos)
+ fs.has_acls (false);
+ debug_printf ("this->path(%s), has_acls(%d)",
+ path, fs.has_acls ());
+ /* CV: We could use this->has_acls() but I want to make sure that
+ we don't forget that the PATH_NOACL flag must be taken into
+ account here. */
+ if (!(path_flags & PATH_NOACL) && fs.has_acls ())
+ set_exec (0); /* We really don't know if this is executable or
+ not here but set it to not executable since
+ it will be figured out later by anything
+ which cares about this. */
+ }
+ /* If the FS has been found to have unrelibale inodes, note
+ that in path_flags. */
+ if (!fs.hasgood_inode ())
+ path_flags |= PATH_IHASH;
+ /* If the OS is caseinsensitive or the FS is caseinsensitive,
+ don't handle path casesensitive. */
+ if (cygwin_shared->obcaseinsensitive || fs.caseinsensitive ())
+ path_flags |= PATH_NOPOSIX;
+ caseinsensitive = (path_flags & PATH_NOPOSIX)
+ ? OBJ_CASE_INSENSITIVE : 0;
+ if (exec_state () != dont_know_if_executable)
+ /* ok */;
+ else if (isdir ())
+ set_exec (1);
+ else if (issymlink () || issocket ())
+ set_exec (0);
}
- /* If the FS has been found to have unrelibale inodes, note
- that in path_flags. */
- if (!fs.hasgood_inode ())
- path_flags |= PATH_IHASH;
- /* If the OS is caseinsensitive or the FS is caseinsensitive,
- don't handle path casesensitive. */
- if (cygwin_shared->obcaseinsensitive || fs.caseinsensitive ())
- path_flags |= PATH_NOPOSIX;
- caseinsensitive = (path_flags & PATH_NOPOSIX)
- ? OBJ_CASE_INSENSITIVE : 0;
- if (exec_state () != dont_know_if_executable)
- /* ok */;
- else if (isdir ())
- set_exec (1);
- else if (issymlink () || issocket ())
- set_exec (0);
- }
- if (opt & PC_NOFULL)
- {
- if (is_relpath)
+ if (opt & PC_NOFULL)
{
- mkrelpath (this->modifiable_path (), !!caseinsensitive);
- /* Invalidate wide_path so that wide relpath can be created
- in later calls to get_nt_native_path or get_wide_win32_path. */
- if (wide_path)
- cfree (wide_path);
- wide_path = NULL;
- }
- if (need_directory)
- {
- size_t n = strlen (this->path);
- /* Do not add trailing \ to UNC device names like \\.\a: */
- if (this->path[n - 1] != '\\' &&
- (strncmp (this->path, "\\\\.\\", 4) != 0))
+ if (is_relpath)
+ {
+ mkrelpath (this->modifiable_path (), !!caseinsensitive);
+ /* Invalidate wide_path so that wide relpath can be created
+ in later calls to get_nt_native_path or get_wide_win32_path. */
+ if (wide_path)
+ cfree (wide_path);
+ wide_path = NULL;
+ }
+ if (need_directory)
{
- this->modifiable_path ()[n] = '\\';
- this->modifiable_path ()[n + 1] = '\0';
+ size_t n = strlen (this->path);
+ /* Do not add trailing \ to UNC device names like \\.\a: */
+ if (this->path[n - 1] != '\\' &&
+ (strncmp (this->path, "\\\\.\\", 4) != 0))
+ {
+ this->modifiable_path ()[n] = '\\';
+ this->modifiable_path ()[n + 1] = '\0';
+ }
}
}
- }
- if (saw_symlinks)
- set_has_symlinks ();
+ if (saw_symlinks)
+ set_has_symlinks ();
- if (opt & PC_OPEN)
- path_flags |= PATH_OPEN;
+ if (opt & PC_OPEN)
+ path_flags |= PATH_OPEN;
- if (opt & PC_CTTY)
- path_flags |= PATH_CTTY;
+ if (opt & PC_CTTY)
+ path_flags |= PATH_CTTY;
- if (opt & PC_POSIX)
- {
- if (tail < path_end && tail > path_copy + 1)
- *tail = '/';
- set_normalized_path (path_copy);
- if (is_msdos && !(opt & PC_NOWARN))
- warn_msdos (src);
- }
+ if (opt & PC_POSIX)
+ {
+ if (tail < path_end && tail > path_copy + 1)
+ *tail = '/';
+ set_normalized_path (path_copy);
+ if (is_msdos && !(opt & PC_NOWARN))
+ warn_msdos (src);
+ }
#if 0
- if (!error)
+ if (!error)
+ {
+ last_path_conv = *this;
+ strcpy (last_src, src);
+ }
+#endif
+ }
+ __except (NO_ERROR)
{
- last_path_conv = *this;
- strcpy (last_src, src);
+ error = EFAULT;
}
-#endif
+ __endtry
}
path_conv::~path_conv ()
@@ -1688,332 +1701,342 @@ symlink_worker (const char *oldpath, const char *newpath, bool isdevice)
/* POSIX says that empty 'newpath' is invalid input while empty
'oldpath' is valid -- it's symlink resolver job to verify if
symlink contents point to existing filesystem object */
- myfault efault;
- if (efault.faulted (EFAULT))
- goto done;
- if (!*oldpath || !*newpath)
+ __try
{
- set_errno (ENOENT);
- goto done;
- }
-
- if (strlen (oldpath) > SYMLINK_MAX)
- {
- set_errno (ENAMETOOLONG);
- goto done;
- }
+ if (!*oldpath || !*newpath)
+ {
+ set_errno (ENOENT);
+ __leave;
+ }
- /* Trailing dirsep is a no-no. */
- len = strlen (newpath);
- has_trailing_dirsep = isdirsep (newpath[len - 1]);
- if (has_trailing_dirsep)
- {
- newpath = strdup (newpath);
- ((char *) newpath)[len - 1] = '\0';
- }
+ if (strlen (oldpath) > SYMLINK_MAX)
+ {
+ set_errno (ENAMETOOLONG);
+ __leave;
+ }
- check_opt = PC_SYM_NOFOLLOW | PC_POSIX | (isdevice ? PC_NOWARN : 0);
- /* We need the normalized full path below. */
- win32_newpath.check (newpath, check_opt, stat_suffixes);
-
- /* Default symlink type is determined by global allow_winsymlinks variable.
- Device files are always shortcuts. */
- wsym_type = isdevice ? WSYM_lnk : allow_winsymlinks;
- /* NFS has its own, dedicated way to create symlinks. */
- if (win32_newpath.fs_is_nfs ())
- wsym_type = WSYM_nfs;
- /* MVFS doesn't handle the SYSTEM DOS attribute, but it handles the R/O
- attribute. Therefore we create symlinks on MVFS always as shortcuts. */
- else if (win32_newpath.fs_is_mvfs ())
- wsym_type = WSYM_lnk;
- /* AFS only supports native symlinks. */
- else if (win32_newpath.fs_is_afs ())
- {
- /* Bail out if OS doesn't support native symlinks. */
- if (wincap.max_sys_priv () < SE_CREATE_SYMBOLIC_LINK_PRIVILEGE)
+ /* Trailing dirsep is a no-no. */
+ len = strlen (newpath);
+ has_trailing_dirsep = isdirsep (newpath[len - 1]);
+ if (has_trailing_dirsep)
{
- set_errno (EPERM);
- goto done;
+ newpath = strdup (newpath);
+ ((char *) newpath)[len - 1] = '\0';
}
- wsym_type = WSYM_nativestrict;
- }
- /* Don't try native symlinks on filesystems not supporting reparse points. */
- else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict)
- && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
- wsym_type = WSYM_sysfile;
-
- /* Attach .lnk suffix when shortcut is requested. */
- if (wsym_type == WSYM_lnk && !win32_newpath.exists ()
- && (isdevice || !win32_newpath.fs_is_nfs ()))
- {
- char *newplnk = tp.c_get ();
- stpcpy (stpcpy (newplnk, newpath), ".lnk");
- win32_newpath.check (newplnk, check_opt);
- }
- if (win32_newpath.error)
- {
- set_errno (win32_newpath.error);
- goto done;
- }
+ check_opt = PC_SYM_NOFOLLOW | PC_POSIX | (isdevice ? PC_NOWARN : 0);
+ /* We need the normalized full path below. */
+ win32_newpath.check (newpath, check_opt, stat_suffixes);
+
+ /* Default symlink type is determined by global allow_winsymlinks
+ variable. Device files are always shortcuts. */
+ wsym_type = isdevice ? WSYM_lnk : allow_winsymlinks;
+ /* NFS has its own, dedicated way to create symlinks. */
+ if (win32_newpath.fs_is_nfs ())
+ wsym_type = WSYM_nfs;
+ /* MVFS doesn't handle the SYSTEM DOS attribute, but it handles the R/O
+ attribute. Therefore we create symlinks on MVFS always as shortcuts. */
+ else if (win32_newpath.fs_is_mvfs ())
+ wsym_type = WSYM_lnk;
+ /* AFS only supports native symlinks. */
+ else if (win32_newpath.fs_is_afs ())
+ {
+ /* Bail out if OS doesn't support native symlinks. */
+ if (wincap.max_sys_priv () < SE_CREATE_SYMBOLIC_LINK_PRIVILEGE)
+ {
+ set_errno (EPERM);
+ __leave;
+ }
+ wsym_type = WSYM_nativestrict;
+ }
+ /* Don't try native symlinks on FSes not supporting reparse points. */
+ else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict)
+ && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
+ wsym_type = WSYM_sysfile;
+
+ /* Attach .lnk suffix when shortcut is requested. */
+ if (wsym_type == WSYM_lnk && !win32_newpath.exists ()
+ && (isdevice || !win32_newpath.fs_is_nfs ()))
+ {
+ char *newplnk = tp.c_get ();
+ stpcpy (stpcpy (newplnk, newpath), ".lnk");
+ win32_newpath.check (newplnk, check_opt);
+ }
- syscall_printf ("symlink (%s, %S) wsym_type %d", oldpath,
- win32_newpath.get_nt_native_path (), wsym_type);
+ if (win32_newpath.error)
+ {
+ set_errno (win32_newpath.error);
+ __leave;
+ }
- if ((!isdevice && win32_newpath.exists ())
- || win32_newpath.is_auto_device ())
- {
- set_errno (EEXIST);
- goto done;
- }
- if (has_trailing_dirsep && !win32_newpath.exists ())
- {
- set_errno (ENOENT);
- goto done;
- }
+ syscall_printf ("symlink (%s, %S) wsym_type %d", oldpath,
+ win32_newpath.get_nt_native_path (), wsym_type);
- /* Handle NFS and native symlinks in their own functions. */
- switch (wsym_type)
- {
- case WSYM_nfs:
- res = symlink_nfs (oldpath, win32_newpath);
- goto done;
- case WSYM_native:
- case WSYM_nativestrict:
- res = symlink_native (oldpath, win32_newpath);
- if (!res)
- goto done;
- /* Strictly native? Too bad. */
- if (wsym_type == WSYM_nativestrict)
+ if ((!isdevice && win32_newpath.exists ())
+ || win32_newpath.is_auto_device ())
{
- __seterrno ();
- goto done;
+ set_errno (EEXIST);
+ __leave;
+ }
+ if (has_trailing_dirsep && !win32_newpath.exists ())
+ {
+ set_errno (ENOENT);
+ __leave;
}
- /* Otherwise, fall back to default symlink type. */
- wsym_type = WSYM_sysfile;
- break;
- default:
- break;
- }
-
- if (wsym_type == WSYM_lnk)
- {
- path_conv win32_oldpath;
- ITEMIDLIST *pidl = NULL;
- size_t full_len = 0;
- unsigned short oldpath_len, desc_len, relpath_len, pidl_len = 0;
- char desc[MAX_PATH + 1], *relpath;
- if (!isdevice)
+ /* Handle NFS and native symlinks in their own functions. */
+ switch (wsym_type)
{
- /* First create an IDLIST to learn how big our shortcut is
- going to be. */
- IShellFolder *psl;
-
- /* The symlink target is relative to the directory in which
- the symlink gets created, not relative to the cwd. Therefore
- we have to mangle the path quite a bit before calling path_conv. */
- if (isabspath (oldpath))
- win32_oldpath.check (oldpath,
- PC_SYM_NOFOLLOW,
- stat_suffixes);
- else
+ case WSYM_nfs:
+ res = symlink_nfs (oldpath, win32_newpath);
+ __leave;
+ case WSYM_native:
+ case WSYM_nativestrict:
+ res = symlink_native (oldpath, win32_newpath);
+ if (!res)
+ __leave;
+ /* Strictly native? Too bad. */
+ if (wsym_type == WSYM_nativestrict)
{
- len = strrchr (win32_newpath.normalized_path, '/')
- - win32_newpath.normalized_path + 1;
- char *absoldpath = tp.t_get ();
- stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path, len),
- oldpath);
- win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW, stat_suffixes);
+ __seterrno ();
+ __leave;
}
- if (SUCCEEDED (SHGetDesktopFolder (&psl)))
+ /* Otherwise, fall back to default symlink type. */
+ wsym_type = WSYM_sysfile;
+ break;
+ default:
+ break;
+ }
+
+ if (wsym_type == WSYM_lnk)
+ {
+ path_conv win32_oldpath;
+ ITEMIDLIST *pidl = NULL;
+ size_t full_len = 0;
+ unsigned short oldpath_len, desc_len, relpath_len, pidl_len = 0;
+ char desc[MAX_PATH + 1], *relpath;
+
+ if (!isdevice)
{
- WCHAR wc_path[win32_oldpath.get_wide_win32_path_len () + 1];
- win32_oldpath.get_wide_win32_path (wc_path);
- /* Amazing but true: Even though the ParseDisplayName method
- takes a wide char path name, it does not understand the
- Win32 prefix for long pathnames! So we have to tack off
- the prefix and convert the path to the "normal" syntax
- for ParseDisplayName. */
- WCHAR *wc = wc_path + 4;
- if (wc[1] != L':') /* native UNC path */
- *(wc += 2) = L'\\';
- HRESULT res;
- if (SUCCEEDED (res = psl->ParseDisplayName (NULL, NULL, wc, NULL,
- &pidl, NULL)))
+ /* First create an IDLIST to learn how big our shortcut is
+ going to be. */
+ IShellFolder *psl;
+
+ /* The symlink target is relative to the directory in which the
+ symlink gets created, not relative to the cwd. Therefore we
+ have to mangle the path quite a bit before calling path_conv.*/
+ if (isabspath (oldpath))
+ win32_oldpath.check (oldpath,
+ PC_SYM_NOFOLLOW,
+ stat_suffixes);
+ else
+ {
+ len = strrchr (win32_newpath.normalized_path, '/')
+ - win32_newpath.normalized_path + 1;
+ char *absoldpath = tp.t_get ();
+ stpcpy (stpncpy (absoldpath, win32_newpath.normalized_path,
+ len),
+ oldpath);
+ win32_oldpath.check (absoldpath, PC_SYM_NOFOLLOW,
+ stat_suffixes);
+ }
+ if (SUCCEEDED (SHGetDesktopFolder (&psl)))
{
- ITEMIDLIST *p;
+ WCHAR wc_path[win32_oldpath.get_wide_win32_path_len () + 1];
+ win32_oldpath.get_wide_win32_path (wc_path);
+ /* Amazing but true: Even though the ParseDisplayName method
+ takes a wide char path name, it does not understand the
+ Win32 prefix for long pathnames! So we have to tack off
+ the prefix and convert the path to the "normal" syntax
+ for ParseDisplayName. */
+ WCHAR *wc = wc_path + 4;
+ if (wc[1] != L':') /* native UNC path */
+ *(wc += 2) = L'\\';
+ HRESULT res;
+ if (SUCCEEDED (res = psl->ParseDisplayName (NULL, NULL, wc,
+ NULL, &pidl,
+ NULL)))
+ {
+ ITEMIDLIST *p;
- for (p = pidl; p->mkid.cb > 0;
- p = (ITEMIDLIST *)((char *) p + p->mkid.cb))
- ;
- pidl_len = (char *) p - (char *) pidl + 2;
+ for (p = pidl; p->mkid.cb > 0;
+ p = (ITEMIDLIST *)((char *) p + p->mkid.cb))
+ ;
+ pidl_len = (char *) p - (char *) pidl + 2;
+ }
+ psl->Release ();
}
- psl->Release ();
}
+ /* Compute size of shortcut file. */
+ full_len = sizeof (win_shortcut_hdr);
+ if (pidl_len)
+ full_len += sizeof (unsigned short) + pidl_len;
+ oldpath_len = strlen (oldpath);
+ /* Unfortunately the length of the description is restricted to a
+ length of 2000 bytes. We don't want to add considerations for
+ the different lengths and even 2000 bytes is not enough for long
+ path names. So what we do here is to set the description to the
+ POSIX path only if the path is not longer than MAX_PATH characters.
+ We append the full path name after the regular shortcut data
+ (see below), which works fine with Windows Explorer as well
+ as older Cygwin versions (as long as the whole file isn't bigger
+ than 8K). The description field is only used for backward
+ compatibility to older Cygwin versions and those versions are
+ not capable of handling long path names anyway. */
+ desc_len = stpcpy (desc, oldpath_len > MAX_PATH
+ ? "[path too long]" : oldpath) - desc;
+ full_len += sizeof (unsigned short) + desc_len;
+ /* Devices get the oldpath string unchanged as relative path. */
+ if (isdevice)
+ {
+ relpath_len = oldpath_len;
+ stpcpy (relpath = tp.c_get (), oldpath);
+ }
+ else
+ {
+ relpath_len = strlen (win32_oldpath.get_win32 ());
+ stpcpy (relpath = tp.c_get (), win32_oldpath.get_win32 ());
+ }
+ full_len += sizeof (unsigned short) + relpath_len;
+ full_len += sizeof (unsigned short) + oldpath_len;
+ /* 1 byte more for trailing 0 written by stpcpy. */
+ if (full_len < NT_MAX_PATH * sizeof (WCHAR))
+ buf = tp.t_get ();
+ else
+ buf = (char *) alloca (full_len + 1);
+
+ /* Create shortcut header */
+ win_shortcut_hdr *shortcut_header = (win_shortcut_hdr *) buf;
+ memset (shortcut_header, 0, sizeof *shortcut_header);
+ shortcut_header->size = sizeof *shortcut_header;
+ shortcut_header->magic = GUID_shortcut;
+ shortcut_header->flags = (WSH_FLAG_DESC | WSH_FLAG_RELPATH);
+ if (pidl)
+ shortcut_header->flags |= WSH_FLAG_IDLIST;
+ shortcut_header->run = SW_NORMAL;
+ cp = buf + sizeof (win_shortcut_hdr);
+
+ /* Create IDLIST */
+ if (pidl)
+ {
+ *(unsigned short *)cp = pidl_len;
+ memcpy (cp += 2, pidl, pidl_len);
+ cp += pidl_len;
+ CoTaskMemFree (pidl);
+ }
+
+ /* Create description */
+ *(unsigned short *)cp = desc_len;
+ cp = stpcpy (cp += 2, desc);
+
+ /* Create relpath */
+ *(unsigned short *)cp = relpath_len;
+ cp = stpcpy (cp += 2, relpath);
+
+ /* Append the POSIX path after the regular shortcut data for
+ the long path support. */
+ unsigned short *plen = (unsigned short *) cp;
+ cp += 2;
+ *(PWCHAR) cp = 0xfeff; /* BOM */
+ cp += 2;
+ *plen = sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath)
+ * sizeof (WCHAR);
+ cp += *plen;
}
- /* Compute size of shortcut file. */
- full_len = sizeof (win_shortcut_hdr);
- if (pidl_len)
- full_len += sizeof (unsigned short) + pidl_len;
- oldpath_len = strlen (oldpath);
- /* Unfortunately the length of the description is restricted to a
- length of 2000 bytes. We don't want to add considerations for
- the different lengths and even 2000 bytes is not enough for long
- path names. So what we do here is to set the description to the
- POSIX path only if the path is not longer than MAX_PATH characters.
- We append the full path name after the regular shortcut data
- (see below), which works fine with Windows Explorer as well
- as older Cygwin versions (as long as the whole file isn't bigger
- than 8K). The description field is only used for backward
- compatibility to older Cygwin versions and those versions are
- not capable of handling long path names anyway. */
- desc_len = stpcpy (desc, oldpath_len > MAX_PATH
- ? "[path too long]" : oldpath) - desc;
- full_len += sizeof (unsigned short) + desc_len;
- /* Devices get the oldpath string unchanged as relative path. */
- if (isdevice)
- {
- relpath_len = oldpath_len;
- stpcpy (relpath = tp.c_get (), oldpath);
- }
- else
- {
- relpath_len = strlen (win32_oldpath.get_win32 ());
- stpcpy (relpath = tp.c_get (), win32_oldpath.get_win32 ());
- }
- full_len += sizeof (unsigned short) + relpath_len;
- full_len += sizeof (unsigned short) + oldpath_len;
- /* 1 byte more for trailing 0 written by stpcpy. */
- if (full_len < NT_MAX_PATH * sizeof (WCHAR))
- buf = tp.t_get ();
else
- buf = (char *) alloca (full_len + 1);
-
- /* Create shortcut header */
- win_shortcut_hdr *shortcut_header = (win_shortcut_hdr *) buf;
- memset (shortcut_header, 0, sizeof *shortcut_header);
- shortcut_header->size = sizeof *shortcut_header;
- shortcut_header->magic = GUID_shortcut;
- shortcut_header->flags = (WSH_FLAG_DESC | WSH_FLAG_RELPATH);
- if (pidl)
- shortcut_header->flags |= WSH_FLAG_IDLIST;
- shortcut_header->run = SW_NORMAL;
- cp = buf + sizeof (win_shortcut_hdr);
-
- /* Create IDLIST */
- if (pidl)
{
- *(unsigned short *)cp = pidl_len;
- memcpy (cp += 2, pidl, pidl_len);
- cp += pidl_len;
- CoTaskMemFree (pidl);
+ /* Default technique creating a symlink. */
+ buf = tp.t_get ();
+ cp = stpcpy (buf, SYMLINK_COOKIE);
+ *(PWCHAR) cp = 0xfeff; /* BOM */
+ cp += 2;
+ /* Note that the terminating nul is written. */
+ cp += sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath)
+ * sizeof (WCHAR);
}
- /* Create description */
- *(unsigned short *)cp = desc_len;
- cp = stpcpy (cp += 2, desc);
-
- /* Create relpath */
- *(unsigned short *)cp = relpath_len;
- cp = stpcpy (cp += 2, relpath);
-
- /* Append the POSIX path after the regular shortcut data for
- the long path support. */
- unsigned short *plen = (unsigned short *) cp;
- cp += 2;
- *(PWCHAR) cp = 0xfeff; /* BOM */
- cp += 2;
- *plen = sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath) * sizeof (WCHAR);
- cp += *plen;
- }
- else
- {
- /* Default technique creating a symlink. */
- buf = tp.t_get ();
- cp = stpcpy (buf, SYMLINK_COOKIE);
- *(PWCHAR) cp = 0xfeff; /* BOM */
- cp += 2;
- /* Note that the terminating nul is written. */
- cp += sys_mbstowcs ((PWCHAR) cp, NT_MAX_PATH, oldpath) * sizeof (WCHAR);
- }
-
- OBJECT_ATTRIBUTES attr;
- IO_STATUS_BLOCK io;
- NTSTATUS status;
- ULONG access;
- HANDLE fh;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ NTSTATUS status;
+ ULONG access;
+ HANDLE fh;
- access = DELETE | FILE_GENERIC_WRITE;
- if (isdevice && win32_newpath.exists ())
- {
- status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES,
- win32_newpath.get_object_attr (attr, sec_none_nih),
- &io, 0, FILE_OPEN_FOR_BACKUP_INTENT);
+ access = DELETE | FILE_GENERIC_WRITE;
+ if (isdevice && win32_newpath.exists ())
+ {
+ status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES,
+ win32_newpath.get_object_attr (attr,
+ sec_none_nih),
+ &io, 0, FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ __leave;
+ }
+ status = NtSetAttributesFile (fh, FILE_ATTRIBUTE_NORMAL);
+ NtClose (fh);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ __leave;
+ }
+ }
+ else if (!isdevice && win32_newpath.has_acls ()
+ && !win32_newpath.isremote ())
+ /* If the filesystem supports ACLs, we will overwrite the DACL after the
+ call to NtCreateFile. This requires a handle with READ_CONTROL and
+ WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
+ open the file again.
+ FIXME: On remote NTFS shares open sometimes fails because even the
+ creator of the file doesn't have the right to change the DACL.
+ I don't know what setting that is or how to recognize such a share,
+ so for now we don't request WRITE_DAC on remote drives. */
+ access |= READ_CONTROL | WRITE_DAC;
+
+ status = NtCreateFile (&fh, access,
+ win32_newpath.get_object_attr (attr, sec_none_nih),
+ &io, NULL, FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_VALID_FLAGS,
+ isdevice ? FILE_OVERWRITE_IF : FILE_CREATE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_NON_DIRECTORY_FILE
+ | FILE_OPEN_FOR_BACKUP_INTENT,
+ NULL, 0);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
- goto done;
+ __leave;
}
- status = NtSetAttributesFile (fh, FILE_ATTRIBUTE_NORMAL);
- NtClose (fh);
- if (!NT_SUCCESS (status))
+ if (win32_newpath.has_acls ())
+ set_file_attribute (fh, win32_newpath, ILLEGAL_UID, ILLEGAL_GID,
+ (io.Information == FILE_CREATED ? S_JUSTCREATED : 0)
+ | S_IFLNK | STD_RBITS | STD_WBITS);
+ status = NtWriteFile (fh, NULL, NULL, NULL, &io, buf, cp - buf,
+ NULL, NULL);
+ if (NT_SUCCESS (status) && io.Information == (ULONG) (cp - buf))
+ {
+ status = NtSetAttributesFile (fh, wsym_type == WSYM_lnk
+ ? FILE_ATTRIBUTE_READONLY
+ : FILE_ATTRIBUTE_SYSTEM);
+ if (!NT_SUCCESS (status))
+ debug_printf ("Setting attributes failed, status = %y", status);
+ res = 0;
+ }
+ else
{
__seterrno_from_nt_status (status);
- goto done;
+ FILE_DISPOSITION_INFORMATION fdi = { TRUE };
+ status = NtSetInformationFile (fh, &io, &fdi, sizeof fdi,
+ FileDispositionInformation);
+ if (!NT_SUCCESS (status))
+ debug_printf ("Setting delete dispostion failed, status = %y",
+ status);
}
- }
- else if (!isdevice && win32_newpath.has_acls () && !win32_newpath.isremote ())
- /* If the filesystem supports ACLs, we will overwrite the DACL after the
- call to NtCreateFile. This requires a handle with READ_CONTROL and
- WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
- open the file again.
- FIXME: On remote NTFS shares open sometimes fails because even the
- creator of the file doesn't have the right to change the DACL.
- I don't know what setting that is or how to recognize such a share,
- so for now we don't request WRITE_DAC on remote drives. */
- access |= READ_CONTROL | WRITE_DAC;
-
- status = NtCreateFile (&fh, access,
- win32_newpath.get_object_attr (attr, sec_none_nih),
- &io, NULL, FILE_ATTRIBUTE_NORMAL,
- FILE_SHARE_VALID_FLAGS,
- isdevice ? FILE_OVERWRITE_IF : FILE_CREATE,
- FILE_SYNCHRONOUS_IO_NONALERT
- | FILE_NON_DIRECTORY_FILE
- | FILE_OPEN_FOR_BACKUP_INTENT,
- NULL, 0);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_nt_status (status);
- goto done;
- }
- if (win32_newpath.has_acls ())
- set_file_attribute (fh, win32_newpath, ILLEGAL_UID, ILLEGAL_GID,
- (io.Information == FILE_CREATED ? S_JUSTCREATED : 0)
- | S_IFLNK | STD_RBITS | STD_WBITS);
- status = NtWriteFile (fh, NULL, NULL, NULL, &io, buf, cp - buf, NULL, NULL);
- if (NT_SUCCESS (status) && io.Information == (ULONG) (cp - buf))
- {
- status = NtSetAttributesFile (fh, wsym_type == WSYM_lnk
- ? FILE_ATTRIBUTE_READONLY
- : FILE_ATTRIBUTE_SYSTEM);
- if (!NT_SUCCESS (status))
- debug_printf ("Setting attributes failed, status = %y", status);
- res = 0;
- }
- else
- {
- __seterrno_from_nt_status (status);
- FILE_DISPOSITION_INFORMATION fdi = { TRUE };
- status = NtSetInformationFile (fh, &io, &fdi, sizeof fdi,
- FileDispositionInformation);
- if (!NT_SUCCESS (status))
- debug_printf ("Setting delete dispostion failed, status = %y", status);
- }
- NtClose (fh);
+ NtClose (fh);
-done:
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%d = symlink_worker(%s, %s, %d)",
res, oldpath, newpath, isdevice);
if (has_trailing_dirsep)
@@ -3109,13 +3132,16 @@ extern "C" char *
getcwd (char *buf, size_t ulen)
{
char* res = NULL;
- myfault efault;
- if (efault.faulted (EFAULT))
- /* errno set */;
- else if (ulen == 0 && buf)
- set_errno (EINVAL);
- else
- res = cygheap->cwd.get (buf, 1, 1, ulen);
+
+ __try
+ {
+ if (ulen == 0 && buf)
+ set_errno (EINVAL);
+ else
+ res = cygheap->cwd.get (buf, 1, 1, ulen);
+ }
+ __except (EFAULT) {}
+ __endtry
return res;
}
@@ -3150,58 +3176,64 @@ get_current_dir_name (void)
extern "C" int
chdir (const char *in_dir)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (!*in_dir)
+ int res = -1;
+
+ __try
{
- set_errno (ENOENT);
- return -1;
- }
+ if (!*in_dir)
+ {
+ set_errno (ENOENT);
+ __leave;
+ }
- syscall_printf ("dir '%s'", in_dir);
+ syscall_printf ("dir '%s'", in_dir);
- /* Convert path. First argument ensures that we don't check for NULL/empty/invalid
- again. */
- path_conv path (PC_NONULLEMPTY, in_dir, PC_SYM_FOLLOW | PC_POSIX);
- if (path.error)
- {
- set_errno (path.error);
- syscall_printf ("-1 = chdir (%s)", in_dir);
- return -1;
- }
+ /* Convert path. First argument ensures that we don't check for
+ NULL/empty/invalid again. */
+ path_conv path (PC_NONULLEMPTY, in_dir, PC_SYM_FOLLOW | PC_POSIX);
+ if (path.error)
+ {
+ set_errno (path.error);
+ syscall_printf ("-1 = chdir (%s)", in_dir);
+ __leave;
+ }
- int res = -1;
- const char *posix_cwd = NULL;
- dev_t devn = path.get_device ();
- if (!path.exists ())
- set_errno (ENOENT);
- else if (!path.isdir ())
- set_errno (ENOTDIR);
- else if (!isvirtual_dev (devn))
+ const char *posix_cwd = NULL;
+ dev_t devn = path.get_device ();
+ if (!path.exists ())
+ set_errno (ENOENT);
+ else if (!path.isdir ())
+ set_errno (ENOTDIR);
+ else if (!isvirtual_dev (devn))
+ {
+ /* The sequence chdir("xx"); chdir(".."); must be a noop if xx
+ is not a symlink. This is exploited by find.exe.
+ The posix_cwd is just path.normalized_path.
+ In other cases we let cwd.set obtain the Posix path through
+ the mount table. */
+ if (!isdrive(path.normalized_path))
+ posix_cwd = path.normalized_path;
+ res = 0;
+ }
+ else
+ {
+ posix_cwd = path.normalized_path;
+ res = 0;
+ }
+
+ if (!res)
+ res = cygheap->cwd.set (&path, posix_cwd);
+
+ /* Note that we're accessing cwd.posix without a lock here.
+ I didn't think it was worth locking just for strace. */
+ syscall_printf ("%R = chdir() cygheap->cwd.posix '%s' native '%S'", res,
+ cygheap->cwd.get_posix (), path.get_nt_native_path ());
+ }
+ __except (EFAULT)
{
- /* The sequence chdir("xx"); chdir(".."); must be a noop if xx
- is not a symlink. This is exploited by find.exe.
- The posix_cwd is just path.normalized_path.
- In other cases we let cwd.set obtain the Posix path through
- the mount table. */
- if (!isdrive(path.normalized_path))
- posix_cwd = path.normalized_path;
- res = 0;
+ res = -1;
}
- else
- {
- posix_cwd = path.normalized_path;
- res = 0;
- }
-
- if (!res)
- res = cygheap->cwd.set (&path, posix_cwd);
-
- /* Note that we're accessing cwd.posix without a lock here. I didn't think
- it was worth locking just for strace. */
- syscall_printf ("%R = chdir() cygheap->cwd.posix '%s' native '%S'", res,
- cygheap->cwd.get_posix (), path.get_nt_native_path ());
+ __endtry
MALLOC_CHECK;
return res;
}
@@ -3239,10 +3271,6 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
size_t size)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
path_conv p;
size_t lsiz = 0;
char *buf = NULL;
@@ -3250,152 +3278,177 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
int error = 0;
bool relative = !!(what & CCP_RELATIVE);
what &= CCP_CONVTYPE_MASK;
+ int ret = -1;
- if (!from)
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
+ if (!from)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
- switch (what)
- {
- case CCP_POSIX_TO_WIN_A:
- {
- p.check ((const char *) from,
- PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP
- | PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0));
- if (p.error)
- return_with_errno (p.error);
- PUNICODE_STRING up = p.get_nt_native_path ();
- buf = tp.c_get ();
- sys_wcstombs (buf, NT_MAX_PATH,
- up->Buffer, up->Length / sizeof (WCHAR));
- /* Convert native path to standard DOS path. */
- if (!strncmp (buf, "\\??\\", 4))
- {
- buf += 4;
- if (buf[1] != ':') /* native UNC path */
- *(buf += 2) = '\\';
- }
- else if (*buf == '\\')
+ switch (what)
+ {
+ case CCP_POSIX_TO_WIN_A:
{
- /* Device name points to somewhere else in the NT namespace.
- Use GLOBALROOT prefix to convert to Win32 path. */
- char *p = buf + sys_wcstombs (buf, NT_MAX_PATH,
- ro_u_globalroot.Buffer,
- ro_u_globalroot.Length
- / sizeof (WCHAR));
- sys_wcstombs (p, NT_MAX_PATH - (p - buf),
+ p.check ((const char *) from,
+ PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP
+ | PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0));
+ if (p.error)
+ {
+ set_errno (p.error);
+ __leave;
+ }
+ PUNICODE_STRING up = p.get_nt_native_path ();
+ buf = tp.c_get ();
+ sys_wcstombs (buf, NT_MAX_PATH,
up->Buffer, up->Length / sizeof (WCHAR));
+ /* Convert native path to standard DOS path. */
+ if (!strncmp (buf, "\\??\\", 4))
+ {
+ buf += 4;
+ if (buf[1] != ':') /* native UNC path */
+ *(buf += 2) = '\\';
+ }
+ else if (*buf == '\\')
+ {
+ /* Device name points to somewhere else in the NT namespace.
+ Use GLOBALROOT prefix to convert to Win32 path. */
+ char *p = buf + sys_wcstombs (buf, NT_MAX_PATH,
+ ro_u_globalroot.Buffer,
+ ro_u_globalroot.Length
+ / sizeof (WCHAR));
+ sys_wcstombs (p, NT_MAX_PATH - (p - buf),
+ up->Buffer, up->Length / sizeof (WCHAR));
+ }
+ lsiz = strlen (buf) + 1;
+ /* TODO: Incoming "." is a special case which leads to a trailing
+ backslash ".\\" in the Win32 path. That's a result of the
+ conversion in normalize_posix_path. This should not occur
+ so the below code is just a band-aid. */
+ if (relative && !strcmp ((const char *) from, ".")
+ && !strcmp (buf, ".\\"))
+ {
+ lsiz = 2;
+ buf[1] = '\0';
+ }
}
- lsiz = strlen (buf) + 1;
- /* TODO: Incoming "." is a special case which leads to a trailing
- backslash ".\\" in the Win32 path. That's a result of the
- conversion in normalize_posix_path. This should not occur
- so the below code is just a band-aid. */
- if (relative && !strcmp ((const char *) from, ".")
- && !strcmp (buf, ".\\"))
- {
- lsiz = 2;
- buf[1] = '\0';
- }
- }
- break;
- case CCP_POSIX_TO_WIN_W:
- p.check ((const char *) from,
- PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP
- | PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0));
- if (p.error)
- return_with_errno (p.error);
- /* Relative Windows paths are always restricted to MAX_PATH chars. */
- if (relative && !isabspath (p.get_win32 ())
- && sys_mbstowcs (NULL, 0, p.get_win32 ()) > MAX_PATH)
- {
- /* Recreate as absolute path. */
- p.check ((const char *) from, PC_POSIX | PC_SYM_FOLLOW
- | PC_NO_ACCESS_CHECK | PC_NOWARN);
+ break;
+ case CCP_POSIX_TO_WIN_W:
+ p.check ((const char *) from,
+ PC_POSIX | PC_SYM_FOLLOW | PC_SYM_NOFOLLOW_REP
+ | PC_NO_ACCESS_CHECK | PC_NOWARN | (relative ? PC_NOFULL : 0));
if (p.error)
- return_with_errno (p.error);
- }
- lsiz = p.get_wide_win32_path_len () + 1;
- path = p.get_nt_native_path ()->Buffer;
+ {
+ set_errno (p.error);
+ __leave;
+ }
+ /* Relative Windows paths are always restricted to MAX_PATH chars. */
+ if (relative && !isabspath (p.get_win32 ())
+ && sys_mbstowcs (NULL, 0, p.get_win32 ()) > MAX_PATH)
+ {
+ /* Recreate as absolute path. */
+ p.check ((const char *) from, PC_POSIX | PC_SYM_FOLLOW
+ | PC_NO_ACCESS_CHECK | PC_NOWARN);
+ if (p.error)
+ {
+ set_errno (p.error);
+ __leave;
+ }
+ }
+ lsiz = p.get_wide_win32_path_len () + 1;
+ path = p.get_nt_native_path ()->Buffer;
- /* Convert native path to standard DOS path. */
- if (!wcsncmp (path, L"\\??\\", 4))
- {
- path[1] = L'\\';
-
- /* Drop long path prefix for short pathnames. Unfortunately there's
- quite a bunch of Win32 functions, especially in user32.dll,
- apparently, which don't grok long path names at all, not even
- in the UNICODE API. */
- if ((path[5] == L':' && lsiz <= MAX_PATH + 4)
- || (!wcsncmp (path + 4, L"UNC\\", 4) && lsiz <= MAX_PATH + 6))
+ /* Convert native path to standard DOS path. */
+ if (!wcsncmp (path, L"\\??\\", 4))
{
- path += 4;
- lsiz -= 4;
- if (path[1] != L':')
+ path[1] = L'\\';
+
+ /* Drop long path prefix for short pathnames. Unfortunately there's
+ quite a bunch of Win32 functions, especially in user32.dll,
+ apparently, which don't grok long path names at all, not even
+ in the UNICODE API. */
+ if ((path[5] == L':' && lsiz <= MAX_PATH + 4)
+ || (!wcsncmp (path + 4, L"UNC\\", 4) && lsiz <= MAX_PATH + 6))
{
- *(path += 2) = '\\';
- lsiz -= 2;
+ path += 4;
+ lsiz -= 4;
+ if (path[1] != L':')
+ {
+ *(path += 2) = '\\';
+ lsiz -= 2;
+ }
}
}
+ else if (*path == L'\\')
+ {
+ /* Device name points to somewhere else in the NT namespace.
+ Use GLOBALROOT prefix to convert to Win32 path. */
+ to = (void *) wcpcpy ((wchar_t *) to, ro_u_globalroot.Buffer);
+ lsiz += ro_u_globalroot.Length / sizeof (WCHAR);
+ }
+ /* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */
+ if (relative && !strcmp ((const char *) from, ".")
+ && !wcscmp (path, L".\\"))
+ {
+ lsiz = 2;
+ path[1] = L'\0';
+ }
+ lsiz *= sizeof (WCHAR);
+ break;
+ case CCP_WIN_A_TO_POSIX:
+ buf = tp.c_get ();
+ error = mount_table->conv_to_posix_path ((const char *) from, buf,
+ relative);
+ if (error)
+ {
+ set_errno (p.error);
+ __leave;
+ }
+ lsiz = strlen (buf) + 1;
+ break;
+ case CCP_WIN_W_TO_POSIX:
+ buf = tp.c_get ();
+ error = mount_table->conv_to_posix_path ((const PWCHAR) from, buf,
+ relative);
+ if (error)
+ {
+ set_errno (error);
+ __leave;
+ }
+ lsiz = strlen (buf) + 1;
+ break;
+ default:
+ set_errno (EINVAL);
+ __leave;
}
- else if (*path == L'\\')
+ if (!size)
{
- /* Device name points to somewhere else in the NT namespace.
- Use GLOBALROOT prefix to convert to Win32 path. */
- to = (void *) wcpcpy ((wchar_t *) to, ro_u_globalroot.Buffer);
- lsiz += ro_u_globalroot.Length / sizeof (WCHAR);
+ ret = lsiz;
+ __leave;
}
- /* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */
- if (relative && !strcmp ((const char *) from, ".")
- && !wcscmp (path, L".\\"))
+ if (size < lsiz)
{
- lsiz = 2;
- path[1] = L'\0';
+ set_errno (ENOSPC);
+ __leave;
}
- lsiz *= sizeof (WCHAR);
- break;
- case CCP_WIN_A_TO_POSIX:
- buf = tp.c_get ();
- error = mount_table->conv_to_posix_path ((const char *) from, buf,
- relative);
- if (error)
- return_with_errno (error);
- lsiz = strlen (buf) + 1;
- break;
- case CCP_WIN_W_TO_POSIX:
- buf = tp.c_get ();
- error = mount_table->conv_to_posix_path ((const PWCHAR) from, buf,
- relative);
- if (error)
- return_with_errno (error);
- lsiz = strlen (buf) + 1;
- break;
- default:
- set_errno (EINVAL);
- return -1;
- }
- if (!size)
- return lsiz;
- if (size < lsiz)
- {
- set_errno (ENOSPC);
- return -1;
- }
- switch (what)
- {
- case CCP_POSIX_TO_WIN_A:
- case CCP_WIN_A_TO_POSIX:
- case CCP_WIN_W_TO_POSIX:
- stpcpy ((char *) to, buf);
- break;
- case CCP_POSIX_TO_WIN_W:
- wcpcpy ((PWCHAR) to, path);
- break;
+ switch (what)
+ {
+ case CCP_POSIX_TO_WIN_A:
+ case CCP_WIN_A_TO_POSIX:
+ case CCP_WIN_W_TO_POSIX:
+ stpcpy ((char *) to, buf);
+ break;
+ case CCP_POSIX_TO_WIN_W:
+ wcpcpy ((PWCHAR) to, path);
+ break;
+ }
+ ret = 0;
}
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return ret;
}
extern "C" void *
@@ -3454,6 +3507,9 @@ cygwin_conv_to_full_posix_path (const char *path, char *posix_path)
extern "C" char *
realpath (const char *__restrict path, char *__restrict resolved)
{
+ tmp_pathbuf tp;
+ char *tpath;
+
/* Make sure the right errno is returned if path is NULL. */
if (!path)
{
@@ -3463,48 +3519,48 @@ realpath (const char *__restrict path, char *__restrict resolved)
/* Guard reading from a potentially invalid path and writing to a
potentially invalid resolved. */
- tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
-
- /* Win32 drive letter paths have to be converted to a POSIX path first,
- because path_conv leaves the incoming path untouched except for
- converting backslashes to forward slashes. */
- char *tpath;
- if (isdrive (path))
+ __try
{
- tpath = tp.c_get ();
- mount_table->conv_to_posix_path (path, tpath, 0);
- }
- else
- tpath = (char *) path;
+ /* Win32 drive letter paths have to be converted to a POSIX path first,
+ because path_conv leaves the incoming path untouched except for
+ converting backslashes to forward slashes. */
+ if (isdrive (path))
+ {
+ tpath = tp.c_get ();
+ mount_table->conv_to_posix_path (path, tpath, 0);
+ }
+ else
+ tpath = (char *) path;
- path_conv real_path (tpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
+ path_conv real_path (tpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
- /* POSIX 2008 requires malloc'ing if resolved is NULL, and states
- that using non-NULL resolved is asking for portability
- problems. */
+ /* POSIX 2008 requires malloc'ing if resolved is NULL, and states
+ that using non-NULL resolved is asking for portability
+ problems. */
- if (!real_path.error && real_path.exists ())
- {
- if (!resolved)
+ if (!real_path.error && real_path.exists ())
{
- resolved = (char *) malloc (strlen (real_path.normalized_path) + 1);
if (!resolved)
- return NULL;
+ {
+ resolved = (char *)
+ malloc (strlen (real_path.normalized_path) + 1);
+ if (!resolved)
+ return NULL;
+ }
+ strcpy (resolved, real_path.normalized_path);
+ return resolved;
}
- strcpy (resolved, real_path.normalized_path);
- return resolved;
- }
- /* FIXME: on error, Linux puts the name of the path
- component which could not be resolved into RESOLVED, but POSIX
- does not require this. */
- if (resolved)
- resolved[0] = '\0';
- set_errno (real_path.error ?: ENOENT);
+ /* FIXME: on error, Linux puts the name of the path
+ component which could not be resolved into RESOLVED, but POSIX
+ does not require this. */
+ if (resolved)
+ resolved[0] = '\0';
+ set_errno (real_path.error ?: ENOENT);
+ }
+ __except (EFAULT) {}
+ __endtry
return NULL;
}
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index 8ce4a28be..17411a098 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -1,7 +1,7 @@
/* poll.cc. Implements poll(2) via usage of select(2) call.
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.
@@ -143,16 +143,19 @@ ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts,
int timeout;
sigset_t oldset = _my_tls.sigmask;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- timeout = (timeout_ts == NULL)
- ? -1
- : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
- if (sigmask)
- set_signal_mask (_my_tls.sigmask, *sigmask);
- int ret = poll (fds, nfds, timeout);
- if (sigmask)
- set_signal_mask (_my_tls.sigmask, oldset);
- return ret;
+ __try
+ {
+ timeout = (timeout_ts == NULL)
+ ? -1
+ : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000);
+ if (sigmask)
+ set_signal_mask (_my_tls.sigmask, *sigmask);
+ int ret = poll (fds, nfds, timeout);
+ if (sigmask)
+ set_signal_mask (_my_tls.sigmask, oldset);
+ return ret;
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
diff --git a/winsup/cygwin/posix_ipc.cc b/winsup/cygwin/posix_ipc.cc
index be4a973a9..067fa5bb0 100644
--- a/winsup/cygwin/posix_ipc.cc
+++ b/winsup/cygwin/posix_ipc.cc
@@ -1,6 +1,6 @@
/* posix_ipc.cc: POSIX IPC API for Cygwin.
- Copyright 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
+ Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2014 Red Hat, Inc.
This file is part of Cygwin.
@@ -414,17 +414,17 @@ extern "C" void *mmap64 (void *, size_t, int, int, int, off_t);
extern "C" mqd_t
mq_open (const char *name, int oflag, ...)
{
- int i, fd = -1, nonblock, created;
+ int i, fd = -1, nonblock, created = 0;
long msgsize, index;
off_t filesize = 0;
va_list ap;
mode_t mode;
- int8_t *mptr;
+ int8_t *mptr = (int8_t *) MAP_FAILED;
struct stat statbuff;
struct mq_hdr *mqhdr;
struct msg_hdr *msghdr;
struct mq_attr *attr;
- struct mq_info *mqinfo;
+ struct mq_info *mqinfo = NULL;
LUID luid;
size_t len = strlen (name);
@@ -433,190 +433,198 @@ mq_open (const char *name, int oflag, ...)
if (!check_path (mqname, mqueue, name, len))
return (mqd_t) -1;
- myfault efault;
- if (efault.faulted (EFAULT))
- return (mqd_t) -1;
+ __try
+ {
+ oflag &= (O_CREAT | O_EXCL | O_NONBLOCK);
+ nonblock = oflag & O_NONBLOCK;
+ oflag &= ~O_NONBLOCK;
- oflag &= (O_CREAT | O_EXCL | O_NONBLOCK);
- created = 0;
- nonblock = oflag & O_NONBLOCK;
- oflag &= ~O_NONBLOCK;
- mptr = (int8_t *) MAP_FAILED;
- mqinfo = NULL;
+ again:
+ if (oflag & O_CREAT)
+ {
+ va_start (ap, oflag); /* init ap to final named argument */
+ mode = va_arg (ap, mode_t) & ~S_IXUSR;
+ attr = va_arg (ap, struct mq_attr *);
+ va_end (ap);
+
+ /* Open and specify O_EXCL and user-execute */
+ fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
+ mode | S_IXUSR);
+ if (fd < 0)
+ {
+ if (errno == EEXIST && (oflag & O_EXCL) == 0)
+ goto exists; /* already exists, OK */
+ return (mqd_t) -1;
+ }
+ created = 1;
+ /* First one to create the file initializes it */
+ if (attr == NULL)
+ attr = &defattr;
+ /* Check minimum and maximum values. The max values are pretty much
+ arbitrary, taken from the linux mq_overview man page. However,
+ these max values make sure that the internal mq_fattr structure
+ can use 32 bit types. */
+ else if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768
+ || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ /* Calculate and set the file size */
+ msgsize = MSGSIZE (attr->mq_msgsize);
+ filesize = sizeof (struct mq_hdr)
+ + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
+ if (lseek64 (fd, filesize - 1, SEEK_SET) == -1)
+ __leave;
+ if (write (fd, "", 1) == -1)
+ __leave;
+
+ /* Memory map the file */
+ mptr = (int8_t *) mmap64 (NULL, (size_t) filesize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (mptr == (int8_t *) MAP_FAILED)
+ __leave;
+
+ /* Allocate one mq_info{} for the queue */
+ if (!(mqinfo = (struct mq_info *)
+ calloc (1, sizeof (struct mq_info))))
+ __leave;
+ mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
+ mqinfo->mqi_magic = MQI_MAGIC;
+ mqinfo->mqi_flags = nonblock;
+
+ /* Initialize header at beginning of file */
+ /* Create free list with all messages on it */
+ mqhdr->mqh_attr.mq_flags = 0;
+ mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
+ mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
+ mqhdr->mqh_attr.mq_curmsgs = 0;
+ mqhdr->mqh_nwait = 0;
+ mqhdr->mqh_pid = 0;
+ NtAllocateLocallyUniqueId (&luid);
+ __small_sprintf (mqhdr->mqh_uname, "%016X%08x%08x",
+ hash_path_name (0,mqname),
+ luid.HighPart, luid.LowPart);
+ mqhdr->mqh_head = 0;
+ mqhdr->mqh_magic = MQI_MAGIC;
+ index = sizeof (struct mq_hdr);
+ mqhdr->mqh_free = index;
+ for (i = 0; i < attr->mq_maxmsg - 1; i++)
+ {
+ msghdr = (struct msg_hdr *) &mptr[index];
+ index += sizeof (struct msg_hdr) + msgsize;
+ msghdr->msg_next = index;
+ }
+ msghdr = (struct msg_hdr *) &mptr[index];
+ msghdr->msg_next = 0; /* end of free list */
-again:
- if (oflag & O_CREAT)
- {
- va_start (ap, oflag); /* init ap to final named argument */
- mode = va_arg (ap, mode_t) & ~S_IXUSR;
- attr = va_arg (ap, struct mq_attr *);
- va_end (ap);
-
- /* Open and specify O_EXCL and user-execute */
- fd = open (mqname, oflag | O_EXCL | O_RDWR | O_CLOEXEC, mode | S_IXUSR);
- if (fd < 0)
+ /* Initialize mutex & condition variables */
+ i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
+ if (i != 0)
+ {
+ set_errno (i);
+ __leave;
+ }
+ i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
+ if (i != 0)
+ {
+ set_errno (i);
+ __leave;
+ }
+ i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
+ if (i != 0)
+ {
+ set_errno (i);
+ __leave;
+ }
+ /* Initialization complete, turn off user-execute bit */
+ if (fchmod (fd, mode) == -1)
+ __leave;
+ close (fd);
+ return ((mqd_t) mqinfo);
+ }
+
+ exists:
+ /* Open the file then memory map */
+ if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0)
{
- if (errno == EEXIST && (oflag & O_EXCL) == 0)
- goto exists; /* already exists, OK */
- return (mqd_t) -1;
+ if (errno == ENOENT && (oflag & O_CREAT))
+ goto again;
+ __leave;
}
- created = 1;
- /* First one to create the file initializes it */
- if (attr == NULL)
- attr = &defattr;
- /* Check minimum and maximum values. The max values are pretty much
- arbitrary, taken from the linux mq_overview man page. However,
- these max values make sure that the internal mq_fattr structure
- can use 32 bit types. */
- else if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > 32768
- || attr->mq_msgsize <= 0 || attr->mq_msgsize > 1048576)
+ /* Make certain initialization is complete */
+ for (i = 0; i < MAX_TRIES; i++)
{
- set_errno (EINVAL);
- goto err;
+ if (stat64 (mqname, &statbuff) == -1)
+ {
+ if (errno == ENOENT && (oflag & O_CREAT))
+ {
+ close (fd);
+ fd = -1;
+ goto again;
+ }
+ __leave;
+ }
+ if ((statbuff.st_mode & S_IXUSR) == 0)
+ break;
+ sleep (1);
+ }
+ if (i == MAX_TRIES)
+ {
+ set_errno (ETIMEDOUT);
+ __leave;
}
- /* Calculate and set the file size */
- msgsize = MSGSIZE (attr->mq_msgsize);
- filesize = sizeof (struct mq_hdr)
- + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
- if (lseek64 (fd, filesize - 1, SEEK_SET) == -1)
- goto err;
- if (write (fd, "", 1) == -1)
- goto err;
- /* Memory map the file */
+ filesize = statbuff.st_size;
mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (mptr == (int8_t *) MAP_FAILED)
- goto err;
+ __leave;
+ close (fd);
+ fd = -1;
- /* Allocate one mq_info{} for the queue */
+ /* Allocate one mq_info{} for each open */
if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info))))
- goto err;
+ __leave;
mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
- mqinfo->mqi_magic = MQI_MAGIC;
- mqinfo->mqi_flags = nonblock;
-
- /* Initialize header at beginning of file */
- /* Create free list with all messages on it */
- mqhdr->mqh_attr.mq_flags = 0;
- mqhdr->mqh_attr.mq_maxmsg = attr->mq_maxmsg;
- mqhdr->mqh_attr.mq_msgsize = attr->mq_msgsize;
- mqhdr->mqh_attr.mq_curmsgs = 0;
- mqhdr->mqh_nwait = 0;
- mqhdr->mqh_pid = 0;
- NtAllocateLocallyUniqueId (&luid);
- __small_sprintf (mqhdr->mqh_uname, "%016X%08x%08x",
- hash_path_name (0,mqname),
- luid.HighPart, luid.LowPart);
- mqhdr->mqh_head = 0;
- mqhdr->mqh_magic = MQI_MAGIC;
- index = sizeof (struct mq_hdr);
- mqhdr->mqh_free = index;
- for (i = 0; i < attr->mq_maxmsg - 1; i++)
+ if (mqhdr->mqh_magic != MQI_MAGIC)
{
- msghdr = (struct msg_hdr *) &mptr[index];
- index += sizeof (struct msg_hdr) + msgsize;
- msghdr->msg_next = index;
+ system_printf (
+ "Old message queue \"%s\" detected!\n"
+ "This file is not usable as message queue anymore due to changes in the "
+ "internal file layout. Please remove the file and try again.", mqname);
+ set_errno (EACCES);
+ __leave;
}
- msghdr = (struct msg_hdr *) &mptr[index];
- msghdr->msg_next = 0; /* end of free list */
+ mqinfo->mqi_magic = MQI_MAGIC;
+ mqinfo->mqi_flags = nonblock;
- /* Initialize mutex & condition variables */
+ /* Initialize mutex & condition variable */
i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
if (i != 0)
- goto pthreaderr;
-
+ {
+ set_errno (i);
+ __leave;
+ }
i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
if (i != 0)
- goto pthreaderr;
-
+ {
+ set_errno (i);
+ __leave;
+ }
i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
if (i != 0)
- goto pthreaderr;
-
- /* Initialization complete, turn off user-execute bit */
- if (fchmod (fd, mode) == -1)
- goto err;
- close (fd);
- return ((mqd_t) mqinfo);
- }
-
-exists:
- /* Open the file then memory map */
- if ((fd = open (mqname, O_RDWR | O_CLOEXEC)) < 0)
- {
- if (errno == ENOENT && (oflag & O_CREAT))
- goto again;
- goto err;
- }
- /* Make certain initialization is complete */
- for (i = 0; i < MAX_TRIES; i++)
- {
- if (stat64 (mqname, &statbuff) == -1)
{
- if (errno == ENOENT && (oflag & O_CREAT))
- {
- close (fd);
- fd = -1;
- goto again;
- }
- goto err;
+ set_errno (i);
+ __leave;
}
- if ((statbuff.st_mode & S_IXUSR) == 0)
- break;
- sleep (1);
+ return (mqd_t) mqinfo;
}
- if (i == MAX_TRIES)
- {
- set_errno (ETIMEDOUT);
- goto err;
- }
-
- filesize = statbuff.st_size;
- mptr = (int8_t *) mmap64 (NULL, (size_t) filesize, PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, 0);
- if (mptr == (int8_t *) MAP_FAILED)
- goto err;
- close (fd);
- fd = -1;
-
- /* Allocate one mq_info{} for each open */
- if (!(mqinfo = (struct mq_info *) calloc (1, sizeof (struct mq_info))))
- goto err;
- mqinfo->mqi_hdr = mqhdr = (struct mq_hdr *) mptr;
- if (mqhdr->mqh_magic != MQI_MAGIC)
- {
- system_printf (
-"Old message queue \"%s\" detected!\n"
-"This file is not usable as message queue anymore due to changes in the "
-"internal file layout. Please remove the file and try again.", mqname);
- set_errno (EACCES);
- goto err;
- }
- mqinfo->mqi_magic = MQI_MAGIC;
- mqinfo->mqi_flags = nonblock;
-
- /* Initialize mutex & condition variable */
- i = ipc_mutex_init (&mqinfo->mqi_lock, mqhdr->mqh_uname);
- if (i != 0)
- goto pthreaderr;
-
- i = ipc_cond_init (&mqinfo->mqi_waitsend, mqhdr->mqh_uname, 'S');
- if (i != 0)
- goto pthreaderr;
-
- i = ipc_cond_init (&mqinfo->mqi_waitrecv, mqhdr->mqh_uname, 'R');
- if (i != 0)
- goto pthreaderr;
-
- return (mqd_t) mqinfo;
-
-pthreaderr:
- errno = i;
-err:
+ __except (EFAULT) {}
+ __endtry
/* Don't let following function calls change errno */
save_errno save;
-
if (created)
unlink (mqname);
if (mptr != (int8_t *) MAP_FAILED)
@@ -644,30 +652,32 @@ mq_getattr (mqd_t mqd, struct mq_attr *mqstat)
struct mq_fattr *attr;
struct mq_info *mqinfo;
- myfault efault;
- if (efault.faulted (EBADF))
- return -1;
-
- mqinfo = (struct mq_info *) mqd;
- if (mqinfo->mqi_magic != MQI_MAGIC)
+ __try
{
- set_errno (EBADF);
- return -1;
- }
- mqhdr = mqinfo->mqi_hdr;
- attr = &mqhdr->mqh_attr;
- if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
- {
- errno = n;
- return -1;
- }
- mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */
- mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */
- mqstat->mq_msgsize = attr->mq_msgsize;
- mqstat->mq_curmsgs = attr->mq_curmsgs;
+ mqinfo = (struct mq_info *) mqd;
+ if (mqinfo->mqi_magic != MQI_MAGIC)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
+ mqhdr = mqinfo->mqi_hdr;
+ attr = &mqhdr->mqh_attr;
+ if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ {
+ errno = n;
+ __leave;
+ }
+ mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */
+ mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */
+ mqstat->mq_msgsize = attr->mq_msgsize;
+ mqstat->mq_curmsgs = attr->mq_curmsgs;
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return 0;
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ return 0;
+ }
+ __except (EBADF) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -678,39 +688,41 @@ mq_setattr (mqd_t mqd, const struct mq_attr *mqstat, struct mq_attr *omqstat)
struct mq_fattr *attr;
struct mq_info *mqinfo;
- myfault efault;
- if (efault.faulted (EBADF))
- return -1;
-
- mqinfo = (struct mq_info *) mqd;
- if (mqinfo->mqi_magic != MQI_MAGIC)
- {
- set_errno (EBADF);
- return -1;
- }
- mqhdr = mqinfo->mqi_hdr;
- attr = &mqhdr->mqh_attr;
- if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ __try
{
- errno = n;
- return -1;
- }
+ mqinfo = (struct mq_info *) mqd;
+ if (mqinfo->mqi_magic != MQI_MAGIC)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
+ mqhdr = mqinfo->mqi_hdr;
+ attr = &mqhdr->mqh_attr;
+ if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ {
+ errno = n;
+ __leave;
+ }
- if (omqstat != NULL)
- {
- omqstat->mq_flags = mqinfo->mqi_flags; /* previous attributes */
- omqstat->mq_maxmsg = attr->mq_maxmsg;
- omqstat->mq_msgsize = attr->mq_msgsize;
- omqstat->mq_curmsgs = attr->mq_curmsgs; /* and current status */
- }
+ if (omqstat != NULL)
+ {
+ omqstat->mq_flags = mqinfo->mqi_flags; /* previous attributes */
+ omqstat->mq_maxmsg = attr->mq_maxmsg;
+ omqstat->mq_msgsize = attr->mq_msgsize;
+ omqstat->mq_curmsgs = attr->mq_curmsgs; /* and current status */
+ }
- if (mqstat->mq_flags & O_NONBLOCK)
- mqinfo->mqi_flags |= O_NONBLOCK;
- else
- mqinfo->mqi_flags &= ~O_NONBLOCK;
+ if (mqstat->mq_flags & O_NONBLOCK)
+ mqinfo->mqi_flags |= O_NONBLOCK;
+ else
+ mqinfo->mqi_flags &= ~O_NONBLOCK;
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return 0;
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ return 0;
+ }
+ __except (EBADF) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -721,45 +733,47 @@ mq_notify (mqd_t mqd, const struct sigevent *notification)
struct mq_hdr *mqhdr;
struct mq_info *mqinfo;
- myfault efault;
- if (efault.faulted (EBADF))
- return -1;
-
- mqinfo = (struct mq_info *) mqd;
- if (mqinfo->mqi_magic != MQI_MAGIC)
- {
- set_errno (EBADF);
- return -1;
- }
- mqhdr = mqinfo->mqi_hdr;
- if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ __try
{
- errno = n;
- return -1;
- }
+ mqinfo = (struct mq_info *) mqd;
+ if (mqinfo->mqi_magic != MQI_MAGIC)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
+ mqhdr = mqinfo->mqi_hdr;
+ if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ {
+ errno = n;
+ __leave;
+ }
- pid = getpid ();
- if (!notification)
- {
- if (mqhdr->mqh_pid == pid)
- mqhdr->mqh_pid = 0; /* unregister calling process */
- }
- else
- {
- if (mqhdr->mqh_pid != 0)
+ pid = getpid ();
+ if (!notification)
{
- if (kill (mqhdr->mqh_pid, 0) != -1 || errno != ESRCH)
+ if (mqhdr->mqh_pid == pid)
+ mqhdr->mqh_pid = 0; /* unregister calling process */
+ }
+ else
+ {
+ if (mqhdr->mqh_pid != 0)
{
- set_errno (EBUSY);
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return -1;
+ if (kill (mqhdr->mqh_pid, 0) != -1 || errno != ESRCH)
+ {
+ set_errno (EBUSY);
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ __leave;
+ }
}
+ mqhdr->mqh_pid = pid;
+ mqhdr->mqh_event = *notification;
}
- mqhdr->mqh_pid = pid;
- mqhdr->mqh_event = *notification;
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ return 0;
}
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return 0;
+ __except (EBADF) {}
+ __endtry
+ return -1;
}
static int
@@ -773,113 +787,116 @@ _mq_send (mqd_t mqd, const char *ptr, size_t len, unsigned int prio,
struct mq_hdr *mqhdr;
struct mq_fattr *attr;
struct msg_hdr *msghdr, *nmsghdr, *pmsghdr;
- struct mq_info *mqinfo;
+ struct mq_info *mqinfo = NULL;
+ bool ipc_mutex_locked = false;
+ int ret = -1;
pthread_testcancel ();
- myfault efault;
- if (efault.faulted (EBADF))
- return -1;
-
- mqinfo = (struct mq_info *) mqd;
- if (mqinfo->mqi_magic != MQI_MAGIC)
- {
- set_errno (EBADF);
- return -1;
- }
- if (prio > MQ_PRIO_MAX)
- {
- set_errno (EINVAL);
- return -1;
- }
-
- mqhdr = mqinfo->mqi_hdr; /* struct pointer */
- mptr = (int8_t *) mqhdr; /* byte pointer */
- attr = &mqhdr->mqh_attr;
- if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ __try
{
- errno = n;
- return -1;
- }
+ mqinfo = (struct mq_info *) mqd;
+ if (mqinfo->mqi_magic != MQI_MAGIC)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
+ if (prio > MQ_PRIO_MAX)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
- if (len > (size_t) attr->mq_msgsize)
- {
- set_errno (EMSGSIZE);
- goto err;
- }
- if (attr->mq_curmsgs == 0)
- {
- if (mqhdr->mqh_pid != 0 && mqhdr->mqh_nwait == 0)
+ mqhdr = mqinfo->mqi_hdr; /* struct pointer */
+ mptr = (int8_t *) mqhdr; /* byte pointer */
+ attr = &mqhdr->mqh_attr;
+ if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
{
- sigev = &mqhdr->mqh_event;
- if (sigev->sigev_notify == SIGEV_SIGNAL)
- sigqueue (mqhdr->mqh_pid, sigev->sigev_signo, sigev->sigev_value);
- mqhdr->mqh_pid = 0; /* unregister */
+ errno = n;
+ __leave;
}
- }
- else if (attr->mq_curmsgs >= attr->mq_maxmsg)
- {
- /* Queue is full */
- if (mqinfo->mqi_flags & O_NONBLOCK)
+ ipc_mutex_locked = true;
+ if (len > (size_t) attr->mq_msgsize)
{
- set_errno (EAGAIN);
- goto err;
+ set_errno (EMSGSIZE);
+ __leave;
}
- /* Wait for room for one message on the queue */
- while (attr->mq_curmsgs >= attr->mq_maxmsg)
+ if (attr->mq_curmsgs == 0)
{
- int ret = ipc_cond_timedwait (mqinfo->mqi_waitsend, mqinfo->mqi_lock,
- abstime);
- if (ret != 0)
+ if (mqhdr->mqh_pid != 0 && mqhdr->mqh_nwait == 0)
{
- set_errno (ret);
- return -1;
+ sigev = &mqhdr->mqh_event;
+ if (sigev->sigev_notify == SIGEV_SIGNAL)
+ sigqueue (mqhdr->mqh_pid, sigev->sigev_signo,
+ sigev->sigev_value);
+ mqhdr->mqh_pid = 0; /* unregister */
+ }
+ }
+ else if (attr->mq_curmsgs >= attr->mq_maxmsg)
+ {
+ /* Queue is full */
+ if (mqinfo->mqi_flags & O_NONBLOCK)
+ {
+ set_errno (EAGAIN);
+ __leave;
+ }
+ /* Wait for room for one message on the queue */
+ while (attr->mq_curmsgs >= attr->mq_maxmsg)
+ {
+ int ret = ipc_cond_timedwait (mqinfo->mqi_waitsend,
+ mqinfo->mqi_lock, abstime);
+ if (ret != 0)
+ {
+ set_errno (ret);
+ __leave;
+ }
}
}
- }
- /* nmsghdr will point to new message */
- if ((freeindex = mqhdr->mqh_free) == 0)
- api_fatal ("mq_send: curmsgs = %ld; free = 0", attr->mq_curmsgs);
+ /* nmsghdr will point to new message */
+ if ((freeindex = mqhdr->mqh_free) == 0)
+ api_fatal ("mq_send: curmsgs = %ld; free = 0", attr->mq_curmsgs);
- nmsghdr = (struct msg_hdr *) &mptr[freeindex];
- nmsghdr->msg_prio = prio;
- nmsghdr->msg_len = len;
- memcpy (nmsghdr + 1, ptr, len); /* copy message from caller */
- mqhdr->mqh_free = nmsghdr->msg_next; /* new freelist head */
+ nmsghdr = (struct msg_hdr *) &mptr[freeindex];
+ nmsghdr->msg_prio = prio;
+ nmsghdr->msg_len = len;
+ memcpy (nmsghdr + 1, ptr, len); /* copy message from caller */
+ mqhdr->mqh_free = nmsghdr->msg_next; /* new freelist head */
- /* Find right place for message in linked list */
- index = mqhdr->mqh_head;
- pmsghdr = (struct msg_hdr *) &(mqhdr->mqh_head);
- while (index)
- {
- msghdr = (struct msg_hdr *) &mptr[index];
- if (prio > msghdr->msg_prio)
+ /* Find right place for message in linked list */
+ index = mqhdr->mqh_head;
+ pmsghdr = (struct msg_hdr *) &(mqhdr->mqh_head);
+ while (index)
{
- nmsghdr->msg_next = index;
+ msghdr = (struct msg_hdr *) &mptr[index];
+ if (prio > msghdr->msg_prio)
+ {
+ nmsghdr->msg_next = index;
+ pmsghdr->msg_next = freeindex;
+ break;
+ }
+ index = msghdr->msg_next;
+ pmsghdr = msghdr;
+ }
+ if (index == 0)
+ {
+ /* Queue was empty or new goes at end of list */
pmsghdr->msg_next = freeindex;
- break;
+ nmsghdr->msg_next = 0;
}
- index = msghdr->msg_next;
- pmsghdr = msghdr;
- }
- if (index == 0)
- {
- /* Queue was empty or new goes at end of list */
- pmsghdr->msg_next = freeindex;
- nmsghdr->msg_next = 0;
- }
- /* Wake up anyone blocked in mq_receive waiting for a message */
- if (attr->mq_curmsgs == 0)
- ipc_cond_signal (mqinfo->mqi_waitrecv);
- attr->mq_curmsgs++;
-
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return 0;
+ /* Wake up anyone blocked in mq_receive waiting for a message */
+ if (attr->mq_curmsgs == 0)
+ ipc_cond_signal (mqinfo->mqi_waitrecv);
+ attr->mq_curmsgs++;
-err:
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return -1;
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ ret = 0;
+ }
+ __except (EBADF) {}
+ __endtry
+ if (ipc_mutex_locked)
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ return ret;
}
extern "C" int
@@ -902,85 +919,84 @@ _mq_receive (mqd_t mqd, char *ptr, size_t maxlen, unsigned int *priop,
int n;
long index;
int8_t *mptr;
- ssize_t len;
+ ssize_t len = -1;
struct mq_hdr *mqhdr;
struct mq_fattr *attr;
struct msg_hdr *msghdr;
- struct mq_info *mqinfo;
+ struct mq_info *mqinfo = (struct mq_info *) mqd;
+ bool ipc_mutex_locked = false;
pthread_testcancel ();
- myfault efault;
- if (efault.faulted (EBADF))
- return -1;
-
- mqinfo = (struct mq_info *) mqd;
- if (mqinfo->mqi_magic != MQI_MAGIC)
- {
- set_errno (EBADF);
- return -1;
- }
- mqhdr = mqinfo->mqi_hdr; /* struct pointer */
- mptr = (int8_t *) mqhdr; /* byte pointer */
- attr = &mqhdr->mqh_attr;
- if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
- {
- errno = n;
- return -1;
- }
-
- if (maxlen < (size_t) attr->mq_msgsize)
- {
- set_errno (EMSGSIZE);
- goto err;
- }
- if (attr->mq_curmsgs == 0) /* queue is empty */
+ __try
{
- if (mqinfo->mqi_flags & O_NONBLOCK)
+ if (mqinfo->mqi_magic != MQI_MAGIC)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
+ mqhdr = mqinfo->mqi_hdr; /* struct pointer */
+ mptr = (int8_t *) mqhdr; /* byte pointer */
+ attr = &mqhdr->mqh_attr;
+ if ((n = ipc_mutex_lock (mqinfo->mqi_lock)) != 0)
+ {
+ errno = n;
+ __leave;
+ }
+ ipc_mutex_locked = true;
+ if (maxlen < (size_t) attr->mq_msgsize)
{
- set_errno (EAGAIN);
- goto err;
+ set_errno (EMSGSIZE);
+ __leave;
}
- /* Wait for a message to be placed onto queue */
- mqhdr->mqh_nwait++;
- while (attr->mq_curmsgs == 0)
+ if (attr->mq_curmsgs == 0) /* queue is empty */
{
- int ret = ipc_cond_timedwait (mqinfo->mqi_waitrecv, mqinfo->mqi_lock,
- abstime);
- if (ret != 0)
+ if (mqinfo->mqi_flags & O_NONBLOCK)
{
- set_errno (ret);
- return -1;
+ set_errno (EAGAIN);
+ __leave;
}
+ /* Wait for a message to be placed onto queue */
+ mqhdr->mqh_nwait++;
+ while (attr->mq_curmsgs == 0)
+ {
+ int ret = ipc_cond_timedwait (mqinfo->mqi_waitrecv,
+ mqinfo->mqi_lock, abstime);
+ if (ret != 0)
+ {
+ set_errno (ret);
+ __leave;
+ }
+ }
+ mqhdr->mqh_nwait--;
}
- mqhdr->mqh_nwait--;
- }
-
- if ((index = mqhdr->mqh_head) == 0)
- api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr->mq_curmsgs);
- msghdr = (struct msg_hdr *) &mptr[index];
- mqhdr->mqh_head = msghdr->msg_next; /* new head of list */
- len = msghdr->msg_len;
- memcpy(ptr, msghdr + 1, len); /* copy the message itself */
- if (priop != NULL)
- *priop = msghdr->msg_prio;
+ if ((index = mqhdr->mqh_head) == 0)
+ api_fatal ("mq_receive: curmsgs = %ld; head = 0", attr->mq_curmsgs);
- /* Just-read message goes to front of free list */
- msghdr->msg_next = mqhdr->mqh_free;
- mqhdr->mqh_free = index;
+ msghdr = (struct msg_hdr *) &mptr[index];
+ mqhdr->mqh_head = msghdr->msg_next; /* new head of list */
+ len = msghdr->msg_len;
+ memcpy(ptr, msghdr + 1, len); /* copy the message itself */
+ if (priop != NULL)
+ *priop = msghdr->msg_prio;
+
+ /* Just-read message goes to front of free list */
+ msghdr->msg_next = mqhdr->mqh_free;
+ mqhdr->mqh_free = index;
- /* Wake up anyone blocked in mq_send waiting for room */
- if (attr->mq_curmsgs == attr->mq_maxmsg)
- ipc_cond_signal (mqinfo->mqi_waitsend);
- attr->mq_curmsgs--;
+ /* Wake up anyone blocked in mq_send waiting for room */
+ if (attr->mq_curmsgs == attr->mq_maxmsg)
+ ipc_cond_signal (mqinfo->mqi_waitsend);
+ attr->mq_curmsgs--;
- ipc_mutex_unlock (mqinfo->mqi_lock);
+ ipc_mutex_unlock (mqinfo->mqi_lock);
+ }
+ __except (EBADF) {}
+ __endtry
+ if (ipc_mutex_locked)
+ ipc_mutex_unlock (mqinfo->mqi_lock);
return len;
-
-err:
- ipc_mutex_unlock (mqinfo->mqi_lock);
- return -1;
}
extern "C" ssize_t
@@ -1004,34 +1020,36 @@ mq_close (mqd_t mqd)
struct mq_fattr *attr;
struct mq_info *mqinfo;
- myfault efault;
- if (efault.faulted (EBADF))
- return -1;
-
- mqinfo = (struct mq_info *) mqd;
- if (mqinfo->mqi_magic != MQI_MAGIC)
+ __try
{
- set_errno (EBADF);
- return -1;
- }
- mqhdr = mqinfo->mqi_hdr;
- attr = &mqhdr->mqh_attr;
+ mqinfo = (struct mq_info *) mqd;
+ if (mqinfo->mqi_magic != MQI_MAGIC)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
+ mqhdr = mqinfo->mqi_hdr;
+ attr = &mqhdr->mqh_attr;
- if (mq_notify (mqd, NULL)) /* unregister calling process */
- return -1;
+ if (mq_notify (mqd, NULL)) /* unregister calling process */
+ __leave;
- msgsize = MSGSIZE (attr->mq_msgsize);
- filesize = sizeof (struct mq_hdr)
- + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
- if (munmap (mqinfo->mqi_hdr, filesize) == -1)
- return -1;
+ msgsize = MSGSIZE (attr->mq_msgsize);
+ filesize = sizeof (struct mq_hdr)
+ + (attr->mq_maxmsg * (sizeof (struct msg_hdr) + msgsize));
+ if (munmap (mqinfo->mqi_hdr, filesize) == -1)
+ __leave;
- mqinfo->mqi_magic = 0; /* just in case */
- ipc_cond_close (mqinfo->mqi_waitsend);
- ipc_cond_close (mqinfo->mqi_waitrecv);
- ipc_mutex_close (mqinfo->mqi_lock);
- free (mqinfo);
- return 0;
+ mqinfo->mqi_magic = 0; /* just in case */
+ ipc_cond_close (mqinfo->mqi_waitsend);
+ ipc_cond_close (mqinfo->mqi_waitrecv);
+ ipc_mutex_close (mqinfo->mqi_lock);
+ free (mqinfo);
+ return 0;
+ }
+ __except (EBADF) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -1062,7 +1080,7 @@ struct sem_finfo
extern "C" sem_t *
sem_open (const char *name, int oflag, ...)
{
- int i, fd = -1, created;
+ int i, fd = -1, created = 0;
va_list ap;
mode_t mode = 0;
unsigned int value = 0;
@@ -1078,97 +1096,99 @@ sem_open (const char *name, int oflag, ...)
if (!check_path (semname, semaphore, name, len))
return SEM_FAILED;
- myfault efault;
- if (efault.faulted (EFAULT))
- return SEM_FAILED;
-
- created = 0;
- oflag &= (O_CREAT | O_EXCL);
-
-again:
- if (oflag & O_CREAT)
+ __try
{
- va_start (ap, oflag); /* init ap to final named argument */
- mode = va_arg (ap, mode_t) & ~S_IXUSR;
- value = va_arg (ap, unsigned int);
- va_end (ap);
-
- /* Open and specify O_EXCL and user-execute */
- fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC, mode | S_IXUSR);
- if (fd < 0)
+ oflag &= (O_CREAT | O_EXCL);
+
+ again:
+ if (oflag & O_CREAT)
{
- if (errno == EEXIST && (oflag & O_EXCL) == 0)
- goto exists; /* already exists, OK */
- return SEM_FAILED;
+ va_start (ap, oflag); /* init ap to final named argument */
+ mode = va_arg (ap, mode_t) & ~S_IXUSR;
+ value = va_arg (ap, unsigned int);
+ va_end (ap);
+
+ /* Open and specify O_EXCL and user-execute */
+ fd = open (semname, oflag | O_EXCL | O_RDWR | O_CLOEXEC,
+ mode | S_IXUSR);
+ if (fd < 0)
+ {
+ if (errno == EEXIST && (oflag & O_EXCL) == 0)
+ goto exists; /* already exists, OK */
+ return SEM_FAILED;
+ }
+ created = 1;
+ /* First one to create the file initializes it. */
+ NtAllocateLocallyUniqueId (&sf.luid);
+ sf.value = value;
+ sf.hash = hash_path_name (0, semname);
+ if (write (fd, &sf, sizeof sf) != sizeof sf)
+ __leave;
+ sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value,
+ wasopen);
+ if (sem == SEM_FAILED)
+ __leave;
+ /* Initialization complete, turn off user-execute bit */
+ if (fchmod (fd, mode) == -1)
+ __leave;
+ /* Don't close (fd); */
+ return sem;
}
- created = 1;
- /* First one to create the file initializes it. */
- NtAllocateLocallyUniqueId (&sf.luid);
- sf.value = value;
- sf.hash = hash_path_name (0, semname);
- if (write (fd, &sf, sizeof sf) != sizeof sf)
- goto err;
- sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, value, wasopen);
- if (sem == SEM_FAILED)
- goto err;
- /* Initialization complete, turn off user-execute bit */
- if (fchmod (fd, mode) == -1)
- goto err;
- /* Don't close (fd); */
- return sem;
- }
-exists:
- /* Open the file and fetch the semaphore name. */
- if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0)
- {
- if (errno == ENOENT && (oflag & O_CREAT))
- goto again;
- goto err;
- }
- /* Make certain initialization is complete */
- for (i = 0; i < MAX_TRIES; i++)
- {
- if (stat64 (semname, &statbuff) == -1)
+ exists:
+ /* Open the file and fetch the semaphore name. */
+ if ((fd = open (semname, O_RDWR | O_CLOEXEC)) < 0)
{
if (errno == ENOENT && (oflag & O_CREAT))
+ goto again;
+ __leave;
+ }
+ /* Make certain initialization is complete */
+ for (i = 0; i < MAX_TRIES; i++)
+ {
+ if (stat64 (semname, &statbuff) == -1)
{
- close (fd);
- fd = -1;
- goto again;
+ if (errno == ENOENT && (oflag & O_CREAT))
+ {
+ close (fd);
+ fd = -1;
+ goto again;
+ }
+ __leave;
}
- goto err;
+ if ((statbuff.st_mode & S_IXUSR) == 0)
+ break;
+ sleep (1);
}
- if ((statbuff.st_mode & S_IXUSR) == 0)
- break;
- sleep (1);
- }
- if (i == MAX_TRIES)
- {
- set_errno (ETIMEDOUT);
- goto err;
+ if (i == MAX_TRIES)
+ {
+ set_errno (ETIMEDOUT);
+ __leave;
+ }
+ if (file.lock (fd, sizeof sf))
+ __leave;
+ if (read (fd, &sf, sizeof sf) != sizeof sf)
+ __leave;
+ sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value,
+ wasopen);
+ file.unlock (fd);
+ if (sem == SEM_FAILED)
+ __leave;
+ /* If wasopen is set, the semaphore was already opened and we already have
+ an open file descriptor pointing to the file. This means, we have to
+ close the file descriptor created in this call. It won't be stored
+ anywhere anyway. */
+ if (wasopen)
+ close (fd);
+ return sem;
}
- if (file.lock (fd, sizeof sf))
- goto err;
- if (read (fd, &sf, sizeof sf) != sizeof sf)
- goto err;
- sem = semaphore::open (sf.hash, sf.luid, fd, oflag, mode, sf.value, wasopen);
- file.unlock (fd);
- if (sem == SEM_FAILED)
- goto err;
- /* If wasopen is set, the semaphore was already opened and we already have
- an open file descriptor pointing to the file. This means, we have to
- close the file descriptor created in this call. It won't be stored
- anywhere anyway. */
- if (wasopen)
- close (fd);
- return sem;
-
-err:
+ __except (EFAULT) {}
+ __endtry
/* Don't let following function calls change errno */
save_errno save;
- file.unlock (fd);
+ if (fd >= 0)
+ file.unlock (fd);
if (created)
unlink (semname);
if (sem != SEM_FAILED)
diff --git a/winsup/cygwin/resource.cc b/winsup/cygwin/resource.cc
index 25e87e6e0..27ba4d4be 100644
--- a/winsup/cygwin/resource.cc
+++ b/winsup/cygwin/resource.cc
@@ -1,7 +1,7 @@
/* resource.cc: getrusage () and friends.
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),
Geoffrey Noer (noer@cygnus.com) of Cygnus Support.
@@ -116,53 +116,51 @@ getrlimit (int resource, struct rlimit *rlp)
{
MEMORY_BASIC_INFORMATION m;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- rlp->rlim_cur = RLIM_INFINITY;
- rlp->rlim_max = RLIM_INFINITY;
-
- switch (resource)
+ __try
{
- case RLIMIT_CPU:
- case RLIMIT_FSIZE:
- 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_INFINITY;
+ rlp->rlim_max = RLIM_INFINITY;
+
+ switch (resource)
{
- rlp->rlim_cur = (rlim_t) &m - (rlim_t) m.AllocationBase;
- rlp->rlim_max = (rlim_t) m.BaseAddress + m.RegionSize
- - (rlim_t) m.AllocationBase;
+ case RLIMIT_CPU:
+ case RLIMIT_FSIZE:
+ 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;
- 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;
}
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
setrlimit (int resource, const struct rlimit *rlp)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
struct rlimit oldlimits;
/* 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)
return -1;
- if (oldlimits.rlim_cur == rlp->rlim_cur &&
- oldlimits.rlim_max == rlp->rlim_max)
- /* No change in resource requirements, succeed immediately */
- return 0;
-
- if (rlp->rlim_cur > rlp->rlim_max)
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
+ if (oldlimits.rlim_cur == rlp->rlim_cur &&
+ oldlimits.rlim_max == rlp->rlim_max)
+ /* No change in resource requirements, succeed immediately */
+ return 0;
- switch (resource)
- {
- case RLIMIT_CORE:
- cygheap->rlim_core = rlp->rlim_cur;
- break;
- case RLIMIT_NOFILE:
- if (rlp->rlim_cur != RLIM_INFINITY)
- return setdtablesize (rlp->rlim_cur);
- break;
- default:
- set_errno (EINVAL);
- return -1;
+ if (rlp->rlim_cur > rlp->rlim_max)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+
+ switch (resource)
+ {
+ case RLIMIT_CORE:
+ cygheap->rlim_core = rlp->rlim_cur;
+ break;
+ 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;
}
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index e83d9a024..6a396852a 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1,7 +1,7 @@
/* select.cc
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.
@@ -230,21 +230,24 @@ pselect(int maxfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval tv;
sigset_t oldset = _my_tls.sigmask;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (ts)
+ __try
{
- tv.tv_sec = ts->tv_sec;
- tv.tv_usec = ts->tv_nsec / 1000;
+ if (ts)
+ {
+ 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)
- 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;
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
/* Call cleanup functions for all inspected fds. Gets rid of any
diff --git a/winsup/cygwin/sem.cc b/winsup/cygwin/sem.cc
index 2c172990a..f7a5db674 100644
--- a/winsup/cygwin/sem.cc
+++ b/winsup/cygwin/sem.cc
@@ -1,6 +1,6 @@
/* 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.
@@ -85,19 +85,22 @@ semctl (int semid, int semnum, int cmd, ...)
}
syscall_printf ("semctl (semid = %d, semnum = %d, cmd = %d, arg = %p)",
semid, semnum, cmd, arg.buf);
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- client_request_sem request (semid, semnum, cmd, &arg);
- if (request.make_request () == -1 || request.retval () == -1)
+ __try
{
- syscall_printf ("-1 [%d] = semctl ()", request.error_code ());
- set_errno (request.error_code ());
- if (request.error_code () == ENOSYS)
- raise (SIGSYS);
- 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 ());
+ 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
@@ -122,17 +125,20 @@ semop (int semid, struct sembuf *sops, size_t nsops)
{
syscall_printf ("semop (semid = %d, sops = %p, nsops = %ld)",
semid, sops, nsops);
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- client_request_sem request (semid, sops, nsops);
- if (request.make_request () == -1 || request.retval () == -1)
+ __try
{
- syscall_printf ("-1 [%d] = semop ()", request.error_code ());
- set_errno (request.error_code ());
- if (request.error_code () == ENOSYS)
- raise (SIGSYS);
- 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 ());
+ set_errno (request.error_code ());
+ if (request.error_code () == ENOSYS)
+ raise (SIGSYS);
+ __leave;
+ }
+ return request.retval ();
}
- return request.retval ();
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
index 03213781a..868545e3b 100644
--- a/winsup/cygwin/shm.cc
+++ b/winsup/cygwin/shm.cc
@@ -260,41 +260,45 @@ shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = %p)",
shmid, cmd, buf);
- myfault efault;
- 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 ());
- set_errno (request.error_code ());
- if (request.error_code () == ENOSYS)
- raise (SIGSYS);
- return -1;
- }
- if (cmd == IPC_RMID)
+ __try
{
- /* Cleanup */
- shm_shmid_list *ssh_entry, *ssh_next_entry;
- SLIST_LOCK ();
- SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry)
+ client_request_shm request (shmid, cmd, buf);
+ if (request.make_request () == -1 || request.retval () == -1)
+ {
+ syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
+ set_errno (request.error_code ());
+ if (request.error_code () == ENOSYS)
+ raise (SIGSYS);
+ __leave;
+ }
+ if (cmd == IPC_RMID)
{
- if (ssh_entry->shmid == shmid)
+ /* Cleanup */
+ shm_shmid_list *ssh_entry, *ssh_next_entry;
+ SLIST_LOCK ();
+ SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry)
{
- /* Remove this entry from the list and close the handle
- only if it's not in use anymore. */
- if (ssh_entry->ref_count <= 0)
+ if (ssh_entry->shmid == shmid)
{
- SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next);
- CloseHandle (ssh_entry->hdl);
- delete ssh_entry;
+ /* 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;
}
- break;
}
+ SLIST_UNLOCK ();
}
- SLIST_UNLOCK ();
+ return request.retval ();
}
- return request.retval ();
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 3ea8af502..d2ca81e00 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -1,7 +1,7 @@
/* signal.cc
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
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;
}
- myfault efault;
- if (efault.faulted (EFAULT))
- return EFAULT;
-
- if (oldset)
- *oldset = opmask;
+ __try
+ {
+ if (oldset)
+ *oldset = opmask;
- if (set)
- {
- sigset_t newmask = opmask;
- switch (how)
+ if (set)
{
- case SIG_BLOCK:
- /* add set to current mask */
- newmask |= *set;
- break;
- case SIG_UNBLOCK:
- /* remove set from current mask */
- newmask &= ~*set;
- break;
- case SIG_SETMASK:
- /* just set it */
- newmask = *set;
- break;
+ sigset_t newmask = opmask;
+ switch (how)
+ {
+ case SIG_BLOCK:
+ /* add set to current mask */
+ newmask |= *set;
+ 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;
}
@@ -382,8 +386,7 @@ sigaction_worker (int sig, const struct sigaction *newact,
struct sigaction *oldact, bool isinternal)
{
int res = -1;
- myfault efault;
- if (!efault.faulted (EFAULT))
+ __try
{
sig_dispatch_pending ();
/* 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];
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
{
- 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)
{
set_errno (EINVAL);
- goto out;
+ __leave;
}
struct sigaction na = *newact;
struct sigaction& gs = global_sigs[sig];
@@ -430,8 +436,8 @@ sigaction_worker (int sig, const struct sigaction *newact,
res = 0;
}
}
-
-out:
+ __except (EFAULT) {}
+ __endtry
return res;
}
@@ -560,41 +566,41 @@ sigwait (const sigset_t *set, int *sig_ptr)
extern "C" int
sigwaitinfo (const sigset_t *set, siginfo_t *info)
{
- pthread_testcancel ();
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ int res = -1;
- set_signal_mask (_my_tls.sigwait_mask, *set);
- sig_dispatch_pending (true);
+ pthread_testcancel ();
- int res;
- switch (cygwait (NULL, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
+ __try
{
- case WAIT_SIGNALED:
- if (!sigismember (set, _my_tls.infodata.si_signo))
- {
- set_errno (EINTR);
- res = -1;
- }
- else
+ set_signal_mask (_my_tls.sigwait_mask, *set);
+ sig_dispatch_pending (true);
+
+ switch (cygwait (NULL, cw_infinite, cw_sig_eintr | cw_cancel | cw_cancel_self))
{
- _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 ();
+ 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;
}
- break;
- default:
- __seterrno ();
- res = -1;
}
-
+ __except (EFAULT) {
+ res = -1;
+ }
+ __endtry
sigproc_printf ("returning signal %d", res);
return res;
}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index d1b1fbad6..56f36a3e6 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -1,7 +1,7 @@
/* spawn.cc
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.
@@ -330,552 +330,552 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
STARTUPINFOW si = {};
int looped = 0;
- myfault efault;
system_call_handle system_call (mode == _P_SYSTEM);
- if (efault.faulted ())
+
+ __try
{
- if (get_errno () == ENOMEM)
- set_errno (E2BIG);
+ child_info_types chtype;
+ if (mode == _P_OVERLAY)
+ chtype = _CH_EXEC;
else
- set_errno (EFAULT);
- res = -1;
- goto out;
- }
-
- child_info_types chtype;
- if (mode == _P_OVERLAY)
- chtype = _CH_EXEC;
- else
- chtype = _CH_SPAWN;
+ chtype = _CH_SPAWN;
- moreinfo = cygheap_exec_info::alloc ();
+ moreinfo = cygheap_exec_info::alloc ();
- /* CreateProcess takes one long string that is the command line (sigh).
- We need to quote any argument that has whitespace or embedded "'s. */
+ /* CreateProcess takes one long string that is the command line (sigh).
+ We need to quote any argument that has whitespace or embedded "'s. */
- int ac;
- for (ac = 0; argv[ac]; ac++)
- /* nothing */;
+ int ac;
+ for (ac = 0; argv[ac]; ac++)
+ /* nothing */;
- int err;
- const char *ext;
- if ((ext = perhaps_suffix (prog_arg, real_path, err, FE_NADA)) == NULL)
- {
- set_errno (err);
- res = -1;
- goto out;
- }
-
- res = newargv.setup (prog_arg, real_path, ext, ac, argv, p_type_exec);
+ int err;
+ const char *ext;
+ if ((ext = perhaps_suffix (prog_arg, real_path, err, FE_NADA)) == NULL)
+ {
+ set_errno (err);
+ res = -1;
+ __leave;
+ }
- if (res)
- goto out;
+ res = newargv.setup (prog_arg, real_path, ext, ac, argv, p_type_exec);
- if (!real_path.iscygexec () && ::cygheap->cwd.get_error ())
- {
- small_printf ("Error: Current working directory %s.\n"
- "Can't start native Windows application from here.\n\n",
- ::cygheap->cwd.get_error_desc ());
- set_errno (::cygheap->cwd.get_error ());
- res = -1;
- goto out;
- }
+ if (res)
+ __leave;
- if (ac == 3 && argv[1][0] == '/' && tolower (argv[1][1]) == 'c' &&
- (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
- {
- real_path.check (prog_arg);
- cmd.add ("\"");
- if (!real_path.error)
- cmd.add (real_path.get_win32 ());
- else
- cmd.add (argv[0]);
- cmd.add ("\"");
- cmd.add (" ");
- cmd.add (argv[1]);
- cmd.add (" ");
- cmd.add (argv[2]);
- real_path.set_path (argv[0]);
- null_app_name = true;
- }
- else
- {
- if (real_path.iscygexec ())
- {
- moreinfo->argc = newargv.argc;
- moreinfo->argv = newargv;
- }
- if ((wincmdln || !real_path.iscygexec ())
- && !cmd.fromargv (newargv, real_path.get_win32 (),
- real_path.iscygexec ()))
+ if (!real_path.iscygexec () && ::cygheap->cwd.get_error ())
{
+ small_printf ("Error: Current working directory %s.\n"
+ "Can't start native Windows application from here.\n\n",
+ ::cygheap->cwd.get_error_desc ());
+ set_errno (::cygheap->cwd.get_error ());
res = -1;
- goto out;
+ __leave;
}
-
- if (mode != _P_OVERLAY || !real_path.iscygexec ()
- || !DuplicateHandle (GetCurrentProcess (), myself.shared_handle (),
- GetCurrentProcess (), &moreinfo->myself_pinfo,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- moreinfo->myself_pinfo = NULL;
+ if (ac == 3 && argv[1][0] == '/' && tolower (argv[1][1]) == 'c' &&
+ (iscmd (argv[0], "command.com") || iscmd (argv[0], "cmd.exe")))
+ {
+ real_path.check (prog_arg);
+ cmd.add ("\"");
+ if (!real_path.error)
+ cmd.add (real_path.get_win32 ());
+ else
+ cmd.add (argv[0]);
+ cmd.add ("\"");
+ cmd.add (" ");
+ cmd.add (argv[1]);
+ cmd.add (" ");
+ cmd.add (argv[2]);
+ real_path.set_path (argv[0]);
+ null_app_name = true;
+ }
else
- VerifyHandle (moreinfo->myself_pinfo);
- }
+ {
+ if (real_path.iscygexec ())
+ {
+ moreinfo->argc = newargv.argc;
+ moreinfo->argv = newargv;
+ }
+ if ((wincmdln || !real_path.iscygexec ())
+ && !cmd.fromargv (newargv, real_path.get_win32 (),
+ real_path.iscygexec ()))
+ {
+ res = -1;
+ __leave;
+ }
- PROCESS_INFORMATION pi;
- pi.hProcess = pi.hThread = NULL;
- pi.dwProcessId = pi.dwThreadId = 0;
- /* Set up needed handles for stdio */
- si.dwFlags = STARTF_USESTDHANDLES;
- si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false);
- si.hStdOutput = handle ((in__stdout < 0 ? 1 : in__stdout), true);
- si.hStdError = handle (2, true);
+ if (mode != _P_OVERLAY || !real_path.iscygexec ()
+ || !DuplicateHandle (GetCurrentProcess (), myself.shared_handle (),
+ GetCurrentProcess (), &moreinfo->myself_pinfo,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ moreinfo->myself_pinfo = NULL;
+ else
+ VerifyHandle (moreinfo->myself_pinfo);
+ }
- si.cb = sizeof (si);
+ PROCESS_INFORMATION pi;
+ pi.hProcess = pi.hThread = NULL;
+ pi.dwProcessId = pi.dwThreadId = 0;
- c_flags = GetPriorityClass (GetCurrentProcess ());
- sigproc_printf ("priority class %d", c_flags);
+ /* Set up needed handles for stdio */
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.hStdInput = handle ((in__stdin < 0 ? 0 : in__stdin), false);
+ si.hStdOutput = handle ((in__stdout < 0 ? 1 : in__stdout), true);
+ si.hStdError = handle (2, true);
- c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT;
+ si.cb = sizeof (si);
- if (wincap.has_program_compatibility_assistant ())
- {
- /* We're adding the CREATE_BREAKAWAY_FROM_JOB flag here to workaround
- issues with the "Program Compatibility Assistant (PCA) Service"
- starting with Windows Vista. For some reason, when starting long
- running sessions from mintty(*), the affected svchost.exe process
- takes more and more memory and at one point takes over the CPU. At
- this point the machine becomes unresponsive. The only way to get
- back to normal is to stop the entire mintty session, or to stop the
- PCA service. However, a process which is controlled by PCA is part
- of a compatibility job, which allows child processes to break away
- from the job. This helps to avoid this issue.
-
- First we call IsProcessInJob. It fetches the information whether or
- not we're part of a job 20 times faster than QueryInformationJobObject.
-
- (*) Note that this is not mintty's fault. It has just been observed
- with mintty in the first place. See the archives for more info:
- http://cygwin.com/ml/cygwin-developers/2012-02/msg00018.html */
-
- JOBOBJECT_BASIC_LIMIT_INFORMATION jobinfo;
- BOOL is_in_job;
-
- if (IsProcessInJob (GetCurrentProcess (), NULL, &is_in_job)
- && is_in_job
- && QueryInformationJobObject (NULL, JobObjectBasicLimitInformation,
- &jobinfo, sizeof jobinfo, NULL)
- && (jobinfo.LimitFlags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK
- | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
- {
- debug_printf ("Add CREATE_BREAKAWAY_FROM_JOB");
- c_flags |= CREATE_BREAKAWAY_FROM_JOB;
- }
- }
+ c_flags = GetPriorityClass (GetCurrentProcess ());
+ sigproc_printf ("priority class %d", c_flags);
- if (mode == _P_DETACH)
- c_flags |= DETACHED_PROCESS;
- else
- fhandler_console::need_invisible ();
+ c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT;
- if (mode != _P_OVERLAY)
- myself->exec_sendsig = NULL;
- else
- {
- /* Reset sendsig so that any process which wants to send a signal
- to this pid will wait for the new process to become active.
- Save the old value in case the exec fails. */
- if (!myself->exec_sendsig)
+ if (wincap.has_program_compatibility_assistant ())
{
- myself->exec_sendsig = myself->sendsig;
- myself->exec_dwProcessId = myself->dwProcessId;
- myself->sendsig = NULL;
- reset_sendsig = true;
+ /* We're adding the CREATE_BREAKAWAY_FROM_JOB flag here to workaround
+ issues with the "Program Compatibility Assistant (PCA) Service"
+ starting with Windows Vista. For some reason, when starting long
+ running sessions from mintty(*), the affected svchost.exe process
+ takes more and more memory and at one point takes over the CPU. At
+ this point the machine becomes unresponsive. The only way to get
+ back to normal is to stop the entire mintty session, or to stop the
+ PCA service. However, a process which is controlled by PCA is part
+ of a compatibility job, which allows child processes to break away
+ from the job. This helps to avoid this issue.
+
+ First we call IsProcessInJob. It fetches the information whether or
+ not we're part of a job 20 times faster than QueryInformationJobObject.
+
+ (*) Note that this is not mintty's fault. It has just been observed
+ with mintty in the first place. See the archives for more info:
+ http://cygwin.com/ml/cygwin-developers/2012-02/msg00018.html */
+
+ JOBOBJECT_BASIC_LIMIT_INFORMATION jobinfo;
+ BOOL is_in_job;
+
+ if (IsProcessInJob (GetCurrentProcess (), NULL, &is_in_job)
+ && is_in_job
+ && QueryInformationJobObject (NULL, JobObjectBasicLimitInformation,
+ &jobinfo, sizeof jobinfo, NULL)
+ && (jobinfo.LimitFlags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK
+ | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
+ {
+ debug_printf ("Add CREATE_BREAKAWAY_FROM_JOB");
+ c_flags |= CREATE_BREAKAWAY_FROM_JOB;
+ }
}
- }
- if (null_app_name)
- runpath = NULL;
- else
- {
- USHORT len = real_path.get_nt_native_path ()->Length / sizeof (WCHAR);
- if (RtlEqualUnicodePathPrefix (real_path.get_nt_native_path (),
- &ro_u_natp, FALSE))
+ if (mode == _P_DETACH)
+ c_flags |= DETACHED_PROCESS;
+ else
+ fhandler_console::need_invisible ();
+
+ if (mode != _P_OVERLAY)
+ myself->exec_sendsig = NULL;
+ else
{
- runpath = real_path.get_wide_win32_path (runpath);
- /* If the executable path length is < MAX_PATH, make sure the long
- path win32 prefix is removed from the path to make subsequent
- not long path aware native Win32 child processes happy. */
- if (len < MAX_PATH + 4)
+ /* Reset sendsig so that any process which wants to send a signal
+ to this pid will wait for the new process to become active.
+ Save the old value in case the exec fails. */
+ if (!myself->exec_sendsig)
{
- if (runpath[5] == ':')
- runpath += 4;
- else if (len < MAX_PATH + 6)
- *(runpath += 6) = L'\\';
+ myself->exec_sendsig = myself->sendsig;
+ myself->exec_dwProcessId = myself->dwProcessId;
+ myself->sendsig = NULL;
+ reset_sendsig = true;
}
}
- else if (len < NT_MAX_PATH - ro_u_globalroot.Length / sizeof (WCHAR))
- {
- UNICODE_STRING rpath;
- RtlInitEmptyUnicodeString (&rpath, runpath,
- (NT_MAX_PATH - 1) * sizeof (WCHAR));
- RtlCopyUnicodeString (&rpath, &ro_u_globalroot);
- RtlAppendUnicodeStringToString (&rpath,
- real_path.get_nt_native_path ());
- }
+ if (null_app_name)
+ runpath = NULL;
else
{
- set_errno (ENAMETOOLONG);
- res = -1;
- goto out;
- }
- }
-
- cygbench ("spawn-worker");
-
- if (!real_path.iscygexec())
- ::cygheap->fdtab.set_file_pointers_for_exec ();
+ USHORT len = real_path.get_nt_native_path ()->Length / sizeof (WCHAR);
+ if (RtlEqualUnicodePathPrefix (real_path.get_nt_native_path (),
+ &ro_u_natp, FALSE))
+ {
+ runpath = real_path.get_wide_win32_path (runpath);
+ /* If the executable path length is < MAX_PATH, make sure the long
+ path win32 prefix is removed from the path to make subsequent
+ not long path aware native Win32 child processes happy. */
+ if (len < MAX_PATH + 4)
+ {
+ if (runpath[5] == ':')
+ runpath += 4;
+ else if (len < MAX_PATH + 6)
+ *(runpath += 6) = L'\\';
+ }
+ }
+ else if (len < NT_MAX_PATH - ro_u_globalroot.Length / sizeof (WCHAR))
+ {
+ UNICODE_STRING rpath;
- moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
- real_path.iscygexec ());
- if (!moreinfo->envp || !envblock)
- {
- set_errno (E2BIG);
- res = -1;
- goto out;
- }
- set (chtype, real_path.iscygexec ());
- __stdin = in__stdin;
- __stdout = in__stdout;
- record_children ();
-
- si.lpReserved2 = (LPBYTE) this;
- si.cbReserved2 = sizeof (*this);
-
- /* Depends on set call above.
- Some file types might need extra effort in the parent after CreateProcess
- and before copying the datastructures to the child. So we have to start
- the child in suspend state, unfortunately, to avoid a race condition. */
- if (!newargv.win16_exe
- && (!iscygwin () || mode != _P_OVERLAY
- || ::cygheap->fdtab.need_fixup_before ()))
- c_flags |= CREATE_SUSPENDED;
- /* If a native application should be spawned, we test here if the spawning
- process is running in a console and, if so, if it's a foreground or
- background process. If it's a background process, we start the native
- process with the CREATE_NEW_PROCESS_GROUP flag set. This lets the native
- process ignore Ctrl-C by default. If we don't do that, pressing Ctrl-C
- in a console will break native processes running in the background,
- because the Ctrl-C event is sent to all processes in the console, unless
- they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */
- if (!iscygwin () && fhandler_console::exists ()
- && fhandler_console::tc_getpgid () != myself->pgid)
- c_flags |= CREATE_NEW_PROCESS_GROUP;
- refresh_cygheap ();
-
- if (mode == _P_DETACH)
- /* all set */;
- else if (mode != _P_OVERLAY || !my_wr_proc_pipe)
- prefork ();
- else
- wr_proc_pipe = my_wr_proc_pipe;
-
- /* Don't allow child to inherit these handles if it's not a Cygwin program.
- wr_proc_pipe will be injected later. parent won't be used by the child
- so there is no reason for the child to have it open as it can confuse
- ps into thinking that children of windows processes are all part of
- the same "execed" process.
- FIXME: Someday, make it so that parent is never created when starting
- non-Cygwin processes. */
- if (!iscygwin ())
- {
- SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT, 0);
- SetHandleInformation (parent, HANDLE_FLAG_INHERIT, 0);
- }
- /* FIXME: racy */
- if (mode != _P_OVERLAY)
- SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT, 0);
- parent_winpid = GetCurrentProcessId ();
-
-loop:
- /* When ruid != euid we create the new process under the current original
- account and impersonate in child, this way maintaining the different
- effective vs. real ids.
- FIXME: If ruid != euid and ruid != saved_uid we currently give
- up on ruid. The new process will have ruid == euid. */
- ::cygheap->user.deimpersonate ();
-
- if (!real_path.iscygexec () && mode == _P_OVERLAY)
- myself->process_state |= PID_NOTCYGWIN;
-
- wchar_t wcmd[(size_t) cmd];
- if (!::cygheap->user.issetuid ()
- || (::cygheap->user.saved_uid == ::cygheap->user.real_uid
- && ::cygheap->user.saved_gid == ::cygheap->user.real_gid
- && !::cygheap->user.groups.issetgroups ()
- && !::cygheap->user.setuid_to_restricted))
- {
- rc = CreateProcessW (runpath, /* image name - with full path */
- cmd.wcs (wcmd),/* what was passed to exec */
- &sec_none_nih, /* process security attrs */
- &sec_none_nih, /* thread security attrs */
- TRUE, /* inherit handles from parent */
- c_flags,
- envblock, /* environment */
- NULL,
- &si,
- &pi);
- }
- else
- {
- /* Give access to myself */
- if (mode == _P_OVERLAY)
- myself.set_acl();
-
- WCHAR wstname[1024] = { L'\0' };
- HWINSTA hwst_orig = NULL, hwst = NULL;
- HDESK hdsk_orig = NULL, hdsk = NULL;
- PSECURITY_ATTRIBUTES sa;
- DWORD n;
-
- hwst_orig = GetProcessWindowStation ();
- hdsk_orig = GetThreadDesktop (GetCurrentThreadId ());
- GetUserObjectInformationW (hwst_orig, UOI_NAME, wstname, 1024, &n);
- /* Prior to Vista it was possible to start a service with the
- "Interact with desktop" flag. This started the service in the
- interactive window station of the console. A big security
- risk, but we don't want to disable this behaviour for older
- OSes because it's still heavily used by some users. They have
- been warned. */
- if (!::cygheap->user.setuid_to_restricted
- && wcscasecmp (wstname, L"WinSta0") != 0)
- {
- WCHAR sid[128];
-
- sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
- ::cygheap->user.sid ());
- /* We're creating a window station per user, not per logon session.
- First of all we might not have a valid logon session for
- the user (logon by create_token), and second, it doesn't
- make sense in terms of security to create a new window
- station for every logon of the same user. It just fills up
- the system with window stations for no good reason. */
- hwst = CreateWindowStationW (::cygheap->user.get_windows_id (sid), 0,
- GENERIC_READ | GENERIC_WRITE, sa);
- if (!hwst)
- system_printf ("CreateWindowStation failed, %E");
- else if (!SetProcessWindowStation (hwst))
- system_printf ("SetProcessWindowStation failed, %E");
- else if (!(hdsk = CreateDesktopW (L"Default", NULL, NULL, 0,
- GENERIC_ALL, sa)))
- system_printf ("CreateDesktop failed, %E");
+ RtlInitEmptyUnicodeString (&rpath, runpath,
+ (NT_MAX_PATH - 1) * sizeof (WCHAR));
+ RtlCopyUnicodeString (&rpath, &ro_u_globalroot);
+ RtlAppendUnicodeStringToString (&rpath,
+ real_path.get_nt_native_path ());
+ }
else
{
- wcpcpy (wcpcpy (wstname, sid), L"\\Default");
- si.lpDesktop = wstname;
- debug_printf ("Desktop: %W", si.lpDesktop);
+ set_errno (ENAMETOOLONG);
+ res = -1;
+ __leave;
}
}
- rc = CreateProcessAsUserW (::cygheap->user.primary_token (),
- runpath, /* image name - with full path */
- cmd.wcs (wcmd),/* what was passed to exec */
- &sec_none_nih, /* process security attrs */
- &sec_none_nih, /* thread security attrs */
- TRUE, /* inherit handles from parent */
- c_flags,
- envblock, /* environment */
- NULL,
- &si,
- &pi);
- if (hwst)
+ cygbench ("spawn-worker");
+
+ if (!real_path.iscygexec())
+ ::cygheap->fdtab.set_file_pointers_for_exec ();
+
+ moreinfo->envp = build_env (envp, envblock, moreinfo->envc,
+ real_path.iscygexec ());
+ if (!moreinfo->envp || !envblock)
+ {
+ set_errno (E2BIG);
+ res = -1;
+ __leave;
+ }
+ set (chtype, real_path.iscygexec ());
+ __stdin = in__stdin;
+ __stdout = in__stdout;
+ record_children ();
+
+ si.lpReserved2 = (LPBYTE) this;
+ si.cbReserved2 = sizeof (*this);
+
+ /* Depends on set call above.
+ Some file types might need extra effort in the parent after CreateProcess
+ and before copying the datastructures to the child. So we have to start
+ the child in suspend state, unfortunately, to avoid a race condition. */
+ if (!newargv.win16_exe
+ && (!iscygwin () || mode != _P_OVERLAY
+ || ::cygheap->fdtab.need_fixup_before ()))
+ c_flags |= CREATE_SUSPENDED;
+ /* If a native application should be spawned, we test here if the spawning
+ process is running in a console and, if so, if it's a foreground or
+ background process. If it's a background process, we start the native
+ process with the CREATE_NEW_PROCESS_GROUP flag set. This lets the native
+ process ignore Ctrl-C by default. If we don't do that, pressing Ctrl-C
+ in a console will break native processes running in the background,
+ because the Ctrl-C event is sent to all processes in the console, unless
+ they ignore it explicitely. CREATE_NEW_PROCESS_GROUP does that for us. */
+ if (!iscygwin () && fhandler_console::exists ()
+ && fhandler_console::tc_getpgid () != myself->pgid)
+ c_flags |= CREATE_NEW_PROCESS_GROUP;
+ refresh_cygheap ();
+
+ if (mode == _P_DETACH)
+ /* all set */;
+ else if (mode != _P_OVERLAY || !my_wr_proc_pipe)
+ prefork ();
+ else
+ wr_proc_pipe = my_wr_proc_pipe;
+
+ /* Don't allow child to inherit these handles if it's not a Cygwin program.
+ wr_proc_pipe will be injected later. parent won't be used by the child
+ so there is no reason for the child to have it open as it can confuse
+ ps into thinking that children of windows processes are all part of
+ the same "execed" process.
+ FIXME: Someday, make it so that parent is never created when starting
+ non-Cygwin processes. */
+ if (!iscygwin ())
{
- SetProcessWindowStation (hwst_orig);
- CloseWindowStation (hwst);
+ SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT, 0);
+ SetHandleInformation (parent, HANDLE_FLAG_INHERIT, 0);
}
- if (hdsk)
+ /* FIXME: racy */
+ if (mode != _P_OVERLAY)
+ SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT, 0);
+ parent_winpid = GetCurrentProcessId ();
+
+ loop:
+ /* When ruid != euid we create the new process under the current original
+ account and impersonate in child, this way maintaining the different
+ effective vs. real ids.
+ FIXME: If ruid != euid and ruid != saved_uid we currently give
+ up on ruid. The new process will have ruid == euid. */
+ ::cygheap->user.deimpersonate ();
+
+ if (!real_path.iscygexec () && mode == _P_OVERLAY)
+ myself->process_state |= PID_NOTCYGWIN;
+
+ wchar_t wcmd[(size_t) cmd];
+ if (!::cygheap->user.issetuid ()
+ || (::cygheap->user.saved_uid == ::cygheap->user.real_uid
+ && ::cygheap->user.saved_gid == ::cygheap->user.real_gid
+ && !::cygheap->user.groups.issetgroups ()
+ && !::cygheap->user.setuid_to_restricted))
{
- SetThreadDesktop (hdsk_orig);
- CloseDesktop (hdsk);
+ rc = CreateProcessW (runpath, /* image name - with full path */
+ cmd.wcs (wcmd),/* what was passed to exec */
+ &sec_none_nih, /* process security attrs */
+ &sec_none_nih, /* thread security attrs */
+ TRUE, /* inherit handles from parent */
+ c_flags,
+ envblock, /* environment */
+ NULL,
+ &si,
+ &pi);
}
- }
-
- if (mode != _P_OVERLAY)
- SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
- HANDLE_FLAG_INHERIT);
-
- /* Set errno now so that debugging messages from it appear before our
- final debugging message [this is a general rule for debugging
- messages]. */
- if (!rc)
- {
- __seterrno ();
- syscall_printf ("CreateProcess failed, %E");
- /* If this was a failed exec, restore the saved sendsig. */
- if (reset_sendsig)
+ else
{
- myself->sendsig = myself->exec_sendsig;
- myself->exec_sendsig = NULL;
+ /* Give access to myself */
+ if (mode == _P_OVERLAY)
+ myself.set_acl();
+
+ WCHAR wstname[1024] = { L'\0' };
+ HWINSTA hwst_orig = NULL, hwst = NULL;
+ HDESK hdsk_orig = NULL, hdsk = NULL;
+ PSECURITY_ATTRIBUTES sa;
+ DWORD n;
+
+ hwst_orig = GetProcessWindowStation ();
+ hdsk_orig = GetThreadDesktop (GetCurrentThreadId ());
+ GetUserObjectInformationW (hwst_orig, UOI_NAME, wstname, 1024, &n);
+ /* Prior to Vista it was possible to start a service with the
+ "Interact with desktop" flag. This started the service in the
+ interactive window station of the console. A big security
+ risk, but we don't want to disable this behaviour for older
+ OSes because it's still heavily used by some users. They have
+ been warned. */
+ if (!::cygheap->user.setuid_to_restricted
+ && wcscasecmp (wstname, L"WinSta0") != 0)
+ {
+ WCHAR sid[128];
+
+ sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
+ ::cygheap->user.sid ());
+ /* We're creating a window station per user, not per logon session.
+ First of all we might not have a valid logon session for
+ the user (logon by create_token), and second, it doesn't
+ make sense in terms of security to create a new window
+ station for every logon of the same user. It just fills up
+ the system with window stations for no good reason. */
+ hwst = CreateWindowStationW (::cygheap->user.get_windows_id (sid), 0,
+ GENERIC_READ | GENERIC_WRITE, sa);
+ if (!hwst)
+ system_printf ("CreateWindowStation failed, %E");
+ else if (!SetProcessWindowStation (hwst))
+ system_printf ("SetProcessWindowStation failed, %E");
+ else if (!(hdsk = CreateDesktopW (L"Default", NULL, NULL, 0,
+ GENERIC_ALL, sa)))
+ system_printf ("CreateDesktop failed, %E");
+ else
+ {
+ wcpcpy (wcpcpy (wstname, sid), L"\\Default");
+ si.lpDesktop = wstname;
+ debug_printf ("Desktop: %W", si.lpDesktop);
+ }
+ }
+
+ rc = CreateProcessAsUserW (::cygheap->user.primary_token (),
+ runpath, /* image name - with full path */
+ cmd.wcs (wcmd),/* what was passed to exec */
+ &sec_none_nih, /* process security attrs */
+ &sec_none_nih, /* thread security attrs */
+ TRUE, /* inherit handles from parent */
+ c_flags,
+ envblock, /* environment */
+ NULL,
+ &si,
+ &pi);
+ if (hwst)
+ {
+ SetProcessWindowStation (hwst_orig);
+ CloseWindowStation (hwst);
+ }
+ if (hdsk)
+ {
+ SetThreadDesktop (hdsk_orig);
+ CloseDesktop (hdsk);
+ }
}
- myself->process_state &= ~PID_NOTCYGWIN;
- /* Reset handle inheritance to default when the execution of a non-Cygwin
- process fails. Only need to do this for _P_OVERLAY since the handle will
- be closed otherwise. Don't need to do this for 'parent' since it will
- be closed in every case. See FIXME above. */
- if (!iscygwin () && mode == _P_OVERLAY)
- SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT,
- HANDLE_FLAG_INHERIT);
- if (wr_proc_pipe == my_wr_proc_pipe)
- wr_proc_pipe = NULL; /* We still own it: don't nuke in destructor */
- /* Restore impersonation. In case of _P_OVERLAY this isn't
- allowed since it would overwrite child data. */
if (mode != _P_OVERLAY)
- ::cygheap->user.reimpersonate ();
+ SetHandleInformation (my_wr_proc_pipe, HANDLE_FLAG_INHERIT,
+ HANDLE_FLAG_INHERIT);
- res = -1;
- goto out;
- }
+ /* Set errno now so that debugging messages from it appear before our
+ final debugging message [this is a general rule for debugging
+ messages]. */
+ if (!rc)
+ {
+ __seterrno ();
+ syscall_printf ("CreateProcess failed, %E");
+ /* If this was a failed exec, restore the saved sendsig. */
+ if (reset_sendsig)
+ {
+ myself->sendsig = myself->exec_sendsig;
+ myself->exec_sendsig = NULL;
+ }
+ myself->process_state &= ~PID_NOTCYGWIN;
+ /* Reset handle inheritance to default when the execution of a non-Cygwin
+ process fails. Only need to do this for _P_OVERLAY since the handle will
+ be closed otherwise. Don't need to do this for 'parent' since it will
+ be closed in every case. See FIXME above. */
+ if (!iscygwin () && mode == _P_OVERLAY)
+ SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT,
+ HANDLE_FLAG_INHERIT);
+ if (wr_proc_pipe == my_wr_proc_pipe)
+ wr_proc_pipe = NULL; /* We still own it: don't nuke in destructor */
+
+ /* Restore impersonation. In case of _P_OVERLAY this isn't
+ allowed since it would overwrite child data. */
+ if (mode != _P_OVERLAY)
+ ::cygheap->user.reimpersonate ();
- /* The CREATE_SUSPENDED case is handled below */
- if (iscygwin () && !(c_flags & CREATE_SUSPENDED))
- strace.write_childpid (pi.dwProcessId);
+ res = -1;
+ __leave;
+ }
- /* Fixup the parent data structures if needed and resume the child's
- main thread. */
- if (::cygheap->fdtab.need_fixup_before ())
- ::cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
+ /* The CREATE_SUSPENDED case is handled below */
+ if (iscygwin () && !(c_flags & CREATE_SUSPENDED))
+ strace.write_childpid (pi.dwProcessId);
- if (mode != _P_OVERLAY)
- cygpid = cygwin_pid (pi.dwProcessId);
- else
- cygpid = myself->pid;
+ /* Fixup the parent data structures if needed and resume the child's
+ main thread. */
+ if (::cygheap->fdtab.need_fixup_before ())
+ ::cygheap->fdtab.fixup_before_exec (pi.dwProcessId);
- /* We print the original program name here so the user can see that too. */
- syscall_printf ("pid %d, prog_arg %s, cmd line %.9500s)",
- rc ? cygpid : (unsigned int) -1, prog_arg, (const char *) cmd);
+ if (mode != _P_OVERLAY)
+ cygpid = cygwin_pid (pi.dwProcessId);
+ else
+ cygpid = myself->pid;
- /* Name the handle similarly to proc_subproc. */
- ProtectHandle1 (pi.hProcess, childhProc);
+ /* We print the original program name here so the user can see that too. */
+ syscall_printf ("pid %d, prog_arg %s, cmd line %.9500s)",
+ rc ? cygpid : (unsigned int) -1, prog_arg, (const char *) cmd);
- if (mode == _P_OVERLAY)
- {
- myself->dwProcessId = pi.dwProcessId;
- strace.execing = 1;
- myself.hProcess = hExeced = pi.hProcess;
- real_path.get_wide_win32_path (myself->progname); // FIXME: race?
- sigproc_printf ("new process name %W", myself->progname);
- if (!iscygwin ())
- close_all_files ();
- }
- else
- {
- myself->set_has_pgid_children ();
- ProtectHandle (pi.hThread);
- pinfo child (cygpid,
- PID_IN_USE | (real_path.iscygexec () ? 0 : PID_NOTCYGWIN));
- if (!child)
+ /* Name the handle similarly to proc_subproc. */
+ ProtectHandle1 (pi.hProcess, childhProc);
+
+ if (mode == _P_OVERLAY)
{
- syscall_printf ("pinfo failed");
- if (get_errno () != ENOMEM)
- set_errno (EAGAIN);
- res = -1;
- goto out;
+ myself->dwProcessId = pi.dwProcessId;
+ strace.execing = 1;
+ myself.hProcess = hExeced = pi.hProcess;
+ real_path.get_wide_win32_path (myself->progname); // FIXME: race?
+ sigproc_printf ("new process name %W", myself->progname);
+ if (!iscygwin ())
+ close_all_files ();
}
- child->dwProcessId = pi.dwProcessId;
- child.hProcess = pi.hProcess;
-
- real_path.get_wide_win32_path (child->progname);
- /* FIXME: This introduces an unreferenced, open handle into the child.
- The purpose is to keep the pid shared memory open so that all of
- the fields filled out by child.remember do not disappear and so there
- is not a brief period during which the pid is not available.
- However, we should try to find another way to do this eventually. */
- DuplicateHandle (GetCurrentProcess (), child.shared_handle (),
- pi.hProcess, NULL, 0, 0, DUPLICATE_SAME_ACCESS);
- child->start_time = time (NULL); /* Register child's starting time. */
- child->nice = myself->nice;
- postfork (child);
- if (!child.remember (mode == _P_DETACH))
+ else
{
- /* FIXME: Child in strange state now */
- CloseHandle (pi.hProcess);
- ForceCloseHandle (pi.hThread);
- res = -1;
- goto out;
+ myself->set_has_pgid_children ();
+ ProtectHandle (pi.hThread);
+ pinfo child (cygpid,
+ PID_IN_USE | (real_path.iscygexec () ? 0 : PID_NOTCYGWIN));
+ if (!child)
+ {
+ syscall_printf ("pinfo failed");
+ if (get_errno () != ENOMEM)
+ set_errno (EAGAIN);
+ res = -1;
+ __leave;
+ }
+ child->dwProcessId = pi.dwProcessId;
+ child.hProcess = pi.hProcess;
+
+ real_path.get_wide_win32_path (child->progname);
+ /* FIXME: This introduces an unreferenced, open handle into the child.
+ The purpose is to keep the pid shared memory open so that all of
+ the fields filled out by child.remember do not disappear and so there
+ is not a brief period during which the pid is not available.
+ However, we should try to find another way to do this eventually. */
+ DuplicateHandle (GetCurrentProcess (), child.shared_handle (),
+ pi.hProcess, NULL, 0, 0, DUPLICATE_SAME_ACCESS);
+ child->start_time = time (NULL); /* Register child's starting time. */
+ child->nice = myself->nice;
+ postfork (child);
+ if (!child.remember (mode == _P_DETACH))
+ {
+ /* FIXME: Child in strange state now */
+ CloseHandle (pi.hProcess);
+ ForceCloseHandle (pi.hThread);
+ res = -1;
+ __leave;
+ }
}
- }
- /* Start the child running */
- if (c_flags & CREATE_SUSPENDED)
- {
- /* Inject a non-inheritable wr_proc_pipe handle into child so that we
- can accurately track when the child exits without keeping this
- process waiting around for it to exit. */
- if (!iscygwin ())
- DuplicateHandle (GetCurrentProcess (), wr_proc_pipe, pi.hProcess, NULL,
- 0, false, DUPLICATE_SAME_ACCESS);
- ResumeThread (pi.hThread);
- if (iscygwin ())
- strace.write_childpid (pi.dwProcessId);
- }
- ForceCloseHandle (pi.hThread);
+ /* Start the child running */
+ if (c_flags & CREATE_SUSPENDED)
+ {
+ /* Inject a non-inheritable wr_proc_pipe handle into child so that we
+ can accurately track when the child exits without keeping this
+ process waiting around for it to exit. */
+ if (!iscygwin ())
+ DuplicateHandle (GetCurrentProcess (), wr_proc_pipe, pi.hProcess, NULL,
+ 0, false, DUPLICATE_SAME_ACCESS);
+ ResumeThread (pi.hThread);
+ if (iscygwin ())
+ strace.write_childpid (pi.dwProcessId);
+ }
+ ForceCloseHandle (pi.hThread);
- sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
+ sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
- bool synced;
- if ((mode == _P_DETACH || mode == _P_NOWAIT) && !iscygwin ())
- synced = false;
- else
- /* Just mark a non-cygwin process as 'synced'. We will still eventually
- wait for it to exit in maybe_set_exit_code_from_windows(). */
- synced = iscygwin () ? sync (pi.dwProcessId, pi.hProcess, INFINITE) : true;
+ bool synced;
+ if ((mode == _P_DETACH || mode == _P_NOWAIT) && !iscygwin ())
+ synced = false;
+ else
+ /* Just mark a non-cygwin process as 'synced'. We will still eventually
+ wait for it to exit in maybe_set_exit_code_from_windows(). */
+ synced = iscygwin () ? sync (pi.dwProcessId, pi.hProcess, INFINITE) : true;
- switch (mode)
- {
- case _P_OVERLAY:
- myself.hProcess = pi.hProcess;
- if (!synced)
+ switch (mode)
{
- if (!proc_retry (pi.hProcess))
+ case _P_OVERLAY:
+ myself.hProcess = pi.hProcess;
+ if (!synced)
+ {
+ if (!proc_retry (pi.hProcess))
+ {
+ looped++;
+ goto loop;
+ }
+ close_all_files (true);
+ }
+ else
{
- looped++;
- goto loop;
+ if (iscygwin ())
+ close_all_files (true);
+ if (!my_wr_proc_pipe
+ && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
+ wait_for_myself ();
}
- close_all_files (true);
+ myself.exit (EXITCODE_NOSET);
+ break;
+ case _P_WAIT:
+ case _P_SYSTEM:
+ system_call.arm ();
+ if (waitpid (cygpid, &res, 0) != cygpid)
+ res = -1;
+ break;
+ case _P_DETACH:
+ res = 0; /* Lost all memory of this child. */
+ break;
+ case _P_NOWAIT:
+ case _P_NOWAITO:
+ case _P_VFORK:
+ res = cygpid;
+ break;
+ default:
+ break;
}
+ }
+ __except (NO_ERROR)
+ {
+ if (get_errno () == ENOMEM)
+ set_errno (E2BIG);
else
- {
- if (iscygwin ())
- close_all_files (true);
- if (!my_wr_proc_pipe
- && WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
- wait_for_myself ();
- }
- myself.exit (EXITCODE_NOSET);
- break;
- case _P_WAIT:
- case _P_SYSTEM:
- system_call.arm ();
- if (waitpid (cygpid, &res, 0) != cygpid)
- res = -1;
- break;
- case _P_DETACH:
- res = 0; /* Lost all memory of this child. */
- break;
- case _P_NOWAIT:
- case _P_NOWAITO:
- case _P_VFORK:
- res = cygpid;
- break;
- default:
- break;
+ set_errno (EFAULT);
+ res = -1;
}
-
-out:
+ __endtry
this->cleanup ();
if (envblock)
free (envblock);
@@ -1137,28 +1137,31 @@ av::setup (const char *prog_arg, path_conv& real_path, const char *ext,
}
{
- myfault efault;
- if (efault.faulted ())
+ __try
{
- UnmapViewOfFile (buf);
- CloseHandle (hm);
- real_path.set_cygexec (false);
- break;
+ if (buf[0] == 'M' && buf[1] == 'Z')
+ {
+ WORD subsys;
+ unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
+ win16_exe = off < sizeof (IMAGE_DOS_HEADER);
+ if (!win16_exe)
+ real_path.set_cygexec (hook_or_detect_cygwin (buf, NULL,
+ subsys, hm));
+ else
+ real_path.set_cygexec (false);
+ UnmapViewOfFile (buf);
+ CloseHandle (hm);
+ break;
+ }
}
- if (buf[0] == 'M' && buf[1] == 'Z')
+ __except (NO_ERROR)
{
- WORD subsys;
- unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
- win16_exe = off < sizeof (IMAGE_DOS_HEADER);
- if (!win16_exe)
- real_path.set_cygexec (hook_or_detect_cygwin (buf, NULL,
- subsys, hm));
- else
- real_path.set_cygexec (false);
UnmapViewOfFile (buf);
CloseHandle (hm);
+ real_path.set_cygexec (false);
break;
}
+ __endtry
}
CloseHandle (hm);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index d53bf347b..fe3a88da3 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1163,31 +1163,31 @@ getsid (pid_t pid)
extern "C" ssize_t
read (int fd, void *ptr, size_t len)
{
- pthread_testcancel ();
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
size_t res = (size_t) -1;
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- goto done;
+ pthread_testcancel ();
- if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)
+ __try
{
- set_errno (EBADF);
- goto done;
- }
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ __leave;
- /* Could block, so let user know we at least got here. */
- syscall_printf ("read(%d, %p, %d) %sblocking",
- fd, ptr, len, cfd->is_nonblocking () ? "non" : "");
+ if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
- cfd->read (ptr, res = len);
+ /* Could block, so let user know we at least got here. */
+ syscall_printf ("read(%d, %p, %d) %sblocking",
+ fd, ptr, len, cfd->is_nonblocking () ? "non" : "");
-done:
+ cfd->read (ptr, len);
+ res = len;
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%lR = read(%d, %p, %d)", res, fd, ptr, len);
MALLOC_CHECK;
return (ssize_t) res;
@@ -1198,38 +1198,38 @@ EXPORT_ALIAS (read, _read)
extern "C" ssize_t
readv (int fd, const struct iovec *const iov, const int iovcnt)
{
- pthread_testcancel ();
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
ssize_t res = -1;
- const ssize_t tot = check_iovec_for_read (iov, iovcnt);
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- goto done;
+ pthread_testcancel ();
- if (tot <= 0)
+ __try
{
- res = tot;
- goto done;
- }
+ const ssize_t tot = check_iovec_for_read (iov, iovcnt);
- if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)
- {
- set_errno (EBADF);
- goto done;
- }
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ __leave;
- /* Could block, so let user know we at least got here. */
- syscall_printf ("readv(%d, %p, %d) %sblocking",
- fd, iov, iovcnt, cfd->is_nonblocking () ? "non" : "");
+ if (tot <= 0)
+ {
+ res = tot;
+ __leave;
+ }
+
+ if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
- res = cfd->readv (iov, iovcnt, tot);
+ /* Could block, so let user know we at least got here. */
+ syscall_printf ("readv(%d, %p, %d) %sblocking",
+ fd, iov, iovcnt, cfd->is_nonblocking () ? "non" : "");
-done:
+ res = cfd->readv (iov, iovcnt, tot);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%lR = readv(%d, %p, %d)", res, fd, iov, iovcnt);
MALLOC_CHECK;
return res;
@@ -1238,9 +1238,10 @@ done:
extern "C" ssize_t
pread (int fd, void *ptr, size_t len, off_t off)
{
+ ssize_t res;
+
pthread_testcancel ();
- ssize_t res;
cygheap_fdget cfd (fd);
if (cfd < 0)
res = -1;
@@ -1254,35 +1255,33 @@ pread (int fd, void *ptr, size_t len, off_t off)
extern "C" ssize_t
write (int fd, const void *ptr, size_t len)
{
- pthread_testcancel ();
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
ssize_t res = -1;
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- goto done;
+ pthread_testcancel ();
- if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)
+ __try
{
- set_errno (EBADF);
- goto done;
- }
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ __leave;
- /* Could block, so let user know we at least got here. */
- if (fd == 1 || fd == 2)
- paranoid_printf ("write(%d, %p, %d)", fd, ptr, len);
- else
- syscall_printf ("write(%d, %p, %d)", fd, ptr, len);
+ if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
- res = cfd->write (ptr, len);
+ /* Could block, so let user know we at least got here. */
+ if (fd == 1 || fd == 2)
+ paranoid_printf ("write(%d, %p, %d)", fd, ptr, len);
+ else
+ syscall_printf ("write(%d, %p, %d)", fd, ptr, len);
-done:
+ res = cfd->write (ptr, len);
+ }
+ __except (EFAULT) {}
+ __endtry
syscall_printf ("%lR = write(%d, %p, %d)", res, fd, ptr, len);
-
MALLOC_CHECK;
return res;
}
@@ -1292,45 +1291,44 @@ EXPORT_ALIAS (write, _write)
extern "C" ssize_t
writev (const int fd, const struct iovec *const iov, const int iovcnt)
{
- pthread_testcancel ();
-
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
ssize_t res = -1;
- const ssize_t tot = check_iovec_for_write (iov, iovcnt);
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- goto done;
+ pthread_testcancel ();
- if (tot <= 0)
+ __try
{
- res = tot;
- goto done;
- }
+ const ssize_t tot = check_iovec_for_write (iov, iovcnt);
- if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)
- {
- set_errno (EBADF);
- goto done;
- }
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ __leave;
- /* Could block, so let user know we at least got here. */
- if (fd == 1 || fd == 2)
- paranoid_printf ("writev(%d, %p, %d)", fd, iov, iovcnt);
- else
- syscall_printf ("writev(%d, %p, %d)", fd, iov, iovcnt);
+ if (tot <= 0)
+ {
+ res = tot;
+ __leave;
+ }
- res = cfd->writev (iov, iovcnt, tot);
+ if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)
+ {
+ set_errno (EBADF);
+ __leave;
+ }
-done:
+ /* Could block, so let user know we at least got here. */
+ if (fd == 1 || fd == 2)
+ paranoid_printf ("writev(%d, %p, %d)", fd, iov, iovcnt);
+ else
+ syscall_printf ("writev(%d, %p, %d)", fd, iov, iovcnt);
+
+ res = cfd->writev (iov, iovcnt, tot);
+ }
+ __except (EFAULT) {}
+ __endtry
if (fd == 1 || fd == 2)
paranoid_printf ("%lR = writev(%d, %p, %d)", res, fd, iov, iovcnt);
else
syscall_printf ("%lR = writev(%d, %p, %d)", res, fd, iov, iovcnt);
-
MALLOC_CHECK;
return res;
}
@@ -1361,75 +1359,76 @@ open (const char *unix_path, int flags, ...)
va_list ap;
mode_t mode = 0;
- syscall_printf ("open(%s, %y)", unix_path, flags);
pthread_testcancel ();
- myfault efault;
- if (efault.faulted (EFAULT))
- /* errno already set */;
- else if (!*unix_path)
- set_errno (ENOENT);
- else
+
+ __try
{
- /* check for optional mode argument */
- va_start (ap, flags);
- mode = va_arg (ap, mode_t);
- va_end (ap);
+ syscall_printf ("open(%s, %y)", unix_path, flags);
+ if (!*unix_path)
+ set_errno (ENOENT);
+ else
+ {
+ /* check for optional mode argument */
+ va_start (ap, flags);
+ mode = va_arg (ap, mode_t);
+ va_end (ap);
- fhandler_base *fh;
- cygheap_fdnew fd;
+ fhandler_base *fh;
+ cygheap_fdnew fd;
- if (fd >= 0)
- {
- /* This is a temporary kludge until all utilities can catch up with
- a change in behavior that implements linux functionality: opening
- a tty should not automatically cause it to become the controlling
- tty for the process. */
- int opt = PC_OPEN | ((flags & (O_NOFOLLOW | O_EXCL))
- ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW);
- if (!(flags & O_NOCTTY) && fd > 2 && myself->ctty != -2)
- {
- flags |= O_NOCTTY;
- opt |= PC_CTTY; /* flag that, if opened, this fhandler could
- later be capable of being a controlling
- terminal if /dev/tty is opened. */
- }
- if (!(fh = build_fh_name (unix_path, opt, stat_suffixes)))
- res = -1; // errno already set
- else if ((flags & O_NOFOLLOW) && fh->issymlink ())
- {
- delete fh;
- res = -1;
- set_errno (ELOOP);
- }
- else if ((flags & O_DIRECTORY) && fh->exists () && !fh->pc.isdir ())
+ if (fd >= 0)
{
- delete fh;
- res = -1;
- set_errno (ENOTDIR);
- }
- else if (((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) && fh->exists ())
- {
- delete fh;
- res = -1;
- set_errno (EEXIST);
- }
- else if ((fh->is_fs_special () && fh->device_access_denied (flags))
- || !fh->open_with_arch (flags, (mode & 07777) & ~cygheap->umask))
- {
- delete fh;
- res = -1;
- }
- else
- {
- fd = fh;
- if (fd <= 2)
- set_std_handle (fd);
- res = fd;
+ /* This is a temporary kludge until all utilities can catch up
+ with a change in behavior that implements linux functionality:
+ opening a tty should not automatically cause it to become the
+ controlling tty for the process. */
+ int opt = PC_OPEN | ((flags & (O_NOFOLLOW | O_EXCL))
+ ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW);
+ if (!(flags & O_NOCTTY) && fd > 2 && myself->ctty != -2)
+ {
+ flags |= O_NOCTTY;
+ /* flag that, if opened, this fhandler could later be capable
+ of being a controlling terminal if /dev/tty is opened. */
+ opt |= PC_CTTY;
+ }
+ if (!(fh = build_fh_name (unix_path, opt, stat_suffixes)))
+ ; // errno already set
+ else if ((flags & O_NOFOLLOW) && fh->issymlink ())
+ {
+ delete fh;
+ set_errno (ELOOP);
+ }
+ else if ((flags & O_DIRECTORY) && fh->exists ()
+ && !fh->pc.isdir ())
+ {
+ delete fh;
+ set_errno (ENOTDIR);
+ }
+ else if (((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ && fh->exists ())
+ {
+ delete fh;
+ set_errno (EEXIST);
+ }
+ else if ((fh->is_fs_special ()
+ && fh->device_access_denied (flags))
+ || !fh->open_with_arch (flags, (mode & 07777)
+ & ~cygheap->umask))
+ delete fh;
+ else
+ {
+ fd = fh;
+ if (fd <= 2)
+ set_std_handle (fd);
+ res = fd;
+ }
}
}
- }
- syscall_printf ("%R = open(%s, %y)", res, unix_path, flags);
+ syscall_printf ("%R = open(%s, %y)", res, unix_path, flags);
+ }
+ __except (EFAULT) {}
+ __endtry
return res;
}
@@ -1893,34 +1892,33 @@ stat_worker (path_conv &pc, struct stat *buf)
{
int res = -1;
- myfault efault;
- if (efault.faulted (EFAULT))
- goto error;
-
- if (pc.error)
- {
- debug_printf ("got %d error from path_conv", pc.error);
- set_errno (pc.error);
- }
- else if (pc.exists ())
+ __try
{
- fhandler_base *fh;
+ if (pc.error)
+ {
+ debug_printf ("got %d error from path_conv", pc.error);
+ set_errno (pc.error);
+ }
+ else if (pc.exists ())
+ {
+ fhandler_base *fh;
- if (!(fh = build_fh_pc (pc)))
- goto error;
+ if (!(fh = build_fh_pc (pc)))
+ __leave;
- debug_printf ("(%S, %p, %p), file_attributes %d",
- pc.get_nt_native_path (), buf, fh, (DWORD) *fh);
- memset (buf, 0, sizeof (*buf));
- res = fh->fstat (buf);
- if (!res)
- fh->stat_fixup (buf);
- delete fh;
+ debug_printf ("(%S, %p, %p), file_attributes %d",
+ pc.get_nt_native_path (), buf, fh, (DWORD) *fh);
+ memset (buf, 0, sizeof (*buf));
+ res = fh->fstat (buf);
+ if (!res)
+ fh->stat_fixup (buf);
+ delete fh;
+ }
+ else
+ set_errno (ENOENT);
}
- else
- set_errno (ENOENT);
-
- error:
+ __except (EFAULT) {}
+ __endtry
MALLOC_CHECK;
syscall_printf ("%d = (%S,%p)", res, pc.get_nt_native_path (), buf);
return res;
@@ -2112,497 +2110,511 @@ rename (const char *oldpath, const char *newpath)
FILE_STANDARD_INFORMATION ofsi;
PFILE_RENAME_INFORMATION pfri;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- if (!*oldpath || !*newpath)
+ __try
{
- /* Reject rename("","x"), rename("x",""). */
- set_errno (ENOENT);
- goto out;
- }
- if (has_dot_last_component (oldpath, true))
- {
- /* Reject rename("dir/.","x"). */
- oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
- set_errno (oldpc.isdir () ? EINVAL : ENOTDIR);
- goto out;
- }
- if (has_dot_last_component (newpath, true))
- {
- /* Reject rename("dir","x/."). */
- newpc.check (newpath, PC_SYM_NOFOLLOW, stat_suffixes);
- set_errno (!newpc.exists () ? ENOENT : newpc.isdir () ? EINVAL : ENOTDIR);
- goto out;
- }
-
- /* A trailing slash requires that the pathname points to an existing
- directory. If it's not, it's a ENOTDIR condition. The same goes
- for newpath a bit further down this function. */
- olen = strlen (oldpath);
- if (isdirsep (oldpath[olen - 1]))
- {
- char *buf;
- char *p = stpcpy (buf = tp.c_get (), oldpath) - 1;
- oldpath = buf;
- while (p >= oldpath && isdirsep (*p))
- *p-- = '\0';
- olen = p + 1 - oldpath;
- if (!olen)
+ if (!*oldpath || !*newpath)
{
- /* The root directory cannot be renamed. This also rejects
- the corner case of rename("/","/"), even though it is the
- same file. */
- set_errno (EINVAL);
- goto out;
+ /* Reject rename("","x"), rename("x",""). */
+ set_errno (ENOENT);
+ __leave;
}
- old_dir_requested = true;
- }
- oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
- if (oldpc.error)
- {
- set_errno (oldpc.error);
- goto out;
- }
- if (!oldpc.exists ())
- {
- set_errno (ENOENT);
- goto out;
- }
- if (oldpc.isspecial () && !oldpc.issocket () && !oldpc.is_fs_special ())
- {
- /* No renames from virtual FS */
- set_errno (EROFS);
- goto out;
- }
- if (oldpc.has_attribute (FILE_ATTRIBUTE_REPARSE_POINT) && !oldpc.issymlink ())
- {
- /* Volume mount point. If we try to rename a volume mount point, NT
- returns STATUS_NOT_SAME_DEVICE ==> Win32 ERROR_NOT_SAME_DEVICE ==>
- errno EXDEV. That's bad since mv(1) will now perform a cross-device
- move. So what we do here is to treat the volume mount point just
- like Linux treats a mount point. */
- set_errno (EBUSY);
- goto out;
- }
- if (old_dir_requested && !oldpc.isdir ())
- {
- /* Reject rename("file/","x"). */
- set_errno (ENOTDIR);
- goto out;
- }
- if (oldpc.known_suffix
- && (ascii_strcasematch (oldpath + olen - 4, ".lnk")
- || ascii_strcasematch (oldpath + olen - 4, ".exe")))
- old_explicit_suffix = true;
-
- nlen = strlen (newpath);
- if (isdirsep (newpath[nlen - 1]))
- {
- char *buf;
- char *p = stpcpy (buf = tp.c_get (), newpath) - 1;
- newpath = buf;
- while (p >= newpath && isdirsep (*p))
- *p-- = '\0';
- nlen = p + 1 - newpath;
- if (!nlen) /* The root directory is never empty. */
+ if (has_dot_last_component (oldpath, true))
{
- set_errno (ENOTEMPTY);
- goto out;
+ /* Reject rename("dir/.","x"). */
+ oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
+ set_errno (oldpc.isdir () ? EINVAL : ENOTDIR);
+ __leave;
}
- new_dir_requested = true;
- }
- newpc.check (newpath, PC_SYM_NOFOLLOW, stat_suffixes);
- if (newpc.error)
- {
- set_errno (newpc.error);
- goto out;
- }
- if (newpc.isspecial () && !newpc.issocket ()) /* No renames to virtual FSes */
- {
- set_errno (EROFS);
- goto out;
- }
- if (new_dir_requested && !(newpc.exists ()
- ? newpc.isdir () : oldpc.isdir ()))
- {
- /* Reject rename("file1","file2/"), but allow rename("dir","d/"). */
- set_errno (newpc.exists () ? ENOTDIR : ENOENT);
- goto out;
- }
- if (newpc.exists () && (oldpc.isdir () ? !newpc.isdir () : newpc.isdir ()))
- {
- /* Reject rename("file","dir") and rename("dir","file"). */
- set_errno (newpc.isdir () ? EISDIR : ENOTDIR);
- goto out;
- }
- if (newpc.known_suffix
- && (ascii_strcasematch (newpath + nlen - 4, ".lnk")
- || ascii_strcasematch (newpath + nlen - 4, ".exe")))
- new_explicit_suffix = true;
-
- /* This test is necessary in almost every case, so just do it once here. */
- equal_path = RtlEqualUnicodeString (oldpc.get_nt_native_path (),
- newpc.get_nt_native_path (),
- oldpc.objcaseinsensitive ());
-
- /* First check if oldpath and newpath only differ by case. If so, it's
- just a request to change the case of the filename. By simply setting
- the file attributes to INVALID_FILE_ATTRIBUTES (which translates to
- "file doesn't exist"), all later tests are skipped. */
- if (oldpc.objcaseinsensitive () && newpc.exists () && equal_path
- && old_explicit_suffix == new_explicit_suffix)
- {
- if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
- newpc.get_nt_native_path (),
- FALSE))
+ if (has_dot_last_component (newpath, true))
{
- res = 0;
- goto out;
+ /* Reject rename("dir","x/."). */
+ newpc.check (newpath, PC_SYM_NOFOLLOW, stat_suffixes);
+ set_errno (!newpc.exists () ? ENOENT
+ : newpc.isdir () ? EINVAL : ENOTDIR);
+ __leave;
}
- newpc.file_attributes (INVALID_FILE_ATTRIBUTES);
- }
- else if (oldpc.isdir ())
- {
- /* Check for newpath being identical or a subdir of oldpath. */
- if (RtlPrefixUnicodeString (oldpc.get_nt_native_path (),
- newpc.get_nt_native_path (),
- TRUE))
+
+ /* A trailing slash requires that the pathname points to an existing
+ directory. If it's not, it's a ENOTDIR condition. The same goes
+ for newpath a bit further down this function. */
+ olen = strlen (oldpath);
+ if (isdirsep (oldpath[olen - 1]))
{
- if (newpc.get_nt_native_path ()->Length
- == oldpc.get_nt_native_path ()->Length)
- {
- res = 0;
- goto out;
- }
- if (*(PWCHAR) ((PBYTE) newpc.get_nt_native_path ()->Buffer
- + oldpc.get_nt_native_path ()->Length) == L'\\')
+ char *buf;
+ char *p = stpcpy (buf = tp.c_get (), oldpath) - 1;
+ oldpath = buf;
+ while (p >= oldpath && isdirsep (*p))
+ *p-- = '\0';
+ olen = p + 1 - oldpath;
+ if (!olen)
{
+ /* The root directory cannot be renamed. This also rejects
+ the corner case of rename("/","/"), even though it is the
+ same file. */
set_errno (EINVAL);
- goto out;
+ __leave;
}
+ old_dir_requested = true;
}
- }
- else if (!newpc.exists ())
- {
- if (equal_path && old_explicit_suffix != new_explicit_suffix)
+ oldpc.check (oldpath, PC_SYM_NOFOLLOW, stat_suffixes);
+ if (oldpc.error)
{
- newpc.check (newpath, PC_SYM_NOFOLLOW);
- if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
- newpc.get_nt_native_path (),
- oldpc.objcaseinsensitive ()))
+ set_errno (oldpc.error);
+ __leave;
+ }
+ if (!oldpc.exists ())
+ {
+ set_errno (ENOENT);
+ __leave;
+ }
+ if (oldpc.isspecial () && !oldpc.issocket () && !oldpc.is_fs_special ())
+ {
+ /* No renames from virtual FS */
+ set_errno (EROFS);
+ __leave;
+ }
+ if (oldpc.has_attribute (FILE_ATTRIBUTE_REPARSE_POINT)
+ && !oldpc.issymlink ())
+ {
+ /* Volume mount point. If we try to rename a volume mount point, NT
+ returns STATUS_NOT_SAME_DEVICE ==> Win32 ERROR_NOT_SAME_DEVICE ==>
+ errno EXDEV. That's bad since mv(1) will now perform a
+ cross-device move. So what we do here is to treat the volume
+ mount point just like Linux treats a mount point. */
+ set_errno (EBUSY);
+ __leave;
+ }
+ if (old_dir_requested && !oldpc.isdir ())
+ {
+ /* Reject rename("file/","x"). */
+ set_errno (ENOTDIR);
+ __leave;
+ }
+ if (oldpc.known_suffix
+ && (ascii_strcasematch (oldpath + olen - 4, ".lnk")
+ || ascii_strcasematch (oldpath + olen - 4, ".exe")))
+ old_explicit_suffix = true;
+
+ nlen = strlen (newpath);
+ if (isdirsep (newpath[nlen - 1]))
+ {
+ char *buf;
+ char *p = stpcpy (buf = tp.c_get (), newpath) - 1;
+ newpath = buf;
+ while (p >= newpath && isdirsep (*p))
+ *p-- = '\0';
+ nlen = p + 1 - newpath;
+ if (!nlen) /* The root directory is never empty. */
{
- res = 0;
- goto out;
+ set_errno (ENOTEMPTY);
+ __leave;
}
+ new_dir_requested = true;
}
- else if (oldpc.is_lnk_special ()
- && !RtlEqualUnicodePathSuffix (newpc.get_nt_native_path (),
- &ro_u_lnk, TRUE))
- rename_append_suffix (newpc, newpath, nlen, ".lnk");
- else if (oldpc.is_binary () && !old_explicit_suffix
- && oldpc.known_suffix
- && !nt_path_has_executable_suffix (newpc.get_nt_native_path ()))
- /* Never append .exe suffix if oldpath had .exe suffix given
- explicitely, or if oldpath wasn't already a .exe file, or
- if the destination filename has one of the blessed executable
- suffixes.
- Note: To rename an executable foo.exe to bar-without-suffix,
- the .exe suffix must be given explicitly in oldpath. */
- rename_append_suffix (newpc, newpath, nlen, ".exe");
- }
- else
- {
- if (equal_path && old_explicit_suffix != new_explicit_suffix)
+ newpc.check (newpath, PC_SYM_NOFOLLOW, stat_suffixes);
+ if (newpc.error)
+ {
+ set_errno (newpc.error);
+ __leave;
+ }
+ if (newpc.isspecial () && !newpc.issocket ())
+ {
+ /* No renames to virtual FSes */
+ set_errno (EROFS);
+ __leave;
+ }
+ if (new_dir_requested && !(newpc.exists ()
+ ? newpc.isdir () : oldpc.isdir ()))
+ {
+ /* Reject rename("file1","file2/"), but allow rename("dir","d/"). */
+ set_errno (newpc.exists () ? ENOTDIR : ENOENT);
+ __leave;
+ }
+ if (newpc.exists ()
+ && (oldpc.isdir () ? !newpc.isdir () : newpc.isdir ()))
+ {
+ /* Reject rename("file","dir") and rename("dir","file"). */
+ set_errno (newpc.isdir () ? EISDIR : ENOTDIR);
+ __leave;
+ }
+ if (newpc.known_suffix
+ && (ascii_strcasematch (newpath + nlen - 4, ".lnk")
+ || ascii_strcasematch (newpath + nlen - 4, ".exe")))
+ new_explicit_suffix = true;
+
+ /* This test is necessary in almost every case, so do it once here. */
+ equal_path = RtlEqualUnicodeString (oldpc.get_nt_native_path (),
+ newpc.get_nt_native_path (),
+ oldpc.objcaseinsensitive ());
+
+ /* First check if oldpath and newpath only differ by case. If so, it's
+ just a request to change the case of the filename. By simply setting
+ the file attributes to INVALID_FILE_ATTRIBUTES (which translates to
+ "file doesn't exist"), all later tests are skipped. */
+ if (oldpc.objcaseinsensitive () && newpc.exists () && equal_path
+ && old_explicit_suffix == new_explicit_suffix)
{
- newpc.check (newpath, PC_SYM_NOFOLLOW);
if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
newpc.get_nt_native_path (),
- oldpc.objcaseinsensitive ()))
+ FALSE))
{
res = 0;
- goto out;
+ __leave;
}
+ newpc.file_attributes (INVALID_FILE_ATTRIBUTES);
}
- else if (oldpc.is_lnk_special ())
+ else if (oldpc.isdir ())
{
- if (!newpc.is_lnk_special ()
- && !RtlEqualUnicodePathSuffix (newpc.get_nt_native_path (),
- &ro_u_lnk, TRUE))
+ /* Check for newpath being identical or a subdir of oldpath. */
+ if (RtlPrefixUnicodeString (oldpc.get_nt_native_path (),
+ newpc.get_nt_native_path (),
+ TRUE))
{
- rename_append_suffix (new2pc, newpath, nlen, ".lnk");
- removepc = &newpc;
+ if (newpc.get_nt_native_path ()->Length
+ == oldpc.get_nt_native_path ()->Length)
+ {
+ res = 0;
+ __leave;
+ }
+ if (*(PWCHAR) ((PBYTE) newpc.get_nt_native_path ()->Buffer
+ + oldpc.get_nt_native_path ()->Length) == L'\\')
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
}
}
- else if (oldpc.is_binary ())
+ else if (!newpc.exists ())
{
- /* Never append .exe suffix if oldpath had .exe suffix given
- explicitely, or if newfile is a binary (in which case the given
- name probably makes sense as it is), or if the destination
- filename has one of the blessed executable suffixes. */
- if (!old_explicit_suffix && oldpc.known_suffix
- && !newpc.is_binary ()
- && !nt_path_has_executable_suffix (newpc.get_nt_native_path ()))
+ if (equal_path && old_explicit_suffix != new_explicit_suffix)
{
- rename_append_suffix (new2pc, newpath, nlen, ".exe");
- removepc = &newpc;
+ newpc.check (newpath, PC_SYM_NOFOLLOW);
+ if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
+ newpc.get_nt_native_path (),
+ oldpc.objcaseinsensitive ()))
+ {
+ res = 0;
+ __leave;
+ }
}
+ else if (oldpc.is_lnk_special ()
+ && !RtlEqualUnicodePathSuffix (newpc.get_nt_native_path (),
+ &ro_u_lnk, TRUE))
+ rename_append_suffix (newpc, newpath, nlen, ".lnk");
+ else if (oldpc.is_binary () && !old_explicit_suffix
+ && oldpc.known_suffix
+ && !nt_path_has_executable_suffix
+ (newpc.get_nt_native_path ()))
+ /* Never append .exe suffix if oldpath had .exe suffix given
+ explicitely, or if oldpath wasn't already a .exe file, or
+ if the destination filename has one of the blessed executable
+ suffixes.
+ Note: To rename an executable foo.exe to bar-without-suffix,
+ the .exe suffix must be given explicitly in oldpath. */
+ rename_append_suffix (newpc, newpath, nlen, ".exe");
}
else
{
- /* If the new path is an existing .lnk symlink or a .exe file,
- but the new path has not been specified with explicit suffix,
- rename to the new name without suffix, as expected, but also
- remove the clashing symlink or executable. Did I ever mention
- how I hate the file suffix idea? */
- if ((newpc.is_lnk_special ()
- || RtlEqualUnicodePathSuffix (newpc.get_nt_native_path (),
- &ro_u_exe, TRUE))
- && !new_explicit_suffix)
+ if (equal_path && old_explicit_suffix != new_explicit_suffix)
{
- new2pc.check (newpath, PC_SYM_NOFOLLOW, stat_suffixes);
- newpc.get_nt_native_path ()->Length -= 4 * sizeof (WCHAR);
- if (new2pc.is_binary () || new2pc.is_lnk_special ())
- removepc = &new2pc;
+ newpc.check (newpath, PC_SYM_NOFOLLOW);
+ if (RtlEqualUnicodeString (oldpc.get_nt_native_path (),
+ newpc.get_nt_native_path (),
+ oldpc.objcaseinsensitive ()))
+ {
+ res = 0;
+ __leave;
+ }
}
- }
- }
- dstpc = (removepc == &newpc) ? &new2pc : &newpc;
-
- /* Check cross-device before touching anything. Otherwise we might end
- up with an unlinked target dir even if the actual rename didn't work. */
- if (oldpc.fs_type () != dstpc->fs_type ()
- || oldpc.fs_serial_number () != dstpc->fs_serial_number ())
- {
- set_errno (EXDEV);
- goto out;
- }
-
- /* Opening the file must be part of the transaction. It's not sufficient
- to call only NtSetInformationFile under the transaction. Therefore we
- have to start the transaction here, if necessary. */
- if (wincap.has_transactions ()
- && (dstpc->fs_flags () & FILE_SUPPORTS_TRANSACTIONS)
- && (dstpc->isdir ()
- || (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))))
- start_transaction (old_trans, trans);
-
- int retry_count;
- retry_count = 0;
-retry:
- /* Talking about inconsistent behaviour...
- - DELETE is required to rename a file. So far, so good.
- - At least one cifs FS (Tru64) needs FILE_READ_ATTRIBUTE, otherwise the
- FileRenameInformation call fails with STATUS_ACCESS_DENIED. However,
- on NFS we get a STATUS_ACCESS_DENIED if FILE_READ_ATTRIBUTE is used
- and the file we try to rename is a symlink. Urgh.
- - Samba (only some versions?) doesn't like the FILE_SHARE_DELETE mode if
- the file has the R/O attribute set and returns STATUS_ACCESS_DENIED in
- that case. */
- {
- ULONG access = DELETE | (oldpc.fs_is_cifs () ? FILE_READ_ATTRIBUTES : 0);
- ULONG sharing = FILE_SHARE_READ | FILE_SHARE_WRITE
- | (oldpc.fs_is_samba () ? 0 : FILE_SHARE_DELETE);
- ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT
- | (oldpc.is_rep_symlink () ? FILE_OPEN_REPARSE_POINT : 0);
- status = NtOpenFile (&fh, access,
- oldpc.get_object_attr (attr, sec_none_nih),
- &io, sharing, flags);
- }
- if (!NT_SUCCESS (status))
- {
- debug_printf ("status %y", status);
- if (status == STATUS_SHARING_VIOLATION
- && cygwait (10L) != WAIT_SIGNALED)
- {
- /* Typical BLODA problem. Some virus scanners check newly generated
- files and while doing that disallow DELETE access. That's really
- bad because it breaks applications which copy files by creating
- a temporary filename and then rename the temp filename to the
- target filename. This renaming fails due to the jealous virus
- scanner and the application fails to create the target file.
-
- This kludge tries to work around that by yielding until the
- sharing violation goes away, or a signal arrived, or after
- about a second, give or take. */
- if (++retry_count < 40)
+ else if (oldpc.is_lnk_special ())
{
- yield ();
- goto retry;
+ if (!newpc.is_lnk_special ()
+ && !RtlEqualUnicodePathSuffix (newpc.get_nt_native_path (),
+ &ro_u_lnk, TRUE))
+ {
+ rename_append_suffix (new2pc, newpath, nlen, ".lnk");
+ removepc = &newpc;
+ }
+ }
+ else if (oldpc.is_binary ())
+ {
+ /* Never append .exe suffix if oldpath had .exe suffix given
+ explicitely, or if newfile is a binary (in which case the given
+ name probably makes sense as it is), or if the destination
+ filename has one of the blessed executable suffixes. */
+ if (!old_explicit_suffix && oldpc.known_suffix
+ && !newpc.is_binary ()
+ && !nt_path_has_executable_suffix
+ (newpc.get_nt_native_path ()))
+ {
+ rename_append_suffix (new2pc, newpath, nlen, ".exe");
+ removepc = &newpc;
+ }
+ }
+ else
+ {
+ /* If the new path is an existing .lnk symlink or a .exe file,
+ but the new path has not been specified with explicit suffix,
+ rename to the new name without suffix, as expected, but also
+ remove the clashing symlink or executable. Did I ever mention
+ how I hate the file suffix idea? */
+ if ((newpc.is_lnk_special ()
+ || RtlEqualUnicodePathSuffix (newpc.get_nt_native_path (),
+ &ro_u_exe, TRUE))
+ && !new_explicit_suffix)
+ {
+ new2pc.check (newpath, PC_SYM_NOFOLLOW, stat_suffixes);
+ newpc.get_nt_native_path ()->Length -= 4 * sizeof (WCHAR);
+ if (new2pc.is_binary () || new2pc.is_lnk_special ())
+ removepc = &new2pc;
+ }
}
}
- else if (NT_TRANSACTIONAL_ERROR (status) && trans)
+ dstpc = (removepc == &newpc) ? &new2pc : &newpc;
+
+ /* Check cross-device before touching anything. Otherwise we might end
+ up with an unlinked target dir even if the actual rename didn't work.*/
+ if (oldpc.fs_type () != dstpc->fs_type ()
+ || oldpc.fs_serial_number () != dstpc->fs_serial_number ())
{
- /* If NtOpenFile fails due to transactional problems, stop
- transaction and go ahead without. */
- stop_transaction (status, old_trans, trans);
- debug_printf ("Transaction failure. Retry open.");
- goto retry;
+ set_errno (EXDEV);
+ __leave;
}
- __seterrno_from_nt_status (status);
- goto out;
- }
- /* Renaming a dir to another, existing dir fails always, even if
- ReplaceIfExists is set to TRUE and the existing dir is empty. So
- we have to remove the destination dir first. This also covers the
- case that the destination directory is not empty. In that case,
- unlink_nt returns with STATUS_DIRECTORY_NOT_EMPTY. */
- if (dstpc->isdir ())
- {
- status = unlink_nt (*dstpc);
+ /* Opening the file must be part of the transaction. It's not sufficient
+ to call only NtSetInformationFile under the transaction. Therefore we
+ have to start the transaction here, if necessary. */
+ if (wincap.has_transactions ()
+ && (dstpc->fs_flags () & FILE_SUPPORTS_TRANSACTIONS)
+ && (dstpc->isdir ()
+ || (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))))
+ start_transaction (old_trans, trans);
+
+ int retry_count;
+ retry_count = 0;
+ retry:
+ /* Talking about inconsistent behaviour...
+ - DELETE is required to rename a file. So far, so good.
+ - At least one cifs FS (Tru64) needs FILE_READ_ATTRIBUTE, otherwise the
+ FileRenameInformation call fails with STATUS_ACCESS_DENIED. However,
+ on NFS we get a STATUS_ACCESS_DENIED if FILE_READ_ATTRIBUTE is used
+ and the file we try to rename is a symlink. Urgh.
+ - Samba (only some versions?) doesn't like the FILE_SHARE_DELETE
+ mode if the file has the R/O attribute set and returns
+ STATUS_ACCESS_DENIED in that case. */
+ {
+ ULONG access = DELETE
+ | (oldpc.fs_is_cifs () ? FILE_READ_ATTRIBUTES : 0);
+ ULONG sharing = FILE_SHARE_READ | FILE_SHARE_WRITE
+ | (oldpc.fs_is_samba () ? 0 : FILE_SHARE_DELETE);
+ ULONG flags = FILE_OPEN_FOR_BACKUP_INTENT
+ | (oldpc.is_rep_symlink () ? FILE_OPEN_REPARSE_POINT : 0);
+ status = NtOpenFile (&fh, access,
+ oldpc.get_object_attr (attr, sec_none_nih),
+ &io, sharing, flags);
+ }
if (!NT_SUCCESS (status))
{
+ debug_printf ("status %y", status);
+ if (status == STATUS_SHARING_VIOLATION
+ && cygwait (10L) != WAIT_SIGNALED)
+ {
+ /* Typical BLODA problem. Some virus scanners check newly
+ generated files and while doing that disallow DELETE access.
+ That's really bad because it breaks applications which copy
+ files by creating a temporary filename and then rename the
+ temp filename to the target filename. This renaming fails due
+ to the jealous virus scanner and the application fails to
+ create the target file.
+
+ This kludge tries to work around that by yielding until the
+ sharing violation goes away, or a signal arrived, or after
+ about a second, give or take. */
+ if (++retry_count < 40)
+ {
+ yield ();
+ goto retry;
+ }
+ }
+ else if (NT_TRANSACTIONAL_ERROR (status) && trans)
+ {
+ /* If NtOpenFile fails due to transactional problems, stop
+ transaction and go ahead without. */
+ stop_transaction (status, old_trans, trans);
+ debug_printf ("Transaction failure. Retry open.");
+ goto retry;
+ }
__seterrno_from_nt_status (status);
- goto out;
+ __leave;
}
- }
- /* You can't copy a file if the destination exists and has the R/O
- attribute set. Remove the R/O attribute first. But first check
- if a removepc exists. If so, dstpc points to a non-existing file
- due to a mangled suffix. */
- else if (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))
- {
- status = NtOpenFile (&nfh, FILE_WRITE_ATTRIBUTES,
- dstpc->get_object_attr (attr, sec_none_nih),
- &io, FILE_SHARE_VALID_FLAGS,
- FILE_OPEN_FOR_BACKUP_INTENT
- | (dstpc->is_rep_symlink ()
- ? FILE_OPEN_REPARSE_POINT : 0));
- if (!NT_SUCCESS (status))
+
+ /* Renaming a dir to another, existing dir fails always, even if
+ ReplaceIfExists is set to TRUE and the existing dir is empty. So
+ we have to remove the destination dir first. This also covers the
+ case that the destination directory is not empty. In that case,
+ unlink_nt returns with STATUS_DIRECTORY_NOT_EMPTY. */
+ if (dstpc->isdir ())
{
- __seterrno_from_nt_status (status);
- goto out;
+ status = unlink_nt (*dstpc);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ __leave;
+ }
}
- status = NtSetAttributesFile (nfh, dstpc->file_attributes ()
- & ~FILE_ATTRIBUTE_READONLY);
- NtClose (nfh);
- if (!NT_SUCCESS (status))
+ /* You can't copy a file if the destination exists and has the R/O
+ attribute set. Remove the R/O attribute first. But first check
+ if a removepc exists. If so, dstpc points to a non-existing file
+ due to a mangled suffix. */
+ else if (!removepc && dstpc->has_attribute (FILE_ATTRIBUTE_READONLY))
{
- __seterrno_from_nt_status (status);
- goto out;
+ status = NtOpenFile (&nfh, FILE_WRITE_ATTRIBUTES,
+ dstpc->get_object_attr (attr, sec_none_nih),
+ &io, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | (dstpc->is_rep_symlink ()
+ ? FILE_OPEN_REPARSE_POINT : 0));
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ __leave;
+ }
+ status = NtSetAttributesFile (nfh, dstpc->file_attributes ()
+ & ~FILE_ATTRIBUTE_READONLY);
+ NtClose (nfh);
+ if (!NT_SUCCESS (status))
+ {
+ __seterrno_from_nt_status (status);
+ __leave;
+ }
}
- }
- /* SUSv3: If the old argument and the new argument resolve to the same
- existing file, rename() shall return successfully and perform no
- other action.
- The test tries to be as quick as possible. Due to the above cross device
- check we already know both files are on the same device. So it just
- tests if oldpath has more than 1 hardlink, then it opens newpath
- and tests for identical file ids. If so, oldpath and newpath refer to
- the same file. */
- if ((removepc || dstpc->exists ())
- && !oldpc.isdir ()
- && NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofsi, sizeof ofsi,
- FileStandardInformation))
- && ofsi.NumberOfLinks > 1
- && NT_SUCCESS (NtOpenFile (&nfh, READ_CONTROL,
+ /* SUSv3: If the old argument and the new argument resolve to the same
+ existing file, rename() shall return successfully and perform no
+ other action.
+ The test tries to be as quick as possible. Due to the above cross
+ device check we already know both files are on the same device. So
+ it just tests if oldpath has more than 1 hardlink, then it opens
+ newpath and tests for identical file ids. If so, oldpath and newpath
+ refer to the same file. */
+ if ((removepc || dstpc->exists ())
+ && !oldpc.isdir ()
+ && NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofsi, sizeof ofsi,
+ FileStandardInformation))
+ && ofsi.NumberOfLinks > 1
+ && NT_SUCCESS (NtOpenFile (&nfh, READ_CONTROL,
(removepc ?: dstpc)->get_object_attr (attr, sec_none_nih),
&io, FILE_SHARE_VALID_FLAGS,
FILE_OPEN_FOR_BACKUP_INTENT
| ((removepc ?: dstpc)->is_rep_symlink ()
? FILE_OPEN_REPARSE_POINT : 0))))
- {
- FILE_INTERNAL_INFORMATION ofii, nfii;
-
- if (NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofii, sizeof ofii,
- FileInternalInformation))
- && NT_SUCCESS (NtQueryInformationFile (nfh, &io, &nfii, sizeof nfii,
- FileInternalInformation))
- && ofii.FileId.QuadPart == nfii.FileId.QuadPart)
{
- debug_printf ("%s and %s are the same file", oldpath, newpath);
+ FILE_INTERNAL_INFORMATION ofii, nfii;
+
+ if (NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofii, sizeof ofii,
+ FileInternalInformation))
+ && NT_SUCCESS (NtQueryInformationFile (nfh, &io, &nfii,
+ sizeof nfii,
+ FileInternalInformation))
+ && ofii.FileId.QuadPart == nfii.FileId.QuadPart)
+ {
+ debug_printf ("%s and %s are the same file", oldpath, newpath);
+ NtClose (nfh);
+ res = 0;
+ __leave;
+ }
NtClose (nfh);
- res = 0;
- goto out;
}
- NtClose (nfh);
- }
- /* Create FILE_RENAME_INFORMATION struct. Using a tmp_pathbuf area allows
- for paths of up to 32757 chars. This test is just for paranoia's sake. */
- if (dstpc->get_nt_native_path ()->Length > NT_MAX_PATH * sizeof (WCHAR)
- - sizeof (FILE_RENAME_INFORMATION))
- {
- debug_printf ("target filename too long");
- set_errno (EINVAL);
- goto out;
- }
- pfri = (PFILE_RENAME_INFORMATION) tp.w_get ();
- pfri->ReplaceIfExists = TRUE;
- pfri->RootDirectory = NULL;
- pfri->FileNameLength = dstpc->get_nt_native_path ()->Length;
- memcpy (&pfri->FileName, dstpc->get_nt_native_path ()->Buffer,
- pfri->FileNameLength);
- status = NtSetInformationFile (fh, &io, pfri,
- sizeof *pfri + pfri->FileNameLength,
- FileRenameInformation);
- /* This happens if the access rights don't allow deleting the destination.
- Even if the handle to the original file is opened with BACKUP
- and/or RECOVERY, these flags don't apply to the destination of the
- rename operation. So, a privileged user can't rename a file to an
- existing file, if the permissions of the existing file aren't right.
- Like directories, we have to handle this separately by removing the
- destination before renaming. */
- if (status == STATUS_ACCESS_DENIED && dstpc->exists () && !dstpc->isdir ())
- {
- if (wincap.has_transactions ()
- && (dstpc->fs_flags () & FILE_SUPPORTS_TRANSACTIONS)
- && !trans)
+ /* Create FILE_RENAME_INFORMATION struct. Using a tmp_pathbuf area
+ allows for paths of up to 32757 chars. This test is just for
+ paranoia's sake. */
+ if (dstpc->get_nt_native_path ()->Length
+ > NT_MAX_PATH * sizeof (WCHAR) - sizeof (FILE_RENAME_INFORMATION))
{
- start_transaction (old_trans, trans);
- /* As mentioned earlier, opening the file must be part of the
- transaction. Therefore we have to reopen the file here if the
- transaction hasn't been started already. Unfortunately we can't
- use the NT "reopen file from existing handle" feature. In that
- case NtOpenFile returns STATUS_TRANSACTIONAL_CONFLICT. We *have*
- to close the handle to the file first, *then* we can re-open it.
- Fortunately nothing has happened yet, so the atomicity of the
- rename functionality is not spoiled. */
- NtClose (fh);
-retry_reopen:
- status = NtOpenFile (&fh, DELETE,
- oldpc.get_object_attr (attr, sec_none_nih),
- &io, FILE_SHARE_VALID_FLAGS,
- FILE_OPEN_FOR_BACKUP_INTENT
- | (oldpc.is_rep_symlink ()
- ? FILE_OPEN_REPARSE_POINT : 0));
- if (!NT_SUCCESS (status))
+ debug_printf ("target filename too long");
+ set_errno (EINVAL);
+ __leave;
+ }
+ pfri = (PFILE_RENAME_INFORMATION) tp.w_get ();
+ pfri->ReplaceIfExists = TRUE;
+ pfri->RootDirectory = NULL;
+ pfri->FileNameLength = dstpc->get_nt_native_path ()->Length;
+ memcpy (&pfri->FileName, dstpc->get_nt_native_path ()->Buffer,
+ pfri->FileNameLength);
+ status = NtSetInformationFile (fh, &io, pfri,
+ sizeof *pfri + pfri->FileNameLength,
+ FileRenameInformation);
+ /* This happens if the access rights don't allow deleting the destination.
+ Even if the handle to the original file is opened with BACKUP
+ and/or RECOVERY, these flags don't apply to the destination of the
+ rename operation. So, a privileged user can't rename a file to an
+ existing file, if the permissions of the existing file aren't right.
+ Like directories, we have to handle this separately by removing the
+ destination before renaming. */
+ if (status == STATUS_ACCESS_DENIED && dstpc->exists ()
+ && !dstpc->isdir ())
+ {
+ if (wincap.has_transactions ()
+ && (dstpc->fs_flags () & FILE_SUPPORTS_TRANSACTIONS)
+ && !trans)
{
- if (NT_TRANSACTIONAL_ERROR (status) && trans)
+ start_transaction (old_trans, trans);
+ /* As mentioned earlier, opening the file must be part of the
+ transaction. Therefore we have to reopen the file here if the
+ transaction hasn't been started already. Unfortunately we
+ can't use the NT "reopen file from existing handle" feature.
+ In that case NtOpenFile returns STATUS_TRANSACTIONAL_CONFLICT.
+ We *have* to close the handle to the file first, *then* we can
+ re-open it. Fortunately nothing has happened yet, so the
+ atomicity of the rename functionality is not spoiled. */
+ NtClose (fh);
+ retry_reopen:
+ status = NtOpenFile (&fh, DELETE,
+ oldpc.get_object_attr (attr, sec_none_nih),
+ &io, FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT
+ | (oldpc.is_rep_symlink ()
+ ? FILE_OPEN_REPARSE_POINT : 0));
+ if (!NT_SUCCESS (status))
{
- /* If NtOpenFile fails due to transactional problems, stop
- transaction and go ahead without. */
- stop_transaction (status, old_trans, trans);
- debug_printf ("Transaction failure. Retry open.");
- goto retry_reopen;
+ if (NT_TRANSACTIONAL_ERROR (status) && trans)
+ {
+ /* If NtOpenFile fails due to transactional problems,
+ stop transaction and go ahead without. */
+ stop_transaction (status, old_trans, trans);
+ debug_printf ("Transaction failure. Retry open.");
+ goto retry_reopen;
+ }
+ __seterrno_from_nt_status (status);
+ __leave;
}
- __seterrno_from_nt_status (status);
- goto out;
}
+ if (NT_SUCCESS (status = unlink_nt (*dstpc)))
+ status = NtSetInformationFile (fh, &io, pfri,
+ sizeof *pfri + pfri->FileNameLength,
+ FileRenameInformation);
+ }
+ if (NT_SUCCESS (status))
+ {
+ if (removepc)
+ unlink_nt (*removepc);
+ res = 0;
}
- if (NT_SUCCESS (status = unlink_nt (*dstpc)))
- status = NtSetInformationFile (fh, &io, pfri,
- sizeof *pfri + pfri->FileNameLength,
- FileRenameInformation);
+ else
+ __seterrno_from_nt_status (status);
}
- if (NT_SUCCESS (status))
+ __except (EFAULT)
{
- if (removepc)
- unlink_nt (*removepc);
- res = 0;
+ res = -1;
}
- else
- __seterrno_from_nt_status (status);
-
-out:
+ __endtry
if (fh)
NtClose (fh);
/* Stop transaction if we started one. */
if (trans)
stop_transaction (status, old_trans, trans);
- syscall_printf ("%R = rename(%s, %s)", res, oldpath, newpath);
+ if (get_errno () != EFAULT)
+ syscall_printf ("%R = rename(%s, %s)", res, oldpath, newpath);
return res;
}
@@ -2611,28 +2623,28 @@ system (const char *cmdstring)
{
pthread_testcancel ();
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- int res;
- const char* command[4];
-
if (cmdstring == NULL)
return 1;
- command[0] = "sh";
- command[1] = "-c";
- command[2] = cmdstring;
- command[3] = (const char *) NULL;
+ int res = -1;
+ const char* command[4];
- if ((res = spawnvp (_P_SYSTEM, "/bin/sh", command)) == -1)
+ __try
{
- // when exec fails, return value should be as if shell
- // executed exit (127)
- res = 127;
- }
+ command[0] = "sh";
+ command[1] = "-c";
+ command[2] = cmdstring;
+ command[3] = (const char *) NULL;
+ if ((res = spawnvp (_P_SYSTEM, "/bin/sh", command)) == -1)
+ {
+ // when exec fails, return value should be as if shell
+ // executed exit (127)
+ res = 127;
+ }
+ }
+ __except (EFAULT) {}
+ __endtry
return res;
}
@@ -2677,24 +2689,25 @@ fpathconf (int fd, int v)
extern "C" long int
pathconf (const char *file, int v)
{
- fhandler_base *fh;
+ fhandler_base *fh = NULL;
long ret = -1;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- if (!*file)
+ __try
{
- set_errno (ENOENT);
- return -1;
+ if (!*file)
+ {
+ set_errno (ENOENT);
+ return -1;
+ }
+ if (!(fh = build_fh_name (file, PC_SYM_FOLLOW, stat_suffixes)))
+ return -1;
+ if (!fh->exists ())
+ set_errno (ENOENT);
+ else
+ ret = fh->fpathconf (v);
}
- if (!(fh = build_fh_name (file, PC_SYM_FOLLOW, stat_suffixes)))
- return -1;
- if (!fh->exists ())
- set_errno (ENOENT);
- else
- ret = fh->fpathconf (v);
+ __except (EFAULT) {}
+ __endtry
delete fh;
return ret;
}
@@ -2703,10 +2716,8 @@ extern "C" int
ttyname_r (int fd, char *buf, size_t buflen)
{
int ret = 0;
- myfault efault;
- if (efault.faulted ())
- ret = EFAULT;
- else
+
+ __try
{
cygheap_fdget cfd (fd, true);
if (cfd < 0)
@@ -2717,8 +2728,13 @@ ttyname_r (int fd, char *buf, size_t buflen)
ret = ERANGE;
else
strcpy (buf, cfd->ttyname ());
+ debug_printf ("returning %d tty: %s", ret, ret ? "NULL" : buf);
}
- debug_printf ("returning %d tty: %s", ret, ret ? "NULL" : buf);
+ __except (NO_ERROR)
+ {
+ ret = EFAULT;
+ }
+ __endtry
return ret;
}
@@ -2975,14 +2991,16 @@ _get_osfhandle (int fd)
extern "C" int
fstatvfs (int fd, struct statvfs *sfs)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- return -1;
- return cfd->fstatvfs (sfs);
+ __try
+ {
+ cygheap_fdget cfd (fd);
+ if (cfd < 0)
+ __leave;
+ return cfd->fstatvfs (sfs);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -2991,30 +3009,31 @@ statvfs (const char *name, struct statvfs *sfs)
int res = -1;
fhandler_base *fh = NULL;
- myfault efault;
- if (efault.faulted (EFAULT))
- goto error;
+ __try
+ {
+ if (!(fh = build_fh_name (name, PC_SYM_FOLLOW, stat_suffixes)))
+ __leave;
- if (!(fh = build_fh_name (name, PC_SYM_FOLLOW, stat_suffixes)))
- goto error;
+ if (fh->error ())
+ {
+ debug_printf ("got %d error from build_fh_name", fh->error ());
+ set_errno (fh->error ());
+ }
+ else if (fh->exists ())
+ {
+ debug_printf ("(%s, %p), file_attributes %d", name, sfs, (DWORD) *fh);
+ res = fh->fstatvfs (sfs);
+ }
+ else
+ set_errno (ENOENT);
- if (fh->error ())
- {
- debug_printf ("got %d error from build_fh_name", fh->error ());
- set_errno (fh->error ());
- }
- else if (fh->exists ())
- {
- debug_printf ("(%s, %p), file_attributes %d", name, sfs, (DWORD) *fh);
- res = fh->fstatvfs (sfs);
}
- else
- set_errno (ENOENT);
-
+ __except (EFAULT) {}
+ __endtry
delete fh;
- error:
MALLOC_CHECK;
- syscall_printf ("%R = statvfs(%s,%p)", res, name, sfs);
+ if (get_errno () != EFAULT)
+ syscall_printf ("%R = statvfs(%s,%p)", res, name, sfs);
return res;
}
@@ -3155,55 +3174,58 @@ mknod_worker (const char *path, mode_t type, mode_t mode, _major_t major,
extern "C" int
mknod32 (const char *path, mode_t mode, dev_t dev)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (!*path)
+ __try
{
- set_errno (ENOENT);
- return -1;
- }
+ if (!*path)
+ {
+ set_errno (ENOENT);
+ __leave;
+ }
- if (strlen (path) >= PATH_MAX)
- return -1;
+ if (strlen (path) >= PATH_MAX)
+ __leave;
- path_conv w32path (path, PC_SYM_NOFOLLOW);
- if (w32path.exists ())
- {
- set_errno (EEXIST);
- return -1;
- }
+ path_conv w32path (path, PC_SYM_NOFOLLOW);
+ if (w32path.exists ())
+ {
+ set_errno (EEXIST);
+ __leave;
+ }
- mode_t type = mode & S_IFMT;
- _major_t major = _major (dev);
- _minor_t minor = _minor (dev);
- switch (type)
- {
- case S_IFCHR:
- case S_IFBLK:
- break;
+ mode_t type = mode & S_IFMT;
+ _major_t major = _major (dev);
+ _minor_t minor = _minor (dev);
+ switch (type)
+ {
+ case S_IFCHR:
+ case S_IFBLK:
+ break;
- case S_IFIFO:
- major = _major (FH_FIFO);
- minor = _minor (FH_FIFO);
- break;
+ case S_IFIFO:
+ major = _major (FH_FIFO);
+ minor = _minor (FH_FIFO);
+ break;
- case 0:
- case S_IFREG:
- {
- int fd = open (path, O_CREAT, mode);
- if (fd < 0)
- return -1;
- close (fd);
- return 0;
- }
+ case 0:
+ case S_IFREG:
+ {
+ int fd = open (path, O_CREAT, mode);
+ if (fd < 0)
+ __leave;
+ close (fd);
+ return 0;
+ }
- default:
- set_errno (EINVAL);
- return -1;
- }
+ default:
+ set_errno (EINVAL);
+ __leave;
+ }
- return mknod_worker (w32path.get_win32 (), type, mode, major, minor);
+ return mknod_worker (w32path.get_win32 (), type, mode, major, minor);
+ }
+ __except (EFAULT)
+ __endtry
+ return -1;
}
extern "C" int
@@ -3912,15 +3934,19 @@ endutent ()
extern "C" void
utmpname (const char *file)
{
- myfault efault;
- if (efault.faulted () || !*file)
+ __try
{
- debug_printf ("Invalid file");
- return;
+ if (*file)
+ {
+ endutent ();
+ utmp_file = strdup (file);
+ debug_printf ("New UTMP file: %s", utmp_file);
+ return;
+ }
}
- endutent ();
- utmp_file = strdup (file);
- debug_printf ("New UTMP file: %s", utmp_file);
+ __except (NO_ERROR) {}
+ __endtry
+ debug_printf ("Invalid file");
}
EXPORT_ALIAS (utmpname, utmpxname)
@@ -3965,94 +3991,99 @@ getutent ()
extern "C" struct utmp *
getutid (const struct utmp *id)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- if (utmp_fd < 0)
+ __try
{
- internal_setutent (false);
if (utmp_fd < 0)
- return NULL;
- }
-
- utmp *ut = utmp_data;
- while (read (utmp_fd, ut, sizeof *ut) == sizeof *ut)
- {
- switch (id->ut_type)
{
- case RUN_LVL:
- case BOOT_TIME:
- case OLD_TIME:
- case NEW_TIME:
- if (id->ut_type == ut->ut_type)
- return ut;
- break;
- case INIT_PROCESS:
- case LOGIN_PROCESS:
- case USER_PROCESS:
- case DEAD_PROCESS:
- if (strncmp (id->ut_id, ut->ut_id, UT_IDLEN) == 0)
- return ut;
- break;
- default:
- return NULL;
+ internal_setutent (false);
+ if (utmp_fd < 0)
+ __leave;
+ }
+ utmp *ut = utmp_data;
+ while (read (utmp_fd, ut, sizeof *ut) == sizeof *ut)
+ {
+ switch (id->ut_type)
+ {
+ case RUN_LVL:
+ case BOOT_TIME:
+ case OLD_TIME:
+ case NEW_TIME:
+ if (id->ut_type == ut->ut_type)
+ return ut;
+ break;
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+ case DEAD_PROCESS:
+ if (strncmp (id->ut_id, ut->ut_id, UT_IDLEN) == 0)
+ return ut;
+ break;
+ default:
+ break;
+ }
}
}
+ __except (EFAULT) {}
+ __endtry
return NULL;
}
extern "C" struct utmp *
getutline (const struct utmp *line)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- if (utmp_fd < 0)
+ __try
{
- internal_setutent (false);
if (utmp_fd < 0)
- return NULL;
- }
-
- utmp *ut = utmp_data;
- while (read (utmp_fd, ut, sizeof *ut) == sizeof *ut)
- if ((ut->ut_type == LOGIN_PROCESS ||
- ut->ut_type == USER_PROCESS) &&
- !strncmp (ut->ut_line, line->ut_line, sizeof (ut->ut_line)))
- return ut;
+ {
+ internal_setutent (false);
+ if (utmp_fd < 0)
+ __leave;
+ }
+ utmp *ut = utmp_data;
+ while (read (utmp_fd, ut, sizeof *ut) == sizeof *ut)
+ if ((ut->ut_type == LOGIN_PROCESS ||
+ ut->ut_type == USER_PROCESS) &&
+ !strncmp (ut->ut_line, line->ut_line, sizeof (ut->ut_line)))
+ return ut;
+ }
+ __except (EFAULT) {}
+ __endtry
return NULL;
}
extern "C" struct utmp *
pututline (const struct utmp *ut)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- internal_setutent (true);
- if (utmp_fd < 0)
+ __try
{
- debug_printf ("error: utmp_fd %d", utmp_fd);
- return NULL;
- }
- debug_printf ("ut->ut_type %d, ut->ut_pid %d, ut->ut_line '%s', ut->ut_id '%s'\n",
- ut->ut_type, ut->ut_pid, ut->ut_line, ut->ut_id);
- debug_printf ("ut->ut_user '%s', ut->ut_host '%s'\n",
- ut->ut_user, ut->ut_host);
+ internal_setutent (true);
+ if (utmp_fd < 0)
+ {
+ debug_printf ("error: utmp_fd %d", utmp_fd);
+ __leave;
+ }
+ debug_printf ("ut->ut_type %d, ut->ut_pid %d, ut->ut_line '%s', ut->ut_id '%s'\n",
+ ut->ut_type, ut->ut_pid, ut->ut_line, ut->ut_id);
+ debug_printf ("ut->ut_user '%s', ut->ut_host '%s'\n",
+ ut->ut_user, ut->ut_host);
- struct utmp *u;
- if ((u = getutid (ut)))
- {
- lseek (utmp_fd, -sizeof *ut, SEEK_CUR);
- write (utmp_fd, ut, sizeof *ut);
- }
- else
- locked_append (utmp_fd, ut, sizeof *ut);
- /* The documentation says to return a pointer to this which implies that
- this has to be cast from a const. That doesn't seem right but the
- documentation seems pretty clear on this. */
- return (struct utmp *) ut;
+ struct utmp *u;
+ if ((u = getutid (ut)))
+ {
+ lseek (utmp_fd, -sizeof *ut, SEEK_CUR);
+ write (utmp_fd, ut, sizeof *ut);
+ }
+ else
+ locked_append (utmp_fd, ut, sizeof *ut);
+ /* The documentation says to return a pointer to this which implies that
+ this has to be cast from a const. That doesn't seem right but the
+ documentation seems pretty clear on this. */
+ return (struct utmp *) ut;
+ }
+ __except (EFAULT) {}
+ __endtry
+ return NULL;
}
extern "C" void
@@ -4070,7 +4101,7 @@ endutxent ()
extern "C" struct utmpx *
getutxent ()
{
- /* UGH. Not thread safe. */
+ /* POSIX: Not required to be thread safe. */
static struct utmpx utx;
return copy_ut_to_utx (getutent (), &utx);
}
@@ -4078,40 +4109,49 @@ getutxent ()
extern "C" struct utmpx *
getutxid (const struct utmpx *id)
{
- /* UGH. Not thread safe. */
+ /* POSIX: Not required to be thread safe. */
static struct utmpx utx;
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- ((struct utmpx *)id)->ut_time = id->ut_tv.tv_sec;
- return copy_ut_to_utx (getutid ((struct utmp *) id), &utx);
+ __try
+ {
+ ((struct utmpx *)id)->ut_time = id->ut_tv.tv_sec;
+ return copy_ut_to_utx (getutid ((struct utmp *) id), &utx);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return NULL;
}
extern "C" struct utmpx *
getutxline (const struct utmpx *line)
{
- /* UGH. Not thread safe. */
+ /* POSIX: Not required to be thread safe. */
static struct utmpx utx;
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- ((struct utmpx *)line)->ut_time = line->ut_tv.tv_sec;
- return copy_ut_to_utx (getutline ((struct utmp *) line), &utx);
+ __try
+ {
+ ((struct utmpx *)line)->ut_time = line->ut_tv.tv_sec;
+ return copy_ut_to_utx (getutline ((struct utmp *) line), &utx);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return NULL;
}
extern "C" struct utmpx *
pututxline (const struct utmpx *utmpx)
{
- /* UGH. Not thread safe. */
+ /* POSIX: Not required to be thread safe. */
static struct utmpx utx;
- myfault efault;
- if (efault.faulted (EFAULT))
- return NULL;
- ((struct utmpx *)utmpx)->ut_time = utmpx->ut_tv.tv_sec;
- return copy_ut_to_utx (pututline ((struct utmp *) utmpx), &utx);
+ __try
+ {
+ ((struct utmpx *)utmpx)->ut_time = utmpx->ut_tv.tv_sec;
+ return copy_ut_to_utx (pututline ((struct utmp *) utmpx), &utx);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return NULL;
}
extern "C" void
@@ -4475,51 +4515,57 @@ extern "C" int
openat (int dirfd, const char *pathname, int flags, ...)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
- va_list ap;
- mode_t mode;
+ va_list ap;
+ mode_t mode;
- va_start (ap, flags);
- mode = va_arg (ap, mode_t);
- va_end (ap);
- return open (path, flags, mode);
+ va_start (ap, flags);
+ mode = va_arg (ap, mode_t);
+ va_end (ap);
+ return open (path, flags, mode);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
faccessat (int dirfd, const char *pathname, int mode, int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
int res = -1;
- char *path = tp.c_get ();
- if (!gen_full_path_at (path, dirfd, pathname))
+
+ __try
{
- if ((mode & ~(F_OK|R_OK|W_OK|X_OK))
- || (flags & ~(AT_SYMLINK_NOFOLLOW|AT_EACCESS)))
- set_errno (EINVAL);
- else
+ char *path = tp.c_get ();
+ if (!gen_full_path_at (path, dirfd, pathname))
{
- fhandler_base *fh = build_fh_name (path, (flags & AT_SYMLINK_NOFOLLOW
- ? PC_SYM_NOFOLLOW
- : PC_SYM_FOLLOW)
- | PC_KEEP_HANDLE,
- stat_suffixes);
- if (fh)
+ if ((mode & ~(F_OK|R_OK|W_OK|X_OK))
+ || (flags & ~(AT_SYMLINK_NOFOLLOW|AT_EACCESS)))
+ set_errno (EINVAL);
+ else
{
- res = fh->fhaccess (mode, !!(flags & AT_EACCESS));
- delete fh;
+ fhandler_base *fh = build_fh_name (path,
+ (flags & AT_SYMLINK_NOFOLLOW
+ ? PC_SYM_NOFOLLOW
+ : PC_SYM_FOLLOW)
+ | PC_KEEP_HANDLE,
+ stat_suffixes);
+ if (fh)
+ {
+ res = fh->fhaccess (mode, !!(flags & AT_EACCESS));
+ delete fh;
+ }
}
}
}
+ __except (EFAULT) {}
+ __endtry
debug_printf ("returning %d", res);
return res;
}
@@ -4528,40 +4574,46 @@ extern "C" int
fchmodat (int dirfd, const char *pathname, mode_t mode, int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (flags)
+ __try
{
- /* BSD has lchmod, but Linux does not. POSIX says
- AT_SYMLINK_NOFOLLOW is allowed to fail on symlinks; but Linux
- blindly fails even for non-symlinks. */
- set_errno ((flags & ~AT_SYMLINK_NOFOLLOW) ? EINVAL : EOPNOTSUPP);
- return -1;
+ if (flags)
+ {
+ /* BSD has lchmod, but Linux does not. POSIX says
+ AT_SYMLINK_NOFOLLOW is allowed to fail on symlinks; but Linux
+ blindly fails even for non-symlinks. */
+ set_errno ((flags & ~AT_SYMLINK_NOFOLLOW) ? EINVAL : EOPNOTSUPP);
+ __leave;
+ }
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return chmod (path, mode);
}
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return chmod (path, mode);
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
fchownat (int dirfd, const char *pathname, uid_t uid, gid_t gid, int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (flags & ~AT_SYMLINK_NOFOLLOW)
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return chown_worker (path, (flags & AT_SYMLINK_NOFOLLOW)
- ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW, uid, gid);
+ if (flags & ~AT_SYMLINK_NOFOLLOW)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return chown_worker (path, (flags & AT_SYMLINK_NOFOLLOW)
+ ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW, uid, gid);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -4569,21 +4621,24 @@ fstatat (int dirfd, const char *__restrict pathname, struct stat *__restrict st,
int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (flags & ~AT_SYMLINK_NOFOLLOW)
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- path_conv pc (path, ((flags & AT_SYMLINK_NOFOLLOW)
- ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW)
- | PC_POSIX | PC_KEEP_HANDLE, stat_suffixes);
- return stat_worker (pc, st);
+ if (flags & ~AT_SYMLINK_NOFOLLOW)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ path_conv pc (path, ((flags & AT_SYMLINK_NOFOLLOW)
+ ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW)
+ | PC_POSIX | PC_KEEP_HANDLE, stat_suffixes);
+ return stat_worker (pc, st);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern int utimens_worker (path_conv &, const struct timespec *);
@@ -4593,34 +4648,40 @@ utimensat (int dirfd, const char *pathname, const struct timespec *times,
int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (flags & ~AT_SYMLINK_NOFOLLOW)
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- path_conv win32 (path, PC_POSIX | ((flags & AT_SYMLINK_NOFOLLOW)
- ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW),
- stat_suffixes);
- return utimens_worker (win32, times);
+ char *path = tp.c_get ();
+ if (flags & ~AT_SYMLINK_NOFOLLOW)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ path_conv win32 (path, PC_POSIX | ((flags & AT_SYMLINK_NOFOLLOW)
+ ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW),
+ stat_suffixes);
+ return utimens_worker (win32, times);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
futimesat (int dirfd, const char *pathname, const struct timeval *times)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname, true))
- return -1;
- return utimes (path, times);
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname, true))
+ __leave;
+ return utimes (path, times);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -4629,70 +4690,82 @@ linkat (int olddirfd, const char *oldpathname,
int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (flags & ~AT_SYMLINK_FOLLOW)
- {
- set_errno (EINVAL);
- return -1;
- }
- char *oldpath = tp.c_get ();
- if (gen_full_path_at (oldpath, olddirfd, oldpathname))
- return -1;
- char *newpath = tp.c_get ();
- if (gen_full_path_at (newpath, newdirfd, newpathname))
- return -1;
- if (flags & AT_SYMLINK_FOLLOW)
+ __try
{
- path_conv old_name (oldpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
- if (old_name.error)
+ if (flags & ~AT_SYMLINK_FOLLOW)
{
- set_errno (old_name.error);
- return -1;
+ set_errno (EINVAL);
+ __leave;
}
- strcpy (oldpath, old_name.normalized_path);
+ char *oldpath = tp.c_get ();
+ if (gen_full_path_at (oldpath, olddirfd, oldpathname))
+ __leave;
+ char *newpath = tp.c_get ();
+ if (gen_full_path_at (newpath, newdirfd, newpathname))
+ __leave;
+ if (flags & AT_SYMLINK_FOLLOW)
+ {
+ path_conv old_name (oldpath, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
+ if (old_name.error)
+ {
+ set_errno (old_name.error);
+ __leave;
+ }
+ strcpy (oldpath, old_name.normalized_path);
+ }
+ return link (oldpath, newpath);
}
- return link (oldpath, newpath);
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
mkdirat (int dirfd, const char *pathname, mode_t mode)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return mkdir (path, mode);
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return mkdir (path, mode);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
mkfifoat (int dirfd, const char *pathname, mode_t mode)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return mkfifo (path, mode);
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return mkfifo (path, mode);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
mknodat (int dirfd, const char *pathname, mode_t mode, dev_t dev)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return mknod32 (path, mode, dev);
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return mknod32 (path, mode, dev);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" ssize_t
@@ -4700,13 +4773,16 @@ readlinkat (int dirfd, const char *__restrict pathname, char *__restrict buf,
size_t bufsize)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return readlink (path, buf, bufsize);
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return readlink (path, buf, bufsize);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -4714,16 +4790,19 @@ renameat (int olddirfd, const char *oldpathname,
int newdirfd, const char *newpathname)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *oldpath = tp.c_get ();
- if (gen_full_path_at (oldpath, olddirfd, oldpathname))
- return -1;
- char *newpath = tp.c_get ();
- if (gen_full_path_at (newpath, newdirfd, newpathname))
- return -1;
- return rename (oldpath, newpath);
+ __try
+ {
+ char *oldpath = tp.c_get ();
+ if (gen_full_path_at (oldpath, olddirfd, oldpathname))
+ __leave;
+ char *newpath = tp.c_get ();
+ if (gen_full_path_at (newpath, newdirfd, newpathname))
+ __leave;
+ return rename (oldpath, newpath);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
@@ -4732,42 +4811,51 @@ scandirat (int dirfd, const char *pathname, struct dirent ***namelist,
int (*compar) (const struct dirent **, const struct dirent **))
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return scandir (pathname, namelist, select, compar);
+ __try
+ {
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return scandir (pathname, namelist, select, compar);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
symlinkat (const char *oldpath, int newdirfd, const char *newpathname)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- char *newpath = tp.c_get ();
- if (gen_full_path_at (newpath, newdirfd, newpathname))
- return -1;
- return symlink (oldpath, newpath);
+ __try
+ {
+ char *newpath = tp.c_get ();
+ if (gen_full_path_at (newpath, newdirfd, newpathname))
+ __leave;
+ return symlink (oldpath, newpath);
+ }
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
extern "C" int
unlinkat (int dirfd, const char *pathname, int flags)
{
tmp_pathbuf tp;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (flags & ~AT_REMOVEDIR)
+ __try
{
- set_errno (EINVAL);
- return -1;
+ if (flags & ~AT_REMOVEDIR)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ char *path = tp.c_get ();
+ if (gen_full_path_at (path, dirfd, pathname))
+ __leave;
+ return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path);
}
- char *path = tp.c_get ();
- if (gen_full_path_at (path, dirfd, pathname))
- return -1;
- return (flags & AT_REMOVEDIR) ? rmdir (path) : unlink (path);
+ __except (EFAULT) {}
+ __endtry
+ return -1;
}
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index dc4faac7c..2ab47b380 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -1,7 +1,7 @@
/* thread.cc: Locking and threading module functions
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.
@@ -122,28 +122,29 @@ __cygwin_lock_unlock (_LOCK_T *lock)
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
-#endif
verifyable_object_isvalid (void const *objectptr, thread_magic_t magic, void *static_ptr1,
void *static_ptr2, void *static_ptr3)
{
- myfault efault;
- if (efault.faulted (objectptr))
- return INVALID_OBJECT;
+ verifyable_object_state state = INVALID_OBJECT;
- verifyable_object **object = (verifyable_object **) objectptr;
+ __try
+ {
+ if (!objectptr || !(*(const char **) objectptr))
+ __leave;
- if ((static_ptr1 && *object == static_ptr1) ||
- (static_ptr2 && *object == static_ptr2) ||
- (static_ptr3 && *object == static_ptr3))
- return VALID_STATIC_OBJECT;
- if ((*object)->magic != magic)
- return INVALID_OBJECT;
- return VALID_OBJECT;
+ verifyable_object **object = (verifyable_object **) objectptr;
+
+ if ((static_ptr1 && *object == static_ptr1) ||
+ (static_ptr2 && *object == static_ptr2) ||
+ (static_ptr3 && *object == static_ptr3))
+ state = VALID_STATIC_OBJECT;
+ else if ((*object)->magic == magic)
+ state = VALID_OBJECT;
+ }
+ __except (NO_ERROR) {}
+ __endtry
+ return state;
}
/* static members */
@@ -2684,18 +2685,20 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
return EAGAIN;
}
- myfault efault;
- if (efault.faulted ())
+ int ret = 0;
+
+ __try
+ {
+ *cond = new_cond;
+ }
+ __except (NO_ERROR)
{
delete new_cond;
- cond_initialization_lock.unlock ();
- return EINVAL;
+ ret = EINVAL;
}
-
- *cond = new_cond;
+ __endtry
cond_initialization_lock.unlock ();
-
- return 0;
+ return ret;
}
extern "C" int
@@ -2747,45 +2750,47 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec tp;
LARGE_INTEGER timeout;
- myfault efault;
- if (efault.faulted ())
- return EINVAL;
-
pthread_testcancel ();
- int err = __pthread_cond_wait_init (cond, mutex);
- if (err)
- return err;
+ __try
+ {
+ int err = __pthread_cond_wait_init (cond, mutex);
+ 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;
+ /* According to SUSv3, the abstime value must be checked for validity. */
+ if (abstime->tv_sec < 0
+ || abstime->tv_nsec < 0
+ || abstime->tv_nsec > 999999999)
+ __leave;
- clock_gettime ((*cond)->clock_id, &tp);
+ 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;
+ /* 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;
+ 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;
+ 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
@@ -2910,18 +2915,20 @@ pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr
return EAGAIN;
}
- myfault efault;
- if (efault.faulted ())
+ int ret = 0;
+
+ __try
+ {
+ *rwlock = new_rwlock;
+ }
+ __except (NO_ERROR)
{
delete new_rwlock;
- rwlock_initialization_lock.unlock ();
- return EINVAL;
+ ret = EINVAL;
}
-
- *rwlock = new_rwlock;
+ __endtry
rwlock_initialization_lock.unlock ();
-
- return 0;
+ return ret;
}
extern "C" int
@@ -3133,15 +3140,17 @@ pthread_mutex::init (pthread_mutex_t *mutex,
new_mutex->type = PTHREAD_MUTEX_ERRORCHECK;
}
- myfault efault;
- if (efault.faulted ())
+ __try
+ {
+ *mutex = new_mutex;
+ }
+ __except (NO_ERROR)
{
delete new_mutex;
mutex_initialization_lock.unlock ();
return EINVAL;
}
-
- *mutex = new_mutex;
+ __endtry
}
mutex_initialization_lock.unlock ();
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;
}
- myfault efault;
- if (efault.faulted ())
+ __try
+ {
+ *spinlock = new_spinlock;
+ }
+ __except (NO_ERROR)
{
delete new_spinlock;
return EINVAL;
}
-
- *spinlock = new_spinlock;
+ __endtry
pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared);
-
return 0;
}
@@ -3502,35 +3512,38 @@ semaphore::_timedwait (const struct timespec *abstime)
{
LARGE_INTEGER timeout;
- myfault efault;
- if (efault.faulted ())
+ __try
{
- /* According to SUSv3, abstime need not be checked for validity,
- if the semaphore can be locked immediately. */
- if (!_trywait ())
- return 0;
- set_errno (EINVAL);
- return -1;
- }
+ timeout.QuadPart = abstime->tv_sec * NSPERSEC
+ + (abstime->tv_nsec + 99) / 100 + FACTOR;
- 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))
+ 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)
{
- 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;
+ /* According to SUSv3, abstime need not be checked for validity,
+ if the semaphore can be locked immediately. */
+ if (_trywait ())
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
}
+ __endtry
return 0;
}
@@ -3761,36 +3774,38 @@ semaphore::post (sem_t *sem)
int
semaphore::getvalue (sem_t *sem, int *sval)
{
- myfault efault;
- if (efault.faulted () || !is_good_object (sem))
+ __try
{
- set_errno (EINVAL);
- return -1;
+ if (is_good_object (sem))
+ return (*sem)->_getvalue (sval);
}
-
- return (*sem)->_getvalue (sval);
+ __except (NO_ERROR) {}
+ __endtry
+ set_errno (EINVAL);
+ return -1;
}
int
semaphore::getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
LUID *sluid, unsigned int *sval)
{
- myfault efault;
- if (efault.faulted () || !is_good_object (sem))
- {
- set_errno (EINVAL);
- return -1;
- }
- if ((*sfd = (*sem)->fd) < 0)
- {
- set_errno (EINVAL);
- 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);
+ __try
+ {
+ if (!is_good_object (sem))
+ __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);
+ }
+ __except (NO_ERROR) {}
+ __endtry
+ set_errno (EINVAL);
+ return -1;
}
/* pthread_null */
diff --git a/winsup/cygwin/timer.cc b/winsup/cygwin/timer.cc
index b1c6e27aa..bfa1495f6 100644
--- a/winsup/cygwin/timer.cc
+++ b/winsup/cygwin/timer.cc
@@ -1,6 +1,6 @@
/* 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.
@@ -219,45 +219,49 @@ it_bad (const timespec& t)
int
timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue)
{
- if (!value)
+ int ret = -1;
+
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
+ if (!value)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
- myfault efault;
- if (efault.faulted (EFAULT)
- || it_bad (value->it_value)
- || it_bad (value->it_interval))
- return -1;
+ if (it_bad (value->it_value) || it_bad (value->it_interval))
+ __leave;
- long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs ();
+ long long now = in_flags & TIMER_ABSTIME ? 0 : gtod.usecs ();
- lock_timer_tracker here;
- cancel ();
+ lock_timer_tracker here;
+ cancel ();
- if (ovalue)
- gettime (ovalue);
+ if (ovalue)
+ gettime (ovalue);
- if (!value->it_value.tv_sec && !value->it_value.tv_nsec)
- 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
- ResetEvent (hcancel);
- if (!syncthread)
- syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
+ if (!value->it_value.tv_sec && !value->it_value.tv_nsec)
+ interval_us = sleepto_us = 0;
else
- ResetEvent (syncthread);
- new cygthread (timer_thread, this, "itimer", syncthread);
+ {
+ 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
+ ResetEvent (hcancel);
+ if (!syncthread)
+ syncthread = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
+ else
+ ResetEvent (syncthread);
+ new cygthread (timer_thread, this, "itimer", syncthread);
+ }
+ ret = 0;
}
-
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return ret;
}
void
@@ -280,43 +284,51 @@ timer_tracker::gettime (itimerspec *ovalue)
extern "C" int
timer_gettime (timer_t timerid, struct itimerspec *ovalue)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ int ret = -1;
- timer_tracker *tt = (timer_tracker *) timerid;
- if (tt->magic != TT_MAGIC)
+ __try
{
- set_errno (EINVAL);
- return -1;
- }
+ timer_tracker *tt = (timer_tracker *) timerid;
+ if (tt->magic != TT_MAGIC)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
- tt->gettime (ovalue);
- return 0;
+ tt->gettime (ovalue);
+ ret = 0;
+ }
+ __except (EFAULT) {}
+ __endtry
+ return ret;
}
extern "C" int
timer_create (clockid_t clock_id, struct sigevent *__restrict evp,
timer_t *__restrict timerid)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ int ret = -1;
- if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id))
+ __try
{
- set_errno (ENOTSUP);
- return -1;
- }
+ if (CLOCKID_IS_PROCESS (clock_id) || CLOCKID_IS_THREAD (clock_id))
+ {
+ set_errno (ENOTSUP);
+ return -1;
+ }
- if (clock_id != CLOCK_REALTIME)
- {
- set_errno (EINVAL);
- return -1;
- }
+ if (clock_id != CLOCK_REALTIME)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
- *timerid = (timer_t) new timer_tracker (clock_id, evp);
- return 0;
+ *timerid = (timer_t) new timer_tracker (clock_id, evp);
+ ret = 0;
+ }
+ __except (EFAULT) {}
+ __endtry
+ return ret;
}
extern "C" int
@@ -324,42 +336,52 @@ timer_settime (timer_t timerid, int flags,
const struct itimerspec *__restrict value,
struct itimerspec *__restrict ovalue)
{
- timer_tracker *tt = (timer_tracker *) timerid;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (tt->magic != TT_MAGIC)
+ int ret = -1;
+
+ __try
{
- set_errno (EINVAL);
- return -1;
+ timer_tracker *tt = (timer_tracker *) timerid;
+ if (tt->magic != TT_MAGIC)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ ret = tt->settime (flags, value, ovalue);
}
-
- return tt->settime (flags, value, ovalue);
+ __except (EFAULT) {}
+ __endtry
+ return ret;
}
extern "C" int
timer_delete (timer_t timerid)
{
- timer_tracker *in_tt = (timer_tracker *) timerid;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
- if (in_tt->magic != TT_MAGIC)
+ int ret = -1;
+
+ __try
{
+ timer_tracker *in_tt = (timer_tracker *) timerid;
+ if (in_tt->magic != TT_MAGIC)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+
+ 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);
- return -1;
+ ret = 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;
- return 0;
- }
- set_errno (EINVAL);
- return 0;
+ __except (EFAULT) {}
+ __endtry
+ return ret;
}
void
@@ -412,18 +434,13 @@ setitimer (int which, const struct itimerval *__restrict value,
extern "C" int
getitimer (int which, struct itimerval *ovalue)
{
- int ret;
+ int ret = -1;
+
if (which != ITIMER_REAL)
- {
- set_errno (EINVAL);
- ret = -1;
- }
+ set_errno (EINVAL);
else
{
- myfault efault;
- if (efault.faulted (EFAULT))
- ret = -1;
- else
+ __try
{
struct itimerspec 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;
}
}
+ __except (EFAULT) {}
+ __endtry
}
syscall_printf ("%R = getitimer()", ret);
return ret;
diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc
index 55157d389..cbff13c77 100644
--- a/winsup/cygwin/times.cc
+++ b/winsup/cygwin/times.cc
@@ -1,7 +1,7 @@
/* times.cc
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.
@@ -59,35 +59,39 @@ __to_clock_t (PLARGE_INTEGER src, int flag)
extern "C" clock_t
times (struct tms *buf)
{
- myfault efault;
- if (efault.faulted (EFAULT))
- return ((clock_t) -1);
-
static SYSTEM_TIMEOFDAY_INFORMATION stodi;
KERNEL_USER_TIMES kut;
LARGE_INTEGER ticks;
+ clock_t tc = (clock_t) -1;
- /* Fetch boot time if we haven't already. */
- if (!stodi.BootTime.QuadPart)
- NtQuerySystemInformation (SystemTimeOfDayInformation,
- &stodi, sizeof stodi, NULL);
-
- NtQueryInformationProcess (NtCurrentProcess (), ProcessTimes,
- &kut, sizeof kut, NULL);
- get_system_time (&ticks);
-
- /* uptime */
- ticks.QuadPart -= stodi.BootTime.QuadPart;
- /* ticks is in in 100ns, convert to clock ticks. */
- clock_t 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);
+ __try
+ {
+ /* Fetch boot time if we haven't already. */
+ if (!stodi.BootTime.QuadPart)
+ NtQuerySystemInformation (SystemTimeOfDayInformation,
+ &stodi, sizeof stodi, NULL);
+ NtQueryInformationProcess (NtCurrentProcess (), ProcessTimes,
+ &kut, sizeof kut, NULL);
+ get_system_time (&ticks);
+
+ /* uptime */
+ ticks.QuadPart -= stodi.BootTime.QuadPart;
+ /* ticks is in in 100ns, convert to clock ticks. */
+ 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);
+ }
+ __except (EFAULT)
+ {
+ tc = (clock_t) -1;
+ }
+ __endtry
syscall_printf ("%D = times(%p)", tc, buf);
return tc;
}
@@ -100,34 +104,37 @@ settimeofday (const struct timeval *tv, const struct timezone *tz)
{
SYSTEMTIME st;
struct tm *ptm;
- int res;
+ int res = -1;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
+ __try
+ {
+ if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
- if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
+ 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)
{
- set_errno (EINVAL);
- return -1;
+ res = -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);
-
+ __endtry
syscall_printf ("%R = settimeofday(%p, %p)", res, tv, tz);
return res;
}
diff --git a/winsup/cygwin/tls_pbuf.cc b/winsup/cygwin/tls_pbuf.cc
index c48ca5853..e4f522344 100644
--- a/winsup/cygwin/tls_pbuf.cc
+++ b/winsup/cygwin/tls_pbuf.cc
@@ -8,17 +8,16 @@ details. */
#include <winsup.h>
#include <malloc.h>
-#include "cygtls.h"
#include "tls_pbuf.h"
-#define tls_pbuf _my_tls.locals.pathbufs
+#define tls_pbuf _my_tls.pathbufs
void
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]);
- 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]);
}
diff --git a/winsup/cygwin/tls_pbuf.h b/winsup/cygwin/tls_pbuf.h
index e98fd60b8..3a94017a1 100644
--- a/winsup/cygwin/tls_pbuf.h
+++ b/winsup/cygwin/tls_pbuf.h
@@ -10,20 +10,20 @@ details. */
class tmp_pathbuf
{
- unsigned c_buf_old;
- unsigned w_buf_old;
+ uint32_t c_buf_old;
+ uint32_t w_buf_old;
public:
tmp_pathbuf () __attribute__ ((always_inline))
- : c_buf_old (_my_tls.locals.pathbufs.c_cnt),
- w_buf_old (_my_tls.locals.pathbufs.w_cnt)
+ : c_buf_old (_my_tls.pathbufs.c_cnt),
+ w_buf_old (_my_tls.pathbufs.w_cnt)
{}
~tmp_pathbuf () __attribute__ ((always_inline))
{
- _my_tls.locals.pathbufs.c_cnt = c_buf_old;
- _my_tls.locals.pathbufs.w_cnt = w_buf_old;
+ _my_tls.pathbufs.c_cnt = c_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
&& w_need + w_buf_old < TP_NUM_W_BUFS;
diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h
index 572dfb7b7..308da2d78 100644
--- a/winsup/cygwin/tlsoffsets.h
+++ b/winsup/cygwin/tlsoffsets.h
@@ -3,44 +3,46 @@
//; $tls::start_offset = -12700;
//; $tls::locals = -12700;
//; $tls::plocals = 0;
-//; $tls::local_clib = -10980;
-//; $tls::plocal_clib = 1720;
-//; $tls::__dontuse = -10980;
-//; $tls::p__dontuse = 1720;
-//; $tls::func = -9892;
-//; $tls::pfunc = 2808;
-//; $tls::saved_errno = -9888;
-//; $tls::psaved_errno = 2812;
-//; $tls::sa_flags = -9884;
-//; $tls::psa_flags = 2816;
-//; $tls::oldmask = -9880;
-//; $tls::poldmask = 2820;
-//; $tls::deltamask = -9876;
-//; $tls::pdeltamask = 2824;
-//; $tls::errno_addr = -9872;
-//; $tls::perrno_addr = 2828;
-//; $tls::sigmask = -9868;
-//; $tls::psigmask = 2832;
-//; $tls::sigwait_mask = -9864;
-//; $tls::psigwait_mask = 2836;
-//; $tls::sigwait_info = -9860;
-//; $tls::psigwait_info = 2840;
-//; $tls::signal_arrived = -9856;
-//; $tls::psignal_arrived = 2844;
-//; $tls::will_wait_for_signal = -9852;
-//; $tls::pwill_wait_for_signal = 2848;
-//; $tls::thread_context = -9848;
-//; $tls::pthread_context = 2852;
-//; $tls::thread_id = -9636;
-//; $tls::pthread_id = 3064;
-//; $tls::infodata = -9632;
-//; $tls::pinfodata = 3068;
-//; $tls::tid = -9484;
-//; $tls::ptid = 3216;
-//; $tls::_ctinfo = -9480;
-//; $tls::p_ctinfo = 3220;
-//; $tls::andreas = -9476;
-//; $tls::pandreas = 3224;
+//; $tls::local_clib = -11388;
+//; $tls::plocal_clib = 1312;
+//; $tls::__dontuse = -11388;
+//; $tls::p__dontuse = 1312;
+//; $tls::func = -10300;
+//; $tls::pfunc = 2400;
+//; $tls::saved_errno = -10296;
+//; $tls::psaved_errno = 2404;
+//; $tls::sa_flags = -10292;
+//; $tls::psa_flags = 2408;
+//; $tls::oldmask = -10288;
+//; $tls::poldmask = 2412;
+//; $tls::deltamask = -10284;
+//; $tls::pdeltamask = 2416;
+//; $tls::errno_addr = -10280;
+//; $tls::perrno_addr = 2420;
+//; $tls::sigmask = -10276;
+//; $tls::psigmask = 2424;
+//; $tls::sigwait_mask = -10272;
+//; $tls::psigwait_mask = 2428;
+//; $tls::sigwait_info = -10268;
+//; $tls::psigwait_info = 2432;
+//; $tls::signal_arrived = -10264;
+//; $tls::psignal_arrived = 2436;
+//; $tls::will_wait_for_signal = -10260;
+//; $tls::pwill_wait_for_signal = 2440;
+//; $tls::thread_context = -10256;
+//; $tls::pthread_context = 2444;
+//; $tls::thread_id = -10044;
+//; $tls::pthread_id = 2656;
+//; $tls::infodata = -10040;
+//; $tls::pinfodata = 2660;
+//; $tls::tid = -9892;
+//; $tls::ptid = 2808;
+//; $tls::_ctinfo = -9888;
+//; $tls::p_ctinfo = 2812;
+//; $tls::andreas = -9884;
+//; $tls::pandreas = 2816;
+//; $tls::pathbufs = -9880;
+//; $tls::ppathbufs = 2820;
//; $tls::wq = -9472;
//; $tls::pwq = 3228;
//; $tls::sig = -9444;
@@ -61,44 +63,46 @@
#define tls_locals (-12700)
#define tls_plocals (0)
-#define tls_local_clib (-10980)
-#define tls_plocal_clib (1720)
-#define tls___dontuse (-10980)
-#define tls_p__dontuse (1720)
-#define tls_func (-9892)
-#define tls_pfunc (2808)
-#define tls_saved_errno (-9888)
-#define tls_psaved_errno (2812)
-#define tls_sa_flags (-9884)
-#define tls_psa_flags (2816)
-#define tls_oldmask (-9880)
-#define tls_poldmask (2820)
-#define tls_deltamask (-9876)
-#define tls_pdeltamask (2824)
-#define tls_errno_addr (-9872)
-#define tls_perrno_addr (2828)
-#define tls_sigmask (-9868)
-#define tls_psigmask (2832)
-#define tls_sigwait_mask (-9864)
-#define tls_psigwait_mask (2836)
-#define tls_sigwait_info (-9860)
-#define tls_psigwait_info (2840)
-#define tls_signal_arrived (-9856)
-#define tls_psignal_arrived (2844)
-#define tls_will_wait_for_signal (-9852)
-#define tls_pwill_wait_for_signal (2848)
-#define tls_thread_context (-9848)
-#define tls_pthread_context (2852)
-#define tls_thread_id (-9636)
-#define tls_pthread_id (3064)
-#define tls_infodata (-9632)
-#define tls_pinfodata (3068)
-#define tls_tid (-9484)
-#define tls_ptid (3216)
-#define tls__ctinfo (-9480)
-#define tls_p_ctinfo (3220)
-#define tls_andreas (-9476)
-#define tls_pandreas (3224)
+#define tls_local_clib (-11388)
+#define tls_plocal_clib (1312)
+#define tls___dontuse (-11388)
+#define tls_p__dontuse (1312)
+#define tls_func (-10300)
+#define tls_pfunc (2400)
+#define tls_saved_errno (-10296)
+#define tls_psaved_errno (2404)
+#define tls_sa_flags (-10292)
+#define tls_psa_flags (2408)
+#define tls_oldmask (-10288)
+#define tls_poldmask (2412)
+#define tls_deltamask (-10284)
+#define tls_pdeltamask (2416)
+#define tls_errno_addr (-10280)
+#define tls_perrno_addr (2420)
+#define tls_sigmask (-10276)
+#define tls_psigmask (2424)
+#define tls_sigwait_mask (-10272)
+#define tls_psigwait_mask (2428)
+#define tls_sigwait_info (-10268)
+#define tls_psigwait_info (2432)
+#define tls_signal_arrived (-10264)
+#define tls_psignal_arrived (2436)
+#define tls_will_wait_for_signal (-10260)
+#define tls_pwill_wait_for_signal (2440)
+#define tls_thread_context (-10256)
+#define tls_pthread_context (2444)
+#define tls_thread_id (-10044)
+#define tls_pthread_id (2656)
+#define tls_infodata (-10040)
+#define tls_pinfodata (2660)
+#define tls_tid (-9892)
+#define tls_ptid (2808)
+#define tls__ctinfo (-9888)
+#define tls_p_ctinfo (2812)
+#define tls_andreas (-9884)
+#define tls_pandreas (2816)
+#define tls_pathbufs (-9880)
+#define tls_ppathbufs (2820)
#define tls_wq (-9472)
#define tls_pwq (3228)
#define tls_sig (-9444)
diff --git a/winsup/cygwin/tlsoffsets64.h b/winsup/cygwin/tlsoffsets64.h
index 991280663..f91a0bf3d 100644
--- a/winsup/cygwin/tlsoffsets64.h
+++ b/winsup/cygwin/tlsoffsets64.h
@@ -3,44 +3,46 @@
//; $tls::start_offset = -12800;
//; $tls::locals = -12800;
//; $tls::plocals = 0;
-//; $tls::local_clib = -10624;
-//; $tls::plocal_clib = 2176;
-//; $tls::__dontuse = -10624;
-//; $tls::p__dontuse = 2176;
-//; $tls::func = -8736;
-//; $tls::pfunc = 4064;
-//; $tls::saved_errno = -8728;
-//; $tls::psaved_errno = 4072;
-//; $tls::sa_flags = -8724;
-//; $tls::psa_flags = 4076;
-//; $tls::oldmask = -8720;
-//; $tls::poldmask = 4080;
-//; $tls::deltamask = -8712;
-//; $tls::pdeltamask = 4088;
-//; $tls::errno_addr = -8704;
-//; $tls::perrno_addr = 4096;
-//; $tls::sigmask = -8696;
-//; $tls::psigmask = 4104;
-//; $tls::sigwait_mask = -8688;
-//; $tls::psigwait_mask = 4112;
-//; $tls::sigwait_info = -8680;
-//; $tls::psigwait_info = 4120;
-//; $tls::signal_arrived = -8672;
-//; $tls::psignal_arrived = 4128;
-//; $tls::will_wait_for_signal = -8664;
-//; $tls::pwill_wait_for_signal = 4136;
-//; $tls::thread_context = -8656;
-//; $tls::pthread_context = 4144;
-//; $tls::thread_id = -7824;
-//; $tls::pthread_id = 4976;
-//; $tls::infodata = -7820;
-//; $tls::pinfodata = 4980;
-//; $tls::tid = -7672;
-//; $tls::ptid = 5128;
-//; $tls::_ctinfo = -7664;
-//; $tls::p_ctinfo = 5136;
-//; $tls::andreas = -7656;
-//; $tls::pandreas = 5144;
+//; $tls::local_clib = -11432;
+//; $tls::plocal_clib = 1368;
+//; $tls::__dontuse = -11432;
+//; $tls::p__dontuse = 1368;
+//; $tls::func = -9544;
+//; $tls::pfunc = 3256;
+//; $tls::saved_errno = -9536;
+//; $tls::psaved_errno = 3264;
+//; $tls::sa_flags = -9532;
+//; $tls::psa_flags = 3268;
+//; $tls::oldmask = -9528;
+//; $tls::poldmask = 3272;
+//; $tls::deltamask = -9520;
+//; $tls::pdeltamask = 3280;
+//; $tls::errno_addr = -9512;
+//; $tls::perrno_addr = 3288;
+//; $tls::sigmask = -9504;
+//; $tls::psigmask = 3296;
+//; $tls::sigwait_mask = -9496;
+//; $tls::psigwait_mask = 3304;
+//; $tls::sigwait_info = -9488;
+//; $tls::psigwait_info = 3312;
+//; $tls::signal_arrived = -9480;
+//; $tls::psignal_arrived = 3320;
+//; $tls::will_wait_for_signal = -9472;
+//; $tls::pwill_wait_for_signal = 3328;
+//; $tls::thread_context = -9464;
+//; $tls::pthread_context = 3336;
+//; $tls::thread_id = -8632;
+//; $tls::pthread_id = 4168;
+//; $tls::infodata = -8628;
+//; $tls::pinfodata = 4172;
+//; $tls::tid = -8480;
+//; $tls::ptid = 4320;
+//; $tls::_ctinfo = -8472;
+//; $tls::p_ctinfo = 4328;
+//; $tls::andreas = -8464;
+//; $tls::pandreas = 4336;
+//; $tls::pathbufs = -8456;
+//; $tls::ppathbufs = 4344;
//; $tls::wq = -7648;
//; $tls::pwq = 5152;
//; $tls::sig = -7600;
@@ -61,44 +63,46 @@
#define tls_locals (-12800)
#define tls_plocals (0)
-#define tls_local_clib (-10624)
-#define tls_plocal_clib (2176)
-#define tls___dontuse (-10624)
-#define tls_p__dontuse (2176)
-#define tls_func (-8736)
-#define tls_pfunc (4064)
-#define tls_saved_errno (-8728)
-#define tls_psaved_errno (4072)
-#define tls_sa_flags (-8724)
-#define tls_psa_flags (4076)
-#define tls_oldmask (-8720)
-#define tls_poldmask (4080)
-#define tls_deltamask (-8712)
-#define tls_pdeltamask (4088)
-#define tls_errno_addr (-8704)
-#define tls_perrno_addr (4096)
-#define tls_sigmask (-8696)
-#define tls_psigmask (4104)
-#define tls_sigwait_mask (-8688)
-#define tls_psigwait_mask (4112)
-#define tls_sigwait_info (-8680)
-#define tls_psigwait_info (4120)
-#define tls_signal_arrived (-8672)
-#define tls_psignal_arrived (4128)
-#define tls_will_wait_for_signal (-8664)
-#define tls_pwill_wait_for_signal (4136)
-#define tls_thread_context (-8656)
-#define tls_pthread_context (4144)
-#define tls_thread_id (-7824)
-#define tls_pthread_id (4976)
-#define tls_infodata (-7820)
-#define tls_pinfodata (4980)
-#define tls_tid (-7672)
-#define tls_ptid (5128)
-#define tls__ctinfo (-7664)
-#define tls_p_ctinfo (5136)
-#define tls_andreas (-7656)
-#define tls_pandreas (5144)
+#define tls_local_clib (-11432)
+#define tls_plocal_clib (1368)
+#define tls___dontuse (-11432)
+#define tls_p__dontuse (1368)
+#define tls_func (-9544)
+#define tls_pfunc (3256)
+#define tls_saved_errno (-9536)
+#define tls_psaved_errno (3264)
+#define tls_sa_flags (-9532)
+#define tls_psa_flags (3268)
+#define tls_oldmask (-9528)
+#define tls_poldmask (3272)
+#define tls_deltamask (-9520)
+#define tls_pdeltamask (3280)
+#define tls_errno_addr (-9512)
+#define tls_perrno_addr (3288)
+#define tls_sigmask (-9504)
+#define tls_psigmask (3296)
+#define tls_sigwait_mask (-9496)
+#define tls_psigwait_mask (3304)
+#define tls_sigwait_info (-9488)
+#define tls_psigwait_info (3312)
+#define tls_signal_arrived (-9480)
+#define tls_psignal_arrived (3320)
+#define tls_will_wait_for_signal (-9472)
+#define tls_pwill_wait_for_signal (3328)
+#define tls_thread_context (-9464)
+#define tls_pthread_context (3336)
+#define tls_thread_id (-8632)
+#define tls_pthread_id (4168)
+#define tls_infodata (-8628)
+#define tls_pinfodata (4172)
+#define tls_tid (-8480)
+#define tls_ptid (4320)
+#define tls__ctinfo (-8472)
+#define tls_p_ctinfo (4328)
+#define tls_andreas (-8464)
+#define tls_pandreas (4336)
+#define tls_pathbufs (-8456)
+#define tls_ppathbufs (4344)
#define tls_wq (-7648)
#define tls_pwq (5152)
#define tls_sig (-7600)
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index ca764269a..732dea836 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -217,10 +217,15 @@ getlogin_r (char *name, size_t namesize)
size_t len = strlen (login) + 1;
if (len > namesize)
return ERANGE;
- myfault efault;
- if (efault.faulted ())
- return EFAULT;
- strncpy (name, login, len);
+ __try
+ {
+ strncpy (name, login, len);
+ }
+ __except (NO_ERROR)
+ {
+ return EFAULT;
+ }
+ __endtry
return 0;
}
diff --git a/winsup/cygwin/uname.cc b/winsup/cygwin/uname.cc
index c571850b4..b586e6374 100644
--- a/winsup/cygwin/uname.cc
+++ b/winsup/cygwin/uname.cc
@@ -1,7 +1,7 @@
/* uname.cc
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
Rewritten by Geoffrey Noer of Cygnus Solutions, noer@cygnus.com
@@ -22,74 +22,77 @@ uname (struct utsname *name)
{
SYSTEM_INFO sysinfo;
- myfault efault;
- if (efault.faulted (EFAULT))
- return -1;
-
- char *snp = strstr (cygwin_version.dll_build_date, "SNP");
+ __try
+ {
+ char *snp = strstr (cygwin_version.dll_build_date, "SNP");
- memset (name, 0, sizeof (*name));
- __small_sprintf (name->sysname, "CYGWIN_%s", wincap.osname ());
+ 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);
+ /* 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);
+ GetSystemInfo (&sysinfo);
- /* Computer name */
- cygwin_gethostname (name->nodename, sizeof (name->nodename) - 1);
+ /* 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 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';
+ /* 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)
+ /* 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)
{
- 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;
+ return -1;
}
-
+ __endtry
return 0;
}