summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/ldsodefs.h1
-rw-r--r--sysdeps/generic/not-cancel.h28
-rw-r--r--sysdeps/generic/symbol-hacks.h3
-rw-r--r--sysdeps/i386/i486/bits/atomic.h107
-rw-r--r--sysdeps/mach/configure11
-rw-r--r--sysdeps/mach/configure.ac11
-rw-r--r--sysdeps/mach/hurd/Makefile8
-rw-r--r--sysdeps/mach/hurd/bind.c8
-rw-r--r--sysdeps/mach/hurd/bits/fcntl.h15
-rw-r--r--sysdeps/mach/hurd/bits/ioctls.h23
-rw-r--r--sysdeps/mach/hurd/bits/libc-lock.h12
-rw-r--r--sysdeps/mach/hurd/bits/posix_opt.h46
-rw-r--r--sysdeps/mach/hurd/bits/sigaction.h81
-rw-r--r--sysdeps/mach/hurd/bits/stat.h33
-rw-r--r--sysdeps/mach/hurd/brk.c6
-rw-r--r--sysdeps/mach/hurd/chflags.c2
-rw-r--r--sysdeps/mach/hurd/configure9
-rw-r--r--sysdeps/mach/hurd/configure.ac9
-rw-r--r--sysdeps/mach/hurd/connect.c4
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c30
-rw-r--r--sysdeps/mach/hurd/f_setlk.c68
-rw-r--r--sysdeps/mach/hurd/f_setlk.h23
-rw-r--r--sysdeps/mach/hurd/fchflags.c2
-rw-r--r--sysdeps/mach/hurd/fcntl.c57
-rw-r--r--sysdeps/mach/hurd/fork.c32
-rw-r--r--sysdeps/mach/hurd/ftok.c43
-rw-r--r--sysdeps/mach/hurd/futimens.c50
-rw-r--r--sysdeps/mach/hurd/gai_misc.h44
-rw-r--r--sysdeps/mach/hurd/getcwd.c12
-rw-r--r--sysdeps/mach/hurd/hp-timing.h42
-rw-r--r--sysdeps/mach/hurd/i386/bits/sigcontext.h4
-rw-r--r--sysdeps/mach/hurd/i386/exc2signal.c123
-rw-r--r--sysdeps/mach/hurd/i386/getcontext.S2
-rw-r--r--sysdeps/mach/hurd/i386/init-first.c12
-rw-r--r--sysdeps/mach/hurd/i386/makecontext-helper.c2
-rw-r--r--sysdeps/mach/hurd/i386/makecontext.S2
-rw-r--r--sysdeps/mach/hurd/i386/setcontext.S2
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c10
-rw-r--r--sysdeps/mach/hurd/i386/swapcontext.S2
-rw-r--r--sysdeps/mach/hurd/i386/tls.h45
-rw-r--r--sysdeps/mach/hurd/i386/tlsdesc.sym19
-rw-r--r--sysdeps/mach/hurd/i386/trampoline.c119
-rw-r--r--sysdeps/mach/hurd/ifaddrs.c306
-rw-r--r--sysdeps/mach/hurd/jmp-unwind.c3
-rw-r--r--sysdeps/mach/hurd/kernel-features.h2
-rw-r--r--sysdeps/mach/hurd/kill.c2
-rw-r--r--sysdeps/mach/hurd/mlock.c13
-rw-r--r--sysdeps/mach/hurd/mmap.c11
-rw-r--r--sysdeps/mach/hurd/mmap64.c47
-rw-r--r--sysdeps/mach/hurd/munlock.c12
-rw-r--r--sysdeps/mach/hurd/pipe.c21
-rw-r--r--sysdeps/mach/hurd/pipe2.c60
-rw-r--r--sysdeps/mach/hurd/profil.c2
-rw-r--r--sysdeps/mach/hurd/ptsname.c18
-rw-r--r--sysdeps/mach/hurd/reboot.c5
-rw-r--r--sysdeps/mach/hurd/recvmsg.c228
-rw-r--r--sysdeps/mach/hurd/sendmsg.c111
-rw-r--r--sysdeps/mach/hurd/sendto.c4
-rw-r--r--sysdeps/mach/hurd/setitimer.c24
-rw-r--r--sysdeps/mach/hurd/shmat.c81
-rw-r--r--sysdeps/mach/hurd/shmctl.c132
-rw-r--r--sysdeps/mach/hurd/shmdt.c51
-rw-r--r--sysdeps/mach/hurd/shmget.c242
-rw-r--r--sysdeps/mach/hurd/sigaction.c16
-rw-r--r--sysdeps/mach/hurd/sigpending.c6
-rw-r--r--sysdeps/mach/hurd/sigprocmask.c8
-rw-r--r--sysdeps/mach/hurd/sigsuspend.c15
-rw-r--r--sysdeps/mach/hurd/sigwait.c21
-rw-r--r--sysdeps/mach/hurd/socket.c15
-rw-r--r--sysdeps/mach/hurd/socketpair.c25
-rw-r--r--sysdeps/mach/hurd/spawni.c26
-rw-r--r--sysdeps/mach/hurd/sysdep-cancel.h9
-rw-r--r--sysdeps/mach/hurd/tls.h13
-rw-r--r--sysdeps/mach/pagecopy.h5
-rw-r--r--sysdeps/mach/thread_state.h2
-rw-r--r--sysdeps/pthread/aio_misc.c5
-rw-r--r--sysdeps/unix/bsd/unlockpt.c2
-rw-r--r--sysdeps/unix/clock_settime.c3
78 files changed, 2339 insertions, 369 deletions
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index ffeb093887..694e6e7360 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -409,6 +409,7 @@ struct rtld_global
size_t count;
void *list[50];
} *_dl_scope_free_list;
+ EXTERN volatile int _dl_thread_gscope_count;
#ifdef SHARED
};
# define __rtld_global_attribute__
diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h
index cc1d606289..062fe17a0a 100644
--- a/sysdeps/generic/not-cancel.h
+++ b/sysdeps/generic/not-cancel.h
@@ -18,10 +18,22 @@
<http://www.gnu.org/licenses/>. */
/* By default we have none. Map the name to the normal functions. */
-#define open_not_cancel(name, flags, mode) \
+
+/* Uncancelable open. */
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+# define open_not_cancel(name, flags, mode) \
__libc_open (name, flags, mode)
-#define open_not_cancel_2(name, flags) \
+# define open_not_cancel_2(name, flags) \
__libc_open (name, flags)
+#else
+/* In this case, we can't use the libc_* internal functions. */
+# define open_not_cancel(name, flags, mode) \
+ __open (name, flags, mode)
+# define open_not_cancel_2(name, flags) \
+ __open (name, flags)
+#endif
+
+/* Uncancelable openat. */
#define openat_not_cancel(fd, name, flags, mode) \
__openat (fd, name, flags, mode)
#define openat_not_cancel_3(fd, name, flags) \
@@ -30,18 +42,30 @@
__openat64 (fd, name, flags, mode)
#define openat64_not_cancel_3(fd, name, flags) \
__openat64 (fd, name, flags, 0)
+
+/* Uncancelable close. */
#define close_not_cancel(fd) \
__close (fd)
#define close_not_cancel_no_status(fd) \
(void) __close (fd)
+
+/* Uncancelable read. */
#define read_not_cancel(fd, buf, n) \
__read (fd, buf, n)
+
+/* Uncancelable write. */
#define write_not_cancel(fd, buf, n) \
__write (fd, buf, n)
+
+/* Uncancelable writev. */
#define writev_not_cancel_no_status(fd, iov, n) \
(void) __writev (fd, iov, n)
+
+/* Uncancelable fcntl. */
#define fcntl_not_cancel(fd, cmd, val) \
__fcntl (fd, cmd, val)
+
+/* Uncancelable waitpid. */
# define waitpid_not_cancel(pid, stat_loc, options) \
__waitpid (pid, stat_loc, options)
#define pause_not_cancel() \
diff --git a/sysdeps/generic/symbol-hacks.h b/sysdeps/generic/symbol-hacks.h
index 9eaf014ff2..fe99289a4b 100644
--- a/sysdeps/generic/symbol-hacks.h
+++ b/sysdeps/generic/symbol-hacks.h
@@ -1,6 +1,9 @@
/* Some compiler optimizations may transform loops into memset/memmove
calls and without proper declaration it may generate PLT calls. */
#if !defined __ASSEMBLER__ && !defined NOT_IN_libc && defined SHARED
+#include <config.h>
+# if !defined NO_HIDDEN
asm ("memmove = __GI_memmove");
asm ("memset = __GI_memset");
+# endif
#endif
diff --git a/sysdeps/i386/i486/bits/atomic.h b/sysdeps/i386/i486/bits/atomic.h
index 76e0e8e2e3..49cea18d58 100644
--- a/sysdeps/i386/i486/bits/atomic.h
+++ b/sysdeps/i386/i486/bits/atomic.h
@@ -63,35 +63,26 @@ typedef uintmax_t uatomic_max_t;
#define __arch_c_compare_and_exchange_val_8_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchgb %b2, %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchgb %b2, %1" \
: "=a" (ret), "=m" (*mem) \
- : "q" (newval), "m" (*mem), "0" (oldval), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "q" (newval), "m" (*mem), "0" (oldval)); \
ret; })
#define __arch_c_compare_and_exchange_val_16_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchgw %w2, %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchgw %w2, %1" \
: "=a" (ret), "=m" (*mem) \
- : "r" (newval), "m" (*mem), "0" (oldval), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "r" (newval), "m" (*mem), "0" (oldval)); \
ret; })
#define __arch_c_compare_and_exchange_val_32_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchgl %2, %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchgl %2, %1" \
: "=a" (ret), "=m" (*mem) \
- : "r" (newval), "m" (*mem), "0" (oldval), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "r" (newval), "m" (*mem), "0" (oldval)); \
ret; })
/* XXX We do not really need 64-bit compare-and-exchange. At least
@@ -132,10 +123,8 @@ typedef uintmax_t uatomic_max_t;
# define __arch_c_compare_and_exchange_val_64_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
__asm __volatile ("xchgl %2, %%ebx\n\t" \
- "cmpl $0, %%gs:%P7\n\t" \
- "je 0f\n\t" \
"lock\n" \
- "0:\tcmpxchg8b %1\n\t" \
+ "\tcmpxchg8b %1\n\t" \
"xchgl %2, %%ebx" \
: "=A" (ret), "=m" (*mem) \
: "DS" (((unsigned long long int) (newval)) \
@@ -143,8 +132,7 @@ typedef uintmax_t uatomic_max_t;
"c" (((unsigned long long int) (newval)) >> 32), \
"m" (*mem), "a" (((unsigned long long int) (oldval)) \
& 0xffffffff), \
- "d" (((unsigned long long int) (oldval)) >> 32), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ "d" (((unsigned long long int) (oldval)) >> 32)); \
ret; })
# else
# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
@@ -161,18 +149,15 @@ typedef uintmax_t uatomic_max_t;
# define __arch_c_compare_and_exchange_val_64_acq(mem, newval, oldval) \
({ __typeof (*mem) ret; \
- __asm __volatile ("cmpl $0, %%gs:%P7\n\t" \
- "je 0f\n\t" \
- "lock\n" \
- "0:\tcmpxchg8b %1" \
+ __asm __volatile ("lock\n" \
+ "\tcmpxchg8b %1" \
: "=A" (ret), "=m" (*mem) \
: "b" (((unsigned long long int) (newval)) \
& 0xffffffff), \
"c" (((unsigned long long int) (newval)) >> 32), \
"m" (*mem), "a" (((unsigned long long int) (oldval)) \
& 0xffffffff), \
- "d" (((unsigned long long int) (oldval)) >> 32), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ "d" (((unsigned long long int) (oldval)) >> 32)); \
ret; })
# endif
#endif
@@ -207,18 +192,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "xaddb %b0, %1" \
: "=q" (__result), "=m" (*mem) \
- : "0" (__addval), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "0" (__addval), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "xaddw %w0, %1" \
: "=r" (__result), "=m" (*mem) \
- : "0" (__addval), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "0" (__addval), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "xaddl %0, %1" \
: "=r" (__result), "=m" (*mem) \
- : "0" (__addval), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "0" (__addval), "m" (*mem)); \
else \
{ \
__typeof (mem) __memp = (mem); \
@@ -235,7 +217,7 @@ typedef uintmax_t uatomic_max_t;
__sync_fetch_and_add (mem, value)
#define __arch_exchange_and_add_cprefix \
- "cmpl $0, %%gs:%P4\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_exchange_and_add(mem, value) \
__arch_exchange_and_add_body (__arch_exchange_and_add_cprefix, __arch_c, \
@@ -251,18 +233,15 @@ typedef uintmax_t uatomic_max_t;
else if (sizeof (*mem) == 1) \
__asm __volatile (lock "addb %b1, %0" \
: "=m" (*mem) \
- : "iq" (value), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "iq" (value), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "addw %w1, %0" \
: "=m" (*mem) \
- : "ir" (value), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (value), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "addl %1, %0" \
: "=m" (*mem) \
- : "ir" (value), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (value), "m" (*mem)); \
else \
{ \
__typeof (value) __addval = (value); \
@@ -280,7 +259,7 @@ typedef uintmax_t uatomic_max_t;
__arch_add_body (LOCK_PREFIX, __arch, mem, value)
#define __arch_add_cprefix \
- "cmpl $0, %%gs:%P3\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_add(mem, value) \
__arch_add_body (__arch_add_cprefix, __arch_c, mem, value)
@@ -329,18 +308,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "incb %b0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "incw %w0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "incl %0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else \
{ \
__typeof (mem) __memp = (mem); \
@@ -356,7 +332,7 @@ typedef uintmax_t uatomic_max_t;
#define atomic_increment(mem) __arch_increment_body (LOCK_PREFIX, __arch, mem)
#define __arch_increment_cprefix \
- "cmpl $0, %%gs:%P2\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_increment(mem) \
__arch_increment_body (__arch_increment_cprefix, __arch_c, mem)
@@ -386,18 +362,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "decb %b0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "decw %w0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "decl %0" \
: "=m" (*mem) \
- : "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "m" (*mem)); \
else \
{ \
__typeof (mem) __memp = (mem); \
@@ -413,7 +386,7 @@ typedef uintmax_t uatomic_max_t;
#define atomic_decrement(mem) __arch_decrement_body (LOCK_PREFIX, __arch, mem)
#define __arch_decrement_cprefix \
- "cmpl $0, %%gs:%P2\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define catomic_decrement(mem) \
__arch_decrement_body (__arch_decrement_cprefix, __arch_c, mem)
@@ -484,24 +457,21 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "andb %b1, %0" \
: "=m" (*mem) \
- : "iq" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "iq" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "andw %w1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "andl %1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else \
abort (); \
} while (0)
#define __arch_cprefix \
- "cmpl $0, %%gs:%P3\n\tje 0f\n\tlock\n0:\t"
+ "lock\n\t"
#define atomic_and(mem, mask) __arch_and_body (LOCK_PREFIX, mem, mask)
@@ -513,18 +483,15 @@ typedef uintmax_t uatomic_max_t;
if (sizeof (*mem) == 1) \
__asm __volatile (lock "orb %b1, %0" \
: "=m" (*mem) \
- : "iq" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "iq" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 2) \
__asm __volatile (lock "orw %w1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else if (sizeof (*mem) == 4) \
__asm __volatile (lock "orl %1, %0" \
: "=m" (*mem) \
- : "ir" (mask), "m" (*mem), \
- "i" (offsetof (tcbhead_t, multiple_threads))); \
+ : "ir" (mask), "m" (*mem)); \
else \
abort (); \
} while (0)
diff --git a/sysdeps/mach/configure b/sysdeps/mach/configure
index 61ac7d9684..d7c102c672 100644
--- a/sysdeps/mach/configure
+++ b/sysdeps/mach/configure
@@ -165,6 +165,11 @@ fi
config_vars="$config_vars
MIG = $MIG"
+if test -n "$sysheaders"; then
+ OLD_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $SYSINCLUDES"
+fi
+
### Sanity checks for Mach header installation
@@ -277,7 +282,7 @@ if test $libc_cv_mach_task_creation_time = no; then
fi
mach_interface_list=
-for ifc in mach mach4 \
+for ifc in mach mach4 gnumach \
clock clock_priv host_priv host_security ledger lock_set \
processor processor_set task thread_act vm_map \
memory_object memory_object_default default_pager \
@@ -553,3 +558,7 @@ if test $hurd_cv_mig_retcode = yes; then
$as_echo "#define HAVE_MIG_RETCODE 1" >>confdefs.h
fi
+
+if test -n "$sysheaders"; then
+ CPPFLAGS=$OLD_CPPFLAGS
+fi
diff --git a/sysdeps/mach/configure.ac b/sysdeps/mach/configure.ac
index db85f47eae..f972270614 100644
--- a/sysdeps/mach/configure.ac
+++ b/sysdeps/mach/configure.ac
@@ -6,6 +6,11 @@ if test "x$MIG" = xMISSING; then
fi
LIBC_CONFIG_VAR([MIG], [$MIG])
+if test -n "$sysheaders"; then
+ OLD_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $SYSINCLUDES"
+fi
+
### Sanity checks for Mach header installation
AC_CHECK_HEADER(mach/mach_types.h,,
[AC_MSG_ERROR([cannot find Mach headers])], -)
@@ -54,7 +59,7 @@ dnl but we don't do a check for that here because in a bare
dnl environment the compile against those headers will fail.
dnl
mach_interface_list=
-for ifc in mach mach4 \
+for ifc in mach mach4 gnumach \
clock clock_priv host_priv host_security ledger lock_set \
processor processor_set task thread_act vm_map \
memory_object memory_object_default default_pager \
@@ -124,3 +129,7 @@ if test $hurd_cv_mig_retcode = yes; then
fi])
hurd_MIG_RETCODE
+
+if test -n "$sysheaders"; then
+ CPPFLAGS=$OLD_CPPFLAGS
+fi
diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
index fe028316ae..e47baa129f 100644
--- a/sysdeps/mach/hurd/Makefile
+++ b/sysdeps/mach/hurd/Makefile
@@ -167,6 +167,10 @@ $(objpfx)librtld.map: $(rpcuserlibs:.so=_pic.a)
CFLAGS-dl-load.c = -DEXTERNAL_MAP_FROM_FD
endif
+ifeq ($(subdir),posix)
+CFLAGS-confstr.c += -DLIBPTHREAD_VERSION='"libpthread 0.3"'
+endif
+
# Override the generic Makeconfig values so we link against the RPC libs.
link-libc-static := -Wl,--start-group \
$(patsubst %,$(common-objpfx)%.a,\
@@ -191,6 +195,10 @@ ifeq (hurd, $(subdir))
sysdep_routines += cthreads
endif
+ifeq (io, $(subdir))
+sysdep_routines += f_setlk
+endif
+
ifeq ($(subdir),sunrpc)
sysdep_headers += nfs/nfs.h
endif
diff --git a/sysdeps/mach/hurd/bind.c b/sysdeps/mach/hurd/bind.c
index 17ef22a7d0..522352ef2a 100644
--- a/sysdeps/mach/hurd/bind.c
+++ b/sysdeps/mach/hurd/bind.c
@@ -25,7 +25,7 @@
#include <stddef.h>
#include <hurd/ifsock.h>
#include <sys/un.h>
-#include <string.h>
+#include "hurd/hurdsocket.h"
/* Give the socket FD the local address ADDR (which is LEN bytes long). */
int
@@ -37,13 +37,11 @@ __bind (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len)
if (addr->sun_family == AF_LOCAL)
{
+ char *name = _hurd_sun_path_dupa (addr, len);
/* For the local domain, we must create a node in the filesystem
using the ifsock translator and then fetch the address from it. */
file_t dir, node;
- char name[len - offsetof (struct sockaddr_un, sun_path) + 1], *n;
-
- strncpy (name, addr->sun_path, sizeof name - 1);
- name[sizeof name - 1] = '\0'; /* Make sure */
+ char *n;
dir = __file_name_split (name, &n);
if (dir == MACH_PORT_NULL)
diff --git a/sysdeps/mach/hurd/bits/fcntl.h b/sysdeps/mach/hurd/bits/fcntl.h
index 135aba3bc9..9460be7ff0 100644
--- a/sysdeps/mach/hurd/bits/fcntl.h
+++ b/sysdeps/mach/hurd/bits/fcntl.h
@@ -163,9 +163,18 @@
# define F_GETOWN 5 /* Get owner (receiver of SIGIO). */
# define F_SETOWN 6 /* Set owner (receiver of SIGIO). */
#endif
-#define F_GETLK 7 /* Get record locking info. */
-#define F_SETLK 8 /* Set record locking info (non-blocking). */
-#define F_SETLKW 9 /* Set record locking info (blocking). */
+#ifdef __USE_FILE_OFFSET64
+# define F_GETLK F_GETLK64
+# define F_SETLK F_SETLK64
+# define F_SETLKW F_SETLKW64
+#else
+# define F_GETLK 7 /* Get record locking info. */
+# define F_SETLK 8 /* Set record locking info (non-blocking). */
+# define F_SETLKW 9 /* Set record locking info (blocking). */
+#endif
+#define F_GETLK64 10 /* Get record locking info. */
+#define F_SETLK64 11 /* Set record locking info (non-blocking). */
+#define F_SETLKW64 12 /* Set record locking info (blocking). */
#ifdef __USE_XOPEN2K8
# define F_DUPFD_CLOEXEC 1030 /* Duplicate, set FD_CLOEXEC on new one. */
diff --git a/sysdeps/mach/hurd/bits/ioctls.h b/sysdeps/mach/hurd/bits/ioctls.h
index e5203ad7e9..efa7bdf0c4 100644
--- a/sysdeps/mach/hurd/bits/ioctls.h
+++ b/sysdeps/mach/hurd/bits/ioctls.h
@@ -148,9 +148,26 @@ enum __ioctl_datum { IOC_8, IOC_16, IOC_32, IOC_64 };
#define _IOT_SIMPLE(type) _IOT (_IOTS (type), 1, 0, 0, 0, 0)
/* Basic C types. */
-#define _IOT__IOTBASE_int _IOT_SIMPLE (int)
#define _IOT__IOTBASE_char _IOT_SIMPLE (char)
#define _IOT__IOTBASE_short _IOT_SIMPLE (short)
+#define _IOT__IOTBASE_int _IOT_SIMPLE (int)
+#define _IOT__IOTBASE_long _IOT_SIMPLE (long)
+#define _IOT_char _IOT_SIMPLE (char)
+#define _IOT_short _IOT_SIMPLE (short)
+#define _IOT_int _IOT_SIMPLE (int)
+#define _IOT_long _IOT_SIMPLE (long)
+
+#define _IOT__IOTBASE_int8_t _IOT_SIMPLE (int8_t)
+#define _IOT__IOTBASE_uint8_t _IOT_SIMPLE (uint8_t)
+#define _IOT__IOTBASE_int16_t _IOT_SIMPLE (int16_t)
+#define _IOT__IOTBASE_uint16_t _IOT_SIMPLE (uint16_t)
+#define _IOT__IOTBASE_int32_t _IOT_SIMPLE (int32_t)
+#define _IOT__IOTBASE_uint32_t _IOT_SIMPLE (uint32_t)
+#define _IOT__IOTBASE_int64_t _IOT_SIMPLE (int64_t)
+#define _IOT__IOTBASE_uint64_t _IOT_SIMPLE (uint64_t)
+
+#define _IOT__IOTBASE_size_t _IOT_SIMPLE (size_t)
+#define _IOT__IOTBASE_ssize_t _IOT_SIMPLE (ssize_t)
/* Standard flavors of ioctls.
@@ -173,6 +190,10 @@ enum __ioctl_datum { IOC_8, IOC_16, IOC_32, IOC_64 };
#define _IOC_ENCODE_TYPE_1(typespec) _IOC_ENCODE_TYPE_2(typespec)
#define _IOC_ENCODE_TYPE_2(typespec) _IOT_##typespec
+/* Also, ignore signedness. */
+#define _IOTBASE_unsigned
+#define _IOTBASE_signed
+
/* ioctls verbatim from 4.4 <sys/ioctl.h>. */
diff --git a/sysdeps/mach/hurd/bits/libc-lock.h b/sysdeps/mach/hurd/bits/libc-lock.h
index a0f83728e4..cc4afb1507 100644
--- a/sysdeps/mach/hurd/bits/libc-lock.h
+++ b/sysdeps/mach/hurd/bits/libc-lock.h
@@ -20,9 +20,9 @@
#define _BITS_LIBC_LOCK_H 1
#if (_LIBC - 0) || (_CTHREADS_ - 0)
-#if (_LIBC - 0)
-#include <tls.h>
-#endif
+# if (_LIBC - 0)
+# include <tls.h>
+# endif
#include <cthreads.h>
typedef struct mutex __libc_lock_t;
@@ -210,4 +210,10 @@ void *__libc_getspecific (__libc_key_t key);
#endif /* _CTHREADS_ */
+/* Hide the definitions which are only supposed to be used inside libc in
+ a separate file. This file is not present in the installation! */
+#ifdef _LIBC
+# include <bits/libc-lockP.h>
+#endif
+
#endif /* bits/libc-lock.h */
diff --git a/sysdeps/mach/hurd/bits/posix_opt.h b/sysdeps/mach/hurd/bits/posix_opt.h
index a897cb1640..9ab9c9f493 100644
--- a/sysdeps/mach/hurd/bits/posix_opt.h
+++ b/sysdeps/mach/hurd/bits/posix_opt.h
@@ -68,27 +68,41 @@
/* X/Open thread realtime support is not supported. */
#undef _XOPEN_REALTIME_THREADS
-/* XPG4.2 shared memory is not supported. */
-#undef _XOPEN_SHM
+/* XPG4.2 shared memory is supported. */
+#define _XOPEN_SHM 1
-/* We do not have the POSIX threads interface. */
-#define _POSIX_THREADS -1
+/* Tell we have POSIX threads. */
+#define _POSIX_THREADS 200112L
/* We have the reentrant functions described in POSIX. */
#define _POSIX_REENTRANT_FUNCTIONS 1
#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
-/* These are all things that won't be supported when _POSIX_THREADS is not. */
+/* We do not provide priority scheduling for threads. */
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
-#define _POSIX_THREAD_ATTR_STACKSIZE -1
-#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+/* We support user-defined stack sizes. */
+#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
+
+/* We support user-defined stacks. */
+#define _POSIX_THREAD_ATTR_STACKADDR 200112L
+
+/* We do not support priority inheritence. */
#define _POSIX_THREAD_PRIO_INHERIT -1
+
+/* We do not support priority protection. */
#define _POSIX_THREAD_PRIO_PROTECT -1
+
#ifdef __USE_XOPEN2K8
+/* We do not support priority inheritence for robust mutexes. */
# define _POSIX_THREAD_ROBUST_PRIO_INHERIT -1
+
+/* We do not support priority protection for robust mutexes. */
# define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1
#endif
-#define _POSIX_SEMAPHORES -1
+
+/* We support POSIX.1b semaphores. */
+#define _POSIX_SEMAPHORES 200112L
/* Real-time signals are not yet supported. */
#define _POSIX_REALTIME_SIGNALS -1
@@ -121,17 +135,17 @@
/* GNU libc provides regular expression handling. */
#define _POSIX_REGEXP 1
-/* Reader/Writer locks are not available. */
-#define _POSIX_READER_WRITER_LOCKS -1
+/* Reader/Writer locks are available. */
+#define _POSIX_READER_WRITER_LOCKS 200112L
/* We have a POSIX shell. */
#define _POSIX_SHELL 1
-/* We cannot support the Timeouts option without _POSIX_THREADS. */
-#define _POSIX_TIMEOUTS -1
+/* We support the Timeouts option. */
+#define _POSIX_TIMEOUTS 200112L
-/* We do not support spinlocks. */
-#define _POSIX_SPIN_LOCKS -1
+/* We support spinlocks. */
+#define _POSIX_SPIN_LOCKS 200112L
/* The `spawn' function family is supported. */
#define _POSIX_SPAWN 200809L
@@ -139,8 +153,8 @@
/* We do not have POSIX timers, but could in future without ABI change. */
#define _POSIX_TIMERS 0
-/* The barrier functions are not available. */
-#define _POSIX_BARRIERS -1
+/* We support barrier functions. */
+#define _POSIX_BARRIERS 200112L
/* POSIX message queues could be available in future. */
#define _POSIX_MESSAGE_PASSING 0
diff --git a/sysdeps/mach/hurd/bits/sigaction.h b/sysdeps/mach/hurd/bits/sigaction.h
new file mode 100644
index 0000000000..7204fc6b86
--- /dev/null
+++ b/sysdeps/mach/hurd/bits/sigaction.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _SIGNAL_H
+# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
+#endif
+
+/* These definitions match those used by the 4.4 BSD kernel.
+ If the operating system has a `sigaction' system call that correctly
+ implements the POSIX.1 behavior, there should be a system-dependent
+ version of this file that defines `struct sigaction' and the `SA_*'
+ constants appropriately. */
+
+/* Structure describing the action to be taken when a signal arrives. */
+struct sigaction
+ {
+ /* Signal handler. */
+#ifdef __USE_POSIX199309
+ union
+ {
+ /* Used if SA_SIGINFO is not set. */
+ __sighandler_t sa_handler;
+ /* Used if SA_SIGINFO is set. */
+ void (*sa_sigaction) (int, siginfo_t *, void *);
+ }
+ __sigaction_handler;
+# define sa_handler __sigaction_handler.sa_handler
+# define sa_sigaction __sigaction_handler.sa_sigaction
+#else
+ __sighandler_t sa_handler;
+#endif
+
+ /* Additional set of signals to be blocked. */
+ __sigset_t sa_mask;
+
+ /* Special flags. */
+ int sa_flags;
+ };
+
+/* Bits in `sa_flags'. */
+#if defined __USE_UNIX98 || defined __USE_MISC
+# define SA_ONSTACK 0x0001 /* Take signal on signal stack. */
+#endif
+#if defined __USE_UNIX98 || defined __USE_MISC || defined __USE_XOPEN2K8
+# define SA_RESTART 0x0002 /* Restart syscall on signal return. */
+# define SA_NODEFER 0x0010 /* Don't automatically block the signal when
+ its handler is being executed. */
+# define SA_RESETHAND 0x0004 /* Reset to SIG_DFL on entry to handler. */
+# define SA_SIGINFO 0x0040 /* Signal handler with SA_SIGINFO args */
+#endif
+#define SA_NOCLDSTOP 0x0008 /* Don't send SIGCHLD when children stop. */
+
+#ifdef __USE_MISC
+# define SA_INTERRUPT 0 /* Historical no-op ("not SA_RESTART"). */
+
+/* Some aliases for the SA_ constants. */
+# define SA_NOMASK SA_NODEFER
+# define SA_ONESHOT SA_RESETHAND
+# define SA_STACK SA_ONSTACK
+#endif
+
+
+/* Values for the HOW argument to `sigprocmask'. */
+#define SIG_BLOCK 1 /* Block signals. */
+#define SIG_UNBLOCK 2 /* Unblock signals. */
+#define SIG_SETMASK 3 /* Set the set of blocked signals. */
diff --git a/sysdeps/mach/hurd/bits/stat.h b/sysdeps/mach/hurd/bits/stat.h
index e6bec34660..f60a58ae9c 100644
--- a/sysdeps/mach/hurd/bits/stat.h
+++ b/sysdeps/mach/hurd/bits/stat.h
@@ -222,9 +222,40 @@ struct stat64
S_IUSEUNK|S_IUNKNOWN|07777))
#endif
-/* Default file creation mask (umask). */
#ifdef __USE_BSD
+
+/* Default file creation mask (umask). */
# define CMASK 0022
+
+
+/* Definitions of flags stored in file flags word. */
+
+/* Super-user and owner changeable flags. */
+# define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags */
+# define UF_NODUMP 0x00000001 /* do not dump file */
+# define UF_IMMUTABLE 0x00000002 /* file may not be changed */
+# define UF_APPEND 0x00000004 /* writes to file may only append */
+# define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */
+# define UF_NOUNLINK 0x00000010 /* file may not be removed or renamed */
+
+/* Super-user changeable flags. */
+# define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */
+# define SF_ARCHIVED 0x00010000 /* file is archived */
+# define SF_IMMUTABLE 0x00020000 /* file may not be changed */
+# define SF_APPEND 0x00040000 /* writes to file may only append */
+# define SF_NOUNLINK 0x00100000 /* file may not be removed or renamed */
+# define SF_SNAPSHOT 0x00200000 /* snapshot inode */
+
+__BEGIN_DECLS
+
+/* Set file flags for FILE to FLAGS. */
+extern int chflags (__const char *__file, unsigned long int __flags) __THROW;
+
+/* Set file flags of the file referred to by FD to FLAGS. */
+extern int fchflags (int __fd, unsigned long int __flags) __THROW;
+
+__END_DECLS
+
#endif
#endif /* bits/stat.h */
diff --git a/sysdeps/mach/hurd/brk.c b/sysdeps/mach/hurd/brk.c
index d97f7418db..28ba29733f 100644
--- a/sysdeps/mach/hurd/brk.c
+++ b/sysdeps/mach/hurd/brk.c
@@ -143,8 +143,12 @@ init_brk (void)
/* If _hurd_brk is already set, don't change it. The assumption is that
it was set in a previous run before something like Emacs's unexec was
called and dumped all the data up to the break at that point. */
- if (_hurd_brk == 0)
+ if (_hurd_brk == 0) {
_hurd_brk = (vm_address_t) &_end;
+ if (_hurd_brk < 0x8000000)
+ /* XXX: PIE case, get out of library area */
+ _hurd_brk = 0x8000000;
+ }
pagend = round_page (_hurd_brk);
diff --git a/sysdeps/mach/hurd/chflags.c b/sysdeps/mach/hurd/chflags.c
index 938f81d0d3..4186af3ccc 100644
--- a/sysdeps/mach/hurd/chflags.c
+++ b/sysdeps/mach/hurd/chflags.c
@@ -24,7 +24,7 @@
/* XXX shouldn't this be __chflags? */
int
-chflags (const char *file, int flags)
+chflags (const char *file, unsigned long int flags)
{
error_t err;
file_t port = __file_name_lookup (file, 0, 0);
diff --git a/sysdeps/mach/hurd/configure b/sysdeps/mach/hurd/configure
index a0f97217e9..4b2ad37e73 100644
--- a/sysdeps/mach/hurd/configure
+++ b/sysdeps/mach/hurd/configure
@@ -17,6 +17,11 @@ case "$machine" in
;;
esac
+if test -n "$sysheaders"; then
+ OLD_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $SYSINCLUDES"
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Hurd header version" >&5
$as_echo_n "checking Hurd header version... " >&6; }
@@ -50,3 +55,7 @@ $as_echo "$libc_cv_hurd_version" >&6; }
if test "x$libc_cv_hurd_version" != xok; then
as_fn_error $? "Hurd headers not installed or too old" "$LINENO" 5
fi
+
+if test -n "$sysheaders"; then
+ CPPFLAGS=$OLD_CPPFLAGS
+fi
diff --git a/sysdeps/mach/hurd/configure.ac b/sysdeps/mach/hurd/configure.ac
index ad915a568b..db783a0943 100644
--- a/sysdeps/mach/hurd/configure.ac
+++ b/sysdeps/mach/hurd/configure.ac
@@ -17,6 +17,11 @@ case "$machine" in
;;
esac
+if test -n "$sysheaders"; then
+ OLD_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $SYSINCLUDES"
+fi
+
AC_CACHE_CHECK(Hurd header version, libc_cv_hurd_version, [dnl
AC_TRY_COMPILE(dnl
[#include <hurd/version.h>], [
@@ -29,3 +34,7 @@ AC_TRY_COMPILE(dnl
if test "x$libc_cv_hurd_version" != xok; then
AC_MSG_ERROR(Hurd headers not installed or too old)
fi
+
+if test -n "$sysheaders"; then
+ CPPFLAGS=$OLD_CPPFLAGS
+fi
diff --git a/sysdeps/mach/hurd/connect.c b/sysdeps/mach/hurd/connect.c
index 24dd616e3b..b78644b173 100644
--- a/sysdeps/mach/hurd/connect.c
+++ b/sysdeps/mach/hurd/connect.c
@@ -22,6 +22,7 @@
#include <hurd/socket.h>
#include <sys/un.h>
#include <hurd/ifsock.h>
+#include "hurd/hurdsocket.h"
/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
For connectionless socket types, just set the default address to send to
@@ -36,9 +37,10 @@ __connect (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len)
if (addr->sun_family == AF_LOCAL)
{
+ char *name = _hurd_sun_path_dupa (addr, len);
/* For the local domain, we must look up the name as a file and talk
to it with the ifsock protocol. */
- file_t file = __file_name_lookup (addr->sun_path, 0, 0);
+ file_t file = __file_name_lookup (name, 0, 0);
if (file == MACH_PORT_NULL)
return -1;
err = __ifsock_getsockaddr (file, &aport);
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index cb65e93ca1..96306aa047 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -61,6 +61,8 @@ void *__libc_stack_end;
hp_timing_t _dl_cpuclock_offset;
#endif
+/* TODO: this is never properly initialized in here. */
+void *_dl_random attribute_relro = NULL;
struct hurd_startup_data *_dl_hurd_data;
@@ -85,12 +87,28 @@ static void fmh(void) {
max=a; break;}
fmha=a+=fmhs;}
if (err) assert(err==KERN_NO_SPACE);
- if (!fmha)fmhs=0;else{
- fmhs=max-fmha;
- err = __vm_map (__mach_task_self (),
- &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1,
- VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
- assert_perror(err);}
+ if (!fmha)
+ fmhs=0;
+ else
+ while (1) {
+ fmhs=max-fmha;
+ if (fmhs == 0)
+ break;
+ err = __vm_map (__mach_task_self (),
+ &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1,
+ VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
+ if (!err)
+ break;
+ if (err != KERN_INVALID_ADDRESS && err != KERN_NO_SPACE)
+ assert_perror(err);
+ vm_address_t new_max = (max - 1) & 0xf0000000U;
+ if (new_max >= max) {
+ fmhs = 0;
+ fmha = 0;
+ break;
+ }
+ max = new_max;
+ }
}
/* XXX loser kludge for vm_map kernel bug */
#endif
diff --git a/sysdeps/mach/hurd/f_setlk.c b/sysdeps/mach/hurd/f_setlk.c
new file mode 100644
index 0000000000..6e1b308756
--- /dev/null
+++ b/sysdeps/mach/hurd/f_setlk.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* XXX
+ We need new RPCs to support POSIX.1 fcntl file locking!!
+ For the time being we support the whole-file case only,
+ with all kinds of WRONG WRONG WRONG semantics,
+ by using flock. This is definitely the Wrong Thing,
+ but it might be better than nothing (?). */
+int
+__f_setlk (int fd, int type, int whence, __off64_t start, __off64_t len, int wait)
+{
+ int cmd = 0;
+
+ switch (type)
+ {
+ case F_RDLCK: cmd |= LOCK_SH | __LOCK_ATOMIC; break;
+ case F_WRLCK: cmd |= LOCK_EX | __LOCK_ATOMIC; break;
+ case F_UNLCK: cmd = LOCK_UN; break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (wait == 0)
+ cmd |= LOCK_NB;
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ if (start == 0 && len == 0) /* Whole file request. */
+ break;
+ /* It seems to be common for applications to lock the first
+ byte of the file when they are really doing whole-file locking.
+ So, since it's so wrong already, might as well do that too. */
+ if (start == 0 && len == 1)
+ break;
+ /* FALLTHROUGH */
+ case SEEK_CUR:
+ case SEEK_END:
+ errno = ENOTSUP;
+ return -1;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return __flock (fd, cmd);
+}
diff --git a/sysdeps/mach/hurd/f_setlk.h b/sysdeps/mach/hurd/f_setlk.h
new file mode 100644
index 0000000000..16c7a8ca8d
--- /dev/null
+++ b/sysdeps/mach/hurd/f_setlk.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _F_SETLK_H
+#define _F_SETLK_H 1
+
+extern int __f_setlk (int fd, int type, int whence, __off64_t start, __off64_t len, int wait);
+
+#endif /* f_setlk.h */
diff --git a/sysdeps/mach/hurd/fchflags.c b/sysdeps/mach/hurd/fchflags.c
index 6d01b1a35b..a9df1fb40f 100644
--- a/sysdeps/mach/hurd/fchflags.c
+++ b/sysdeps/mach/hurd/fchflags.c
@@ -25,7 +25,7 @@
/* XXX should be __fchflags? */
int
-fchflags (int fd, int flags)
+fchflags (int fd, unsigned long int flags)
{
error_t err;
diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c
index 813f3370ed..076f2eaa71 100644
--- a/sysdeps/mach/hurd/fcntl.c
+++ b/sysdeps/mach/hurd/fcntl.c
@@ -21,6 +21,7 @@
#include <hurd/fd.h>
#include <stdarg.h>
#include <sys/file.h> /* XXX for LOCK_* */
+#include "f_setlk.h"
/* Perform file control operations on FD. */
int
@@ -128,56 +129,48 @@ __libc_fcntl (int fd, int cmd, ...)
case F_SETLK:
case F_SETLKW:
{
- /* XXX
- We need new RPCs to support POSIX.1 fcntl file locking!!
- For the time being we support the whole-file case only,
- with all kinds of WRONG WRONG WRONG semantics,
- by using flock. This is definitely the Wrong Thing,
- but it might be better than nothing (?). */
struct flock *fl = va_arg (ap, struct flock *);
+ int wait = 0;
va_end (ap);
switch (cmd)
{
case F_GETLK:
errno = ENOSYS;
return -1;
+ case F_SETLKW:
+ wait = 1;
+ /* FALLTHROUGH */
case F_SETLK:
- cmd = LOCK_NB;
- break;
- default:
- cmd = 0;
- break;
- }
- switch (fl->l_type)
- {
- case F_RDLCK: cmd |= LOCK_SH; break;
- case F_WRLCK: cmd |= LOCK_EX; break;
- case F_UNLCK: cmd |= LOCK_UN; break;
+ return __f_setlk (fd, fl->l_type, fl->l_whence,
+ fl->l_start, fl->l_len, wait);
default:
errno = EINVAL;
return -1;
}
- switch (fl->l_whence)
+ }
+
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ {
+ struct flock64 *fl = va_arg (ap, struct flock64 *);
+ int wait = 0;
+ va_end (ap);
+ switch (cmd)
{
- case SEEK_SET:
- if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */
- break;
- /* It seems to be common for applications to lock the first
- byte of the file when they are really doing whole-file locking.
- So, since it's so wrong already, might as well do that too. */
- if (fl->l_start == 0 && fl->l_len == 1)
- break;
- /* FALLTHROUGH */
- case SEEK_CUR:
- case SEEK_END:
- errno = ENOTSUP;
+ case F_GETLK64:
+ errno = ENOSYS;
return -1;
+ case F_SETLKW64:
+ wait = 1;
+ /* FALLTHROUGH */
+ case F_SETLK64:
+ return __f_setlk (fd, fl->l_type, fl->l_whence,
+ fl->l_start, fl->l_len, wait);
default:
errno = EINVAL;
return -1;
}
-
- return __flock (fd, cmd);
}
case F_GETFL: /* Get per-open flags. */
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
index 64026e00c2..6e5a7bece2 100644
--- a/sysdeps/mach/hurd/fork.c
+++ b/sysdeps/mach/hurd/fork.c
@@ -130,9 +130,13 @@ __fork (void)
ports_locked = 1;
+ /* Keep our SS locked while stopping other threads, so they don't get a
+ chance to have it locked in the copied space. */
+ __spin_lock (&ss->lock);
/* Stop all other threads while copying the address space,
so nothing changes. */
err = __proc_dostop (_hurd_ports[INIT_PORT_PROC].port, ss->thread);
+ __spin_unlock (&ss->lock);
if (!err)
{
stopped = 1;
@@ -465,6 +469,7 @@ __fork (void)
function, accounted for by mach_port_names (and which will thus be
accounted for in the child below). This extra right gets consumed
in the child by the store into _hurd_sigthread in the child fork. */
+ /* XXX consumed? (_hurd_sigthread is no more) */
if (thread_refs > 1 &&
(err = __mach_port_mod_refs (newtask, ss->thread,
MACH_PORT_RIGHT_SEND,
@@ -625,10 +630,6 @@ __fork (void)
for (i = 0; i < _hurd_nports; ++i)
__spin_unlock (&_hurd_ports[i].lock);
- /* We are one of the (exactly) two threads in this new task, we
- will take the task-global signals. */
- _hurd_sigthread = ss->thread;
-
/* Claim our sigstate structure and unchain the rest: the
threads existed in the parent task but don't exist in this
task (the child process). Delay freeing them until later
@@ -648,6 +649,25 @@ __fork (void)
ss->next = NULL;
_hurd_sigstates = ss;
__mutex_unlock (&_hurd_siglock);
+ /* Earlier on, the global sigstate may have been tainted and now needs to
+ be reinitialized. Nobody is interested in its present state anymore:
+ we're not, the signal thread will be restarted, and there are no other
+ threads.
+
+ We can't simply allocate a fresh global sigstate here, as
+ _hurd_thread_sigstate will call malloc and that will deadlock trying
+ to determine the current thread's sigstate. */
+#if 0
+ _hurd_thread_sigstate_init (_hurd_global_sigstate, MACH_PORT_NULL);
+#else
+ /* Only reinitialize the lock -- otherwise we might have to do additional
+ setup as done in hurdsig.c:_hurdsig_init. */
+ __spin_lock_init (&_hurd_global_sigstate->lock);
+#endif
+
+ /* We are one of the (exactly) two threads in this new task, we
+ will take the task-global signals. */
+ _hurd_sigstate_set_global_rcv (ss);
/* Fetch our new process IDs from the proc server. No need to
refetch our pgrp; it is always inherited from the parent (so
@@ -656,8 +676,10 @@ __fork (void)
err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid,
&_hurd_orphaned));
- /* Forking clears the trace flag. */
+ /* Forking clears the trace flag and pending masks. */
__sigemptyset (&_hurdsig_traced);
+ __sigemptyset (&_hurd_global_sigstate->pending);
+ __sigemptyset (&ss->pending);
/* Run things that want to run in the child task to set up. */
RUN_HOOK (_hurd_fork_child_hook, ());
diff --git a/sysdeps/mach/hurd/ftok.c b/sysdeps/mach/hurd/ftok.c
new file mode 100644
index 0000000000..a6aba15c86
--- /dev/null
+++ b/sysdeps/mach/hurd/ftok.c
@@ -0,0 +1,43 @@
+/* SysV ftok for Hurd.
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/ipc.h>
+#include <sys/stat.h>
+
+
+/* In the Hurd, we use the second-to-most-significant bit as flag for
+ private keys. We use an order of the components different from the generic
+ code in sysvipc/ftok.c so that the biggest one--the inode number--is
+ affected by this. */
+
+key_t
+ftok (pathname, proj_id)
+ const char *pathname;
+ int proj_id;
+{
+ struct stat64 st;
+ key_t key;
+
+ if (__xstat64 (_STAT_VER, pathname, &st) < 0)
+ return (key_t) -1;
+
+ key = ((st.st_dev & 0xff) | ((proj_id & 0xff) << 8)
+ | ((st.st_ino & 0x3fff) << 16));
+
+ return key;
+}
diff --git a/sysdeps/mach/hurd/futimens.c b/sysdeps/mach/hurd/futimens.c
new file mode 100644
index 0000000000..4f82f1e76b
--- /dev/null
+++ b/sysdeps/mach/hurd/futimens.c
@@ -0,0 +1,50 @@
+/* futimes -- change access and modification times of open file. Hurd version.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/time.h>
+#include <errno.h>
+#include <stddef.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Change the access time of FD to TSP[0] and
+ the modification time of FD to TSP[1]. */
+int
+__futimens (int fd, const struct timespec tsp[2])
+{
+ time_value_t atime, mtime;
+ error_t err;
+
+ if (tsp == NULL)
+ {
+ /* Setting the number of microseconds to `-1' tells the
+ underlying filesystems to use the current time. */
+ atime.microseconds = mtime.microseconds = -1;
+ }
+ else
+ {
+ atime.seconds = tsp[0].tv_sec;
+ atime.microseconds = tsp[0].tv_nsec / 1000;
+ mtime.seconds = tsp[1].tv_sec;
+ mtime.microseconds = tsp[1].tv_nsec / 1000;
+ }
+
+ err = HURD_DPORT_USE (fd, __file_utimes (port, atime, mtime));
+ return err ? __hurd_dfail (fd, err) : 0;
+}
+weak_alias (__futimens, futimens)
diff --git a/sysdeps/mach/hurd/gai_misc.h b/sysdeps/mach/hurd/gai_misc.h
new file mode 100644
index 0000000000..ee8117fa96
--- /dev/null
+++ b/sysdeps/mach/hurd/gai_misc.h
@@ -0,0 +1,44 @@
+#include <signal.h>
+#include <pthread.h>
+
+#define gai_start_notify_thread __gai_start_notify_thread
+#define gai_create_helper_thread __gai_create_helper_thread
+
+extern inline void
+__gai_start_notify_thread (void)
+{
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigprocmask(SIG_SETMASK, &ss, NULL);
+}
+
+extern inline int
+__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
+ void *arg)
+{
+ pthread_attr_t attr;
+
+ /* Make sure the thread is created detached. */
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+ /* The helper thread needs only very little resources. */
+ (void) pthread_attr_setstacksize (&attr, 0x10000);
+
+ /* Block all signals in the helper thread. To do this thoroughly we
+ temporarily have to block all signals here. */
+ sigset_t ss;
+ sigset_t oss;
+ sigfillset (&ss);
+ sigprocmask(SIG_SETMASK, &ss, &oss);
+
+ int ret = pthread_create (threadp, &attr, tf, arg);
+
+ /* Restore the signal mask. */
+ sigprocmask(SIG_SETMASK, &oss, NULL);
+
+ (void) pthread_attr_destroy (&attr);
+ return ret;
+}
+
+#include_next <gai_misc.h>
diff --git a/sysdeps/mach/hurd/getcwd.c b/sysdeps/mach/hurd/getcwd.c
index d1ac7aef2c..3d4d0565a3 100644
--- a/sysdeps/mach/hurd/getcwd.c
+++ b/sysdeps/mach/hurd/getcwd.c
@@ -266,11 +266,6 @@ _hurd_canonicalize_directory_name_internal (file_t thisdir,
So the root is our current directory. */
*--file_namep = '/';
- if (thisid != rootid)
- /* We did not get to our root directory. The returned name should
- not begin with a slash. */
- ++file_namep;
-
memmove (file_name, file_namep, file_name + size - file_namep);
cleanup ();
return file_name;
@@ -310,13 +305,6 @@ __getcwd (char *buf, size_t size)
__USEPORT (CWDIR,
_hurd_canonicalize_directory_name_internal (port,
buf, size));
- if (cwd && cwd[0] != '/')
- {
- /* `cwd' is an unknown root directory. */
- if (buf == NULL)
- free (cwd);
- return __hurd_fail (EGRATUITOUS), NULL;
- }
return cwd;
}
weak_alias (__getcwd, getcwd)
diff --git a/sysdeps/mach/hurd/hp-timing.h b/sysdeps/mach/hurd/hp-timing.h
new file mode 100644
index 0000000000..1246e21958
--- /dev/null
+++ b/sysdeps/mach/hurd/hp-timing.h
@@ -0,0 +1,42 @@
+/* High precision, low overhead timing functions. Generic version.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _HP_TIMING_H
+#define _HP_TIMING_H 1
+
+/* We don't have support for high precision timing for now. */
+
+/* Provide dummy definitions. */
+#define HP_TIMING_AVAIL (0)
+#define HP_SMALL_TIMING_AVAIL (0)
+#define HP_TIMING_INLINE (0)
+typedef int hp_timing_t;
+#define HP_TIMING_ZERO(Var)
+#define HP_TIMING_NOW(var)
+#define HP_TIMING_DIFF_INIT()
+#define HP_TIMING_DIFF(Diff, Start, End)
+#define HP_TIMING_ACCUM(Sum, Diff)
+#define HP_TIMING_ACCUM_NT(Sum, Diff)
+#define HP_TIMING_PRINT(Buf, Len, Val)
+
+/* Since this implementation is not available we tell the user about it. */
+#define HP_TIMING_NONAVAIL 1
+
+#endif /* hp-timing.h */
diff --git a/sysdeps/mach/hurd/i386/bits/sigcontext.h b/sysdeps/mach/hurd/i386/bits/sigcontext.h
index c51a94ef1a..321bbb4804 100644
--- a/sysdeps/mach/hurd/i386/bits/sigcontext.h
+++ b/sysdeps/mach/hurd/i386/bits/sigcontext.h
@@ -95,6 +95,10 @@ struct sigcontext
#define sc_ps sc_efl
+/* The deprecated sigcode values below are passed as an extra, non-portable
+ argument to regular signal handlers. You should use SA_SIGINFO handlers
+ instead, which use the standard POSIX signal codes. */
+
/* Codes for SIGFPE. */
#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
#define FPE_INTDIV_FAULT 0x2 /* integer divide by zero */
diff --git a/sysdeps/mach/hurd/i386/exc2signal.c b/sysdeps/mach/hurd/i386/exc2signal.c
index b67acff08d..b4e35e9040 100644
--- a/sysdeps/mach/hurd/i386/exc2signal.c
+++ b/sysdeps/mach/hurd/i386/exc2signal.c
@@ -23,8 +23,8 @@
/* Translate the Mach exception codes, as received in an `exception_raise' RPC,
into a signal number and signal subcode. */
-void
-_hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+static void
+exception2signal (struct hurd_signal_detail *detail, int *signo, int posix)
{
detail->error = 0;
@@ -36,44 +36,62 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
break;
case EXC_BAD_ACCESS:
- if (detail->exc_code == KERN_INVALID_ADDRESS
- || detail->exc_code == KERN_PROTECTION_FAILURE
- || detail->exc_code == KERN_WRITE_PROTECTION_FAILURE)
- *signo = SIGSEGV;
- else
- *signo = SIGBUS;
- detail->code = detail->exc_subcode;
+ switch (detail->exc_code)
+ {
+ case KERN_INVALID_ADDRESS:
+ case KERN_MEMORY_FAILURE:
+ *signo = SIGSEGV;
+ detail->code = posix ? SEGV_MAPERR : detail->exc_subcode;
+ break;
+
+ case KERN_PROTECTION_FAILURE:
+ case KERN_WRITE_PROTECTION_FAILURE:
+ *signo = SIGSEGV;
+ detail->code = posix ? SEGV_ACCERR : detail->exc_subcode;
+ break;
+
+ default:
+ *signo = SIGBUS;
+ detail->code = 0;
+ break;
+ }
detail->error = detail->exc_code;
break;
case EXC_BAD_INSTRUCTION:
*signo = SIGILL;
- if (detail->exc_code == EXC_I386_INVOP)
- detail->code = ILL_INVOPR_FAULT;
- else if (detail->exc_code == EXC_I386_STKFLT)
- detail->code = ILL_STACK_FAULT;
- else
- detail->code = 0;
+ switch (detail->exc_code)
+ {
+ case EXC_I386_INVOP:
+ detail->code = posix ? ILL_ILLOPC : ILL_INVOPR_FAULT;
+ break;
+
+ case EXC_I386_STKFLT:
+ detail->code = posix ? ILL_BADSTK : ILL_STACK_FAULT;
+ break;
+
+ default:
+ detail->code = 0;
+ break;
+ }
break;
case EXC_ARITHMETIC:
+ *signo = SIGFPE;
switch (detail->exc_code)
{
case EXC_I386_DIV: /* integer divide by zero */
- *signo = SIGFPE;
- detail->code = FPE_INTDIV_FAULT;
+ detail->code = posix ? FPE_INTDIV : FPE_INTDIV_FAULT;
break;
case EXC_I386_INTO: /* integer overflow */
- *signo = SIGFPE;
- detail->code = FPE_INTOVF_TRAP;
+ detail->code = posix ? FPE_INTOVF : FPE_INTOVF_TRAP;
break;
/* These aren't anywhere documented or used in Mach 3.0. */
case EXC_I386_NOEXT:
case EXC_I386_EXTOVR:
default:
- *signo = SIGFPE;
detail->code = 0;
break;
@@ -82,51 +100,43 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
Give an error code corresponding to the first bit set. */
if (detail->exc_subcode & FPS_IE)
{
- *signo = SIGILL;
- detail->code = ILL_FPEOPR_FAULT;
+ /* NB: We used to send SIGILL here but we can't distinguish
+ POSIX vs. legacy with respect to what signal we send. */
+ detail->code = posix ? FPE_FLTINV : 0 /*ILL_FPEOPR_FAULT*/;
}
else if (detail->exc_subcode & FPS_DE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTDNR_FAULT;
+ detail->code = posix ? FPE_FLTUND : FPE_FLTDNR_FAULT;
}
else if (detail->exc_subcode & FPS_ZE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTDIV_FAULT;
+ detail->code = posix ? FPE_FLTDIV : FPE_FLTDIV_FAULT;
}
else if (detail->exc_subcode & FPS_OE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTOVF_FAULT;
+ detail->code = posix ? FPE_FLTOVF : FPE_FLTOVF_FAULT;
}
else if (detail->exc_subcode & FPS_UE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTUND_FAULT;
+ detail->code = posix ? FPE_FLTUND : FPE_FLTUND_FAULT;
}
else if (detail->exc_subcode & FPS_PE)
{
- *signo = SIGFPE;
- detail->code = FPE_FLTINX_FAULT;
+ detail->code = posix ? FPE_FLTRES : FPE_FLTINX_FAULT;
}
else
{
- *signo = SIGFPE;
detail->code = 0;
}
break;
/* These two can only be arithmetic exceptions if we
- are in V86 mode, which sounds like emulation to me.
- (See Mach 3.0 i386/trap.c.) */
+ are in V86 mode. (See Mach 3.0 i386/trap.c.) */
case EXC_I386_EMERR:
- *signo = SIGFPE;
- detail->code = FPE_EMERR_FAULT;
+ detail->code = posix ? 0 : FPE_EMERR_FAULT;
break;
case EXC_I386_BOUND:
- *signo = SIGFPE;
- detail->code = FPE_EMBND_FAULT;
+ detail->code = posix ? FPE_FLTSUB : FPE_EMBND_FAULT;
break;
}
break;
@@ -143,7 +153,7 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
if (detail->exc_code == EXC_I386_BOUND)
{
*signo = SIGFPE;
- detail->code = FPE_SUBRNG_FAULT;
+ detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT;
}
else
{
@@ -154,12 +164,33 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
case EXC_BREAKPOINT:
*signo = SIGTRAP;
- if (detail->exc_code == EXC_I386_SGL)
- detail->code = DBG_SINGLE_TRAP;
- else if (detail->exc_code == EXC_I386_BPT)
- detail->code = DBG_BRKPNT_FAULT;
- else
- detail->code = 0;
+ switch (detail->exc_code)
+ {
+ case EXC_I386_SGL:
+ detail->code = posix ? TRAP_BRKPT : DBG_SINGLE_TRAP;
+ break;
+
+ case EXC_I386_BPT:
+ detail->code = posix ? TRAP_BRKPT : DBG_BRKPNT_FAULT;
+ break;
+
+ default:
+ detail->code = 0;
+ break;
+ }
break;
}
}
+
+void
+_hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+{
+ exception2signal (detail, signo, 1);
+}
+
+void
+_hurd_exception2signal_legacy (struct hurd_signal_detail *detail, int *signo)
+{
+ exception2signal (detail, signo, 0);
+}
+
diff --git a/sysdeps/mach/hurd/i386/getcontext.S b/sysdeps/mach/hurd/i386/getcontext.S
index b456158f21..e71f3bc645 100644
--- a/sysdeps/mach/hurd/i386/getcontext.S
+++ b/sysdeps/mach/hurd/i386/getcontext.S
@@ -1,5 +1,5 @@
/* Save current context.
- Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
index 4a0f5d9e5f..064561a63d 100644
--- a/sysdeps/mach/hurd/i386/init-first.c
+++ b/sysdeps/mach/hurd/i386/init-first.c
@@ -112,9 +112,7 @@ init1 (int argc, char *arg0, ...)
then after the environment pointers there is no Hurd
data block; the argument strings start there. */
if ((void *) d == argv[0])
- {
- return;
- }
+ return;
#ifndef SHARED
__libc_enable_secure = d->flags & EXEC_SECURE;
@@ -168,7 +166,7 @@ init (int *data)
/* If we are the bootstrap task started by the kernel,
then after the environment pointers there is no Hurd
data block; the argument strings start there. */
- if ((void *) d == argv[0])
+ if ((void *) d == argv[0] || !d->phdr)
{
/* With a new enough linker (binutils-2.23 or better),
the magic __ehdr_start symbol will be available and
@@ -192,9 +190,9 @@ init (int *data)
assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0);
}
- /* We need to setup TLS before starting sigthread */
- extern void __pthread_initialize_minimal(void);
- __pthread_initialize_minimal();
+ /* We need to setup TLS before starting the signal thread. */
+ extern void __pthread_initialize_minimal (void);
+ __pthread_initialize_minimal ();
#endif
diff --git a/sysdeps/mach/hurd/i386/makecontext-helper.c b/sysdeps/mach/hurd/i386/makecontext-helper.c
index e604488264..c6fb90ca5a 100644
--- a/sysdeps/mach/hurd/i386/makecontext-helper.c
+++ b/sysdeps/mach/hurd/i386/makecontext-helper.c
@@ -1,5 +1,5 @@
/* Helper for makecontext: handle threadvars.
- Copyright (C) 2013 Free Software Foundation, Inc.
+ Copyright (C) 2013-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/sysdeps/mach/hurd/i386/makecontext.S b/sysdeps/mach/hurd/i386/makecontext.S
index b81403b04f..95ae3411a8 100644
--- a/sysdeps/mach/hurd/i386/makecontext.S
+++ b/sysdeps/mach/hurd/i386/makecontext.S
@@ -1,5 +1,5 @@
/* Create new context.
- Copyright (C) 2001,2002,2005,2007,2008,2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/sysdeps/mach/hurd/i386/setcontext.S b/sysdeps/mach/hurd/i386/setcontext.S
index 2294eb623a..3f38ff2018 100644
--- a/sysdeps/mach/hurd/i386/setcontext.S
+++ b/sysdeps/mach/hurd/i386/setcontext.S
@@ -1,5 +1,5 @@
/* Install given context.
- Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
index 0ef593bb61..8776cca896 100644
--- a/sysdeps/mach/hurd/i386/sigreturn.c
+++ b/sysdeps/mach/hurd/i386/sigreturn.c
@@ -38,7 +38,7 @@ __sigreturn (struct sigcontext *scp)
}
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* Remove the link on the `active resources' chain added by
_hurd_setup_sighandler. Its purpose was to make sure
@@ -50,19 +50,19 @@ __sigreturn (struct sigcontext *scp)
ss->intr_port = scp->sc_intr_port;
/* Check for pending signals that were blocked by the old set. */
- if (ss->pending & ~ss->blocked)
+ if (_hurd_sigstate_pending (ss) & ~ss->blocked)
{
/* There are pending signals that just became unblocked. Wake up the
signal thread to deliver them. But first, squirrel away SCP where
the signal thread will notice it if it runs another handler, and
arrange to have us called over again in the new reality. */
ss->context = scp;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
/* If a pending signal was handled, sig_post never returned.
If it did return, the pending signal didn't run a handler;
proceed as usual. */
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
ss->context = NULL;
}
@@ -73,7 +73,7 @@ __sigreturn (struct sigcontext *scp)
abort ();
}
else
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Destroy the MiG reply port used by the signal handler, and restore the
reply port in use by the thread when interrupted. */
diff --git a/sysdeps/mach/hurd/i386/swapcontext.S b/sysdeps/mach/hurd/i386/swapcontext.S
index fb45b70849..5a35eaa56b 100644
--- a/sysdeps/mach/hurd/i386/swapcontext.S
+++ b/sysdeps/mach/hurd/i386/swapcontext.S
@@ -1,5 +1,5 @@
/* Save current context and install the given one.
- Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/sysdeps/mach/hurd/i386/tls.h b/sysdeps/mach/hurd/i386/tls.h
index 5b48239ce7..00b611e903 100644
--- a/sysdeps/mach/hurd/i386/tls.h
+++ b/sysdeps/mach/hurd/i386/tls.h
@@ -75,6 +75,8 @@ typedef struct
# define __i386_set_gdt(thr, sel, desc) ((void) (thr), (void) (sel), (void) (desc), MIG_BAD_ID)
# endif
+#define __i386_selector_is_ldt(sel) (!!((sel) & 4))
+
# include <errno.h>
# include <assert.h>
@@ -107,6 +109,8 @@ static inline const char * __attribute__ ((unused))
_hurd_tls_init (tcbhead_t *tcb, int secondcall)
{
HURD_TLS_DESC_DECL (desc, tcb);
+ thread_t self = __mach_thread_self ();
+ const char *msg = NULL;
if (!secondcall)
{
@@ -114,25 +118,26 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall)
from the TLS point of view. */
tcb->tcb = tcb;
- /* Cache our thread port. */
- tcb->self = __mach_thread_self ();
-
/* Get the first available selector. */
int sel = -1;
- kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc);
+ kern_return_t err = __i386_set_gdt (self, &sel, desc);
if (err == MIG_BAD_ID)
{
/* Old kernel, use a per-thread LDT. */
sel = 0x27;
- err = __i386_set_ldt (tcb->self, sel, &desc, 1);
+ err = __i386_set_ldt (self, sel, &desc, 1);
assert_perror (err);
if (err)
- return "i386_set_ldt failed";
+ {
+ msg = "i386_set_ldt failed";
+ goto out;
+ }
}
else if (err)
{
assert_perror (err); /* Separate from above with different line #. */
- return "i386_set_gdt failed";
+ msg = "i386_set_gdt failed";
+ goto out;
}
/* Now install the new selector. */
@@ -143,23 +148,31 @@ _hurd_tls_init (tcbhead_t *tcb, int secondcall)
/* Fetch the selector set by the first call. */
int sel;
asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0));
- if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
{
- kern_return_t err = __i386_set_ldt (tcb->self, sel, &desc, 1);
+ kern_return_t err = __i386_set_ldt (self, sel, &desc, 1);
assert_perror (err);
if (err)
- return "i386_set_ldt failed";
+ {
+ msg = "i386_set_ldt failed";
+ goto out;
+ }
}
else
{
- kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc);
+ kern_return_t err = __i386_set_gdt (self, &sel, desc);
assert_perror (err);
if (err)
- return "i386_set_gdt failed";
+ {
+ msg = "i386_set_gdt failed";
+ goto out;
+ }
}
}
- return 0;
+out:
+ __mach_port_deallocate (__mach_task_self (), self);
+ return msg;
}
/* Code to initially initialize the thread pointer. This might need
@@ -216,7 +229,7 @@ _hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state)
kern_return_t err;
unsigned int count = 1;
- if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
err = __i386_get_ldt (orig, sel, 1, &_desc, &count);
else
err = __i386_get_gdt (orig, sel, &desc);
@@ -225,7 +238,7 @@ _hurd_tls_fork (thread_t child, thread_t orig, struct i386_thread_state *state)
if (err)
return err;
- if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
err = __i386_set_ldt (child, sel, &desc, 1);
else
err = __i386_set_gdt (child, &sel, desc);
@@ -249,7 +262,7 @@ _hurd_tls_new (thread_t child, struct i386_thread_state *state, tcbhead_t *tcb)
tcb->tcb = tcb;
tcb->self = child;
- if (__builtin_expect (sel, 0x48) & 4) /* LDT selector */
+ if (__glibc_unlikely (__i386_selector_is_ldt(sel)))
err = __i386_set_ldt (child, sel, &desc, 1);
else
err = __i386_set_gdt (child, &sel, desc);
diff --git a/sysdeps/mach/hurd/i386/tlsdesc.sym b/sysdeps/mach/hurd/i386/tlsdesc.sym
new file mode 100644
index 0000000000..a358f7e325
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/tlsdesc.sym
@@ -0,0 +1,19 @@
+#include <stddef.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <link.h>
+#include <dl-tlsdesc.h>
+
+--
+
+-- We have to override sysdeps/i386/tlsdesc.sym to adapt to our libpthread.
+
+-- Abuse tls.h macros to derive offsets relative to the thread register.
+
+DTV_OFFSET offsetof(tcbhead_t, dtv)
+
+TLSDESC_ARG offsetof(struct tlsdesc, arg)
+
+TLSDESC_GEN_COUNT offsetof(struct tlsdesc_dynamic_arg, gen_count)
+TLSDESC_MODID offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_module)
+TLSDESC_MODOFF offsetof(struct tlsdesc_dynamic_arg, tlsinfo.ti_offset)
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
index 7e0d093b93..0b1f07234b 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -19,13 +19,66 @@
#include <hurd/signal.h>
#include <hurd/userlink.h>
#include <thread_state.h>
+#include <mach/exception.h>
#include <mach/machine/eflags.h>
#include <assert.h>
#include <errno.h>
#include "hurdfault.h"
#include <intr-msg.h>
+#include <sys/ucontext.h>
+/* Fill in a siginfo_t structure for SA_SIGINFO-enabled handlers. */
+static void fill_siginfo (siginfo_t *si, int signo,
+ const struct hurd_signal_detail *detail,
+ const struct machine_thread_all_state *state)
+{
+ si->si_signo = signo;
+ si->si_errno = detail->error;
+ si->si_code = detail->code;
+
+ /* XXX We would need a protocol change for sig_post to include
+ * this information. */
+ si->si_pid = -1;
+ si->si_uid = -1;
+
+ /* Address of the faulting instruction or memory access. */
+ if (detail->exc == EXC_BAD_ACCESS)
+ si->si_addr = (void *) detail->exc_subcode;
+ else
+ si->si_addr = (void *) state->basic.eip;
+
+ /* XXX On SIGCHLD, this should be the exit status of the child
+ * process. We would need a protocol change for the proc server
+ * to send this information along with the signal. */
+ si->si_status = 0;
+
+ si->si_band = 0; /* SIGPOLL is not supported yet. */
+ si->si_value.sival_int = 0; /* sigqueue() is not supported yet. */
+}
+
+/* Fill in a ucontext_t structure SA_SIGINFO-enabled handlers. */
+static void fill_ucontext (ucontext_t *uc, const struct sigcontext *sc)
+{
+ uc->uc_flags = 0;
+ uc->uc_link = NULL;
+ uc->uc_sigmask = sc->sc_mask;
+ uc->uc_stack.ss_sp = (__ptr_t) sc->sc_esp;
+ uc->uc_stack.ss_size = 0;
+ uc->uc_stack.ss_flags = 0;
+
+ /* Registers. */
+ memcpy (&uc->uc_mcontext.gregs[REG_GS], &sc->sc_gs,
+ (REG_TRAPNO - REG_GS) * sizeof (int));
+ uc->uc_mcontext.gregs[REG_TRAPNO] = 0;
+ uc->uc_mcontext.gregs[REG_ERR] = 0;
+ memcpy (&uc->uc_mcontext.gregs[REG_EIP], &sc->sc_eip,
+ (NGREG - REG_EIP) * sizeof (int));
+
+ /* XXX FPU state. */
+ memset (&uc->uc_mcontext.fpregs, 0, sizeof (fpregset_t));
+}
+
struct sigcontext *
_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
int signo, struct hurd_signal_detail *detail,
@@ -38,18 +91,37 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
extern const void _hurd_intr_rpc_msg_in_trap;
extern const void _hurd_intr_rpc_msg_cx_sp;
extern const void _hurd_intr_rpc_msg_sp_restored;
+ struct sigaction *action;
void *volatile sigsp;
struct sigcontext *scp;
struct
{
int signo;
- long int sigcode;
- struct sigcontext *scp; /* Points to ctx, below. */
+ union
+ {
+ /* Extra arguments for traditional signal handlers */
+ struct
+ {
+ long int sigcode;
+ struct sigcontext *scp; /* Points to ctx, below. */
+ } legacy;
+
+ /* Extra arguments for SA_SIGINFO handlers */
+ struct
+ {
+ siginfo_t *siginfop; /* Points to siginfo, below. */
+ ucontext_t *uctxp; /* Points to uctx, below. */
+ } posix;
+ };
void *sigreturn_addr;
void *sigreturn_returns_here;
struct sigcontext *return_scp; /* Same; arg to sigreturn. */
+
+ /* NB: sigreturn assumes link is next to ctx. */
struct sigcontext ctx;
struct hurd_userlink link;
+ ucontext_t ucontext;
+ siginfo_t siginfo;
} *stackframe;
if (ss->context)
@@ -75,7 +147,11 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
interrupted RPC frame. */
state->basic.esp = state->basic.uesp;
- if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ /* XXX what if handler != action->handler (for instance, if a signal
+ * preemptor took over) ? */
+ action = & _hurd_sigstate_actions (ss) [signo];
+
+ if ((action->sa_flags & SA_ONSTACK) &&
!(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK)))
{
sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
@@ -137,15 +213,9 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
= &stackframe->link.thread.next;
ss->active_resources = &stackframe->link;
- /* Set up the arguments for the signal handler. */
- stackframe->signo = signo;
- stackframe->sigcode = detail->code;
- stackframe->scp = stackframe->return_scp = scp = &stackframe->ctx;
- stackframe->sigreturn_addr = &__sigreturn;
- stackframe->sigreturn_returns_here = firewall; /* Crash on return. */
-
/* Set up the sigcontext from the current state of the thread. */
+ scp = &stackframe->ctx;
scp->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0;
/* struct sigcontext is laid out so that starting at sc_gs mimics a
@@ -159,6 +229,35 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
&state->fpu, &scp->sc_i386_float_state,
sizeof (state->fpu));
+ /* Set up the arguments for the signal handler. */
+ stackframe->signo = signo;
+ if (action->sa_flags & SA_SIGINFO)
+ {
+ stackframe->posix.siginfop = &stackframe->siginfo;
+ stackframe->posix.uctxp = &stackframe->ucontext;
+ fill_siginfo (&stackframe->siginfo, signo, detail, state);
+ fill_ucontext (&stackframe->ucontext, scp);
+ }
+ else
+ {
+ if (detail->exc)
+ {
+ int nsigno;
+ _hurd_exception2signal_legacy (detail, &nsigno);
+ assert (nsigno == signo);
+ }
+ else
+ detail->code = 0;
+
+ stackframe->legacy.sigcode = detail->code;
+ stackframe->legacy.scp = &stackframe->ctx;
+ }
+
+ /* Set up the bottom of the stack. */
+ stackframe->sigreturn_addr = &__sigreturn;
+ stackframe->sigreturn_returns_here = firewall; /* Crash on return. */
+ stackframe->return_scp = &stackframe->ctx;
+
_hurdsig_end_catch_fault ();
if (! ok)
diff --git a/sysdeps/mach/hurd/ifaddrs.c b/sysdeps/mach/hurd/ifaddrs.c
new file mode 100644
index 0000000000..d2f8978673
--- /dev/null
+++ b/sysdeps/mach/hurd/ifaddrs.c
@@ -0,0 +1,306 @@
+/* getifaddrs -- get names and addresses of all network interfaces
+ Copyright (C) 2013-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <hurd/lookup.h>
+#include <hurd/fs.h>
+
+/* Create a linked list of `struct ifaddrs' structures, one for each
+ network interface on the host machine. If successful, store the
+ list in *IFAP and return 0. On errors, return -1 and set `errno'. */
+int
+getifaddrs (struct ifaddrs **ifap)
+{
+ /* XXX: Hackish. This assumes pfinet parameter style, and that the same
+ pfinet is on /servers/socket/2 and /servers/socket/26.
+
+ To be replaced by something like a netlink protocol, or fix ifreq into
+ using sockaddr_storage (but break existing compiled programs using it). */
+
+ file_t node;
+ char *argz = 0, *cur;
+ size_t argz_len = 0;
+ unsigned naddrs;
+ const char *ifa_name = NULL;
+ char *addr, *cidr_a;
+ int cidr;
+
+ node = __file_name_lookup (_SERVERS_SOCKET "/2", 0, 0666);
+
+ if (node == MACH_PORT_NULL)
+ return -1;
+
+ __file_get_fs_options (node, &argz, &argz_len);
+
+ __mach_port_deallocate (__mach_task_self (), node);
+
+ /* XXX: Two hardcoded for lo */
+ naddrs = 2;
+
+ for (cur = argz; cur < argz + argz_len; cur = cur + strlen (cur) + 1)
+ {
+ if (!strncmp (cur, "--address=", 10))
+ naddrs++;
+ else if (!strncmp (cur, "--address6=", 11))
+ naddrs++;
+ }
+
+ {
+ struct
+ {
+ struct ifaddrs ia;
+ struct sockaddr_storage addr, netmask, broadaddr;
+ char name[IF_NAMESIZE];
+ } *storage;
+ int i;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ storage = malloc (naddrs * sizeof storage[0]);
+ if (storage == NULL)
+ {
+ __munmap (argz, argz_len);
+ return -1;
+ }
+
+ i = 0;
+
+ /* XXX: Hardcoded lo interface */
+ ifa_name = "lo";
+
+ /* 127.0.0.1/8 */
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin = ((struct sockaddr_in *) &storage[i].addr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin = ((struct sockaddr_in *) &storage[i].netmask);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr = htonl (IN_CLASSA_NET);
+
+ storage[i].ia.ifa_broadaddr = (struct sockaddr *) &storage[i].addr;
+
+ storage[i].ia.ifa_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
+
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+
+ i++;
+
+ /* ::1/128 */
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].addr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, "::1", &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].netmask);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_broadaddr = NULL;
+
+ storage[i].ia.ifa_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING;
+
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+
+ for (cur = argz; cur < argz + argz_len; cur = cur + strlen (cur) + 1)
+ {
+ if (!strncmp (cur, "--interface=", 12))
+ {
+ ifa_name = cur + 12;
+ continue;
+ }
+
+ else if (!strncmp (cur, "--address=", 10))
+ {
+ i++;
+ /* IPv4 address */
+ addr = cur + 10;
+
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin = ((struct sockaddr_in *) &storage[i].addr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ inet_pton (AF_INET, addr, &sin->sin_addr);
+
+ storage[i].ia.ifa_netmask = NULL;
+ storage[i].ia.ifa_broadaddr = NULL;
+
+ storage[i].ia.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+ }
+
+ else if (!strncmp (cur, "--netmask=", 10))
+ {
+ /* IPv4 netmask */
+ addr = cur + 10;
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin = ((struct sockaddr_in *) &storage[i].netmask);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ inet_pton (AF_INET, addr, &sin->sin_addr);
+
+ storage[i].ia.ifa_broadaddr = (struct sockaddr *) &storage[i].broadaddr;
+ sin = ((struct sockaddr_in *) &storage[i].broadaddr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ sin->sin_addr.s_addr =
+ ((struct sockaddr_in *) &storage[i].addr)->sin_addr.s_addr
+ | ~(((struct sockaddr_in *) &storage[i].netmask)->sin_addr.s_addr);
+ }
+
+ else if (!strncmp (cur, "--peer=", 7))
+ {
+ /* IPv4 peer */
+ addr = cur + 7;
+
+ storage[i].ia.ifa_dstaddr = (struct sockaddr *) &storage[i].broadaddr;
+ sin = ((struct sockaddr_in *) &storage[i].broadaddr);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = 0;
+ inet_pton (AF_INET, addr, &sin->sin_addr);
+
+ storage[i].ia.ifa_flags &= ~IFF_BROADCAST;
+ storage[i].ia.ifa_flags |= IFF_POINTOPOINT;
+ }
+
+ else if (!strncmp (cur, "--address6=", 11))
+ {
+ i++;
+ /* IPv6 address */
+ addr = cur + 11;
+ cidr_a = strchr (addr, '/');
+ if (!cidr_a)
+ {
+ /* No CIDR length?! Assume 64. */
+ addr = strdup (addr);
+ cidr = 64;
+ }
+ else
+ {
+ addr = strndup (addr, cidr_a - addr);
+ cidr = atoi (cidr_a + 1);
+ }
+
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifa_name, sizeof (storage[i].name));
+
+ storage[i].ia.ifa_addr = (struct sockaddr *) &storage[i].addr;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].addr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, addr, &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_netmask = (struct sockaddr *) &storage[i].netmask;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].netmask);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ sin6->sin6_addr.s6_addr32[0] = htonl (cidr >= 32 ? 0xffffffffUL : cidr <= 0 ? 0 : ~((1UL << ( 32 - cidr)) - 1));
+ sin6->sin6_addr.s6_addr32[1] = htonl (cidr >= 64 ? 0xffffffffUL : cidr <= 32 ? 0 : ~((1UL << ( 64 - cidr)) - 1));
+ sin6->sin6_addr.s6_addr32[2] = htonl (cidr >= 96 ? 0xffffffffUL : cidr <= 64 ? 0 : ~((1UL << ( 96 - cidr)) - 1));
+ sin6->sin6_addr.s6_addr32[3] = htonl (cidr >= 128 ? 0xffffffffUL : cidr <= 96 ? 0 : ~((1UL << (128 - cidr)) - 1));
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_broadaddr = NULL;
+ storage[i].ia.ifa_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+ free (addr);
+ }
+
+ else if (!strncmp (cur, "--peer6=", 8))
+ {
+ /* IPv6 peer */
+ addr = cur + 8;
+
+ storage[i].ia.ifa_dstaddr = (struct sockaddr *) &storage[i].broadaddr;
+ sin6 = ((struct sockaddr_in6 *) &storage[i].broadaddr);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_port = 0;
+ sin6->sin6_flowinfo = 0;
+ inet_pton (AF_INET6, addr, &sin6->sin6_addr);
+ sin6->sin6_scope_id = 0;
+
+ storage[i].ia.ifa_flags &= ~IFF_BROADCAST;
+ storage[i].ia.ifa_flags |= IFF_POINTOPOINT;
+ }
+ }
+
+ storage[i].ia.ifa_next = NULL;
+
+ *ifap = &storage[0].ia;
+ }
+
+ __munmap (argz, argz_len);
+
+ return 0;
+}
+#ifndef getifaddrs
+libc_hidden_def (getifaddrs)
+#endif
+
+void
+freeifaddrs (struct ifaddrs *ifa)
+{
+ free (ifa);
+}
+libc_hidden_def (freeifaddrs)
diff --git a/sysdeps/mach/hurd/jmp-unwind.c b/sysdeps/mach/hurd/jmp-unwind.c
index 4df4edbf71..558b09b46f 100644
--- a/sysdeps/mach/hurd/jmp-unwind.c
+++ b/sysdeps/mach/hurd/jmp-unwind.c
@@ -49,9 +49,8 @@ _longjmp_unwind (jmp_buf env, int val)
/* All access to SS->active_resources must take place inside a critical
section where signal handlers cannot run. */
- __spin_lock (&ss->lock);
- assert (! __spin_lock_locked (&ss->critical_section_lock));
__spin_lock (&ss->critical_section_lock);
+ __spin_lock (&ss->lock);
/* Remove local signal preemptors being unwound past. */
while (ss->preemptors &&
diff --git a/sysdeps/mach/hurd/kernel-features.h b/sysdeps/mach/hurd/kernel-features.h
index fa4a1d8247..646e506430 100644
--- a/sysdeps/mach/hurd/kernel-features.h
+++ b/sysdeps/mach/hurd/kernel-features.h
@@ -23,3 +23,5 @@
#define __ASSUME_O_CLOEXEC 1
#define __ASSUME_DUP3 1
#define __ASSUME_ACCEPT4 1
+#define __ASSUME_SOCK_CLOEXEC 1
+#define __ASSUME_PIPE2 1
diff --git a/sysdeps/mach/hurd/kill.c b/sysdeps/mach/hurd/kill.c
index 999be3a6a5..dde132db65 100644
--- a/sysdeps/mach/hurd/kill.c
+++ b/sysdeps/mach/hurd/kill.c
@@ -64,7 +64,7 @@ __kill (pid_t pid, int sig)
{
if (msgport != MACH_PORT_NULL)
/* Send a signal message to his message port. */
- return __msg_sig_post (msgport, sig, 0, refport);
+ return __msg_sig_post (msgport, sig, SI_USER, refport);
/* The process has no message port. Perhaps try direct
frobnication of the task. */
diff --git a/sysdeps/mach/hurd/mlock.c b/sysdeps/mach/hurd/mlock.c
index 14c311c061..00e72b0cb6 100644
--- a/sysdeps/mach/hurd/mlock.c
+++ b/sysdeps/mach/hurd/mlock.c
@@ -28,19 +28,20 @@
int
mlock (const void *addr, size_t len)
{
- mach_port_t hostpriv;
+ mach_port_t host;
vm_address_t page;
error_t err;
- err = __get_privileged_ports (&hostpriv, NULL);
+ err = __get_privileged_ports (&host, NULL);
if (err)
- return __hurd_fail (EPERM);
+ host = __mach_host_self();
page = trunc_page ((vm_address_t) addr);
len = round_page ((vm_address_t) addr + len) - page;
- err = __vm_wire (hostpriv, __mach_task_self (), page, len,
- VM_PROT_READ);
- __mach_port_deallocate (__mach_task_self (), hostpriv);
+
+ err = __vm_wire (host, __mach_task_self (), page, len, VM_PROT_READ);
+ if (host != __mach_host_self())
+ __mach_port_deallocate (__mach_task_self (), host);
return err ? __hurd_fail (err) : 0;
}
diff --git a/sysdeps/mach/hurd/mmap.c b/sysdeps/mach/hurd/mmap.c
index 5407ed9b65..c6ddb39765 100644
--- a/sysdeps/mach/hurd/mmap.c
+++ b/sysdeps/mach/hurd/mmap.c
@@ -97,6 +97,13 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
}
switch (prot & (PROT_READ|PROT_WRITE))
{
+ /* Although it apparently doesn't make sense to map a file with
+ protection set to PROT_NONE, it is actually sometimes done.
+ In particular, that's how localedef reserves some space for
+ the locale archive file, the rationale being that some
+ implementations take into account whether the mapping is
+ anonymous or not when selecting addresses. */
+ case PROT_NONE:
case PROT_READ:
memobj = robj;
if (wobj != MACH_PORT_NULL)
@@ -126,8 +133,8 @@ __mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
return (__ptr_t) (long int) __hurd_fail (EACCES);
}
break;
- default: /* impossible */
- return 0;
+ default:
+ __builtin_unreachable ();
}
break;
/* XXX handle MAP_NOEXTEND */
diff --git a/sysdeps/mach/hurd/mmap64.c b/sysdeps/mach/hurd/mmap64.c
new file mode 100644
index 0000000000..24e1e3eb80
--- /dev/null
+++ b/sysdeps/mach/hurd/mmap64.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1997-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+
+/* Map addresses starting near ADDR and extending for LEN bytes. From
+ OFFSET into the file FD describes according to PROT and FLAGS. If ADDR
+ is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
+ set in FLAGS, the mapping will be at ADDR exactly (which must be
+ page-aligned); otherwise the system chooses a convenient nearby address.
+ The return value is the actual mapping address chosen or MAP_FAILED
+ for errors (in which case `errno' is set). A successful `mmap' call
+ deallocates any previous mapping for the affected region. */
+
+__ptr_t
+__mmap64 (__ptr_t addr, size_t len, int prot, int flags, int fd,
+ __off64_t offset)
+{
+ vm_offset_t small_offset = (vm_offset_t) offset;
+
+ if (small_offset != offset)
+ {
+ /* We cannot do this since the offset is too large. */
+ __set_errno (EOVERFLOW);
+ return MAP_FAILED;
+ }
+
+ return __mmap (addr, len, prot, flags, fd, small_offset);
+}
+
+weak_alias (__mmap64, mmap64)
diff --git a/sysdeps/mach/hurd/munlock.c b/sysdeps/mach/hurd/munlock.c
index c03af90cb8..b31aaa0c03 100644
--- a/sysdeps/mach/hurd/munlock.c
+++ b/sysdeps/mach/hurd/munlock.c
@@ -27,18 +27,20 @@
int
munlock (const void *addr, size_t len)
{
- mach_port_t hostpriv;
+ mach_port_t host;
vm_address_t page;
error_t err;
- err = __get_privileged_ports (&hostpriv, NULL);
+ err = __get_privileged_ports (&host, NULL);
if (err)
- return __hurd_fail (EPERM);
+ host = __mach_host_self();
page = trunc_page ((vm_address_t) addr);
len = round_page ((vm_address_t) addr + len) - page;
- err = __vm_wire (hostpriv, __mach_task_self (), page, len, VM_PROT_NONE);
- __mach_port_deallocate (__mach_task_self (), hostpriv);
+
+ err = __vm_wire (host, __mach_task_self (), page, len, VM_PROT_NONE);
+ if (host != __mach_host_self())
+ __mach_port_deallocate (__mach_task_self (), host);
return err ? __hurd_fail (err) : 0;
}
diff --git a/sysdeps/mach/hurd/pipe.c b/sysdeps/mach/hurd/pipe.c
index 8bc446e7f2..44cea4f6af 100644
--- a/sysdeps/mach/hurd/pipe.c
+++ b/sysdeps/mach/hurd/pipe.c
@@ -15,9 +15,6 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <errno.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
#include <unistd.h>
/* Create a one-way communication channel (pipe).
@@ -28,23 +25,7 @@
int
__pipe (int fds[2])
{
- int save_errno = errno;
- int result;
-
- /* The magic S_IFIFO protocol tells the pflocal server to create
- sockets which report themselves as FIFOs, as POSIX requires for
- pipes. */
- result = __socketpair (PF_LOCAL, SOCK_STREAM, S_IFIFO, fds);
- if (result == -1 && errno == EPROTONOSUPPORT)
- {
- /* We contacted an "old" pflocal server that doesn't support the
- magic S_IFIFO protocol.
- FIXME: Remove this junk somewhere in the future. */
- __set_errno (save_errno);
- return __socketpair (PF_LOCAL, SOCK_STREAM, 0, fds);
- }
-
- return result;
+ return __pipe2 (fds, 0);
}
libc_hidden_def (__pipe)
weak_alias (__pipe, pipe)
diff --git a/sysdeps/mach/hurd/pipe2.c b/sysdeps/mach/hurd/pipe2.c
new file mode 100644
index 0000000000..8086d64724
--- /dev/null
+++ b/sysdeps/mach/hurd/pipe2.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1992-2015 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <fcntl-internal.h>
+#include <hurd.h>
+
+/* Create a one-way communication channel (pipe).
+ Actually the channel is two-way on the Hurd.
+ If successful, two file descriptors are stored in FDS;
+ bytes written on FDS[1] can be read from FDS[0].
+ Apply FLAGS to the new file descriptors.
+ Returns 0 if successful, -1 if not. */
+int
+__pipe2 (int fds[2], int flags)
+{
+ int save_errno = errno;
+ int result;
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
+
+ flags = o_to_sock_flags (flags);
+
+ /* The magic S_IFIFO protocol tells the pflocal server to create
+ sockets which report themselves as FIFOs, as POSIX requires for
+ pipes. */
+ result = __socketpair (PF_LOCAL, SOCK_STREAM | flags, S_IFIFO, fds);
+ if (result == -1 && errno == EPROTONOSUPPORT)
+ {
+ /* We contacted an "old" pflocal server that doesn't support the
+ magic S_IFIFO protocol.
+ FIXME: Remove this junk somewhere in the future. */
+ __set_errno (save_errno);
+ return __socketpair (PF_LOCAL, SOCK_STREAM | flags, 0, fds);
+ }
+
+ return result;
+}
+weak_alias (__pipe2, pipe2)
diff --git a/sysdeps/mach/hurd/profil.c b/sysdeps/mach/hurd/profil.c
index 0422867b98..dbedeb22a2 100644
--- a/sysdeps/mach/hurd/profil.c
+++ b/sysdeps/mach/hurd/profil.c
@@ -69,7 +69,7 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
err = __mach_setup_thread (__mach_task_self (), profile_thread,
&profile_waiter, NULL, NULL);
if (! err)
- err = __mach_setup_tls(profile_thread);
+ err = __mach_setup_tls (profile_thread);
}
else
err = 0;
diff --git a/sysdeps/mach/hurd/ptsname.c b/sysdeps/mach/hurd/ptsname.c
index bc39cef573..55eb4ef84f 100644
--- a/sysdeps/mach/hurd/ptsname.c
+++ b/sysdeps/mach/hurd/ptsname.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <string.h>
+#include <sys/stat.h>
#include <hurd.h>
#include <hurd/fd.h>
#include <hurd/term.h>
@@ -38,11 +39,10 @@ ptsname (int fd)
}
-/* Store at most BUFLEN characters of the pathname of the slave pseudo
- terminal associated with the master FD is open on in BUF.
- Return 0 on success, otherwise an error number. */
+/* We can't make use of STP, but do it that way for conformity with the Linux
+ version... */
int
-__ptsname_r (int fd, char *buf, size_t buflen)
+__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp)
{
string_t peername;
size_t len;
@@ -61,4 +61,14 @@ __ptsname_r (int fd, char *buf, size_t buflen)
memcpy (buf, peername, len);
return 0;
}
+
+
+/* Store at most BUFLEN characters of the pathname of the slave pseudo
+ terminal associated with the master FD is open on in BUF.
+ Return 0 on success, otherwise an error number. */
+int
+__ptsname_r (int fd, char *buf, size_t buflen)
+{
+ return __ptsname_internal (fd, buf, buflen, NULL);
+}
weak_alias (__ptsname_r, ptsname_r)
diff --git a/sysdeps/mach/hurd/reboot.c b/sysdeps/mach/hurd/reboot.c
index 83187d46e0..7844ecbbd9 100644
--- a/sysdeps/mach/hurd/reboot.c
+++ b/sysdeps/mach/hurd/reboot.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <unistd.h>
#include <hurd.h>
+#include <hurd/paths.h>
#include <hurd/startup.h>
#include <sys/reboot.h>
@@ -33,8 +34,8 @@ reboot (int howto)
if (err)
return __hurd_fail (EPERM);
- err = __USEPORT (PROC, __proc_getmsgport (port, 1, &init));
- if (!err)
+ init = __file_name_lookup (_SERVERS_STARTUP, 0, 0);
+ if (init != MACH_PORT_NULL)
{
err = __startup_reboot (init, hostpriv, howto);
__mach_port_deallocate (__mach_task_self (), init);
diff --git a/sysdeps/mach/hurd/recvmsg.c b/sysdeps/mach/hurd/recvmsg.c
index ae45478e12..71ba20e0f6 100644
--- a/sysdeps/mach/hurd/recvmsg.c
+++ b/sysdeps/mach/hurd/recvmsg.c
@@ -23,6 +23,123 @@
#include <hurd/fd.h>
#include <hurd/socket.h>
+static unsigned
+contains_uid (unsigned int n, __uid_t uids[n], __uid_t uid)
+{
+ unsigned i;
+
+ for (i = 0; i < n; i++)
+ if (uids[i] == uid)
+ return 1;
+ return 0;
+}
+
+static unsigned
+contains_gid (unsigned int n, __gid_t gids[n], __gid_t gid)
+{
+ unsigned i;
+
+ for (i = 0; i < n; i++)
+ if (gids[i] == gid)
+ return 1;
+ return 0;
+}
+
+/* Check the passed credentials. */
+static error_t
+check_auth (mach_port_t rendezvous,
+ __pid_t pid,
+ __uid_t uid, __uid_t euid,
+ __gid_t gid,
+ int ngroups, __gid_t groups[ngroups])
+{
+ error_t err;
+ size_t neuids = CMGROUP_MAX, nauids = CMGROUP_MAX;
+ size_t negids = CMGROUP_MAX, nagids = CMGROUP_MAX;
+ __uid_t euids_buf[neuids], auids_buf[nauids];
+ __gid_t egids_buf[negids], agids_buf[nagids];
+ __uid_t *euids = euids_buf, *auids = auids_buf;
+ __gid_t *egids = egids_buf, *agids = agids_buf;
+
+ struct procinfo *pi = NULL;
+ mach_msg_type_number_t pi_size = 0;
+ int flags = PI_FETCH_TASKINFO;
+ char *tw = NULL;
+ size_t tw_size = 0;
+ unsigned i;
+
+ err = mach_port_mod_refs (mach_task_self (), rendezvous,
+ MACH_PORT_RIGHT_SEND, 1);
+ if (err)
+ goto out;
+
+ do
+ err = __USEPORT
+ (AUTH, __auth_server_authenticate (port,
+ rendezvous, MACH_MSG_TYPE_COPY_SEND,
+ MACH_PORT_NULL, 0,
+ &euids, &neuids, &auids, &nauids,
+ &egids, &negids, &agids, &nagids));
+ while (err == EINTR);
+ if (err)
+ goto out;
+
+ /* Check whether this process indeed has these IDs */
+ if ( !contains_uid (neuids, euids, uid)
+ && !contains_uid (nauids, auids, uid)
+ || !contains_uid (neuids, euids, euid)
+ && !contains_uid (nauids, auids, euid)
+ || !contains_gid (negids, egids, gid)
+ && !contains_gid (nagids, agids, gid)
+ )
+ {
+ err = EIO;
+ goto out;
+ }
+
+ /* Check groups */
+ for (i = 0; i < ngroups; i++)
+ if ( !contains_gid (negids, egids, groups[i])
+ && !contains_gid (nagids, agids, groups[i]))
+ {
+ err = EIO;
+ goto out;
+ }
+
+ /* Check PID */
+ /* XXX: Using proc_getprocinfo until
+ proc_user_authenticate proc_server_authenticate is implemented
+ */
+ /* Get procinfo to check the owner. Maybe he faked the pid, but at least we
+ check the owner. */
+ err = __USEPORT (PROC, __proc_getprocinfo (port, pid, &flags,
+ (procinfo_t *)&pi,
+ &pi_size, &tw, &tw_size));
+ if (err)
+ goto out;
+
+ if ( !contains_uid (neuids, euids, pi->owner)
+ && !contains_uid (nauids, auids, pi->owner))
+ err = EIO;
+
+out:
+ mach_port_deallocate (mach_task_self (), rendezvous);
+ if (euids != euids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) euids, neuids * sizeof(uid_t));
+ if (auids != auids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) auids, nauids * sizeof(uid_t));
+ if (egids != egids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) egids, negids * sizeof(uid_t));
+ if (agids != agids_buf)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) agids, nagids * sizeof(uid_t));
+ if (tw_size)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) tw, tw_size);
+ if (pi_size)
+ __vm_deallocate (__mach_task_self(), (vm_address_t) pi, pi_size);
+
+ return err;
+}
+
/* Receive a message as described by MESSAGE from socket FD.
Returns the number of bytes read or -1 for errors. */
ssize_t
@@ -32,13 +149,33 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
addr_port_t aport;
char *data = NULL;
mach_msg_type_number_t len = 0;
- mach_port_t *ports;
+ mach_port_t *ports, *newports = NULL;
mach_msg_type_number_t nports = 0;
+ struct cmsghdr *cmsg;
char *cdata = NULL;
mach_msg_type_number_t clen = 0;
size_t amount;
char *buf;
- int i;
+ int nfds, *opened_fds = NULL;
+ int i, ii, j;
+
+ error_t reauthenticate (mach_port_t port, mach_port_t *result)
+ {
+ error_t err;
+ mach_port_t ref;
+ ref = __mach_reply_port ();
+ do
+ err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
+ while (err == EINTR);
+ if (!err)
+ do
+ err = __USEPORT (AUTH, __auth_user_authenticate (port,
+ ref, MACH_MSG_TYPE_MAKE_SEND,
+ result));
+ while (err == EINTR);
+ __mach_port_destroy (__mach_task_self (), ref);
+ return err;
+ }
/* Find the total number of bytes to be read. */
amount = 0;
@@ -135,9 +272,96 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
message->msg_controllen = clen;
memcpy (message->msg_control, cdata, message->msg_controllen);
+ if (nports > 0)
+ {
+ newports = __alloca (nports * sizeof (mach_port_t));
+ opened_fds = __alloca (nports * sizeof (int));
+ }
+
+ /* This counts how many ports we processed completely. */
+ i = 0;
+
+ for (cmsg = CMSG_FIRSTHDR (message);
+ cmsg;
+ cmsg = CMSG_NXTHDR (message, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ /* SCM_RIGHTS support. */
+ /* The fd's flags are passed in the control data. */
+ int *fds = (int *) CMSG_DATA (cmsg);
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+
+ for (j = 0; j < nfds; j++)
+ {
+ err = reauthenticate (ports[i], &newports[i]);
+ if (err)
+ goto cleanup;
+ fds[j] = opened_fds[i] = _hurd_intern_fd (newports[i], fds[j], 0);
+ if (fds[j] == -1)
+ {
+ err = errno;
+ __mach_port_deallocate (__mach_task_self (), newports[i]);
+ goto cleanup;
+ }
+ i++;
+ }
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ {
+ /* SCM_CREDS support. */
+ /* Check received credentials */
+ struct cmsgcred *ucredp = (struct cmsgcred *) CMSG_DATA(cmsg);
+
+ err = check_auth (ports[i],
+ ucredp->cmcred_pid,
+ ucredp->cmcred_uid, ucredp->cmcred_euid,
+ ucredp->cmcred_gid,
+ ucredp->cmcred_ngroups, ucredp->cmcred_groups);
+ if (err)
+ goto cleanup;
+ i++;
+ }
+ }
+
+ for (i = 0; i < nports; i++)
+ __mach_port_deallocate (mach_task_self (), ports[i]);
+
__vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
return (buf - data);
+
+cleanup:
+ /* Clean up all the file descriptors from port 0 to i-1. */
+ if (nports > 0)
+ {
+ ii = 0;
+ j = 0;
+ for (cmsg = CMSG_FIRSTHDR (message);
+ cmsg;
+ cmsg = CMSG_NXTHDR (message, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+ for (j = 0; j < nfds && ii < i; j++, ii++)
+ {
+ _hurd_fd_close (_hurd_fd_get (opened_fds[ii]));
+ __mach_port_deallocate (__mach_task_self (), newports[ii]);
+ __mach_port_deallocate (__mach_task_self (), ports[ii]);
+ }
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ {
+ __mach_port_deallocate (__mach_task_self (), ports[ii]);
+ }
+ }
+ }
+
+ __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
+ return __hurd_fail (err);
}
weak_alias (__libc_recvmsg, recvmsg)
diff --git a/sysdeps/mach/hurd/sendmsg.c b/sysdeps/mach/hurd/sendmsg.c
index 2ef6a0fa09..4774a5c3ee 100644
--- a/sysdeps/mach/hurd/sendmsg.c
+++ b/sysdeps/mach/hurd/sendmsg.c
@@ -24,6 +24,7 @@
#include <hurd/fd.h>
#include <hurd/ifsock.h>
#include <hurd/socket.h>
+#include "hurd/hurdsocket.h"
/* Send a message described MESSAGE on socket FD.
Returns the number of bytes sent, or -1 for errors. */
@@ -31,6 +32,10 @@ ssize_t
__libc_sendmsg (int fd, const struct msghdr *message, int flags)
{
error_t err = 0;
+ struct cmsghdr *cmsg;
+ mach_port_t *ports = NULL;
+ mach_msg_type_number_t nports = 0;
+ int *fds, nfds;
struct sockaddr_un *addr = message->msg_name;
socklen_t addr_len = message->msg_namelen;
addr_port_t aport = MACH_PORT_NULL;
@@ -43,6 +48,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
mach_msg_type_number_t len;
mach_msg_type_number_t amount;
int dealloc = 0;
+ int socketrpc = 0;
int i;
/* Find the total number of bytes to be written. */
@@ -100,18 +106,94 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
}
}
+ /* Allocate enough room for ports. */
+ cmsg = CMSG_FIRSTHDR (message);
+ for (; cmsg; cmsg = CMSG_NXTHDR (message, cmsg))
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ nports += (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ nports++;
+
+ if (nports)
+ ports = __alloca (nports * sizeof (mach_port_t));
+
+ nports = 0;
+ for (cmsg = CMSG_FIRSTHDR (message);
+ cmsg;
+ cmsg = CMSG_NXTHDR (message, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ /* SCM_RIGHTS support: send FDs. */
+ fds = (int *) CMSG_DATA (cmsg);
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
+ / sizeof (int);
+
+ for (i = 0; i < nfds; i++)
+ {
+ err = HURD_DPORT_USE
+ (fds[i],
+ ({
+ err = __io_restrict_auth (port, &ports[nports],
+ 0, 0, 0, 0);
+ if (! err)
+ nports++;
+ /* We pass the flags in the control data. */
+ fds[i] = descriptor->flags;
+ err;
+ }));
+
+ if (err)
+ goto out;
+ }
+ }
+ else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDS)
+ {
+ /* SCM_CREDS support: send credentials. */
+ mach_port_t rendezvous = __mach_reply_port (), reply;
+ struct cmsgcred *ucredp;
+
+ err = mach_port_insert_right (mach_task_self (), rendezvous,
+ rendezvous, MACH_MSG_TYPE_MAKE_SEND);
+ ports[nports++] = rendezvous;
+ if (err)
+ goto out;
+
+ ucredp = (struct cmsgcred *) CMSG_DATA(cmsg);
+ /* Fill in credentials data */
+ ucredp->cmcred_pid = __getpid();
+ ucredp->cmcred_uid = __getuid();
+ ucredp->cmcred_euid = __geteuid();
+ ucredp->cmcred_gid = __getgid();
+ ucredp->cmcred_ngroups =
+ __getgroups (sizeof (ucredp->cmcred_groups) / sizeof (gid_t),
+ ucredp->cmcred_groups);
+
+ /* And make auth server authenticate us. */
+ reply = __mach_reply_port();
+ err = __USEPORT
+ (AUTH, __auth_user_authenticate_request (port,
+ reply, MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ rendezvous, MACH_MSG_TYPE_MAKE_SEND));
+ mach_port_deallocate (__mach_task_self (), reply);
+ if (err)
+ goto out;
+ }
+ }
+
if (addr)
{
if (addr->sun_family == AF_LOCAL)
{
+ char *name = _hurd_sun_path_dupa (addr, addr_len);
/* For the local domain, we must look up the name as a file
and talk to it with the ifsock protocol. */
- file_t file = __file_name_lookup (addr->sun_path, 0, 0);
+ file_t file = __file_name_lookup (name, 0, 0);
if (file == MACH_PORT_NULL)
{
- if (dealloc)
- __vm_deallocate (__mach_task_self (), data.addr, len);
- return -1;
+ err = errno;
+ goto out;
}
err = __ifsock_getsockaddr (file, &aport);
__mach_port_deallocate (__mach_task_self (), file);
@@ -119,11 +201,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
/* The file did not grok the ifsock protocol. */
err = ENOTSOCK;
if (err)
- {
- if (dealloc)
- __vm_deallocate (__mach_task_self (), data.addr, len);
- return __hurd_fail (err);
- }
+ goto out;
}
else
err = EIEIO;
@@ -142,8 +220,9 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
/* Send the data. */
err = __socket_send (port, aport,
flags, data.ptr, len,
- NULL,
- MACH_MSG_TYPE_COPY_SEND, 0,
+ ports,
+ MACH_MSG_TYPE_COPY_SEND,
+ nports,
message->msg_control,
message->msg_controllen,
&amount);
@@ -152,11 +231,19 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
}
err;
}));
+ socketrpc = 1;
+
+ out:
+ for (i = 0; i < nports; i++)
+ __mach_port_deallocate (__mach_task_self (), ports[i]);
if (dealloc)
__vm_deallocate (__mach_task_self (), data.addr, len);
- return err ? __hurd_sockfail (fd, flags, err) : amount;
+ if (socketrpc)
+ return err ? __hurd_sockfail (fd, flags, err) : amount;
+ else
+ return __hurd_fail (err);
}
weak_alias (__libc_sendmsg, sendmsg)
diff --git a/sysdeps/mach/hurd/sendto.c b/sysdeps/mach/hurd/sendto.c
index 477b4aaa5d..b9f26b6886 100644
--- a/sysdeps/mach/hurd/sendto.c
+++ b/sysdeps/mach/hurd/sendto.c
@@ -22,6 +22,7 @@
#include <hurd/fd.h>
#include <hurd/ifsock.h>
#include <hurd/socket.h>
+#include "hurd/hurdsocket.h"
/* Send N bytes of BUF on socket FD to peer at address ADDR (which is
ADDR_LEN bytes long). Returns the number sent, or -1 for errors. */
@@ -47,9 +48,10 @@ __sendto (int fd,
if (addr->sun_family == AF_LOCAL)
{
+ char *name = _hurd_sun_path_dupa (addr, addr_len);
/* For the local domain, we must look up the name as a file and talk
to it with the ifsock protocol. */
- file_t file = __file_name_lookup (addr->sun_path, 0, 0);
+ file_t file = __file_name_lookup (name, 0, 0);
if (file == MACH_PORT_NULL)
return errno;
err_port = __ifsock_getsockaddr (file, aport);
diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c
index 8d77d1d345..5294b46787 100644
--- a/sysdeps/mach/hurd/setitimer.c
+++ b/sysdeps/mach/hurd/setitimer.c
@@ -103,7 +103,7 @@ timer_thread (void)
__msg_sig_post_request (_hurd_msgport,
_hurd_itimer_port,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
- SIGALRM, 0, __mach_task_self ());
+ SIGALRM, SI_TIMER, __mach_task_self ());
break;
case MACH_RCV_INTERRUPTED:
@@ -128,7 +128,8 @@ timer_thread (void)
/* Forward declaration. */
static int setitimer_locked (const struct itimerval *new,
- struct itimerval *old, void *crit);
+ struct itimerval *old, void *crit,
+ int hurd_siglocked);
static sighandler_t
restart_itimer (struct hurd_signal_preemptor *preemptor,
@@ -142,7 +143,7 @@ restart_itimer (struct hurd_signal_preemptor *preemptor,
/* Either reload or disable the itimer. */
__spin_lock (&_hurd_itimer_lock);
it.it_value = it.it_interval = _hurd_itimerval.it_interval;
- setitimer_locked (&it, NULL, NULL);
+ setitimer_locked (&it, NULL, NULL, 1);
/* Continue with normal delivery (or hold, etc.) of SIGALRM. */
return SIG_ERR;
@@ -154,7 +155,7 @@ restart_itimer (struct hurd_signal_preemptor *preemptor,
static int
setitimer_locked (const struct itimerval *new, struct itimerval *old,
- void *crit)
+ void *crit, int hurd_siglocked)
{
struct itimerval newval;
struct timeval now, remaining, elapsed;
@@ -192,16 +193,19 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
run `restart_itimer' each time a SIGALRM would arrive. */
static struct hurd_signal_preemptor preemptor =
{
- __sigmask (SIGALRM), 0, 0,
+ __sigmask (SIGALRM), SI_TIMER, SI_TIMER,
&restart_itimer,
};
- __mutex_lock (&_hurd_siglock);
+ if (!hurd_siglocked)
+ __mutex_lock (&_hurd_siglock);
if (! preemptor.next && _hurdsig_preemptors != &preemptor)
{
preemptor.next = _hurdsig_preemptors;
_hurdsig_preemptors = &preemptor;
+ _hurdsig_preempted_set |= preemptor.signals;
}
- __mutex_unlock (&_hurd_siglock);
+ if (!hurd_siglocked)
+ __mutex_unlock (&_hurd_siglock);
if (_hurd_itimer_port == MACH_PORT_NULL)
{
@@ -226,7 +230,7 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
&timer_thread,
&_hurd_itimer_thread_stack_base,
&_hurd_itimer_thread_stack_size))
- || (err = __mach_setup_tls(_hurd_itimer_thread)))
+ || (err = __mach_setup_tls (_hurd_itimer_thread)))
{
__thread_terminate (_hurd_itimer_thread);
_hurd_itimer_thread = MACH_PORT_NULL;
@@ -349,7 +353,7 @@ __setitimer (enum __itimer_which which, const struct itimerval *new,
crit = _hurd_critical_section_lock ();
__spin_lock (&_hurd_itimer_lock);
- return setitimer_locked (new, old, crit);
+ return setitimer_locked (new, old, crit, 0);
}
static void
@@ -364,7 +368,7 @@ fork_itimer (void)
it = _hurd_itimerval;
it.it_value = it.it_interval;
- setitimer_locked (&it, NULL, NULL);
+ setitimer_locked (&it, NULL, NULL, 0);
(void) &fork_itimer; /* Avoid gcc optimizing out the function. */
}
diff --git a/sysdeps/mach/hurd/shmat.c b/sysdeps/mach/hurd/shmat.c
new file mode 100644
index 0000000000..6bc88705b8
--- /dev/null
+++ b/sysdeps/mach/hurd/shmat.c
@@ -0,0 +1,81 @@
+/* SysV shmat for Hurd.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <utime.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "sysvshm.h"
+
+/* Attach the shared memory segment associated with SHMID to the data
+ segment of the calling process. SHMADDR and SHMFLG determine how
+ and where the segment is attached. */
+void *
+__shmat (int shmid, const void *shmaddr, int shmflg)
+{
+ error_t err;
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
+ int fd;
+ void *addr;
+ struct stat statbuf;
+ int res;
+
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, shmid);
+ fd = __open (filename, (shmflg & SHM_RDONLY) ? O_RDONLY : O_RDWR);
+ if (fd < 0)
+ {
+ if (errno == ENOENT)
+ errno = EINVAL;
+ return (void *) -1;
+ }
+
+ res = __fstat (fd, &statbuf);
+ if (res < 0)
+ {
+ err = errno;
+ __close (fd);
+ errno = err;
+ return (void *) -1;
+ }
+
+ addr = __mmap ((void *) shmaddr, statbuf.st_size,
+ PROT_READ | ((shmflg & SHM_RDONLY) ? 0 : PROT_WRITE),
+ MAP_SHARED, fd, 0);
+ __close (fd);
+ if (addr == MAP_FAILED)
+ return (void *) -1;
+
+ err = __sysvshm_add (addr, statbuf.st_size);
+ if (err)
+ {
+ munmap (addr, statbuf.st_size);
+ errno = err;
+ return (void *) -1;
+ }
+
+ return addr;
+}
+
+weak_alias(__shmat, shmat)
diff --git a/sysdeps/mach/hurd/shmctl.c b/sysdeps/mach/hurd/shmctl.c
new file mode 100644
index 0000000000..a991a0c8de
--- /dev/null
+++ b/sysdeps/mach/hurd/shmctl.c
@@ -0,0 +1,132 @@
+/* SysV shmctl for Hurd.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "sysvshm.h"
+
+/* Provide operations to control shared memory segments. */
+int
+__shmctl (int id, int cmd, struct shmid_ds *buf)
+{
+ error_t err = 0;
+ int fd;
+ int res;
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
+ struct stat statbuf;
+
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, id);
+ /* SysV requires read access for IPC_STAT. */
+ fd = __open (filename, O_NORW);
+ if (fd < 0)
+ {
+ if (errno == ENOENT)
+ errno = EINVAL;
+ return -1;
+ }
+
+ res = __fstat (fd, &statbuf);
+ if (res < 0)
+ {
+ err = errno;
+ __close (fd);
+ errno = err;
+ return -1;
+ }
+
+ switch (cmd)
+ {
+ case IPC_STAT:
+
+ buf->shm_perm.__key = id;
+ buf->shm_perm.uid = statbuf.st_uid;
+ buf->shm_perm.gid = statbuf.st_gid;
+
+ /* We do not support the creator. */
+ buf->shm_perm.cuid = statbuf.st_uid;
+ buf->shm_perm.cgid = statbuf.st_gid;
+
+ /* We just want the protection bits. */
+ buf->shm_perm.mode = statbuf.st_mode & 0777;
+ /* Hopeless. We do not support a sequence number. */
+ buf->shm_perm.__seq = statbuf.st_ino;
+ buf->shm_segsz = statbuf.st_size;
+
+ /* Hopeless. We do not support any of these. */
+ buf->shm_atime = statbuf.st_atime;
+ buf->shm_dtime = statbuf.st_mtime;
+ /* Well, this comes at least close. */
+ buf->shm_ctime = statbuf.st_ctime;
+
+ /* We do not support the PID. */
+ buf->shm_cpid = 0;
+ buf->shm_lpid = 0;
+
+ if (statbuf.st_mode & S_IMMAP0)
+ buf->shm_nattch = 0;
+ else
+ /* 42 is the answer. Of course this is bogus, but for most
+ applications, this should be fine. */
+ buf->shm_nattch = 42;
+
+ break;
+
+ case IPC_SET:
+ if (statbuf.st_uid != buf->shm_perm.uid
+ || statbuf.st_gid != buf->shm_perm.gid)
+ {
+ res = __fchown (fd,
+ (statbuf.st_uid != buf->shm_perm.uid)
+ ? buf->shm_perm.uid : -1,
+ (statbuf.st_gid != buf->shm_perm.gid)
+ ? buf->shm_perm.gid : -1);
+ if (res < 0)
+ err = errno;
+ }
+
+ if (!err && statbuf.st_mode & 0777 != buf->shm_perm.mode & 0777)
+ {
+ res = __fchmod (fd, (statbuf.st_mode & ~0777)
+ | (buf->shm_perm.mode & 0777));
+ if (res < 0)
+ err = errno;
+ }
+ break;
+
+ case IPC_RMID:
+ res = __unlink (filename);
+ /* FIXME: Check error (mapping ENOENT to EINVAL). */
+ break;
+
+ default:
+ err = EINVAL;
+ }
+
+ __close (fd);
+ errno = err;
+ return err ? -1 : 0;
+}
+
+weak_alias(__shmctl, shmctl)
diff --git a/sysdeps/mach/hurd/shmdt.c b/sysdeps/mach/hurd/shmdt.c
new file mode 100644
index 0000000000..988fab8ee6
--- /dev/null
+++ b/sysdeps/mach/hurd/shmdt.c
@@ -0,0 +1,51 @@
+/* SysV shmdt for Hurd.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include "sysvshm.h"
+
+/* Detach shared memory segment starting at address specified by
+ SHMADDR from the caller's data segment. */
+int
+__shmdt (const void *shmaddr)
+{
+ error_t err;
+ size_t size;
+
+ err = __sysvshm_remove ((void *) shmaddr, &size);
+ if (err)
+ {
+ errno = err;
+ return -1;
+ }
+
+ __munmap ((void *) shmaddr, size);
+ return 0;
+}
+
+weak_alias(__shmdt, shmdt)
diff --git a/sysdeps/mach/hurd/shmget.c b/sysdeps/mach/hurd/shmget.c
new file mode 100644
index 0000000000..2065b41989
--- /dev/null
+++ b/sysdeps/mach/hurd/shmget.c
@@ -0,0 +1,242 @@
+/* SysV shmget for Hurd.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <hurd/fd.h>
+
+#include "sysvshm.h"
+
+/* Create a new shared memory segment file without linking it into the
+ filesystem. Return the directory and file ports in R_DIR and R_FILE. */
+static error_t
+create_shm_file (size_t size, int flags, file_t *r_dir, file_t *r_file)
+{
+ error_t err;
+ file_t dir;
+ file_t file;
+
+ flags &= 0777;
+
+ /* Get a port to the directory that will contain the file. */
+ dir = __file_name_lookup (SHM_DIR, 0, 0);
+ if (dir == MACH_PORT_NULL)
+ return errno;
+
+ /* Create an unnamed file in the directory. */
+ err = __dir_mkfile (dir, O_RDWR, flags, &file);
+ if (err)
+ {
+ __mach_port_deallocate (__mach_task_self (), dir);
+ return err;
+ }
+
+ err = __file_set_size (file, size);
+ if (err)
+ {
+ __mach_port_deallocate (__mach_task_self (), file);
+ __mach_port_deallocate (__mach_task_self (), dir);
+
+ return err;
+ }
+
+ *r_dir = dir;
+ *r_file = file;
+
+ return 0;
+}
+
+
+/* Open the shared memory segment *R_KEY and return a file descriptor
+ to it in R_FD. If KEY is IPC_PRIVATE, use a private key and return
+ it in R_KEY. */
+static error_t
+get_exclusive (int shmflags, size_t size, key_t *r_key, int *r_fd)
+{
+ error_t err;
+ file_t dir;
+ file_t file;
+ char filename[SHM_NAMEMAX];
+ key_t key = *r_key;
+ bool is_private;
+
+ /* Create the shared memory segment. */
+ err = create_shm_file (size, shmflags, &dir, &file);
+ if (err)
+ return err;
+
+ if (key == IPC_PRIVATE)
+ {
+ is_private = true;
+ key = SHM_PRIV_KEY_START;
+
+ /* Try to link the shared memory segment into the filesystem
+ (exclusively). */
+ do
+ {
+ sprintf (filename, SHM_NAMEPRI, key);
+ err = __dir_link (dir, file, filename, 1);
+ if (!err)
+ {
+ /* We are done. */
+ *r_key = key;
+ break;
+ }
+ else if (err == EEXIST)
+ {
+ /* Check if we ran out of keys. If not, try again with new
+ key. */
+ if (key == SHM_PRIV_KEY_END)
+ err = ENOSPC;
+ else
+ err = 0;
+
+ key--;
+ }
+ }
+ while (!err);
+ }
+ else
+ {
+ /* Try to link the shared memory segment into the filesystem
+ (exclusively) under the given key. */
+ sprintf (filename, SHM_NAMEPRI, key);
+ err = __dir_link (dir, file, filename, 1);
+ }
+
+ __mach_port_deallocate (__mach_task_self (), dir);
+
+ if (!err)
+ {
+ int fd;
+
+ /* Get a file descriptor for that port. */
+ fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */
+ if (fd < 0)
+ err = errno;
+ else
+ *r_fd = fd;
+ }
+
+ return err;
+}
+
+
+/* Open the shared memory segment KEY (creating it if it doesn't yet
+ exist) and return a file descriptor to it in R_FD. */
+static error_t
+get_shared (int shmflags, size_t size, key_t key, int *r_fd)
+{
+ error_t err = 0;
+ char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
+ int fd = -1;
+ sprintf (filename, SHM_DIR SHM_NAMEPRI, key);
+
+ do
+ {
+ fd = __open (filename, O_NORW, shmflags & 0777);
+
+ if (fd < 0 && errno != ENOENT)
+ /* We give up. */
+ return errno;
+ else if (fd >= 0)
+ {
+ int res;
+ struct stat statbuf;
+
+ /* Check the size (we only need to do this if we did not
+ create the shared memory segment file ourselves). */
+ res = __fstat (fd, &statbuf);
+ if (res < 0)
+ {
+ err = errno;
+ __close (fd);
+ return err;
+ }
+
+ if (statbuf.st_size < size)
+ {
+ __close (fd);
+ return EINVAL;
+ }
+ }
+ else
+ {
+ /* The memory segment doesn't exist. */
+ if (shmflags & IPC_CREAT)
+ {
+ /* Try to create it exclusively. */
+ err = get_exclusive (shmflags, size, &key, &fd);
+ if (err == EEXIST)
+ /* If somebody created it in the meanwhile, just try again. */
+ err = 0;
+ }
+ else
+ err = ENOENT;
+ }
+ }
+ while (fd < 0 && !err);
+
+ if (!err)
+ *r_fd = fd;
+ else
+ *r_fd = -1;
+
+ return err;
+}
+
+/* Return an identifier for an shared memory segment of at least size
+ SIZE which is associated with KEY. */
+int
+__shmget (key_t key, size_t size, int shmflags)
+{
+ error_t err;
+ int fd;
+
+ if (key == IPC_PRIVATE || shmflags & IPC_EXCL)
+ /* An exclusive shared memory segment must be created. */
+ err = get_exclusive (shmflags, size, &key, &fd);
+ else
+ err = get_shared (shmflags, size, key, &fd);
+
+ if (err)
+ {
+ errno = err;
+ return -1;
+ }
+
+ /* From here, we can't fail. That's important, as otherwise we
+ would need to unlink the file if we created it (in that case, the
+ code above would have to be changed to pass a "created" flag down
+ to the caller). */
+
+ __close (fd);
+
+ return key;
+}
+
+weak_alias(__shmget, shmget)
diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
index a0620de2bd..5eb7beeecb 100644
--- a/sysdeps/mach/hurd/sigaction.c
+++ b/sysdeps/mach/hurd/sigaction.c
@@ -49,15 +49,15 @@ __sigaction (sig, act, oact)
ss = _hurd_self_sigstate ();
__spin_lock (&ss->critical_section_lock);
- __spin_lock (&ss->lock);
- old = ss->actions[sig];
+ _hurd_sigstate_lock (ss);
+ old = _hurd_sigstate_actions (ss) [sig];
if (act != NULL)
- ss->actions[sig] = a;
+ _hurd_sigstate_actions (ss) [sig] = a;
if (act != NULL && sig == SIGCHLD &&
(a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP))
{
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Inform the proc server whether or not it should send us SIGCHLD for
stopped children. We do this in a critical section so that no
@@ -65,8 +65,8 @@ __sigaction (sig, act, oact)
__USEPORT (PROC,
__proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
- __spin_lock (&ss->lock);
- pending = ss->pending & ~ss->blocked;
+ _hurd_sigstate_lock (ss);
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
}
else if (act != NULL && (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL))
/* We are changing to an action that might be to ignore SIG signals.
@@ -75,11 +75,11 @@ __sigaction (sig, act, oact)
back and then SIG is unblocked, the signal pending now should not
arrive. So wake up the signal thread to check the new state and do
the right thing. */
- pending = ss->pending & __sigmask (sig);
+ pending = _hurd_sigstate_pending (ss) & __sigmask (sig);
else
pending = 0;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__spin_unlock (&ss->critical_section_lock);
if (pending)
diff --git a/sysdeps/mach/hurd/sigpending.c b/sysdeps/mach/hurd/sigpending.c
index 5f2600f562..3679101d73 100644
--- a/sysdeps/mach/hurd/sigpending.c
+++ b/sysdeps/mach/hurd/sigpending.c
@@ -37,9 +37,9 @@ sigpending (set)
}
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
- pending = ss->pending;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_lock (ss);
+ pending = _hurd_sigstate_pending (ss);
+ _hurd_sigstate_unlock (ss);
*set = pending;
return 0;
diff --git a/sysdeps/mach/hurd/sigprocmask.c b/sysdeps/mach/hurd/sigprocmask.c
index b3c13425af..92f605f579 100644
--- a/sysdeps/mach/hurd/sigprocmask.c
+++ b/sysdeps/mach/hurd/sigprocmask.c
@@ -39,7 +39,7 @@ __sigprocmask (how, set, oset)
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
old = ss->blocked;
@@ -60,7 +60,7 @@ __sigprocmask (how, set, oset)
break;
default:
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
errno = EINVAL;
return -1;
}
@@ -68,9 +68,9 @@ __sigprocmask (how, set, oset)
ss->blocked &= ~_SIG_CANT_MASK;
}
- pending = ss->pending & ~ss->blocked;
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
if (oset != NULL)
*oset = old;
diff --git a/sysdeps/mach/hurd/sigsuspend.c b/sysdeps/mach/hurd/sigsuspend.c
index 60f235e1ee..b631e08722 100644
--- a/sysdeps/mach/hurd/sigsuspend.c
+++ b/sysdeps/mach/hurd/sigsuspend.c
@@ -41,7 +41,7 @@ __sigsuspend (set)
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
oldmask = ss->blocked;
if (set != NULL)
@@ -49,11 +49,11 @@ __sigsuspend (set)
ss->blocked = newmask & ~_SIG_CANT_MASK;
/* Notice if any pending signals just became unblocked. */
- pending = ss->pending & ~ss->blocked;
+ pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
/* Tell the signal thread to message us when a signal arrives. */
ss->suspended = wait;
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
if (pending)
/* Tell the signal thread to check for pending signals. */
@@ -64,10 +64,11 @@ __sigsuspend (set)
MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
__mach_port_destroy (__mach_task_self (), wait);
- __spin_lock (&ss->lock);
- ss->blocked = oldmask; /* Restore the old mask. */
- pending = ss->pending & ~ss->blocked; /* Again check for pending signals. */
- __spin_unlock (&ss->lock);
+ /* Restore the old mask and check for pending signals again. */
+ _hurd_sigstate_lock (ss);
+ ss->blocked = oldmask;
+ pending = _hurd_sigstate_pending(ss) & ~ss->blocked;
+ _hurd_sigstate_unlock (ss);
if (pending)
/* Tell the signal thread to check for pending signals. */
diff --git a/sysdeps/mach/hurd/sigwait.c b/sysdeps/mach/hurd/sigwait.c
index 89193e6dfd..fcee4df8a4 100644
--- a/sysdeps/mach/hurd/sigwait.c
+++ b/sysdeps/mach/hurd/sigwait.c
@@ -27,7 +27,7 @@ int
__sigwait (const sigset_t *set, int *sig)
{
struct hurd_sigstate *ss;
- sigset_t mask, ready;
+ sigset_t mask, ready, blocked;
int signo = 0;
struct hurd_signal_preemptor preemptor;
jmp_buf buf;
@@ -49,8 +49,8 @@ __sigwait (const sigset_t *set, int *sig)
/* Make sure this is all kosher */
assert (__sigismember (&mask, signo));
- /* Make sure this signal is unblocked */
- __sigdelset (&ss->blocked, signo);
+ /* Restore the blocking mask. */
+ ss->blocked = blocked;
return pe->handler;
}
@@ -71,10 +71,11 @@ __sigwait (const sigset_t *set, int *sig)
__sigemptyset (&mask);
ss = _hurd_self_sigstate ();
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* See if one of these signals is currently pending. */
- __sigandset (&ready, &ss->pending, &mask);
+ sigset_t pending = _hurd_sigstate_pending (ss);
+ __sigandset (&ready, &pending, &mask);
if (! __sigisemptyset (&ready))
{
for (signo = 1; signo < NSIG; signo++)
@@ -102,7 +103,11 @@ __sigwait (const sigset_t *set, int *sig)
preemptor.next = ss->preemptors;
ss->preemptors = &preemptor;
- __spin_unlock (&ss->lock);
+ /* Unblock the expected signals */
+ blocked = ss->blocked;
+ ss->blocked &= ~mask;
+
+ _hurd_sigstate_unlock (ss);
/* Wait. */
__mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
@@ -113,7 +118,7 @@ __sigwait (const sigset_t *set, int *sig)
{
assert (signo);
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
/* Delete our preemptor. */
assert (ss->preemptors == &preemptor);
@@ -122,7 +127,7 @@ __sigwait (const sigset_t *set, int *sig)
all_done:
- spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
__mach_port_destroy (__mach_task_self (), wait);
*sig = signo;
diff --git a/sysdeps/mach/hurd/socket.c b/sysdeps/mach/hurd/socket.c
index 173a2f3f66..5a37ba5271 100644
--- a/sysdeps/mach/hurd/socket.c
+++ b/sysdeps/mach/hurd/socket.c
@@ -21,6 +21,7 @@
#include <hurd/socket.h>
#include <hurd/fd.h>
#include <fcntl.h>
+#include <fcntl-internal.h>
/* Create a new socket of type TYPE in domain DOMAIN, using
protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically.
@@ -33,6 +34,11 @@ __socket (domain, type, protocol)
{
error_t err;
socket_t sock, server;
+ int flags = sock_to_o_flags (type & ~SOCK_TYPE_MASK);
+ type &= SOCK_TYPE_MASK;
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
/* Find the socket server for DOMAIN. */
server = _hurd_socket_server (domain, 0);
@@ -58,10 +64,17 @@ __socket (domain, type, protocol)
|| err == MIG_BAD_ID || err == EOPNOTSUPP)
err = EAFNOSUPPORT;
+ if (! err)
+ {
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (sock, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ }
+
if (err)
return __hurd_fail (err);
- return _hurd_intern_fd (sock, O_IGNORE_CTTY, 1);
+ return _hurd_intern_fd (sock, O_IGNORE_CTTY | flags, 1);
}
weak_alias (__socket, socket)
diff --git a/sysdeps/mach/hurd/socketpair.c b/sysdeps/mach/hurd/socketpair.c
index b128a9bc64..9352aab11e 100644
--- a/sysdeps/mach/hurd/socketpair.c
+++ b/sysdeps/mach/hurd/socketpair.c
@@ -17,6 +17,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <fcntl-internal.h>
#include <sys/socket.h>
#include <unistd.h>
@@ -34,6 +35,11 @@ __socketpair (int domain, int type, int protocol, int fds[2])
error_t err;
socket_t server, sock1, sock2;
int d1, d2;
+ int flags = sock_to_o_flags (type & ~SOCK_TYPE_MASK);
+ type &= SOCK_TYPE_MASK;
+
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ return __hurd_fail (EINVAL);
if (fds == NULL)
return __hurd_fail (EINVAL);
@@ -56,6 +62,14 @@ __socketpair (int domain, int type, int protocol, int fds[2])
return -1;
err = __socket_create (server, type, protocol, &sock1);
}
+ /* TODO: do we need special ERR massaging here, like it is done in
+ __socket? */
+ if (! err)
+ {
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (sock1, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ }
if (err)
return __hurd_fail (err);
if (err = __socket_create (server, type, protocol, &sock2))
@@ -63,7 +77,12 @@ __socketpair (int domain, int type, int protocol, int fds[2])
__mach_port_deallocate (__mach_task_self (), sock1);
return __hurd_fail (err);
}
- if (err = __socket_connect2 (sock1, sock2))
+ if (flags & O_NONBLOCK)
+ err = __io_set_some_openmodes (sock2, O_NONBLOCK);
+ /* TODO: do we need special ERR massaging after the previous call? */
+ if (! err)
+ err = __socket_connect2 (sock1, sock2);
+ if (err)
{
__mach_port_deallocate (__mach_task_self (), sock1);
__mach_port_deallocate (__mach_task_self (), sock2);
@@ -72,13 +91,13 @@ __socketpair (int domain, int type, int protocol, int fds[2])
/* Put the sockets into file descriptors. */
- d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1);
+ d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY | flags, 1);
if (d1 < 0)
{
__mach_port_deallocate (__mach_task_self (), sock2);
return -1;
}
- d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1);
+ d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY | flags, 1);
if (d2 < 0)
{
err = errno;
diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
index a685a1f013..757395fe42 100644
--- a/sysdeps/mach/hurd/spawni.c
+++ b/sysdeps/mach/hurd/spawni.c
@@ -235,29 +235,31 @@ __spawni (pid_t *pid, const char *file,
ss = _hurd_self_sigstate ();
- assert (! __spin_lock_locked (&ss->critical_section_lock));
__spin_lock (&ss->critical_section_lock);
- __spin_lock (&ss->lock);
+ _hurd_sigstate_lock (ss);
ints[INIT_SIGMASK] = ss->blocked;
- ints[INIT_SIGPENDING] = ss->pending;
+ ints[INIT_SIGPENDING] = 0;
ints[INIT_SIGIGN] = 0;
/* Unless we were asked to reset all handlers to SIG_DFL,
pass down the set of signals that were set to SIG_IGN. */
- if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
- for (i = 1; i < NSIG; ++i)
- if (ss->actions[i].sa_handler == SIG_IGN)
- ints[INIT_SIGIGN] |= __sigmask (i);
-
- /* We hold the sigstate lock until the exec has failed so that no signal
- can arrive between when we pack the blocked and ignored signals, and
- when the exec actually happens. A signal handler could change what
+ {
+ struct sigaction *actions = _hurd_sigstate_actions (ss);
+ if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
+ for (i = 1; i < NSIG; ++i)
+ if (actions[i].sa_handler == SIG_IGN)
+ ints[INIT_SIGIGN] |= __sigmask (i);
+ }
+
+ /* We hold the critical section lock until the exec has failed so that no
+ signal can arrive between when we pack the blocked and ignored signals,
+ and when the exec actually happens. A signal handler could change what
signals are blocked and ignored. Either the change will be reflected
in the exec, or the signal will never be delivered. Setting the
critical section flag avoids anything we call trying to acquire the
sigstate lock. */
- __spin_unlock (&ss->lock);
+ _hurd_sigstate_unlock (ss);
/* Set signal mask. */
if ((flags & POSIX_SPAWN_SETSIGMASK) != 0)
diff --git a/sysdeps/mach/hurd/sysdep-cancel.h b/sysdeps/mach/hurd/sysdep-cancel.h
new file mode 100644
index 0000000000..ec55c7330f
--- /dev/null
+++ b/sysdeps/mach/hurd/sysdep-cancel.h
@@ -0,0 +1,9 @@
+#include <sysdep.h>
+
+/* Always multi-thread (since there's at least the sig handler), but no
+ handling enabled. */
+#define SINGLE_THREAD_P (0)
+#define RTLD_SINGLE_THREAD_P (0)
+#define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */
+#define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */
+#define LIBC_CANCEL_HANDLED() /* Nothing. */
diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h
index 5f3f8df053..487c84ae16 100644
--- a/sysdeps/mach/hurd/tls.h
+++ b/sysdeps/mach/hurd/tls.h
@@ -53,5 +53,18 @@
#endif /* !ASSEMBLER */
+#ifndef __ASSEMBLER__
+#include <mach/mach_traps.h>
+#include <atomic.h>
+/* Temporary poor-man's global scope switch support: just busy-waits */
+#define THREAD_GSCOPE_SET_FLAG() \
+ asm volatile ("lock incl %0":"=m"(GL(dl_thread_gscope_count)))
+#define THREAD_GSCOPE_RESET_FLAG() \
+ asm volatile ("lock decl %0":"=m"(GL(dl_thread_gscope_count)))
+#define THREAD_GSCOPE_WAIT() \
+ while (GL(dl_thread_gscope_count)) { \
+ __swtch_pri (0); \
+ }
+#endif
#endif /* tls.h */
diff --git a/sysdeps/mach/pagecopy.h b/sysdeps/mach/pagecopy.h
index 36c3697605..9d1f4de8bb 100644
--- a/sysdeps/mach/pagecopy.h
+++ b/sysdeps/mach/pagecopy.h
@@ -20,7 +20,10 @@
/* Threshold at which vm_copy is more efficient than well-optimized copying
by words. This parameter should be tuned as necessary. */
-#define PAGE_THRESHOLD (2 * PAGE_SIZE) /* XXX ? */
+#define PAGE_THRESHOLD (16384) /* XXX Tune this. */
+#if 0
+#define PAGE_COPY_THRESHOLD (16384) /* XXX Tune this. */
+#endif
#define PAGE_SIZE __vm_page_size
#define PAGE_COPY_FWD(dstp, srcp, nbytes_left, nbytes) \
diff --git a/sysdeps/mach/thread_state.h b/sysdeps/mach/thread_state.h
index 357c8bfbea..a6d3634070 100644
--- a/sysdeps/mach/thread_state.h
+++ b/sysdeps/mach/thread_state.h
@@ -38,7 +38,7 @@
#endif
#endif
#ifndef MACHINE_THREAD_STATE_FIX_NEW
-#define MACHINE_THREAD_STATE_FIX_NEW(ts)
+# define MACHINE_THREAD_STATE_FIX_NEW(ts)
#endif
/* These functions are of use in machine-dependent signal trampoline
diff --git a/sysdeps/pthread/aio_misc.c b/sysdeps/pthread/aio_misc.c
index 5ebceeee40..e703089dea 100644
--- a/sysdeps/pthread/aio_misc.c
+++ b/sysdeps/pthread/aio_misc.c
@@ -311,7 +311,10 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
if (operation == LIO_SYNC || operation == LIO_DSYNC)
aiocbp->aiocb.aio_reqprio = 0;
else if (aiocbp->aiocb.aio_reqprio < 0
- || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX)
+#ifdef AIO_PRIO_DELTA_MAX
+ || aiocbp->aiocb.aio_reqprio > AIO_PRIO_DELTA_MAX
+#endif
+ )
{
/* Invalid priority value. */
__set_errno (EINVAL);
diff --git a/sysdeps/unix/bsd/unlockpt.c b/sysdeps/unix/bsd/unlockpt.c
index 548f0ddc9a..27b77ea5f5 100644
--- a/sysdeps/unix/bsd/unlockpt.c
+++ b/sysdeps/unix/bsd/unlockpt.c
@@ -27,7 +27,7 @@
int
unlockpt (int fd)
{
- char buf[sizeof (_PATH_TTY) + 2];
+ char buf[1024]; /* XXX */
/* BSD doesn't have a lock, but it does have `revoke'. */
if (__ptsname_r (fd, buf, sizeof (buf)))
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index f3c67ef8c9..b600e1183b 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -21,6 +21,9 @@
#include <libc-internal.h>
#include <ldsodefs.h>
+/* TODO */
+#include <sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h>
+
#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
/* Clock frequency of the processor. We make it a 64-bit variable