diff options
author | gcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2006-08-17 01:18:26 +0000 |
---|---|---|
committer | gcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2006-08-17 01:18:26 +0000 |
commit | 15f34685e7a9b5caf761af2ebf6afa20438d440b (patch) | |
tree | dc04ce3cdf040f198743c15b64557824de174680 /libc/sysdeps/mach | |
parent | 1e848e0e775a36f6359161f5deb890942ef42ff3 (diff) | |
download | eglibc2-15f34685e7a9b5caf761af2ebf6afa20438d440b.tar.gz |
Import glibc-mainline for 2006-08-16
git-svn-id: svn://svn.eglibc.org/fsf/trunk@4 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/sysdeps/mach')
322 files changed, 25949 insertions, 0 deletions
diff --git a/libc/sysdeps/mach/Makefile b/libc/sysdeps/mach/Makefile new file mode 100644 index 000000000..af2c273e4 --- /dev/null +++ b/libc/sysdeps/mach/Makefile @@ -0,0 +1,52 @@ +# Copyright (C) 1993,1994,1996,1997,2002,2003 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. + +ifdef in-Makerules + +# Look for header files in mach/ under the top-level library source directory. +# Look for generated header files where they get created. +includes += -I$(..)mach -I$(common-objpfx)mach/ + +ifneq (mach,$(subdir)) +# Subdirectories other than mach/ might use the generated Mach headers. +# So make sure we get a chance to run in mach/ to make them before all else. + +mach-objpfx = $(common-objpfx)mach/ +else +mach-objpfx = $(objpfx) +endif + +# These are all the generated files that <mach.h> includes. +# Actually, it's only some of them. We omit mach_interface.h +# because it's different in Darwin and the conditional crap is +# too much trouble. This should suffice for getting the mach/Makefile +# rules invoked when they need to be. +mach-before-compile := $(mach-objpfx)mach-shortcuts.h \ + $(patsubst %,$(mach-objpfx)mach/mach_%.h,\ + port host) + +ifneq (mach,$(subdir)) +# This patsubst generates patterns like `m%h-shortcuts.h', which are damn +# likely to match just the corresponding particular file we want. +$(patsubst mach%,m\%h%,$(mach-before-compile)): # Run only if doesn't exist. + $(MAKE) -C $(..)mach mach-before-compile no_deps=t generating=t + +before-compile += $(mach-before-compile) +endif + +endif # in-Makerules diff --git a/libc/sysdeps/mach/Subdirs b/libc/sysdeps/mach/Subdirs new file mode 100644 index 000000000..24fa4a3c9 --- /dev/null +++ b/libc/sysdeps/mach/Subdirs @@ -0,0 +1,9 @@ +# This file says that the mach subdirectory should appear before all others. +# The mach and hurd subdirectories have many generated header files which +# much of the rest of the library depends on, so it is best to build them +# first (and mach before hurd, at that). The before-compile additions in +# sysdeps/{mach,hurd}/Makefile should make it reliably work for these files +# not to exist when making in other directories, but it will be slower that +# way with more somewhat expensive `make' invocations. + +first mach diff --git a/libc/sysdeps/mach/_strerror.c b/libc/sysdeps/mach/_strerror.c new file mode 100644 index 000000000..a67bbb962 --- /dev/null +++ b/libc/sysdeps/mach/_strerror.c @@ -0,0 +1,121 @@ +/* Copyright (C) 1993,95,96,97,98,2000,02 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 <libintl.h> +#include <stdio.h> +#include <string.h> +#include <mach/error.h> +#include <errorlib.h> +#include <sys/param.h> +#include <stdio-common/_itoa.h> + +/* It is critical here that we always use the `dcgettext' function for + the message translation. Since <libintl.h> only defines the macro + `dgettext' to use `dcgettext' for optimizing programs this is not + always guaranteed. */ +#ifndef dgettext +# include <locale.h> /* We need LC_MESSAGES. */ +# define dgettext(domainname, msgid) dcgettext (domainname, msgid, LC_MESSAGES) +#endif + +/* Return a string describing the errno code in ERRNUM. */ +char * +__strerror_r (int errnum, char *buf, size_t buflen) +{ + int system; + int sub; + int code; + const struct error_system *es; + extern void __mach_error_map_compat (int *); + + __mach_error_map_compat (&errnum); + + system = err_get_system (errnum); + sub = err_get_sub (errnum); + code = err_get_code (errnum); + + if (system > err_max_system || ! __mach_error_systems[system].bad_sub) + { + /* Buffer we use to print the number in. For a maximum size for + `int' of 8 bytes we never need more than 20 digits. */ + char numbuf[21]; + const char *unk = _("Error in unknown error system: "); + const size_t unklen = strlen (unk); + char *p, *q; + + numbuf[20] = '\0'; + p = _itoa_word (errnum, &numbuf[20], 16, 1); + + /* Now construct the result while taking care for the destination + buffer size. */ + q = __mempcpy (buf, unk, MIN (unklen, buflen)); + if (unklen < buflen) + memcpy (q, p, MIN (&numbuf[21] - p, buflen - unklen)); + + /* Terminate the string in any case. */ + if (buflen > 0) + buf[buflen - 1] = '\0'; + + return buf; + } + + es = &__mach_error_systems[system]; + + if (sub >= es->max_sub) + return (char *) es->bad_sub; + + if (code >= es->subsystem[sub].max_code) + { + /* Buffer we use to print the number in. For a maximum size for + `int' of 8 bytes we never need more than 20 digits. */ + char numbuf[21]; + const char *unk = _("Unknown error "); + const size_t unklen = strlen (unk); + char *p, *q; + size_t len = strlen (es->subsystem[sub].subsys_name); + + numbuf[20] = '\0'; + p = _itoa_word (errnum, &numbuf[20], 10, 0); + + /* Now construct the result while taking care for the destination + buffer size. */ + q = __mempcpy (buf, unk, MIN (unklen, buflen)); + if (unklen < buflen) + { + q = __mempcpy (q, es->subsystem[sub].subsys_name, + MIN (len, buflen - unklen)); + if (unklen + len < buflen) + { + *q++ = ' '; + if (unklen + len + 1 < buflen) + memcpy (q, p, + MIN (&numbuf[21] - p, buflen - unklen - len - 1)); + } + } + + /* Terminate the string in any case. */ + if (buflen > 0) + buf[buflen - 1] = '\0'; + + return buf; + } + + return (char *) _(es->subsystem[sub].codes[code]); +} +libc_hidden_def (__strerror_r) +weak_alias (__strerror_r, strerror_r) diff --git a/libc/sysdeps/mach/adjtime.c b/libc/sysdeps/mach/adjtime.c new file mode 100644 index 000000000..612a32043 --- /dev/null +++ b/libc/sysdeps/mach/adjtime.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1991, 1995, 1997 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/time.h> +#include <hurd.h> + +/* Adjust the current time of day by the amount in DELTA. + If OLDDELTA is not NULL, it is filled in with the amount + of time adjustment remaining to be done from the last `__adjtime' call. + This call is restricted to the super-user. */ +int +__adjtime (delta, olddelta) + const struct timeval *delta; + struct timeval *olddelta; +{ + error_t err; + mach_port_t hostpriv; + + hostpriv = __pid2task (-1); + if (hostpriv == MACH_PORT_NULL) + return -1; + err = __host_adjust_time (hostpriv, delta, olddelta); + __mach_port_deallocate (__mach_task_self (), hostpriv); + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__adjtime, adjtime) diff --git a/libc/sysdeps/mach/alpha/machine-lock.h b/libc/sysdeps/mach/alpha/machine-lock.h new file mode 100644 index 000000000..80f8750c8 --- /dev/null +++ b/libc/sysdeps/mach/alpha/machine-lock.h @@ -0,0 +1,80 @@ +/* Machine-specific definition for spin locks. Alpha version. + Copyright (C) 1994, 1997 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 _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile long int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0L + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + __asm__ __volatile__ ("mb; stq $31, %0; mb" + : "=m" (__lock)); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + register long int __rtn, __tmp; + + do + { + __asm__ __volatile__ ("mb; ldq_l %0,%1" /* Load lock value into TMP. */ + : "=r" (__tmp) : "m" (*__lock)); + __rtn = 2; /* Load locked value into RTN. */ + if (__tmp) + /* The lock is already taken. */ + return 0; + + /* The lock is not taken; try to get it now. */ + __asm__ __volatile__ ("stq_c %0,%1" + : "=r" (__rtn), "=m" (*__lock) + : "0" (__rtn), "1" (*__lock)); + /* RTN is clear if stq_c was interrupted; loop to try the lock again. */ + } while (! __rtn); + /* RTN is now nonzero; we have the lock. */ + return __rtn; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return *__lock != 0; +} + + +#endif /* machine-lock.h */ diff --git a/libc/sysdeps/mach/alpha/machine-sp.h b/libc/sysdeps/mach/alpha/machine-sp.h new file mode 100644 index 000000000..b73752557 --- /dev/null +++ b/libc/sysdeps/mach/alpha/machine-sp.h @@ -0,0 +1,36 @@ +/* Machine-specific function to return the stack pointer. Alpha version. + Copyright (C) 1994, 1997 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 _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +_EXTERN_INLINE void * +__thread_stack_pointer (void) +{ + register void *__sp__ __asm__ ("$30"); + return __sp__; +} + +#endif /* machine-sp.h */ diff --git a/libc/sysdeps/mach/alpha/setfpucw.c b/libc/sysdeps/mach/alpha/setfpucw.c new file mode 100644 index 000000000..a2887c8df --- /dev/null +++ b/libc/sysdeps/mach/alpha/setfpucw.c @@ -0,0 +1,69 @@ +/* Set FP exception mask and rounding mode. Mach/Alpha version. + Copyright (C) 2002 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 <fpu_control.h> + + +#define FPCR_DYN_SHIFT 58 /* first dynamic rounding mode bit */ +#define FPCR_DYN_CHOPPED (0x0UL << FPCR_DYN_SHIFT) /* towards 0 */ +#define FPCR_DYN_MINUS (0x1UL << FPCR_DYN_SHIFT) /* towards -INF */ +#define FPCR_DYN_NORMAL (0x2UL << FPCR_DYN_SHIFT) /* towards nearest */ +#define FPCR_DYN_PLUS (0x3UL << FPCR_DYN_SHIFT) /* towards +INF */ +#define FPCR_DYN_MASK (0x3UL << FPCR_DYN_SHIFT) + +static inline unsigned long +rdfpcr (void) +{ + unsigned long fpcr; + asm ("excb; mf_fpcr %0" : "=f"(fpcr)); + return fpcr; +} + +static inline void +wrfpcr (unsigned long fpcr) +{ + asm volatile ("mt_fpcr %0; excb" : : "f"(fpcr)); +} + + +void +__setfpucw (fpu_control_t fpu_control) +{ + unsigned long fpcr; + + if (!fpu_control) + fpu_control = _FPU_DEFAULT; + + /* first, set dynamic rounding mode: */ + + fpcr = rdfpcr(); + fpcr &= ~FPCR_DYN_MASK; + switch (fpu_control & 0xc00) + { + case _FPU_RC_NEAREST: fpcr |= FPCR_DYN_NORMAL; break; + case _FPU_RC_DOWN: fpcr |= FPCR_DYN_MINUS; break; + case _FPU_RC_UP: fpcr |= FPCR_DYN_PLUS; break; + case _FPU_RC_ZERO: fpcr |= FPCR_DYN_CHOPPED; break; + } + wrfpcr(fpcr); + + /* XXX trap bits? */ + + __fpu_control = fpu_control; /* update global copy */ +} diff --git a/libc/sysdeps/mach/alpha/syscall.S b/libc/sysdeps/mach/alpha/syscall.S new file mode 100644 index 000000000..15fc5b75b --- /dev/null +++ b/libc/sysdeps/mach/alpha/syscall.S @@ -0,0 +1,37 @@ +/* Copyright (C) 1994,97,2002 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 <sysdep.h> + +ENTRY (syscall) + mov a0, v0 /* Load system call number from first arg. */ + mov a1, a0 + mov a2, a1 + mov a3, a2 + mov a4, a3 + mov a5, a4 + /* Load the remaining possible args (up to 11) from the stack. */ + ldq a5,0(sp) + ldq t0,8(sp) + ldq t1,16(sp) + ldq t2,24(sp) + ldq t3,32(sp) + ldq t4,40(sp) + callsys + ret +END (syscall) diff --git a/libc/sysdeps/mach/alpha/sysdep.h b/libc/sysdeps/mach/alpha/sysdep.h new file mode 100644 index 000000000..84e21c8d5 --- /dev/null +++ b/libc/sysdeps/mach/alpha/sysdep.h @@ -0,0 +1,59 @@ +/* Copyright (C) 1994,97,2002 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. */ + +#define MOVE(x,y) mov x, y + +#define LOSE asm volatile ("call_pal 0") /* halt */ + +#define START_MACHDEP \ + asm ("_start: mov $30, $16\n" /* Put initial SP in a0. */ \ + " br $27, 1f\n" /* Load GP from PC. */ \ + "1: ldgp $29, 0($27)\n" \ + " jmp $26, _start0"); /* Jump to _start0; don't return. */ +#define START_ARGS char **sparg +#define SNARF_ARGS(argc, argv, envp) \ + (envp = &(argv = &sparg[1])[(argc = *(int *) sparg) + 1]) + +#define CALL_WITH_SP(fn, sp) \ + ({ register long int __fn = (long int) fn, __sp = (long int) sp; \ + asm volatile ("mov %0,$30; jmp $31, (%1); ldgp $29, 0(%1)" \ + : : "r" (__sp), "r" (__fn)); }) + +#define STACK_GROWTH_DOWN + +#define RETURN_TO(sp, pc, retval) \ + asm volatile ("mov %0,$30; jmp $31, (%1); mov %2,$0" \ + : : "r" (sp), "r" (pc), "r" ((long int) (retval))); + +#define ALIGN 3 +#include <sysdeps/mach/sysdep.h> + +/* Alpha needs the .ent and .frame magic that the generic version lacks. */ +#undef ENTRY +#define ENTRY(name) \ + .globl name; \ + .align 3; \ + .ent name, 0; \ + name##: \ + .frame sp, 0, ra + +#include <mach/alpha/asm.h> +#undef at +#define at 28 +#define AT $28 +#define fp s6 diff --git a/libc/sysdeps/mach/alpha/thread_state.h b/libc/sysdeps/mach/alpha/thread_state.h new file mode 100644 index 000000000..0c9527bd2 --- /dev/null +++ b/libc/sysdeps/mach/alpha/thread_state.h @@ -0,0 +1,39 @@ +/* Mach thread state definitions for machine-independent code. Alpha version. + Copyright (C) 1994, 1997 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 <mach/machine/thread_status.h> + +#define MACHINE_THREAD_STATE_FLAVOR ALPHA_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT ALPHA_THREAD_STATE_COUNT + +#define machine_thread_state alpha_thread_state + +#define PC pc +#define SP r30 +#define SYSRETURN r0 + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct alpha_thread_state basic; + struct alpha_exc_state exc; + struct alpha_float_state fpu; + }; + +#include <sysdeps/mach/thread_state.h> diff --git a/libc/sysdeps/mach/bits/libc-lock.h b/libc/sysdeps/mach/bits/libc-lock.h new file mode 100644 index 000000000..76bbd02d0 --- /dev/null +++ b/libc/sysdeps/mach/bits/libc-lock.h @@ -0,0 +1,144 @@ +/* libc-internal interface for mutex locks. Mach cthreads version. + Copyright (C) 1996,97,98,2000,01, 2002 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 _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#ifdef _LIBC +#include <cthreads.h> +#define __libc_lock_t struct mutex +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +#endif + +/* Type for key of thread specific data. */ +typedef cthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. */ +#define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = MUTEX_INITIALIZER; + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#define __libc_lock_init(NAME) __mutex_init (&(NAME)) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) __mutex_unlock (&(NAME)) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) __mutex_lock (&(NAME)) + +/* Lock the named lock variable. */ +#define __libc_lock_trylock(NAME) (!__mutex_trylock (&(NAME))) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME)) + + +/* XXX for now */ +#define __libc_rwlock_define __libc_lock_define +#define __libc_rwlock_define_initialized __libc_lock_define_initialized +#define __libc_rwlock_init __libc_lock_init +#define __libc_rwlock_fini __libc_lock_fini +#define __libc_rwlock_rdlock __libc_lock_lock +#define __libc_rwlock_wrlock __libc_lock_lock +#define __libc_rwlock_tryrdlock __libc_lock_trylock +#define __libc_rwlock_trywrlock __libc_lock_trylock +#define __libc_rwlock_unlock __libc_lock_unlock + + +/* Start a critical region with a cleanup function */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ +{ \ + typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0; \ + typeof (ARG) __save_ARG = ARG; \ + /* close brace is in __libc_cleanup_region_end below. */ + +/* End a critical region started with __libc_cleanup_region_start. */ +#define __libc_cleanup_region_end(DOIT) \ + if ((DOIT) && __save_FCT != 0) \ + (*__save_FCT)(__save_ARG); \ +} + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if ((DOIT) && __save_FCT != 0) \ + (*__save_FCT)(__save_ARG); \ + + +/* Use mutexes as once control variables. */ + +struct __libc_once + { + __libc_lock_t lock; + int done; + }; + +#define __libc_once_define(CLASS,NAME) \ + CLASS struct __libc_once NAME = { MUTEX_INITIALIZER, 0 } + + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + __libc_lock_lock (ONCE_CONTROL.lock); \ + if (!ONCE_CONTROL.done) \ + (INIT_FUNCTION) (); \ + ONCE_CONTROL.done = 1; \ + __libc_lock_unlock (ONCE_CONTROL.lock); \ + } while (0) + +#ifdef _LIBC +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __mutex_unlock +#endif + +#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY) +#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL) +void *__libc_getspecific (__libc_key_t key); + +/* XXX until cthreads supports recursive locks */ +#define __libc_lock_define_initialized_recursive __libc_lock_define_initialized +#define __libc_lock_init_recursive __libc_lock_init +#define __libc_lock_fini_recursive __libc_lock_fini +#define __libc_lock_trylock_recursive __libc_lock_trylock +#define __libc_lock_unlock_recursive __libc_lock_unlock +#define __libc_lock_lock_recursive __libc_lock_lock + +#define __rtld_lock_define_initialized_recursive __libc_lock_define_initialized +#define __rtld_lock_init_recursive __libc_lock_init +#define __rtld_lock_fini_recursive __libc_lock_fini +#define __rtld_lock_trylock_recursive __libc_lock_trylock +#define __rtld_lock_unlock_recursive __libc_lock_unlock +#define __rtld_lock_lock_recursive __libc_lock_lock + +#endif /* bits/libc-lock.h */ diff --git a/libc/sysdeps/mach/configure b/libc/sysdeps/mach/configure new file mode 100644 index 000000000..bf4f98d4d --- /dev/null +++ b/libc/sysdeps/mach/configure @@ -0,0 +1,678 @@ +# This file is generated from configure.in by Autoconf. DO NOT EDIT! + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mig", so it can be a program name with args. +set dummy ${ac_tool_prefix}mig; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_MIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$MIG"; then + ac_cv_prog_MIG="$MIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MIG="${ac_tool_prefix}mig" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +MIG=$ac_cv_prog_MIG +if test -n "$MIG"; then + echo "$as_me:$LINENO: result: $MIG" >&5 +echo "${ECHO_T}$MIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_MIG"; then + ac_ct_MIG=$MIG + # Extract the first word of "mig", so it can be a program name with args. +set dummy mig; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_MIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_MIG"; then + ac_cv_prog_ac_ct_MIG="$ac_ct_MIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MIG="mig" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_MIG" && ac_cv_prog_ac_ct_MIG="MISSING" +fi +fi +ac_ct_MIG=$ac_cv_prog_ac_ct_MIG +if test -n "$ac_ct_MIG"; then + echo "$as_me:$LINENO: result: $ac_ct_MIG" >&5 +echo "${ECHO_T}$ac_ct_MIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + MIG=$ac_ct_MIG +else + MIG="$ac_cv_prog_MIG" +fi + +if test "x$MIG" = xMISSING; then + { { echo "$as_me:$LINENO: error: cannot find required build tool mig" >&5 +echo "$as_me: error: cannot find required build tool mig" >&2;} + { (exit 1); exit 1; }; } +fi + +### Sanity checks for Mach header installation + + +echo "$as_me:$LINENO: checking for mach/mach_types.h" >&5 +echo $ECHO_N "checking for mach/mach_types.h... $ECHO_C" >&6 +if test "${ac_cv_header_mach_mach_types_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/mach_types.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_mach_mach_types_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_mach_mach_types_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_mach_mach_types_h" >&5 +echo "${ECHO_T}$ac_cv_header_mach_mach_types_h" >&6 +if test $ac_cv_header_mach_mach_types_h = yes; then + : +else + { { echo "$as_me:$LINENO: error: cannot find Mach headers" >&5 +echo "$as_me: error: cannot find Mach headers" >&2;} + { (exit 1); exit 1; }; } +fi + + +echo "$as_me:$LINENO: checking for mach/mach_types.defs" >&5 +echo $ECHO_N "checking for mach/mach_types.defs... $ECHO_C" >&6 +if test "${ac_cv_header_mach_mach_types_defs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/mach_types.defs> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_mach_mach_types_defs=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_mach_mach_types_defs=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_mach_mach_types_defs" >&5 +echo "${ECHO_T}$ac_cv_header_mach_mach_types_defs" >&6 +if test $ac_cv_header_mach_mach_types_defs = yes; then + : +else + { { echo "$as_me:$LINENO: error: cannot find Mach .defs files" >&5 +echo "$as_me: error: cannot find Mach .defs files" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + +echo "$as_me:$LINENO: checking for task_t in mach/mach_types.h" >&5 +echo $ECHO_N "checking for task_t in mach/mach_types.h... $ECHO_C" >&6 +if test "${libc_cv_mach_task_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/mach_types.h> +int +main () +{ +extern task_t foo; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + libc_cv_mach_task_t=task_t +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +libc_cv_mach_task_t=task_port_t +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $libc_cv_mach_task_t" >&5 +echo "${ECHO_T}$libc_cv_mach_task_t" >&6 +if test $libc_cv_mach_task_t != task_t; then + DEFINES="$DEFINES -Dtask_t=task_port_t" +fi +echo "$as_me:$LINENO: checking for thread_t in mach/mach_types.h" >&5 +echo $ECHO_N "checking for thread_t in mach/mach_types.h... $ECHO_C" >&6 +if test "${libc_cv_mach_thread_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/mach_types.h> +int +main () +{ +extern thread_t foo; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + libc_cv_mach_thread_t=thread_t +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +libc_cv_mach_thread_t=thread_port_t +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $libc_cv_mach_thread_t" >&5 +echo "${ECHO_T}$libc_cv_mach_thread_t" >&6 +if test $libc_cv_mach_thread_t != thread_t; then + DEFINES="$DEFINES -Dthread_t=thread_port_t" +fi + +echo "$as_me:$LINENO: checking for creation_time in task_basic_info" >&5 +echo $ECHO_N "checking for creation_time in task_basic_info... $ECHO_C" >&6 +if test "${libc_cv_mach_task_creation_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/task_info.h> +int +main () +{ + +extern struct task_basic_info *i; +long s = i->creation_time.seconds; + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + libc_cv_mach_task_creation_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +libc_cv_mach_task_creation_time=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $libc_cv_mach_task_creation_time" >&5 +echo "${ECHO_T}$libc_cv_mach_task_creation_time" >&6 +if test $libc_cv_mach_task_creation_time = no; then + { { echo "$as_me:$LINENO: error: you need Mach headers supporting task_info.creation_time" >&5 +echo "$as_me: error: you need Mach headers supporting task_info.creation_time" >&2;} + { (exit 1); exit 1; }; } +fi + +mach_interface_list= +for ifc in mach mach4 \ + 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 \ + i386/mach_i386 \ + ; do + as_ac_Header=`echo "ac_cv_header_mach/${ifc}.defs" | $as_tr_sh` +echo "$as_me:$LINENO: checking for mach/${ifc}.defs" >&5 +echo $ECHO_N "checking for mach/${ifc}.defs... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/${ifc}.defs> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + mach_interface_list="$mach_interface_list $ifc" +fi + + +done +if test "x$mach_interface_list" = x; then + { { echo "$as_me:$LINENO: error: what manner of Mach is this?" >&5 +echo "$as_me: error: what manner of Mach is this?" >&2;} + { (exit 1); exit 1; }; } +fi + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for host_page_size in mach_host.defs" >&5 +echo $ECHO_N "checking for host_page_size in mach_host.defs... $ECHO_C" >&6 +if test "${libc_cv_mach_host_page_size+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/mach_host.defs> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "host_page_size" >/dev/null 2>&1; then + libc_cv_mach_host_page_size=yes +else + libc_cv_mach_host_page_size=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $libc_cv_mach_host_page_size" >&5 +echo "${ECHO_T}$libc_cv_mach_host_page_size" >&6 +if test $libc_cv_mach_host_page_size = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_HOST_PAGE_SIZE 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for mach/machine/ndr_def.h" >&5 +echo $ECHO_N "checking for mach/machine/ndr_def.h... $ECHO_C" >&6 +if test "${ac_cv_header_mach_machine_ndr_def_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/machine/ndr_def.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_mach_machine_ndr_def_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_mach_machine_ndr_def_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_mach_machine_ndr_def_h" >&5 +echo "${ECHO_T}$ac_cv_header_mach_machine_ndr_def_h" >&6 +if test $ac_cv_header_mach_machine_ndr_def_h = yes; then + DEFINES="$DEFINES -DNDR_DEF_HEADER='<mach/machine/ndr_def.h>'" +else + echo "$as_me:$LINENO: checking for machine/ndr_def.h" >&5 +echo $ECHO_N "checking for machine/ndr_def.h... $ECHO_C" >&6 +if test "${ac_cv_header_machine_ndr_def_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <machine/ndr_def.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_machine_ndr_def_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_machine_ndr_def_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_machine_ndr_def_h" >&5 +echo "${ECHO_T}$ac_cv_header_machine_ndr_def_h" >&6 +if test $ac_cv_header_machine_ndr_def_h = yes; then + DEFINES="$DEFINES -DNDR_DEF_HEADER='<machine/ndr_def.h>'" +fi + + +fi + + + +echo "$as_me:$LINENO: checking for i386_io_perm_modify in mach_i386.defs" >&5 +echo $ECHO_N "checking for i386_io_perm_modify in mach_i386.defs... $ECHO_C" >&6 +if test "${libc_cv_mach_i386_ioports+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/i386/mach_i386.defs> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "i386_io_perm_modify" >/dev/null 2>&1; then + libc_cv_mach_i386_ioports=yes +else + libc_cv_mach_i386_ioports=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $libc_cv_mach_i386_ioports" >&5 +echo "${ECHO_T}$libc_cv_mach_i386_ioports" >&6 +if test $libc_cv_mach_i386_ioports = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_I386_IO_PERM_MODIFY 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for i386_set_gdt in mach_i386.defs" >&5 +echo $ECHO_N "checking for i386_set_gdt in mach_i386.defs... $ECHO_C" >&6 +if test "${libc_cv_mach_i386_gdt+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <mach/i386/mach_i386.defs> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "i386_set_gdt" >/dev/null 2>&1; then + libc_cv_mach_i386_gdt=yes +else + libc_cv_mach_i386_gdt=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $libc_cv_mach_i386_gdt" >&5 +echo "${ECHO_T}$libc_cv_mach_i386_gdt" >&6 +if test $libc_cv_mach_i386_gdt = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_I386_SET_GDT 1 +_ACEOF + +fi + + + +# See if mig groks `retcode'. +echo "$as_me:$LINENO: checking whether $MIG supports the retcode keyword" >&5 +echo $ECHO_N "checking whether $MIG supports the retcode keyword... $ECHO_C" >&6 +if test "${hurd_cv_mig_retcode+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.defs <<\EOF +#include <mach/std_types.defs> +#include <mach/mach_types.defs> +subsystem foobar 1000; +type reply_port_t = polymorphic | MACH_MSG_TYPE_PORT_SEND_ONCE + ctype: mach_port_t; +simpleroutine foobar_reply ( + reply_port: reply_port_t; + err: kern_return_t, RetCode); +EOF +if { ac_try='CC="${CC}" ${MIG-false} -n conftest.defs 1>&5' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + hurd_cv_mig_retcode=yes +else + hurd_cv_mig_retcode=no +fi +rm -f conftest* +fi +echo "$as_me:$LINENO: result: $hurd_cv_mig_retcode" >&5 +echo "${ECHO_T}$hurd_cv_mig_retcode" >&6 +if test $hurd_cv_mig_retcode = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_MIG_RETCODE 1 +_ACEOF + +fi diff --git a/libc/sysdeps/mach/configure.in b/libc/sysdeps/mach/configure.in new file mode 100644 index 000000000..2f82c3a87 --- /dev/null +++ b/libc/sysdeps/mach/configure.in @@ -0,0 +1,125 @@ +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + +AC_CHECK_TOOL(MIG, mig, MISSING) +if test "x$MIG" = xMISSING; then + AC_MSG_ERROR([cannot find required build tool mig]) +fi + +### Sanity checks for Mach header installation +AC_CHECK_HEADER(mach/mach_types.h,, + [AC_MSG_ERROR([cannot find Mach headers])], -) +AC_CHECK_HEADER(mach/mach_types.defs,, [dnl +AC_MSG_ERROR([cannot find Mach .defs files])], -) + +dnl +dnl mach_TYPE_CHECK(foo_t, bar_t) +dnl +dnl Check if foo_t is defined by <mach/mach_types.h>. +dnl If not, compile with -Dfoo_t=bar_t. +dnl +AC_DEFUN([mach_TYPE_CHECK], [dnl +AC_CACHE_CHECK(for $1 in mach/mach_types.h, libc_cv_mach_$1, +AC_TRY_COMPILE([#include <mach/mach_types.h>], [extern $1 foo;], +libc_cv_mach_$1=$1, libc_cv_mach_$1=$2)) +if test [$]libc_cv_mach_$1 != $1; then + DEFINES="$DEFINES -D$1=$2" +fi]) + +dnl +dnl OSF Mach has renamed these typedefs for some reason. +dnl +mach_TYPE_CHECK(task_t, task_port_t) +mach_TYPE_CHECK(thread_t, thread_port_t) + +dnl +dnl The creation_time field is a GNU Mach addition the other variants lack. +dnl +AC_CACHE_CHECK(for creation_time in task_basic_info, + libc_cv_mach_task_creation_time, [dnl +AC_TRY_COMPILE([#include <mach/task_info.h>], [ +extern struct task_basic_info *i; +long s = i->creation_time.seconds; +], libc_cv_mach_task_creation_time=yes, libc_cv_mach_task_creation_time=no)]) +if test $libc_cv_mach_task_creation_time = no; then + AC_MSG_ERROR([you need Mach headers supporting task_info.creation_time]) +fi + +dnl +dnl The Darwin variant no longer has <mach/mach.defs> +dnl but instead has several constituent .defs files. +dnl In this scenario we will presume there is a <mach/mach_interface.h> +dnl that contains an #include for each constituent header file, +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 \ + 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 \ + i386/mach_i386 \ + ; do + AC_CHECK_HEADER(mach/${ifc}.defs, [dnl + mach_interface_list="$mach_interface_list $ifc"],, -) +done +if test "x$mach_interface_list" = x; then + AC_MSG_ERROR([what manner of Mach is this?]) +fi + +AC_CACHE_CHECK(for host_page_size in mach_host.defs, + libc_cv_mach_host_page_size, [dnl +AC_EGREP_HEADER(host_page_size, mach/mach_host.defs, + libc_cv_mach_host_page_size=yes, + libc_cv_mach_host_page_size=no)]) +if test $libc_cv_mach_host_page_size = yes; then + AC_DEFINE([HAVE_HOST_PAGE_SIZE]) +fi + +AC_CHECK_HEADER(mach/machine/ndr_def.h, [dnl + DEFINES="$DEFINES -DNDR_DEF_HEADER='<mach/machine/ndr_def.h>'"], [dnl +AC_CHECK_HEADER(machine/ndr_def.h, [dnl + DEFINES="$DEFINES -DNDR_DEF_HEADER='<machine/ndr_def.h>'"],, -)], -) + +AC_CACHE_CHECK(for i386_io_perm_modify in mach_i386.defs, + libc_cv_mach_i386_ioports, [dnl +AC_EGREP_HEADER(i386_io_perm_modify, mach/i386/mach_i386.defs, + libc_cv_mach_i386_ioports=yes, + libc_cv_mach_i386_ioports=no)]) +if test $libc_cv_mach_i386_ioports = yes; then + AC_DEFINE([HAVE_I386_IO_PERM_MODIFY]) +fi + +AC_CACHE_CHECK(for i386_set_gdt in mach_i386.defs, + libc_cv_mach_i386_gdt, [dnl +AC_EGREP_HEADER(i386_set_gdt, mach/i386/mach_i386.defs, + libc_cv_mach_i386_gdt=yes, + libc_cv_mach_i386_gdt=no)]) +if test $libc_cv_mach_i386_gdt = yes; then + AC_DEFINE([HAVE_I386_SET_GDT]) +fi + +dnl Swiped from hurd/aclocal.m4 +AC_DEFUN([hurd_MIG_RETCODE], [dnl +# See if mig groks `retcode'. +AC_CACHE_CHECK(whether $MIG supports the retcode keyword, hurd_cv_mig_retcode, +[cat > conftest.defs <<\EOF +#include <mach/std_types.defs> +#include <mach/mach_types.defs> +subsystem foobar 1000; +type reply_port_t = polymorphic | MACH_MSG_TYPE_PORT_SEND_ONCE + ctype: mach_port_t; +simpleroutine foobar_reply ( + reply_port: reply_port_t; + err: kern_return_t, RetCode); +EOF +if AC_TRY_COMMAND([CC="${CC}" ${MIG-false} -n conftest.defs 1>&AS_MESSAGE_LOG_FD]); then + hurd_cv_mig_retcode=yes +else + hurd_cv_mig_retcode=no +fi +rm -f conftest*]) +if test $hurd_cv_mig_retcode = yes; then + AC_DEFINE(HAVE_MIG_RETCODE) +fi]) + +hurd_MIG_RETCODE diff --git a/libc/sysdeps/mach/getloadavg.c b/libc/sysdeps/mach/getloadavg.c new file mode 100644 index 000000000..db3be248b --- /dev/null +++ b/libc/sysdeps/mach/getloadavg.c @@ -0,0 +1,54 @@ +/* Get system load averages. Mach version. + Copyright (C) 1999, 2000 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 <mach.h> +#include <mach/host_info.h> +#include <hurd.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> + + +/* Put the 1 minute, 5 minute and 15 minute load averages + into the first NELEM elements of LOADAVG. + Return the number written (never more than 3, but may be less than NELEM), + or -1 if an error occurred. */ + +int +getloadavg (double loadavg[], int nelem) +{ + host_load_info_data_t info; + mach_msg_type_number_t size = HOST_LOAD_INFO_COUNT; + error_t err; + int i; + + err = __host_info (__mach_host_self (), HOST_LOAD_INFO, + (host_info_t) &info, &size); + if (err) + return __hurd_fail (err); + if (size < HOST_LOAD_INFO_COUNT) + return __hurd_fail (EGRATUITOUS); + + if (nelem > 3) + nelem = 3; + for (i = 0; i < nelem; ++i) + loadavg[i] = (double) info.avenrun[i] / (double) LOAD_SCALE; + + return i; +} diff --git a/libc/sysdeps/mach/getpagesize.c b/libc/sysdeps/mach/getpagesize.c new file mode 100644 index 000000000..a3140a4ab --- /dev/null +++ b/libc/sysdeps/mach/getpagesize.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1995, 1996, 2002 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 <unistd.h> +#include <mach.h> + +/* Return the system page size. */ +int +__getpagesize () +{ + return __vm_page_size; +} +libc_hidden_def (__getpagesize) +weak_alias (__getpagesize, getpagesize) diff --git a/libc/sysdeps/mach/getsysstats.c b/libc/sysdeps/mach/getsysstats.c new file mode 100644 index 000000000..d2bebb621 --- /dev/null +++ b/libc/sysdeps/mach/getsysstats.c @@ -0,0 +1,102 @@ +/* System dependent pieces of sysconf; Mach version + Copyright (C) 1996,97,99,2001,02 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 <mach.h> +#include <hurd.h> +#include <sys/sysinfo.h> + + +/* Return the number of processors configured on the system. */ +int +__get_nprocs_conf () +{ + struct host_basic_info hbi; + kern_return_t err; + mach_msg_type_number_t cnt = HOST_BASIC_INFO_COUNT; + + err = __host_info (__mach_host_self (), HOST_BASIC_INFO, + (host_info_t) &hbi, &cnt); + if (err) + return __hurd_fail (err); + else if (cnt != HOST_BASIC_INFO_COUNT) + return __hurd_fail (EIEIO); + + return hbi.max_cpus; +} + +/* Return the number of processors currently available on the system. */ +int +__get_nprocs () +{ + struct host_basic_info hbi; + kern_return_t err; + mach_msg_type_number_t cnt = HOST_BASIC_INFO_COUNT; + + err = __host_info (__mach_host_self (), HOST_BASIC_INFO, + (host_info_t) &hbi, &cnt); + if (err) + return __hurd_fail (err); + else if (cnt != HOST_BASIC_INFO_COUNT) + return __hurd_fail (EIEIO); + + return hbi.avail_cpus; +} + +/* Return the number of physical pages on the system. */ +long int +__get_phys_pages () +{ + struct host_basic_info hbi; + kern_return_t err; + mach_msg_type_number_t cnt = HOST_BASIC_INFO_COUNT; + + err = __host_info (__mach_host_self (), HOST_BASIC_INFO, + (host_info_t) &hbi, &cnt); + if (err) + return __hurd_fail (err); + else if (cnt != HOST_BASIC_INFO_COUNT) + return __hurd_fail (EIEIO); + + return hbi.memory_size / __vm_page_size; +} + +/* Return the number of available physical pages */ +long int +__get_avphys_pages () +{ + vm_statistics_data_t vs; + kern_return_t err; + +#ifdef HOST_VM_INFO + { + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + err = __host_info (__mach_host_self (), HOST_VM_INFO, + (host_info_t) &vs, &count); + if (!err && count < HOST_VM_INFO_COUNT) + err = EGRATUITOUS; + } +#else + err = __vm_statistics (__mach_task_self (), &vs); +#endif + if (err) + return __hurd_fail (err); + + return vs.free_count; +} diff --git a/libc/sysdeps/mach/gettimeofday.c b/libc/sysdeps/mach/gettimeofday.c new file mode 100644 index 000000000..7eb60c4b5 --- /dev/null +++ b/libc/sysdeps/mach/gettimeofday.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991,1992,1995-1997,2001,2002 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 <stddef.h> +#include <sys/time.h> +#include <mach.h> + +#undef __gettimeofday + +/* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. */ +int +__gettimeofday (tv, tz) + struct timeval *tv; + struct timezone *tz; +{ + kern_return_t err; + + if (tz != NULL) + *tz = (struct timezone){0, 0}; /* XXX */ + + if (err = __host_get_time (__mach_host_self (), (time_value_t *) tv)) + { + errno = err; + return -1; + } + return 0; +} + +INTDEF(__gettimeofday) +weak_alias (__gettimeofday, gettimeofday) diff --git a/libc/sysdeps/mach/hurd/.cvsignore b/libc/sysdeps/mach/hurd/.cvsignore new file mode 100644 index 000000000..1f69fd919 --- /dev/null +++ b/libc/sysdeps/mach/hurd/.cvsignore @@ -0,0 +1,4 @@ +*.gz *.Z *.tar *.tgz +=* +TODO COPYING* AUTHORS copyr-* copying.* +glibc-* diff --git a/libc/sysdeps/mach/hurd/Implies b/libc/sysdeps/mach/hurd/Implies new file mode 100644 index 000000000..b6063463c --- /dev/null +++ b/libc/sysdeps/mach/hurd/Implies @@ -0,0 +1,5 @@ +# The gnu subdirectory exists for things common to both Linux-based and +# Hurd-based GNU systems. +gnu +# The Hurd provides a rough superset of the functionality of 4.4 BSD. +unix/bsd/bsd4.4 diff --git a/libc/sysdeps/mach/hurd/Makeconfig b/libc/sysdeps/mach/hurd/Makeconfig new file mode 100644 index 000000000..1b65bb07a --- /dev/null +++ b/libc/sysdeps/mach/hurd/Makeconfig @@ -0,0 +1,4 @@ +# We need special startup code for statically linked binaries. +# See Makefile in this directory for the rule that builds this. +# We must define this variable earlier than sysdeps Makefiles are included. +static-start-installed-name = crt0.o diff --git a/libc/sysdeps/mach/hurd/Makefile b/libc/sysdeps/mach/hurd/Makefile new file mode 100644 index 000000000..8677515cd --- /dev/null +++ b/libc/sysdeps/mach/hurd/Makefile @@ -0,0 +1,209 @@ +# Copyright (C) 1993,94,95,96,97,98,99,2000,2001,2002, 2003, 2004 +# 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. + +ifdef in-Makerules + +# Look for header files in hurd/ under the top-level library source directory. +# Look for generated header files where they get created. +includes += -I$(..)hurd -I$(common-objpfx)hurd/ + +# We use the style `if (err = call(...))' a lot in the Hurd code, +# where we have a lot of functions that return zero or an errno code. ++cflags += -Wno-parentheses + +# Do not use any assembly code from sysdeps/unix (and subdirectories). +# This bypasses all the system call stubs and uses any existing posix or +# generic C files instead. +inhibit-sysdep-asm += unix* +inhibit-unix-syscalls = yes + +# Don't try to generate anything from the installed Unix system and its +# libraries. That is only of use when building for a Unix system, so as to +# be compatible with some existing binaries for that system. +inhibit-glue = yes + +ifeq (,$(filter mach hurd,$(subdir))) +# Subdirectories other than hurd/ might use the generated Hurd headers. +# So make sure we get a chance to run in hurd/ to make them before all else. +# (But we don't want to do this in mach/, because hurd/ needs some things +# there, and we know mach/ doesn't need anything from hurd/.) + +hurd-objpfx = $(common-objpfx)hurd/ + +# These are all the generated headers that <hurd.h> includes. +before-compile += $(patsubst %,$(hurd-objpfx)hurd/%.h,auth io fs process) +$(patsubst %,$(hurd-objpfx)hurd/%.%,auth io fs process): \ + $(common-objpfx)mach/mach-shortcuts.h + $(MAKE) -C $(..)hurd before-compile no_deps=t +endif + +# Hurd profil.c includes this file, so give a rule to make it. +ifeq ($(subdir),gmon) +$(common-objpfx)hurd/../mach/RPC_task_get_sampled_pcs.c: + $(MAKE) -C $(..)mach before-compile no_deps=t +endif + + +# Generate bits/errno.h from the section of the manual that lists all the errno +# codes. + +errno.texinfo = $(..)manual/errno.texi + +hurd = $(..)sysdeps/mach/hurd + +define mach-errno-h +($(foreach h,mach/message.h \ + mach/kern_return.h \ + mach/mig_errors.h \ + device/device_types.h,\ + echo '#include <$h>';\ + )) +endef + +# We use the compiler to generate a list of absolute file names for +# the headers we want to search for Mach error codes, listed above (and +# incidentally, all other headers those include). +-include $(common-objpfx)errnos.d +$(common-objpfx)errnos.d: $(mach-errnos-deps) + $(mach-errno-h) | \ + $(CC) $(CFLAGS) $(CPPFLAGS) -M -x c - | \ + sed $(sed-remove-objpfx) -e 's,- *:,mach-errnos-deps :=,' \ + -e 's, \.\./, $(..),g' > $@t + mv -f $@t $@ + +$(hurd)/bits/errno.h: $(common-objpfx)stamp-errnos ; +$(common-objpfx)stamp-errnos: $(hurd)/errnos.awk $(errno.texinfo) \ + $(mach-errnos-deps) $(common-objpfx)errnos.d + $(AWK) -f $^ > $(hurd)/bits/errno.h-tmp +# Make it unwritable so noone will edit it by mistake. + -chmod a-w $(hurd)/bits/errno.h-tmp + $(move-if-change) $(hurd)/bits/errno.h-tmp $(hurd)/bits/errno.h +ifeq ($(with-cvs),yes) + test ! -d $(hurd)/CVS || \ + (cd $(hurd) && cvs commit -m'Regenerated from $^' bits/errno.h) +endif + touch $@ + +common-generated += errnos.d stamp-errnos + +# We install the real libc.a as libcrt.a and as libc.a we install a linker +# script which does -( -lcrt -lmachuser -lhurduser -). + +libc-name = crt + +ifeq (,$(subdir)) +install-others += $(inst_libdir)/libc.a +$(inst_libdir)/libc.a: $(hurd)/libc-ldscript $(+force); $(do-install) +ifeq (yes,$(build-profile)) +install-others += $(inst_libdir)/libc_p.a +$(inst_libdir)/libc_p.a: $(hurd)/libc_p-ldscript $(+force); $(do-install) +endif +endif + +# Make sure these are used to build the libc.so shared object too. There +# is a circular dependency between each of these shared objects and libc +# (many high-level libc functions call stubs, stubs call low-level libc +# functions like memcpy and mach_msg). This works out fine at run time +# (all the objects are loaded before resolving their symbols, so these +# interdependencies are fine). But to create the shared objects we must +# link them one at a time; since each needs one or both of the others to +# produce its DT_NEEDED entries and to assign its undefined symbols the +# right symbol versions, we can't do any of them before the others! To +# get around this, we link each lib*user.so shared object twice. First, +# we link an object without reference to libc.so (since we haven't linked +# libc.so yet), so it lacks a DT_NEEDED record for the libc soname it +# depends on, and its undefined symbol references lack the symbol version +# assignments they should have. We will use this shared object solely to +# link libc.so against it; that gives libc.so the proper DT_NEEDED record, +# and symbol versions assignments (if the lib*user.so object is using them). +# Finally we link a second version of the same lib*user.so shared object, +# this time linked normally against libc so it gets a proper DT_NEEDED +# record and symbol version set; this one can be installed for run-time use. +rpcuserlibs := $(common-objpfx)mach/libmachuser.so \ + $(common-objpfx)hurd/libhurduser.so +link-rpcuserlibs := $(rpcuserlibs:%user.so=%user-link.so) +$(common-objpfx)libc.so: $(link-rpcuserlibs) +rpath-dirs += mach hurd + +# Make sure the `lib' pass builds the dummy shared objects so +# we can link libc against them. +ifeq (mach,$(subdir)) +lib-noranlib: $(common-objpfx)mach/libmachuser-link.so +endif +ifeq (hurd,$(subdir)) +lib-noranlib: $(common-objpfx)hurd/libhurduser-link.so +endif + +$(link-rpcuserlibs): %-link.so: %_pic.a +# These shared objects are just for the purpose of linking libc, +# so they don't need abi-note.o linked into them. + $(build-shlib-helper) \ + -nostdlib -o $@ \ + -Wl,-soname=$(*F).so$($(*F).so-version) \ + $(build-shlib-objlist) +libmachuser-link.so-no-z-defs = yes +libhurduser-link.so-no-z-defs = yes + +# And get them into the libc.so ldscript. +$(inst_libdir)/libc.so: $(rpcuserlibs) + +# The RPC stubs from these libraries are needed in building the dynamic +# linker, too. It must be self-contained, so we link the needed PIC +# objects directly into the shared object. +ifeq (elf,$(subdir)) +$(objpfx)librtld.map: $(rpcuserlibs:.so=_pic.a) + +CFLAGS-dl-load.c = -DEXTERNAL_MAP_FROM_FD +endif + +# We need these libs to link static programs in the libc source tree, too. +ifeq (yes,$(build-static)) +link-libc-static := -Wl,-\( \ + $(patsubst %,$(common-objpfx)%.a,\ + libc mach/libmachuser hurd/libhurduser) \ + $(static-gnulib) -Wl,-\) +else +ifeq (yes,$(build-shared)) +# We can try to link the programs with lib*_pic.a... +link-libc-static := $(link-libc) -Wl,-\( \ + $(patsubst %,$(common-objpfx)%_pic.a,\ + libc mach/libmachuser hurd/libhurduser) \ + $(static-gnulib) -Wl,-\) +endif +endif + +ifeq ($(subdir),csu) + +extra-objs += static-start.o + +# We need special startup code for statically linked binaries. +$(objpfx)crt0.o: $(objpfx)static-start.o $(objpfx)abi-note.o $(objpfx)init.o + $(link-relocatable) + +endif + +ifeq (hurd, $(subdir)) +sysdep_routines += cthreads +endif + +ifeq ($(subdir),sunrpc) +sysdep_headers += nfs/nfs.h +endif + +endif # in-Makerules diff --git a/libc/sysdeps/mach/hurd/Subdirs b/libc/sysdeps/mach/hurd/Subdirs new file mode 100644 index 000000000..7a7757582 --- /dev/null +++ b/libc/sysdeps/mach/hurd/Subdirs @@ -0,0 +1,9 @@ +# This file says that the hurd subdirectory should appear before all others. +# The mach and hurd subdirectories have many generated header files which +# much of the rest of the library depends on, so it is best to build them +# first (and mach before hurd, at that). The before-compile additions in +# sysdeps/{mach,hurd}/Makefile should make it reliably work for these files +# not to exist when making in other directories, but it will be slower that +# way with more somewhat expensive `make' invocations. + +first hurd diff --git a/libc/sysdeps/mach/hurd/Versions b/libc/sysdeps/mach/hurd/Versions new file mode 100644 index 000000000..89e19061a --- /dev/null +++ b/libc/sysdeps/mach/hurd/Versions @@ -0,0 +1,37 @@ +libc { + GLIBC_2.0 { + # functions with a weak definition in the dynamic linker + __getcwd; __mmap; + } + GLIBC_PRIVATE { + # Functions shared with the dynamic linker + __libc_read; __libc_write; __libc_lseek64; + + _dl_init_first; + } +} + +ld { + GLIBC_2.0 { + # variables that must be shared with libc + __hurd_sigthread_stack_base; __hurd_sigthread_stack_end; + __hurd_sigthread_variables; + __hurd_threadvar_stack_mask; __hurd_threadvar_stack_offset; + + # functions that must be shared with libc + __close; __getcwd; __getpid; + __mmap; __open; __xstat64; __fxstat64; + _exit; _hurd_intr_rpc_mach_msg; + abort; + } + GLIBC_2.2.6 { + # this also must be shared with libc. + __errno_location; + } + GLIBC_PRIVATE { + _dl_init_first; + + # functions that must be shared with libc + __libc_read; __libc_write; __libc_lseek64; + } +} diff --git a/libc/sysdeps/mach/hurd/_G_config.h b/libc/sysdeps/mach/hurd/_G_config.h new file mode 100644 index 000000000..b64305923 --- /dev/null +++ b/libc/sysdeps/mach/hurd/_G_config.h @@ -0,0 +1,102 @@ +/* This file is needed by libio to define various configuration parameters. + These are always the same in the GNU C library. */ + +#ifndef _G_config_h +#define _G_config_h 1 + +/* Define types for libio in terms of the standard internal type names. */ + +#include <bits/types.h> +#define __need_size_t +#define __need_wchar_t +#define __need_wint_t +#define __need_NULL +#include <stddef.h> +#ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +#endif +#define __need_mbstate_t +#include <wchar.h> +#define _G_size_t size_t +typedef struct +{ + __off_t __pos; + __mbstate_t __state; +} _G_fpos_t; +typedef struct +{ + __off64_t __pos; + __mbstate_t __state; +} _G_fpos64_t; +#define _G_ssize_t __ssize_t +#define _G_off_t __off_t +#define _G_off64_t __off64_t +#define _G_pid_t __pid_t +#define _G_uid_t __uid_t +#define _G_wchar_t wchar_t +#define _G_wint_t wint_t +#define _G_stat64 stat64 +#include <gconv.h> +typedef union +{ + struct __gconv_info __cd; + struct + { + struct __gconv_info __cd; + struct __gconv_step_data __data; + } __combined; +} _G_iconv_t; + +typedef int _G_int16_t __attribute__ ((__mode__ (__HI__))); +typedef int _G_int32_t __attribute__ ((__mode__ (__SI__))); +typedef unsigned int _G_uint16_t __attribute__ ((__mode__ (__HI__))); +typedef unsigned int _G_uint32_t __attribute__ ((__mode__ (__SI__))); + +#define _G_HAVE_BOOL 1 + + +/* These library features are always available in the GNU C library. */ +#define _G_HAVE_ATEXIT 1 +#define _G_HAVE_SYS_CDEFS 1 +#define _G_HAVE_SYS_WAIT 1 +#define _G_NEED_STDARG_H 1 +#define _G_va_list __gnuc_va_list + +#define _G_HAVE_PRINTF_FP 1 +#define _G_HAVE_MMAP 1 +#define _G_HAVE_LONG_DOUBLE_IO 1 +#define _G_HAVE_IO_FILE_OPEN 1 +#define _G_HAVE_IO_GETLINE_INFO 1 + +#define _G_IO_IO_FILE_VERSION 0x20001 + +#define _G_OPEN64 __open64 +#define _G_LSEEK64 __lseek64 +#define _G_MMAP64 __mmap64 +#define _G_FSTAT64(fd,buf) __fxstat64 (_STAT_VER, fd, buf) + +/* This is defined by <bits/stat.h> if `st_blksize' exists. */ +#define _G_HAVE_ST_BLKSIZE defined (_STATBUF_ST_BLKSIZE) + +#define _G_BUFSIZ 8192 + +/* These are the vtbl details for ELF. */ +#define _G_NAMES_HAVE_UNDERSCORE 0 +#define _G_VTABLE_LABEL_HAS_LENGTH 1 +#define _G_USING_THUNKS 1 +#define _G_VTABLE_LABEL_PREFIX "__vt_" +#define _G_VTABLE_LABEL_PREFIX_ID __vt_ + + +#if defined __cplusplus || defined __STDC__ +# define _G_ARGS(ARGLIST) ARGLIST +#else +# define _G_ARGS(ARGLIST) () +#endif + +#endif /* _G_config.h */ diff --git a/libc/sysdeps/mach/hurd/_exit.c b/libc/sysdeps/mach/hurd/_exit.c new file mode 100644 index 000000000..af0337b30 --- /dev/null +++ b/libc/sysdeps/mach/hurd/_exit.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1993,94,95,96,97,99,2002 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 <unistd.h> +#include <hurd.h> +#include <hurd/port.h> +#include <sysdep.h> +#include <sys/wait.h> + +void +_hurd_exit (int status) +{ + /* Give the proc server our exit status. */ + __USEPORT (PROC, __proc_mark_exit (port, status, 0)); + + /* Commit suicide. */ + __task_terminate (__mach_task_self ()); + + /* Perhaps the cached mach_task_self was bogus. */ + __task_terminate ((__mach_task_self) ()); + + /* This sucker really doesn't want to die. */ + while (1) + { +#ifdef LOSE + LOSE; +#else + volatile const int zero = 0, one = 1; + volatile int lossage = one / zero; +#endif + } +} + +void +_exit (status) + int status; +{ + _hurd_exit (W_EXITCODE (status, 0)); +} +libc_hidden_def (_exit) +weak_alias (_exit, _Exit) diff --git a/libc/sysdeps/mach/hurd/accept.c b/libc/sysdeps/mach/hurd/accept.c new file mode 100644 index 000000000..362c42c5b --- /dev/null +++ b/libc/sysdeps/mach/hurd/accept.c @@ -0,0 +1,87 @@ +/* Copyright (C) 1992,1993,1994,1997,1999,2002 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 <fcntl.h> +#include <string.h> +#include <sys/socket.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> + +/* Await a connection on socket FD. + When a connection arrives, open a new socket to communicate with it, + set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting + peer and *ADDR_LEN to the address's actual length, and return the + new socket's descriptor, or -1 for errors. */ +int +accept (fd, addrarg, addr_len) + int fd; + __SOCKADDR_ARG addrarg; + socklen_t *addr_len; +{ + error_t err; + socket_t new; + addr_port_t aport; + struct sockaddr *addr = addrarg.__sockaddr__; + char *buf = (char *) addr; + mach_msg_type_number_t buflen; + int type; + + if (err = HURD_DPORT_USE (fd, __socket_accept (port, &new, &aport))) + return __hurd_dfail (fd, err); + + if (addr != NULL) + { + buflen = *addr_len; + err = __socket_whatis_address (aport, &type, &buf, &buflen); + if (err == EOPNOTSUPP) + /* If the protocol server can't tell us the address, just return a + zero-length one. */ + { + buf = (char *)addr; + buflen = 0; + err = 0; + } + } + __mach_port_deallocate (__mach_task_self (), aport); + + if (err) + { + __mach_port_deallocate (__mach_task_self (), new); + return __hurd_dfail (fd, err); + } + + if (addr != NULL) + { + if (*addr_len > buflen) + *addr_len = buflen; + + if (buf != (char *) addr) + { + memcpy (addr, buf, *addr_len); + __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen); + } + + if (buflen > 0) + addr->sa_family = type; + } + + return _hurd_intern_fd (new, O_IGNORE_CTTY, 1); +} +libc_hidden_def (accept) diff --git a/libc/sysdeps/mach/hurd/access.c b/libc/sysdeps/mach/hurd/access.c new file mode 100644 index 000000000..22eb9668b --- /dev/null +++ b/libc/sysdeps/mach/hurd/access.c @@ -0,0 +1,149 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 <unistd.h> +#include <hurd.h> +#include <hurd/port.h> +#include <hurd/id.h> +#include <hurd/lookup.h> +#include <fcntl.h> + +/* Test for access to FILE by our real user and group IDs. */ +int +__access (file, type) + const char *file; + int type; +{ + error_t err; + file_t rcrdir, rcwdir, io; + int flags, allowed; + + error_t reauthenticate (int which, file_t *result) + { + /* Get a port to our root directory, authenticated with the real IDs. */ + error_t err; + mach_port_t ref; + ref = __mach_reply_port (); + err = HURD_PORT_USE + (&_hurd_ports[which], + ({ + err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + err = __auth_user_authenticate (_hurd_id.rid_auth, + ref, MACH_MSG_TYPE_MAKE_SEND, + result); + err; + })); + __mach_port_destroy (__mach_task_self (), ref); + return err; + } + + error_t init_port (int which, error_t (*operate) (mach_port_t)) + { + switch (which) + { + case INIT_PORT_AUTH: + return (*operate) (_hurd_id.rid_auth); + case INIT_PORT_CRDIR: + return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?: + (*operate) (rcrdir)); + case INIT_PORT_CWDIR: + return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?: + (*operate) (rcwdir)); + default: + return _hurd_ports_use (which, operate); + } + } + + rcrdir = rcwdir = MACH_PORT_NULL; + + HURD_CRITICAL_BEGIN; + + __mutex_lock (&_hurd_id.lock); + /* Get _hurd_id up to date. */ + if (err = _hurd_check_ids ()) + goto lose; + + if (_hurd_id.rid_auth == MACH_PORT_NULL) + { + /* Set up _hurd_id.rid_auth. This is a special auth server port + which uses the real uid and gid (the first aux uid and gid) as + the only effective uid and gid. */ + + if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1) + { + /* We do not have a real UID and GID. Lose, lose, lose! */ + err = EGRATUITOUS; + goto lose; + } + + /* Create a new auth port using our real UID and GID (the first + auxiliary UID and GID) as the only effective IDs. */ + if (err = __USEPORT (AUTH, + __auth_makeauth (port, + NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.aux.uids, 1, + _hurd_id.aux.uids, + _hurd_id.aux.nuids, + _hurd_id.aux.gids, 1, + _hurd_id.aux.gids, + _hurd_id.aux.ngids, + &_hurd_id.rid_auth))) + goto lose; + } + + if (!err) + /* Look up the file name using the modified init ports. */ + err = __hurd_file_name_lookup (&init_port, &__getdport, 0, + file, 0, 0, &io); + + /* We are done with _hurd_id.rid_auth now. */ + lose: + __mutex_unlock (&_hurd_id.lock); + + HURD_CRITICAL_END; + + if (rcrdir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), rcrdir); + if (rcwdir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), rcwdir); + if (err) + return __hurd_fail (err); + + /* Find out what types of access we are allowed to this file. */ + err = __file_check_access (io, &allowed); + __mach_port_deallocate (__mach_task_self (), io); + if (err) + return __hurd_fail (err); + + flags = 0; + if (type & R_OK) + flags |= O_READ; + if (type & W_OK) + flags |= O_WRITE; + if (type & X_OK) + flags |= O_EXEC; + + if (flags & ~allowed) + /* We are not allowed all the requested types of access. */ + return __hurd_fail (EACCES); + + return 0; +} + +weak_alias (__access, access) diff --git a/libc/sysdeps/mach/hurd/adjtime.c b/libc/sysdeps/mach/hurd/adjtime.c new file mode 100644 index 000000000..cc9cd7d40 --- /dev/null +++ b/libc/sysdeps/mach/hurd/adjtime.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1991,93,95,97,2001 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/time.h> +#include <hurd.h> + +/* Adjust the current time of day by the amount in DELTA. + If OLDDELTA is not NULL, it is filled in with the amount + of time adjustment remaining to be done from the last `__adjtime' call. + This call is restricted to the super-user. */ +int +__adjtime (delta, olddelta) + const struct timeval *delta; + struct timeval *olddelta; +{ + error_t err; + mach_port_t hostpriv; + + err = __get_privileged_ports (&hostpriv, NULL); + if (err) + return __hurd_fail (EPERM); + + err = __host_adjust_time (hostpriv, + /* `time_value_t' and `struct timeval' are in + fact identical with the names changed. */ + *(time_value_t *) delta, + (time_value_t *) olddelta); + __mach_port_deallocate (__mach_task_self (), hostpriv); + + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__adjtime, adjtime) diff --git a/libc/sysdeps/mach/hurd/alpha/bits/sigcontext.h b/libc/sysdeps/mach/hurd/alpha/bits/sigcontext.h new file mode 100644 index 000000000..4f13a2c9b --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/bits/sigcontext.h @@ -0,0 +1,73 @@ +/* Machine-dependent signal context structure for GNU Hurd. Alpha version. + Copyright (C) 1994,97,2001 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. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead." +#endif + +#ifndef sc_alpha_thread_state + +/* Signal handlers are actually called: + void handler (int sig, int code, struct sigcontext *scp); */ + +/* State of this thread when the signal was taken. */ +struct sigcontext + { + /* These first members are machine-independent. */ + + long int sc_onstack; /* Nonzero if running on sigstack. */ + __sigset_t sc_mask; /* Blocked signals to restore. */ + + /* MiG reply port this thread is using. */ + unsigned long int sc_reply_port; + + /* Port this thread is doing an interruptible RPC on. */ + unsigned long int sc_intr_port; + + /* Error code associated with this signal (interpreted as `error_t'). */ + int sc_error; + + /* All following members are machine-dependent. The rest of this + structure is written to be laid out identically to: + { + struct alpha_thread_state basic; + struct alpha_exc_state exc; + struct alpha_float_state fpu; + } + trampoline.c knows this, so it must be changed if this changes. */ + +#define sc_alpha_thread_state sc_regs /* Beginning of correspondence. */ + long int sc_regs[31]; /* General registers $0..$30. */ + long int sc_pc; /* Program counter. */ + + /* struct alpha_exc_state */ +#define sc_alpha_exc_state sc_badvaddr + unsigned long int sc_badvaddr; + unsigned int sc_cause; /* Machine-level trap code. */ +#define SC_CAUSE_SET_SSTEP 1 + int sc_used_fpa; /* Nonzero if FPU was used. */ + + /* struct alpha_float_state + This is only filled in if sc_used_fpa is nonzero. */ +#define sc_alpha_float_state sc_fpregs + double sc_fpregs[31]; /* Floating point registers $f0..$f30. */ + long int sc_fpcsr; /* Floating point control/status register. */ + }; + +#endif /* sc_alpha_thread_state */ diff --git a/libc/sysdeps/mach/hurd/alpha/exc2signal.c b/libc/sysdeps/mach/hurd/alpha/exc2signal.c new file mode 100644 index 000000000..5f3fbbbbb --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/exc2signal.c @@ -0,0 +1,75 @@ +/* Translate Mach exception codes into signal numbers. Alpha version. + Copyright (C) 1994,97,2002 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 <hurd.h> +#include <hurd/signal.h> +#include <mach/exception.h> + +/* 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) +{ + detail->error = 0; + + switch (detail->exc) + { + default: + *signo = SIGIOT; + detail->code = detail->exc; + break; + + case EXC_BAD_ACCESS: + if (detail->exc_code == KERN_PROTECTION_FAILURE) + *signo = SIGSEGV; + else + *signo = SIGBUS; + detail->code = detail->exc_subcode; + detail->error = detail->exc_code; + break; + + case EXC_BAD_INSTRUCTION: + *signo = SIGILL; + detail->code = detail->exc_code; + break; + + case EXC_ARITHMETIC: + *signo = SIGFPE; + detail->code = detail->exc_code; + break; + break; + + case EXC_EMULATION: + /* 3.0 doesn't give this one, why, I don't know. */ + *signo = SIGEMT; + detail->code = detail->exc_code; + break; + + case EXC_SOFTWARE: + *signo = SIGEMT; + detail->code = detail->exc_code; + break; + + case EXC_BREAKPOINT: + *signo = SIGTRAP; + detail->code = detail->exc_code; + break; + } +} diff --git a/libc/sysdeps/mach/hurd/alpha/init-first.c b/libc/sysdeps/mach/hurd/alpha/init-first.c new file mode 100644 index 000000000..6e5522589 --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/init-first.c @@ -0,0 +1,302 @@ +/* Initialization code run first thing by the ELF startup code. Alpha/Hurd. + Copyright (C) 1995,96,97,98,99,2000,01,02,03 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 <assert.h> +#include <hurd.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sysdep.h> +#include <set-hooks.h> +#include "hurdstartup.h" +#include "hurdmalloc.h" /* XXX */ + +extern void __mach_init (void); +extern void __init_misc (int, char **, char **); +#ifdef USE_NONOPTION_FLAGS +extern void __getopt_clean_environment (char **); +#endif +#ifndef SHARED +extern void _dl_non_dynamic_init (void) internal_function; +#endif +extern void __libc_global_ctors (void); + +unsigned int __hurd_threadvar_max; +unsigned long int __hurd_threadvar_stack_offset; +unsigned long int __hurd_threadvar_stack_mask; + +#ifndef SHARED +int __libc_enable_secure; +#endif +int __libc_multiple_libcs attribute_hidden = 1; + +extern int __libc_argc attribute_hidden; +extern char **__libc_argv attribute_hidden; +extern char **_dl_argv; + +void *(*_cthread_init_routine) (void); /* Returns new SP to use. */ +void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__)); + +/* Things that want to be run before _hurd_init or much anything else. + Importantly, these are called before anything tries to use malloc. */ +DEFINE_HOOK (_hurd_preinit_hook, (void)); + + +/* We call this once the Hurd magic is all set up and we are ready to be a + Posixoid program. This does the same things the generic version does. */ +static void +posixland_init (int argc, char **argv, char **envp) +{ + __libc_argc = argc; + __libc_argv = argv; + __environ = envp; + +#ifndef SHARED + _dl_non_dynamic_init (); +#endif + __init_misc (argc, argv, envp); + +#ifdef USE_NONOPTION_FLAGS + /* This is a hack to make the special getopt in GNU libc working. */ + __getopt_clean_environment (envp); +#endif + +#ifdef SHARED + __libc_global_ctors (); +#endif +} + + +static void +init1 (intptr_t *data) +{ + int argc = (intptr_t) *data; + char **argv = (char **) &data[1]; + char **envp = &argv[argc + 1]; + struct hurd_startup_data *d; + + while (*envp) + ++envp; + d = (void *) ++envp; + + /* 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. */ + /* OSF Mach starts the bootstrap task with argc == 0. + XXX This fails if a non-bootstrap task gets started + with argc == 0. */ + if (argc && (void *) d != argv[0]) + { + _hurd_init_dtable = d->dtable; + _hurd_init_dtablesize = d->dtablesize; + + { + /* Check if the stack we are now on is different from + the one described by _hurd_stack_{base,size}. */ + + char dummy; + const vm_address_t newsp = (vm_address_t) &dummy; + + if (d->stack_size != 0 && (newsp < d->stack_base || + newsp - d->stack_base > d->stack_size)) + /* The new stack pointer does not intersect with the + stack the exec server set up for us, so free that stack. */ + __vm_deallocate (__mach_task_self (), d->stack_base, d->stack_size); + } + } + + if ((void *) d != argv[0] && (d->portarray || d->intarray)) + /* Initialize library data structures, start signal processing, etc. */ + _hurd_init (d->flags, argv, + d->portarray, d->portarraysize, + d->intarray, d->intarraysize); + +#ifndef SHARED + __libc_enable_secure = d->flags & EXEC_SECURE; +#endif +} + + +static inline void +init (intptr_t *data) +{ + int argc = *data; + char **argv = (void *) (data + 1); + char **envp = &argv[argc + 1]; + struct hurd_startup_data *d; + unsigned long int threadvars[_HURD_THREADVAR_MAX]; + + /* Provide temporary storage for thread-specific variables on the + startup stack so the cthreads initialization code can use them + for malloc et al, or so we can use malloc below for the real + threadvars array. */ + memset (threadvars, 0, sizeof threadvars); + __hurd_threadvar_stack_offset = (unsigned long int) threadvars; + + /* Since the cthreads initialization code uses malloc, and the + malloc initialization code needs to get at the environment, make + sure we can find it. We'll need to do this again later on since + switching stacks changes the location where the environment is + stored. */ + __environ = envp; + + while (*envp) + ++envp; + d = (void *) ++envp; + + /* The user might have defined a value for this, to get more variables. + Otherwise it will be zero on startup. We must make sure it is set + properly before before cthreads initialization, so cthreads can know + how much space to leave for thread variables. */ + if (__hurd_threadvar_max < _HURD_THREADVAR_MAX) + __hurd_threadvar_max = _HURD_THREADVAR_MAX; + + + /* After possibly switching stacks, call `init1' (above) with the user + code as the return address, and the argument data immediately above + that on the stack. */ + + if (_cthread_init_routine) + { + /* Initialize cthreads, which will allocate us a new stack to run on. */ + void *newsp = (*_cthread_init_routine) (); + struct hurd_startup_data *od; + + void switch_stacks (void); + + /* Copy per-thread variables from that temporary + area onto the new cthread stack. */ + memcpy (__hurd_threadvar_location_from_sp (0, newsp), + threadvars, sizeof threadvars); + + /* Copy the argdata from the old stack to the new one. */ + newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data, + (char *) d - (char *) data); + +#ifdef SHARED + /* And readjust the dynamic linker's idea of where the argument + vector lives. */ + assert (_dl_argv == argv); + _dl_argv = (void *) ((int *) newsp + 1); +#endif + + /* Set up the Hurd startup data block immediately following + the argument and environment pointers on the new stack. */ + od = (newsp + ((char *) d - (char *) data)); + if ((void *) argv[0] == d) + /* We were started up by the kernel with arguments on the stack. + There is no Hurd startup data, so zero the block. */ + memset (od, 0, sizeof *od); + else + /* Copy the Hurd startup data block to the new stack. */ + *od = *d; + + /* + Force NEWSP into sp and &init1 into pv, then branch to pv (call init1). + */ + asm volatile ("lda $30,0(%0); lda $27,0(%1); jsr $26,($27)" + : : "r" (newsp), "r" (&init1)); + } + else + { + /* We are not using cthreads, so we will have just a single allocated + area for the per-thread variables of the main user thread. */ + unsigned long int *array; + unsigned int i; + + array = malloc (__hurd_threadvar_max * sizeof (unsigned long int)); + if (array == NULL) + __libc_fatal ("Can't allocate single-threaded thread variables."); + + /* Copy per-thread variables from the temporary array into the + newly malloc'd space. */ + memcpy (array, threadvars, sizeof threadvars); + __hurd_threadvar_stack_offset = (unsigned long int) array; + for (i = _HURD_THREADVAR_MAX; i < __hurd_threadvar_max; ++i) + array[i] = 0; + + init1 (data); + } +} + + +/* Do the first essential initializations that must precede all else. */ +static inline void +first_init (void) +{ + /* Initialize data structures so we can do RPCs. */ + __mach_init (); + + RUN_HOOK (_hurd_preinit_hook, ()); +} + +#ifdef SHARED +/* This function is called specially by the dynamic linker to do early + initialization of the shared C library before normal initializers + expecting a Posixoid environment can run. It gets called with the + stack set up just as the user will see it, so it can switch stacks. */ + +void +_dl_init_first (intptr_t argc, ...) +{ + first_init (); + + init (&argc); +} +#endif + + +#ifdef SHARED +/* The regular posixland initialization is what goes into libc's + normal initializer. */ +/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT + pointer in the dynamic section based solely on that. It is convention + for this function to be in the `.init' section, but the symbol name is + the only thing that really matters!! */ +strong_alias (posixland_init, _init); + +void +__libc_init_first (int argc, char **argv, char **envp) +{ + /* Everything was done in the shared library initializer, _init. */ +} +#else +strong_alias (posixland_init, __libc_init_first); + + +void +_hurd_stack_setup (volatile intptr_t argc, ...) +{ + first_init (); + + _hurd_startup ((void **) &argc, &init); +} +#endif + + +/* This function is defined here so that if this file ever gets into + ld.so we will get a link error. Having this file silently included + in ld.so causes disaster, because the _init definition above will + cause ld.so to gain an init function, which is not a cool thing. */ + +void +_dl_start (void) +{ + abort (); +} diff --git a/libc/sysdeps/mach/hurd/alpha/intr-msg.h b/libc/sysdeps/mach/hurd/alpha/intr-msg.h new file mode 100644 index 000000000..4f172124e --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/intr-msg.h @@ -0,0 +1,100 @@ +/* Machine-dependent details of interruptible RPC messaging. Alpha version. + Copyright (C) 2002 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. */ + +#define INTR_MSG_TRAP(msg, option, send_size, rcv_size, rcv_name, timeout, notify) \ +({ \ + error_t err; \ + asm (".globl _hurd_intr_rpc_msg_do_trap\n" \ + ".globl _hurd_intr_rpc_msg_in_trap\n" \ + " mov %1, $16\n" \ + " mov %2, $17\n" \ + " mov %3, $18\n" \ + " mov %4, $19\n" \ + " mov %5, $20\n" \ + " mov %6, $21\n" \ + " mov %7, $1\n" \ + " lda $0, -25\n" \ + "_hurd_intr_rpc_msg_do_trap: callsys\n" \ + "_hurd_intr_rpc_msg_in_trap: ret\n" \ + : "=r" (err) \ + : "r" (msg), "r" (option), "r" (send_size), "r" (rcv_size), \ + "r" (rcv_name), "r" (timeout), "r" (notify) \ + : "16", "17", "18", "19", "20", "21", "1", "0"); \ + err; \ +}) + +static void inline +INTR_MSG_BACK_OUT (struct alpha_thread_state *state) +{ + return; +} + +#include "hurdfault.h" + +/* This cannot be an inline function because it calls setjmp. */ +#define SYSCALL_EXAMINE(state, callno) \ +({ \ + u_int32_t *p = (void *) ((state)->pc - 4); \ + int result; \ + _hurdsig_catch_memory_fault (p) ? 0 : \ + ({ \ + result = (*p == 0x00000083); \ + _hurdsig_end_catch_fault (); \ + if (result) \ + /* The PC is just after a `callsys' instruction. \ + This is a system call in progress; v0 holds the call number. */ \ + *(callno) = (state)->r0; \ + result; \ + }); \ +}) + +struct mach_msg_trap_args + { + /* This is the order of arguments to mach_msg_trap. */ + mach_msg_header_t *msg; + mach_msg_option_t option; + mach_msg_size_t send_size; + mach_msg_size_t rcv_size; + mach_port_t rcv_name; + mach_msg_timeout_t timeout; + mach_port_t notify; + }; + +/* This cannot be an inline function because it calls setjmp. */ +#define MSG_EXAMINE(state, msgid, rcv_name, send_name, option, timeout) \ +({ \ + mach_msg_header_t *msg = (mach_msg_header_t *) (state)->r16; \ + *(option) = (mach_msg_option_t) (state)->r17; \ + *(rcv_name) = (mach_port_t) (state)->r18; \ + *(timeout) = (mach_msg_timeout_t) (state)->r19; \ + (msg == 0) ? \ + ({ \ + *(send_name) = MACH_PORT_NULL; \ + *(msgid) = 0; \ + 0; \ + }) : \ + (_hurdsig_catch_memory_fault (msg) ? -1 : \ + ({ \ + *(send_name) = msg->msgh_remote_port; \ + *(msgid) = msg->msgh_id; \ + _hurdsig_end_catch_fault (); \ + 0; \ + }) \ + ); \ +}) diff --git a/libc/sysdeps/mach/hurd/alpha/longjmp-ts.c b/libc/sysdeps/mach/hurd/alpha/longjmp-ts.c new file mode 100644 index 000000000..f472dbcb3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/longjmp-ts.c @@ -0,0 +1,49 @@ +/* Perform a `longjmp' on a Mach thread_state. Alpha version. + Copyright (C) 2002, 2006 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 <hurd/signal.h> +#include <setjmp.h> +#include <jmpbuf-offsets.h> +#include <mach/thread_status.h> + + +/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */ + +void +_hurd_longjmp_thread_state (void *state, jmp_buf env, int val) +{ + struct alpha_thread_state *const ts = state; + + ts->r9 = env[0].__jmpbuf[JB_S0]; + ts->r10 = env[0].__jmpbuf[JB_S1]; + ts->r11 = env[0].__jmpbuf[JB_S2]; + ts->r12 = env[0].__jmpbuf[JB_S3]; + ts->r13 = env[0].__jmpbuf[JB_S4]; + ts->r13 = env[0].__jmpbuf[JB_S5]; + ts->pc = env[0].__jmpbuf[JB_PC]; + ts->r15 = env[0].__jmpbuf[JB_FP]; + ts->r30 = env[0].__jmpbuf[JB_SP]; + ts->r0 = val ?: 1; + + /* XXX + To mimic longjmp we ought to restore some fp registers too. + But those registers are in struct alpha_float_state. + The only use of this is in fork, and it probably won't matter. + */ +} diff --git a/libc/sysdeps/mach/hurd/alpha/sigreturn.c b/libc/sysdeps/mach/hurd/alpha/sigreturn.c new file mode 100644 index 000000000..182d4cbd8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/sigreturn.c @@ -0,0 +1,211 @@ +/* Return from signal handler in GNU C library for Hurd. Alpha version. + Copyright (C) 1994,95,97,98,2002 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 <hurd.h> +#include <hurd/signal.h> +#include <hurd/threadvar.h> +#include <hurd/msg.h> +#include <stdlib.h> +#include <string.h> + +int +__sigreturn (struct sigcontext *scp) +{ + struct hurd_sigstate *ss; + mach_port_t *reply_port; + + if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)) + { + errno = EINVAL; + return -1; + } + + ss = _hurd_self_sigstate (); + __spin_lock (&ss->lock); + + /* Restore the set of blocked signals, and the intr_port slot. */ + ss->blocked = scp->sc_mask; + ss->intr_port = scp->sc_intr_port; + + /* Check for pending signals that were blocked by the old set. */ + if (ss->pending & ~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; + /* Clear the intr_port slot, since we are not in fact doing + an interruptible RPC right now. If SS->intr_port is not null, + the SCP context is doing an interruptible RPC, but the signal + thread will examine us while we are blocked in the sig_post RPC. */ + ss->intr_port = MACH_PORT_NULL; + __spin_unlock (&ss->lock); + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + /* If a pending signal was handled, sig_post never returned. */ + __spin_lock (&ss->lock); + } + + if (scp->sc_onstack) + { + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */ + /* XXX cannot unlock until off sigstack */ + abort (); + } + else + __spin_unlock (&ss->lock); + + /* Destroy the MiG reply port used by the signal handler, and restore the + reply port in use by the thread when interrupted. */ + reply_port = + (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); + if (*reply_port) + __mach_port_destroy (__mach_task_self (), *reply_port); + *reply_port = scp->sc_reply_port; + + if (scp->sc_used_fpa) + { + /* Restore FPU state. */ + + /* Restore the floating-point control/status register. + We must do this first because the compiler will need + a temporary FP register for the load. */ + asm volatile ("mt_fpcr %0" : : "f" (scp->sc_fpcsr)); + + /* Restore floating-point registers. */ +#define restore_fpr(n) \ + asm volatile ("ldt $f" #n ",%0" : : "m" (scp->sc_fpregs[n])) + restore_fpr (0); + restore_fpr (1); + restore_fpr (2); + restore_fpr (3); + restore_fpr (4); + restore_fpr (5); + restore_fpr (6); + restore_fpr (7); + restore_fpr (8); + restore_fpr (9); + restore_fpr (10); + restore_fpr (11); + restore_fpr (12); + restore_fpr (13); + restore_fpr (14); + restore_fpr (15); + restore_fpr (16); + restore_fpr (17); + restore_fpr (18); + restore_fpr (19); + restore_fpr (20); + restore_fpr (21); + restore_fpr (22); + restore_fpr (23); + restore_fpr (24); + restore_fpr (25); + restore_fpr (26); + restore_fpr (27); + restore_fpr (28); + restore_fpr (29); + restore_fpr (30); + } + + /* Load all the registers from the sigcontext. */ +#define restore_gpr(n) \ + asm volatile ("ldq $" #n ",%0" : : "m" (scpreg->sc_regs[n])) + + { + /* The `rei' PAL pseudo-instruction restores registers $2..$7, the PC + and processor status. So we can use these few registers for our + working variables. Unfortunately, it finds its data on the stack + and merely pops the SP ($30) over the words of state restored, + allowing no other option for the new SP value. So we must push the + registers and PSW it will to restore, onto the user's stack and let + it pop them from there. */ + register const struct sigcontext *const scpreg asm ("$2") = scp; + register integer_t *usp asm ("$3") = (integer_t *) scpreg->sc_regs[30]; + register integer_t usp_align asm ("$4"); + + /* Push an 8-word "trap frame" onto the user stack for `rei': + registers $2..$7, the PC, and the PSW. */ + + register struct rei_frame + { + integer_t regs[5], pc, ps; + } *rei_frame asm ("$5"); + + usp -= 8; + /* `rei' demands that the stack be aligned to a 64 byte (8 word) + boundary; bits 61..56 of the PSW are OR'd back into the SP value + after popping the 8-word trap frame, so we store (sp % 64) + there and this restores the original user SP. */ + usp_align = (integer_t) usp & 63L; + rei_frame = (void *) ((integer_t) usp & ~63L); + + /* Copy the registers and PC from the sigcontext. */ + memcpy (rei_frame->regs, &scpreg->sc_regs[2], sizeof rei_frame->regs); + rei_frame->pc = scpreg->sc_pc; + + /* Compute the new PS value to be restored. `rei' adds the value at + bits 61..56 to the SP to compensate for the alignment above that + cleared the low 6 bits; bits 5..3 are the new mode/privilege level + (must be >= current mode; 3 == user mode); bits 2..0 are "software", + unused by the processor or kernel (XXX should trampoline save these? + How?); in user mode, `rei' demands that all other bits be zero. */ + rei_frame->ps = (usp_align << 56) | (3 << 3); /* XXX low 3 bits??? */ + + /* Restore the other general registers: everything except $2..$7, which + are in the `rei' trap frame we set up above, and $30, which is the + SP which is popped by `rei'. */ + restore_gpr (1); + restore_gpr (8); + restore_gpr (9); + restore_gpr (10); + restore_gpr (11); + restore_gpr (12); + restore_gpr (13); + restore_gpr (14); + restore_gpr (15); + restore_gpr (16); + restore_gpr (17); + restore_gpr (18); + restore_gpr (19); + restore_gpr (20); + restore_gpr (21); + restore_gpr (22); + restore_gpr (23); + restore_gpr (24); + restore_gpr (25); + restore_gpr (26); + restore_gpr (27); + restore_gpr (28); + restore_gpr (29); + + /* Switch the stack pointer to the trap frame set up on + the user stack and do the magical `rei' PAL call. */ + asm volatile ("mov %0, $30\n" + "call_pal %1" + : : "r" (rei_frame), "i" (63)); /* PAL_rti */ + /* Firewall. */ + asm volatile ("halt"); + } + + /* NOTREACHED */ + return -1; +} + +weak_alias (__sigreturn, sigreturn) diff --git a/libc/sysdeps/mach/hurd/alpha/static-start.S b/libc/sysdeps/mach/hurd/alpha/static-start.S new file mode 100644 index 000000000..a31d0d097 --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/static-start.S @@ -0,0 +1,30 @@ +/* Startup code for statically linked Hurd/Alpha binaries. + Copyright (C) 2002 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 <sysdep.h> + + .text + .align 3 + .globl _start + .type _start,@function +_start: + jsr ra, _hurd_stack_setup + +#define _start _start1 +#include <sysdeps/alpha/elf/start.S> diff --git a/libc/sysdeps/mach/hurd/alpha/trampoline.c b/libc/sysdeps/mach/hurd/alpha/trampoline.c new file mode 100644 index 000000000..2360cbb46 --- /dev/null +++ b/libc/sysdeps/mach/hurd/alpha/trampoline.c @@ -0,0 +1,249 @@ +/* Set thread_state for sighandler, and sigcontext to recover. Alpha version. + Copyright (C) 1994,95,97,98,2002 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 <hurd/signal.h> +#include "thread_state.h" +#include "hurdfault.h" +#include <assert.h> + +struct mach_msg_trap_args + { + /* This is the order of arguments to mach_msg_trap. */ + mach_msg_header_t *msg; + mach_msg_option_t option; + mach_msg_size_t send_size; + mach_msg_size_t rcv_size; + mach_port_t rcv_name; + mach_msg_timeout_t timeout; + mach_port_t notify; + }; + + +struct sigcontext * +_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, + int signo, struct hurd_signal_detail *detail, + int rpc_wait, struct machine_thread_all_state *state) +{ + __label__ trampoline, rpc_wait_trampoline; + void *sigsp; + struct sigcontext *scp; + + if (ss->context) + { + /* We have a previous sigcontext that sigreturn was about + to restore when another signal arrived. We will just base + our setup on that. */ + if (! _hurdsig_catch_memory_fault (ss->context)) + { + memcpy (&state->basic, &ss->context->sc_alpha_thread_state, + sizeof (state->basic)); + memcpy (&state->exc, &ss->context->sc_alpha_exc_state, + sizeof (state->exc)); + state->set = (1 << ALPHA_THREAD_STATE) | (1 << ALPHA_EXC_STATE); + if (state->exc.used_fpa) + { + memcpy (&state->fpu, &ss->context->sc_alpha_float_state, + sizeof (state->fpu)); + state->set |= (1 << ALPHA_FLOAT_STATE); + } + assert (! rpc_wait); + /* The intr_port slot was cleared before sigreturn sent us the + sig_post that made us notice this pending signal, so + _hurd_internal_post_signal wouldn't do interrupt_operation. + After we return, our caller will set SCP->sc_intr_port (in the + new context) from SS->intr_port and clear SS->intr_port. Now + that we are restoring this old context recorded by sigreturn, + we want to restore its intr_port too; so store it in + SS->intr_port now, so it will end up in SCP->sc_intr_port + later. */ + ss->intr_port = ss->context->sc_intr_port; + } + _hurdsig_end_catch_fault (); + + /* If the sigreturn context was bogus, just ignore it. */ + ss->context = NULL; + } + else if (! machine_get_basic_state (ss->thread, state)) + return NULL; + + if ((ss->actions[signo].sa_flags & SA_ONSTACK) && + !(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK))) + { + sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size; + ss->sigaltstack.ss_flags |= SS_ONSTACK; + /* XXX need to set up base of new stack for + per-thread variables, cthreads. */ + } + else + sigsp = (char *) state->basic.SP; + + /* Set up the sigcontext structure on the stack. This is all the stack + needs, since the args are passed in registers (below). */ + sigsp -= sizeof (*scp); + scp = sigsp; + + if (_hurdsig_catch_memory_fault (scp)) + { + /* We got a fault trying to write the stack frame. + We cannot set up the signal handler. + Returning NULL tells our caller, who will nuke us with a SIGILL. */ + return NULL; + } + else + { + /* Set up the sigcontext from the current state of the thread. */ + + scp->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0; + + /* struct sigcontext is laid out so that starting at sc_regs + mimics a struct alpha_thread_state. */ + memcpy (&scp->sc_alpha_thread_state, + &state->basic, sizeof (state->basic)); + + /* struct sigcontext is laid out so that starting at sc_badvaddr + mimics a struct mips_exc_state. */ + if (! machine_get_state (ss->thread, state, ALPHA_EXC_STATE, + &state->exc, &scp->sc_alpha_exc_state, + sizeof (state->exc))) + return NULL; + + if (state->exc.used_fpa && + /* struct sigcontext is laid out so that starting at sc_fpregs + mimics a struct alpha_float_state. This state + is only meaningful if the coprocessor was used. */ + ! machine_get_state (ss->thread, state, ALPHA_FLOAT_STATE, + &state->fpu, + &scp->sc_alpha_float_state, + sizeof (state->fpu))) + return NULL; + + _hurdsig_end_catch_fault (); + } + + /* Modify the thread state to call the trampoline code on the new stack. */ + if (rpc_wait) + { + /* The signalee thread was blocked in a mach_msg_trap system call, + still waiting for a reply. We will have it run the special + trampoline code which retries the message receive before running + the signal handler. + + To do this we change the OPTION argument in its registers to + enable only message reception, since the request message has + already been sent. */ + + /* The system call arguments are stored in consecutive registers + starting with a0 ($16). */ + struct mach_msg_trap_args *args = (void *) &state->basic.r16; + + assert (args->option & MACH_RCV_MSG); + /* Disable the message-send, since it has already completed. The + calls we retry need only wait to receive the reply message. */ + args->option &= ~MACH_SEND_MSG; + + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + + state->basic.pc = (long int) &&rpc_wait_trampoline; + /* After doing the message receive, the trampoline code will need to + update the v0 ($0) value to be restored by sigreturn. To simplify + the assembly code, we pass the address of its slot in SCP to the + trampoline code in at ($28). */ + state->basic.r28 = (long int) &scp->sc_regs[0]; + /* We must preserve the mach_msg_trap args in a0..a5 and t0 + ($16..$21, $1). Pass the handler args to the trampoline code in + t8..t10 ($22.$24). */ + state->basic.r22 = signo; + state->basic.r23 = detail->code; + state->basic.r24 = (long int) scp; + } + else + { + state->basic.pc = (long int) &&trampoline; + state->basic.r16 = signo; + state->basic.r17 = detail->code; + state->basic.r18 = (long int) scp; + } + + state->basic.r30 = (long int) sigsp; /* $30 is the stack pointer. */ + + /* We pass the handler function to the trampoline code in ra ($26). */ + state->basic.r26 = (long int) handler; + /* In the callee-saved register t12/pv ($27), we store the + address of __sigreturn itself, for the trampoline code to use. */ + state->basic.r27 = (long int) &__sigreturn; + /* In the callee-saved register t11/ai ($25), we save the SCP value to pass + to __sigreturn after the handler returns. */ + state->basic.r25 = (long int) scp; + + return scp; + + /* The trampoline code follows. This is not actually executed as part of + this function, it is just convenient to write it that way. */ + + rpc_wait_trampoline: + /* This is the entry point when we have an RPC reply message to receive + before running the handler. The MACH_MSG_SEND bit has already been + cleared in the OPTION argument in our registers. For our convenience, + at ($28) points to the sc_regs[0] member of the sigcontext (saved v0 + ($0)). */ + asm volatile + (/* Retry the interrupted mach_msg system call. */ + "lda $0, -25($31)\n" /* mach_msg_trap */ + "callsys\n" /* Magic system call instruction. */ + /* When the sigcontext was saved, v0 was MACH_RCV_INTERRUPTED. But + now the message receive has completed and the original caller of + the RPC (i.e. the code running when the signal arrived) needs to + see the final return value of the message receive in v0. So + store the new v0 value into the sc_regs[0] member of the sigcontext + (whose address is in at to make this code simpler). */ + "stq $0, 0($28)\n" + /* Since the argument registers needed to have the mach_msg_trap + arguments, we've stored the arguments to the handler function + in registers t8..t10 ($22..$24). */ + "mov $22, $16\n" + "mov $23, $17\n" + "mov $24, $18\n"); + + trampoline: + /* Entry point for running the handler normally. The arguments to the + handler function are already in the standard registers: + + a0 SIGNO + a1 SIGCODE + a2 SCP + + t12 also contains SCP; this value is callee-saved (and so should not get + clobbered by running the handler). We use this saved value to pass to + __sigreturn, so the handler can clobber the argument registers if it + likes. */ + /* Call the handler function, saving return address in ra ($26). */ + asm volatile ("jsr $26, ($26)"); + /* Reset gp ($29) from the return address (here) in ra ($26). */ + asm volatile ("ldgp $29, 0($26)"); + asm volatile ("mov $25, $16"); /* Move saved SCP to argument register. */ + /* Call __sigreturn (SCP); this cannot return. */ + asm volatile ("jmp $31, ($27)"); + + /* NOTREACHED */ + return NULL; +} diff --git a/libc/sysdeps/mach/hurd/bind.c b/libc/sysdeps/mach/hurd/bind.c new file mode 100644 index 000000000..a42b78ac0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bind.c @@ -0,0 +1,125 @@ +/* Copyright (C) 1992,94,95,96,97,98,2001,02 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 <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> +#include <hurd/paths.h> +#include <fcntl.h> +#include <stddef.h> +#include <hurd/ifsock.h> +#include <sys/un.h> +#include <string.h> + +/* Give the socket FD the local address ADDR (which is LEN bytes long). */ +int +__bind (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len) +{ + addr_port_t aport; + error_t err; + const struct sockaddr_un *addr = addrarg.__sockaddr_un__; + + if (addr->sun_family == AF_LOCAL) + { + /* 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 */ + + dir = __file_name_split (name, &n); + if (dir == MACH_PORT_NULL) + return -1; + + /* Create a new, unlinked node in the target directory. */ + err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node); + + if (! err) + { + /* Set the node's translator to make it a local-domain socket. */ + err = __file_set_translator (node, + FS_TRANS_EXCL | FS_TRANS_SET, + FS_TRANS_EXCL | FS_TRANS_SET, 0, + _HURD_IFSOCK, sizeof _HURD_IFSOCK, + MACH_PORT_NULL, + MACH_MSG_TYPE_COPY_SEND); + if (! err) + { + /* Link the node, now a socket, into the target directory. */ + err = __dir_link (dir, node, n, 1); + if (err == EEXIST) + err = EADDRINUSE; + } + __mach_port_deallocate (__mach_task_self (), node); + if (! err) + { + /* Get a port to the ifsock translator. */ + file_t ifsock = __file_name_lookup_under (dir, n, 0, 0); + if (ifsock == MACH_PORT_NULL) + { + err = errno; + /* If we failed, get rid of the node we created. */ + __dir_unlink (dir, n); + } + else + { + /* Get the address port. */ + err = __ifsock_getsockaddr (ifsock, &aport); + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + /* We are not talking to /hurd/ifsock. Probably + someone came in after we linked our node, unlinked + it, and replaced it with a different node, before we + did our lookup. Treat it as if our link had failed + with EEXIST. */ + err = EADDRINUSE; + } + __mach_port_deallocate (__mach_task_self (), ifsock); + } + } + __mach_port_deallocate (__mach_task_self (), dir); + + if (err) + return __hurd_fail (err); + } + else + err = EIEIO; + + err = HURD_DPORT_USE (fd, + ({ + if (err) + err = __socket_create_address (port, + addr->sun_family, + (char *) addr, len, + &aport); + if (! err) + { + err = __socket_bind (port, aport); + __mach_port_deallocate (__mach_task_self (), + aport); + } + err; + })); + + return err ? __hurd_dfail (fd, err) : 0; +} + +weak_alias (__bind, bind) diff --git a/libc/sysdeps/mach/hurd/bits/errno.h b/libc/sysdeps/mach/hurd/bits/errno.h new file mode 100644 index 000000000..a7d57adeb --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/errno.h @@ -0,0 +1,321 @@ +/* This file generated by errnos.awk. */ + +/* The Hurd uses Mach error system 0x10, currently only subsystem 0. */ +#ifndef _HURD_ERRNO +#define _HURD_ERRNO(n) ((0x10 << 26) | ((n) & 0x3fff)) +#endif + +#ifdef _ERRNO_H + +enum __error_t_codes +{ +#undef EDOM +#undef ERANGE + EPERM = _HURD_ERRNO (1), +#define EPERM _HURD_ERRNO (1) /* Operation not permitted */ + ENOENT = _HURD_ERRNO (2), +#define ENOENT _HURD_ERRNO (2) /* No such file or directory */ + ESRCH = _HURD_ERRNO (3), +#define ESRCH _HURD_ERRNO (3) /* No such process */ + EINTR = _HURD_ERRNO (4), +#define EINTR _HURD_ERRNO (4) /* Interrupted system call */ + EIO = _HURD_ERRNO (5), +#define EIO _HURD_ERRNO (5) /* Input/output error */ + ENXIO = _HURD_ERRNO (6), +#define ENXIO _HURD_ERRNO (6) /* No such device or address */ + E2BIG = _HURD_ERRNO (7), +#define E2BIG _HURD_ERRNO (7) /* Argument list too long */ + ENOEXEC = _HURD_ERRNO (8), +#define ENOEXEC _HURD_ERRNO (8) /* Exec format error */ + EBADF = _HURD_ERRNO (9), +#define EBADF _HURD_ERRNO (9) /* Bad file descriptor */ + ECHILD = _HURD_ERRNO (10), +#define ECHILD _HURD_ERRNO (10)/* No child processes */ + EDEADLK = _HURD_ERRNO (11), +#define EDEADLK _HURD_ERRNO (11)/* Resource deadlock avoided */ + ENOMEM = _HURD_ERRNO (12), +#define ENOMEM _HURD_ERRNO (12)/* Cannot allocate memory */ + EACCES = _HURD_ERRNO (13), +#define EACCES _HURD_ERRNO (13)/* Permission denied */ + EFAULT = _HURD_ERRNO (14), +#define EFAULT _HURD_ERRNO (14)/* Bad address */ + ENOTBLK = _HURD_ERRNO (15), +#define ENOTBLK _HURD_ERRNO (15)/* Block device required */ + EBUSY = _HURD_ERRNO (16), +#define EBUSY _HURD_ERRNO (16)/* Device or resource busy */ + EEXIST = _HURD_ERRNO (17), +#define EEXIST _HURD_ERRNO (17)/* File exists */ + EXDEV = _HURD_ERRNO (18), +#define EXDEV _HURD_ERRNO (18)/* Invalid cross-device link */ + ENODEV = _HURD_ERRNO (19), +#define ENODEV _HURD_ERRNO (19)/* No such device */ + ENOTDIR = _HURD_ERRNO (20), +#define ENOTDIR _HURD_ERRNO (20)/* Not a directory */ + EISDIR = _HURD_ERRNO (21), +#define EISDIR _HURD_ERRNO (21)/* Is a directory */ + EINVAL = _HURD_ERRNO (22), +#define EINVAL _HURD_ERRNO (22)/* Invalid argument */ + EMFILE = _HURD_ERRNO (24), +#define EMFILE _HURD_ERRNO (24)/* Too many open files */ + ENFILE = _HURD_ERRNO (23), +#define ENFILE _HURD_ERRNO (23)/* Too many open files in system */ + ENOTTY = _HURD_ERRNO (25), +#define ENOTTY _HURD_ERRNO (25)/* Inappropriate ioctl for device */ + ETXTBSY = _HURD_ERRNO (26), +#define ETXTBSY _HURD_ERRNO (26)/* Text file busy */ + EFBIG = _HURD_ERRNO (27), +#define EFBIG _HURD_ERRNO (27)/* File too large */ + ENOSPC = _HURD_ERRNO (28), +#define ENOSPC _HURD_ERRNO (28)/* No space left on device */ + ESPIPE = _HURD_ERRNO (29), +#define ESPIPE _HURD_ERRNO (29)/* Illegal seek */ + EROFS = _HURD_ERRNO (30), +#define EROFS _HURD_ERRNO (30)/* Read-only file system */ + EMLINK = _HURD_ERRNO (31), +#define EMLINK _HURD_ERRNO (31)/* Too many links */ + EPIPE = _HURD_ERRNO (32), +#define EPIPE _HURD_ERRNO (32)/* Broken pipe */ + EDOM = _HURD_ERRNO (33), +#define EDOM _HURD_ERRNO (33)/* Numerical argument out of domain */ + ERANGE = _HURD_ERRNO (34), +#define ERANGE _HURD_ERRNO (34)/* Numerical result out of range */ + EAGAIN = _HURD_ERRNO (35), +#define EAGAIN _HURD_ERRNO (35)/* Resource temporarily unavailable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ + EINPROGRESS = _HURD_ERRNO (36), +#define EINPROGRESS _HURD_ERRNO (36)/* Operation now in progress */ + EALREADY = _HURD_ERRNO (37), +#define EALREADY _HURD_ERRNO (37)/* Operation already in progress */ + ENOTSOCK = _HURD_ERRNO (38), +#define ENOTSOCK _HURD_ERRNO (38)/* Socket operation on non-socket */ + EMSGSIZE = _HURD_ERRNO (40), +#define EMSGSIZE _HURD_ERRNO (40)/* Message too long */ + EPROTOTYPE = _HURD_ERRNO (41), +#define EPROTOTYPE _HURD_ERRNO (41)/* Protocol wrong type for socket */ + ENOPROTOOPT = _HURD_ERRNO (42), +#define ENOPROTOOPT _HURD_ERRNO (42)/* Protocol not available */ + EPROTONOSUPPORT = _HURD_ERRNO (43), +#define EPROTONOSUPPORT _HURD_ERRNO (43)/* Protocol not supported */ + ESOCKTNOSUPPORT = _HURD_ERRNO (44), +#define ESOCKTNOSUPPORT _HURD_ERRNO (44)/* Socket type not supported */ + EOPNOTSUPP = _HURD_ERRNO (45), +#define EOPNOTSUPP _HURD_ERRNO (45)/* Operation not supported */ + EPFNOSUPPORT = _HURD_ERRNO (46), +#define EPFNOSUPPORT _HURD_ERRNO (46)/* Protocol family not supported */ + EAFNOSUPPORT = _HURD_ERRNO (47), +#define EAFNOSUPPORT _HURD_ERRNO (47)/* Address family not supported by protocol */ + EADDRINUSE = _HURD_ERRNO (48), +#define EADDRINUSE _HURD_ERRNO (48)/* Address already in use */ + EADDRNOTAVAIL = _HURD_ERRNO (49), +#define EADDRNOTAVAIL _HURD_ERRNO (49)/* Cannot assign requested address */ + ENETDOWN = _HURD_ERRNO (50), +#define ENETDOWN _HURD_ERRNO (50)/* Network is down */ + ENETUNREACH = _HURD_ERRNO (51), +#define ENETUNREACH _HURD_ERRNO (51)/* Network is unreachable */ + ENETRESET = _HURD_ERRNO (52), +#define ENETRESET _HURD_ERRNO (52)/* Network dropped connection on reset */ + ECONNABORTED = _HURD_ERRNO (53), +#define ECONNABORTED _HURD_ERRNO (53)/* Software caused connection abort */ + ECONNRESET = _HURD_ERRNO (54), +#define ECONNRESET _HURD_ERRNO (54)/* Connection reset by peer */ + ENOBUFS = _HURD_ERRNO (55), +#define ENOBUFS _HURD_ERRNO (55)/* No buffer space available */ + EISCONN = _HURD_ERRNO (56), +#define EISCONN _HURD_ERRNO (56)/* Transport endpoint is already connected */ + ENOTCONN = _HURD_ERRNO (57), +#define ENOTCONN _HURD_ERRNO (57)/* Transport endpoint is not connected */ + EDESTADDRREQ = _HURD_ERRNO (39), +#define EDESTADDRREQ _HURD_ERRNO (39)/* Destination address required */ + ESHUTDOWN = _HURD_ERRNO (58), +#define ESHUTDOWN _HURD_ERRNO (58)/* Cannot send after transport endpoint shutdown */ + ETOOMANYREFS = _HURD_ERRNO (59), +#define ETOOMANYREFS _HURD_ERRNO (59)/* Too many references: cannot splice */ + ETIMEDOUT = _HURD_ERRNO (60), +#define ETIMEDOUT _HURD_ERRNO (60)/* Connection timed out */ + ECONNREFUSED = _HURD_ERRNO (61), +#define ECONNREFUSED _HURD_ERRNO (61)/* Connection refused */ + ELOOP = _HURD_ERRNO (62), +#define ELOOP _HURD_ERRNO (62)/* Too many levels of symbolic links */ + ENAMETOOLONG = _HURD_ERRNO (63), +#define ENAMETOOLONG _HURD_ERRNO (63)/* File name too long */ + EHOSTDOWN = _HURD_ERRNO (64), +#define EHOSTDOWN _HURD_ERRNO (64)/* Host is down */ + EHOSTUNREACH = _HURD_ERRNO (65), +#define EHOSTUNREACH _HURD_ERRNO (65)/* No route to host */ + ENOTEMPTY = _HURD_ERRNO (66), +#define ENOTEMPTY _HURD_ERRNO (66)/* Directory not empty */ + EPROCLIM = _HURD_ERRNO (67), +#define EPROCLIM _HURD_ERRNO (67)/* Too many processes */ + EUSERS = _HURD_ERRNO (68), +#define EUSERS _HURD_ERRNO (68)/* Too many users */ + EDQUOT = _HURD_ERRNO (69), +#define EDQUOT _HURD_ERRNO (69)/* Disk quota exceeded */ + ESTALE = _HURD_ERRNO (70), +#define ESTALE _HURD_ERRNO (70)/* Stale NFS file handle */ + EREMOTE = _HURD_ERRNO (71), +#define EREMOTE _HURD_ERRNO (71)/* Object is remote */ + EBADRPC = _HURD_ERRNO (72), +#define EBADRPC _HURD_ERRNO (72)/* RPC struct is bad */ + ERPCMISMATCH = _HURD_ERRNO (73), +#define ERPCMISMATCH _HURD_ERRNO (73)/* RPC version wrong */ + EPROGUNAVAIL = _HURD_ERRNO (74), +#define EPROGUNAVAIL _HURD_ERRNO (74)/* RPC program not available */ + EPROGMISMATCH = _HURD_ERRNO (75), +#define EPROGMISMATCH _HURD_ERRNO (75)/* RPC program version wrong */ + EPROCUNAVAIL = _HURD_ERRNO (76), +#define EPROCUNAVAIL _HURD_ERRNO (76)/* RPC bad procedure for program */ + ENOLCK = _HURD_ERRNO (77), +#define ENOLCK _HURD_ERRNO (77)/* No locks available */ + EFTYPE = _HURD_ERRNO (79), +#define EFTYPE _HURD_ERRNO (79)/* Inappropriate file type or format */ + EAUTH = _HURD_ERRNO (80), +#define EAUTH _HURD_ERRNO (80)/* Authentication error */ + ENEEDAUTH = _HURD_ERRNO (81), +#define ENEEDAUTH _HURD_ERRNO (81)/* Need authenticator */ + ENOSYS = _HURD_ERRNO (78), +#define ENOSYS _HURD_ERRNO (78)/* Function not implemented */ + ENOTSUP = _HURD_ERRNO (118), +#define ENOTSUP _HURD_ERRNO (118)/* Not supported */ + EILSEQ = _HURD_ERRNO (106), +#define EILSEQ _HURD_ERRNO (106)/* Invalid or incomplete multibyte or wide character */ + EBACKGROUND = _HURD_ERRNO (100), +#define EBACKGROUND _HURD_ERRNO (100)/* Inappropriate operation for background process */ + EDIED = _HURD_ERRNO (101), +#define EDIED _HURD_ERRNO (101)/* Translator died */ + ED = _HURD_ERRNO (102), +#define ED _HURD_ERRNO (102)/* ? */ + EGREGIOUS = _HURD_ERRNO (103), +#define EGREGIOUS _HURD_ERRNO (103)/* You really blew it this time */ + EIEIO = _HURD_ERRNO (104), +#define EIEIO _HURD_ERRNO (104)/* Computer bought the farm */ + EGRATUITOUS = _HURD_ERRNO (105), +#define EGRATUITOUS _HURD_ERRNO (105)/* Gratuitous error */ + EBADMSG = _HURD_ERRNO (107), +#define EBADMSG _HURD_ERRNO (107)/* Bad message */ + EIDRM = _HURD_ERRNO (108), +#define EIDRM _HURD_ERRNO (108)/* Identifier removed */ + EMULTIHOP = _HURD_ERRNO (109), +#define EMULTIHOP _HURD_ERRNO (109)/* Multihop attempted */ + ENODATA = _HURD_ERRNO (110), +#define ENODATA _HURD_ERRNO (110)/* No data available */ + ENOLINK = _HURD_ERRNO (111), +#define ENOLINK _HURD_ERRNO (111)/* Link has been severed */ + ENOMSG = _HURD_ERRNO (112), +#define ENOMSG _HURD_ERRNO (112)/* No message of desired type */ + ENOSR = _HURD_ERRNO (113), +#define ENOSR _HURD_ERRNO (113)/* Out of streams resources */ + ENOSTR = _HURD_ERRNO (114), +#define ENOSTR _HURD_ERRNO (114)/* Device not a stream */ + EOVERFLOW = _HURD_ERRNO (115), +#define EOVERFLOW _HURD_ERRNO (115)/* Value too large for defined data type */ + EPROTO = _HURD_ERRNO (116), +#define EPROTO _HURD_ERRNO (116)/* Protocol error */ + ETIME = _HURD_ERRNO (117), +#define ETIME _HURD_ERRNO (117)/* Timer expired */ + ECANCELED = _HURD_ERRNO (118), +#define ECANCELED _HURD_ERRNO (118)/* Operation canceled */ + + /* Errors from <mach/message.h>. */ + EMACH_SEND_IN_PROGRESS = 0x10000001, + EMACH_SEND_INVALID_DATA = 0x10000002, + EMACH_SEND_INVALID_DEST = 0x10000003, + EMACH_SEND_TIMED_OUT = 0x10000004, + EMACH_SEND_WILL_NOTIFY = 0x10000005, + EMACH_SEND_NOTIFY_IN_PROGRESS = 0x10000006, + EMACH_SEND_INTERRUPTED = 0x10000007, + EMACH_SEND_MSG_TOO_SMALL = 0x10000008, + EMACH_SEND_INVALID_REPLY = 0x10000009, + EMACH_SEND_INVALID_RIGHT = 0x1000000a, + EMACH_SEND_INVALID_NOTIFY = 0x1000000b, + EMACH_SEND_INVALID_MEMORY = 0x1000000c, + EMACH_SEND_NO_BUFFER = 0x1000000d, + EMACH_SEND_NO_NOTIFY = 0x1000000e, + EMACH_SEND_INVALID_TYPE = 0x1000000f, + EMACH_SEND_INVALID_HEADER = 0x10000010, + EMACH_RCV_IN_PROGRESS = 0x10004001, + EMACH_RCV_INVALID_NAME = 0x10004002, + EMACH_RCV_TIMED_OUT = 0x10004003, + EMACH_RCV_TOO_LARGE = 0x10004004, + EMACH_RCV_INTERRUPTED = 0x10004005, + EMACH_RCV_PORT_CHANGED = 0x10004006, + EMACH_RCV_INVALID_NOTIFY = 0x10004007, + EMACH_RCV_INVALID_DATA = 0x10004008, + EMACH_RCV_PORT_DIED = 0x10004009, + EMACH_RCV_IN_SET = 0x1000400a, + EMACH_RCV_HEADER_ERROR = 0x1000400b, + EMACH_RCV_BODY_ERROR = 0x1000400c, + + /* Errors from <mach/kern_return.h>. */ + EKERN_INVALID_ADDRESS = 1, + EKERN_PROTECTION_FAILURE = 2, + EKERN_NO_SPACE = 3, + EKERN_INVALID_ARGUMENT = 4, + EKERN_FAILURE = 5, + EKERN_RESOURCE_SHORTAGE = 6, + EKERN_NOT_RECEIVER = 7, + EKERN_NO_ACCESS = 8, + EKERN_MEMORY_FAILURE = 9, + EKERN_MEMORY_ERROR = 10, + EKERN_NOT_IN_SET = 12, + EKERN_NAME_EXISTS = 13, + EKERN_ABORTED = 14, + EKERN_INVALID_NAME = 15, + EKERN_INVALID_TASK = 16, + EKERN_INVALID_RIGHT = 17, + EKERN_INVALID_VALUE = 18, + EKERN_UREFS_OVERFLOW = 19, + EKERN_INVALID_CAPABILITY = 20, + EKERN_RIGHT_EXISTS = 21, + EKERN_INVALID_HOST = 22, + EKERN_MEMORY_PRESENT = 23, + EKERN_WRITE_PROTECTION_FAILURE = 24, + EKERN_TERMINATED = 26, + + /* Errors from <mach/mig_errors.h>. */ + EMIG_TYPE_ERROR = -300 /* client type check failure */, + EMIG_REPLY_MISMATCH = -301 /* wrong reply message ID */, + EMIG_REMOTE_ERROR = -302 /* server detected error */, + EMIG_BAD_ID = -303 /* bad request message ID */, + EMIG_BAD_ARGUMENTS = -304 /* server type check failure */, + EMIG_NO_REPLY = -305 /* no reply should be sent */, + EMIG_EXCEPTION = -306 /* server raised exception */, + EMIG_ARRAY_TOO_LARGE = -307 /* array not large enough */, + EMIG_SERVER_DIED = -308 /* server died */, + EMIG_DESTROY_REQUEST = -309 /* destroy request with no reply */, + + /* Errors from <device/device_types.h>. */ + ED_IO_ERROR = 2500 /* hardware IO error */, + ED_WOULD_BLOCK = 2501 /* would block, but D_NOWAIT set */, + ED_NO_SUCH_DEVICE = 2502 /* no such device */, + ED_ALREADY_OPEN = 2503 /* exclusive-use device already open */, + ED_DEVICE_DOWN = 2504 /* device has been shut down */, + ED_INVALID_OPERATION = 2505 /* bad operation for device */, + ED_INVALID_RECNUM = 2506 /* invalid record (block) number */, + ED_INVALID_SIZE = 2507 /* invalid IO size */, + ED_NO_MEMORY = 2508 /* memory allocation failure */, + ED_READ_ONLY = 2509 /* device cannot be written to */ + +}; + +#define _HURD_ERRNOS 119 + +/* User-visible type of error codes. It is ok to use `int' or + `kern_return_t' for these, but with `error_t' the debugger prints + symbolic values. */ +#ifdef __USE_GNU +typedef enum __error_t_codes error_t; +#define __error_t_defined 1 +#endif + +/* Return the current thread's location for `errno'. + The syntax of this function allows redeclarations like `int errno'. */ +extern int *__errno_location (void) __THROW __attribute__ ((__const__)); + +#define errno (*__errno_location ()) + +#endif /* <errno.h> included. */ + +#if !defined (_ERRNO_H) && defined (__need_Emath) +#define EDOM _HURD_ERRNO (33)/* Numerical argument out of domain */ +#define ERANGE _HURD_ERRNO (34)/* Numerical result out of range */ +#endif /* <errno.h> not included and need math error codes. */ diff --git a/libc/sysdeps/mach/hurd/bits/fcntl.h b/libc/sysdeps/mach/hurd/bits/fcntl.h new file mode 100644 index 000000000..e709cc6fb --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/fcntl.h @@ -0,0 +1,210 @@ +/* O_*, F_*, FD_* bit values for GNU. + Copyright (C) 1993,94,96,97,98,99,2000,01,04 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 _FCNTL_H +# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead." +#endif + +/* File access modes. These are understood by io servers; they can be + passed in `dir_lookup', and are returned by `io_get_openmodes'. + Consequently they can be passed to `open', `hurd_file_name_lookup', and + `file_name_lookup'; and are returned by `fcntl' with the F_GETFL + command. */ + +/* In GNU, read and write are bits (unlike BSD). */ +#ifdef __USE_GNU +# define O_READ O_RDONLY /* Open for reading. */ +# define O_WRITE O_WRONLY /* Open for writing. */ +# define O_EXEC 0x0004 /* Open for execution. */ +# define O_NORW 0 /* Open without R/W access. */ +#endif +/* POSIX.1 standard names. */ +#define O_RDONLY 0x0001 /* Open read-only. */ +#define O_WRONLY 0x0002 /* Open write-only. */ +#define O_RDWR (O_RDONLY|O_WRONLY) /* Open for reading and writing. */ +#define O_ACCMODE O_RDWR /* Mask for file access modes. */ + +#define O_LARGEFILE 0 + + +/* File name translation flags. These are understood by io servers; + they can be passed in `dir_lookup', and consequently to `open', + `hurd_file_name_lookup', and `file_name_lookup'. */ + +#define O_CREAT 0x0010 /* Create file if it doesn't exist. */ +#define O_EXCL 0x0020 /* Fail if file already exists. */ +#ifdef __USE_GNU +# define O_NOLINK 0x0040 /* No name mappings on final component. */ +# define O_NOTRANS 0x0080 /* No translator on final component. */ + +# define O_NOFOLLOW 0x00100000 /* Produce ENOENT if file is a symlink. */ +# define O_DIRECTORY 0x00200000 /* Produce ENOTDIR if not a directory. */ +#endif + + +/* I/O operating modes. These are understood by io servers; they can be + passed in `dir_lookup' and set or fetched with `io_*_openmodes'. + Consequently they can be passed to `open', `hurd_file_name_lookup', + `file_name_lookup', and `fcntl' with the F_SETFL command; and are + returned by `fcntl' with the F_GETFL command. */ + +#define O_APPEND 0x0100 /* Writes always append to the file. */ +#define O_ASYNC 0x0200 /* Send SIGIO to owner when data is ready. */ +#define O_FSYNC 0x0400 /* Synchronous writes. */ +#define O_SYNC O_FSYNC +#ifdef __USE_GNU +# define O_NOATIME 0x0800 /* Don't set access time on read (owner). */ +#endif +#ifdef __USE_MISC +# define O_SHLOCK 0x00020000 /* Open with shared file lock. */ +# define O_EXLOCK 0x00040000 /* Open with exclusive file lock. */ +#endif + +/* These are lesser flavors of partial synchronization that are + implied by our one flag (O_FSYNC). */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + + +/* The name O_NONBLOCK is unfortunately overloaded; it is both a file name + translation flag and an I/O operating mode. O_NDELAY is the deprecated + BSD name for the same flag, overloaded in the same way. + + When used in `dir_lookup' (and consequently `open', `hurd_file_name_lookup', + or `file_name_lookup'), O_NONBLOCK says the open should return immediately + instead of blocking for any significant length of time (e.g., to wait + for carrier detect on a serial line). It is also saved as an I/O + operating mode, and after open has the following meaning. + + When used in `io_*_openmodes' (and consequently `fcntl' with the F_SETFL + command), the O_NONBLOCK flag means to do nonblocking i/o: any i/o + operation that would block for any significant length of time will instead + fail with EAGAIN. */ + +#define O_NONBLOCK 0x0008 /* Non-blocking open or non-blocking I/O. */ +#ifdef __USE_BSD +# define O_NDELAY O_NONBLOCK /* Deprecated. */ +#endif + + +#ifdef __USE_GNU +/* Mask of bits which are understood by io servers. */ +# define O_HURD (0xffff | O_EXLOCK | O_SHLOCK) +#endif + + +/* Open-time action flags. These are understood by `hurd_file_name_lookup' + and consequently by `open' and `file_name_lookup'. They are not preserved + once the file has been opened. */ + +#define O_TRUNC 0x00010000 /* Truncate file to zero length. */ + + +/* Controlling terminal flags. These are understood only by `open', + and are not preserved once the file has been opened. */ + +#ifdef __USE_GNU +# define O_IGNORE_CTTY 0x00080000 /* Don't do any ctty magic at all. */ +#endif +/* `open' never assigns a controlling terminal in GNU. */ +#define O_NOCTTY 0 /* Don't assign a controlling terminal. */ + + +#ifdef __USE_BSD +/* Bits in the file status flags returned by F_GETFL. */ +# define FREAD O_RDONLY +# define FWRITE O_WRONLY + +/* Traditional BSD names the O_* bits. */ +# define FASYNC O_ASYNC +# define FCREAT O_CREAT +# define FEXCL O_EXCL +# define FTRUNC O_TRUNC +# define FNOCTTY O_NOCTTY +# define FFSYNC O_FSYNC +# define FSYNC O_SYNC +# define FAPPEND O_APPEND +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif + + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#if defined __USE_BSD || defined __USE_UNIX98 +# 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). */ + +/* File descriptor flags used with F_GETFD and F_SETFD. */ +#define FD_CLOEXEC 1 /* Close on exec. */ + + +#include <bits/types.h> + +/* The structure describing an advisory lock. This is the type of the third + argument to `fcntl' for the F_GETLK, F_SETLK, and F_SETLKW requests. */ +struct flock + { + int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Values for the `l_type' field of a `struct flock'. */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 3 /* Remove lock. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif diff --git a/libc/sysdeps/mach/hurd/bits/ioctls.h b/libc/sysdeps/mach/hurd/bits/ioctls.h new file mode 100644 index 000000000..06a73df75 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/ioctls.h @@ -0,0 +1,371 @@ +/* Copyright (C) 1992,93,96,97,98,99,2001 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 __BITS_IOCTLS_H +#define __BITS_IOCTLS_H 1 + +#if !defined _HURD_IOCTL_H && !defined _SYS_IOCTL_H +# error "Never use <bits/ioctls.h> directly; include <hurd/ioctl.h> instead." +#endif + +/* These macros are also defined in <bits/termios.h> (with numerically + identical values) but this serves to shut up cpp's complaining. */ +#ifdef MDMBUF +# undef MDMBUF +#endif +#ifdef ECHO +# undef ECHO +#endif +#ifdef TOSTOP +# undef TOSTOP +#endif +#ifdef FLUSHO +# undef FLUSHO +#endif +#ifdef PENDIN +# undef PENDIN +#endif +#ifdef NOFLSH +# undef NOFLSH +#endif + +/* Hurd ioctl request are made up of several fields: + + 10987654321098765432109876543210 + IOt0t1t2cc0c0cc1c1cc2ggggccccccc + + bits [31,30]: inout direction (enum __ioctl_dir) + bits [29,11]: type encoding as follows; zero count indicates omitted datum + [29,28]: datum #0 type (enum __ioctl_datum) + [27,26]: datum #1 type (enum __ioctl_datum) + [24,25]: datum #2 type (enum __ioctl_datum) + [23,19]: datum #0 count [0,31] + [18,14]: datum #1 count [0,31] + [13,11]: datum #2 count [0,3] + bits [07,10]: group (letter - 'f': ['f','v']) + bits [00,06]: command [0,127] + + The following macros construct and dissect these fields. */ + +enum __ioctl_dir + { + IOC_VOID = 0, /* No parameters. */ + IOC_OUT = 1, /* Data is written into the user's buffer. */ + IOC_IN = 2, /* Data is read from the user's buffer. */ + IOC_INOUT = (IOC_IN|IOC_OUT) + }; + +enum __ioctl_datum { IOC_8, IOC_16, IOC_32, IOC_64 }; + +/* Construct an ioctl from constructed type plus other fields. */ +#define _IOC(inout, group, num, type) \ + ((num) | ((((group) - 'f') | ((type) | (inout) << 19) << 4) << 7)) + +/* Dissect an ioctl into its component fields. */ +#define _IOC_INOUT(request) (((unsigned int) (request) >> 30) & IOC_INOUT) +#define _IOC_GROUP(request) ('f' + (((unsigned int) (request) >> 7) & 0xf)) +#define _IOC_COMMAND(request) ((unsigned int) (request) & 0x7f) +#define _IOC_TYPE(request) (((unsigned int) (request) >> 11) & 0x7ffff) +#define _IOC_NOTYPE(request) ((unsigned int) (request) & 0x3ff) + +/* Construct a type information field from + the broken-out type and count fields. */ +#define _IOT(t0, c0, t1, c1, t2, c2) \ + ((c2) | (((c1) | ((c0) | ((t2) | ((t1) | (t0) << 2) << 2) << 5) << 5) << 3)) + +/* Dissect a type information field into the type and count fields. */ +#define _IOT_TYPE0(type) (((unsigned int) (type) >> 17) & 3) +#define _IOT_TYPE1(type) (((unsigned int) (type) >> 15) & 3) +#define _IOT_TYPE2(type) (((unsigned int) (type) >> 13) & 3) +#define _IOT_COUNT0(type) (((unsigned int) (type) >> 8) & 0x1f) +#define _IOT_COUNT1(type) (((unsigned int) (type) >> 3) & 0x1f) +#define _IOT_COUNT2(type) (((unsigned int) (type) >> 0) & 7) + +/* Construct an ioctl from all the broken-out fields. */ +#define _IOCT(inout, group, num, t0, c0, t1, c1, t2, c2) \ + _IOC ((inout), (group), (num), _IOT ((t0), (c0), (t1), (c1), (t2), (c2))) + +/* Construct an individual type field for TYPE. */ +#define _IOTS(type) \ + (sizeof (type) == 8 ? IOC_64 : (sizeof (type) >> 1)) + +/* Construct a type information field for + a single argument of the scalar TYPE. */ +#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) + + +/* Standard flavors of ioctls. + _IOT_foobar is defined either in this file, + or where struct foobar is defined. */ +#define _IO(g, n) _IOC (IOC_VOID, (g), (n), 0) +#define _IOR(g, n, t) _IOC (IOC_OUT, (g), (n), _IOC_ENCODE_TYPE (t)) +#define _IOW(g, n, t) _IOC (IOC_IN, (g), (n), _IOC_ENCODE_TYPE (t)) +#define _IOWR(g, n, t) _IOC (IOC_INOUT, (g), (n), _IOC_ENCODE_TYPE (t)) + +/* These macros do some preprocessor gymnastics to turn a TYPESPEC of + `struct foobar' into the identifier `_IOT_foobar', which is generally + defined using `_IOT' (above) in whatever file defines `struct foobar'. + For a TYPESPEC that does not begin with `struct' produces a different + identifier: `int' produces `_IOT__IOTBASE_int'. These identifiers + are defined for the basic C types above. */ +#define _IOC_ENCODE_TYPE(typespec) _IOC_ENCODE_TYPE_1(_IOTBASE_##typespec) +#define _IOTBASE_struct +#define _IOC_ENCODE_TYPE_1(typespec) _IOC_ENCODE_TYPE_2(typespec) +#define _IOC_ENCODE_TYPE_2(typespec) _IOT_##typespec + + +/* ioctls verbatim from 4.4 <sys/ioctl.h>. */ + +#define TIOCMODG _IOR('t', 3, int) /* get modem control state */ +#define TIOCMODS _IOW('t', 4, int) /* set modem control state */ +#define TIOCM_LE 0001 /* line enable */ +#define TIOCM_DTR 0002 /* data terminal ready */ +#define TIOCM_RTS 0004 /* request to send */ +#define TIOCM_ST 0010 /* secondary transmit */ +#define TIOCM_SR 0020 /* secondary receive */ +#define TIOCM_CTS 0040 /* clear to send */ +#define TIOCM_CAR 0100 /* carrier detect */ +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RNG 0200 /* ring */ +#define TIOCM_RI TIOCM_RNG +#define TIOCM_DSR 0400 /* data set ready */ + /* 8-10 compat */ +#define TIOCEXCL _IO('t', 13) /* set exclusive use of tty */ +#define TIOCNXCL _IO('t', 14) /* reset exclusive use of tty */ + /* 15 unused */ +#define TIOCFLUSH _IOW('t', 16, int) /* flush buffers */ + /* 17-18 compat */ +#define TIOCGETA _IOR('t', 19, struct termios) /* get termios struct */ +#define TIOCSETA _IOW('t', 20, struct termios) /* set termios struct */ +#define TIOCSETAW _IOW('t', 21, struct termios) /* drain output, set */ +#define TIOCSETAF _IOW('t', 22, struct termios) /* drn out, fls in, set */ +#define TIOCGETD _IOR('t', 26, int) /* get line discipline */ +#define TIOCSETD _IOW('t', 27, int) /* set line discipline */ + /* 127-124 compat */ +#define TIOCSBRK _IO('t', 123) /* set break bit */ +#define TIOCCBRK _IO('t', 122) /* clear break bit */ +#define TIOCSDTR _IO('t', 121) /* set data terminal ready */ +#define TIOCCDTR _IO('t', 120) /* clear data terminal ready */ +#define TIOCGPGRP _IOR('t', 119, int) /* get pgrp of tty */ +#define TIOCSPGRP _IOW('t', 118, int) /* set pgrp of tty */ + /* 117-116 compat */ +#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ +#define TIOCSTI _IOW('t', 114, char) /* simulate terminal input */ +#define TIOCNOTTY _IO('t', 113) /* void tty association */ +#define TIOCPKT _IOW('t', 112, int) /* pty: set/clear packet mode */ +#define TIOCPKT_DATA 0x00 /* data packet */ +#define TIOCPKT_FLUSHREAD 0x01 /* flush packet */ +#define TIOCPKT_FLUSHWRITE 0x02 /* flush packet */ +#define TIOCPKT_STOP 0x04 /* stop output */ +#define TIOCPKT_START 0x08 /* start output */ +#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ +#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ +#define TIOCPKT_IOCTL 0x40 /* state change of pty driver */ +#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ +#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +#define TIOCMSET _IOW('t', 109, int) /* set all modem bits */ +#define TIOCMBIS _IOW('t', 108, int) /* bis modem bits */ +#define TIOCMBIC _IOW('t', 107, int) /* bic modem bits */ +#define TIOCMGET _IOR('t', 106, int) /* get all modem bits */ +#define TIOCREMOTE _IOW('t', 105, int) /* remote input editing */ +#define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */ +#define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */ +#define TIOCUCNTL _IOW('t', 102, int) /* pty: set/clr usr cntl mode */ +#define UIOCCMD(n) _IO('u', n) /* usr cntl op "n" */ +#define TIOCCONS _IOW('t', 98, int) /* become virtual console */ +#define TIOCSCTTY _IO('t', 97) /* become controlling tty */ +#define TIOCEXT _IOW('t', 96, int) /* pty: external processing */ +#define TIOCSIG _IO('t', 95) /* pty: generate signal */ +#define TIOCDRAIN _IO('t', 94) /* wait till output drained */ + +#define TTYDISC 0 /* termios tty line discipline */ +#define TABLDISC 3 /* tablet discipline */ +#define SLIPDISC 4 /* serial IP discipline */ + + +#define FIOCLEX _IO('f', 1) /* set close on exec on fd */ +#define FIONCLEX _IO('f', 2) /* remove close on exec */ +#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */ +#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */ +#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */ +#define FIOSETOWN _IOW('f', 124, int) /* set owner */ +#define FIOGETOWN _IOR('f', 123, int) /* get owner */ + +/* socket i/o controls */ +#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */ +#define SIOCSPGRP _IOW('s', 8, int) /* set process group */ +#define SIOCGPGRP _IOR('s', 9, int) /* get process group */ + +#define SIOCADDRT _IOW('r', 10, struct ortentry) /* add route */ +#define SIOCDELRT _IOW('r', 11, struct ortentry) /* delete route */ + +#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ +#define OSIOCGIFADDR _IOWR('i',13, struct ifreq) /* get ifnet address */ +#define SIOCGIFADDR _IOWR('i',33, struct ifreq) /* get ifnet address */ +#define SIOCGIFHWADDR _IOWR('i',39, struct ifreq) /* get hwaddress */ +#define SIOCSIFDSTADDR _IOW('i', 14, struct ifreq) /* set p-p address */ +#define OSIOCGIFDSTADDR _IOWR('i',15, struct ifreq) /* get p-p address */ +#define SIOCGIFDSTADDR _IOWR('i',34, struct ifreq) /* get p-p address */ +#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq_short)/* set ifnet flags */ +#define SIOCGIFFLAGS _IOWR('i',17, struct ifreq_short)/* get ifnet flags */ +#define OSIOCGIFBRDADDR _IOWR('i',18, struct ifreq) /* get broadcast addr */ +#define SIOCGIFBRDADDR _IOWR('i',35, struct ifreq) /* get broadcast addr */ +#define SIOCSIFBRDADDR _IOW('i',19, struct ifreq) /* set broadcast addr */ +#define OSIOCGIFCONF _IOWR('i',20, struct ifconf) /* get ifnet list */ +#define SIOCGIFCONF _IOWR('i',36, struct ifconf) /* get ifnet list */ +#define OSIOCGIFNETMASK _IOWR('i',21, struct ifreq) /* get net addr mask */ +#define SIOCGIFNETMASK _IOWR('i',37, struct ifreq) /* get net addr mask */ +#define SIOCSIFNETMASK _IOW('i',22, struct ifreq) /* set net addr mask */ +#define SIOCGIFMETRIC _IOWR('i',23, struct ifreq_int) /* get IF metric */ +#define SIOCSIFMETRIC _IOW('i',24, struct ifreq_int) /* set IF metric */ +#define SIOCDIFADDR _IOW('i',25, struct ifreq) /* delete IF addr */ +#define SIOCAIFADDR _IOW('i',26, struct ifaliasreq) /* add/chg IF alias */ + +#define SIOCSARP _IOW('i', 30, struct arpreq) /* set arp entry */ +#define OSIOCGARP _IOWR('i',31, struct arpreq) /* get arp entry */ +#define SIOCGARP _IOWR('i',38, struct arpreq) /* get arp entry */ +#define SIOCDARP _IOW('i', 32, struct arpreq) /* delete arp entry */ + +#define SIOCGIFMTU _IOWR('i', 51, struct ifreq_int)/* get IF mtu */ +#define SIOCSIFMTU _IOW('i', 52, struct ifreq_int) /* set IF mtu */ + +#define SIOCGIFINDEX _IOWR('i', 90, struct ifreq_int)/* get IF index */ +#define SIOCGIFNAME _IOWR('i', 91, struct ifreq_int)/* set IF name */ + + +/* Compatibility with 4.3 BSD terminal driver. + From 4.4 <sys/ioctl_compat.h>. */ + +#ifdef USE_OLD_TTY +# undef TIOCGETD +# define TIOCGETD _IOR('t', 0, int) /* get line discipline */ +# undef TIOCSETD +# define TIOCSETD _IOW('t', 1, int) /* set line discipline */ +#else +# define OTIOCGETD _IOR('t', 0, int) /* get line discipline */ +# define OTIOCSETD _IOW('t', 1, int) /* set line discipline */ +#endif +#define TIOCHPCL _IO('t', 2) /* hang up on last close */ +#define TIOCGETP _IOR('t', 8,struct sgttyb)/* get parameters -- gtty */ +#define TIOCSETP _IOW('t', 9,struct sgttyb)/* set parameters -- stty */ +#define TIOCSETN _IOW('t',10,struct sgttyb)/* as above, but no flushtty*/ +#define TIOCSETC _IOW('t',17,struct tchars)/* set special characters */ +#define TIOCGETC _IOR('t',18,struct tchars)/* get special characters */ +#define TANDEM 0x00000001 /* send stopc on out q full */ +#define CBREAK 0x00000002 /* half-cooked mode */ +#define LCASE 0x00000004 /* simulate lower case */ +#define ECHO 0x00000008 /* echo input */ +#define CRMOD 0x00000010 /* map \r to \r\n on output */ +#define RAW 0x00000020 /* no i/o processing */ +#define ODDP 0x00000040 /* get/send odd parity */ +#define EVENP 0x00000080 /* get/send even parity */ +#define ANYP 0x000000c0 /* get any parity/send none */ +#define NLDELAY 0x00000300 /* \n delay */ +#define NL0 0x00000000 +#define NL1 0x00000100 /* tty 37 */ +#define NL2 0x00000200 /* vt05 */ +#define NL3 0x00000300 +#define TBDELAY 0x00000c00 /* horizontal tab delay */ +#define TAB0 0x00000000 +#define TAB1 0x00000400 /* tty 37 */ +#define TAB2 0x00000800 +#define XTABS 0x00000c00 /* expand tabs on output */ +#define CRDELAY 0x00003000 /* \r delay */ +#define CR0 0x00000000 +#define CR1 0x00001000 /* tn 300 */ +#define CR2 0x00002000 /* tty 37 */ +#define CR3 0x00003000 /* concept 100 */ +#define VTDELAY 0x00004000 /* vertical tab delay */ +#define FF0 0x00000000 +#define FF1 0x00004000 /* tty 37 */ +#define BSDELAY 0x00008000 /* \b delay */ +#define BS0 0x00000000 +#define BS1 0x00008000 +#define ALLDELAY (NLDELAY|TBDELAY|CRDELAY|VTDELAY|BSDELAY) +#define CRTBS 0x00010000 /* do backspacing for crt */ +#define PRTERA 0x00020000 /* \ ... / erase */ +#define CRTERA 0x00040000 /* " \b " to wipe out char */ +#define TILDE 0x00080000 /* hazeltine tilde kludge */ +#define MDMBUF 0x00100000 /*start/stop output on carrier*/ +#define LITOUT 0x00200000 /* literal output */ +#define TOSTOP 0x00400000 /*SIGSTOP on background output*/ +#define FLUSHO 0x00800000 /* flush output to terminal */ +#define NOHANG 0x01000000 /* (no-op) was no SIGHUP on carrier drop */ +#define L001000 0x02000000 +#define CRTKIL 0x04000000 /* kill line with " \b " */ +#define PASS8 0x08000000 +#define CTLECH 0x10000000 /* echo control chars as ^X */ +#define PENDIN 0x20000000 /* tp->t_rawq needs reread */ +#define DECCTQ 0x40000000 /* only ^Q starts after ^S */ +#define NOFLSH 0x80000000 /* no output flush on signal */ +#define TIOCLBIS _IOW('t', 127, int) /* bis local mode bits */ +#define TIOCLBIC _IOW('t', 126, int) /* bic local mode bits */ +#define TIOCLSET _IOW('t', 125, int) /* set entire local mode word */ +#define TIOCLGET _IOR('t', 124, int) /* get local modes */ +#define LCRTBS (CRTBS>>16) +#define LPRTERA (PRTERA>>16) +#define LCRTERA (CRTERA>>16) +#define LTILDE (TILDE>>16) +#define LMDMBUF (MDMBUF>>16) +#define LLITOUT (LITOUT>>16) +#define LTOSTOP (TOSTOP>>16) +#define LFLUSHO (FLUSHO>>16) +#define LNOHANG (NOHANG>>16) +#define LCRTKIL (CRTKIL>>16) +#define LPASS8 (PASS8>>16) +#define LCTLECH (CTLECH>>16) +#define LPENDIN (PENDIN>>16) +#define LDECCTQ (DECCTQ>>16) +#define LNOFLSH (NOFLSH>>16) +#define TIOCSLTC _IOW('t',117,struct ltchars)/* set local special chars*/ +#define TIOCGLTC _IOR('t',116,struct ltchars)/* get local special chars*/ +#define OTIOCCONS _IO('t', 98) /* for hp300 -- sans int arg */ +#define OTTYDISC 0 +#define NETLDISC 1 +#define NTTYDISC 2 + +/* From 4.4 <sys/ttydev.h>. */ +#ifdef USE_OLD_TTY +# define B0 0 +# define B50 1 +# define B75 2 +# define B110 3 +# define B134 4 +# define B150 5 +# define B200 6 +# define B300 7 +# define B600 8 +# define B1200 9 +# define B1800 10 +# define B2400 11 +# define B4800 12 +# define B9600 13 +# define EXTA 14 +# define EXTB 15 +#endif /* USE_OLD_TTY */ + +#endif /* bits/ioctls.h */ diff --git a/libc/sysdeps/mach/hurd/bits/libc-lock.h b/libc/sysdeps/mach/hurd/bits/libc-lock.h new file mode 100644 index 000000000..0fa90bcc3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/libc-lock.h @@ -0,0 +1,203 @@ +/* libc-internal interface for mutex locks. Hurd version using Mach cthreads. + Copyright (C) 1996,97,98,2000,01, 2002, 2003 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 _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#if (_LIBC - 0) || (_CTHREADS_ - 0) +#include <cthreads.h> +#include <hurd/threadvar.h> + +typedef struct mutex __libc_lock_t; +typedef struct +{ + struct mutex mutex; + void *owner; + int count; +} __libc_lock_recursive_t; + +#define __libc_lock_owner_self() ((void *) __hurd_threadvar_location (0)) + +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +#endif + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. */ +#define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = MUTEX_INITIALIZER; + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#define __libc_lock_init(NAME) __mutex_init (&(NAME)) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) __mutex_unlock (&(NAME)) +#define __libc_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __mutex_unlock (&(NAME).mutex) + + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) __mutex_lock (&(NAME)) + +/* Lock the named lock variable. */ +#define __libc_lock_trylock(NAME) (!__mutex_trylock (&(NAME))) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME)) + + +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER { MUTEX_INITIALIZER, 0, 0 } +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; + +#define __rtld_lock_define_recursive(CLASS,NAME) \ + __libc_lock_define_recursive (CLASS, NAME) +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + _LIBC_LOCK_RECURSIVE_INITIALIZER +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + __libc_lock_define_initialized_recursive (CLASS, NAME) + +#define __libc_lock_init_recursive(NAME) \ + ({ __libc_lock_recursive_t *const __lock = &(NAME); \ + __lock->owner = 0; mutex_init (&__lock->mutex); }) + +#define __libc_lock_trylock_recursive(NAME) \ + ({ __libc_lock_recursive_t *const __lock = &(NAME); \ + void *__self = __libc_lock_owner_self (); \ + __mutex_trylock (&__lock->mutex) \ + ? (__lock->owner = __self, __lock->count = 1, 0) \ + : __lock->owner == __self ? (++__lock->count, 0) : 1; }) + +#define __libc_lock_lock_recursive(NAME) \ + ({ __libc_lock_recursive_t *const __lock = &(NAME); \ + void *__self = __libc_lock_owner_self (); \ + if (__mutex_trylock (&__lock->mutex) \ + || (__lock->owner != __self \ + && (__mutex_lock (&__lock->mutex), 1))) \ + __lock->owner = __self, __lock->count = 1; \ + else \ + ++__lock->count; \ + }) +#define __libc_lock_unlock_recursive(NAME) \ + ({ __libc_lock_recursive_t *const __lock = &(NAME); \ + if (--__lock->count == 0) \ + { \ + __lock->owner = 0; \ + __mutex_unlock (&__lock->mutex); \ + } \ + }) + + +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) +#define __rtld_lock_lock_recursive(NAME) \ + __libc_lock_lock_recursive(NAME) +#define __rtld_lock_unlock_recursive(NAME) \ + __libc_lock_unlock_recursive (NAME) + + +/* XXX for now */ +#define __libc_rwlock_define __libc_lock_define +#define __libc_rwlock_define_initialized __libc_lock_define_initialized +#define __libc_rwlock_init __libc_lock_init +#define __libc_rwlock_fini __libc_lock_fini +#define __libc_rwlock_rdlock __libc_lock_lock +#define __libc_rwlock_wrlock __libc_lock_lock +#define __libc_rwlock_tryrdlock __libc_lock_trylock +#define __libc_rwlock_trywrlock __libc_lock_trylock +#define __libc_rwlock_unlock __libc_lock_unlock + + +/* Start a critical region with a cleanup function */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ +{ \ + typeof (***(FCT)) *__save_FCT = (DOIT) ? (FCT) : 0; \ + typeof (ARG) __save_ARG = ARG; \ + /* close brace is in __libc_cleanup_region_end below. */ + +/* End a critical region started with __libc_cleanup_region_start. */ +#define __libc_cleanup_region_end(DOIT) \ + if ((DOIT) && __save_FCT != 0) \ + (*__save_FCT)(__save_ARG); \ +} + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if ((DOIT) && __save_FCT != 0) \ + (*__save_FCT)(__save_ARG); \ + +#define __libc_cleanup_push(fct, arg) __libc_cleanup_region_start (1, fct, arg) +#define __libc_cleanup_pop(execute) __libc_cleanup_region_end (execute) + +#if (_CTHREADS_ - 0) + +/* Use mutexes as once control variables. */ + +struct __libc_once + { + __libc_lock_t lock; + int done; + }; + +#define __libc_once_define(CLASS,NAME) \ + CLASS struct __libc_once NAME = { MUTEX_INITIALIZER, 0 } + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + __libc_lock_lock (ONCE_CONTROL.lock); \ + if (!ONCE_CONTROL.done) \ + (INIT_FUNCTION) (); \ + ONCE_CONTROL.done = 1; \ + __libc_lock_unlock (ONCE_CONTROL.lock); \ + } while (0) + +#ifdef _LIBC +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __mutex_unlock +#endif + +/* Type for key of thread specific data. */ +typedef cthread_key_t __libc_key_t; + +#define __libc_key_create(KEY,DEST) cthread_keycreate (KEY) +#define __libc_setspecific(KEY,VAL) cthread_setspecific (KEY, VAL) +void *__libc_getspecific (__libc_key_t key); + +#endif /* _CTHREADS_ */ + +#endif /* bits/libc-lock.h */ diff --git a/libc/sysdeps/mach/hurd/bits/libc-tsd.h b/libc/sysdeps/mach/hurd/bits/libc-tsd.h new file mode 100644 index 000000000..56393e930 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/libc-tsd.h @@ -0,0 +1,34 @@ +/* libc-internal interface for thread-specific data. Hurd version. + Copyright (C) 1998,2002 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 _BITS_LIBC_TSD_H +#define _BITS_LIBC_TSD_H 1 + +#include <hurd/threadvar.h> + +#define __libc_tsd_define(CLASS, KEY) /* nothing, always have threadvars */ + +#define __libc_tsd_address(KEY) \ + ((void **) __hurd_threadvar_location (_HURD_THREADVAR_##KEY)) + +#define __libc_tsd_get(KEY) (*__libc_tsd_address (KEY)) +#define __libc_tsd_set(KEY, VALUE) (*__libc_tsd_address (KEY) = (VALUE)) + + +#endif /* bits/libc-tsd.h */ diff --git a/libc/sysdeps/mach/hurd/bits/local_lim.h b/libc/sysdeps/mach/hurd/bits/local_lim.h new file mode 100644 index 000000000..51a2791b1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/local_lim.h @@ -0,0 +1,46 @@ +/* Minimum guaranteed maximum values for system limits. Hurd version. + Copyright (C) 1993,94,96,98,2002 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. */ + +/* GNU has no arbitrary fixed limits on most of these things, so we + don't define the macros. Some things are unlimited. Some are in + fact limited but the limit is run-time dependent and fetched with + `sysconf' or `pathconf'. */ + +/* This one value is actually constrained by the `struct dirent' + layout, in which the `d_namlen' member is only 8 bits wide. */ + +#define NAME_MAX 255 + +/* POSIX.1 requires that we define NGROUPS_MAX (though none of the others + is required). GNU allows any number of supplementary groups, + dynamically allocated. So we pick a number which seems vaguely + suitable, and `sysconf' will return a number at least as large. */ + +#define NGROUPS_MAX 256 + +/* The maximum number of symbolic links that are allowed in a single file + name resolution. When a further link is encountered, the call returns + ELOOP. This name is a GNU extension; POSIX.1 has no such limit, and BSD + calls it MAXSYMLINKS in <sys/param.h>. (We define the name under + _BSD_SOURCE even without _GNU_SOURCE because our <sys/param.h> uses it + to define MAXSYMLINKS.) */ + +#if defined __USE_GNU || defined __USE_BSD /* 1003.1a defines this */ +#define SYMLOOP_MAX 8 +#endif diff --git a/libc/sysdeps/mach/hurd/bits/posix_opt.h b/libc/sysdeps/mach/hurd/bits/posix_opt.h new file mode 100644 index 000000000..6747bc276 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/posix_opt.h @@ -0,0 +1,165 @@ +/* Define POSIX options for GNU/Hurd. + Copyright (C) 1998,2000,2001,2002,2006 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 _UNISTD_H +#error "Never include this file directly; use <unistd.h> instead." +#endif + +#ifndef _BITS_POSIX_OPT_H +#define _BITS_POSIX_OPT_H 1 + + +/* Job control is supported. */ +#define _POSIX_JOB_CONTROL 1 + +/* Processes have a saved set-user-ID and a saved set-group-ID. */ +#define _POSIX_SAVED_IDS 1 + +/* Synchronizing file data is supported, but msync is missing. */ +#undef _POSIX_SYNCHRONIZED_IO + +/* The fsync function is present. */ +#define _POSIX_FSYNC 200112L + +/* Mapping of files to memory is supported. */ +#define _POSIX_MAPPED_FILES 200112L + +/* Locking of all memory could be supported in future. */ +#define _POSIX_MEMLOCK 0 + +/* Locking of ranges of memory is supported. */ +#define _POSIX_MEMLOCK_RANGE 200112L + +/* Setting of memory protections is supported. */ +#define _POSIX_MEMORY_PROTECTION 200112L + +/* Elements of the `c_cc' member of `struct termios' structure + can be disabled by using the value _POSIX_VDISABLE. */ +#define _POSIX_VDISABLE ((unsigned char) -1) + + +/* Different Hurd filesystems might do these differently. + You must query the particular file with `pathconf' or `fpathconf'. */ +#undef _POSIX_CHOWN_RESTRICTED /* Only root can change owner of file? */ +#undef _POSIX_NO_TRUNC /* Overlong file names get error? */ +#undef _POSIX_SYNC_IO /* File supports O_SYNC et al? */ + + +/* We do not have the POSIX threads interface. */ +#define _POSIX_THREADS -1 + +/* We have the reentrant functions described in POSIX. */ +#define _POSIX_REENTRANT_FUNCTIONS 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +/* These are all things that won't be supported when _POSIX_THREADS is not. */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 +#define _POSIX_THREAD_ATTR_STACKSIZE -1 +#define _POSIX_THREAD_ATTR_STACKADDR -1 +#define _POSIX_SEMAPHORES -1 + +/* Real-time signals are not yet supported. */ +#define _POSIX_REALTIME_SIGNALS -1 + +/* Asynchronous I/O might supported with the existing ABI. */ +#define _POSIX_ASYNCHRONOUS_IO 0 +/* Alternative name for Unix98. */ +#define _LFS_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO + +/* The LFS support in asynchronous I/O is also available. */ +#define _LFS64_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO + +/* The rest of the LFS is also available. */ +#define _LFS_LARGEFILE 1 +#define _LFS64_LARGEFILE 1 +#define _LFS64_STDIO 1 + +/* POSIX.4 shared memory objects are supported (using regular files). */ +#define _POSIX_SHARED_MEMORY_OBJECTS _POSIX_MAPPED_FILES + +/* CPU-time clocks support needs to be checked at runtime. */ +#define _POSIX_CPUTIME 0 + +/* Clock support in threads must be also checked at runtime. */ +#define _POSIX_THREAD_CPUTIME 0 + +/* GNU libc provides regular expression handling. */ +#define _POSIX_REGEXP 1 + +/* Reader/Writer locks are not available. */ +#define _POSIX_READER_WRITER_LOCKS -1 + +/* We have a POSIX shell. */ +#define _POSIX_SHELL 1 + +/* We cannot support the Timeouts option without _POSIX_THREADS. */ +#define _POSIX_TIMEOUTS -1 + +/* The `spawn' function family is supported. */ +#define _POSIX_SPAWN 200112L + +/* 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 + +/* POSIX message queues could be available in future. */ +#define _POSIX_MESSAGE_PASSING 0 + +/* Thread process-shared synchronization is not supported. */ +#define _POSIX_THREAD_PROCESS_SHARED -1 + +/* The monotonic clock might be available. */ +#define _POSIX_MONOTONIC_CLOCK 0 + +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200112L + +/* Advisory information interfaces could be available in future. */ +#define _POSIX_ADVISORY_INFO 0 + +/* IPv6 support is available. */ +#define _POSIX_IPV6 200112L + +/* Raw socket support is available. */ +#define _POSIX_RAW_SOCKETS 200112L + +/* We have at least one terminal. */ +#define _POSIX2_CHAR_TERM 200112L + +/* Neither process nor thread sporadic server interfaces is available. */ +#define _POSIX_SPORADIC_SERVER -1 +#define _POSIX_THREAD_SPORADIC_SERVER -1 + +/* trace.h is not available. */ +#define _POSIX_TRACE -1 +#define _POSIX_TRACE_EVENT_FILTER -1 +#define _POSIX_TRACE_INHERIT -1 +#define _POSIX_TRACE_LOG -1 + +/* Typed memory objects are not available. */ +#define _POSIX_TYPED_MEMORY_OBJECTS -1 + +/* No support for priority inheritance or protection so far. */ +#define _POSIX_THREAD_PRIO_INHERIT -1 +#define _POSIX_THREAD_PRIO_PROTECT -1 + + +#endif /* bits/posix_opt.h */ diff --git a/libc/sysdeps/mach/hurd/bits/stat.h b/libc/sysdeps/mach/hurd/bits/stat.h new file mode 100644 index 000000000..c3f96660c --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/stat.h @@ -0,0 +1,196 @@ +/* Copyright (C) 1992,93,94,96,97,99,2000,2005 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 _SYS_STAT_H +# error "Never include <bits/stat.h> directly; use <sys/stat.h> instead." +#endif + +#include <bits/types.h> + +/* NOTE: The size of this structure (32 ints) is known in + <hurd/hurd_types.defs>, since it is used in the `io_stat' RPC. MiG + does not cope at all well with the passed C structure not being of + the expected size. There are some filler words at the end to allow + for future expansion. To increase the size of the structure used + in the RPC and retain binary compatibility, we would need to assign + a new message number. */ + +struct stat + { + int st_fstype; /* File system type. */ + __fsid_t st_fsid; /* File system ID. */ +#define st_dev st_fsid + +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File number. */ +#else + __ino64_t st_ino; /* File number. */ +#endif + unsigned int st_gen; /* To detect reuse of file numbers. */ + __dev_t st_rdev; /* Device if special file. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Number of links. */ + + __uid_t st_uid; /* Owner. */ + __gid_t st_gid; /* Owning group. */ + +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size in bytes. */ +#else + __off64_t st_size; /* Size in bytes. */ +#endif + + __time_t st_atime; /* Access time, seconds */ + unsigned long int st_atime_usec; /* and microseconds. */ + __time_t st_mtime; /* Modification time, seconds */ + unsigned long int st_mtime_usec; /* and microseconds. */ + __time_t st_ctime; /* Status change time, seconds */ + unsigned long int st_ctime_usec; /* and microseconds. */ + + __blksize_t st_blksize; /* Optimal size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. + Not related to `st_blksize'. */ +#else + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. + Not related to `st_blksize'. */ +#endif + + __uid_t st_author; /* File author. */ + + unsigned int st_flags; /* User-defined flags. + High 16 bits can be set only by root. */ + +#ifndef __USE_FILE_OFFSET64 +# define _SPARE_SIZE ((sizeof (__fsid_t) == sizeof (int)) ? 12 : 11) +#else +# define _SPARE_SIZE ((sizeof (__fsid_t) == sizeof (int)) ? 9 : 8) +#endif + int st_spare[_SPARE_SIZE]; /* Room for future expansion. */ +#undef _SPARE_SIZE + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + int st_fstype; /* File system type. */ + __fsid_t st_fsid; /* File system ID. */ +# define st_dev st_fsid + + __ino64_t st_ino; /* File number. */ + unsigned int st_gen; /* To detect reuse of file numbers. */ + __dev_t st_rdev; /* Device if special file. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Number of links. */ + + __uid_t st_uid; /* Owner. */ + __gid_t st_gid; /* Owning group. */ + + __off64_t st_size; /* Size in bytes. */ + + __time_t st_atime; /* Access time, seconds */ + unsigned long int st_atime_usec; /* and microseconds. */ + __time_t st_mtime; /* Modification time, seconds */ + unsigned long int st_mtime_usec; /* and microseconds. */ + __time_t st_ctime; /* Status change time, seconds */ + unsigned long int st_ctime_usec; /* and microseconds. */ + + __blksize_t st_blksize; /* Optimal size for I/O. */ + + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. + Not related to `st_blksize'. */ + + __uid_t st_author; /* File author. */ + + unsigned int st_flags; /* User-defined flags. + High 16 bits can be set only by root. */ + +#define _SPARE_SIZE ((sizeof (__fsid_t) == sizeof (int)) ? 9 : 8) + int st_spare[_SPARE_SIZE]; /* Room for future expansion. */ +#undef _SPARE_SIZE + }; +#endif + +#define _STATBUF_ST_BLKSIZE /* Tell code we have this member. */ + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ +#define __S_IFIFO 0010000 /* FIFO. */ + +/* POSIX.1b objects. */ +#define __S_TYPEISMQ(buf) (0) +#define __S_TYPEISSEM(buf) (0) +#define __S_TYPEISSHM(buf) (0) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 00400 /* Read by owner. */ +#define __S_IWRITE 00200 /* Write by owner. */ +#define __S_IEXEC 00100 /* Execute by owner. */ + + +#ifdef __USE_GNU +/* If set, there is no benefit in caching the contents of this file. */ +#define S_INOCACHE 000000200000 + +/* If the S_IUSEUNK bit is set, then the S_IUNKNOWN bits (see below) + control access for unknown users. If S_IUSEUNK is clear, then unknown + users are treated as "others" for purposes of access control. */ +#define S_IUSEUNK 000000400000 +/* Mask of protection bits for unknown users (no effective IDs at all). */ +#define S_IUNKNOWN 000007000000 +/* Shift S_IREAD, S_IWRITE, S_IEXEC left this many bits to produce the + protection bits for unknown users. */ +#define S_IUNKSHIFT 12 + +/* Read only bits: */ + +/* There is a passive translator set for this file */ +#define S_IPTRANS 000010000000 +/* There is an active translator running on this file */ +#define S_IATRANS 000020000000 +/* This is the root of a filesystem (or single node translator) */ +#define S_IROOT 000040000000 +/* All the bits relevant to translators */ +#define S_ITRANS 000070000000 + +/* Definitely no mmaps to this. */ +#define S_IMMAP0 000100000000 + +/* ALL the unused bits. */ +#define S_ISPARE (~(S_IFMT|S_ITRANS|S_INOCACHE|S_IMMAP0| \ + S_IUSEUNK|S_IUNKNOWN|07777)) +#endif + +/* Default file creation mask (umask). */ +#ifdef __USE_BSD +#define CMASK 0022 +#endif diff --git a/libc/sysdeps/mach/hurd/bits/statfs.h b/libc/sysdeps/mach/hurd/bits/statfs.h new file mode 100644 index 000000000..9183f98c8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/statfs.h @@ -0,0 +1,87 @@ +/* Definition of `struct statfs', information about a filesystem. + Copyright (C) 1996, 97, 98, 2000 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 _SYS_STATFS_H +# error "Never include <bits/statfs.h> directly; use <sys/statfs.h> instead." +#endif + +#include <bits/types.h> + +/* GNU Hurd NOTE: The size of this structure (16 ints) is known in + <hurd/hurd_types.defs>, since it is used in the `file_statfs' RPC. MiG + does not cope at all well with the passed C structure not being of the + expected size. There are some filler words at the end to allow for + future expansion. To increase the size of the structure used in the RPC + and retain binary compatibility, we would need to assign a new message + number. + + Note also that `struct statvfs' in <bits/statvfs.h> is laid out + identically to `struct statfs', so they can be used interchangeably. + Any changes made here must also be made in that file. */ + +struct statfs + { + unsigned int f_type; + unsigned int f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsblkcnt_t f_files; + __fsblkcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsblkcnt64_t f_files; + __fsblkcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + unsigned int f_namelen; +#ifndef __USE_FILE_OFFSET64 + __fsfilcnt_t f_favail; +#else + __fsfilcnt64_t f_favail; +#endif + unsigned int f_frsize; + unsigned int f_flag; + unsigned int f_spare[3]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + unsigned int f_type; + unsigned int f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsblkcnt64_t f_files; + __fsblkcnt64_t f_ffree; + __fsid_t f_fsid; + unsigned int f_namelen; + __fsfilcnt64_t f_favail; + unsigned int f_frsize; + unsigned int f_flag; + unsigned int f_spare[3]; + }; +#endif + +/* Tell code we have this member. */ +#define _STATFS_F_NAMELEN diff --git a/libc/sysdeps/mach/hurd/bits/statvfs.h b/libc/sysdeps/mach/hurd/bits/statvfs.h new file mode 100644 index 000000000..bbaf59a72 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/statvfs.h @@ -0,0 +1,94 @@ +/* Definition of `struct statvfs', information about a filesystem. + Copyright (C) 1998, 2002 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 _SYS_STATVFS_H +# error "Never include <bits/statvfs.h> directly; use <sys/statvfs.h> instead." +#endif + +#include <bits/types.h> + +/* GNU Hurd NOTE: This structure is carefully laid out such that we + can use the `file_statfs' RPC to implement `statvfs' and + `fstatvfs'. Please keep this file in sync with <bits/statfs.h>, + and pay attention to the note in that file. */ + +struct statvfs + { + unsigned int __f_type; + unsigned int f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + unsigned int f_namemax; /* NOTE: f_namelen in `struct statfs'. */ +#ifndef __USE_FILE_OFFSET64 + __fsfilcnt_t f_favail; +#else + __fsfilcnt64_t f_favail; +#endif + unsigned int f_frsize; + unsigned int f_flag; + unsigned int f_spare[3]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned int __f_type; + unsigned int f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + unsigned int f_namemax; + __fsfilcnt64_t f_favail; + unsigned int f_frsize; + unsigned int f_flag; + unsigned int f_spare[3]; + }; +#endif + +/* Definitions for the flag in `f_flag'. + The values for the non-standard flags come from Linux. */ +enum +{ + ST_RDONLY = 1, +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2 +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + , + ST_NOEXEC = 8, +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16 +# define ST_SYNCHRONOUS ST_SYNCHRONOUS +#endif +}; diff --git a/libc/sysdeps/mach/hurd/bits/typesizes.h b/libc/sysdeps/mach/hurd/bits/typesizes.h new file mode 100644 index 000000000..4322617a9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Hurd version. + Copyright (C) 2002,2003 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 _BITS_TYPES_H +# error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See <bits/types.h> for the meaning of these macros. This file exists so + that <bits/types.h> need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __U32_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE __UQUAD_TYPE +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 256 + + +#endif /* bits/typesizes.h */ diff --git a/libc/sysdeps/mach/hurd/brk.c b/libc/sysdeps/mach/hurd/brk.c new file mode 100644 index 000000000..931b260b1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/brk.c @@ -0,0 +1,153 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,99,2000 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 <hurd.h> +#include <hurd/resource.h> +#include <cthreads.h> /* For `struct mutex'. */ + + +/* Initial maximum size of the data segment (this is arbitrary). */ +#define DATA_SIZE (128 * 1024 * 1024) + +/* Up to the page including this address is allocated from the kernel. + This address is the data resource limit. */ +vm_address_t _hurd_data_end; + +/* Up to this address is actually available to the user. + Pages beyond the one containing this address allow no access. */ +vm_address_t _hurd_brk = 0; + +/* This name is used by the Linux crtbeginS.o for reasons you don't even + want to think about it. It's just easier to provide some definition for + it than even to explain the braindamage involved. */ +weak_alias (_hurd_brk, ___brk_addr) + +struct mutex _hurd_brk_lock; + +extern int __data_start, _end; +weak_extern (__data_start) +static vm_address_t static_data_start; + + +/* Set the end of the process's data space to INADDR. + Return 0 if successful, -1 if not. */ +int +__brk (void *inaddr) +{ + int ret; + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_brk_lock); + ret = _hurd_set_brk ((vm_address_t) inaddr); + __mutex_unlock (&_hurd_brk_lock); + HURD_CRITICAL_END; + return ret; +} +weak_alias (__brk, brk) + + +int +_hurd_set_brk (vm_address_t addr) +{ + error_t err; + vm_address_t pagend = round_page (addr); + vm_address_t pagebrk = round_page (_hurd_brk); + long int rlimit; + + if (pagend <= pagebrk) + { + if (pagend < pagebrk) + { + /* XXX wish this were atomic... */ + /* First deallocate the memory to release its backing space. */ + __vm_deallocate (__mach_task_self (), pagend, pagebrk - pagend); + /* Now reallocate it with no access allowed. */ + err = __vm_map (__mach_task_self (), + &pagend, pagebrk - pagend, + 0, 0, MACH_PORT_NULL, 0, 0, + 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE, + VM_INHERIT_COPY); + /* XXX what if error? */ + } + _hurd_brk = addr; + return 0; + } + + __mutex_lock (&_hurd_rlimit_lock); + rlimit = _hurd_rlimits[RLIMIT_DATA].rlim_cur; + __mutex_unlock (&_hurd_rlimit_lock); + + if (addr - static_data_start > rlimit) + { + /* Need to increase the resource limit. */ + errno = ENOMEM; + return -1; + } + + if (pagend > _hurd_data_end) + { + /* We didn't allocate enough space! Hopefully we can get some more! */ + err = __vm_allocate (__mach_task_self (), &pagebrk, pagend - pagebrk, 0); + if (! err) + _hurd_data_end = pagend; + } + else + /* Make the memory accessible. */ + err = __vm_protect (__mach_task_self (), pagebrk, pagend - pagebrk, + 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); + + if (err) + return __hurd_fail (err); + + _hurd_brk = addr; + return 0; +} + +static void +init_brk (void) +{ + vm_address_t pagend; + + __mutex_init (&_hurd_brk_lock); + + static_data_start = (vm_address_t) (&__data_start ?: &_end); + + /* 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) + _hurd_brk = (vm_address_t) &_end; + + pagend = round_page (_hurd_brk); + + _hurd_data_end = round_page (static_data_start + DATA_SIZE); + + if (pagend < _hurd_data_end) + { + /* We use vm_map to allocate and change permissions atomically. */ + if (__vm_map (__mach_task_self (), &pagend, _hurd_data_end - pagend, + 0, 0, MACH_PORT_NULL, 0, 0, + 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE, + VM_INHERIT_COPY)) + /* Couldn't allocate the memory. The break will be very short. */ + _hurd_data_end = pagend; + } + + (void) &init_brk; /* Avoid ``defined but not used'' warning. */ +} +text_set_element (_hurd_preinit_hook, init_brk); diff --git a/libc/sysdeps/mach/hurd/chdir.c b/libc/sysdeps/mach/hurd/chdir.c new file mode 100644 index 000000000..ee0f3f0f9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/chdir.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991,92,93,94,95,97,99 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 <unistd.h> +#include <hurd.h> +#include <fcntl.h> +#include <hurd/port.h> + +/* Change the current directory to FILE_NAME. */ +int +__chdir (file_name) + const char *file_name; +{ + return _hurd_change_directory_port_from_name (&_hurd_ports[INIT_PORT_CWDIR], + file_name); +} + +weak_alias (__chdir, chdir) diff --git a/libc/sysdeps/mach/hurd/check_fds.c b/libc/sysdeps/mach/hurd/check_fds.c new file mode 100644 index 000000000..c5d85225b --- /dev/null +++ b/libc/sysdeps/mach/hurd/check_fds.c @@ -0,0 +1,108 @@ +/* Copyright (C) 2000 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 <fcntl.h> +#include <paths.h> +#include <unistd.h> + +#include <hurd.h> +#include <hurd/fd.h> + +#include <set-hooks.h> + +/* Try to get a machine dependent instruction which will make the + program crash. This is used in case everything else fails. */ +#include <abort-instr.h> +#ifndef ABORT_INSTRUCTION +/* No such instruction is available. */ +# define ABORT_INSTRUCTION +#endif + +static void +check_one_fd (int fd, int mode) +{ + struct hurd_fd *d; + + d = _hurd_fd_get (fd); + if (d == NULL) + { + /* This descriptor hasn't been opened. We try to allocate the + descriptor and open /dev/null on it so that the SUID program + we are about to start does not accidently use this + descriptor. */ + d = _hurd_alloc_fd (NULL, fd); + if (d != NULL) + { + mach_port_t port; + + port = __file_name_lookup (_PATH_DEVNULL, mode, 0); + if (port) + { + /* Since /dev/null isn't supposed to be a terminal, we + avoid any ctty magic. */ + d->port.port = port; + d->flags = 0; + + __spin_unlock (&d->port.lock); + return; + } + } + + /* We cannot even give an error message here since it would run + into the same problems. */ + while (1) + /* Try for ever and ever. */ + ABORT_INSTRUCTION; + } +} + +static void +check_standard_fds (void) +{ + /* Check all three standard file descriptors. */ + check_one_fd (STDIN_FILENO, O_RDONLY); + check_one_fd (STDOUT_FILENO, O_RDWR); + check_one_fd (STDERR_FILENO, O_RDWR); +} + +static void +init_standard_fds (void) +{ + /* Now that we have FDs, make sure that, if this is a SUID program, + FDs 0, 1 and 2 are allocated. If necessary we'll set them up + ourselves. If that's not possible we stop the program. */ + if (__builtin_expect (__libc_enable_secure, 0)) + check_standard_fds (); + + (void) &init_standard_fds; /* Avoid "defined but not used" warning. */ +} +text_set_element (_hurd_fd_subinit, init_standard_fds); + + +#ifndef SHARED +void +__libc_check_standard_fds (void) +{ + /* We don't check the standard file descriptors here. They will be + checked when we initialize the file descriptor table, as part of + the _hurd_fd_subinit hook. + + This function is only present to make sure that this module gets + linked in when part of the static libc. */ +} +#endif diff --git a/libc/sysdeps/mach/hurd/chflags.c b/libc/sysdeps/mach/hurd/chflags.c new file mode 100644 index 000000000..a0b427ccf --- /dev/null +++ b/libc/sysdeps/mach/hurd/chflags.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991, 92, 93, 94, 97, 98 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> + +/* Change the flags of FILE to FLAGS. */ + +/* XXX shouldn't this be __chflags? */ +int +chflags (const char *file, int flags) +{ + error_t err; + file_t port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chflags (port, flags); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/chmod.c b/libc/sysdeps/mach/hurd/chmod.c new file mode 100644 index 000000000..c2edeb310 --- /dev/null +++ b/libc/sysdeps/mach/hurd/chmod.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1992, 1994, 1995, 1997 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> + +/* Change the protections of FILE to MODE. */ +int +__chmod (file, mode) + const char *file; + mode_t mode; +{ + error_t err; + file_t port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chmod (port, mode); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__chmod, chmod) diff --git a/libc/sysdeps/mach/hurd/chown.c b/libc/sysdeps/mach/hurd/chown.c new file mode 100644 index 000000000..7cb2ce3b2 --- /dev/null +++ b/libc/sysdeps/mach/hurd/chown.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991,1992,1994,1995,1997,2002 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 <stddef.h> +#include <unistd.h> +#include <hurd.h> + +/* Change the owner and group of FILE. */ +int +__chown (file, owner, group) + const char *file; + uid_t owner; + gid_t group; +{ + error_t err; + file_t port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chown (port, owner, group); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} +libc_hidden_def (__chown) +weak_alias (__chown, chown) diff --git a/libc/sysdeps/mach/hurd/chroot.c b/libc/sysdeps/mach/hurd/chroot.c new file mode 100644 index 000000000..fde016471 --- /dev/null +++ b/libc/sysdeps/mach/hurd/chroot.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1991,92,93,94,95,97,99,2001 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 <string.h> +#include <unistd.h> + +#include <hurd.h> +#include <hurd/port.h> + +/* Make PATH be the root directory (the starting point for absolute + paths). Note that while on traditional UNIX systems this call is + restricted to the super-user, it isn't on the Hurd. */ +int +chroot (const char *path) +{ + const char *lookup; + size_t len; + file_t dir, root; + error_t err; + + /* Append trailing "/." to directory name to force ENOTDIR if it's not a + directory and EACCES if we don't have search permission. */ + len = strlen (path); + if (len >= 2 && path[len - 2] == '/' && path[len - 1] == '.') + lookup = path; + else + { + char *n = alloca (len + 3); + memcpy (n, path, len); + n[len] = '/'; + n[len + 1] = '.'; + n[len + 2] = '\0'; + lookup = n; + } + + dir = __file_name_lookup (lookup, 0, 0); + if (dir == MACH_PORT_NULL) + return -1; + + /* Prevent going through DIR's .. */ + err = __file_reparent (dir, MACH_PORT_NULL, &root); + __mach_port_deallocate (__mach_task_self (), dir); + if (err) + return __hurd_fail (err); + + _hurd_port_set (&_hurd_ports[INIT_PORT_CRDIR], root); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/clock.c b/libc/sysdeps/mach/hurd/clock.c new file mode 100644 index 000000000..d6d4597bc --- /dev/null +++ b/libc/sysdeps/mach/hurd/clock.c @@ -0,0 +1,54 @@ +/* Return the CPU time used by the program so far. Hurd version. + Copyright (C) 2001 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 <time.h> +#include <sys/time.h> +#include <mach.h> +#include <mach/task_info.h> +#include <hurd.h> + +/* Return the time used by the program so far (user time + system time). */ +clock_t +clock (void) +{ + struct task_basic_info bi; + struct task_thread_times_info tti; + mach_msg_type_number_t count; + clock_t total; + error_t err; + + count = TASK_BASIC_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_BASIC_INFO, + (task_info_t) &bi, &count); + if (err) + return __hurd_fail (err); + + count = TASK_THREAD_TIMES_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_THREAD_TIMES_INFO, + (task_info_t) &tti, &count); + if (err) + return __hurd_fail (err); + + total = bi.user_time.seconds * 1000000 + bi.user_time.microseconds; + total += tti.user_time.seconds * 1000000 + tti.user_time.microseconds; + total += bi.system_time.seconds * 1000000 + bi.system_time.microseconds; + total += tti.system_time.seconds * 1000000 + tti.system_time.microseconds; + + return total; +} diff --git a/libc/sysdeps/mach/hurd/close.c b/libc/sysdeps/mach/hurd/close.c new file mode 100644 index 000000000..6e18c0891 --- /dev/null +++ b/libc/sysdeps/mach/hurd/close.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991,92,93,94,95,97,2002 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 <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Close the file descriptor FD. */ +int +__close (int fd) +{ + error_t err; + + err = HURD_FD_USE (fd, _hurd_fd_close (descriptor)); + + return err ? __hurd_fail (err) : 0; +} +libc_hidden_def (__close) +weak_alias (__close, close) diff --git a/libc/sysdeps/mach/hurd/closedir.c b/libc/sysdeps/mach/hurd/closedir.c new file mode 100644 index 000000000..2f08f2465 --- /dev/null +++ b/libc/sysdeps/mach/hurd/closedir.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1993, 1995, 1996, 1997 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 <stddef.h> +#include <stdlib.h> +#include <dirent.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> +#include "dirstream.h" + +/* Close the directory stream DIRP. + Return 0 if successful, -1 if not. */ +int +__closedir (DIR *dirp) +{ + error_t err; + + if (dirp == NULL) + { + errno = EINVAL; + return -1; + } + + __libc_lock_lock (dirp->__lock); + err = __vm_deallocate (__mach_task_self (), + (vm_address_t) dirp->__data, dirp->__allocation); + dirp->__data = NULL; + err = _hurd_fd_close (dirp->__fd); + + if (err) + { + /* Unlock the DIR. A failing closedir can be repeated (and may fail + again, but shouldn't deadlock). */ + __libc_lock_unlock (dirp->__lock); + return __hurd_fail (err); + } + + /* Clean up the lock and free the structure. */ + __libc_lock_fini (dirp->__lock); + free (dirp); + + return 0; +} +weak_alias (__closedir, closedir) diff --git a/libc/sysdeps/mach/hurd/configure b/libc/sysdeps/mach/hurd/configure new file mode 100755 index 000000000..959a779fa --- /dev/null +++ b/libc/sysdeps/mach/hurd/configure @@ -0,0 +1,92 @@ +# This file is generated from configure.in by Autoconf. DO NOT EDIT! + +# GNU libc on the Hurd is always reentrant. +DEFINES="$DEFINES -D_LIBC_REENTRANT" + +cat >>confdefs.h <<\_ACEOF +#define NO_HIDDEN 1 +_ACEOF + + +# Don't bother trying to generate any glue code to be compatible with the +# existing system library, because we are the only system library. +inhibit_glue=yes + +if test "x$prefix" != x; then + { echo "$as_me:$LINENO: WARNING: --prefix= (empty) is required for GNU/Hurd to work normally" >&5 +echo "$as_me: WARNING: --prefix= (empty) is required for GNU/Hurd to work normally" >&2;} +fi + +case "$machine" in + i386*) + # The default oldest ABI is 2.2.6. + # We only need a "yes" here if the oldest ABI supported will be < 2.2.6. + if test "$oldest_abi" != default && test "$oldest_abi" \< "2.2.6"; then + libc_cv_gcc_unwind_find_fde=yes + fi + ;; +esac + + +echo "$as_me:$LINENO: checking Hurd header version" >&5 +echo $ECHO_N "checking Hurd header version... $ECHO_C" >&6 +if test "${libc_cv_hurd_version+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <hurd/version.h> +int +main () +{ + +#define NEED_VERSION 20020609 +#if HURD_INTERFACE_VERSION < NEED_VERSION +# error Hurd version too old: HURD_INTERFACE_VERSION < NEED_VERSION +#endif + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + libc_cv_hurd_version=ok +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +libc_cv_hurd_version=bad +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $libc_cv_hurd_version" >&5 +echo "${ECHO_T}$libc_cv_hurd_version" >&6 +if test "x$libc_cv_hurd_version" != xok; then + { { echo "$as_me:$LINENO: error: Hurd headers not installed or too old" >&5 +echo "$as_me: error: Hurd headers not installed or too old" >&2;} + { (exit 1); exit 1; }; } +fi diff --git a/libc/sysdeps/mach/hurd/configure.in b/libc/sysdeps/mach/hurd/configure.in new file mode 100644 index 000000000..87c07c11d --- /dev/null +++ b/libc/sysdeps/mach/hurd/configure.in @@ -0,0 +1,38 @@ +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + +# GNU libc on the Hurd is always reentrant. +DEFINES="$DEFINES -D_LIBC_REENTRANT" + +dnl We need this setting because of the need for PLT calls in ld.so. +AC_DEFINE([NO_HIDDEN]) + +# Don't bother trying to generate any glue code to be compatible with the +# existing system library, because we are the only system library. +inhibit_glue=yes + +if test "x$prefix" != x; then + AC_MSG_WARN([--prefix= (empty) is required for GNU/Hurd to work normally]) +fi + +case "$machine" in + i386*) + # The default oldest ABI is 2.2.6. + # We only need a "yes" here if the oldest ABI supported will be < 2.2.6. + if test "$oldest_abi" != default && test "$oldest_abi" \< "2.2.6"; then + libc_cv_gcc_unwind_find_fde=yes + fi + ;; +esac + +AC_CACHE_CHECK(Hurd header version, libc_cv_hurd_version, [dnl +AC_TRY_COMPILE(dnl +[#include <hurd/version.h>], [ +#define NEED_VERSION 20020609 +#if HURD_INTERFACE_VERSION < NEED_VERSION +# error Hurd version too old: HURD_INTERFACE_VERSION < NEED_VERSION +#endif], + libc_cv_hurd_version=ok, + libc_cv_hurd_version=bad)]) +if test "x$libc_cv_hurd_version" != xok; then + AC_MSG_ERROR(Hurd headers not installed or too old) +fi diff --git a/libc/sysdeps/mach/hurd/connect.c b/libc/sysdeps/mach/hurd/connect.c new file mode 100644 index 000000000..30883f65a --- /dev/null +++ b/libc/sysdeps/mach/hurd/connect.c @@ -0,0 +1,78 @@ +/* Copyright (C) 1992,94,95,96,97,2002 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 <hurd.h> +#include <hurd/fd.h> +#include <sys/socket.h> +#include <hurd/socket.h> +#include <sys/un.h> +#include <hurd/ifsock.h> + +#undef __connect + +/* 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 + and the only address from which to accept transmissions. + Return 0 on success, -1 for errors. */ +int +__connect (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len) +{ + error_t err; + addr_port_t aport; + const struct sockaddr_un *addr = addrarg.__sockaddr_un__; + + if (addr->sun_family == AF_LOCAL) + { + /* 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); + if (file == MACH_PORT_NULL) + return -1; + err = __ifsock_getsockaddr (file, &aport); + __mach_port_deallocate (__mach_task_self (), file); + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + /* The file did not grok the ifsock protocol. */ + err = ENOTSOCK; + if (err) + return __hurd_fail (err); + } + else + err = EIEIO; + + err = HURD_DPORT_USE (fd, + ({ + if (err) + err = __socket_create_address (port, + addr->sun_family, + (char *) addr, len, + &aport); + if (! err) + { + err = __socket_connect (port, aport); + __mach_port_deallocate (__mach_task_self (), + aport); + } + err; + })); + + return err ? __hurd_dfail (fd, err) : 0; +} + +INTDEF(__connect) +weak_alias (__connect, connect) diff --git a/libc/sysdeps/mach/hurd/cthreads.c b/libc/sysdeps/mach/hurd/cthreads.c new file mode 100644 index 000000000..fcadaddbd --- /dev/null +++ b/libc/sysdeps/mach/hurd/cthreads.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1997 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 <bits/libc-lock.h> +#include <errno.h> +#include <stdlib.h> + +/* Placeholder for key creation routine from Hurd cthreads library. */ +int +weak_function +cthread_keycreate (key) + cthread_key_t *key; +{ + __set_errno (ENOSYS); + *key = -1; + return -1; +} + +/* Placeholder for key retrieval routine from Hurd cthreads library. */ +int +weak_function +cthread_getspecific (key, pval) + cthread_key_t key; + void **pval; +{ + *pval = NULL; + __set_errno (ENOSYS); + return -1; +} + +/* Placeholder for key setting routine from Hurd cthreads library. */ +int +weak_function +cthread_setspecific (key, val) + cthread_key_t key; + void *val; +{ + __set_errno (ENOSYS); + return -1; +} + +/* Call cthread_getspecific which gets a pointer to the return value instead + of just returning it. */ +void * +__libc_getspecific (key) + cthread_key_t key; +{ + void *val; + cthread_getspecific (key, &val); + return val; +} diff --git a/libc/sysdeps/mach/hurd/device-nrs.h b/libc/sysdeps/mach/hurd/device-nrs.h new file mode 100644 index 000000000..ce441a50f --- /dev/null +++ b/libc/sysdeps/mach/hurd/device-nrs.h @@ -0,0 +1,28 @@ +/* Device numbers of devices used in the implementation. Hurd version. + Copyright (C) 2001 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 _DEVICE_NRS_H +#define _DEVICE_NRS_H 1 + +#include <hurd/hurd_types.h> + +/* Check whether a given device is a tty. */ +#define DEV_TTY_P(statp) ((statp)->st_fstype == FSTYPE_TERM) + +#endif /* device-nrs.h */ diff --git a/libc/sysdeps/mach/hurd/dirfd.c b/libc/sysdeps/mach/hurd/dirfd.c new file mode 100644 index 000000000..fde13fae3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/dirfd.c @@ -0,0 +1,41 @@ +/* dirfd -- Return the file descriptor used by a DIR stream. Hurd version. + Copyright (C) 1995, 1996 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 <dirent.h> +#include <dirstream.h> +#include <hurd/fd.h> +#include <errno.h> + +int +dirfd (DIR *dirp) +{ + int fd; + __mutex_lock (&_hurd_dtable_lock); + for (fd = 0; fd < _hurd_dtablesize; ++fd) + if (_hurd_dtable[fd] == dirp->__fd) + break; + if (fd == _hurd_dtablesize) + { + errno = EINVAL; + fd = -1; + } + __mutex_unlock (&_hurd_dtable_lock); + + return fd; +} diff --git a/libc/sysdeps/mach/hurd/dirstream.h b/libc/sysdeps/mach/hurd/dirstream.h new file mode 100644 index 000000000..aab6b897f --- /dev/null +++ b/libc/sysdeps/mach/hurd/dirstream.h @@ -0,0 +1,42 @@ +/* Copyright (C) 1993,94,95,96,97,2002 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 _DIRSTREAM_H + +#define _DIRSTREAM_H 1 + +#include <bits/libc-lock.h> + +/* Directory stream type. + + The Hurd directory format is the same as `struct dirent', so `readdir' + returns a pointer into the buffer we read directory data into. */ + +struct __dirstream + { + void *__fd; /* `struct hurd_fd' pointer for descriptor. */ + char *__data; /* Directory block. */ + int __entry_data; /* Entry number `__data' corresponds to. */ + char *__ptr; /* Current pointer into the block. */ + int __entry_ptr; /* Entry number `__ptr' corresponds to. */ + size_t __allocation; /* Space allocated for the block. */ + size_t __size; /* Total valid data in the block. */ + __libc_lock_define (, __lock) /* Mutex lock for this structure. */ + }; + +#endif /* dirstream.h */ diff --git a/libc/sysdeps/mach/hurd/dl-cache.c b/libc/sysdeps/mach/hurd/dl-cache.c new file mode 100644 index 000000000..f7ad3a85d --- /dev/null +++ b/libc/sysdeps/mach/hurd/dl-cache.c @@ -0,0 +1,29 @@ +/* Stubby version of dl-cache; the Hurd doesn't support this "feature". + Copyright (C) 1996, 1997 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. */ + +const char * +_dl_load_cache_lookup (const char *name) +{ + return 0; +} + +void +_dl_unload_cache (void) +{ +} diff --git a/libc/sysdeps/mach/hurd/dl-execstack.c b/libc/sysdeps/mach/hurd/dl-execstack.c new file mode 100644 index 000000000..0e82a3f60 --- /dev/null +++ b/libc/sysdeps/mach/hurd/dl-execstack.c @@ -0,0 +1,52 @@ +/* Stack executability handling for GNU dynamic linker. Hurd version. + Copyright (C) 2004 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 <ldsodefs.h> +#include <hurdstartup.h> +#include <errno.h> + +extern struct hurd_startup_data *_dl_hurd_data attribute_hidden; + +/* There is no portable way to know the bounds of the initial thread's stack + so as to mprotect it. */ + +int +internal_function +_dl_make_stack_executable (void **stack_endp) +{ + /* Challenge the caller. */ + if (__builtin_expect (*stack_endp != __libc_stack_end, 0)) + return EPERM; + *stack_endp = NULL; + +#ifdef IS_IN_rtld + if (__mprotect ((void *)_dl_hurd_data->stack_base, _dl_hurd_data->stack_size, + PROT_READ|PROT_WRITE|PROT_EXEC) != 0) + return errno; + + /* Remember that we changed the permission. */ + GL(dl_stack_flags) |= PF_X; + + return 0; +#else + /* We don't bother to implement this for static linking. */ + return ENOSYS; +#endif +} +rtld_hidden_def (_dl_make_stack_executable) diff --git a/libc/sysdeps/mach/hurd/dl-sysdep.c b/libc/sysdeps/mach/hurd/dl-sysdep.c new file mode 100644 index 000000000..668aaaf8b --- /dev/null +++ b/libc/sysdeps/mach/hurd/dl-sysdep.c @@ -0,0 +1,669 @@ +/* Operating system support for run-time dynamic linker. Hurd version. + Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004 + 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 <hurd.h> +#include <link.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <ldsodefs.h> +#include <sys/wait.h> +#include <assert.h> +#include <sysdep.h> +#include <mach/mig_support.h> +#include "hurdstartup.h" +#include <hurd/lookup.h> +#include <hurd/auth.h> +#include <hurd/term.h> +#include <stdarg.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/uio.h> + +#include <entry.h> +#include <dl-machine.h> +#include <dl-procinfo.h> + +extern void __mach_init (void); + +extern int _dl_argc; +extern char **_dl_argv; +extern char **_environ; + +int __libc_enable_secure = 0; +INTVARDEF(__libc_enable_secure) +int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion + of init-first. */ +/* This variable containts the lowest stack address ever used. */ +void *__libc_stack_end; + +#if HP_TIMING_AVAIL +hp_timing_t _dl_cpuclock_offset; +#endif + + +struct hurd_startup_data *_dl_hurd_data; + +/* This is used only within ld.so, via dl-minimal.c's __errno_location. */ +#undef errno +int errno attribute_hidden; + +/* Defining these variables here avoids the inclusion of hurdsig.c. */ +unsigned long int __hurd_sigthread_stack_base; +unsigned long int __hurd_sigthread_stack_end; +unsigned long int *__hurd_sigthread_variables; + +/* Defining these variables here avoids the inclusion of init-first.c. + We need to provide temporary storage for the per-thread variables + of the main user thread here, since it is used for storing the + `errno' variable. Note that this information is lost once we + relocate the dynamic linker. */ +static unsigned long int threadvars[_HURD_THREADVAR_MAX]; +unsigned long int __hurd_threadvar_stack_offset + = (unsigned long int) &threadvars; +unsigned long int __hurd_threadvar_stack_mask; + +#define FMH defined(__i386__) +#if ! FMH +# define fmh() ((void)0) +# define unfmh() ((void)0) +#else +/* XXX loser kludge for vm_map kernel bug */ +#undef ELF_MACHINE_USER_ADDRESS_MASK +#define ELF_MACHINE_USER_ADDRESS_MASK 0 +static vm_address_t fmha; +static vm_size_t fmhs; +static void unfmh(void){ +__vm_deallocate(__mach_task_self(),fmha,fmhs);} +static void fmh(void) { + error_t err;int x;mach_port_t p; + vm_address_t a=0x08000000U,max=VM_MAX_ADDRESS; + while (!(err=__vm_region(__mach_task_self(),&a,&fmhs,&x,&x,&x,&x,&p,&x))){ + __mach_port_deallocate(__mach_task_self(),p); + if (a+fmhs>=0x80000000U){ + 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);} + } +/* XXX loser kludge for vm_map kernel bug */ +#endif + + +ElfW(Addr) +_dl_sysdep_start (void **start_argptr, + void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phent, + ElfW(Addr) *user_entry)) +{ + void go (intptr_t *argdata) + { + extern unsigned int _dl_skip_args; /* rtld.c */ + char **p; + + /* Cache the information in various global variables. */ + _dl_argc = *argdata; + _dl_argv = 1 + (char **) argdata; + _environ = &_dl_argv[_dl_argc + 1]; + for (p = _environ; *p++;); /* Skip environ pointers and terminator. */ + + if ((void *) p == _dl_argv[0]) + { + static struct hurd_startup_data nodata; + _dl_hurd_data = &nodata; + nodata.user_entry = (vm_address_t) ENTRY_POINT; + } + else + _dl_hurd_data = (void *) p; + + INTUSE(__libc_enable_secure) = _dl_hurd_data->flags & EXEC_SECURE; + + if (_dl_hurd_data->flags & EXEC_STACK_ARGS && + _dl_hurd_data->user_entry == 0) + _dl_hurd_data->user_entry = (vm_address_t) ENTRY_POINT; + +unfmh(); /* XXX */ + +#if 0 /* XXX make this work for real someday... */ + if (_dl_hurd_data->user_entry == (vm_address_t) ENTRY_POINT) + /* We were invoked as a command, not as the program interpreter. + The generic ld.so code supports this: it will parse the args + as "ld.so PROGRAM [ARGS...]". For booting the Hurd, we + support an additional special syntax: + ld.so [-LIBS...] PROGRAM [ARGS...] + Each LIBS word consists of "FILENAME=MEMOBJ"; + for example "-/lib/libc.so=123" says that the contents of + /lib/libc.so are found in a memory object whose port name + in our task is 123. */ + while (_dl_argc > 2 && _dl_argv[1][0] == '-' && _dl_argv[1][1] != '-') + { + char *lastslash, *memobjname, *p; + struct link_map *l; + mach_port_t memobj; + error_t err; + + ++_dl_skip_args; + --_dl_argc; + p = _dl_argv++[1] + 1; + + memobjname = strchr (p, '='); + if (! memobjname) + _dl_sysdep_fatal ("Bogus library spec: ", p, "\n", NULL); + *memobjname++ = '\0'; + memobj = 0; + while (*memobjname != '\0') + memobj = (memobj * 10) + (*memobjname++ - '0'); + + /* Add a user reference on the memory object port, so we will + still have one after _dl_map_object_from_fd calls our + `close'. */ + err = __mach_port_mod_refs (__mach_task_self (), memobj, + MACH_PORT_RIGHT_SEND, +1); + assert_perror (err); + + lastslash = strrchr (p, '/'); + l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p, + memobj, strdup (p), 0); + + /* Squirrel away the memory object port where it + can be retrieved by the program later. */ + l->l_info[DT_NULL] = (void *) memobj; + } +#endif + + /* Call elf/rtld.c's main program. It will set everything + up and leave us to transfer control to USER_ENTRY. */ + (*dl_main) ((const ElfW(Phdr) *) _dl_hurd_data->phdr, + _dl_hurd_data->phdrsz / sizeof (ElfW(Phdr)), + &_dl_hurd_data->user_entry); + + /* The call above might screw a few things up. + + First of all, if _dl_skip_args is nonzero, we are ignoring + the first few arguments. However, if we have no Hurd startup + data, it is the magical convention that ARGV[0] == P. The + startup code in init-first.c will get confused if this is not + the case, so we must rearrange things to make it so. We'll + overwrite the origional ARGV[0] at P with ARGV[_dl_skip_args]. + + Secondly, if we need to be secure, it removes some dangerous + environment variables. If we have no Hurd startup date this + changes P (since that's the location after the terminating + NULL in the list of environment variables). We do the same + thing as in the first case but make sure we recalculate P. + If we do have Hurd startup data, we have to move the data + such that it starts just after the terminating NULL in the + environment list. + + We use memmove, since the locations might overlap. */ + if (INTUSE(__libc_enable_secure) || _dl_skip_args) + { + char **newp; + + for (newp = _environ; *newp++;); + + if (_dl_argv[-_dl_skip_args] == (char *) p) + { + if ((char *) newp != _dl_argv[0]) + { + assert ((char *) newp < _dl_argv[0]); + _dl_argv[0] = memmove ((char *) newp, _dl_argv[0], + strlen (_dl_argv[0]) + 1); + } + } + else + { + if ((void *) newp != _dl_hurd_data) + memmove (newp, _dl_hurd_data, sizeof (*_dl_hurd_data)); + } + } + + { + extern void _dl_start_user (void); + /* Unwind the stack to ARGDATA and simulate a return from _dl_start + to the RTLD_START code which will run the user's entry point. */ + RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry); + } + } + + /* Set up so we can do RPCs. */ + __mach_init (); + + /* Initialize frequently used global variable. */ + GLRO(dl_pagesize) = __getpagesize (); + +#if HP_TIMING_AVAIL + HP_TIMING_NOW (_dl_cpuclock_offset); +#endif + +fmh(); /* XXX */ + + /* See hurd/hurdstartup.c; this deals with getting information + from the exec server and slicing up the arguments. + Then it will call `go', above. */ + _hurd_startup (start_argptr, &go); + + LOSE; + abort (); +} + +void +internal_function +_dl_sysdep_start_cleanup (void) +{ + /* Deallocate the reply port and task port rights acquired by + __mach_init. We are done with them now, and the user will + reacquire them for himself when he wants them. */ + __mig_dealloc_reply_port (MACH_PORT_NULL); + __mach_port_deallocate (__mach_task_self (), __mach_task_self_); +} + +/* Minimal open/close/mmap implementation sufficient for initial loading of + shared libraries. These are weak definitions so that when the + dynamic linker re-relocates itself to be user-visible (for -ldl), + it will get the user's definition (i.e. usually libc's). */ + +/* Open FILE_NAME and return a Hurd I/O for it in *PORT, or return an + error. If STAT is non-zero, stat the file into that stat buffer. */ +static error_t +open_file (const char *file_name, int flags, + mach_port_t *port, struct stat64 *stat) +{ + enum retry_type doretry; + char retryname[1024]; /* XXX string_t LOSES! */ + file_t startdir; + error_t err; + + error_t use_init_port (int which, error_t (*operate) (file_t)) + { + return (which < _dl_hurd_data->portarraysize + ? ((*operate) (_dl_hurd_data->portarray[which])) + : EGRATUITOUS); + } + file_t get_dtable_port (int fd) + { + if ((unsigned int) fd < _dl_hurd_data->dtablesize + && _dl_hurd_data->dtable[fd] != MACH_PORT_NULL) + { + __mach_port_mod_refs (__mach_task_self (), _dl_hurd_data->dtable[fd], + MACH_PORT_RIGHT_SEND, +1); + return _dl_hurd_data->dtable[fd]; + } + errno = EBADF; + return MACH_PORT_NULL; + } + + assert (!(flags & ~O_READ)); + + startdir = _dl_hurd_data->portarray[file_name[0] == '/' ? + INIT_PORT_CRDIR : INIT_PORT_CWDIR]; + + while (file_name[0] == '/') + file_name++; + + err = __dir_lookup (startdir, (char *)file_name, O_RDONLY, 0, + &doretry, retryname, port); + + if (!err) + err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port, + __dir_lookup, doretry, retryname, + O_RDONLY, 0, port); + if (!err && stat) + { + err = __io_stat (*port, stat); + if (err) + __mach_port_deallocate (__mach_task_self (), *port); + } + + return err; +} + +int weak_function +__open (const char *file_name, int mode, ...) +{ + mach_port_t port; + error_t err = open_file (file_name, mode, &port, 0); + if (err) + return __hurd_fail (err); + else + return (int)port; +} + +int weak_function +__close (int fd) +{ + if (fd != (int) MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd); + return 0; +} + +__ssize_t weak_function +__libc_read (int fd, void *buf, size_t nbytes) +{ + error_t err; + char *data; + mach_msg_type_number_t nread; + + data = buf; + err = __io_read ((mach_port_t) fd, &data, &nread, -1, nbytes); + if (err) + return __hurd_fail (err); + + if (data != buf) + { + memcpy (buf, data, nread); + __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread); + } + + return nread; +} +libc_hidden_weak (__libc_read) + +__ssize_t weak_function +__libc_write (int fd, const void *buf, size_t nbytes) +{ + error_t err; + mach_msg_type_number_t nwrote; + + assert (fd < _hurd_init_dtablesize); + + err = __io_write (_hurd_init_dtable[fd], buf, nbytes, -1, &nwrote); + if (err) + return __hurd_fail (err); + + return nwrote; +} +libc_hidden_weak (__libc_write) + +/* This is only used for printing messages (see dl-misc.c). */ +__ssize_t weak_function +__writev (int fd, const struct iovec *iov, int niov) +{ + if (fd >= _hurd_init_dtablesize) + { + errno = EBADF; + return -1; + } + + int i; + size_t total = 0; + for (i = 0; i < niov; ++i) + total += iov[i].iov_len; + + if (total != 0) + { + char buf[total], *bufp = buf; + error_t err; + mach_msg_type_number_t nwrote; + + for (i = 0; i < niov; ++i) + bufp = (memcpy (bufp, iov[i].iov_base, iov[i].iov_len) + + iov[i].iov_len); + + err = __io_write (_hurd_init_dtable[fd], buf, total, -1, &nwrote); + if (err) + return __hurd_fail (err); + + return nwrote; + } + return 0; +} + + +off64_t weak_function +__libc_lseek64 (int fd, off64_t offset, int whence) +{ + error_t err; + + err = __io_seek ((mach_port_t) fd, offset, whence, &offset); + if (err) + return __hurd_fail (err); + + return offset; +} + +__ptr_t weak_function +__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset) +{ + error_t err; + vm_prot_t vmprot; + vm_address_t mapaddr; + mach_port_t memobj_rd, memobj_wr; + + vmprot = VM_PROT_NONE; + if (prot & PROT_READ) + vmprot |= VM_PROT_READ; + if (prot & PROT_WRITE) + vmprot |= VM_PROT_WRITE; + if (prot & PROT_EXEC) + vmprot |= VM_PROT_EXECUTE; + + if (flags & MAP_ANON) + memobj_rd = MACH_PORT_NULL; + else + { + assert (!(flags & MAP_SHARED)); + err = __io_map ((mach_port_t) fd, &memobj_rd, &memobj_wr); + if (err) + return __hurd_fail (err), MAP_FAILED; + __mach_port_deallocate (__mach_task_self (), memobj_wr); + } + + mapaddr = (vm_address_t) addr; + err = __vm_map (__mach_task_self (), + &mapaddr, (vm_size_t) len, ELF_MACHINE_USER_ADDRESS_MASK, + !(flags & MAP_FIXED), + memobj_rd, + (vm_offset_t) offset, + flags & (MAP_COPY|MAP_PRIVATE), + vmprot, VM_PROT_ALL, + (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY); + if (err == KERN_NO_SPACE && (flags & MAP_FIXED)) + { + /* XXX this is not atomic as it is in unix! */ + /* The region is already allocated; deallocate it first. */ + err = __vm_deallocate (__mach_task_self (), mapaddr, len); + if (! err) + err = __vm_map (__mach_task_self (), + &mapaddr, (vm_size_t) len, + ELF_MACHINE_USER_ADDRESS_MASK, + !(flags & MAP_FIXED), + memobj_rd, (vm_offset_t) offset, + flags & (MAP_COPY|MAP_PRIVATE), + vmprot, VM_PROT_ALL, + (flags & MAP_SHARED) + ? VM_INHERIT_SHARE : VM_INHERIT_COPY); + } + + if ((flags & MAP_ANON) == 0) + __mach_port_deallocate (__mach_task_self (), memobj_rd); + + if (err) + return __hurd_fail (err), MAP_FAILED; + return (__ptr_t) mapaddr; +} + +int weak_function +__fxstat64 (int vers, int fd, struct stat64 *buf) +{ + error_t err; + + assert (vers == _STAT_VER); + + err = __io_stat ((mach_port_t) fd, buf); + if (err) + return __hurd_fail (err); + + return 0; +} +libc_hidden_def (__fxstat64) + +int weak_function +__xstat64 (int vers, const char *file, struct stat64 *buf) +{ + error_t err; + mach_port_t port; + + assert (vers == _STAT_VER); + + err = open_file (file, 0, &port, buf); + if (err) + return __hurd_fail (err); + + __mach_port_deallocate (__mach_task_self (), port); + + return 0; +} +libc_hidden_def (__xstat64) + +/* This function is called by the dynamic linker (rtld.c) to check + whether debugging malloc is allowed even for SUID binaries. This + stub will always fail, which means that malloc-debugging is always + disabled for SUID binaries. */ +int weak_function +__access (const char *file, int type) +{ + errno = ENOSYS; + return -1; +} + +pid_t weak_function +__getpid () +{ + pid_t pid, ppid; + int orphaned; + + if (__proc_getpids (_dl_hurd_data->portarray[INIT_PORT_PROC], + &pid, &ppid, &orphaned)) + return -1; + + return pid; +} + +/* This is called only in some strange cases trying to guess a value + for $ORIGIN for the executable. The dynamic linker copes with + getcwd failing (dl-object.c), and it's too much hassle to include + the functionality here. (We could, it just requires duplicating or + reusing getcwd.c's code but using our special lookup function as in + `open', above.) */ +char * +weak_function +__getcwd (char *buf, size_t size) +{ + errno = ENOSYS; + return NULL; +} + +void weak_function attribute_hidden +_exit (int status) +{ + __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC], + W_EXITCODE (status, 0), 0); + while (__task_terminate (__mach_task_self ())) + __mach_task_self_ = (__mach_task_self) (); +} +/* We need this alias to satisfy references from libc_pic.a objects + that were affected by the libc_hidden_proto declaration for _exit. */ +strong_alias (_exit, __GI__exit) + +/* Try to get a machine dependent instruction which will make the + program crash. This is used in case everything else fails. */ +#include <abort-instr.h> +#ifndef ABORT_INSTRUCTION +/* No such instruction is available. */ +# define ABORT_INSTRUCTION +#endif + +void weak_function +abort (void) +{ + /* Try to abort using the system specific command. */ + ABORT_INSTRUCTION; + + /* If the abort instruction failed, exit. */ + _exit (127); + + /* If even this fails, make sure we never return. */ + while (1) + /* Try for ever and ever. */ + ABORT_INSTRUCTION; +} + +/* We need this alias to satisfy references from libc_pic.a objects + that were affected by the libc_hidden_proto declaration for abort. */ +strong_alias (abort, __GI_abort) + +/* This function is called by interruptible RPC stubs. For initial + dynamic linking, just use the normal mach_msg. Since this defn is + weak, the real defn in libc.so will override it if we are linked into + the user program (-ldl). */ + +error_t weak_function +_hurd_intr_rpc_mach_msg (mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t timeout, + mach_port_t notify) +{ + return __mach_msg (msg, option, send_size, rcv_size, rcv_name, + timeout, notify); +} + + +void +internal_function +_dl_show_auxv (void) +{ + /* There is nothing to print. Hurd has no auxiliary vector. */ +} + + +/* Return an array of useful/necessary hardware capability names. */ +const struct r_strlenpair * +internal_function +_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, + size_t *max_capstrlen) +{ + struct r_strlenpair *result; + + /* Return an empty array. Hurd has no hardware capabilities. */ + result = (struct r_strlenpair *) malloc (sizeof (*result)); + if (result == NULL) + _dl_signal_error (ENOMEM, NULL, NULL, "cannot create capability list"); + + result[0].str = (char *) result; /* Does not really matter. */ + result[0].len = 0; + + *sz = 1; + return result; +} + +void weak_function +_dl_init_first (int argc, ...) +{ + /* This no-op definition only gets used if libc is not linked in. */ +} diff --git a/libc/sysdeps/mach/hurd/dl-sysdep.h b/libc/sysdeps/mach/hurd/dl-sysdep.h new file mode 100644 index 000000000..4b21b779e --- /dev/null +++ b/libc/sysdeps/mach/hurd/dl-sysdep.h @@ -0,0 +1,31 @@ +/* System-specific settings for dynamic linker code. Hurd version. + Copyright (C) 2002, 2005 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. */ + +/* The private errno doesn't make sense on the Hurd. errno is always the + thread-local slot shared with libc, and it matters to share the cell + with libc because after startup we use libc functions that set errno + (open, mmap, etc). */ + +#define RTLD_PRIVATE_ERRNO 0 + +#ifdef SHARED +/* _dl_argv cannot be attribute_relro, because the stack-switching + libc initializer for using cthreads might write into it. */ +# define DL_ARGV_NOT_RELRO 1 +#endif diff --git a/libc/sysdeps/mach/hurd/dup2.c b/libc/sysdeps/mach/hurd/dup2.c new file mode 100644 index 000000000..3abd30cfb --- /dev/null +++ b/libc/sysdeps/mach/hurd/dup2.c @@ -0,0 +1,134 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 97, 2002 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 <fcntl.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Duplicate FD to FD2, closing the old FD2 and making FD2 be + open on the same file as FD is. Return FD2 or -1. */ +int +__dup2 (fd, fd2) + int fd; + int fd2; +{ + struct hurd_fd *d; + + /* Extract the ports and flags from FD. */ + d = _hurd_fd_get (fd); + if (d == NULL) + { + errno = EBADF; + return -1; + } + + HURD_CRITICAL_BEGIN; + + __spin_lock (&d->port.lock); + if (d->port.port == MACH_PORT_NULL) + { + __spin_unlock (&d->port.lock); + errno = EBADF; + fd2 = -1; + } + else if (fd2 == fd) + /* FD is valid and FD2 is already the same; just return it. */ + __spin_unlock (&d->port.lock); + else + { + struct hurd_userlink ulink, ctty_ulink; + int flags = d->flags; + io_t ctty = _hurd_port_get (&d->ctty, &ctty_ulink); + io_t port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */ + + if (fd2 < 0) + { + errno = EBADF; + fd2 = -1; + } + else + { + /* Get a hold of the destination descriptor. */ + struct hurd_fd *d2; + + if (fd2 >= _hurd_dtablesize) + { + /* The table is not large enough to hold the destination + descriptor. Enlarge it as necessary to allocate this + descriptor. */ + __mutex_unlock (&_hurd_dtable_lock); + /* We still hold FD1's lock, but this is safe because + _hurd_alloc_fd will only examine the cells starting + at FD2. */ + d2 = _hurd_alloc_fd (NULL, fd2); + if (d2) + __spin_unlock (&d2->port.lock); + __mutex_lock (&_hurd_dtable_lock); + } + else + { + d2 = _hurd_dtable[fd2]; + if (d2 == NULL) + { + /* Must allocate a new one. We don't initialize the port + cells with this call so that if it fails (out of + memory), we will not have already added user + references for the ports, which we would then have to + deallocate. */ + d2 = _hurd_dtable[fd2] = _hurd_new_fd (MACH_PORT_NULL, + MACH_PORT_NULL); + } + } + + if (d2 == NULL) + { + fd2 = -1; + if (errno == EINVAL) + errno = EBADF; /* POSIX.1-1990 6.2.1.2 ll 54-55. */ + } + else + { + /* Give the ports each a user ref for the new descriptor. */ + __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_SEND, 1); + if (ctty != MACH_PORT_NULL) + __mach_port_mod_refs (__mach_task_self (), ctty, + MACH_PORT_RIGHT_SEND, 1); + + /* Install the ports and flags in the new descriptor slot. */ + __spin_lock (&d2->port.lock); + d2->flags = flags & ~FD_CLOEXEC; /* Dup clears FD_CLOEXEC. */ + _hurd_port_set (&d2->ctty, ctty); + _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */ + } + } + __mutex_unlock (&_hurd_dtable_lock); + + _hurd_port_free (&d->port, &ulink, port); + if (ctty != MACH_PORT_NULL) + _hurd_port_free (&d->ctty, &ctty_ulink, port); + } + + HURD_CRITICAL_END; + + return fd2; +} +libc_hidden_def (__dup2) +weak_alias (__dup2, dup2) diff --git a/libc/sysdeps/mach/hurd/enbl-secure.c b/libc/sysdeps/mach/hurd/enbl-secure.c new file mode 100644 index 000000000..19f724ca7 --- /dev/null +++ b/libc/sysdeps/mach/hurd/enbl-secure.c @@ -0,0 +1,24 @@ +/* Define and initialize the `__libc_enable_secure' flag. Hurd version. + Copyright (C) 1998 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. */ + +/* There is no need for this file in the Hurd; it is just a placeholder + to prevent inclusion of the sysdeps/generic version. + In the shared library, the `__libc_enable_secure' variable is defined + by the dynamic linker in dl-sysdep.c and set there. + In the static library, it is defined in init-first.c and set there. */ diff --git a/libc/sysdeps/mach/hurd/err_hurd.sub b/libc/sysdeps/mach/hurd/err_hurd.sub new file mode 100644 index 000000000..4a4dee3aa --- /dev/null +++ b/libc/sysdeps/mach/hurd/err_hurd.sub @@ -0,0 +1,12 @@ +/* This file defines the Mach error system for Hurd server errors. */ + +#include <errno.h> + +extern const char *const _hurd_errlist[]; + +/* Omit `const' because we are included with `static' + defined to `static const'. */ +static struct error_subsystem err_hurd_sub[] = + { + { "(os/hurd)", _HURD_ERRNOS, (const char *const *) _hurd_errlist }, + }; diff --git a/libc/sysdeps/mach/hurd/errlist.c b/libc/sysdeps/mach/hurd/errlist.c new file mode 100644 index 000000000..fe5709cf6 --- /dev/null +++ b/libc/sysdeps/mach/hurd/errlist.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1998,2002 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. */ + +/* sys_errlist cannot have Unix semantics on the Hurd, so it is easier just + to rename it. We also need to remap error codes to array indices by + taking their subcode. */ +#define _sys_errlist_internal _hurd_errlist +#define _sys_nerr_internal _hurd_nerr +#define ERRLIST_NO_COMPAT 1 + +#include <mach/error.h> +#define ERR_REMAP(n) (err_get_code (n)) + +#include <sysdeps/gnu/errlist.c> diff --git a/libc/sysdeps/mach/hurd/errno-loc.c b/libc/sysdeps/mach/hurd/errno-loc.c new file mode 100644 index 000000000..9ff09ebb6 --- /dev/null +++ b/libc/sysdeps/mach/hurd/errno-loc.c @@ -0,0 +1,29 @@ +/* __errno_location -- helper function for locating per-thread errno value + Copyright (C) 2002 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 <hurd/threadvar.h> + +int * +__errno_location (void) +{ + return (int *) __hurd_threadvar_location (_HURD_THREADVAR_ERRNO); +} +strong_alias (__errno_location, __hurd_errno_location) +libc_hidden_def (__errno_location) diff --git a/libc/sysdeps/mach/hurd/errno.c b/libc/sysdeps/mach/hurd/errno.c new file mode 100644 index 000000000..a29091b5e --- /dev/null +++ b/libc/sysdeps/mach/hurd/errno.c @@ -0,0 +1 @@ +/* No definition of `errno' variable on the Hurd. */ diff --git a/libc/sysdeps/mach/hurd/errnos.awk b/libc/sysdeps/mach/hurd/errnos.awk new file mode 100644 index 000000000..cefa24f0a --- /dev/null +++ b/libc/sysdeps/mach/hurd/errnos.awk @@ -0,0 +1,169 @@ +# Copyright (C) 1991,92,93,94,95,96,97,2000,01,02 +# 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. + +# errno.texinfo contains lines like: +# @comment errno.h +# @comment POSIX.1: Function not implemented +# @deftypevr Macro int ENOSYS +# @comment errno 123 + +BEGIN { + print "/* This file generated by errnos.awk. */"; + print ""; + print "/* The Hurd uses Mach error system 0x10, currently only subsystem 0. */"; + print "#ifndef _HURD_ERRNO"; + print "#define _HURD_ERRNO(n)\t((0x10 << 26) | ((n) & 0x3fff))"; + print "#endif"; + print ""; + print "#ifdef _ERRNO_H\n"; + print "enum __error_t_codes\n{"; + errnoh = 0; + maxerrno = 0; + in_mach_errors = ""; + in_math = 0; + edom = erange = ""; + print "#undef EDOM\n#undef ERANGE"; + lno = 0; + } + +$1 == "@comment" && $2 == "errno.h" { errnoh=1; next } +$1 == "@comment" && errnoh == 1 \ + { + ++errnoh; + etext = ""; + for (i = 3; i <= NF; ++i) + etext = etext " " $i; + next; + } + +errnoh == 2 && $1 == "@deftypevr" && $2 == "Macro" && $3 == "int" \ + { ++errnoh; e = $4; next; } + +errnoh == 3 && $1 == "@comment" && $2 == "errno" { + if (e == "EWOULDBLOCK") + { + lines[lno++]="#define EWOULDBLOCK EAGAIN /* Operation would block */"; + next; + } + errno = $3 + 0; + if (errno == 0) + next; + if (errno > maxerrno) maxerrno = errno; + x = sprintf ("%-40s/*%s */", sprintf ("%-24s%s", "#define\t" e, + "_HURD_ERRNO (" errno ")"), + etext); + if (e == "EDOM") + edom = x; + else if (e == "ERANGE") + erange = x; + comma[lno] = 1; + lines[lno++] = sprintf("\t%-16s= _HURD_ERRNO (%d)", e, errno); + lines[lno++] = x; + next; + } +{ errnoh=0 } + +NF == 3 && $1 == "#define" && $2 == "MACH_SEND_IN_PROGRESS" \ + { + in_mach_errors = FILENAME; + lines[lno++] = "\n\t/* Errors from <mach/message.h>. */"; + } +NF == 3 && $1 == "#define" && $2 == "KERN_SUCCESS" \ + { + in_mach_errors = FILENAME; + lines[lno++] = "\n\t/* Errors from <mach/kern_return.h>. */"; + next; + } + +in_mach_errors != "" && $2 == "MACH_IPC_COMPAT" \ + { + in_mach_errors = ""; + } + +in_mach_errors == FILENAME && NF == 3 && $1 == "#define" \ + { + comma[lno] = 1; + lines[lno++] = sprintf("\t%-32s= %s", "E" $2, $3); + } + +$1 == "#define" && $2 == "_MACH_MIG_ERRORS_H_" \ + { + in_mig_errors = 1; + lines[lno++] = "\n\t/* Errors from <mach/mig_errors.h>. */"; + next; + } +in_mig_errors && $1 == "#endif" && $3 == "_MACH_MIG_ERRORS_H_" \ + { + in_mig_errors = 0; + } + +(in_mig_errors && $1 == "#define" && $3 <= -300) || \ +(in_device_errors && $1 == "#define" && /D_/ && NF > 3) \ + { + comment = ""; + for (i = 4; i <= NF; ++i) + comment = comment " " $i; + comma[lno] = 1; + lines[lno++] = sprintf("%-32s", sprintf ("\t%-24s= %s", "E" $2, $3)) comment; + } + +$1 == "#define" && $2 == "D_SUCCESS" \ + { + in_device_errors = 1; + lines[lno++] = "\n\t/* Errors from <device/device_types.h>. */"; + next; + } +in_device_errors && $1 == "#endif" \ + { + in_device_errors = 0; + } + + +END \ + { + for (i = 0; i < lno - 1; ++i) + printf "%s%s\n", lines[i], (comma[i] ? "," : ""); + print lines[i]; + print ""; + print "};"; + print ""; + printf "#define\t_HURD_ERRNOS\t%d\n", maxerrno+1; + print ""; + print "\ +/* User-visible type of error codes. It is ok to use `int' or\n\ + `kern_return_t' for these, but with `error_t' the debugger prints\n\ + symbolic values. */"; + print "#ifdef __USE_GNU"; + print "typedef enum __error_t_codes error_t;" + print "#define __error_t_defined\t1" + print "#endif"; + print ""; + print "\ +/* Return the current thread's location for `errno'.\n\ + The syntax of this function allows redeclarations like `int errno'. */\n\ +extern int *__errno_location (void) __THROW __attribute__ ((__const__));\n\ +\n\ +#define errno (*__errno_location ())\n\ +"; + print "#endif /* <errno.h> included. */"; + print ""; + print "#if !defined (_ERRNO_H) && defined (__need_Emath)"; + print edom; print erange; + print "#endif /* <errno.h> not included and need math error codes. */"; + } diff --git a/libc/sysdeps/mach/hurd/euidaccess.c b/libc/sysdeps/mach/hurd/euidaccess.c new file mode 100644 index 000000000..57f2a015c --- /dev/null +++ b/libc/sysdeps/mach/hurd/euidaccess.c @@ -0,0 +1,60 @@ +/* Test for access to FILE using effective UID and GID. Hurd version. + Copyright (C) 1991, 1995, 1997, 2006 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 <stddef.h> +#include <unistd.h> +#include <fcntl.h> +#include <hurd.h> + +int +__euidaccess (file, type) + const char *file; + int type; +{ + error_t err; + file_t port; + int allowed, flags; + + port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + + /* Find out what types of access we are allowed to this file. */ + err = __file_check_access (port, &allowed); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + + flags = 0; + if (type & R_OK) + flags |= O_READ; + if (type & W_OK) + flags |= O_WRITE; + if (type & X_OK) + flags |= O_EXEC; + + if (flags & ~allowed) + /* We are not allowed all the requested types of access. */ + return __hurd_fail (EACCES); + + return 0; +} +weak_alias (__euidaccess, euidaccess) +weak_alias (__euidaccess, eaccess) diff --git a/libc/sysdeps/mach/hurd/execve.c b/libc/sysdeps/mach/hurd/execve.c new file mode 100644 index 000000000..8af8b330b --- /dev/null +++ b/libc/sysdeps/mach/hurd/execve.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 97 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 <unistd.h> +#include <hurd.h> +#include <fcntl.h> + +/* Replace the current process, executing FILE_NAME with arguments ARGV and + environment ENVP. ARGV and ENVP are terminated by NULL pointers. */ +int +__execve (file_name, argv, envp) + const char *file_name; + char *const argv[]; + char *const envp[]; +{ + error_t err; + file_t file = __file_name_lookup (file_name, O_EXEC, 0); + + if (file == MACH_PORT_NULL) + return -1; + + /* Hopefully this will not return. */ + err = _hurd_exec (__mach_task_self (), file, argv, envp); + + /* Oh well. Might as well be tidy. */ + __mach_port_deallocate (__mach_task_self (), file); + + return __hurd_fail (err); +} + +weak_alias (__execve, execve) diff --git a/libc/sysdeps/mach/hurd/faccessat.c b/libc/sysdeps/mach/hurd/faccessat.c new file mode 100644 index 000000000..bb3c9fe19 --- /dev/null +++ b/libc/sysdeps/mach/hurd/faccessat.c @@ -0,0 +1,70 @@ +/* Test for access to file, relative to open directory. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <sys/types.h> +#include <hurd.h> +#include <hurd/fd.h> + +int +faccessat (fd, file, type, flag) + int fd; + const char *file; + int type; + int flag; +{ + error_t err; + file_t port; + int allowed, flags; + + if ((flag & AT_EACCESS) == 0) + { + if (fd == AT_FDCWD || file[0] == '/') + return __access (file, type); + __set_errno (ENOTSUP); /* XXX later */ + return -1; + } + + port = __file_name_lookup_at (fd, flag &~ AT_EACCESS, file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + + /* Find out what types of access we are allowed to this file. */ + err = __file_check_access (port, &allowed); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + + flags = 0; + if (type & R_OK) + flags |= O_READ; + if (type & W_OK) + flags |= O_WRITE; + if (type & X_OK) + flags |= O_EXEC; + + if (flags & ~allowed) + /* We are not allowed all the requested types of access. */ + return __hurd_fail (EACCES); + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/fchdir.c b/libc/sysdeps/mach/hurd/fchdir.c new file mode 100644 index 000000000..d1d4fc38e --- /dev/null +++ b/libc/sysdeps/mach/hurd/fchdir.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,99 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 <unistd.h> +#include <hurd.h> +#include <hurd/port.h> +#include <hurd/fd.h> + +/* Change the current directory to FD. */ + +int +__fchdir (fd) + int fd; +{ + return _hurd_change_directory_port_from_fd (&_hurd_ports[INIT_PORT_CWDIR], + fd); +} +weak_alias (__fchdir, fchdir) diff --git a/libc/sysdeps/mach/hurd/fchflags.c b/libc/sysdeps/mach/hurd/fchflags.c new file mode 100644 index 000000000..71bcbf0c9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fchflags.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 92, 93, 94, 97, 98 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Change the flags of the file FD refers to to FLAGS. */ + +/* XXX should be __fchflags? */ +int +fchflags (int fd, int flags) +{ + error_t err; + + if (err = HURD_DPORT_USE (fd, __file_chflags (port, flags))) + return __hurd_dfail (fd, err); + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/fchmod.c b/libc/sysdeps/mach/hurd/fchmod.c new file mode 100644 index 000000000..025b09200 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fchmod.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991, 1992, 1994, 1995, 1997 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Change the protections of the file FD refers to to MODE. */ +int +__fchmod (fd, mode) + int fd; + mode_t mode; +{ + error_t err; + + if (err = HURD_DPORT_USE (fd, __file_chmod (port, mode))) + return __hurd_dfail (fd, err); + + return 0; +} + +weak_alias (__fchmod, fchmod) diff --git a/libc/sysdeps/mach/hurd/fchmodat.c b/libc/sysdeps/mach/hurd/fchmodat.c new file mode 100644 index 000000000..d27e84527 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fchmodat.c @@ -0,0 +1,44 @@ +/* Change the protections of file relative to open directory. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <sys/types.h> +#include <hurd.h> +#include <hurd/fd.h> + +int +fchmodat (fd, file, mode, flag) + int fd; + const char *file; + mode_t mode; + int flag; +{ + error_t err; + file_t port = __file_name_lookup_at (fd, flag, file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chmod (port, mode); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/fchown.c b/libc/sysdeps/mach/hurd/fchown.c new file mode 100644 index 000000000..3286e24bc --- /dev/null +++ b/libc/sysdeps/mach/hurd/fchown.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 97 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 <stddef.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Change the owner and group of the file referred to by FD. */ +int +__fchown (fd, owner, group) + int fd; + uid_t owner; + gid_t group; +{ + error_t err; + + if (err = HURD_DPORT_USE (fd, __file_chown (port, owner, group))) + return __hurd_dfail (fd, err); + + return 0; +} + +weak_alias (__fchown, fchown) diff --git a/libc/sysdeps/mach/hurd/fchownat.c b/libc/sysdeps/mach/hurd/fchownat.c new file mode 100644 index 000000000..1b99b2927 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fchownat.c @@ -0,0 +1,46 @@ +/* Change owner and group of a file relative to open directory. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <sys/types.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Change the owner and group of FILE. */ +int +fchownat (fd, file, owner, group, flag) + int fd; + const char *file; + uid_t owner; + gid_t group; + int flag; +{ + error_t err; + file_t port = __file_name_lookup_at (fd, flag, file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chown (port, owner, group); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/fcntl.c b/libc/sysdeps/mach/hurd/fcntl.c new file mode 100644 index 000000000..d4e4aa5da --- /dev/null +++ b/libc/sysdeps/mach/hurd/fcntl.c @@ -0,0 +1,207 @@ +/* Copyright (C) 1992-1997,1999,2000,2002 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 <fcntl.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <stdarg.h> +#include <sys/file.h> /* XXX for LOCK_* */ + +/* Perform file control operations on FD. */ +int +__libc_fcntl (int fd, int cmd, ...) +{ + va_list ap; + struct hurd_fd *d; + int result; + + d = _hurd_fd_get (fd); + + if (d == NULL) + return __hurd_fail (EBADF); + + va_start (ap, cmd); + + switch (cmd) + { + error_t err; + + default: /* Bad command. */ + errno = EINVAL; + result = -1; + break; + + /* First the descriptor-based commands, which do no RPCs. */ + + case F_DUPFD: /* Duplicate the file descriptor. */ + { + struct hurd_fd *new; + io_t port, ctty; + struct hurd_userlink ulink, ctty_ulink; + int flags; + + HURD_CRITICAL_BEGIN; + + /* Extract the ports and flags from the file descriptor. */ + __spin_lock (&d->port.lock); + flags = d->flags; + ctty = _hurd_port_get (&d->ctty, &ctty_ulink); + port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */ + + /* Get a new file descriptor. The third argument to __fcntl is the + minimum file descriptor number for it. */ + new = _hurd_alloc_fd (&result, va_arg (ap, int)); + if (new == NULL) + /* _hurd_alloc_fd has set errno. */ + result = -1; + else + { + /* Give the ports each a user ref for the new descriptor. */ + __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_SEND, 1); + if (ctty != MACH_PORT_NULL) + __mach_port_mod_refs (__mach_task_self (), ctty, + MACH_PORT_RIGHT_SEND, 1); + + /* Install the ports and flags in the new descriptor. */ + if (ctty != MACH_PORT_NULL) + _hurd_port_set (&new->ctty, ctty); + /* Duplication clears the FD_CLOEXEC flag. */ + new->flags = flags & ~FD_CLOEXEC; + _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */ + } + + HURD_CRITICAL_END; + + _hurd_port_free (&d->port, &ulink, port); + if (ctty != MACH_PORT_NULL) + _hurd_port_free (&d->ctty, &ctty_ulink, port); + + break; + } + + /* Set RESULT by evaluating EXPR with the descriptor locked. + Check for an empty descriptor and return EBADF. */ +#define LOCKED(expr) \ + HURD_CRITICAL_BEGIN; \ + __spin_lock (&d->port.lock); \ + if (d->port.port == MACH_PORT_NULL) \ + result = __hurd_fail (EBADF); \ + else \ + result = (expr); \ + __spin_unlock (&d->port.lock); \ + HURD_CRITICAL_END; + + case F_GETFD: /* Get descriptor flags. */ + LOCKED (d->flags); + break; + + case F_SETFD: /* Set descriptor flags. */ + LOCKED ((d->flags = va_arg (ap, int), 0)); + break; + + + /* Now the real io operations, done by RPCs to io servers. */ + + case F_GETLK: + 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 *); + va_end (ap); + switch (cmd) + { + case F_GETLK: + errno = ENOSYS; + return -1; + 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; + default: + errno = EINVAL; + return -1; + } + switch (fl->l_whence) + { + 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; + return -1; + default: + errno = EINVAL; + return -1; + } + + return __flock (fd, cmd); + } + + case F_GETFL: /* Get per-open flags. */ + if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result))) + result = __hurd_dfail (fd, err); + break; + + case F_SETFL: /* Set per-open flags. */ + err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port, + va_arg (ap, int))); + result = err ? __hurd_dfail (fd, err) : 0; + break; + + case F_GETOWN: /* Get owner. */ + if (err = HURD_FD_PORT_USE (d, __io_get_owner (port, &result))) + result = __hurd_dfail (fd, err); + break; + + case F_SETOWN: /* Set owner. */ + err = HURD_FD_PORT_USE (d, __io_mod_owner (port, va_arg (ap, pid_t))); + result = err ? __hurd_dfail (fd, err) : 0; + break; + } + + va_end (ap); + + return result; +} +libc_hidden_def (__libc_fcntl) +weak_alias (__libc_fcntl, __fcntl) +libc_hidden_weak (__fcntl) +weak_alias (__libc_fcntl, fcntl) diff --git a/libc/sysdeps/mach/hurd/fdatasync.c b/libc/sysdeps/mach/hurd/fdatasync.c new file mode 100644 index 000000000..4546cb9ed --- /dev/null +++ b/libc/sysdeps/mach/hurd/fdatasync.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 92, 93, 94, 96, 97 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 <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Make all changes done to FD's file data actually appear on disk. */ +int +fdatasync (int fd) +{ + error_t err = HURD_DPORT_USE (fd, __file_sync (port, 1, 1)); + if (err) + return __hurd_dfail (fd, err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/fdopendir.c b/libc/sysdeps/mach/hurd/fdopendir.c new file mode 100644 index 000000000..016f825f1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fdopendir.c @@ -0,0 +1,58 @@ +/* Open a directory stream from a file descriptor. Hurd version. + Copyright (C) 2005, 2006 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 <dirent.h> +#include <errno.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <fcntl.h> + +DIR *_hurd_fd_opendir (struct hurd_fd *d); /* opendir.c */ + +/* Open a directory stream on FD. */ +DIR * +__fdopendir (int fd) +{ + struct hurd_fd *d = _hurd_fd_get (fd); + + if (d == NULL) + { + errno = EBADF; + return NULL; + } + + /* Ensure that it's a directory. */ + error_t err = HURD_FD_PORT_USE + (d, ({ + file_t dir = __file_name_lookup_under (port, "/", + O_DIRECTORY | O_NOTRANS, 0);; + if (dir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), dir); + dir != MACH_PORT_NULL ? 0 : errno; + })); + + if (err) + { + errno = err; + return NULL; + } + + return _hurd_fd_opendir (d); +} +weak_alias (__fdopendir, fdopendir) diff --git a/libc/sysdeps/mach/hurd/fexecve.c b/libc/sysdeps/mach/hurd/fexecve.c new file mode 100644 index 000000000..d6eb7c09a --- /dev/null +++ b/libc/sysdeps/mach/hurd/fexecve.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1993, 1994, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <errno.h> + +/* Execute the file FD refers to, overlaying the running program image. */ + +int +fexecve (int fd, char *const argv[], char *const envp[]) +{ + error_t err = HURD_DPORT_USE (fd, _hurd_exec (__mach_task_self (), port, + argv, envp)); + if (! err) + err = EGRATUITOUS; + return __hurd_fail (err); +} diff --git a/libc/sysdeps/mach/hurd/fgetxattr.c b/libc/sysdeps/mach/hurd/fgetxattr.c new file mode 100644 index 000000000..2eb6db06c --- /dev/null +++ b/libc/sysdeps/mach/hurd/fgetxattr.c @@ -0,0 +1,34 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2004 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> +#include <hurd/fd.h> + +ssize_t +fgetxattr (int fd, const char *name, void *value, size_t size) +{ + error_t err; + + err = HURD_DPORT_USE (fd, _hurd_xattr_get (port, name, value, &size)); + + return err ? __hurd_dfail (fd, err) : size; +} diff --git a/libc/sysdeps/mach/hurd/flistxattr.c b/libc/sysdeps/mach/hurd/flistxattr.c new file mode 100644 index 000000000..a577e4e39 --- /dev/null +++ b/libc/sysdeps/mach/hurd/flistxattr.c @@ -0,0 +1,34 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2005 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> +#include <hurd/fd.h> + +ssize_t +flistxattr (int fd, char *list, size_t size) +{ + error_t err; + + err = HURD_DPORT_USE (fd, _hurd_xattr_list (port, list, &size)); + + return err ? __hurd_dfail (fd, err) : size; +} diff --git a/libc/sysdeps/mach/hurd/flock.c b/libc/sysdeps/mach/hurd/flock.c new file mode 100644 index 000000000..d3a518a3b --- /dev/null +++ b/libc/sysdeps/mach/hurd/flock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1992, 1994, 1995, 1997 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/file.h> +#include <hurd/fd.h> +#include <hurd/fs.h> + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +int +__flock (fd, operation) + int fd; + int operation; +{ + error_t err; + + if (err = HURD_DPORT_USE (fd, __file_lock (port, operation))) + return __hurd_dfail (fd, err); + + return 0; +} + +weak_alias (__flock, flock) diff --git a/libc/sysdeps/mach/hurd/fork.c b/libc/sysdeps/mach/hurd/fork.c new file mode 100644 index 000000000..fa7da6020 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fork.c @@ -0,0 +1,706 @@ +/* Copyright (C) 1994,1995,1996,1997,1999,2001,2002,2004,2005 + 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 <unistd.h> +#include <hurd.h> +#include <hurd/signal.h> +#include <setjmp.h> +#include <thread_state.h> +#include <sysdep.h> /* For stack growth direction. */ +#include "set-hooks.h" +#include <assert.h> +#include "hurdmalloc.h" /* XXX */ +#include <tls.h> + +#undef __fork + + +/* Things that want to be locked while forking. */ +symbol_set_declare (_hurd_fork_locks) + + +/* Things that want to be called before we fork, to prepare the parent for + task_create, when the new child task will inherit our address space. */ +DEFINE_HOOK (_hurd_fork_prepare_hook, (void)); + +/* Things that want to be called when we are forking, with the above all + locked. They are passed the task port of the child. The child process + is all set up except for doing proc_child, and has no threads yet. */ +DEFINE_HOOK (_hurd_fork_setup_hook, (void)); + +/* Things to be run in the child fork. */ +DEFINE_HOOK (_hurd_fork_child_hook, (void)); + +/* Things to be run in the parent fork. */ +DEFINE_HOOK (_hurd_fork_parent_hook, (void)); + + +/* Clone the calling process, creating an exact copy. + Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ +pid_t +__fork (void) +{ + jmp_buf env; + pid_t pid; + size_t i; + error_t err; + struct hurd_sigstate *volatile ss; + + ss = _hurd_self_sigstate (); + __spin_lock (&ss->critical_section_lock); + +#undef LOSE +#define LOSE do { assert_perror (err); goto lose; } while (0) /* XXX */ + + if (! setjmp (env)) + { + process_t newproc; + task_t newtask; + thread_t thread, sigthread; + mach_port_urefs_t thread_refs, sigthread_refs; + struct machine_thread_state state; + mach_msg_type_number_t statecount; + mach_port_t *portnames = NULL; + mach_msg_type_number_t nportnames = 0; + mach_port_type_t *porttypes = NULL; + mach_msg_type_number_t nporttypes = 0; + thread_t *threads = NULL; + mach_msg_type_number_t nthreads = 0; + int ports_locked = 0, stopped = 0; + + void resume_threads (void) + { + if (! stopped) + return; + + assert (threads); + + for (i = 0; i < nthreads; ++i) + if (threads[i] != ss->thread) + __thread_resume (threads[i]); + stopped = 0; + } + + /* Run things that prepare for forking before we create the task. */ + RUN_HOOK (_hurd_fork_prepare_hook, ()); + + /* Lock things that want to be locked before we fork. */ + { + void *const *p; + for (p = symbol_set_first_element (_hurd_fork_locks); + ! symbol_set_end_p (_hurd_fork_locks, p); + ++p) + __mutex_lock (*p); + } + __mutex_lock (&_hurd_siglock); + + newtask = MACH_PORT_NULL; + thread = sigthread = MACH_PORT_NULL; + newproc = MACH_PORT_NULL; + + /* Lock all the port cells for the standard ports while we copy the + address space. We want to insert all the send rights into the + child with the same names. */ + for (i = 0; i < _hurd_nports; ++i) + __spin_lock (&_hurd_ports[i].lock); + ports_locked = 1; + + + /* Stop all other threads while copying the address space, + so nothing changes. */ + err = __proc_dostop (_hurd_ports[INIT_PORT_PROC].port, ss->thread); + if (!err) + { + stopped = 1; + +#define XXX_KERNEL_PAGE_FAULT_BUG /* XXX work around page fault bug in mk */ + +#ifdef XXX_KERNEL_PAGE_FAULT_BUG + /* Gag me with a pitchfork. + The bug scenario is this: + + - The page containing __mach_task_self_ is paged out. + - The signal thread was faulting on that page when we + suspended it via proc_dostop. It holds some lock, or set + some busy bit, or somesuch. + - Now this thread faults on that same page. + - GRATUIOUS DEADLOCK + + We can break the deadlock by aborting the thread that faulted + first, which if the bug happened was the signal thread because + it is the only other thread and we just suspended it. + */ + __thread_abort (_hurd_msgport_thread); +#endif + /* Create the child task. It will inherit a copy of our memory. */ + err = __task_create (__mach_task_self (), +#ifdef KERN_INVALID_LEDGER + NULL, 0, /* OSF Mach */ +#endif + 1, &newtask); + } + + /* Unlock the global signal state lock, so we do not + block the signal thread any longer than necessary. */ + __mutex_unlock (&_hurd_siglock); + + if (err) + LOSE; + + /* Fetch the names of all ports used in this task. */ + if (err = __mach_port_names (__mach_task_self (), + &portnames, &nportnames, + &porttypes, &nporttypes)) + LOSE; + if (nportnames != nporttypes) + { + err = EGRATUITOUS; + LOSE; + } + + /* Get send rights for all the threads in this task. + We want to avoid giving these rights to the child. */ + if (err = __task_threads (__mach_task_self (), &threads, &nthreads)) + LOSE; + + /* Get the child process's proc server port. We will insert it into + the child with the same name as we use for our own proc server + port; and we will need it to set the child's message port. */ + if (err = __proc_task2proc (_hurd_ports[INIT_PORT_PROC].port, + newtask, &newproc)) + LOSE; + + /* Insert all our port rights into the child task. */ + thread_refs = sigthread_refs = 0; + for (i = 0; i < nportnames; ++i) + { + if (porttypes[i] & MACH_PORT_TYPE_RECEIVE) + { + /* This is a receive right. We want to give the child task + its own new receive right under the same name. */ + err = __mach_port_allocate_name (newtask, + MACH_PORT_RIGHT_RECEIVE, + portnames[i]); + if (err == KERN_NAME_EXISTS) + { + /* It already has a right under this name (?!). Well, + there is this bizarre old Mach IPC feature (in #ifdef + MACH_IPC_COMPAT in the ukernel) which results in new + tasks getting a new receive right for task special + port number 2. What else might be going on I'm not + sure. So let's check. */ +#if !MACH_IPC_COMPAT +#define TASK_NOTIFY_PORT 2 +#endif + assert (({ mach_port_t thisport, notify_port; + mach_msg_type_name_t poly; + (__task_get_special_port (newtask, + TASK_NOTIFY_PORT, + ¬ify_port) == 0 && + __mach_port_extract_right + (newtask, + portnames[i], + MACH_MSG_TYPE_MAKE_SEND, + &thisport, &poly) == 0 && + (thisport == notify_port) && + __mach_port_deallocate (__mach_task_self (), + thisport) == 0 && + __mach_port_deallocate (__mach_task_self (), + notify_port) == 0); + })); + } + else if (err) + LOSE; + if (porttypes[i] & MACH_PORT_TYPE_SEND) + { + /* Give the child as many send rights for its receive + right as we have for ours. */ + mach_port_urefs_t refs; + mach_port_t port; + mach_msg_type_name_t poly; + if (err = __mach_port_get_refs (__mach_task_self (), + portnames[i], + MACH_PORT_RIGHT_SEND, + &refs)) + LOSE; + if (err = __mach_port_extract_right (newtask, + portnames[i], + MACH_MSG_TYPE_MAKE_SEND, + &port, &poly)) + LOSE; + if (portnames[i] == _hurd_msgport) + { + /* We just created a receive right for the child's + message port and are about to insert send rights + for it. Now, while we happen to have a send right + for it, give it to the proc server. */ + mach_port_t old; + if (err = __proc_setmsgport (newproc, port, &old)) + LOSE; + if (old != MACH_PORT_NULL) + /* XXX what to do here? */ + __mach_port_deallocate (__mach_task_self (), old); + /* The new task will receive its own exceptions + on its message port. */ + if (err = +#ifdef TASK_EXCEPTION_PORT + __task_set_special_port (newtask, + TASK_EXCEPTION_PORT, + port) +#elif defined (EXC_MASK_ALL) + __task_set_exception_ports + (newtask, EXC_MASK_ALL & ~(EXC_MASK_SYSCALL + | EXC_MASK_MACH_SYSCALL + | EXC_MASK_RPC_ALERT), + port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) +#else +# error task_set_exception_port? +#endif + ) + LOSE; + } + if (err = __mach_port_insert_right (newtask, + portnames[i], + port, + MACH_MSG_TYPE_MOVE_SEND)) + LOSE; + if (refs > 1 && + (err = __mach_port_mod_refs (newtask, + portnames[i], + MACH_PORT_RIGHT_SEND, + refs - 1))) + LOSE; + } + if (porttypes[i] & MACH_PORT_TYPE_SEND_ONCE) + { + /* Give the child a send-once right for its receive right, + since we have one for ours. */ + mach_port_t port; + mach_msg_type_name_t poly; + if (err = __mach_port_extract_right + (newtask, + portnames[i], + MACH_MSG_TYPE_MAKE_SEND_ONCE, + &port, &poly)) + LOSE; + if (err = __mach_port_insert_right + (newtask, + portnames[i], port, + MACH_MSG_TYPE_MOVE_SEND_ONCE)) + LOSE; + } + } + else if (porttypes[i] & + (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_DEAD_NAME)) + { + /* This is a send right or a dead name. + Give the child as many references for it as we have. */ + mach_port_urefs_t refs, *record_refs = NULL; + mach_port_t insert; + mach_msg_type_name_t insert_type = MACH_MSG_TYPE_COPY_SEND; + if (portnames[i] == newtask || portnames[i] == newproc) + /* Skip the name we use for the child's task or proc ports. */ + continue; + if (portnames[i] == __mach_task_self ()) + /* For the name we use for our own task port, + insert the child's task port instead. */ + insert = newtask; + else if (portnames[i] == _hurd_ports[INIT_PORT_PROC].port) + { + /* Use the proc server port for the new task. */ + insert = newproc; + insert_type = MACH_MSG_TYPE_COPY_SEND; + } + else if (portnames[i] == ss->thread) + { + /* For the name we use for our own thread port, we will + insert the thread port for the child main user thread + after we create it. */ + insert = MACH_PORT_NULL; + record_refs = &thread_refs; + /* Allocate a dead name right for this name as a + placeholder, so the kernel will not chose this name + for any other new port (it might use it for one of the + rights created when a thread is created). */ + if (err = __mach_port_allocate_name + (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i])) + LOSE; + } + else if (portnames[i] == _hurd_msgport_thread) + /* For the name we use for our signal thread's thread port, + we will insert the thread port for the child's signal + thread after we create it. */ + { + insert = MACH_PORT_NULL; + record_refs = &sigthread_refs; + /* Allocate a dead name right as a placeholder. */ + if (err = __mach_port_allocate_name + (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i])) + LOSE; + } + else + { + /* Skip the name we use for any of our own thread ports. */ + mach_msg_type_number_t j; + for (j = 0; j < nthreads; ++j) + if (portnames[i] == threads[j]) + break; + if (j < nthreads) + continue; + + /* Copy our own send right. */ + insert = portnames[i]; + } + /* Find out how many user references we have for + the send right with this name. */ + if (err = __mach_port_get_refs (__mach_task_self (), + portnames[i], + MACH_PORT_RIGHT_SEND, + record_refs ?: &refs)) + LOSE; + if (insert == MACH_PORT_NULL) + continue; + if (insert == portnames[i] && + (porttypes[i] & MACH_PORT_TYPE_DEAD_NAME)) + /* This is a dead name; allocate another dead name + with the same name in the child. */ + allocate_dead_name: + err = __mach_port_allocate_name (newtask, + MACH_PORT_RIGHT_DEAD_NAME, + portnames[i]); + else + /* Insert the chosen send right into the child. */ + err = __mach_port_insert_right (newtask, + portnames[i], + insert, insert_type); + switch (err) + { + case KERN_NAME_EXISTS: + { + /* It already has a send right under this name (?!). + Well, it starts out with a send right for its task + port, and inherits the bootstrap and exception ports + from us. */ + mach_port_t childport; + mach_msg_type_name_t poly; + assert (__mach_port_extract_right (newtask, portnames[i], + MACH_MSG_TYPE_COPY_SEND, + &childport, + &poly) == 0 && + childport == insert && + __mach_port_deallocate (__mach_task_self (), + childport) == 0); + break; + } + + case KERN_INVALID_CAPABILITY: + /* The port just died. It was a send right, + and now it's a dead name. */ + goto allocate_dead_name; + + default: + LOSE; + break; + + case KERN_SUCCESS: + /* Give the child as many user references as we have. */ + if (refs > 1 && + (err = __mach_port_mod_refs (newtask, + portnames[i], + MACH_PORT_RIGHT_SEND, + refs - 1))) + LOSE; + } + } + } + + /* Unlock the standard port cells. The child must unlock its own + copies too. */ + for (i = 0; i < _hurd_nports; ++i) + __spin_unlock (&_hurd_ports[i].lock); + ports_locked = 0; + + /* All state has now been copied from the parent. It is safe to + resume other parent threads. */ + resume_threads (); + + /* Create the child main user thread and signal thread. */ + if ((err = __thread_create (newtask, &thread)) || + (err = __thread_create (newtask, &sigthread))) + LOSE; + + /* Insert send rights for those threads. We previously allocated + dead name rights with the names we want to give the thread ports + in the child as placeholders. Now deallocate them so we can use + the names. */ + if ((err = __mach_port_deallocate (newtask, ss->thread)) || + (err = __mach_port_insert_right (newtask, ss->thread, + thread, MACH_MSG_TYPE_COPY_SEND))) + LOSE; + /* We have one extra user reference created at the beginning of this + 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. */ + if (thread_refs > 1 && + (err = __mach_port_mod_refs (newtask, ss->thread, + MACH_PORT_RIGHT_SEND, + thread_refs))) + LOSE; + if ((_hurd_msgport_thread != MACH_PORT_NULL) /* Let user have none. */ + && ((err = __mach_port_deallocate (newtask, _hurd_msgport_thread)) || + (err = __mach_port_insert_right (newtask, _hurd_msgport_thread, + sigthread, + MACH_MSG_TYPE_COPY_SEND)))) + LOSE; + if (sigthread_refs > 1 && + (err = __mach_port_mod_refs (newtask, _hurd_msgport_thread, + MACH_PORT_RIGHT_SEND, + sigthread_refs - 1))) + LOSE; + + /* This seems like a convenient juncture to copy the proc server's + idea of what addresses our argv and envp are found at from the + parent into the child. Since we happen to know that the child + shares our memory image, it is we who should do this copying. */ + { + vm_address_t argv, envp; + err = (__USEPORT (PROC, __proc_get_arg_locations (port, &argv, &envp)) + ?: __proc_set_arg_locations (newproc, argv, envp)); + if (err) + LOSE; + } + + /* Set the child signal thread up to run the msgport server function + using the same signal thread stack copied from our address space. + We fetch the state before longjmp'ing it so that miscellaneous + registers not affected by longjmp (such as i386 segment registers) + are in their normal default state. */ + statecount = MACHINE_THREAD_STATE_COUNT; + if (err = __thread_get_state (_hurd_msgport_thread, + MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state, &statecount)) + LOSE; +#if STACK_GROWTH_UP +#define THREADVAR_SPACE (__hurd_threadvar_max \ + * sizeof *__hurd_sightread_variables) + if (__hurd_sigthread_stack_base == 0) + { + state.SP &= __hurd_threadvar_stack_mask; + state.SP += __hurd_threadvar_stack_offset + THREADVAR_SPACE; + } + else + state.SP = __hurd_sigthread_stack_base; +#else + if (__hurd_sigthread_stack_end == 0) + { + /* The signal thread has a normal stack assigned by cthreads. + The threadvar_stack variables conveniently tell us how + to get to the highest address in the stack, just below + the per-thread variables. */ + state.SP &= __hurd_threadvar_stack_mask; + state.SP += __hurd_threadvar_stack_offset; + } + else + state.SP = __hurd_sigthread_stack_end; +#endif + MACHINE_THREAD_STATE_SET_PC (&state, + (unsigned long int) _hurd_msgport_receive); + if (err = __thread_set_state (sigthread, MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state, statecount)) + LOSE; + /* We do not thread_resume SIGTHREAD here because the child + fork needs to do more setup before it can take signals. */ + + /* Set the child user thread up to return 1 from the setjmp above. */ + _hurd_longjmp_thread_state (&state, env, 1); + +#if USE_TLS + /* Do special thread setup for TLS if needed. */ + if (err = _hurd_tls_fork (thread, &state)) + LOSE; +#endif + + if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state, statecount)) + LOSE; + + /* Get the PID of the child from the proc server. We must do this + before calling proc_child below, because at that point any + authorized POSIX.1 process may kill the child task with SIGKILL. */ + if (err = __USEPORT (PROC, __proc_task2pid (port, newtask, &pid))) + LOSE; + + /* Register the child with the proc server. It is important that + this be that last thing we do before starting the child thread + running. Once proc_child has been done for the task, it appears + as a POSIX.1 process. Any errors we get must be detected before + this point, and the child must have a message port so it responds + to POSIX.1 signals. */ + if (err = __USEPORT (PROC, __proc_child (port, newtask))) + LOSE; + + /* This must be the absolutely last thing we do; we can't assume that + the child will remain alive for even a moment once we do this. We + ignore errors because we have committed to the fork and are not + allowed to return them after the process becomes visible to + POSIX.1 (which happened right above when we called proc_child). */ + (void) __thread_resume (thread); + + lose: + if (ports_locked) + for (i = 0; i < _hurd_nports; ++i) + __spin_unlock (&_hurd_ports[i].lock); + + resume_threads (); + + if (newtask != MACH_PORT_NULL) + { + if (err) + __task_terminate (newtask); + __mach_port_deallocate (__mach_task_self (), newtask); + } + if (thread != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), thread); + if (sigthread != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), sigthread); + if (newproc != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), newproc); + + if (portnames) + __vm_deallocate (__mach_task_self (), + (vm_address_t) portnames, + nportnames * sizeof (*portnames)); + if (porttypes) + __vm_deallocate (__mach_task_self (), + (vm_address_t) porttypes, + nporttypes * sizeof (*porttypes)); + if (threads) + { + for (i = 0; i < nthreads; ++i) + __mach_port_deallocate (__mach_task_self (), threads[i]); + __vm_deallocate (__mach_task_self (), + (vm_address_t) threads, + nthreads * sizeof (*threads)); + } + + /* Run things that want to run in the parent to restore it to + normality. Usually prepare hooks and parent hooks are + symmetrical: the prepare hook arrests state in some way for the + fork, and the parent hook restores the state for the parent to + continue executing normally. */ + RUN_HOOK (_hurd_fork_parent_hook, ()); + } + else + { + struct hurd_sigstate *oldstates; + + /* We are the child task. Unlock the standard port cells, which were + locked in the parent when we copied its memory. The parent has + inserted send rights with the names that were in the cells then. */ + 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 + because some of the further setup and unlocking might be + required for free to work. Before we finish cleaning up, + we will reclaim the signal thread's sigstate structure (if + it had one). */ + oldstates = _hurd_sigstates; + if (oldstates == ss) + oldstates = ss->next; + else + { + while (_hurd_sigstates->next != ss) + _hurd_sigstates = _hurd_sigstates->next; + _hurd_sigstates->next = ss->next; + } + ss->next = NULL; + _hurd_sigstates = ss; + __mutex_unlock (&_hurd_siglock); + + /* Fetch our new process IDs from the proc server. No need to + refetch our pgrp; it is always inherited from the parent (so + _hurd_pgrp is already correct), and the proc server will send us a + proc_newids notification when it changes. */ + err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid, + &_hurd_orphaned)); + + /* Forking clears the trace flag. */ + __sigemptyset (&_hurdsig_traced); + + /* Run things that want to run in the child task to set up. */ + RUN_HOOK (_hurd_fork_child_hook, ()); + + /* Set up proc server-assisted fault recovery for the signal thread. */ + _hurdsig_fault_init (); + + /* Start the signal thread listening on the message port. */ + if (!err) + err = __thread_resume (_hurd_msgport_thread); + + /* Reclaim the signal thread's sigstate structure and free the + other old sigstate structures. */ + while (oldstates != NULL) + { + struct hurd_sigstate *next = oldstates->next; + + if (oldstates->thread == _hurd_msgport_thread) + { + /* If we have a second signal state structure then we + must have been through here before--not good. */ + assert (_hurd_sigstates->next == 0); + _hurd_sigstates->next = oldstates; + oldstates->next = 0; + } + else + free (oldstates); + + oldstates = next; + } + + /* XXX what to do if we have any errors here? */ + + pid = 0; + } + + /* Unlock things we locked before creating the child task. + They are locked in both the parent and child tasks. */ + { + void *const *p; + for (p = symbol_set_first_element (_hurd_fork_locks); + ! symbol_set_end_p (_hurd_fork_locks, p); + ++p) + __mutex_unlock (*p); + } + + _hurd_critical_section_unlock (ss); + + return err ? __hurd_fail (err) : pid; +} +libc_hidden_def (__fork) + +weak_alias (__fork, fork) diff --git a/libc/sysdeps/mach/hurd/fpathconf.c b/libc/sysdeps/mach/hurd/fpathconf.c new file mode 100644 index 000000000..ffd50d6eb --- /dev/null +++ b/libc/sysdeps/mach/hurd/fpathconf.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 92, 94, 95, 96, 97 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Get file-specific information about descriptor FD. */ +long int +__fpathconf (int fd, int name) +{ + error_t err; + int value; + + if (err = HURD_DPORT_USE (fd, __io_pathconf (port, name, &value))) + return __hurd_dfail (fd, err), -1L; + + return value; +} + +weak_alias (__fpathconf, fpathconf) diff --git a/libc/sysdeps/mach/hurd/fremovexattr.c b/libc/sysdeps/mach/hurd/fremovexattr.c new file mode 100644 index 000000000..5d3aca609 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fremovexattr.c @@ -0,0 +1,34 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2005 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> +#include <hurd/fd.h> + +int +fremovexattr (int fd, const char *name) +{ + error_t err; + + err = HURD_DPORT_USE (fd, _hurd_xattr_remove (port, name)); + + return err ? __hurd_dfail (fd, err) : 0; +} diff --git a/libc/sysdeps/mach/hurd/fsetxattr.c b/libc/sysdeps/mach/hurd/fsetxattr.c new file mode 100644 index 000000000..db8b676a0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fsetxattr.c @@ -0,0 +1,34 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2006 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> +#include <hurd/fd.h> + +ssize_t +fsetxattr (int fd, const char *name, const void *value, size_t size, int flags) +{ + error_t err; + + err = HURD_DPORT_USE (fd, _hurd_xattr_set (port, name, value, size, flags)); + + return err ? __hurd_dfail (fd, err) : 0; +} diff --git a/libc/sysdeps/mach/hurd/fstatfs.c b/libc/sysdeps/mach/hurd/fstatfs.c new file mode 100644 index 000000000..5949b497e --- /dev/null +++ b/libc/sysdeps/mach/hurd/fstatfs.c @@ -0,0 +1,32 @@ +/* fstatfs -- Return information about the filesystem on which FD resides. + Copyright (C) 1996,97,2002 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 <sys/statfs.h> + +#include "statfsconv.c" + +/* Return information about the filesystem on which FD resides. */ +int +__fstatfs (int fd, struct statfs *buf) +{ + struct statfs64 buf64; + return __fstatfs64 (fd, &buf64) ?: statfs64_conv (buf, &buf64); +} + +weak_alias (__fstatfs, fstatfs) diff --git a/libc/sysdeps/mach/hurd/fstatfs64.c b/libc/sysdeps/mach/hurd/fstatfs64.c new file mode 100644 index 000000000..d87aa378a --- /dev/null +++ b/libc/sysdeps/mach/hurd/fstatfs64.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2001,02 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 <sys/statfs.h> +#include <hurd.h> +#include <hurd/fd.h> + +#include "statfsconv.c" + +/* Return information about the filesystem on which FD resides. */ +int +__fstatfs64 (int fd, struct statfs64 *buf) +{ + error_t err; + + if (err = HURD_DPORT_USE (fd, __file_statfs (port, buf))) + return __hurd_dfail (fd, err); + + return 0; +} +weak_alias (__fstatfs64, fstatfs64) diff --git a/libc/sysdeps/mach/hurd/fstatvfs.c b/libc/sysdeps/mach/hurd/fstatvfs.c new file mode 100644 index 000000000..a11abe89f --- /dev/null +++ b/libc/sysdeps/mach/hurd/fstatvfs.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1998, 2001, 2002 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 <sys/statfs.h> +#include <sys/statvfs.h> + +int +fstatvfs (int fd, struct statvfs *buf) +{ + /* `struct statvfs' is in fact identical to `struct statfs' so we + can simply call fstatfs. */ + return __fstatfs (fd, (struct statfs *)buf); +} +libc_hidden_def (fstatvfs) diff --git a/libc/sysdeps/mach/hurd/fstatvfs64.c b/libc/sysdeps/mach/hurd/fstatvfs64.c new file mode 100644 index 000000000..ac610daaf --- /dev/null +++ b/libc/sysdeps/mach/hurd/fstatvfs64.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 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 <sys/statfs.h> +#include <sys/statvfs.h> + +int +fstatvfs64 (int fd, struct statvfs64 *buf) +{ + /* `struct statvfs64' is in fact identical to `struct statfs64' so + we can simply call fstatfs64. */ + return __fstatfs64 (fd, (struct statfs64 *)buf); +} diff --git a/libc/sysdeps/mach/hurd/fsync.c b/libc/sysdeps/mach/hurd/fsync.c new file mode 100644 index 000000000..325b01558 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fsync.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 92, 93, 94, 96, 97 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 <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Make all changes done to FD actually appear on disk. */ +int +fsync (fd) + int fd; +{ + error_t err = HURD_DPORT_USE (fd, __file_sync (port, 1, 0)); + if (err) + return __hurd_dfail (fd, err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/ftruncate.c b/libc/sysdeps/mach/hurd/ftruncate.c new file mode 100644 index 000000000..404459e6d --- /dev/null +++ b/libc/sysdeps/mach/hurd/ftruncate.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 97, 98 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/types.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Truncate the file FD refers to to LENGTH bytes. */ +int +__ftruncate (fd, length) + int fd; + __off_t length; +{ + error_t err; + if (err = HURD_DPORT_USE (fd, __file_set_size (port, length))) + return __hurd_dfail (fd, err); + return 0; +} + +weak_alias (__ftruncate, ftruncate) diff --git a/libc/sysdeps/mach/hurd/futimes.c b/libc/sysdeps/mach/hurd/futimes.c new file mode 100644 index 000000000..ca687b8bd --- /dev/null +++ b/libc/sysdeps/mach/hurd/futimes.c @@ -0,0 +1,47 @@ +/* futimes -- change access and modification times of open file. Hurd version. + Copyright (C) 2002 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 <sys/time.h> +#include <errno.h> +#include <stddef.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Change the access time of FD to TVP[0] and + the modification time of FD to TVP[1]. */ +int +__futimes (int fd, const struct timeval tvp[2]) +{ + struct timeval timevals[2]; + error_t err; + + if (tvp == NULL) + { + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + timevals[1].tv_usec = timevals[0].tv_usec = (time_t)-1; + tvp = timevals; + } + + err = HURD_DPORT_USE (fd, __file_utimes (port, + *(time_value_t *) &tvp[0], + *(time_value_t *) &tvp[1])); + return err ? __hurd_dfail (fd, err) : 0; +} +weak_alias (__futimes, futimes) diff --git a/libc/sysdeps/mach/hurd/fxstat.c b/libc/sysdeps/mach/hurd/fxstat.c new file mode 100644 index 000000000..8a2520c5d --- /dev/null +++ b/libc/sysdeps/mach/hurd/fxstat.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1992,93,94,95,96,97,2002 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 <stddef.h> +#include <sys/stat.h> + +#include "xstatconv.c" + +/* Get information about the file descriptor FD in BUF. */ +int +__fxstat (int vers, int fd, struct stat *buf) +{ + struct stat64 buf64; + return __fxstat64 (vers, fd, &buf64) ?: xstat64_conv (buf, &buf64); +} +hidden_def (__fxstat) +weak_alias (__fxstat, _fxstat) diff --git a/libc/sysdeps/mach/hurd/fxstat64.c b/libc/sysdeps/mach/hurd/fxstat64.c new file mode 100644 index 000000000..c1390d1bb --- /dev/null +++ b/libc/sysdeps/mach/hurd/fxstat64.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2000,02 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 RTLD_STAT64 /* dl-fxstat64.c, but we don't want it. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Get information about the file descriptor FD in BUF. */ +int +__fxstat64 (int vers, int fd, struct stat64 *buf) +{ + error_t err; + + if (vers != _STAT_VER) + return __hurd_fail (EINVAL); + + if (err = HURD_DPORT_USE (fd, __io_stat (port, buf))) + return __hurd_dfail (fd, err); + + return 0; +} +hidden_def (__fxstat64) + +#endif diff --git a/libc/sysdeps/mach/hurd/fxstatat.c b/libc/sysdeps/mach/hurd/fxstatat.c new file mode 100644 index 000000000..dd9d2796e --- /dev/null +++ b/libc/sysdeps/mach/hurd/fxstatat.c @@ -0,0 +1,33 @@ +/* Get information about file named relative to open directory. Hurd version. + Copyright (C) 2006 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 <stddef.h> +#include <sys/stat.h> + +#include "xstatconv.c" + +int +__fxstatat (int vers, int fd, const char *filename, struct stat *buf, int flag) +{ + struct stat64 buf64; + return (__fxstatat64 (vers, fd, filename, &buf64, flag) + ?: xstat64_conv (buf, &buf64)); +} +libc_hidden_def (__fxstatat) diff --git a/libc/sysdeps/mach/hurd/fxstatat64.c b/libc/sysdeps/mach/hurd/fxstatat64.c new file mode 100644 index 000000000..6862e80d5 --- /dev/null +++ b/libc/sysdeps/mach/hurd/fxstatat64.c @@ -0,0 +1,46 @@ +/* Get information about file named relative to open directory. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Get information about the file descriptor FD in BUF. */ +int +__fxstatat64 (int vers, int fd, const char *filename, struct stat64 *buf, + int flag) +{ + error_t err; + io_t port; + + if (vers != _STAT_VER) + return __hurd_fail (EINVAL); + + port = __file_name_lookup_at (fd, flag, filename, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + + err = __io_stat (port, buf); + __mach_port_deallocate (__mach_task_self (), port); + + return __hurd_fail (err); +} diff --git a/libc/sysdeps/mach/hurd/getclktck.c b/libc/sysdeps/mach/hurd/getclktck.c new file mode 100644 index 000000000..9cb46bbca --- /dev/null +++ b/libc/sysdeps/mach/hurd/getclktck.c @@ -0,0 +1,37 @@ +/* Return run-time value of CLK_TCK for Hurd. + Copyright (C) 1999, 2000, 2001 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 <time.h> + +/* Return frequency of `times'. + Since Mach reports CPU times in microseconds, we always use 1 million. */ +int +__getclktck () +{ + return 1000000; +} + +/* Before glibc 2.2, the Hurd actually did this differently, so we + need to keep a compatibility symbol. */ + +#include <shlib-compat.h> + +#if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_2) +compat_symbol (libc, __getclktck, __libc_clk_tck, GLIBC_2_1_1); +#endif diff --git a/libc/sysdeps/mach/hurd/getcwd.c b/libc/sysdeps/mach/hurd/getcwd.c new file mode 100644 index 000000000..7e07e6b40 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getcwd.c @@ -0,0 +1,324 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,2002,04 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/types.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/port.h> +#include <dirent.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> + + +/* Get the canonical absolute name of the given directory port, and put it + in SIZE bytes of BUF. Returns NULL if the directory couldn't be + determined or SIZE was too small. If successful, returns BUF. In GNU, + if BUF is NULL, an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE <= 0, in which case it is as big as necessary. + If our root directory cannot be reached, the result will not begin with + a slash to indicate that it is relative to some unknown root directory. */ + +char * +_hurd_canonicalize_directory_name_internal (file_t thisdir, + char *buf, + size_t size) +{ + error_t err; + mach_port_t rootid, thisid, rootdevid, thisdevid; + ino64_t rootino, thisino; + char *file_name; + register char *file_namep; + file_t parent; + char *dirbuf = NULL; + unsigned int dirbufsize = 0; + const size_t orig_size = size; + + inline void cleanup (void) + { + if (parent != thisdir) + __mach_port_deallocate (__mach_task_self (), parent); + + __mach_port_deallocate (__mach_task_self (), thisid); + __mach_port_deallocate (__mach_task_self (), thisdevid); + __mach_port_deallocate (__mach_task_self (), rootid); + __mach_port_deallocate (__mach_task_self (), rootdevid); + + if (dirbuf != NULL) + __vm_deallocate (__mach_task_self (), + (vm_address_t) dirbuf, dirbufsize); + } + + + if (size <= 0) + { + if (buf != NULL) + { + errno = EINVAL; + return NULL; + } + + size = FILENAME_MAX * 4 + 1; /* Good starting guess. */ + } + + if (buf != NULL) + file_name = buf; + else + { + file_name = malloc (size); + if (file_name == NULL) + return NULL; + } + + file_namep = file_name + size; + *--file_namep = '\0'; + + /* Get a port to our root directory and get its identity. */ + + if (err = __USEPORT (CRDIR, __io_identity (port, + &rootid, &rootdevid, &rootino))) + return __hurd_fail (err), NULL; + __mach_port_deallocate (__mach_task_self (), rootdevid); + + /* Stat the port to the directory of interest. */ + + if (err = __io_identity (thisdir, &thisid, &thisdevid, &thisino)) + { + __mach_port_deallocate (__mach_task_self (), rootid); + return __hurd_fail (err), NULL; + } + + parent = thisdir; + while (thisid != rootid) + { + /* PARENT is a port to the directory we are currently on; + THISID, THISDEV, and THISINO are its identity. + Look in its parent (..) for a file with the same file number. */ + + struct dirent64 *d; + mach_port_t dotid, dotdevid; + ino64_t dotino; + int mount_point; + file_t newp; + char *dirdata; + size_t dirdatasize; + int direntry, nentries; + + + /* Look at the parent directory. */ + newp = __file_name_lookup_under (parent, "..", O_READ, 0); + if (newp == MACH_PORT_NULL) + goto lose; + if (parent != thisdir) + __mach_port_deallocate (__mach_task_self (), parent); + parent = newp; + + /* Get this directory's identity and figure out if it's a mount + point. */ + if (err = __io_identity (parent, &dotid, &dotdevid, &dotino)) + goto errlose; + mount_point = dotdevid != thisdevid; + + if (thisid == dotid) + { + /* `..' == `.' but it is not our root directory. */ + __mach_port_deallocate (__mach_task_self (), dotid); + __mach_port_deallocate (__mach_task_self (), dotdevid); + break; + } + + /* Search for the last directory. */ + direntry = 0; + dirdata = dirbuf; + dirdatasize = dirbufsize; + while (!(err = __dir_readdir (parent, &dirdata, &dirdatasize, + direntry, -1, 0, &nentries)) && + nentries != 0) + { + /* We have a block of directory entries. */ + + unsigned int offset; + + direntry += nentries; + + if (dirdata != dirbuf) + { + /* The data was passed out of line, so our old buffer is no + longer useful. Deallocate the old buffer and reset our + information for the new buffer. */ + __vm_deallocate (__mach_task_self (), + (vm_address_t) dirbuf, dirbufsize); + dirbuf = dirdata; + dirbufsize = round_page (dirdatasize); + } + + /* Iterate over the returned directory entries, looking for one + whose file number is THISINO. */ + + offset = 0; + while (offset < dirdatasize) + { + d = (struct dirent64 *) &dirdata[offset]; + offset += d->d_reclen; + + /* Ignore `.' and `..'. */ + if (d->d_name[0] == '.' && + (d->d_namlen == 1 || + (d->d_namlen == 2 && d->d_name[1] == '.'))) + continue; + + if (mount_point || d->d_ino == thisino) + { + file_t try = __file_name_lookup_under (parent, d->d_name, + O_NOLINK, 0); + file_t id, devid; + ino64_t fileno; + if (try == MACH_PORT_NULL) + goto lose; + err = __io_identity (try, &id, &devid, &fileno); + __mach_port_deallocate (__mach_task_self (), try); + if (err) + goto inner_errlose; + __mach_port_deallocate (__mach_task_self (), id); + __mach_port_deallocate (__mach_task_self (), devid); + if (id == thisid) + goto found; + } + } + } + + if (err) + { + inner_errlose: /* Goto ERRLOSE: after cleaning up. */ + __mach_port_deallocate (__mach_task_self (), dotid); + __mach_port_deallocate (__mach_task_self (), dotdevid); + goto errlose; + } + else if (nentries == 0) + { + /* We got to the end of the directory without finding anything! + We are in a directory that has been unlinked, or something is + broken. */ + err = ENOENT; + goto inner_errlose; + } + else + found: + { + /* Prepend the directory name just discovered. */ + + if (file_namep - file_name < d->d_namlen + 1) + { + if (orig_size > 0) + { + errno = ERANGE; + return NULL; + } + else + { + size *= 2; + buf = realloc (file_name, size); + if (buf == NULL) + { + free (file_name); + return NULL; + } + file_namep = &buf[file_namep - file_name + size / 2]; + file_name = buf; + /* Move current contents up to the end of the buffer. + This is guaranteed to be non-overlapping. */ + memcpy (file_namep, file_namep - size / 2, + file_name + size - file_namep); + } + } + file_namep -= d->d_namlen; + (void) memcpy (file_namep, d->d_name, d->d_namlen); + *--file_namep = '/'; + } + + /* The next iteration will find the name of the directory we + just searched through. */ + __mach_port_deallocate (__mach_task_self (), thisid); + __mach_port_deallocate (__mach_task_self (), thisdevid); + thisid = dotid; + thisdevid = dotdevid; + thisino = dotino; + } + + if (file_namep == &file_name[size - 1]) + /* We found nothing and got all the way to the root. + 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; + + errlose: + /* Set errno. */ + (void) __hurd_fail (err); + lose: + cleanup (); + return NULL; +} + +char * +__canonicalize_directory_name_internal (thisdir, buf, size) + const char *thisdir; + char *buf; + size_t size; +{ + char *result; + file_t port = __file_name_lookup (thisdir, 0, 0); + if (port == MACH_PORT_NULL) + return NULL; + result = _hurd_canonicalize_directory_name_internal (port, buf, size); + __mach_port_deallocate (__mach_task_self (), port); + return result; +} + +/* Get the pathname of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined or + SIZE was too small. If successful, returns BUF. In GNU, if BUF is + NULL, an array is allocated with `malloc'; the array is SIZE bytes long, + unless SIZE <= 0, in which case it is as big as necessary. */ +char * +__getcwd (char *buf, size_t size) +{ + char *cwd = + __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/libc/sysdeps/mach/hurd/getdents.c b/libc/sysdeps/mach/hurd/getdents.c new file mode 100644 index 000000000..d15be3b8f --- /dev/null +++ b/libc/sysdeps/mach/hurd/getdents.c @@ -0,0 +1 @@ +#include <dirent/getdents.c> diff --git a/libc/sysdeps/mach/hurd/getdomain.c b/libc/sysdeps/mach/hurd/getdomain.c new file mode 100644 index 000000000..04f6e7d1d --- /dev/null +++ b/libc/sysdeps/mach/hurd/getdomain.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1998, 2002 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 <unistd.h> +#include "hurdhost.h" + +/* Put the name of the current NIS domain in no more than LEN bytes of NAME. + The result is null-terminated if LEN is large enough for the full + name and the terminator. */ +int +getdomainname (char *name, size_t len) +{ + /* The NIS domain name is just the contents of the file /etc/nisdomain. */ + ssize_t n = _hurd_get_host_config ("/etc/nisdomain", name, len); + return n < 0 ? -1 : 0; +} +libc_hidden_def (getdomainname) diff --git a/libc/sysdeps/mach/hurd/getdtsz.c b/libc/sysdeps/mach/hurd/getdtsz.c new file mode 100644 index 000000000..a740c1ee9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getdtsz.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991,92,93,94,95,97,2000 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 <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/resource.h> + +/* Return the maximum number of file descriptors the current process + could possibly have (until it raises the resource limit). */ +int +__getdtablesize () +{ + rlim_t limit; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_rlimit_lock); + limit = _hurd_rlimits[RLIMIT_NOFILE].rlim_cur; + __mutex_unlock (&_hurd_rlimit_lock); + HURD_CRITICAL_END; + + /* RLIM_INFINITY is not meaningful to our caller. -1 is a good choice + because `sysconf (_SC_OPEN_MAX)' calls us, and -1 from sysconf means + "no determinable limit". */ + return limit == RLIM_INFINITY ? -1 : (int) limit; +} + +weak_alias (__getdtablesize, getdtablesize) diff --git a/libc/sysdeps/mach/hurd/getegid.c b/libc/sysdeps/mach/hurd/getegid.c new file mode 100644 index 000000000..36f1a2274 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getegid.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Get the effective group ID of the calling process. */ +gid_t +__getegid () +{ + error_t err; + gid_t egid; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + + if (err = _hurd_check_ids ()) + { + errno = err; + egid = -1; + } + else if (_hurd_id.gen.ngids >= 1) + egid = _hurd_id.gen.gids[0]; + else if (_hurd_id.aux.ngids >= 1) + /* We have no effective gids. Return the real gid. */ + egid = _hurd_id.aux.gids[0]; + else + { + /* We do not even have a real gid. */ + errno = EGRATUITOUS; + egid = -1; + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + return egid; +} + +weak_alias (__getegid, getegid) diff --git a/libc/sysdeps/mach/hurd/geteuid.c b/libc/sysdeps/mach/hurd/geteuid.c new file mode 100644 index 000000000..a80b9c20d --- /dev/null +++ b/libc/sysdeps/mach/hurd/geteuid.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Get the effective user ID of the calling process. */ +uid_t +__geteuid () +{ + error_t err; + uid_t euid; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + + if (err = _hurd_check_ids ()) + { + errno = err; + euid = -1; + } + else if (_hurd_id.gen.nuids >= 1) + euid = _hurd_id.gen.uids[0]; + else if (_hurd_id.aux.nuids >= 1) + /* We have no effective uids. Return the real uid. */ + euid = _hurd_id.aux.uids[0]; + else + { + /* We do not even have a real uid. */ + errno = EGRATUITOUS; + euid = -1; + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + return euid; +} + +weak_alias (__geteuid, geteuid) diff --git a/libc/sysdeps/mach/hurd/getgid.c b/libc/sysdeps/mach/hurd/getgid.c new file mode 100644 index 000000000..b9e24ae4f --- /dev/null +++ b/libc/sysdeps/mach/hurd/getgid.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Get the real group ID of the calling process. */ +gid_t +__getgid () +{ + error_t err; + gid_t gid; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + + if (err = _hurd_check_ids ()) + { + errno = err; + gid = -1; + } + else if (_hurd_id.aux.ngids >= 1) + gid = _hurd_id.aux.gids[0]; + else + { + /* We do not even have a real gid. */ + errno = EGRATUITOUS; + gid = -1; + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + return gid; +} + +weak_alias (__getgid, getgid) diff --git a/libc/sysdeps/mach/hurd/getgroups.c b/libc/sysdeps/mach/hurd/getgroups.c new file mode 100644 index 000000000..919336e7f --- /dev/null +++ b/libc/sysdeps/mach/hurd/getgroups.c @@ -0,0 +1,69 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> +#include <string.h> + +int +__getgroups (n, gidset) + int n; + gid_t *gidset; +{ + error_t err; + int ngids; + void *crit; + + crit = _hurd_critical_section_lock (); + __mutex_lock (&_hurd_id.lock); + + if (err = _hurd_check_ids ()) + { + __mutex_unlock (&_hurd_id.lock); + _hurd_critical_section_unlock (crit); + return __hurd_fail (err); + } + + ngids = _hurd_id.gen.ngids; + + if (n != 0) + { + /* Copy the gids onto stack storage and then release the idlock. */ + gid_t gids[ngids]; + memcpy (gids, _hurd_id.gen.gids, sizeof (gids)); + __mutex_unlock (&_hurd_id.lock); + _hurd_critical_section_unlock (crit); + + /* Now that the lock is released, we can safely copy the + group set into the user's array, which might fault. */ + if (ngids > n) + ngids = n; + memcpy (gidset, gids, ngids * sizeof (gid_t)); + } + else + { + __mutex_unlock (&_hurd_id.lock); + _hurd_critical_section_unlock (crit); + } + + return ngids; +} + +weak_alias (__getgroups, getgroups) diff --git a/libc/sysdeps/mach/hurd/gethostid.c b/libc/sysdeps/mach/hurd/gethostid.c new file mode 100644 index 000000000..f4f1d4bae --- /dev/null +++ b/libc/sysdeps/mach/hurd/gethostid.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 92, 93, 94, 96, 97 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 <unistd.h> +#include <hurd.h> +#include "hurdhost.h" + +/* Return the current machine's Internet number. */ +long int +gethostid () +{ + /* The hostid is just the contents of the file /etc/hostid, + kept as text of hexadecimal digits. */ + /* XXX this is supposed to come from the hardware serial number */ + char buf[8]; + ssize_t n = _hurd_get_host_config ("/etc/hostid", buf, sizeof buf); + if (n < 0) + return -1; + return strtol (buf, NULL, 16); +} diff --git a/libc/sysdeps/mach/hurd/gethostname.c b/libc/sysdeps/mach/hurd/gethostname.c new file mode 100644 index 000000000..f77895da0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/gethostname.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991-1997, 2000, 2001 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 <unistd.h> +#include "hurdhost.h" + +/* Put the name of the current host in no more than LEN bytes of NAME. + The result is null-terminated if LEN is large enough for the full + name and the terminator. */ +int +__gethostname (name, len) + char *name; + size_t len; +{ + /* The host name is just the contents of the file /etc/hostname. */ + ssize_t n = _hurd_get_host_config ("/etc/hostname", name, len); + return n < 0 ? -1 : 0; +} + +weak_alias (__gethostname, gethostname) diff --git a/libc/sysdeps/mach/hurd/getitimer.c b/libc/sysdeps/mach/hurd/getitimer.c new file mode 100644 index 000000000..77b355736 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getitimer.c @@ -0,0 +1,104 @@ +/* Copyright (C) 1994, 1995, 1997 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 <stddef.h> +#include <errno.h> +#include <sys/time.h> +#include <hurd.h> + +/* XXX Temporary cheezoid implementation; see __setitmr.c. */ + +/* These are defined in __setitmr.c. */ +extern spin_lock_t _hurd_itimer_lock; +extern struct itimerval _hurd_itimerval; +extern struct timeval _hurd_itimer_started; + +static inline void +subtract_timeval (struct timeval *from, const struct timeval *subtract) +{ + from->tv_usec -= subtract->tv_usec; + from->tv_sec -= subtract->tv_sec; + while (from->tv_usec < 0) + { + --from->tv_sec; + from->tv_usec += 1000000; + } +} + +/* Set *VALUE to the current setting of timer WHICH. + Return 0 on success, -1 on errors. */ +int +__getitimer (which, value) + enum __itimer_which which; + struct itimerval *value; +{ + struct itimerval val; + struct timeval elapsed; + + switch (which) + { + default: + return __hurd_fail (EINVAL); + + case ITIMER_VIRTUAL: + case ITIMER_PROF: + return __hurd_fail (ENOSYS); + + case ITIMER_REAL: + break; + } + + /* Get the time now. */ + if (__gettimeofday (&elapsed, NULL) < 0) + return -1; + + /* Extract the current timer setting; and the time it was set, so we can + calculate the time elapsed so far. */ + HURD_CRITICAL_BEGIN; + __spin_lock (&_hurd_itimer_lock); + val = _hurd_itimerval; + subtract_timeval (&elapsed, &_hurd_itimer_started); + __spin_unlock (&_hurd_itimer_lock); + HURD_CRITICAL_END; + + if ((val.it_value.tv_sec | val.it_value.tv_usec) != 0) + { + /* There is a pending alarm set. VAL indicates the interval it was + set for, relative to the time recorded in _hurd_itimer_started. + Now compensate for the time elapsed since to get the user's + conception of the current value of the timer (as if the value + stored decreased every microsecond). */ + if (timercmp (&val.it_value, &elapsed, <)) + { + /* Hmm. The timer should have just gone off, but has not been + reset. This is a possible timing glitch. The alarm will signal + soon, so fabricate a value for how soon. */ + val.it_value.tv_sec = 0; + val.it_value.tv_usec = 10; /* Random. */ + } + else + /* Subtract the time elapsed since the timer was set + from the current timer value the user sees. */ + subtract_timeval (&val.it_value, &elapsed); + } + + *value = val; + return 0; +} + +weak_alias (__getitimer, getitimer) diff --git a/libc/sysdeps/mach/hurd/getlogin.c b/libc/sysdeps/mach/hurd/getlogin.c new file mode 100644 index 000000000..248ddb144 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getlogin.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991, 1992, 1993, 1994, 1997 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 <stddef.h> +#include <errno.h> +#include <unistd.h> +#include <hurd.h> + +/* Return the login name of the user, or NULL if it can't be determined. + The returned pointer, if not NULL, is good only until the next call. */ +char * +getlogin () +{ + static char login[1024]; /* XXX */ + error_t err; + + if (err = __USEPORT (PROC, __proc_getlogin (port, login))) + { + errno = err; + return NULL; + } + + return login; +} diff --git a/libc/sysdeps/mach/hurd/getlogin_r.c b/libc/sysdeps/mach/hurd/getlogin_r.c new file mode 100644 index 000000000..f4d5faed7 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getlogin_r.c @@ -0,0 +1,42 @@ +/* Reentrant function to return the current login name. Hurd version. + Copyright (C) 1996, 2002 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 <unistd.h> +#include <hurd.h> +#include <string.h> + +/* Return at most NAME_LEN characters of the login name of the user in NAME. + If it cannot be determined or some other error occurred, return the error + code. Otherwise return 0. */ +int +getlogin_r (name, name_len) + char *name; + size_t name_len; +{ + static char login[1024]; /* XXX */ + error_t err; + + if (err = __USEPORT (PROC, __proc_getlogin (port, login))) + return errno = err; + + strncpy (name, login, name_len); + return 0; +} +libc_hidden_def (getlogin_r) diff --git a/libc/sysdeps/mach/hurd/getpeername.c b/libc/sysdeps/mach/hurd/getpeername.c new file mode 100644 index 000000000..325b6fd75 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getpeername.c @@ -0,0 +1,70 @@ +/* Copyright (C) 1992,1994,1997,1999,2000,2005 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 <string.h> +#include <sys/socket.h> + +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> + +/* Put the address of the peer connected to socket FD into *ADDR + (which is *LEN bytes long), and its actual length into *LEN. */ +int +__getpeername (int fd, __SOCKADDR_ARG addrarg, socklen_t *len) +{ + error_t err; + mach_msg_type_number_t buflen = *len; + int type; + struct sockaddr *addr = addrarg.__sockaddr__; + char *buf = (char *) addr; + addr_port_t aport; + + if (err = HURD_DPORT_USE (fd, __socket_peername (port, &aport))) + return __hurd_dfail (fd, err); + + err = __socket_whatis_address (aport, &type, &buf, &buflen); + __mach_port_deallocate (__mach_task_self (), aport); + + if (err) + return __hurd_dfail (fd, err); + + if (*len > buflen) + *len = buflen; + + if (buf != (char *) addr) + { + memcpy (addr, buf, *len); + __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen); + } + + const sa_family_t family = type; + if (*len > offsetof (struct sockaddr, sa_family)) + { + if (*len < (char *) (&addr->sa_family + 1) - (char *) addr) + memcpy (&addr->sa_family, &family, + *len - offsetof (struct sockaddr, sa_family)); + else + addr->sa_family = family; + } + + return 0; +} + +weak_alias (__getpeername, getpeername) diff --git a/libc/sysdeps/mach/hurd/getpgid.c b/libc/sysdeps/mach/hurd/getpgid.c new file mode 100644 index 000000000..167d748e5 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getpgid.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 97, 2002 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 <unistd.h> +#include <hurd.h> +#include <hurd/port.h> + +/* Get the process group ID of process PID. */ +int +__getpgid (pid) + pid_t pid; +{ + error_t err; + pid_t pgrp; + + if (pid == 0) + { + /* Assume atomic word fetch and store, so don't lock _hurd_pid_lock. */ + pgrp = _hurd_pgrp; + err = 0; + } + else + err = __USEPORT (PROC, __proc_getpgrp (port, pid, &pgrp)); + + return err ? __hurd_fail (err) : pgrp; +} +libc_hidden_def (__getpgid) +weak_alias (__getpgid, getpgid) diff --git a/libc/sysdeps/mach/hurd/getpid.c b/libc/sysdeps/mach/hurd/getpid.c new file mode 100644 index 000000000..a8324f291 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getpid.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1993, 1995, 1997, 2002 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 <unistd.h> +#include <hurd.h> + +/* Get the process ID of the calling process. */ +pid_t +__getpid () +{ + /* Assumes atomic word fetch and store, so doesn't lock _hurd_pid_lock. */ + return _hurd_pid; +} +libc_hidden_def (__getpid) +weak_alias (__getpid, getpid) +libc_hidden_weak (getpid) diff --git a/libc/sysdeps/mach/hurd/getppid.c b/libc/sysdeps/mach/hurd/getppid.c new file mode 100644 index 000000000..436cdb2cb --- /dev/null +++ b/libc/sysdeps/mach/hurd/getppid.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1993, 1995, 1997 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 <unistd.h> +#include <sys/types.h> +#include <hurd.h> + + +/* Get the parent process ID of the calling process. */ +pid_t +__getppid () +{ + /* Assumes atomic word fetch and store, so doesn't lock _hurd_pid_lock. */ + return _hurd_ppid; +} + +weak_alias (__getppid, getppid) diff --git a/libc/sysdeps/mach/hurd/getpriority.c b/libc/sysdeps/mach/hurd/getpriority.c new file mode 100644 index 000000000..8f7c3c6d9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getpriority.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1994,95,96,97,2000,02 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 <limits.h> +#include <hurd.h> +#include <hurd/resource.h> + +/* Return the highest priority of any process specified by WHICH and WHO + (see <sys/resource.h>); if WHO is zero, the current process, process group, + or user (as specified by WHO) is used. A lower priority number means higher + priority. Priorities range from PRIO_MIN to PRIO_MAX. */ +int +getpriority (enum __priority_which which, id_t who) +{ + error_t err, onerr; + int maxpri = INT_MIN; + struct procinfo *pip; /* Just for sizeof. */ + int pibuf[sizeof *pip + 2 * sizeof (pip->threadinfos[0])], *pi = pibuf; + size_t pisize = sizeof pibuf / sizeof pibuf[0]; + + error_t getonepriority (pid_t pid, struct procinfo *pip) + { + if (pip) + onerr = 0; + else + { + int *oldpi = pi; + size_t oldpisize = pisize; + char *tw = 0; + size_t twsz = 0; + int flags = PI_FETCH_TASKINFO; + onerr = __USEPORT (PROC, __proc_getprocinfo (port, pid, &flags, + &pi, &pisize, + &tw, &twsz)); + if (twsz) + __vm_deallocate (__mach_task_self (), (vm_address_t) tw, twsz); + if (pi != oldpi && oldpi != pibuf) + /* Old buffer from last call was not reused; free it. */ + __vm_deallocate (__mach_task_self (), + (vm_address_t) oldpi, oldpisize * sizeof pi[0]); + pip = (struct procinfo *) pi; + } +#ifdef TASK_SCHED_TIMESHARE_INFO + if (!onerr && pip->timeshare_base_info.base_priority > maxpri) + maxpri = pip->timeshare_base_info.base_priority; +#else + if (!onerr && pip->taskinfo.base_priority > maxpri) + maxpri = pip->taskinfo.base_priority; +#endif + return 0; + } + + onerr = 0; + err = _hurd_priority_which_map (which, who, + getonepriority, PI_FETCH_TASKINFO); + + if (pi != pibuf) + __vm_deallocate (__mach_task_self (), + (vm_address_t) pi, pisize * sizeof pi[0]); + + if (!err && maxpri == INT_MIN) + /* No error, but no pids found. */ + err = onerr ?: ESRCH; + + if (err) + return __hurd_fail (err); + + return MACH_PRIORITY_TO_NICE (maxpri); +} +libc_hidden_def (getpriority) diff --git a/libc/sysdeps/mach/hurd/getresgid.c b/libc/sysdeps/mach/hurd/getresgid.c new file mode 100644 index 000000000..7847d213c --- /dev/null +++ b/libc/sysdeps/mach/hurd/getresgid.c @@ -0,0 +1,62 @@ +/* getresgid -- fetch real group ID, effective group ID, and saved-set group ID + Copyright (C) 2002, 2006 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Fetch the real group ID, effective group ID, and saved-set group ID, + of the calling process. */ +int +__getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid) +{ + error_t err; + gid_t real, eff, saved; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + + err = _hurd_check_ids (); + if (!err) + { + if (_hurd_id.aux.ngids < 1) + /* We do not even have a real GID. */ + err = EGRATUITOUS; + else + { + real = _hurd_id.aux.gids[0]; + eff = _hurd_id.gen.ngids < 1 ? real : _hurd_id.gen.gids[0]; + saved = _hurd_id.aux.ngids < 2 ? real : _hurd_id.aux.gids[1]; + } + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + *rgid = real; + *egid = eff; + *sgid = saved; + return 0; +} +libc_hidden_def (__getresgid) +weak_alias (__getresgid, getresgid) diff --git a/libc/sysdeps/mach/hurd/getresuid.c b/libc/sysdeps/mach/hurd/getresuid.c new file mode 100644 index 000000000..668e463a3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getresuid.c @@ -0,0 +1,62 @@ +/* getresuid -- fetch real user ID, effective user ID, and saved-set user ID + Copyright (C) 2002, 2006 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Fetch the real user ID, effective user ID, and saved-set user ID, + of the calling process. */ +int +__getresuid (uid_t *ruid, uid_t *euid, uid_t *suid) +{ + error_t err; + uid_t real, eff, saved; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + + err = _hurd_check_ids (); + if (!err) + { + if (_hurd_id.aux.nuids < 1) + /* We do not even have a real UID. */ + err = EGRATUITOUS; + else + { + real = _hurd_id.aux.uids[0]; + eff = _hurd_id.gen.nuids < 1 ? real : _hurd_id.gen.uids[0]; + saved = _hurd_id.aux.nuids < 2 ? real : _hurd_id.aux.uids[1]; + } + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + *ruid = real; + *euid = eff; + *suid = saved; + return 0; +} +libc_hidden_def (__getresuid) +weak_alias (__getresuid, getresuid) diff --git a/libc/sysdeps/mach/hurd/getrlimit.c b/libc/sysdeps/mach/hurd/getrlimit.c new file mode 100644 index 000000000..4ad8f3c57 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getrlimit.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991,93,94,96,97,2000 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 <sys/resource.h> +#include <errno.h> +#include <hurd.h> +#include <hurd/resource.h> + +/* Put the soft and hard limits for RESOURCE in *RLIMITS. + Returns 0 if successful, -1 if not (and sets errno). */ +int +__getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits) +{ + struct rlimit lim; + + if (rlimits == NULL || (unsigned int) resource >= RLIMIT_NLIMITS) + { + errno = EINVAL; + return -1; + } + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_rlimit_lock); + lim = _hurd_rlimits[resource]; + __mutex_unlock (&_hurd_rlimit_lock); + HURD_CRITICAL_END; + + *rlimits = lim; + + return 0; +} +weak_alias (__getrlimit, getrlimit) diff --git a/libc/sysdeps/mach/hurd/getrusage.c b/libc/sysdeps/mach/hurd/getrusage.c new file mode 100644 index 000000000..373486ffc --- /dev/null +++ b/libc/sysdeps/mach/hurd/getrusage.c @@ -0,0 +1,94 @@ +/* getrusage -- Get resource usage information about processes. Hurd version. + Copyright (C) 1999,2001 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 <string.h> +#include <sys/resource.h> +#include <mach.h> +#include <mach/task_info.h> +#include <hurd.h> + +/* Return resource usage information on process indicated by WHO + and put it in *USAGE. Returns 0 for success, -1 for failure. */ +int +__getrusage (who, usage) + enum __rusage_who who; + struct rusage *usage; +{ + struct task_basic_info bi; + struct task_events_info ei; + struct task_thread_times_info tti; + mach_msg_type_number_t count; + error_t err; + + switch (who) + { + case RUSAGE_SELF: + count = TASK_BASIC_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_BASIC_INFO, + (task_info_t) &bi, &count); + if (err) + return __hurd_fail (err); + + count = TASK_EVENTS_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_EVENTS_INFO, + (task_info_t) &ei, &count); + if (err == KERN_INVALID_ARGUMENT) /* microkernel doesn't implement it */ + memset (&ei, 0, sizeof ei); + else if (err) + return __hurd_fail (err); + + count = TASK_THREAD_TIMES_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_THREAD_TIMES_INFO, + (task_info_t) &tti, &count); + if (err) + return __hurd_fail (err); + + time_value_add (&bi.user_time, &tti.user_time); + time_value_add (&bi.system_time, &tti.system_time); + + memset (usage, 0, sizeof (struct rusage)); + + usage->ru_utime.tv_sec = bi.user_time.seconds; + usage->ru_utime.tv_usec = bi.user_time.microseconds; + usage->ru_stime.tv_sec = bi.system_time.seconds; + usage->ru_stime.tv_usec = bi.system_time.microseconds; + + /* These statistics map only approximately. */ + usage->ru_majflt = ei.pageins; + usage->ru_minflt = ei.faults - ei.pageins; + usage->ru_msgsnd = ei.messages_sent; /* Mach IPC, not SysV IPC */ + usage->ru_msgrcv = ei.messages_received; /* Mach IPC, not SysV IPC */ + break; + + case RUSAGE_CHILDREN: + /* XXX Not implemented yet. However, zero out USAGE to be + consistent with the wait3 and wait4 functions. */ + memset (usage, 0, sizeof (struct rusage)); + + break; + + default: + return EINVAL; + } + + return 0; +} + +weak_alias (__getrusage, getrusage) diff --git a/libc/sysdeps/mach/hurd/getsid.c b/libc/sysdeps/mach/hurd/getsid.c new file mode 100644 index 000000000..9dcfa90fd --- /dev/null +++ b/libc/sysdeps/mach/hurd/getsid.c @@ -0,0 +1,39 @@ +/* getsid -- Return session ID of a process. Hurd version. + Copyright (C) 1995,97,2002 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 <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <hurd.h> + +pid_t +getsid (pid_t pid) +{ + error_t err; + pid_t sid; + + if (pid == 0) + pid = _hurd_pid; + + err = __USEPORT (PROC, __proc_getsid (port, pid, &sid)); + if (err) + return (pid_t) __hurd_fail (err); + return sid; +} +libc_hidden_def (getsid) diff --git a/libc/sysdeps/mach/hurd/getsockname.c b/libc/sysdeps/mach/hurd/getsockname.c new file mode 100644 index 000000000..dd0dddaed --- /dev/null +++ b/libc/sysdeps/mach/hurd/getsockname.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1992, 1994, 1997, 1999, 2002 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 <string.h> +#include <sys/socket.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> + +/* Put the local address of FD into *ADDR and its length in *LEN. */ +int +__getsockname (fd, addrarg, len) + int fd; + __SOCKADDR_ARG addrarg; + socklen_t *len; +{ + error_t err; + struct sockaddr *addr = addrarg.__sockaddr__; + char *buf = (char *) addr; + mach_msg_type_number_t buflen = *len; + int type; + addr_port_t aport; + + if (err = HURD_DPORT_USE (fd, __socket_name (port, &aport))) + return __hurd_dfail (fd, err); + + err = __socket_whatis_address (aport, &type, &buf, &buflen); + __mach_port_deallocate (__mach_task_self (), aport); + + if (err) + return __hurd_dfail (fd, err); + + if (*len > buflen) + *len = buflen; + + if (buf != (char *) addr) + { + memcpy (addr, buf, *len); + __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen); + } + + addr->sa_family = type; + + return 0; +} + +weak_alias (__getsockname, getsockname) diff --git a/libc/sysdeps/mach/hurd/getsockopt.c b/libc/sysdeps/mach/hurd/getsockopt.c new file mode 100644 index 000000000..7e35fa502 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getsockopt.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1992,94,97,2001,02 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 <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> +#include <string.h> + +/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL + into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's + actual length. Returns 0 on success, -1 for errors. */ + +/* XXX should be __getsockopt ? */ +int +getsockopt (int fd, + int level, + int optname, + void *optval, + socklen_t *optlen) +{ + error_t err; + char *buf = optval; + mach_msg_type_number_t buflen = *optlen; + + if (err = HURD_DPORT_USE (fd, __socket_getopt (port, + level, optname, + &buf, &buflen))) + return __hurd_dfail (fd, err); + + if (*optlen > buflen) + *optlen = buflen; + if (buf != optval) + { + memcpy (optval, buf, *optlen); + __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen); + } + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/getuid.c b/libc/sysdeps/mach/hurd/getuid.c new file mode 100644 index 000000000..138b2e6c9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getuid.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Get the real user ID of the calling process. */ +uid_t +__getuid () +{ + error_t err; + uid_t uid; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + + if (err = _hurd_check_ids ()) + { + errno = err; + uid = -1; + } + else if (_hurd_id.aux.nuids >= 1) + uid = _hurd_id.aux.uids[0]; + else + { + /* We do not even have a real uid. */ + errno = EGRATUITOUS; + uid = -1; + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + return uid; +} + +weak_alias (__getuid, getuid) diff --git a/libc/sysdeps/mach/hurd/getxattr.c b/libc/sysdeps/mach/hurd/getxattr.c new file mode 100644 index 000000000..8f688a1d2 --- /dev/null +++ b/libc/sysdeps/mach/hurd/getxattr.c @@ -0,0 +1,35 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2004 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> + +ssize_t +getxattr (const char *path, const char *name, void *value, size_t size) +{ + error_t err; + file_t port = __file_name_lookup (path, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = _hurd_xattr_get (port, name, value, &size); + __mach_port_deallocate (__mach_task_self (), port); + return err ? __hurd_fail (err) : size; +} diff --git a/libc/sysdeps/mach/hurd/group_member.c b/libc/sysdeps/mach/hurd/group_member.c new file mode 100644 index 000000000..927342ca5 --- /dev/null +++ b/libc/sysdeps/mach/hurd/group_member.c @@ -0,0 +1,56 @@ +/* `group_member' -- test if process is in a given group. Hurd version. + Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +int +__group_member (gid) + gid_t gid; +{ + int member = 0; + error_t err; + void *crit; + + crit = _hurd_critical_section_lock (); + __mutex_lock (&_hurd_id.lock); + + err = _hurd_check_ids (); + if (! err) + { + size_t i; + for (i = 0; i < _hurd_id.gen.ngids; ++i) + if (_hurd_id.gen.gids[i] == gid) + { + member = 1; + break; + } + } + + __mutex_unlock (&_hurd_id.lock); + _hurd_critical_section_unlock (crit); + + if (err) + __hurd_fail (err); + return member; +} + +weak_alias (__group_member, group_member) diff --git a/libc/sysdeps/mach/hurd/i386/Makefile b/libc/sysdeps/mach/hurd/i386/Makefile new file mode 100644 index 000000000..0eef17e8f --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),misc) +sysdep_routines += ioperm +sysdep_headers += sys/io.h +endif diff --git a/libc/sysdeps/mach/hurd/i386/Versions b/libc/sysdeps/mach/hurd/i386/Versions new file mode 100644 index 000000000..67e6d9420 --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/Versions @@ -0,0 +1,10 @@ +libc { + GLIBC_2.0 { + # Exception handling support functions from libgcc + __register_frame; __register_frame_table; __deregister_frame; + __frame_state_for; __register_frame_info_table; + } + GLIBC_2.2.6 { + ioperm; + } +} diff --git a/libc/sysdeps/mach/hurd/i386/bits/sigcontext.h b/libc/sysdeps/mach/hurd/i386/bits/sigcontext.h new file mode 100644 index 000000000..a78dd2f27 --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/bits/sigcontext.h @@ -0,0 +1,120 @@ +/* Machine-dependent signal context structure for GNU Hurd. i386 version. + Copyright (C) 1991, 1992, 1994, 1997, 2001 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. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead." +#endif + +#ifndef sc_pc + +/* Signal handlers are actually called: + void handler (int sig, int code, struct sigcontext *scp); */ + +#include <mach/machine/fp_reg.h> + +/* State of this thread when the signal was taken. */ +struct sigcontext + { + /* These first members are machine-independent. */ + + int sc_onstack; /* Nonzero if running on sigstack. */ + __sigset_t sc_mask; /* Blocked signals to restore. */ + + /* MiG reply port this thread is using. */ + unsigned int sc_reply_port; + + /* Port this thread is doing an interruptible RPC on. */ + unsigned int sc_intr_port; + + /* Error code associated with this signal (interpreted as `error_t'). */ + int sc_error; + + /* All following members are machine-dependent. The rest of this + structure is written to be laid out identically to: + { + struct i386_thread_state basic; + struct i386_float_state fpu; + } + trampoline.c knows this, so it must be changed if this changes. */ + +#define sc_i386_thread_state sc_gs /* Beginning of correspondence. */ + /* Segment registers. */ + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + + /* "General" registers. These members are in the order that the i386 + `pusha' and `popa' instructions use (`popa' ignores %esp). */ + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_esp; /* Not used; sc_uesp is used instead. */ + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + + int sc_eip; /* Instruction pointer. */ + int sc_cs; /* Code segment register. */ + + int sc_efl; /* Processor flags. */ + + int sc_uesp; /* This stack pointer is used. */ + int sc_ss; /* Stack segment register. */ + + /* Following mimics struct i386_float_state. Structures and symbolic + values can be found in <mach/i386/fp_reg.h>. */ +#define sc_i386_float_state sc_fpkind + int sc_fpkind; /* FP_NO, FP_387, etc. */ + int sc_fpused; /* If zero, ignore rest of float state. */ + struct i386_fp_save sc_fpsave; + struct i386_fp_regs sc_fpregs; + int sc_fpexcsr; /* FPSR including exception bits. */ + }; + +/* Traditional BSD names for some members. */ +#define sc_sp sc_uesp /* Stack pointer. */ +#define sc_fp sc_ebp /* Frame pointer. */ +#define sc_pc sc_eip /* Process counter. */ +#define sc_ps sc_efl + + +/* Codes for SIGFPE. */ +#define FPE_INTOVF_TRAP 0x1 /* integer overflow */ +#define FPE_INTDIV_FAULT 0x2 /* integer divide by zero */ +#define FPE_FLTOVF_FAULT 0x3 /* floating overflow */ +#define FPE_FLTDIV_FAULT 0x4 /* floating divide by zero */ +#define FPE_FLTUND_FAULT 0x5 /* floating underflow */ +#define FPE_SUBRNG_FAULT 0x7 /* BOUNDS instruction failed */ +#define FPE_FLTDNR_FAULT 0x8 /* denormalized operand */ +#define FPE_FLTINX_FAULT 0x9 /* floating loss of precision */ +#define FPE_EMERR_FAULT 0xa /* mysterious emulation error 33 */ +#define FPE_EMBND_FAULT 0xb /* emulation BOUNDS instruction failed */ + +/* Codes for SIGILL. */ +#define ILL_INVOPR_FAULT 0x1 /* invalid operation */ +#define ILL_STACK_FAULT 0x2 /* fault on microkernel stack access */ +#define ILL_FPEOPR_FAULT 0x3 /* invalid floating operation */ + +/* Codes for SIGTRAP. */ +#define DBG_SINGLE_TRAP 0x1 /* single step */ +#define DBG_BRKPNT_FAULT 0x2 /* breakpoint instruction */ + +#endif /* sc_pc */ diff --git a/libc/sysdeps/mach/hurd/i386/dl-machine.h b/libc/sysdeps/mach/hurd/i386/dl-machine.h new file mode 100644 index 000000000..40f2ff29d --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/dl-machine.h @@ -0,0 +1,7 @@ +/* Dynamic linker magic for Hurd/i386. + This file just gets us a call to _dl_first_init inserted + into the asm in sysdeps/i386/dl-machine.h that contains + the initializer code. */ + +#define RTLD_START_SPECIAL_INIT "call _dl_init_first@PLT; movl (%esp), %edx" +#include_next "dl-machine.h" diff --git a/libc/sysdeps/mach/hurd/i386/exc2signal.c b/libc/sysdeps/mach/hurd/i386/exc2signal.c new file mode 100644 index 000000000..a6bf750d7 --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/exc2signal.c @@ -0,0 +1,166 @@ +/* Translate Mach exception codes into signal numbers. i386 version. + Copyright (C) 1991,1992,1994,1996,1997,2001 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 <hurd.h> +#include <hurd/signal.h> +#include <mach/exception.h> + +/* 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) +{ + detail->error = 0; + + switch (detail->exc) + { + default: + *signo = SIGIOT; + detail->code = detail->exc; + 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; + 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; + break; + + case EXC_ARITHMETIC: + switch (detail->exc_code) + { + case EXC_I386_DIV: /* integer divide by zero */ + *signo = SIGFPE; + detail->code = FPE_INTDIV_FAULT; + break; + + case EXC_I386_INTO: /* integer overflow */ + *signo = SIGFPE; + detail->code = 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; + + case EXC_I386_EXTERR: + /* Subcode is the fp_status word saved by the hardware. + Give an error code corresponding to the first bit set. */ + if (detail->exc_subcode & FPS_IE) + { + *signo = SIGILL; + detail->code = ILL_FPEOPR_FAULT; + } + else if (detail->exc_subcode & FPS_DE) + { + *signo = SIGFPE; + detail->code = FPE_FLTDNR_FAULT; + } + else if (detail->exc_subcode & FPS_ZE) + { + *signo = SIGFPE; + detail->code = FPE_FLTDIV_FAULT; + } + else if (detail->exc_subcode & FPS_OE) + { + *signo = SIGFPE; + detail->code = FPE_FLTOVF_FAULT; + } + else if (detail->exc_subcode & FPS_UE) + { + *signo = SIGFPE; + detail->code = FPE_FLTUND_FAULT; + } + else if (detail->exc_subcode & FPS_PE) + { + *signo = SIGFPE; + detail->code = 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.) */ + case EXC_I386_EMERR: + *signo = SIGFPE; + detail->code = FPE_EMERR_FAULT; + break; + case EXC_I386_BOUND: + *signo = SIGFPE; + detail->code = FPE_EMBND_FAULT; + break; + } + break; + + case EXC_EMULATION: + /* 3.0 doesn't give this one, why, I don't know. */ + *signo = SIGEMT; + detail->code = 0; + break; + + case EXC_SOFTWARE: + /* The only time we get this in Mach 3.0 + is for an out of bounds trap. */ + if (detail->exc_code == EXC_I386_BOUND) + { + *signo = SIGFPE; + detail->code = FPE_SUBRNG_FAULT; + } + else + { + *signo = SIGEMT; + detail->code = 0; + } + break; + + 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; + break; + } +} diff --git a/libc/sysdeps/mach/hurd/i386/init-first.c b/libc/sysdeps/mach/hurd/i386/init-first.c new file mode 100644 index 000000000..f9a7a58de --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/init-first.c @@ -0,0 +1,393 @@ +/* Initialization code run first thing by the ELF startup code. For i386/Hurd. + Copyright (C) 1995,96,97,98,99,2000,01,02,03,04,05 + 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 <assert.h> +#include <hurd.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sysdep.h> +#include <set-hooks.h> +#include "hurdstartup.h" +#include "hurdmalloc.h" /* XXX */ +#include "../locale/localeinfo.h" + +#include <ldsodefs.h> +#include <fpu_control.h> + +extern void __mach_init (void); +extern void __init_misc (int, char **, char **); +#ifdef USE_NONOPTION_FLAGS +extern void __getopt_clean_environment (char **); +#endif +#ifndef SHARED +extern void _dl_non_dynamic_init (void) internal_function; +#endif +extern void __libc_global_ctors (void); + +unsigned int __hurd_threadvar_max; +unsigned long int __hurd_threadvar_stack_offset; +unsigned long int __hurd_threadvar_stack_mask; + +#ifndef SHARED +int __libc_enable_secure; +#endif +int __libc_multiple_libcs attribute_hidden = 1; + +extern int __libc_argc attribute_hidden; +extern char **__libc_argv attribute_hidden; +extern char **_dl_argv; + +extern void *(*_cthread_init_routine) (void) __attribute__ ((weak)); +void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__)); + +/* Things that want to be run before _hurd_init or much anything else. + Importantly, these are called before anything tries to use malloc. */ +DEFINE_HOOK (_hurd_preinit_hook, (void)); + + +/* We call this once the Hurd magic is all set up and we are ready to be a + Posixoid program. This does the same things the generic version does. */ +static void +posixland_init (int argc, char **argv, char **envp) +{ + __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up; + + /* Make sure we don't initialize twice. */ + if (!__libc_multiple_libcs) + { + /* Set the FPU control word to the proper default value. */ + __setfpucw (__fpu_control); + } + + /* Save the command-line arguments. */ + __libc_argc = argc; + __libc_argv = argv; + __environ = envp; + +#ifndef SHARED + _dl_non_dynamic_init (); +#endif + __init_misc (argc, argv, envp); + +#ifdef USE_NONOPTION_FLAGS + /* This is a hack to make the special getopt in GNU libc working. */ + __getopt_clean_environment (envp); +#endif + +#ifdef SHARED + __libc_global_ctors (); +#endif +} + + +static void +init1 (int argc, char *arg0, ...) +{ + char **argv = &arg0; + char **envp = &argv[argc + 1]; + struct hurd_startup_data *d; +#ifndef SHARED + extern ElfW(Phdr) *_dl_phdr; + extern size_t _dl_phnum; +#endif + + while (*envp) + ++envp; + d = (void *) ++envp; + + /* 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]) + { +#ifndef SHARED + /* We may need to see our own phdrs, e.g. for TLS setup. + Try the usual kludge to find the headers without help from + the exec server. */ + extern const void _start; + const ElfW(Ehdr) *const ehdr = &_start; + _dl_phdr = (ElfW(Phdr) *) ((const void *) ehdr + ehdr->e_phoff); + _dl_phnum = ehdr->e_phnum; + assert (ehdr->e_phentsize == sizeof (ElfW(Phdr))); +#endif + return; + } + +#ifndef SHARED + __libc_enable_secure = d->flags & EXEC_SECURE; + + _dl_phdr = (ElfW(Phdr) *) d->phdr; + _dl_phnum = d->phdrsz / sizeof (ElfW(Phdr)); + assert (d->phdrsz % sizeof (ElfW(Phdr)) == 0); +#endif + + _hurd_init_dtable = d->dtable; + _hurd_init_dtablesize = d->dtablesize; + + { + /* Check if the stack we are now on is different from + the one described by _hurd_stack_{base,size}. */ + + char dummy; + const vm_address_t newsp = (vm_address_t) &dummy; + + if (d->stack_size != 0 && (newsp < d->stack_base || + newsp - d->stack_base > d->stack_size)) + /* The new stack pointer does not intersect with the + stack the exec server set up for us, so free that stack. */ + __vm_deallocate (__mach_task_self (), d->stack_base, d->stack_size); + } + + if (d->portarray || d->intarray) + /* Initialize library data structures, start signal processing, etc. */ + _hurd_init (d->flags, argv, + d->portarray, d->portarraysize, + d->intarray, d->intarraysize); +} + + +static inline void +init (int *data) +{ + int argc = *data; + char **argv = (void *) (data + 1); + char **envp = &argv[argc + 1]; + struct hurd_startup_data *d; + unsigned long int threadvars[_HURD_THREADVAR_MAX]; + + /* Provide temporary storage for thread-specific variables on the + startup stack so the cthreads initialization code can use them + for malloc et al, or so we can use malloc below for the real + threadvars array. */ + memset (threadvars, 0, sizeof threadvars); + threadvars[_HURD_THREADVAR_LOCALE] = (unsigned long int) &_nl_global_locale; + __hurd_threadvar_stack_offset = (unsigned long int) threadvars; + + /* Since the cthreads initialization code uses malloc, and the + malloc initialization code needs to get at the environment, make + sure we can find it. We'll need to do this again later on since + switching stacks changes the location where the environment is + stored. */ + __environ = envp; + + while (*envp) + ++envp; + d = (void *) ++envp; + + /* The user might have defined a value for this, to get more variables. + Otherwise it will be zero on startup. We must make sure it is set + properly before before cthreads initialization, so cthreads can know + how much space to leave for thread variables. */ + if (__hurd_threadvar_max < _HURD_THREADVAR_MAX) + __hurd_threadvar_max = _HURD_THREADVAR_MAX; + + + /* After possibly switching stacks, call `init1' (above) with the user + code as the return address, and the argument data immediately above + that on the stack. */ + + if (&_cthread_init_routine && _cthread_init_routine) + { + /* Initialize cthreads, which will allocate us a new stack to run on. */ + int *newsp = (*_cthread_init_routine) (); + struct hurd_startup_data *od; + + void switch_stacks (void); + + /* Copy per-thread variables from that temporary + area onto the new cthread stack. */ + memcpy (__hurd_threadvar_location_from_sp (0, newsp), + threadvars, sizeof threadvars); + + /* Copy the argdata from the old stack to the new one. */ + newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data, + (char *) d - (char *) data); + +#ifdef SHARED + /* And readjust the dynamic linker's idea of where the argument + vector lives. */ + assert (_dl_argv == argv); + _dl_argv = (void *) (newsp + 1); +#endif + + /* Set up the Hurd startup data block immediately following + the argument and environment pointers on the new stack. */ + od = ((void *) newsp + ((char *) d - (char *) data)); + if ((void *) argv[0] == d) + /* We were started up by the kernel with arguments on the stack. + There is no Hurd startup data, so zero the block. */ + memset (od, 0, sizeof *od); + else + /* Copy the Hurd startup data block to the new stack. */ + *od = *d; + + /* Push the user code address on the top of the new stack. It will + be the return address for `init1'; we will jump there with NEWSP + as the stack pointer. */ + *--newsp = data[-1]; + ((void **) data)[-1] = switch_stacks; + /* Force NEWSP into %ecx and &init1 into %eax, which are not restored + by function return. */ + asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1)); + } + else + { + /* We are not using cthreads, so we will have just a single allocated + area for the per-thread variables of the main user thread. */ + unsigned long int *array; + unsigned int i; + int usercode; + + void call_init1 (void); + + array = malloc (__hurd_threadvar_max * sizeof (unsigned long int)); + if (array == NULL) + __libc_fatal ("Can't allocate single-threaded thread variables."); + + /* Copy per-thread variables from the temporary array into the + newly malloc'd space. */ + memcpy (array, threadvars, sizeof threadvars); + __hurd_threadvar_stack_offset = (unsigned long int) array; + for (i = _HURD_THREADVAR_MAX; i < __hurd_threadvar_max; ++i) + array[i] = 0; + + /* The argument data is just above the stack frame we will unwind by + returning. Mutate our own return address to run the code below. */ + usercode = data[-1]; + data[-1] = (int) &call_init1; + /* Force USERCODE into %eax and &init1 into %ecx, which are not + restored by function return. */ + asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1)); + } +} + +/* These bits of inline assembler used to be located inside `init'. + However they were optimized away by gcc 2.95. */ + +/* The return address of `init' above, was redirected to here, so at + this point our stack is unwound and callers' registers restored. + Only %ecx and %eax are call-clobbered and thus still have the + values we set just above. Fetch from there the new stack pointer + we will run on, and jmp to the run-time address of `init1'; when it + returns, it will run the user code with the argument data at the + top of the stack. */ +asm ("switch_stacks:\n" + " movl %eax, %esp\n" + " jmp *%ecx"); + +/* As in the stack-switching case, at this point our stack is unwound + and callers' registers restored, and only %ecx and %eax communicate + values from the lines above. In this case we have stashed in %eax + the user code return address. Push it on the top of the stack so + it acts as init1's return address, and then jump there. */ +asm ("call_init1:\n" + " push %eax\n" + " jmp *%ecx\n"); + + +/* Do the first essential initializations that must precede all else. */ +static inline void +first_init (void) +{ + /* Initialize data structures so we can do RPCs. */ + __mach_init (); + + RUN_HOOK (_hurd_preinit_hook, ()); +} + +#ifdef SHARED +/* This function is called specially by the dynamic linker to do early + initialization of the shared C library before normal initializers + expecting a Posixoid environment can run. It gets called with the + stack set up just as the user will see it, so it can switch stacks. */ + +void +_dl_init_first (void) +{ + first_init (); + + init ((int *) __builtin_frame_address (0) + 2); +} +#endif + + +#ifdef SHARED +/* The regular posixland initialization is what goes into libc's + normal initializer. */ +/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT + pointer in the dynamic section based solely on that. It is convention + for this function to be in the `.init' section, but the symbol name is + the only thing that really matters!! */ +strong_alias (posixland_init, _init); + +void +__libc_init_first (int argc, char **argv, char **envp) +{ + /* Everything was done in the shared library initializer, _init. */ +} +#else +strong_alias (posixland_init, __libc_init_first); + + +/* XXX This is all a crock and I am not happy with it. + This poorly-named function is called by static-start.S, + which should not exist at all. */ +void +_hurd_stack_setup (void) +{ + intptr_t caller = (intptr_t) __builtin_return_address (0); + + void doinit (intptr_t *data) + { + /* This function gets called with the argument data at TOS. */ + void doinit1 (void) + { + init ((int *) __builtin_frame_address (0) + 2); + } + + /* Push the user return address after the argument data, and then + jump to `doinit1' (above), so it is as if __libc_init_first's + caller had called `doinit1' with the argument data already on the + stack. */ + *--data = caller; + asm volatile ("movl %0, %%esp\n" /* Switch to new outermost stack. */ + "movl $0, %%ebp\n" /* Clear outermost frame pointer. */ + "jmp *%1" : : "r" (data), "r" (&doinit1) : "sp"); + /* NOTREACHED */ + } + + first_init (); + + _hurd_startup ((void **) __builtin_frame_address (0) + 2, &doinit); +} +#endif + + +/* This function is defined here so that if this file ever gets into + ld.so we will get a link error. Having this file silently included + in ld.so causes disaster, because the _init definition above will + cause ld.so to gain an init function, which is not a cool thing. */ + +void +_dl_start (void) +{ + abort (); +} diff --git a/libc/sysdeps/mach/hurd/i386/intr-msg.h b/libc/sysdeps/mach/hurd/i386/intr-msg.h new file mode 100644 index 000000000..8b9b34b37 --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/intr-msg.h @@ -0,0 +1,113 @@ +/* Machine-dependent details of interruptible RPC messaging. i386 version. + Copyright (C) 1995,96,97,99,2001 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. */ + + +/* Note that we must mark OPTION and TIMEOUT as outputs of this operation, + to indicate that the signal thread might mutate them as part + of sending us to a signal handler. */ +#define INTR_MSG_TRAP(msg, option, send_size, rcv_size, rcv_name, timeout, notify) \ +({ \ + error_t err; \ + asm (".globl _hurd_intr_rpc_msg_do_trap\n" \ + ".globl _hurd_intr_rpc_msg_in_trap\n" \ + ".globl _hurd_intr_rpc_msg_cx_sp\n" \ + ".globl _hurd_intr_rpc_msg_sp_restored\n" \ + " movl %%esp, %%ecx\n" \ + " leal %3, %%esp\n" \ + "_hurd_intr_rpc_msg_cx_sp: movl $-25, %%eax\n" \ + "_hurd_intr_rpc_msg_do_trap: lcall $7, $0 # status in %0\n" \ + "_hurd_intr_rpc_msg_in_trap: movl %%ecx, %%esp\n" \ + "_hurd_intr_rpc_msg_sp_restored:" \ + : "=a" (err), "=m" (option), "=m" (timeout) \ + : "m" ((&msg)[-1]), "1" (option), "2" (timeout) \ + : "%ecx"); \ + err; \ +}) + + +static void inline +INTR_MSG_BACK_OUT (struct i386_thread_state *state) +{ + extern const void _hurd_intr_rpc_msg_cx_sp; + if (state->eip >= (natural_t) &_hurd_intr_rpc_msg_cx_sp) + state->uesp = state->ecx; + else + state->ecx = state->uesp; +} + +#include "hurdfault.h" + +/* This cannot be an inline function because it calls setjmp. */ +#define SYSCALL_EXAMINE(state, callno) \ +({ \ + struct { unsigned int c[2]; } *p = (void *) ((state)->eip - 7); \ + int result; \ + if (_hurdsig_catch_memory_fault (p)) \ + return 0; \ + if (result = p->c[0] == 0x0000009a && (p->c[1] & 0x00ffffff) == 0x00000700) \ + /* The PC is just after an `lcall $7,$0' instruction. \ + This is a system call in progress; %eax holds the call number. */ \ + *(callno) = (state)->eax; \ + _hurdsig_end_catch_fault (); \ + result; \ +}) + + +struct mach_msg_trap_args + { + void *retaddr; /* Address mach_msg_trap will return to. */ + /* This is the order of arguments to mach_msg_trap. */ + mach_msg_header_t *msg; + mach_msg_option_t option; + mach_msg_size_t send_size; + mach_msg_size_t rcv_size; + mach_port_t rcv_name; + mach_msg_timeout_t timeout; + mach_port_t notify; + }; + + +/* This cannot be an inline function because it calls setjmp. */ +#define MSG_EXAMINE(state, msgid, rcvname, send_name, opt, tmout) \ +({ \ + const struct mach_msg_trap_args *args = (const void *) (state)->uesp; \ + mach_msg_header_t *msg; \ + _hurdsig_catch_memory_fault (args) ? -1 : \ + ({ \ + msg = args->msg; \ + *(opt) = args->option; \ + *(tmout) = args->timeout; \ + *(rcvname) = args->rcv_name; \ + _hurdsig_end_catch_fault (); \ + if (msg == 0) \ + { \ + *(send_name) = MACH_PORT_NULL; \ + *(msgid) = 0; \ + } \ + else \ + { \ + if (_hurdsig_catch_memory_fault (msg)) \ + return -1; \ + *(send_name) = msg->msgh_remote_port; \ + *(msgid) = msg->msgh_id; \ + _hurdsig_end_catch_fault (); \ + } \ + 0; \ + }); \ +}) diff --git a/libc/sysdeps/mach/hurd/i386/ioperm.c b/libc/sysdeps/mach/hurd/i386/ioperm.c new file mode 100644 index 000000000..be243d1ac --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/ioperm.c @@ -0,0 +1,54 @@ +/* Access to hardware i/o ports. Hurd/x86 version. + Copyright (C) 2002 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 <sys/io.h> +#include <hurd.h> +#include <mach/i386/mach_i386.h> + +int +ioperm (unsigned long int from, unsigned long int num, int turn_on) +{ +#if ! HAVE_I386_IO_PERM_MODIFY + return __hurd_fail (ENOSYS); +#else + error_t err; + device_t devmaster; + + /* With the device master port we get a capability that represents + this range of io ports. */ + err = __get_privileged_ports (NULL, &devmaster); + if (! err) + { + io_perm_t perm; + err = __i386_io_perm_create (devmaster, from, from + num - 1, &perm); + __mach_port_deallocate (__mach_task_self (), devmaster); + if (! err) + { + /* Now we add or remove that set from our task's bitmap. */ + err = __i386_io_perm_modify (__mach_task_self (), perm, turn_on); + __mach_port_deallocate (__mach_task_self (), perm); + } + + if (err == MIG_BAD_ID) /* Old kernels don't have these RPCs. */ + err = ENOSYS; + } + + return err ? __hurd_fail (err) : 0; +#endif +} diff --git a/libc/sysdeps/mach/hurd/i386/longjmp-ts.c b/libc/sysdeps/mach/hurd/i386/longjmp-ts.c new file mode 100644 index 000000000..c902002cb --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/longjmp-ts.c @@ -0,0 +1,40 @@ +/* Perform a `longjmp' on a Mach thread_state. i386 version. + Copyright (C) 1991, 1994, 1995, 1997, 2006 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 <hurd/signal.h> +#include <setjmp.h> +#include <jmpbuf-offsets.h> +#include <mach/thread_status.h> + + +/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */ + +void +_hurd_longjmp_thread_state (void *state, jmp_buf env, int val) +{ + struct i386_thread_state *ts = state; + + ts->ebx = env[0].__jmpbuf[JB_BX]; + ts->esi = env[0].__jmpbuf[JB_SI]; + ts->edi = env[0].__jmpbuf[JB_DI]; + ts->ebp = env[0].__jmpbuf[JB_BP]; + ts->uesp = env[0].__jmpbuf[JB_SP]; + ts->eip = env[0].__jmpbuf[JB_PC]; + ts->eax = val ?: 1; +} diff --git a/libc/sysdeps/mach/hurd/i386/sigcontextinfo.h b/libc/sysdeps/mach/hurd/i386/sigcontextinfo.h new file mode 100644 index 000000000..a3bad2af8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/sigcontextinfo.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1998, 1999 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. */ + +#define SIGCONTEXT struct sigcontext +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) (ctx).sc_eip) +#define GET_FRAME(ctx) ((void *) (ctx).sc_ebp) +#define GET_STACK(ctx) ((void *) (ctx).sc_uesp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/libc/sysdeps/mach/hurd/i386/sigreturn.c b/libc/sysdeps/mach/hurd/i386/sigreturn.c new file mode 100644 index 000000000..60b0d006a --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/sigreturn.c @@ -0,0 +1,140 @@ +/* Copyright (C) 1991,92,94,95,96,97,98,2001 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. */ + +register int *sp asm ("%esp"); + +#include <hurd.h> +#include <hurd/signal.h> +#include <hurd/threadvar.h> +#include <hurd/msg.h> +#include <stdlib.h> +#include <string.h> + +int +__sigreturn (struct sigcontext *scp) +{ + struct hurd_sigstate *ss; + struct hurd_userlink *link = (void *) &scp[1]; + mach_port_t *reply_port; + + if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)) + { + errno = EINVAL; + return -1; + } + + ss = _hurd_self_sigstate (); + __spin_lock (&ss->lock); + + /* Remove the link on the `active resources' chain added by + _hurd_setup_sighandler. Its purpose was to make sure + that we got called; now we have, it is done. */ + _hurd_userlink_unlink (link); + + /* Restore the set of blocked signals, and the intr_port slot. */ + ss->blocked = scp->sc_mask; + ss->intr_port = scp->sc_intr_port; + + /* Check for pending signals that were blocked by the old set. */ + if (ss->pending & ~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); + __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); + ss->context = NULL; + } + + if (scp->sc_onstack) + { + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */ + /* XXX cannot unlock until off sigstack */ + abort (); + } + else + __spin_unlock (&ss->lock); + + /* Destroy the MiG reply port used by the signal handler, and restore the + reply port in use by the thread when interrupted. */ + reply_port = + (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); + if (*reply_port) + { + mach_port_t port = *reply_port; + + /* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port not to + get another reply port, but avoids mig_dealloc_reply_port trying to + deallocate it after the receive fails (which it will, because the + reply port will be bogus, whether we do this or not). */ + *reply_port = MACH_PORT_DEAD; + + __mach_port_destroy (__mach_task_self (), port); + } + *reply_port = scp->sc_reply_port; + + if (scp->sc_fpused) + /* Restore the FPU state. Mach conveniently stores the state + in the format the i387 `frstor' instruction uses to restore it. */ + asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); + + { + /* There are convenient instructions to pop state off the stack, so we + copy the registers onto the user's stack, switch there, pop and + return. */ + + int *usp = (int *) scp->sc_uesp; + + *--usp = scp->sc_eip; + *--usp = scp->sc_efl; + memcpy (usp -= 12, &scp->sc_i386_thread_state, 12 * sizeof (int)); + + sp = usp; + +#define A(line) asm volatile (#line) + /* The members in the sigcontext are arranged in this order + so we can pop them easily. */ + + /* Pop the segment registers (except %cs and %ss, done last). */ + A (popl %gs); + A (popl %fs); + A (popl %es); + A (popl %ds); + /* Pop the general registers. */ + A (popa); + /* Pop the processor flags. */ + A (popf); + /* Return to the saved PC. */ + A (ret); + + /* Firewall. */ + A (hlt); +#undef A + } + + /* NOTREACHED */ + return -1; +} + +weak_alias (__sigreturn, sigreturn) diff --git a/libc/sysdeps/mach/hurd/i386/static-start.S b/libc/sysdeps/mach/hurd/i386/static-start.S new file mode 100644 index 000000000..e80d5b755 --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/static-start.S @@ -0,0 +1,28 @@ +/* Startup code for statically linked Hurd/i386 binaries. + Copyright (C) 1998 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. */ + + .text + .globl _start +_start: + call _hurd_stack_setup + xorl %edx, %edx + jmp _start1 + +#define _start _start1 +#include <sysdeps/i386/elf/start.S> diff --git a/libc/sysdeps/mach/hurd/i386/sys/io.h b/libc/sysdeps/mach/hurd/i386/sys/io.h new file mode 100644 index 000000000..49ac9985a --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/sys/io.h @@ -0,0 +1,178 @@ +/* Access to hardware i/o ports. GNU/x86 version. + Copyright (C) 2002 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 _SYS_IO_H +#define _SYS_IO_H 1 + +#include <features.h> + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; + +#if defined __GNUC__ && __GNUC__ >= 2 + +static __inline unsigned char +inb (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned char +inb_p (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw (unsigned short int port) +{ + unsigned short _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw_p (unsigned short int port) +{ + unsigned short int _v; + + __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl (unsigned short int port) +{ + unsigned int _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl_p (unsigned short int port) +{ + unsigned int _v; + __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline void +outb (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outb_p (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outw (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port)); + +} + +static __inline void +outw_p (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outl (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outl_p (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +insb (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insb":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insw (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insw":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insl (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insl":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsb (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsw (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsl (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +#endif /* GNU C */ + +__END_DECLS +#endif /* _SYS_IO_H */ diff --git a/libc/sysdeps/mach/hurd/i386/tls.h b/libc/sysdeps/mach/hurd/i386/tls.h new file mode 100644 index 000000000..223a47d2f --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/tls.h @@ -0,0 +1,174 @@ +/* Definitions for thread-local data handling. Hurd/i386 version. + Copyright (C) 2003, 2004 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 _I386_TLS_H +#define _I386_TLS_H + +#if defined HAVE_TLS_SUPPORT + +/* Some things really need not be machine-dependent. */ +# include <sysdeps/mach/hurd/tls.h> + +/* Indiciate that TLS support is available. */ +# define USE_TLS 1 + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +# ifndef ASSEMBLER + +/* Use i386-specific RPCs to arrange that %gs segment register prefix + addresses the TCB in each thread. */ +# include <mach/i386/mach_i386.h> + +# ifndef HAVE_I386_SET_GDT +# define __i386_set_gdt(thr, sel, desc) ((void) (thr), (void) (sel), (void) (desc), MIG_BAD_ID) +# endif + +# include <errno.h> +# include <assert.h> + +#define HURD_TLS_DESC_DECL(desc, tcb) \ + struct descriptor desc = \ + { /* low word: */ \ + 0xffff /* limit 0..15 */ \ + | (((unsigned int) (tcb)) << 16) /* base 0..15 */ \ + , /* high word: */ \ + ((((unsigned int) (tcb)) >> 16) & 0xff) /* base 16..23 */ \ + | ((0x12 | 0x60 | 0x80) << 8) /* access = ACC_DATA_W|ACC_PL_U|ACC_P */ \ + | (0xf << 16) /* limit 16..19 */ \ + | ((4 | 8) << 20) /* granularity = SZ_32|SZ_G */ \ + | (((unsigned int) (tcb)) & 0xff000000) /* base 24..31 */ \ + } + + +static inline const char * __attribute__ ((unused)) +_hurd_tls_init (tcbhead_t *tcb, int secondcall) +{ + HURD_TLS_DESC_DECL (desc, tcb); + + if (!secondcall) + { + /* This field is used by TLS accesses to get our "thread pointer" + 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; + error_t err = __i386_set_gdt (tcb->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); + assert_perror (err); + if (err) + return "i386_set_ldt failed"; + } + else if (err) + { + assert_perror (err); /* Separate from above with different line #. */ + return "i386_set_gdt failed"; + } + + /* Now install the new selector. */ + asm volatile ("mov %w0, %%gs" :: "q" (sel)); + } + else + { + /* Fetch the selector set by the first call. */ + int sel; + asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0)); + if (__builtin_expect (sel, 0x50) & 4) /* LDT selector */ + { + error_t err = __i386_set_ldt (tcb->self, sel, &desc, 1); + assert_perror (err); + if (err) + return "i386_set_ldt failed"; + } + else + { + error_t err = __i386_set_gdt (tcb->self, &sel, desc); + assert_perror (err); + if (err) + return "i386_set_gdt failed"; + } + } + + return 0; +} + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + _hurd_tls_init ((tcbhead_t *) (descr), (secondcall)) +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the TCB address of the current thread. */ +# define THREAD_SELF \ + ({ tcbhead_t *__tcb; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__tcb) \ + : "i" (offsetof (tcbhead_t, tcb))); \ + __tcb;}) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtvp) \ + ({ asm volatile ("movl %0,%%gs:%P1" \ + : : "ir" (dtvp), "i" (offsetof (tcbhead_t, dtv))); }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ dtv_t *_dtv; \ + asm ("movl %%gs:%P1,%0" : "=q" (_dtv) : "i" (offsetof (tcbhead_t, dtv)));\ + _dtv; }) + +#include <mach/machine/thread_status.h> + +/* Set up TLS in the new thread of a fork child, copying from our own. */ +static inline error_t __attribute__ ((unused)) +_hurd_tls_fork (thread_t child, struct i386_thread_state *state) +{ + /* Fetch the selector set by _hurd_tls_init. */ + int sel; + asm ("mov %%gs, %w0" : "=q" (sel) : "0" (0)); + if (sel == state->ds) /* _hurd_tls_init was never called. */ + return 0; + + tcbhead_t *const tcb = THREAD_SELF; + HURD_TLS_DESC_DECL (desc, tcb); + error_t err; + + if (__builtin_expect (sel, 0x50) & 4) /* LDT selector */ + err = __i386_set_ldt (child, sel, &desc, 1); + else + err = __i386_set_gdt (child, &sel, desc); + + state->gs = sel; + return err; +} + +# endif /* !ASSEMBLER */ +#endif /* HAVE_TLS_SUPPORT */ + +#endif /* i386/tls.h */ diff --git a/libc/sysdeps/mach/hurd/i386/trampoline.c b/libc/sysdeps/mach/hurd/i386/trampoline.c new file mode 100644 index 000000000..dddc6f3ef --- /dev/null +++ b/libc/sysdeps/mach/hurd/i386/trampoline.c @@ -0,0 +1,264 @@ +/* Set thread_state for sighandler, and sigcontext to recover. i386 version. + Copyright (C) 1994,1995,1996,1997,1998,1999,2005 + 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 <hurd/signal.h> +#include <hurd/userlink.h> +#include <thread_state.h> +#include <assert.h> +#include <errno.h> +#include "hurdfault.h" +#include <intr-msg.h> + + +struct sigcontext * +_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, + int signo, struct hurd_signal_detail *detail, + volatile int rpc_wait, + struct machine_thread_all_state *state) +{ + void trampoline (void); + void rpc_wait_trampoline (void); + void firewall (void); + 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; + void *volatile sigsp; + struct sigcontext *scp; + struct + { + int signo; + long int sigcode; + struct sigcontext *scp; /* Points to ctx, below. */ + void *sigreturn_addr; + void *sigreturn_returns_here; + struct sigcontext *return_scp; /* Same; arg to sigreturn. */ + struct sigcontext ctx; + struct hurd_userlink link; + } *stackframe; + + if (ss->context) + { + /* We have a previous sigcontext that sigreturn was about + to restore when another signal arrived. We will just base + our setup on that. */ + if (! _hurdsig_catch_memory_fault (ss->context)) + { + memcpy (&state->basic, &ss->context->sc_i386_thread_state, + sizeof (state->basic)); + memcpy (&state->fpu, &ss->context->sc_i386_float_state, + sizeof (state->fpu)); + state->set |= (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE); + } + } + + if (! machine_get_basic_state (ss->thread, state)) + return NULL; + + /* Save the original SP in the gratuitous `esp' slot. + We may need to reset the SP (the `uesp' slot) to avoid clobbering an + interrupted RPC frame. */ + state->basic.esp = state->basic.uesp; + + if ((ss->actions[signo].sa_flags & SA_ONSTACK) && + !(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK))) + { + sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size; + ss->sigaltstack.ss_flags |= SS_ONSTACK; + /* XXX need to set up base of new stack for + per-thread variables, cthreads. */ + } + /* This code has intimate knowledge of the special mach_msg system call + done in intr-msg.c; that code does (see intr-msg.h): + movl %esp, %ecx + leal ARGS, %esp + _hurd_intr_rpc_msg_cx_sp: movl $-25, %eax + _hurd_intr_rpc_msg_do_trap: lcall $7, $0 + _hurd_intr_rpc_msg_in_trap: movl %ecx, %esp + _hurd_intr_rpc_msg_sp_restored: + We must check for the window during which %esp points at the + mach_msg arguments. The space below until %ecx is used by + the _hurd_intr_rpc_mach_msg frame, and must not be clobbered. */ + else if (state->basic.eip >= (int) &_hurd_intr_rpc_msg_cx_sp && + state->basic.eip < (int) &_hurd_intr_rpc_msg_sp_restored) + /* The SP now points at the mach_msg args, but there is more stack + space used below it. The real SP is saved in %ecx; we must push the + new frame below there, and restore that value as the SP on + sigreturn. */ + sigsp = (char *) (state->basic.uesp = state->basic.ecx); + else + sigsp = (char *) state->basic.uesp; + + /* Push the arguments to call `trampoline' on the stack. */ + sigsp -= sizeof (*stackframe); + stackframe = sigsp; + + if (_hurdsig_catch_memory_fault (stackframe)) + { + /* We got a fault trying to write the stack frame. + We cannot set up the signal handler. + Returning NULL tells our caller, who will nuke us with a SIGILL. */ + return NULL; + } + else + { + int ok; + + extern void _hurdsig_longjmp_from_handler (void *, jmp_buf, int); + + /* Add a link to the thread's active-resources list. We mark this as + the only user of the "resource", so the cleanup function will be + called by any longjmp which is unwinding past the signal frame. + The cleanup function (in sigunwind.c) will make sure that all the + appropriate cleanups done by sigreturn are taken care of. */ + stackframe->link.cleanup = &_hurdsig_longjmp_from_handler; + stackframe->link.cleanup_data = &stackframe->ctx; + stackframe->link.resource.next = NULL; + stackframe->link.resource.prevp = NULL; + stackframe->link.thread.next = ss->active_resources; + stackframe->link.thread.prevp = &ss->active_resources; + if (stackframe->link.thread.next) + stackframe->link.thread.next->thread.prevp + = &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->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0; + + /* struct sigcontext is laid out so that starting at sc_gs mimics a + struct i386_thread_state. */ + memcpy (&scp->sc_i386_thread_state, + &state->basic, sizeof (state->basic)); + + /* struct sigcontext is laid out so that starting at sc_fpkind mimics + a struct i386_float_state. */ + ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE, + &state->fpu, &scp->sc_i386_float_state, + sizeof (state->fpu)); + + _hurdsig_end_catch_fault (); + + if (! ok) + return NULL; + } + + /* Modify the thread state to call the trampoline code on the new stack. */ + if (rpc_wait) + { + /* The signalee thread was blocked in a mach_msg_trap system call, + still waiting for a reply. We will have it run the special + trampoline code which retries the message receive before running + the signal handler. + + To do this we change the OPTION argument on its stack to enable only + message reception, since the request message has already been + sent. */ + + struct mach_msg_trap_args *args = (void *) state->basic.esp; + + if (_hurdsig_catch_memory_fault (args)) + { + /* Faulted accessing ARGS. Bomb. */ + return NULL; + } + + assert (args->option & MACH_RCV_MSG); + /* Disable the message-send, since it has already completed. The + calls we retry need only wait to receive the reply message. */ + args->option &= ~MACH_SEND_MSG; + + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + + _hurdsig_end_catch_fault (); + + state->basic.eip = (int) rpc_wait_trampoline; + /* The reply-receiving trampoline code runs initially on the original + user stack. We pass it the signal stack pointer in %ebx. */ + state->basic.uesp = state->basic.esp; /* Restore mach_msg syscall SP. */ + state->basic.ebx = (int) sigsp; + /* After doing the message receive, the trampoline code will need to + update the %eax value to be restored by sigreturn. To simplify + the assembly code, we pass the address of its slot in SCP to the + trampoline code in %ecx. */ + state->basic.ecx = (int) &scp->sc_eax; + } + else + { + state->basic.eip = (int) trampoline; + state->basic.uesp = (int) sigsp; + } + /* We pass the handler function to the trampoline code in %edx. */ + state->basic.edx = (int) handler; + + return scp; +} + +/* The trampoline code follows. This used to be located inside + _hurd_setup_sighandler, but was optimized away by gcc 2.95. */ + +asm ("rpc_wait_trampoline:\n"); + /* This is the entry point when we have an RPC reply message to receive + before running the handler. The MACH_MSG_SEND bit has already been + cleared in the OPTION argument on our stack. The interrupted user + stack pointer has not been changed, so the system call can find its + arguments; the signal stack pointer is in %ebx. For our convenience, + %ecx points to the sc_eax member of the sigcontext. */ +asm (/* Retry the interrupted mach_msg system call. */ + "movl $-25, %eax\n" /* mach_msg_trap */ + "lcall $7, $0\n" + /* When the sigcontext was saved, %eax was MACH_RCV_INTERRUPTED. But + now the message receive has completed and the original caller of + the RPC (i.e. the code running when the signal arrived) needs to + see the final return value of the message receive in %eax. So + store the new %eax value into the sc_eax member of the sigcontext + (whose address is in %ecx to make this code simpler). */ + "movl %eax, (%ecx)\n" + /* Switch to the signal stack. */ + "movl %ebx, %esp\n"); + + asm ("trampoline:\n"); + /* Entry point for running the handler normally. The arguments to the + handler function are already on the top of the stack: + + 0(%esp) SIGNO + 4(%esp) SIGCODE + 8(%esp) SCP + */ +asm ("call *%edx\n" /* Call the handler function. */ + "addl $12, %esp\n" /* Pop its args. */ + /* The word at the top of stack is &__sigreturn; following are a dummy + word to fill the slot for the address for __sigreturn to return to, + and a copy of SCP for __sigreturn's argument. "Return" to calling + __sigreturn (SCP); this call never returns. */ + "ret"); + +asm ("firewall:\n" + "hlt"); diff --git a/libc/sysdeps/mach/hurd/if_index.c b/libc/sysdeps/mach/hurd/if_index.c new file mode 100644 index 000000000..664a3a1ef --- /dev/null +++ b/libc/sysdeps/mach/hurd/if_index.c @@ -0,0 +1,190 @@ +/* Find network interface names and index numbers. Hurd version. + Copyright (C) 2000,01,02 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 <error.h> +#include <net/if.h> +#include <string.h> +#include <sys/ioctl.h> +#include <unistd.h> + +#include <hurd.h> +#include <hurd/ioctl.h> +#include <hurd/pfinet.h> + +/* Return the interface index corresponding to interface IFNAME. + On error, return 0. */ +unsigned int +if_nametoindex (const char *ifname) +{ + struct ifreq ifr; + int fd = __opensock (); + + if (fd < 0) + return 0; + + strncpy (ifr.ifr_name, ifname, IFNAMSIZ); + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; + __close (fd); + if (saved_errno == EINVAL || saved_errno == ENOTTY) + __set_errno (ENOSYS); + return 0; + } + __close (fd); + return ifr.ifr_ifindex; +} +libc_hidden_def (if_nametoindex) + +/* Free the structure IFN returned by if_nameindex. */ +void +if_freenameindex (struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + if (ptr->if_name) + free (ptr->if_name); + ++ptr; + } + free (ifn); +} + +/* Return an array of if_nameindex structures, one for each network + interface present, plus one indicating the end of the array. On + error, return NULL. */ +struct if_nameindex * +if_nameindex (void) +{ + error_t err = 0; + char data[2048]; + file_t server; + int fd = __opensock (); + struct ifconf ifc; + unsigned int nifs, i; + struct if_nameindex *idx = NULL; + + ifc.ifc_buf = data; + + if (fd < 0) + return NULL; + + server = _hurd_socket_server (PF_INET, 0); + if (server == MACH_PORT_NULL) + nifs = 0; + else + { + size_t len = sizeof data; + err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len); + if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED) + { + /* On the first use of the socket server during the operation, + allow for the old server port dying. */ + server = _hurd_socket_server (PF_INET, 1); + if (server == MACH_PORT_NULL) + goto out; + err = __pfinet_siocgifconf (server, -1, &ifc.ifc_buf, &len); + } + if (err) + goto out; + + ifc.ifc_len = len; + nifs = len / sizeof (struct ifreq); + } + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + err = ENOBUFS; + goto out; + } + + for (i = 0; i < nifs; ++i) + { + struct ifreq *ifr = &ifc.ifc_req[i]; + idx[i].if_name = __strdup (ifr->ifr_name); + if (idx[i].if_name == NULL + || __ioctl (fd, SIOCGIFINDEX, ifr) < 0) + { + unsigned int j; + err = errno; + + for (j = 0; j < i; ++j) + free (idx[j].if_name); + free (idx); + idx = NULL; + + if (err == EINVAL) + err = ENOSYS; + else if (err == ENOMEM) + err = ENOBUFS; + goto out; + } + idx[i].if_index = ifr->ifr_ifindex; + } + + idx[i].if_index = 0; + idx[i].if_name = NULL; + + out: + __close (fd); + if (data != ifc.ifc_buf) + __vm_deallocate (__mach_task_self (), (vm_address_t) ifc.ifc_buf, + ifc.ifc_len); + __set_errno (err); + return idx; +} + +/* Store the name of the interface corresponding to index IFINDEX in + IFNAME (which has space for at least IFNAMSIZ characters). Return + IFNAME, or NULL on error. */ +char * +if_indextoname (unsigned int ifindex, char *ifname) +{ + struct ifreq ifr; + int fd = __opensock (); + + if (fd < 0) + return NULL; + + ifr.ifr_ifindex = ifindex; + if (__ioctl (fd, SIOCGIFNAME, &ifr) < 0) + { + int saved_errno = errno; + __close (fd); + if (saved_errno == EINVAL || saved_errno == ENOTTY) + __set_errno (ENOSYS); + else if (saved_errno == ENODEV) + __set_errno (ENXIO); + return NULL; + } + __close (fd); + return strncpy (ifname, ifr.ifr_name, IFNAMSIZ); +} +libc_hidden_def (if_indextoname) + +#if 0 +void +internal_function +__protocol_available (int *have_inet, int *have_inet6) +{ + *have_inet = _hurd_socket_server (PF_INET, 0) != MACH_PORT_NULL; + *have_inet6 = _hurd_socket_server (PF_INET6, 0) != MACH_PORT_NULL; +} +#endif diff --git a/libc/sysdeps/mach/hurd/ifreq.c b/libc/sysdeps/mach/hurd/ifreq.c new file mode 100644 index 000000000..9da8a6803 --- /dev/null +++ b/libc/sysdeps/mach/hurd/ifreq.c @@ -0,0 +1,65 @@ +/* Fetch the host's network interface list. Hurd version. + Copyright (C) 2002,2005 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 <ifreq.h> +#include <hurd.h> +#include <hurd/pfinet.h> +#include <sys/mman.h> + + +void +__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd) +{ + file_t server; + + server = _hurd_socket_server (PF_INET, 0); + if (server == MACH_PORT_NULL) + { + out: + *num_ifs = 0; + *ifreqs = NULL; + } + else + { + char *data = NULL; + size_t len = 0; + error_t err = __pfinet_siocgifconf (server, -1, &data, &len); + if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED) + { + /* On the first use of the socket server during the operation, + allow for the old server port dying. */ + server = _hurd_socket_server (PF_INET, 1); + if (server == MACH_PORT_NULL) + goto out; + err = __pfinet_siocgifconf (server, -1, (data_t *) ifreqs, &len); + } + if (err) + goto out; + + if (len % sizeof (struct ifreq) != 0) + { + munmap (data, len); + errno = EGRATUITOUS; + goto out; + } + *num_ifs = len / sizeof (struct ifreq); + *ifreqs = (struct ifreq *) data; + } + +} diff --git a/libc/sysdeps/mach/hurd/init-posix.c b/libc/sysdeps/mach/hurd/init-posix.c new file mode 100644 index 000000000..eaf6332fe --- /dev/null +++ b/libc/sysdeps/mach/hurd/init-posix.c @@ -0,0 +1,2 @@ +/* We don't need the unix/bsd version. */ +#include <posix/init-posix.c> diff --git a/libc/sysdeps/mach/hurd/ioctl.c b/libc/sysdeps/mach/hurd/ioctl.c new file mode 100644 index 000000000..bcc78bc84 --- /dev/null +++ b/libc/sysdeps/mach/hurd/ioctl.c @@ -0,0 +1,324 @@ +/* Copyright (C) 1992,93,94,95,96,97,99,2000,2002,2005 + 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/ioctl.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/signal.h> +#include <stdarg.h> +#include <mach/notify.h> +#include <assert.h> +#include <string.h> +#include <stdint.h> +#include <hurd/ioctl.h> +#include <mach/mig_support.h> + +#include <hurd/ioctls.defs> + +#define typesize(type) (1 << (type)) + + +/* Perform the I/O control operation specified by REQUEST on FD. + The actual type and use of ARG and the return value depend on REQUEST. */ +int +__ioctl (int fd, unsigned long int request, ...) +{ +#ifdef MACH_MSG_TYPE_CHAR + /* Map individual type fields to Mach IPC types. */ + static const int mach_types[] = + { MACH_MSG_TYPE_CHAR, MACH_MSG_TYPE_INTEGER_16, MACH_MSG_TYPE_INTEGER_32, + MACH_MSG_TYPE_INTEGER_64 }; +#define io2mach_type(count, type) \ + ((mach_msg_type_t) { mach_types[type], typesize (type) * 8, count, 1, 0, 0 }) +#endif + + /* Extract the type information encoded in the request. */ + unsigned int type = _IOC_TYPE (request); + + /* Message buffer. */ +#define msg_align(x) \ + (((x) + sizeof (mach_msg_type_t) - 1) & ~(sizeof (mach_msg_type_t) - 1)) + struct + { +#ifdef MACH_MSG_TYPE_BIT + union + { + mig_reply_header_t header; + struct + { + mach_msg_header_t Head; + int RetCodeType; + kern_return_t RetCode; + } header_typecheck; + }; + char data[3 * sizeof (mach_msg_type_t) + + msg_align (_IOT_COUNT0 (type) * typesize (_IOT_TYPE0 (type))) + + msg_align (_IOT_COUNT1 (type) * typesize (_IOT_TYPE1 (type))) + + _IOT_COUNT2 (type) * typesize (_IOT_TYPE2 (type))]; +#else /* Untyped Mach IPC format. */ + mig_reply_error_t header; + char data[_IOT_COUNT0 (type) * typesize (_IOT_TYPE0 (type)) + + _IOT_COUNT1 (type) * typesize (_IOT_TYPE1 (type)) + + _IOT_COUNT2 (type) * typesize (_IOT_TYPE2 (type))]; + mach_msg_trailer_t trailer; +#endif + } msg; + mach_msg_header_t *const m = &msg.header.Head; + mach_msg_id_t msgid; + unsigned int reply_size; +#ifdef MACH_MSG_TYPE_BIT + mach_msg_type_t *t; +#else + void *p; +#endif + + void *arg; + + error_t err; + + /* Send the RPC already packed up in MSG to IOPORT + and decode the return value. */ + error_t send_rpc (io_t ioport) + { + error_t err; +#ifdef MACH_MSG_TYPE_BIT + mach_msg_type_t *t = &msg.header.RetCodeType; +#else + void *p = &msg.header.RetCode; +#endif + + /* Marshal the request arguments into the message buffer. + We must redo this work each time we retry the RPC after a SIGTTOU, + because the reply message containing the EBACKGROUND error code + clobbers the same message buffer also used for the request. */ + + if (_IOC_INOUT (request) & IOC_IN) + { + /* We don't want to advance ARG since it will be used to copy out + too if IOC_OUT is also set. */ + void *argptr = arg; + + /* Pack an argument into the message buffer. */ + void in (unsigned int count, enum __ioctl_datum type) + { + if (count > 0) + { + const size_t len = count * typesize ((unsigned int) type); +#ifdef MACH_MSG_TYPE_BIT + void *p = &t[1]; + *t = io2mach_type (count, type); + p = __mempcpy (p, argptr, len); + p = (void *) (((uintptr_t) p + sizeof (*t) - 1) + & ~(sizeof (*t) - 1)); + t = p; +#else + p = __mempcpy (p, argptr, len); +#endif + argptr += len; + } + } + + /* Pack the argument data. */ + in (_IOT_COUNT0 (type), _IOT_TYPE0 (type)); + in (_IOT_COUNT1 (type), _IOT_TYPE1 (type)); + in (_IOT_COUNT2 (type), _IOT_TYPE2 (type)); + } + else if (_IOC_INOUT (request) == IOC_VOID) + { + /* The RPC takes a single integer_t argument. + Rather than pointing to the value, ARG is the value itself. */ +#ifdef MACH_MSG_TYPE_BIT + *t++ = io2mach_type (1, _IOTS (integer_t)); + *(integer_t *) t = (integer_t) arg; + t = (void *) t + sizeof (integer_t); +#else + *(integer_t *) p = (integer_t) arg; + p = (void *) p + sizeof (integer_t); +#endif + } + + memset (m, 0, sizeof *m); /* Clear unused fields. */ + m->msgh_size = ( +#ifdef MACH_MSG_TYPE_BIT + (char *) t +#else + (char *) p +#endif + - (char *) &msg); + m->msgh_remote_port = ioport; + m->msgh_local_port = __mig_get_reply_port (); + m->msgh_id = msgid; + m->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, + MACH_MSG_TYPE_MAKE_SEND_ONCE); + err = _hurd_intr_rpc_mach_msg (m, MACH_SEND_MSG|MACH_RCV_MSG, + m->msgh_size, sizeof (msg), + m->msgh_local_port, + MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + switch (err) + { + case MACH_MSG_SUCCESS: + break; + case MACH_SEND_INVALID_REPLY: + case MACH_RCV_INVALID_NAME: + __mig_dealloc_reply_port (m->msgh_local_port); + default: + return err; + } + + if ((m->msgh_bits & MACH_MSGH_BITS_COMPLEX)) + { + /* Allow no ports or VM. */ + __mach_msg_destroy (m); + /* Want to return a different error below for a different msgid. */ + if (m->msgh_id == msgid + 100) + return MIG_TYPE_ERROR; + } + + if (m->msgh_id != msgid + 100) + return (m->msgh_id == MACH_NOTIFY_SEND_ONCE ? + MIG_SERVER_DIED : MIG_REPLY_MISMATCH); + + if (m->msgh_size != reply_size && + m->msgh_size != sizeof msg.header) + return MIG_TYPE_ERROR; + +#ifdef MACH_MSG_TYPE_BIT + if (msg.header_typecheck.RetCodeType != + ((union { mach_msg_type_t t; int i; }) + { t: io2mach_type (1, _IOTS (msg.header.RetCode)) }).i) + return MIG_TYPE_ERROR; +#endif + return msg.header.RetCode; + } + + va_list ap; + + va_start (ap, request); + arg = va_arg (ap, void *); + va_end (ap); + + { + /* Check for a registered handler for REQUEST. */ + ioctl_handler_t handler = _hurd_lookup_ioctl_handler (request); + if (handler) + { + /* This handler groks REQUEST. Se lo puntamonos. */ + int save = errno; + int result = (*handler) (fd, request, arg); + if (result != -1 || errno != ENOTTY) + return result; + + /* The handler doesn't really grok this one. + Try the normal RPC translation. */ + errno = save; + } + } + + /* Compute the Mach message ID for the RPC from the group and command + parts of the ioctl request. */ + msgid = IOC_MSGID (request); + + /* Compute the expected size of the reply. There is a standard header + consisting of the message header and the reply code. Then, for out + and in/out ioctls, there come the data with their type headers. */ + reply_size = sizeof msg.header; + + if (_IOC_INOUT (request) & IOC_OUT) + { + inline void figure_reply (unsigned int count, enum __ioctl_datum type) + { + if (count > 0) + { +#ifdef MACH_MSG_TYPE_BIT + /* Add the size of the type and data. */ + reply_size += sizeof (mach_msg_type_t) + typesize (type) * count; + /* Align it to word size. */ + reply_size += sizeof (mach_msg_type_t) - 1; + reply_size &= ~(sizeof (mach_msg_type_t) - 1); +#else + reply_size += typesize (type) * count; +#endif + } + } + figure_reply (_IOT_COUNT0 (type), _IOT_TYPE0 (type)); + figure_reply (_IOT_COUNT1 (type), _IOT_TYPE1 (type)); + figure_reply (_IOT_COUNT2 (type), _IOT_TYPE2 (type)); + } + + /* Marshal the arguments into the request message and make the RPC. + This wrapper function handles EBACKGROUND returns, turning them + into either SIGTTOU or EIO. */ + err = HURD_DPORT_USE (fd, _hurd_ctty_output (port, ctty, send_rpc)); + +#ifdef MACH_MSG_TYPE_BIT + t = (mach_msg_type_t *) msg.data; +#else + p = (void *) msg.data; +#endif + switch (err) + { + /* Unpack the message buffer into the argument location. */ + int out (unsigned int count, unsigned int type, + void *store, void **update) + { + if (count > 0) + { + const size_t len = count * typesize (type); +#ifdef MACH_MSG_TYPE_BIT + union { mach_msg_type_t t; int i; } ipctype; + ipctype.t = io2mach_type (count, type); + if (*(int *) t != ipctype.i) + return 1; + ++t; + memcpy (store, t, len); + if (update != NULL) + *update += len; + t = (void *) (((uintptr_t) t + len + sizeof (*t) - 1) + & ~(sizeof (*t) - 1)); +#else + memcpy (store, p, len); + p += len; + if (update != NULL) + *update += len; +#endif + } + return 0; + } + + case 0: + if (m->msgh_size != reply_size || + ((_IOC_INOUT (request) & IOC_OUT) && + (out (_IOT_COUNT0 (type), _IOT_TYPE0 (type), arg, &arg) || + out (_IOT_COUNT1 (type), _IOT_TYPE1 (type), arg, &arg) || + out (_IOT_COUNT2 (type), _IOT_TYPE2 (type), arg, &arg)))) + return __hurd_fail (MIG_TYPE_ERROR); + return 0; + + case MIG_BAD_ID: + case EOPNOTSUPP: + /* The server didn't understand the RPC. */ + err = ENOTTY; + default: + return __hurd_fail (err); + } +} + +weak_alias (__ioctl, ioctl) diff --git a/libc/sysdeps/mach/hurd/isatty.c b/libc/sysdeps/mach/hurd/isatty.c new file mode 100644 index 000000000..faf498038 --- /dev/null +++ b/libc/sysdeps/mach/hurd/isatty.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1994, 1995, 1997 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 <unistd.h> +#include <hurd/fd.h> +#include <hurd/term.h> + +/* Return 1 if FD is a terminal, 0 if not. */ +int +__isatty (fd) + int fd; +{ + error_t err; + mach_port_t id; + + err = HURD_DPORT_USE (fd, __term_getctty (port, &id)); + if (! err) + __mach_port_deallocate (__mach_task_self (), id); + + return !err; +} + +weak_alias (__isatty, isatty) diff --git a/libc/sysdeps/mach/hurd/jmp-unwind.c b/libc/sysdeps/mach/hurd/jmp-unwind.c new file mode 100644 index 000000000..e0e16e28b --- /dev/null +++ b/libc/sysdeps/mach/hurd/jmp-unwind.c @@ -0,0 +1,80 @@ +/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. Hurd version. + Copyright (C) 1995,1996,2005,2006 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 <jmpbuf-unwind.h> +#include <hurd/userlink.h> +#include <hurd/signal.h> +#include <hurd/sigpreempt.h> +#include <assert.h> +#include <stdint.h> + + +#ifndef _JMPBUF_UNWINDS +#error "<jmpbuf-unwind.h> fails to define _JMPBUF_UNWINDS" +#endif + +static inline uintptr_t +demangle_ptr (uintptr_t x) +{ +# ifdef PTR_DEMANGLE + PTR_DEMANGLE (x); +# endif + return x; +} + +/* This function is called by `longjmp' (with its arguments) to restore + active resources to a sane state before the frames code using them are + jumped out of. */ + +void +_longjmp_unwind (jmp_buf env, int val) +{ + struct hurd_sigstate *ss = _hurd_self_sigstate (); + struct hurd_userlink *link; + + /* 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); + + /* Remove local signal preemptors being unwound past. */ + while (ss->preemptors && + _JMPBUF_UNWINDS (env[0].__jmpbuf, ss->preemptors, demangle_ptr)) + ss->preemptors = ss->preemptors->next; + + __spin_unlock (&ss->lock); + + /* Iterate over the current thread's list of active resources. + Process the head portion of the list whose links reside + in stack frames being unwound by this jump. */ + + for (link = ss->active_resources; + link && _JMPBUF_UNWINDS (env[0].__jmpbuf, link, demangle_ptr); + link = link->thread.next) + /* Remove this link from the resource's users list, + since the frame using the resource is being unwound. + This call returns nonzero if that was the last user. */ + if (_hurd_userlink_unlink (link)) + /* One of the frames being unwound by the longjmp was the last user + of its resource. Call the cleanup function to deallocate it. */ + (*link->cleanup) (link->cleanup_data, env, val); + + _hurd_critical_section_unlock (ss); +} diff --git a/libc/sysdeps/mach/hurd/kill.c b/libc/sysdeps/mach/hurd/kill.c new file mode 100644 index 000000000..a9946e0af --- /dev/null +++ b/libc/sysdeps/mach/hurd/kill.c @@ -0,0 +1,150 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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/types.h> +#include <signal.h> +#include <hurd.h> +#include <hurd/port.h> +#include <hurd/signal.h> +#include <hurd/msg.h> + +/* Send signal SIG to process number PID. If PID is zero, + send SIG to all processes in the current process's process group. + If PID is < -1, send SIG to all processes in process group - PID. */ +int +__kill (pid_t pid, int sig) +{ + int delivered = 0; /* Set when we deliver any signal. */ + error_t err; + mach_port_t proc; + struct hurd_userlink ulink; + + void kill_pid (pid_t pid) /* Kill one PID. */ + { + /* SIGKILL is not delivered as a normal signal. + Sending SIGKILL to a process means to terminate its task. */ + if (sig == SIGKILL) + /* Fetch the process's task port and terminate the task. We + loop in case the process execs and changes its task port. + If the old task port dies after we fetch it but before we + send the RPC, we get MACH_SEND_INVALID_DEST; if it dies + after we send the RPC request but before it is serviced, we + get MIG_SERVER_DIED. */ + do + { + task_t refport; + err = __proc_pid2task (proc, pid, &refport); + /* Ignore zombies. */ + if (!err && refport != MACH_PORT_NULL) + { + err = __task_terminate (refport); + __mach_port_deallocate (__mach_task_self (), refport); + } + } while (err == MACH_SEND_INVALID_DEST || + err == MIG_SERVER_DIED); + else + { + error_t taskerr; + error_t kill_port (mach_port_t msgport, mach_port_t refport) + { + if (msgport != MACH_PORT_NULL) + /* Send a signal message to his message port. */ + return __msg_sig_post (msgport, sig, 0, refport); + + /* The process has no message port. Perhaps try direct + frobnication of the task. */ + + if (taskerr) + /* If we could not get the task port, we can do nothing. */ + return taskerr; + + if (refport == MACH_PORT_NULL) + /* proc_pid2task returned success with a null task port. + That means the process is a zombie. Signals + to zombies should return success and do nothing. */ + return 0; + + /* For user convenience in the case of a task that has + not registered any message port with the proc server, + translate a few signals to direct task operations. */ + switch (sig) + { + /* The only signals that really make sense for an + unregistered task are kill, suspend, and continue. */ + case SIGSTOP: + case SIGTSTP: + return __task_suspend (refport); + case SIGCONT: + return __task_resume (refport); + case SIGTERM: + case SIGQUIT: + case SIGINT: + return __task_terminate (refport); + default: + /* We have full permission to send signals, but there is + no meaningful way to express this signal. */ + return EPERM; + } + } + err = HURD_MSGPORT_RPC (__proc_getmsgport (proc, pid, &msgport), + (taskerr = __proc_pid2task (proc, pid, + &refport)) ? + __proc_getsidport (proc, &refport) : 0, 1, + kill_port (msgport, refport)); + } + if (! err) + delivered = 1; + } + + proc = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink); + + if (pid <= 0) + { + /* Send SIG to each process in pgrp (- PID). */ + pid_t pidbuf[10], *pids = pidbuf; + mach_msg_type_number_t i, npids = sizeof (pidbuf) / sizeof (pidbuf[0]); + + err = __proc_getpgrppids (proc, - pid, &pids, &npids); + if (!err) + { + for (i = 0; i < npids; ++i) + { + kill_pid (pids[i]); + if (err == ESRCH) + /* The process died already. Ignore it. */ + err = 0; + } + if (pids != pidbuf) + __vm_deallocate (__mach_task_self (), + (vm_address_t) pids, npids * sizeof (pids[0])); + } + } + else + kill_pid (pid); + + _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, proc); + + /* If we delivered no signals, but ERR is clear, this must mean that + every kill_pid call failed with ESRCH, meaning all the processes in + the pgrp died between proc_getpgrppids and kill_pid; in that case we + fail with ESRCH. */ + return delivered ? 0 : __hurd_fail (err ?: ESRCH); +} + +weak_alias (__kill, kill) diff --git a/libc/sysdeps/mach/hurd/lchmod.c b/libc/sysdeps/mach/hurd/lchmod.c new file mode 100644 index 000000000..284c2815c --- /dev/null +++ b/libc/sysdeps/mach/hurd/lchmod.c @@ -0,0 +1,39 @@ +/* lchmod -- Change the protections of a file or symbolic link. Hurd version. + Copyright (C) 2002 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 <stddef.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <hurd.h> + +/* Change the protections of FILE to MODE. */ +int +lchmod (const char *file, mode_t mode) +{ + error_t err; + file_t port = __file_name_lookup (file, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chmod (port, mode); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/lchown.c b/libc/sysdeps/mach/hurd/lchown.c new file mode 100644 index 000000000..9795e4b8e --- /dev/null +++ b/libc/sysdeps/mach/hurd/lchown.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 92, 94, 95, 96, 97 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 <stddef.h> +#include <unistd.h> +#include <hurd.h> +#include <fcntl.h> + +/* Change the owner and group of FILE; if it's a link, do the link and + not the target. */ +int +__lchown (file, owner, group) + const char *file; + uid_t owner; + gid_t group; +{ + error_t err; + file_t port = __file_name_lookup (file, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_chown (port, owner, group); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__lchown, lchown) diff --git a/libc/sysdeps/mach/hurd/lgetxattr.c b/libc/sysdeps/mach/hurd/lgetxattr.c new file mode 100644 index 000000000..5ab591575 --- /dev/null +++ b/libc/sysdeps/mach/hurd/lgetxattr.c @@ -0,0 +1,36 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2004 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> +#include <fcntl.h> + +ssize_t +lgetxattr (const char *path, const char *name, void *value, size_t size) +{ + error_t err; + file_t port = __file_name_lookup (path, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + err = _hurd_xattr_get (port, name, value, &size); + __mach_port_deallocate (__mach_task_self (), port); + return err ? __hurd_fail (err) : size; +} diff --git a/libc/sysdeps/mach/hurd/libc-ldscript b/libc/sysdeps/mach/hurd/libc-ldscript new file mode 100644 index 000000000..499a2b2b9 --- /dev/null +++ b/libc/sysdeps/mach/hurd/libc-ldscript @@ -0,0 +1,6 @@ +/* GNU ld script + This linker script is installed as /lib/libc.a. + It makes -lc become just like -( -lcrt -lmachuser -lhurduser -). + */ + +GROUP ( libcrt.a libmachuser.a libhurduser.a ) diff --git a/libc/sysdeps/mach/hurd/libc_p-ldscript b/libc/sysdeps/mach/hurd/libc_p-ldscript new file mode 100644 index 000000000..7dcd52eec --- /dev/null +++ b/libc/sysdeps/mach/hurd/libc_p-ldscript @@ -0,0 +1,6 @@ +/* GNU ld script + This linker script is installed as /lib/libc_p.a. + It makes -lc_p become just like -( -lcrt_p -lmachuser_p -lhurduser_p -). + */ + +GROUP ( libcrt_p.a libmachuser_p.a libhurduser_p.a ) diff --git a/libc/sysdeps/mach/hurd/link.c b/libc/sysdeps/mach/hurd/link.c new file mode 100644 index 000000000..f97d7bdfd --- /dev/null +++ b/libc/sysdeps/mach/hurd/link.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 <stddef.h> +#include <unistd.h> +#include <hurd.h> + +/* Make a link to FROM called TO. */ +int +__link (from, to) + const char *from; + const char *to; +{ + error_t err; + file_t oldfile, linknode, todir; + char *toname; + + oldfile = __file_name_lookup (from, 0, 0); + if (oldfile == MACH_PORT_NULL) + return -1; + + /* The file_getlinknode RPC returns the port that should be passed to + the receiving filesystem (the one containing TODIR) in dir_link. */ + + err = __file_getlinknode (oldfile, &linknode); + __mach_port_deallocate (__mach_task_self (), oldfile); + if (err) + return __hurd_fail (err); + + todir = __file_name_split (to, &toname); + if (todir != MACH_PORT_NULL) + { + err = __dir_link (todir, linknode, toname, 1); + __mach_port_deallocate (__mach_task_self (), todir); + } + __mach_port_deallocate (__mach_task_self (), linknode); + if (todir == MACH_PORT_NULL) + return -1; + + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__link, link) diff --git a/libc/sysdeps/mach/hurd/linkat.c b/libc/sysdeps/mach/hurd/linkat.c new file mode 100644 index 000000000..1942144e0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/linkat.c @@ -0,0 +1,66 @@ +/* Make a link between file names relative to open directories. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + + +/* Make a link to FROM relative to FROMFD called TO relative to TOFD. */ +int +linkat (fromfd, from, tofd, to, flags) + int fromfd; + const char *from; + int tofd; + const char *to; + int flags; +{ + error_t err; + file_t oldfile, linknode, todir; + char *toname; + + oldfile = __file_name_lookup_at (fromfd, flags, from, 0, 0); + if (oldfile == MACH_PORT_NULL) + return -1; + + /* The file_getlinknode RPC returns the port that should be passed to + the receiving filesystem (the one containing TODIR) in dir_link. */ + + err = __file_getlinknode (oldfile, &linknode); + __mach_port_deallocate (__mach_task_self (), oldfile); + if (err) + return __hurd_fail (err); + + todir = __file_name_split_at (tofd, to, &toname); + if (todir != MACH_PORT_NULL) + { + err = __dir_link (todir, linknode, toname, 1); + __mach_port_deallocate (__mach_task_self (), todir); + } + __mach_port_deallocate (__mach_task_self (), linknode); + if (todir == MACH_PORT_NULL) + return -1; + + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/listen.c b/libc/sysdeps/mach/hurd/listen.c new file mode 100644 index 000000000..8ee2650be --- /dev/null +++ b/libc/sysdeps/mach/hurd/listen.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1992, 1994, 1997, 2001, 2002 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 <hurd.h> +#include <hurd/fd.h> +#include <sys/socket.h> +#include <hurd/socket.h> + +/* Prepare to accept connections on socket FD. + N connection requests will be queued before further requests are refused. + Returns 0 on success, -1 for errors. */ + +int +__listen (fd, n) + int fd; + int n; +{ + error_t err = HURD_DPORT_USE (fd, __socket_listen (port, n)); + if (err) + return __hurd_dfail (fd, err); + return 0; +} + +weak_alias (__listen, listen) diff --git a/libc/sysdeps/mach/hurd/listxattr.c b/libc/sysdeps/mach/hurd/listxattr.c new file mode 100644 index 000000000..5f84e8831 --- /dev/null +++ b/libc/sysdeps/mach/hurd/listxattr.c @@ -0,0 +1,35 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2005 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> + +ssize_t +listxattr (const char *path, char *list, size_t size) +{ + error_t err; + file_t port = __file_name_lookup (path, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = _hurd_xattr_list (port, list, &size); + __mach_port_deallocate (__mach_task_self (), port); + return err ? __hurd_fail (err) : size; +} diff --git a/libc/sysdeps/mach/hurd/lseek.c b/libc/sysdeps/mach/hurd/lseek.c new file mode 100644 index 000000000..e4b70b3fa --- /dev/null +++ b/libc/sysdeps/mach/hurd/lseek.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991,92,93,94,95,97,2000,02 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 <unistd.h> +#include <sys/types.h> + +/* Seek to OFFSET on FD, starting from WHENCE. */ +off_t +__libc_lseek (int fd, off_t offset, int whence) +{ + return __libc_lseek64 (fd, (off64_t) offset, whence); +} + +weak_alias (__libc_lseek, __lseek) +libc_hidden_def (__lseek) +weak_alias (__libc_lseek, lseek) diff --git a/libc/sysdeps/mach/hurd/lseek64.c b/libc/sysdeps/mach/hurd/lseek64.c new file mode 100644 index 000000000..0345d38f0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/lseek64.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2000,02 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 <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Seek to OFFSET on FD, starting from WHENCE. */ +off64_t +__libc_lseek64 (int fd, off64_t offset, int whence) +{ + error_t err; + if (err = HURD_DPORT_USE (fd, __io_seek (port, offset, whence, &offset))) + return __hurd_dfail (fd, err); + return offset; +} + +weak_alias (__libc_lseek64, __lseek64) +weak_alias (__libc_lseek64, lseek64) diff --git a/libc/sysdeps/mach/hurd/lsetxattr.c b/libc/sysdeps/mach/hurd/lsetxattr.c new file mode 100644 index 000000000..c2eae40e3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/lsetxattr.c @@ -0,0 +1,37 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2004 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> +#include <fcntl.h> + +ssize_t +lsetxattr (const char *path, const char *name, const void *value, size_t size, + int flags) +{ + error_t err; + file_t port = __file_name_lookup (path, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + err = _hurd_xattr_set (port, name, value, size, flags); + __mach_port_deallocate (__mach_task_self (), port); + return err ? __hurd_fail (err) : size; +} diff --git a/libc/sysdeps/mach/hurd/lutimes.c b/libc/sysdeps/mach/hurd/lutimes.c new file mode 100644 index 000000000..cf89d8862 --- /dev/null +++ b/libc/sysdeps/mach/hurd/lutimes.c @@ -0,0 +1,53 @@ +/* lutimes -- change access and modification times of a symlink. Hurd version. + Copyright (C) 2002 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 <sys/time.h> +#include <errno.h> +#include <stddef.h> +#include <hurd.h> +#include <fcntl.h> + +/* Change the access time of FILE to TVP[0] and + the modification time of FILE to TVP[1]. */ +int +__lutimes (const char *file, const struct timeval tvp[2]) +{ + struct timeval timevals[2]; + error_t err; + file_t port; + + if (tvp == NULL) + { + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + timevals[1].tv_usec = timevals[0].tv_usec = (time_t)-1; + tvp = timevals; + } + + port = __file_name_lookup (file, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_utimes (port, + *(time_value_t *) &tvp[0], *(time_value_t *) &tvp[1]); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} +weak_alias (__lutimes, lutimes) diff --git a/libc/sysdeps/mach/hurd/lxstat.c b/libc/sysdeps/mach/hurd/lxstat.c new file mode 100644 index 000000000..d6d12798e --- /dev/null +++ b/libc/sysdeps/mach/hurd/lxstat.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1992,93,94,95,96,97,2002 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/stat.h> +#include <stddef.h> + +#include "xstatconv.c" + +int +__lxstat (int vers, const char *file, struct stat *buf) +{ + struct stat64 buf64; + return __lxstat64 (vers, file, &buf64) ?: xstat64_conv (buf, &buf64); +} +hidden_def (__lxstat) +weak_alias (__lxstat, _lxstat) diff --git a/libc/sysdeps/mach/hurd/lxstat64.c b/libc/sysdeps/mach/hurd/lxstat64.c new file mode 100644 index 000000000..a53f6921e --- /dev/null +++ b/libc/sysdeps/mach/hurd/lxstat64.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2000,02 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 <stddef.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <hurd.h> + +/* Get information about the file descriptor FD in BUF. */ +int +__lxstat64 (int vers, const char *file, struct stat64 *buf) +{ + error_t err; + file_t port; + + if (vers != _STAT_VER) + return __hurd_fail (EINVAL); + + port = __file_name_lookup (file, O_NOLINK, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __io_stat (port, buf); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} +hidden_def (__lxstat64) diff --git a/libc/sysdeps/mach/hurd/malloc-machine.h b/libc/sysdeps/mach/hurd/malloc-machine.h new file mode 100644 index 000000000..70aaf11b8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/malloc-machine.h @@ -0,0 +1,68 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + Copyright (C) 2003 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 _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include <atomic.h> +#include <bits/libc-lock.h> + +/* Assume hurd, with cthreads */ + +/* Cthreads `mutex_t' is a pointer to a mutex, and malloc wants just the + mutex itself. */ +#undef mutex_t +#define mutex_t struct mutex + +#undef mutex_init +#define mutex_init(m) (__mutex_init(m), 0) + +#undef mutex_lock +#define mutex_lock(m) (__mutex_lock(m), 0) + +#undef mutex_unlock +#define mutex_unlock(m) (__mutex_unlock(m), 0) + +#define mutex_trylock(m) (!__mutex_trylock(m)) + +#define thread_atfork(prepare, parent, child) do {} while(0) +#define thread_atfork_static(prepare, parent, child) \ + text_set_element(_hurd_fork_prepare_hook, prepare); \ + text_set_element(_hurd_fork_parent_hook, parent); \ + text_set_element(_hurd_fork_child_hook, child); + +/* No we're *not* using pthreads. */ +#define __pthread_initialize ((void (*)(void))0) + +/* thread specific data for glibc */ + +#include <bits/libc-tsd.h> + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include <sysdeps/generic/malloc-machine.h> + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/libc/sysdeps/mach/hurd/mig-reply.c b/libc/sysdeps/mach/hurd/mig-reply.c new file mode 100644 index 000000000..5e40c147b --- /dev/null +++ b/libc/sysdeps/mach/hurd/mig-reply.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1994,1995,1996,1997,2005 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 <mach.h> +#include <hurd/threadvar.h> + +#define GETPORT \ + mach_port_t *portloc = \ + (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY) +#define reply_port (*(use_threadvar ? portloc : &global_reply_port)) + +static int use_threadvar; +static mach_port_t global_reply_port; + +/* These functions are called by MiG-generated code. */ + +/* Called by MiG to get a reply port. */ +mach_port_t +__mig_get_reply_port (void) +{ + GETPORT; + + if (reply_port == MACH_PORT_NULL) + reply_port = __mach_reply_port (); + + return reply_port; +} +weak_alias (__mig_get_reply_port, mig_get_reply_port) + +/* Called by MiG to deallocate the reply port. */ +void +__mig_dealloc_reply_port (mach_port_t arg) +{ + mach_port_t port; + + GETPORT; + + port = reply_port; + reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */ + + if (MACH_PORT_VALID (port)) + __mach_port_mod_refs (__mach_task_self (), port, + MACH_PORT_RIGHT_RECEIVE, -1); +} +weak_alias (__mig_dealloc_reply_port, mig_dealloc_reply_port) + +/* Called by mig interfaces when done with a port. Used to provide the + same interface as needed when a custom allocator is used. */ +void +__mig_put_reply_port(mach_port_t port) +{ + /* Do nothing. */ +} +weak_alias (__mig_put_reply_port, mig_put_reply_port) + +/* Called at startup with STACK == NULL. When per-thread variables are set + up, this is called again with STACK set to the new stack being switched + to, where per-thread variables should be set up. */ +void +__mig_init (void *stack) +{ + use_threadvar = stack != 0; + + if (use_threadvar) + { + /* Recycle the reply port used before multithreading was enabled. */ + mach_port_t *portloc = (mach_port_t *) + __hurd_threadvar_location_from_sp (_HURD_THREADVAR_MIG_REPLY, stack); + *portloc = global_reply_port; + global_reply_port = MACH_PORT_NULL; + } +} +weak_alias (__mig_init, mig_init) diff --git a/libc/sysdeps/mach/hurd/mkdir.c b/libc/sysdeps/mach/hurd/mkdir.c new file mode 100644 index 000000000..b7e80748f --- /dev/null +++ b/libc/sysdeps/mach/hurd/mkdir.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991,93,94,95,96,97,2002 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> + +/* Create a directory named FILE_NAME with protections MODE. */ +int +__mkdir (file_name, mode) + const char *file_name; + mode_t mode; +{ + error_t err; + const char *name; + file_t parent = __directory_name_split (file_name, (char **) &name); + if (parent == MACH_PORT_NULL) + return -1; + err = __dir_mkdir (parent, name, mode & ~_hurd_umask); + __mach_port_deallocate (__mach_task_self (), parent); + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__mkdir, mkdir) diff --git a/libc/sysdeps/mach/hurd/mkdirat.c b/libc/sysdeps/mach/hurd/mkdirat.c new file mode 100644 index 000000000..321d59f2f --- /dev/null +++ b/libc/sysdeps/mach/hurd/mkdirat.c @@ -0,0 +1,42 @@ +/* Create a directory named relative to another open directory. Hurd version. + Copyright (C) 1991,1993,1994,1995,1996,1997,2002,2006 + 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> + +int +mkdirat (fd, path, mode) + int fd; + const char *path; + mode_t mode; +{ + error_t err; + const char *name; + file_t parent = __directory_name_split (path, (char **) &name); + if (parent == MACH_PORT_NULL) + return -1; + err = __dir_mkdir (parent, name, mode & ~_hurd_umask); + __mach_port_deallocate (__mach_task_self (), parent); + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/mlock.c b/libc/sysdeps/mach/hurd/mlock.c new file mode 100644 index 000000000..bb96c9c07 --- /dev/null +++ b/libc/sysdeps/mach/hurd/mlock.c @@ -0,0 +1,47 @@ +/* mlock -- guarantee pages are resident in memory. Mach/Hurd version. + Copyright (C) 2001 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 <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <hurd.h> +#include <mach/mach_host.h> + +/* Guarantee all whole pages mapped by the range [ADDR,ADDR+LEN) to + be memory resident. */ + +int +mlock (const void *addr, size_t len) +{ + mach_port_t hostpriv; + vm_address_t page; + error_t err; + + err = __get_privileged_ports (&hostpriv, NULL); + if (err) + return __hurd_fail (EPERM); + + 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_ALL); /* XXX ? */ + __mach_port_deallocate (__mach_task_self (), hostpriv); + + return err ? __hurd_fail (err) : 0; +} diff --git a/libc/sysdeps/mach/hurd/mmap.c b/libc/sysdeps/mach/hurd/mmap.c new file mode 100644 index 000000000..1d1460cea --- /dev/null +++ b/libc/sysdeps/mach/hurd/mmap.c @@ -0,0 +1,168 @@ +/* Copyright (C) 1994,1995,1996,1997,1999,2002,2003,2004 + 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 <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <hurd.h> +#include <hurd/fd.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 (__ptr_t) -1 + for errors (in which case `errno' is set). A successful `mmap' call + deallocates any previous mapping for the affected region. */ + +__ptr_t +__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset) +{ + error_t err; + vm_prot_t vmprot; + memory_object_t memobj; + vm_address_t mapaddr; + + mapaddr = (vm_address_t) addr; + + /* ADDR and OFFSET must be page-aligned. */ + if ((mapaddr & (vm_page_size - 1)) || (offset & (vm_page_size - 1))) + return (__ptr_t) (long int) __hurd_fail (EINVAL); + + if ((flags & (MAP_TYPE|MAP_INHERIT)) == MAP_ANON + && prot == (PROT_READ|PROT_WRITE)) /* cf VM_PROT_DEFAULT */ + { + /* vm_allocate has (a little) less overhead in the kernel too. */ + err = __vm_allocate (__mach_task_self (), &mapaddr, len, + !(flags & MAP_FIXED)); + + if (err == KERN_NO_SPACE && (flags & MAP_FIXED)) + { + /* XXX this is not atomic as it is in unix! */ + /* The region is already allocated; deallocate it first. */ + err = __vm_deallocate (__mach_task_self (), mapaddr, len); + if (!err) + err = __vm_allocate (__mach_task_self (), &mapaddr, len, 0); + } + + return err ? (__ptr_t) (long int) __hurd_fail (err) : (__ptr_t) mapaddr; + } + + vmprot = VM_PROT_NONE; + if (prot & PROT_READ) + vmprot |= VM_PROT_READ; + if (prot & PROT_WRITE) + vmprot |= VM_PROT_WRITE; + if (prot & PROT_EXEC) + vmprot |= VM_PROT_EXECUTE; + + switch (flags & MAP_TYPE) + { + default: + return (__ptr_t) (long int) __hurd_fail (EINVAL); + + case MAP_ANON: + memobj = MACH_PORT_NULL; + break; + + case MAP_FILE: + case 0: /* Allow, e.g., just MAP_SHARED. */ + { + mach_port_t robj, wobj; + if (err = HURD_DPORT_USE (fd, __io_map (port, &robj, &wobj))) + { + if (err == MIG_BAD_ID || err == EOPNOTSUPP || err == ENOSYS) + err = ENODEV; /* File descriptor doesn't support mmap. */ + return (__ptr_t) (long int) __hurd_dfail (fd, err); + } + switch (prot & (PROT_READ|PROT_WRITE)) + { + case PROT_READ: + memobj = robj; + if (wobj != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), wobj); + break; + case PROT_WRITE: + memobj = wobj; + if (robj != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), robj); + break; + case PROT_READ|PROT_WRITE: + if (robj == wobj) + { + memobj = wobj; + /* Remove extra reference. */ + __mach_port_deallocate (__mach_task_self (), memobj); + } + else if (wobj == MACH_PORT_NULL && /* Not writable by mapping. */ + !(flags & MAP_SHARED)) + /* The file can only be mapped for reading. Since we are + making a private mapping, we will never try to write the + object anyway, so we don't care. */ + memobj = robj; + else + { + __mach_port_deallocate (__mach_task_self (), wobj); + return (__ptr_t) (long int) __hurd_fail (EACCES); + } + break; + default: /* impossible */ + return 0; + } + break; + /* XXX handle MAP_NOEXTEND */ + } + } + + /* XXX handle MAP_INHERIT */ + + err = __vm_map (__mach_task_self (), + &mapaddr, (vm_size_t) len, (vm_address_t) 0, + ! (flags & MAP_FIXED), + memobj, (vm_offset_t) offset, + ! (flags & MAP_SHARED), + vmprot, VM_PROT_ALL, + (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY); + + if (err == KERN_NO_SPACE && (flags & MAP_FIXED)) + { + /* XXX this is not atomic as it is in unix! */ + /* The region is already allocated; deallocate it first. */ + err = __vm_deallocate (__mach_task_self (), mapaddr, len); + if (! err) + err = __vm_map (__mach_task_self (), + &mapaddr, (vm_size_t) len, (vm_address_t) 0, + 0, memobj, (vm_offset_t) offset, + ! (flags & MAP_SHARED), + vmprot, VM_PROT_ALL, + (flags & MAP_SHARED) ? VM_INHERIT_SHARE + : VM_INHERIT_COPY); + } + + if (memobj != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), memobj); + + if (err) + return (__ptr_t) (long int) __hurd_fail (err); + + return (__ptr_t) mapaddr; +} + +weak_alias (__mmap, mmap) diff --git a/libc/sysdeps/mach/hurd/munlock.c b/libc/sysdeps/mach/hurd/munlock.c new file mode 100644 index 000000000..8753006b6 --- /dev/null +++ b/libc/sysdeps/mach/hurd/munlock.c @@ -0,0 +1,45 @@ +/* munlock -- undo the effects of prior mlock calls. Mach/Hurd version. + Copyright (C) 2001 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 <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <hurd.h> +#include <mach/mach_host.h> + +/* Undo the effects on these whole pages of any prior mlock calls. */ + +int +munlock (const void *addr, size_t len) +{ + mach_port_t hostpriv; + vm_address_t page; + error_t err; + + err = __get_privileged_ports (&hostpriv, NULL); + if (err) + return __hurd_fail (EPERM); + + 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); + + return err ? __hurd_fail (err) : 0; +} diff --git a/libc/sysdeps/mach/hurd/net/ethernet.h b/libc/sysdeps/mach/hurd/net/ethernet.h new file mode 100644 index 000000000..2c524dc12 --- /dev/null +++ b/libc/sysdeps/mach/hurd/net/ethernet.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1997 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. */ + +/* Based on the FreeBSD version of this file. Curiously, that file + lacks a copyright in the header. */ + +#ifndef __NET_ETHERNET_H +#define __NET_ETHERNET_H 1 + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <net/if_ether.h> /* IEEE 802.3 Ethernet constants */ + +__BEGIN_DECLS + +/* This is a name for the 48 bit ethernet address available on many + systems. */ +struct ether_addr +{ + u_int8_t ether_addr_octet[ETH_ALEN]; +}; + +/* 10Mb/s ethernet header */ +struct ether_header +{ + u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ + u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ + u_int16_t ether_type; /* packet type ID field */ +}; + +/* Ethernet protocol ID's */ +#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */ +#define ETHERTYPE_IP 0x0800 /* IP */ +#define ETHERTYPE_ARP 0x0806 /* Address resolution */ +#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */ + +#define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ +#define ETHER_TYPE_LEN 2 /* bytes in type field */ +#define ETHER_CRC_LEN 4 /* bytes in CRC field */ +#define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ +#define ETHER_MIN_LEN (ETH_ZLEN + ETH_CRC_LEN) /* min packet length */ +#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETH_CRC_LEN) /* max packet length */ + +/* make sure ethenet length is valid */ +#define ETHER_IS_VALID_LEN(foo) \ + ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) + +/* + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed + * by an ETHER type (as given above) and then the (variable-length) header. + */ +#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ +#define ETHERTYPE_NTRAILER 16 + +#define ETHERMTU ETH_DATA_LEN +#define ETHERMIN (ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN) + +__END_DECLS + +#endif /* net/ethernet.h */ diff --git a/libc/sysdeps/mach/hurd/net/if_arp.h b/libc/sysdeps/mach/hurd/net/if_arp.h new file mode 100644 index 000000000..c0153c93a --- /dev/null +++ b/libc/sysdeps/mach/hurd/net/if_arp.h @@ -0,0 +1,145 @@ +/* Definitions for Address Resolution Protocol. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_IF_ARP_H + +#define _NET_IF_ARP_H 1 +#include <sys/cdefs.h> + +#include <sys/types.h> +#include <sys/socket.h> + +__BEGIN_DECLS + +/* Some internals from deep down in the kernel. */ +#define MAX_ADDR_LEN 7 + + +/* This structure defines an ethernet arp header. */ + +/* ARP protocol opcodes. */ +#define ARPOP_REQUEST 1 /* ARP request. */ +#define ARPOP_REPLY 2 /* ARP reply. */ +#define ARPOP_RREQUEST 3 /* RARP request. */ +#define ARPOP_RREPLY 4 /* RARP reply. */ + +/* See RFC 826 for protocol description. ARP packets are variable + in size; the arphdr structure defines the fixed-length portion. + Protocol type values are the same as those for 10 Mb/s Ethernet. + It is followed by the variable-sized fields ar_sha, arp_spa, + arp_tha and arp_tpa in that order, according to the lengths + specified. Field names used correspond to RFC 826. */ + +struct arphdr + { + unsigned short int ar_hrd; /* Format of hardware address. */ + unsigned short int ar_pro; /* Format of protocol address. */ + unsigned char ar_hln; /* Length of hardware address. */ + unsigned char ar_pln; /* Length of protocol address. */ + unsigned short int ar_op; /* ARP opcode (command). */ +#if 0 + /* Ethernet looks like this : This bit is variable sized + however... */ + unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */ + unsigned char __ar_sip[4]; /* Sender IP address. */ + unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */ + unsigned char __ar_tip[4]; /* Target IP address. */ +#endif + }; + + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* From KA9Q: NET/ROM pseudo. */ +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps. */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet. */ +#define ARPHRD_AX25 3 /* AX.25 Level 2. */ +#define ARPHRD_PRONET 4 /* PROnet token ring. */ +#define ARPHRD_CHAOS 5 /* Chaosnet. */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB. */ +#define ARPHRD_ARCNET 7 /* ARCnet. */ +#define ARPHRD_APPLETLK 8 /* APPLEtalk. */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI. */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id). */ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 /* Notional KISS type. */ +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 /* CCITT X.25. */ +#define ARPHRD_PPP 512 +#define ARPHRD_HDLC 513 /* (Cisco) HDLC. */ +#define ARPHRD_LAPB 516 /* LAPB. */ + +#define ARPHRD_TUNNEL 768 /* IPIP tunnel. */ +#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel. */ +#define ARPHRD_FRAD 770 /* Frame Relay Access Device. */ +#define ARPHRD_SKIP 771 /* SKIP vif. */ +#define ARPHRD_LOOPBACK 772 /* Loopback device. */ +#define ARPHRD_LOCALTLK 773 /* Localtalk device. */ +#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface. */ +#define ARPHRD_BIF 775 /* AP1000 BIF. */ +#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4. */ + + +/* ARP ioctl request. */ +struct arpreq + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + char arp_dev[16]; + }; + +/* ARP Flag values. */ +#define ATF_COM 0x02 /* Completed entry (ha valid). */ +#define ATF_PERM 0x04 /* Permanent entry. */ +#define ATF_PUBL 0x08 /* Publish entry. */ +#define ATF_USETRAILERS 0x10 /* Has requested trailers. */ +#define ATF_NETMASK 0x20 /* Want to use a netmask (only + for proxy entries). */ +#define ATF_DONTPUB 0x40 /* Don't answer this addresses. */ +#define ATF_MAGIC 0x80 /* Automatically added entry. */ + + +/* Support for the user space arp daemon, arpd. */ +#define ARPD_UPDATE 0x01 +#define ARPD_LOOKUP 0x02 +#define ARPD_FLUSH 0x03 + +struct arpd_request + { + unsigned short int req; /* Request type. */ + u_int32_t ip; /* IP address of entry. */ + unsigned long int dev; /* Device entry is tied to. */ + unsigned long int stamp; + unsigned long int updated; + unsigned char ha[MAX_ADDR_LEN]; /* Hardware address. */ + }; + +__END_DECLS + +#endif /* net/if_arp.h */ diff --git a/libc/sysdeps/mach/hurd/net/if_ether.h b/libc/sysdeps/mach/hurd/net/if_ether.h new file mode 100644 index 000000000..36300cb72 --- /dev/null +++ b/libc/sysdeps/mach/hurd/net/if_ether.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1997 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 _NET_IF_ETHER_H +#define _NET_IF_ETHER_H 1 + +/* + * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble + * and FCS/CRC (frame check sequence). + */ + +#define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_HLEN 14 /* Total octets in header. */ +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ +#define ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ + +/* + * These are the defined Ethernet Protocol ID's. + */ + +#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ +#define ETH_P_ECHO 0x0200 /* Ethernet Echo packet */ +#define ETH_P_PUP 0x0400 /* Xerox PUP packet */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define ETH_P_X25 0x0805 /* CCITT X.25 */ +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ +#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ +#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ +#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ +#define ETH_P_LAT 0x6004 /* DEC LAT */ +#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ +#define ETH_P_CUST 0x6006 /* DEC Customer use */ +#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ +#define ETH_P_ATALK 0x809B /* Appletalk DDP */ +#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ +#define ETH_P_IPX 0x8137 /* IPX over DIX */ +#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ + +/* + * Non DIX types. Won't clash for 1500 types. + */ + +#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ +#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ +#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ +#define ETH_P_802_2 0x0004 /* 802.2 frames */ +#define ETH_P_SNAP 0x0005 /* Internal only */ +#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ +#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ +#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ +#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ +#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ +#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ + +/* + * This is an Ethernet frame header. + */ + +struct ethhdr +{ + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + unsigned short int h_proto; /* packet type ID field */ +}; + +#endif /* net/if_ether.h */ diff --git a/libc/sysdeps/mach/hurd/net/if_ppp.h b/libc/sysdeps/mach/hurd/net/if_ppp.h new file mode 100644 index 000000000..bf5ec8387 --- /dev/null +++ b/libc/sysdeps/mach/hurd/net/if_ppp.h @@ -0,0 +1,169 @@ +/* From: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * ==FILEVERSION 960926== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, please set the above date. + * if_ppp.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new if_ppp.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + + +#ifndef __NET_IF_PPP_H +#define __NET_IF_PPP_H 1 + +#include <sys/types.h> +#include <sys/cdefs.h> + +#include <net/if.h> +#include <sys/ioctl.h> +#include <net/ppp_defs.h> + +__BEGIN_DECLS + +/* + * Packet sizes + */ + +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#define PPP_MAXMRU 65000 /* Largest MRU we allow */ +#define PPP_VERSION "2.2.0" +#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ +#define PROTO_IPX 0x002b /* protocol numbers */ +#define PROTO_DNA_RT 0x0027 /* DNA Routing */ + + +/* + * Bit definitions for flags. + */ + +#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ +#define SC_COMP_AC 0x00000002 /* header compression (output) */ +#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ +#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ +#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ +#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ +#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ +#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ +#define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */ +#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ +#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ +#define SC_DEBUG 0x00010000 /* enable debug messages */ +#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ +#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ +#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ +#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_MASK 0x0fE0ffff /* bits that user can change */ + +/* state bits */ +#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ +#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ +#define SC_VJ_RESET 0x20000000 /* Need to reset the VJ decompressor */ +#define SC_XMIT_BUSY 0x10000000 /* ppp_write_wakeup is active */ +#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ +#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ +#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ +#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ +#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */ +#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */ + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP protocol, e.g. PPP_IP */ + enum NPmode mode; +}; + +/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ +struct ppp_option_data { + u_int8_t *ptr; + u_int32_t length; + int transmit; +}; + +struct ifpppstatsreq { + struct ifreq b; + struct ppp_stats stats; /* statistic information */ +}; + +struct ifpppcstatsreq { + struct ifreq b; + struct ppp_comp_stats stats; +}; + +#define ifr__name b.ifr_ifrn.ifrn_name +#define stats_ptr b.ifr_ifru.ifru_data + +/* + * Ioctl definitions. + */ + +#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ +#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ +#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ +#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ +#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ +#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ +#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ +#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ +#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ +#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ +#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ +#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ +#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ +#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) +#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ +#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */ +#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */ +#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ + +#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) +#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */ +#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2) + +#if !defined(ifr_mtu) +#define ifr_mtu ifr_ifru.ifru_metric +#endif + +__END_DECLS + +#endif /* net/if_ppp.h */ diff --git a/libc/sysdeps/mach/hurd/net/route.h b/libc/sysdeps/mach/hurd/net/route.h new file mode 100644 index 000000000..7b674611a --- /dev/null +++ b/libc/sysdeps/mach/hurd/net/route.h @@ -0,0 +1,141 @@ +/* Copyright (C) 1997 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. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_ROUTE_H + +#define _NET_ROUTE_H 1 +#include <features.h> + +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + + +/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ +struct rtentry + { + unsigned long int rt_pad1; + struct sockaddr rt_dst; /* Target address. */ + struct sockaddr rt_gateway; /* Gateway addr (RTF_GATEWAY). */ + struct sockaddr rt_genmask; /* Target network mask (IP). */ + unsigned short int rt_flags; + short int rt_pad2; + unsigned long int rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; + short int rt_pad4; + short int rt_metric; /* +1 for binary compatibility! */ + char *rt_dev; /* Forcing the device at add. */ + unsigned long int rt_mtu; /* Per route MTU/Window. */ + unsigned long int rt_window; /* Window clamping. */ + unsigned short int rt_irtt; /* Initial RTT. */ + }; +/* Compatibility hack. */ +#define rt_mss rt_mtu + + +struct in6_rtmsg + { + struct in6_addr rtmsg_dst; + struct in6_addr rtmsg_src; + struct in6_addr rtmsg_gateway; + u_int32_t rtmsg_type; + u_int16_t rtmsg_dst_len; + u_int16_t rtmsg_src_len; + u_int32_t rtmsg_metric; + unsigned long int rtmsg_info; + u_int32_t rtmsg_flags; + int rtmsg_ifindex; + }; + + +#define RTF_UP 0x0001 /* Route usable. */ +#define RTF_GATEWAY 0x0002 /* Destination is a gateway. */ + +#define RTF_HOST 0x0004 /* Host entry (net otherwise). */ +#define RTF_REINSTATE 0x0008 /* Reinstate route after timeout. */ +#define RTF_DYNAMIC 0x0010 /* Created dyn. (by redirect). */ +#define RTF_MODIFIED 0x0020 /* Modified dyn. (by redirect). */ +#define RTF_MTU 0x0040 /* Specific MTU for this route. */ +#define RTF_MSS RTF_MTU /* Compatibility. */ +#define RTF_WINDOW 0x0080 /* Per route window clamping. */ +#define RTF_IRTT 0x0100 /* Initial round trip time. */ +#define RTF_REJECT 0x0200 /* Reject route. */ +#define RTF_STATIC 0x0400 /* Manually injected route. */ +#define RTF_XRESOLVE 0x0800 /* External resolver. */ +#define RTF_NOFORWARD 0x1000 /* Forwarding inhibited. */ +#define RTF_THROW 0x2000 /* Go to next class. */ +#define RTF_NOPMTUDISC 0x4000 /* Do not send packets with DF. */ + +/* for IPv6 */ +#define RTF_DEFAULT 0x00010000 /* default - learned via ND */ +#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */ +#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ + +#define RTF_LINKRT 0x00100000 /* link specific - device match */ +#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ + +#define RTF_CACHE 0x01000000 /* cache entry */ +#define RTF_FLOW 0x02000000 /* flow significant route */ +#define RTF_POLICY 0x04000000 /* policy route */ + +#define RTCF_VALVE 0x00200000 +#define RTCF_MASQ 0x00400000 +#define RTCF_NAT 0x00800000 +#define RTCF_DOREDIRECT 0x01000000 +#define RTCF_LOG 0x02000000 +#define RTCF_DIRECTSRC 0x04000000 + +#define RTF_LOCAL 0x80000000 +#define RTF_INTERFACE 0x40000000 +#define RTF_MULTICAST 0x20000000 +#define RTF_BROADCAST 0x10000000 +#define RTF_NAT 0x08000000 + +#define RTF_ADDRCLASSMASK 0xF8000000 +#define RT_ADDRCLASS(flags) ((__u_int32_t) flags >> 23) + +#define RT_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +#define RT_LOCALADDR(flags) ((flags & RTF_ADDRCLASSMASK) \ + == (RTF_LOCAL|RTF_INTERFACE)) + +#define RT_CLASS_UNSPEC 0 +#define RT_CLASS_DEFAULT 253 + +#define RT_CLASS_MAIN 254 +#define RT_CLASS_LOCAL 255 +#define RT_CLASS_MAX 255 + + +#define RTMSG_ACK NLMSG_ACK +#define RTMSG_OVERRUN NLMSG_OVERRUN + +#define RTMSG_NEWDEVICE 0x11 +#define RTMSG_DELDEVICE 0x12 +#define RTMSG_NEWROUTE 0x21 +#define RTMSG_DELROUTE 0x22 +#define RTMSG_NEWRULE 0x31 +#define RTMSG_DELRULE 0x32 +#define RTMSG_CONTROL 0x40 + +#define RTMSG_AR_FAILED 0x51 /* Address Resolution failed. */ + +#endif /* net/route.h */ diff --git a/libc/sysdeps/mach/hurd/open.c b/libc/sysdeps/mach/hurd/open.c new file mode 100644 index 000000000..bdfed5e31 --- /dev/null +++ b/libc/sysdeps/mach/hurd/open.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1992,93,94,95,97,2000,2002,2006 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 <fcntl.h> +#include <stdarg.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Open FILE with access OFLAG. If OFLAG includes O_CREAT, + a third argument is the file protection. */ +int +__libc_open (const char *file, int oflag, ...) +{ + mode_t mode; + io_t port; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, mode_t); + va_end (arg); + } + else + mode = 0; + + port = __file_name_lookup (file, oflag, mode); + if (port == MACH_PORT_NULL) + return -1; + + return _hurd_intern_fd (port, oflag, 1); +} + +libc_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libc_hidden_weak (__open) +weak_alias (__libc_open, open) + +/* open64 is just the same as open for us. */ +weak_alias (__libc_open, __libc_open64) +weak_alias (__libc_open, __open64) +libc_hidden_weak (_open64) +weak_alias (__libc_open, open64) diff --git a/libc/sysdeps/mach/hurd/open64.c b/libc/sysdeps/mach/hurd/open64.c new file mode 100644 index 000000000..018ac94f2 --- /dev/null +++ b/libc/sysdeps/mach/hurd/open64.c @@ -0,0 +1 @@ +/* open64 is defined in open.c as an alias. */ diff --git a/libc/sysdeps/mach/hurd/openat.c b/libc/sysdeps/mach/hurd/openat.c new file mode 100644 index 000000000..1faf857e1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/openat.c @@ -0,0 +1,62 @@ +/* openat -- Open a file named relative to an open directory. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stdarg.h> +#include <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Open FILE with access OFLAG. Interpret relative paths relative to + the directory associated with FD. If OFLAG includes O_CREAT, a + third argument is the file protection. */ +int +__openat (fd, file, oflag) + int fd; + const char *file; + int oflag; +{ + int mode; + io_t port; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, int); + va_end (arg); + } + else + mode = 0; + + port = __file_name_lookup_at (fd, 0, file, oflag, mode); + if (port == MACH_PORT_NULL) + return -1; + + return _hurd_intern_fd (port, oflag, 1); +} +libc_hidden_def (__openat) +weak_alias (__openat, openat) + +/* openat64 is just the same as openat for us. */ +weak_alias (__openat, __openat64) +libc_hidden_weak (__openat64) +weak_alias (__openat, openat64) diff --git a/libc/sysdeps/mach/hurd/openat64.c b/libc/sysdeps/mach/hurd/openat64.c new file mode 100644 index 000000000..15d9d6a18 --- /dev/null +++ b/libc/sysdeps/mach/hurd/openat64.c @@ -0,0 +1 @@ +/* openat64 is defined in openat.c as an alias. */ diff --git a/libc/sysdeps/mach/hurd/opendir.c b/libc/sysdeps/mach/hurd/opendir.c new file mode 100644 index 000000000..23e04ede0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/opendir.c @@ -0,0 +1,93 @@ +/* Copyright (C) 1993,1994,1995,1996,1997,1998,2001,2003,2005,2006 + 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 <limits.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <hurd.h> +#include <hurd/fd.h> +#include "dirstream.h" + + +/* Open a directory stream on a file descriptor in Hurd internal form. + We do no checking here on the descriptor. */ +DIR * +_hurd_fd_opendir (struct hurd_fd *d) +{ + DIR *dirp; + + if (d == NULL) + { + errno = EBADF; + return NULL; + } + + dirp = (DIR *) malloc (sizeof (DIR)); + if (dirp == NULL) + return NULL; + + /* Set the descriptor to close on exec. */ + __spin_lock (&d->port.lock); + d->flags |= FD_CLOEXEC; + __spin_unlock (&d->port.lock); + + dirp->__fd = d; + dirp->__data = dirp->__ptr = NULL; + dirp->__entry_data = dirp->__entry_ptr = 0; + dirp->__allocation = 0; + dirp->__size = 0; + + __libc_lock_init (dirp->__lock); + + return dirp; +} + + +/* Open a directory stream on NAME. */ +DIR * +__opendir (const char *name) +{ + if (name[0] == '\0') + { + /* POSIX.1-1990 says an empty name gets ENOENT; + but `open' might like it fine. */ + __set_errno (ENOENT); + return NULL; + } + + int fd = __open (name, O_RDONLY | O_NONBLOCK | O_DIRECTORY); + if (fd < 0) + return NULL; + + /* Extract the pointer to the descriptor structure. */ + DIR *dirp = _hurd_fd_opendir (_hurd_fd_get (fd)); + if (dirp == NULL) + __close (fd); + + return dirp; +} +weak_alias (__opendir, opendir) diff --git a/libc/sysdeps/mach/hurd/pathconf.c b/libc/sysdeps/mach/hurd/pathconf.c new file mode 100644 index 000000000..2f95e2be8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/pathconf.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1992, 1994, 1995, 1997 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 <stddef.h> +#include <sys/stat.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Get file-specific information about FILE. */ +long int +__pathconf (const char *file, int name) +{ + error_t err; + int value; /* RPC returns an `int', not a `long int'. */ + file_t port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1L; + err = __io_pathconf (port, name, &value); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err), -1L; + return value; +} + +weak_alias (__pathconf, pathconf) diff --git a/libc/sysdeps/mach/hurd/pipe.c b/libc/sysdeps/mach/hurd/pipe.c new file mode 100644 index 000000000..7a5d78c29 --- /dev/null +++ b/libc/sysdeps/mach/hurd/pipe.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1992,93,94,95,96,99,2000,2002 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> + +/* 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]. + Returns 0 if successful, -1 if not. */ +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; +} +libc_hidden_def (__pipe) +weak_alias (__pipe, pipe) diff --git a/libc/sysdeps/mach/hurd/poll.c b/libc/sysdeps/mach/hurd/poll.c new file mode 100644 index 000000000..f6f7127ef --- /dev/null +++ b/libc/sysdeps/mach/hurd/poll.c @@ -0,0 +1,51 @@ +/* poll file descriptors. Hurd version. + Copyright (C) 1998, 2001, 2002 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 <sys/poll.h> +#include <sys/time.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ + +int +__poll (fds, nfds, timeout) + struct pollfd *fds; + nfds_t nfds; + int timeout; +{ + struct timespec ts, *to; + + if (timeout < 0) + to = NULL; + else + { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + to = &ts; + } + + return _hurd_select (nfds, fds, NULL, NULL, NULL, to, NULL); +} +libc_hidden_def (__poll) +weak_alias (__poll, poll) diff --git a/libc/sysdeps/mach/hurd/powerpc/bits/sigcontext.h b/libc/sysdeps/mach/hurd/powerpc/bits/sigcontext.h new file mode 100644 index 000000000..bbed8f9ff --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/bits/sigcontext.h @@ -0,0 +1,80 @@ +/* Machine-dependent signal context structure for GNU Hurd. PowerPC version. + Copyright (C) 2001,02 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead." +#endif + +#ifndef sc_pc + +/* Signal handlers are actually called: + void handler (int sig, int code, struct sigcontext *scp); */ + +/* State of this thread when the signal was taken. */ +struct sigcontext + { + /* These first members are machine-independent. */ + + int sc_onstack; /* Nonzero if running on sigstack. */ + __sigset_t sc_mask; /* Blocked signals to restore. */ + + /* MiG reply port this thread is using. */ + unsigned int sc_reply_port; + + /* Port this thread is doing an interruptible RPC on. */ + unsigned int sc_intr_port; + + /* Error code associated with this signal (interpreted as `error_t'). */ + int sc_error; + + /* All following members are machine-dependent. The rest of this + structure is written to be laid out identically to: + { + struct ppc_thread_state basic; + struct ppc_exc_state exc; + struct ppc_float_state fpu; + } + trampoline.c knows this, so it must be changed if this changes. */ + +#define sc_ppc_thread_state sc_srr0 /* Beginning of correspondence. */ +#define sc_pc sc_srr0 /* For sysdeps/generic/profil-counter.h. */ + unsigned int sc_srr0; + unsigned int sc_srr1; + unsigned int sc_gprs[32]; + unsigned int sc_cr; + unsigned int sc_xer; + unsigned int sc_lr; + unsigned int sc_ctr; + unsigned int sc_mq; + unsigned int sc_ts_pad; + +#define sc_ppc_exc_state sc_dar + unsigned int sc_dar; + unsigned int sc_dsisr; + unsigned int sc_exception; + unsigned int sc_es_pad0; + unsigned int sc_es_pad1[4]; + +#define sc_ppc_float_state sc_fprs[0] + double sc_fprs[32]; + unsigned int sc_fpscr_pad; + unsigned int sc_fpscr; + }; + +#endif /* sc_pc */ diff --git a/libc/sysdeps/mach/hurd/powerpc/exc2signal.c b/libc/sysdeps/mach/hurd/powerpc/exc2signal.c new file mode 100644 index 000000000..7cea85daa --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/exc2signal.c @@ -0,0 +1,74 @@ +/* Translate Mach exception codes into signal numbers. PowerPC version. + Copyright (C) 1991,92,94,96,97,2001 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 <hurd.h> +#include <hurd/signal.h> +#include <mach/exception.h> + +/* 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) +{ + detail->error = 0; + + switch (detail->exc) + { + default: + *signo = SIGIOT; + detail->code = detail->exc; + break; + + case EXC_BAD_ACCESS: + if (detail->exc_code == KERN_PROTECTION_FAILURE) + *signo = SIGSEGV; + else + *signo = SIGBUS; + detail->code = detail->exc_subcode; + detail->error = detail->exc_code; + break; + + /* XXX there has got to be something more here */ + + case EXC_BAD_INSTRUCTION: + *signo = SIGILL; + detail->code = 0; + break; + + case EXC_ARITHMETIC: + *signo = SIGFPE; + detail->code = 0; + break; + + case EXC_EMULATION: + *signo = SIGEMT; + detail->code = 0; + break; + + case EXC_SOFTWARE: + *signo = SIGEMT; + detail->code = 0; + break; + + case EXC_BREAKPOINT: + *signo = SIGTRAP; + detail->code = 0; + } +} diff --git a/libc/sysdeps/mach/hurd/powerpc/init-first.c b/libc/sysdeps/mach/hurd/powerpc/init-first.c new file mode 100644 index 000000000..20fa1d4f1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/init-first.c @@ -0,0 +1,339 @@ +/* Initialization code run first thing by the ELF startup code. PowerPC/Hurd. + Copyright (C) 1995-2001, 2002, 2003 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 <assert.h> +#include <hurd.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sysdep.h> +#include <set-hooks.h> +#include "hurdstartup.h" +#include "hurdmalloc.h" /* XXX */ + +extern void __mach_init (void); +extern void __init_misc (int, char **, char **); +#ifdef USE_NONOPTION_FLAGS +extern void __getopt_clean_environment (char **); +#endif +#ifndef SHARED +extern void _dl_non_dynamic_init (void) internal_function; +#endif +extern void __libc_global_ctors (void); + +unsigned int __hurd_threadvar_max; +unsigned long int __hurd_threadvar_stack_offset; +unsigned long int __hurd_threadvar_stack_mask; + +#ifndef SHARED +int __libc_enable_secure; +#endif +int __libc_multiple_libcs attribute_hidden = 1; + +extern int __libc_argc attribute_hidden; +extern char **__libc_argv attribute_hidden; +extern char **_dl_argv; + +void *(*_cthread_init_routine) (void); /* Returns new SP to use. */ +void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__)); + +#ifndef SHARED +static unsigned int return_address; /* Make init1 return to _start. */ +#endif + +/* Things that want to be run before _hurd_init or much anything else. + Importantly, these are called before anything tries to use malloc. */ +DEFINE_HOOK (_hurd_preinit_hook, (void)); + + +/* We call this once the Hurd magic is all set up and we are ready to be a + Posixoid program. This does the same things the generic version does. */ +static void internal_function +posixland_init (int argc, char **argv, char **envp) +{ + asm ("li 3,0xbb; .long 0"); + __libc_argc = argc; + __libc_argv = argv; + __environ = envp; + +#ifndef SHARED + _dl_non_dynamic_init (); +#endif + __init_misc (argc, argv, envp); + +#ifdef USE_NONOPTION_FLAGS + /* This is a hack to make the special getopt in GNU libc working. */ + __getopt_clean_environment (__environ); +#endif + +#ifdef SHARED + __libc_global_ctors (); +#endif +} + + +static void +init1 (int *data) +{ + int argc = *data; + char **argv = (char **) &data[1]; + char **envp = &argv[argc + 1]; + struct hurd_startup_data *d; + + while (*envp) + ++envp; + d = (void *) ++envp; + + /* 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. */ + /* OSF Mach starts the bootstrap task with argc == 0. + XXX This fails if a non-bootstrap task gets started + with argc == 0. */ + if (argc && (void *) d != argv[0]) + { + _hurd_init_dtable = d->dtable; + _hurd_init_dtablesize = d->dtablesize; + +#if 0 /* We can't free the old stack because it contains the argument strings. */ + { + /* Check if the stack we are now on is different from + the one described by _hurd_stack_{base,size}. */ + + char dummy; + const vm_address_t newsp = (vm_address_t) &dummy; + + if (d->stack_size != 0 && (newsp < d->stack_base || + newsp - d->stack_base > d->stack_size)) + /* The new stack pointer does not intersect with the + stack the exec server set up for us, so free that stack. */ + __vm_deallocate (__mach_task_self (), d->stack_base, d->stack_size); + } +#endif + } + + if (argc && (void *) d != argv[0] && (d->portarray || d->intarray)) + /* Initialize library data structures, start signal processing, etc. */ + _hurd_init (d->flags, argv, + d->portarray, d->portarraysize, + d->intarray, d->intarraysize); + +#ifndef SHARED + __libc_enable_secure = d->flags & EXEC_SECURE; +#endif +} + + +static inline void +init (int *data) +{ + int argc = *data; + char **argv = (void *) (data + 1); + char **envp = &argv[argc + 1]; + struct hurd_startup_data *d; + unsigned long int threadvars[_HURD_THREADVAR_MAX]; + + /* Provide temporary storage for thread-specific variables on the startup + stack so the cthreads initialization code can use them for malloc et al, + or so we can use malloc below for the real threadvars array. */ + memset (threadvars, 0, sizeof threadvars); + __hurd_threadvar_stack_offset = (unsigned long int) threadvars; + + while (*envp) + ++envp; + d = (void *) ++envp; + + /* The user might have defined a value for this, to get more variables. + Otherwise it will be zero on startup. We must make sure it is set + properly before before cthreads initialization, so cthreads can know + how much space to leave for thread variables. */ + if (__hurd_threadvar_max < _HURD_THREADVAR_MAX) + __hurd_threadvar_max = _HURD_THREADVAR_MAX; + + + /* After possibly switching stacks, call `init1' (above) with the user + code as the return address, and the argument data immediately above + that on the stack. */ + + if (_cthread_init_routine) + { + /* Initialize cthreads, which will allocate us a new stack to run on. */ + void *newsp = (*_cthread_init_routine) (); + struct hurd_startup_data *od; +#ifdef SHARED + void *oldsp; + unsigned int i, data_offset; +#endif + + /* Copy per-thread variables from that temporary + area onto the new cthread stack. */ + memcpy (__hurd_threadvar_location_from_sp (0, newsp), + threadvars, sizeof threadvars); + + /* Copy the argdata from the old stack to the new one. */ + newsp = memcpy (newsp - ((char *) &d[1] - (char *) data), data, + (char *) d - (char *) data); + +#ifdef SHARED + /* And readjust the dynamic linker's idea of where the argument + vector lives. */ + assert (_dl_argv == argv); + _dl_argv = (void *) ((int *) newsp + 1); +#endif + + /* Set up the Hurd startup data block immediately following + the argument and environment pointers on the new stack. */ + od = (newsp + ((char *) d - (char *) data)); + if (!argc || (void *) argv[0] == d) + /* We were started up by the kernel with arguments on the stack. + There is no Hurd startup data, so zero the block. */ + memset (od, 0, sizeof *od); + else + /* Copy the Hurd startup data block to the new stack. */ + *od = *d; + +#ifndef SHARED + asm ("mtlr %0; mr 1,%1; li 0,0; mr 3,%1; stwu 0,-16(1); b init1" + : : "r" (return_address), "r" (newsp)); + (void) init1; /* To avoid `defined but not used' warning. */ + /* NOTREACHED */ +#else + /* Copy the rest of the stack. Don't call a function to do that, + because that will alter the current stack. */ + asm ("mr %0,1" : "=r" (oldsp)); + data_offset = (unsigned int) data - (unsigned int) oldsp; + newsp -= data_offset; + for (i = 0; i < data_offset / 4; i++) + ((unsigned int *)newsp)[i] = ((unsigned int *)oldsp)[i]; + + /* Relocate stack frames. */ + { + unsigned int *oldframe0 = (unsigned int *)oldsp; + unsigned int *oldframe1 = *(unsigned int **)oldframe0; + unsigned int *oldframe2 = *(unsigned int **)oldframe1; + unsigned int *newframe0 = (unsigned int *)newsp; + unsigned int *newframe1 = newframe0 + (unsigned int)(oldframe1 - oldframe0); + unsigned int *newframe2 = newframe1 + (unsigned int)(oldframe2 - oldframe1); + *(unsigned int **)newframe0 = newframe1; + *(unsigned int **)newframe1 = newframe2; + } + + asm ("mr 1,%0; mr 31,%0" : : "r" (newsp)); /* XXX */ + init1 (newsp + data_offset); +#endif + } + else + { + /* We are not using cthreads, so we will have just a single allocated + area for the per-thread variables of the main user thread. */ + unsigned long int *array; + unsigned int i; + + array = malloc (__hurd_threadvar_max * sizeof (unsigned long int)); + if (array == NULL) + __libc_fatal ("Can't allocate single-threaded thread variables."); + + /* Copy per-thread variables from the temporary array into the + newly malloc'd space. */ + memcpy (array, threadvars, sizeof threadvars); + __hurd_threadvar_stack_offset = (unsigned long int) array; + for (i = _HURD_THREADVAR_MAX; i < __hurd_threadvar_max; ++i) + array[i] = 0; + +#ifndef SHARED + asm ("mr 3,%0; mtlr %1; addi 1,3,-16; b init1" + : : "r" (data), "r" (return_address)); + /* NOTREACHED */ +#else + init1 (data); +#endif + } +} + + +/* Do the first essential initializations that must precede all else. */ +static inline void +first_init (void) +{ + /* Initialize data structures so we can do RPCs. */ + __mach_init (); + + RUN_HOOK (_hurd_preinit_hook, ()); +} + +#ifdef SHARED +/* This function is called specially by the dynamic linker to do early + initialization of the shared C library before normal initializers + expecting a Posixoid environment can run. It gets called with the + stack set up just as the user will see it, so it can switch stacks. */ + +void +_dl_init_first (int argc, ...) +{ + asm ("li 3,0xaa; .long 0"); + first_init (); + + init (&argc); +} +#endif + + +#ifdef SHARED +/* The regular posixland initialization is what goes into libc's + normal initializer. */ +/* NOTE! The linker notices the magical name `_init' and sets the DT_INIT + pointer in the dynamic section based solely on that. It is convention + for this function to be in the `.init' section, but the symbol name is + the only thing that really matters!! */ +strong_alias (posixland_init, _init); + + +void +__libc_init_first (int argc, char **argv, char **envp) +{ + /* Everything was done in the shared library initializer, _init. */ +} +#else +strong_alias (posixland_init, __libc_init_first); + + +void +_hurd_stack_setup (int *data) +{ + register unsigned int address; + asm ("mflr %0" : "=r" (address)); + return_address = address; + + first_init (); + + _hurd_startup ((void **) data, &init); +} +#endif + + +/* This function is defined here so that if this file ever gets into + ld.so we will get a link error. Having this file silently included + in ld.so causes disaster, because the _init definition above will + cause ld.so to gain an init function, which is not a cool thing. */ + +void +_dl_start (void) +{ + abort (); +} diff --git a/libc/sysdeps/mach/hurd/powerpc/intr-msg.h b/libc/sysdeps/mach/hurd/powerpc/intr-msg.h new file mode 100644 index 000000000..a3cb6ef7e --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/intr-msg.h @@ -0,0 +1,99 @@ +/* Machine-dependent details of interruptible RPC messaging. PowerPC version. + Copyright (C) 1995,96,97,99,2001 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. */ + +#define INTR_MSG_TRAP(msg, option, send_size, rcv_size, rcv_name, timeout, notify) \ +({ \ + error_t err; \ + asm (".globl _hurd_intr_rpc_msg_do_trap\n" \ + ".globl _hurd_intr_rpc_msg_in_trap\n" \ + " mr 3, %1\n" \ + " mr 4, %2\n" \ + " mr 5, %3\n" \ + " mr 6, %4\n" \ + " mr 7, %5\n" \ + " mr 8, %6\n" \ + " mr 9, %7\n" \ + " li 0, -25\n" \ + "_hurd_intr_rpc_msg_do_trap: sc\n" \ + "_hurd_intr_rpc_msg_in_trap: mr 3, %0\n" \ + : "=r" (err) \ + : "r" (msg), "r" (option), "r" (send_size), "r" (rcv_size), \ + "r" (rcv_name), "r" (timeout), "r" (notify) \ + : "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"); \ + err; \ +}) + +static void inline +INTR_MSG_BACK_OUT (struct ppc_thread_state *state) +{ + return; +} + +#include "hurdfault.h" + +/* This cannot be an inline function because it calls setjmp. */ +#define SYSCALL_EXAMINE(state, callno) \ +({ \ + u_int32_t *p = (void *) ((state)->srr0 - 4); \ + int result; \ + _hurdsig_catch_memory_fault (p) ? 0 : \ + ({ \ + if (result = (*p == 0x44000002)) \ + /* The PC is just after an `sc' instruction. \ + This is a system call in progress; %r0 holds the call number. */ \ + *(callno) = (state)->r0; \ + _hurdsig_end_catch_fault (); \ + result; \ + }); \ +}) + +struct mach_msg_trap_args + { + /* This is the order of arguments to mach_msg_trap. */ + mach_msg_header_t *msg; + mach_msg_option_t option; + mach_msg_size_t send_size; + mach_msg_size_t rcv_size; + mach_port_t rcv_name; + mach_msg_timeout_t timeout; + mach_port_t notify; + }; + +/* This cannot be an inline function because it calls setjmp. */ +#define MSG_EXAMINE(state, msgid, rcv_name, send_name, option, timeout) \ +({ \ + mach_msg_header_t *msg = (mach_msg_header_t *) (state)->r3; \ + *(option) = (mach_msg_option_t) (state)->r4; \ + *(rcv_name) = (mach_port_t) (state)->r7; \ + *(timeout) = (mach_msg_timeout_t) (state)->r8; \ + (msg == 0) ? \ + ({ \ + *(send_name) = MACH_PORT_NULL; \ + *(msgid) = 0; \ + 0; \ + }) : \ + (_hurdsig_catch_memory_fault (msg) ? -1 : \ + ({ \ + *(send_name) = msg->msgh_remote_port; \ + *(msgid) = msg->msgh_id; \ + _hurdsig_end_catch_fault (); \ + 0; \ + }) \ + ); \ +}) diff --git a/libc/sysdeps/mach/hurd/powerpc/longjmp-ts.c b/libc/sysdeps/mach/hurd/powerpc/longjmp-ts.c new file mode 100644 index 000000000..757366bc4 --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/longjmp-ts.c @@ -0,0 +1,57 @@ +/* Perform a `longjmp' on a Mach thread_state. PowerPC version. + Copyright (C) 1991,94,95,97,2001, 2006 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 <hurd/signal.h> +#include <setjmp.h> +#include <jmpbuf-offsets.h> +#include <mach/thread_status.h> + + +/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */ + +void +_hurd_longjmp_thread_state (void *state, jmp_buf env, int val) +{ + struct ppc_thread_state *ts = state; + + /* XXX should we set up the FPRs as well? And how? */ + ts->r1 = env[0].__jmpbuf[JB_GPR1]; + ts->r2 = env[0].__jmpbuf[JB_GPR2]; + ts->r14 = env[0].__jmpbuf[JB_GPRS+0]; + ts->r15 = env[0].__jmpbuf[JB_GPRS+1]; + ts->r16 = env[0].__jmpbuf[JB_GPRS+2]; + ts->r17 = env[0].__jmpbuf[JB_GPRS+3]; + ts->r18 = env[0].__jmpbuf[JB_GPRS+4]; + ts->r19 = env[0].__jmpbuf[JB_GPRS+5]; + ts->r20 = env[0].__jmpbuf[JB_GPRS+6]; + ts->r21 = env[0].__jmpbuf[JB_GPRS+7]; + ts->r22 = env[0].__jmpbuf[JB_GPRS+8]; + ts->r23 = env[0].__jmpbuf[JB_GPRS+9]; + ts->r24 = env[0].__jmpbuf[JB_GPRS+10]; + ts->r25 = env[0].__jmpbuf[JB_GPRS+11]; + ts->r26 = env[0].__jmpbuf[JB_GPRS+12]; + ts->r27 = env[0].__jmpbuf[JB_GPRS+13]; + ts->r28 = env[0].__jmpbuf[JB_GPRS+14]; + ts->r29 = env[0].__jmpbuf[JB_GPRS+15]; + ts->r30 = env[0].__jmpbuf[JB_GPRS+16]; + ts->r31 = env[0].__jmpbuf[JB_GPRS+17]; + ts->cr = env[0].__jmpbuf[JB_CR]; + ts->r3 = val ?: 1; + ts->srr0 = ts->lr = env[0].__jmpbuf[JB_LR]; +} diff --git a/libc/sysdeps/mach/hurd/powerpc/register-dump.h b/libc/sysdeps/mach/hurd/powerpc/register-dump.h new file mode 100644 index 000000000..037717522 --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/register-dump.h @@ -0,0 +1,120 @@ +/* Dump registers. PowerPC/Hurd version. + Copyright (C) 1998, 2001 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 <sys/uio.h> +#include <stdio-common/_itoa.h> + +/* This prints out the information in the following form: */ +static const char dumpform[] = "\ +Register dump:\n\ +fp0-3: 0000030%0000031% 0000032%0000033% 0000034%0000035% 0000036%0000037%\n\ +fp4-7: 0000038%0000039% 000003a%000003b% 000003c%000003d% 000003e%000003f%\n\ +fp8-11: 0000040%0000041% 0000042%0000043% 0000044%0000045% 0000046%0000047%\n\ +fp12-15: 0000048%0000049% 000004a%000004b% 000004c%000004d% 000004e%000004f%\n\ +fp16-19: 0000050%0000051% 0000052%0000053% 0000054%0000055% 0000056%0000057%\n\ +fp20-23: 0000058%0000059% 000005a%000005b% 000005c%000005d% 000005e%000005f%\n\ +fp24-27: 0000060%0000061% 0000062%0000063% 0000064%0000065% 0000066%0000067%\n\ +fp28-31: 0000068%0000069% 000006a%000006b% 000006c%000006d% 000006e%000006f%\n\ +r0 =0000002% sp =0000003% r2 =0000004% r3 =0000005%\n\ +r4 =0000006% r5 =0000007% r6 =0000008% r7 =0000009% sr0=0000000% sr1=0000001%\n\ +r8 =000000a% r9 =000000b% r10=000000c% r11=000000d% cr=0000022% xer=0000023%\n\ +r12=000000e% r13=000000f% r14=0000010% r15=0000011% lr=0000024% ctr=0000025%\n\ +r16=0000012% r17=0000013% r18=0000014% r19=0000015% mq=0000026% fcr=0000071%\n\ +r20=0000016% r21=0000017% r22=0000018% r23=0000019% dar=0000028% dsi=0000029%\n\ +r24=000001a% r25=000001b% r26=000001c% r27=000001d% exc=000002a%\n\ +r28=000001e% r29=000001f% r30=0000020% r31=0000021%\n\ +"; + +/* Most of the fields are self-explanatory. 'sr0' is the next + instruction to execute, from SRR0, which may have some relationship + with the instruction that caused the exception. 'r3*' is the value + that will be returned in register 3 when the current system call + returns. 'sr1' is SRR1, bits 16-31 of which are copied from the MSR: + + 16 - External interrupt enable + 17 - Privilege level (1=user, 0=supervisor) + 18 - FP available + 19 - Machine check enable (if clear, processor locks up on machine check) + 20 - FP exception mode bit 0 (FP exceptions recoverable) + 21 - Single-step trace enable + 22 - Branch trace enable + 23 - FP exception mode bit 1 + 25 - exception prefix (if set, exceptions are taken from 0xFFFnnnnn, + otherwise from 0x000nnnnn). + 26 - Instruction address translation enabled. + 27 - Data address translation enabled. + 30 - Exception is recoverable (otherwise, don't try to return). + 31 - Little-endian mode enable. + + 'Trap' is the address of the exception: + + 00200 - Machine check exception (memory parity error, for instance) + 00300 - Data access exception (memory not mapped, see dsisr for why) + 00400 - Instruction access exception (memory not mapped) + 00500 - External interrupt + 00600 - Alignment exception (see dsisr for more information) + 00700 - Program exception (illegal/trap instruction, FP exception) + 00800 - FP unavailable (should not be seen by user code) + 00900 - Decrementer exception (for instance, SIGALRM) + 00A00 - I/O controller interface exception + 00C00 - System call exception (for instance, kill(3)). + 00E00 - FP assist exception (optional FP instructions, etc.) + + 'dar' is the memory location, for traps 00300, 00400, 00600, 00A00. + 'dsisr' has the following bits under trap 00300: + 0 - direct-store error exception + 1 - no page table entry for page + 4 - memory access not permitted + 5 - trying to access I/O controller space or using lwarx/stwcx on + non-write-cached memory + 6 - access was store + 9 - data access breakpoint hit + 10 - segment table search failed to find translation (64-bit ppcs only) + 11 - I/O controller instruction not permitted + For trap 00400, the same bits are set in SRR1 instead. + For trap 00600, bits 12-31 of the DSISR set to allow emulation of + the instruction without actually having to read it from memory. +*/ + +#define xtoi(x) (x >= 'a' ? x + 10 - 'a' : x - '0') + +static void +register_dump (int fd, struct sigcontext *ctx) +{ + char buffer[sizeof(dumpform)]; + char *bufferpos; + unsigned regno; + unsigned *regs = (unsigned *)(&ctx->sc_srr0); + + memcpy(buffer, dumpform, sizeof(dumpform)); + + /* Generate the output. */ + while ((bufferpos = memchr (buffer, '%', sizeof(dumpform)))) + { + regno = xtoi (bufferpos[-1]) | xtoi (bufferpos[-2]) << 4; + memset (bufferpos-2, '0', 3); + _itoa_word (regs[regno], bufferpos+1, 16, 0); + } + + /* Write the output. */ + write (fd, buffer, sizeof(buffer)); +} + +#define REGISTER_DUMP \ + register_dump (fd, ctx) diff --git a/libc/sysdeps/mach/hurd/powerpc/sigreturn.c b/libc/sysdeps/mach/hurd/powerpc/sigreturn.c new file mode 100644 index 000000000..18e37a3d4 --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/sigreturn.c @@ -0,0 +1,186 @@ +/* Return from signal handler for Hurd. PowerPC version. + Copyright (C) 1996,97,98,2001 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 <hurd.h> +#include <hurd/signal.h> +#include <hurd/threadvar.h> +#include <stdlib.h> + +int +__sigreturn (struct sigcontext *scp) +{ + struct hurd_sigstate *ss; + mach_port_t *reply_port; + + if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK)) + { + errno = EINVAL; + return -1; + } + + ss = _hurd_self_sigstate (); + __spin_lock (&ss->lock); + + /* Restore the set of blocked signals, and the intr_port slot. */ + ss->blocked = scp->sc_mask; + ss->intr_port = scp->sc_intr_port; + + /* Check for pending signals that were blocked by the old set. */ + if (ss->pending & ~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); + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + /* If a pending signal was handled, sig_post never returned. */ + __spin_lock (&ss->lock); + ss->context = NULL; + } + + if (scp->sc_onstack) + { + ss->sigaltstack.ss_flags &= ~SS_ONSTACK; /* XXX threadvars */ + /* XXX cannot unlock until off sigstack */ + abort (); + } + else + __spin_unlock (&ss->lock); + + /* Destroy the MiG reply port used by the signal handler, and restore the + reply port in use by the thread when interrupted. */ + reply_port = + (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); + if (*reply_port) + { + mach_port_t port = *reply_port; + + /* Assigning MACH_PORT_DEAD here tells libc's mig_get_reply_port not to + get another reply port, but avoids mig_dealloc_reply_port trying to + deallocate it after the receive fails (which it will, because the + reply port will be bogus, whether we do this or not). */ + *reply_port = MACH_PORT_DEAD; + + __mach_port_destroy (__mach_task_self (), port); + } + *reply_port = scp->sc_reply_port; + + /* Restore FPU state. */ +#define restore_fpr(n) \ + asm volatile ("lfd " #n ",%0(31)" : : "i" (n * 4)) + + asm volatile ("mr 31,%0" : : "r" (scp->sc_fprs)); + + /* Restore the floating-point control/status register. */ + asm volatile ("lfd 0,256(31)"); + asm volatile ("mtfsf 0xff,0"); + + /* Restore floating-point registers. */ + restore_fpr (0); + restore_fpr (1); + restore_fpr (2); + restore_fpr (3); + restore_fpr (4); + restore_fpr (5); + restore_fpr (6); + restore_fpr (7); + restore_fpr (8); + restore_fpr (9); + restore_fpr (10); + restore_fpr (11); + restore_fpr (12); + restore_fpr (13); + restore_fpr (14); + restore_fpr (15); + restore_fpr (16); + restore_fpr (17); + restore_fpr (18); + restore_fpr (19); + restore_fpr (20); + restore_fpr (21); + restore_fpr (22); + restore_fpr (23); + restore_fpr (24); + restore_fpr (25); + restore_fpr (26); + restore_fpr (27); + restore_fpr (28); + restore_fpr (29); + restore_fpr (30); + restore_fpr (31); + + /* Load all the registers from the sigcontext. */ +#define restore_gpr(n) \ + asm volatile ("lwz " #n ",%0(31)" : : "i" (n * 4)) + + asm volatile ("addi 31,31,-188"); /* r31 = scp->gprs */ + + /* Restore the special purpose registers. */ + asm volatile ("lwz 0,128(31); mtcr 0"); + asm volatile ("lwz 0,132(31); mtxer 0"); + asm volatile ("lwz 0,136(31); mtlr 0"); + asm volatile ("lwz 0,-8(31); mtctr 0"); /* XXX this is the PC */ +#if 0 + asm volatile ("lwz 0,144(31); mtmq %0"); /* PPC601 only */ +#endif + + /* Restore the normal registers. */ + restore_gpr (0); + restore_gpr (1); + restore_gpr (2); + restore_gpr (3); + restore_gpr (4); + restore_gpr (5); + restore_gpr (6); + restore_gpr (7); + restore_gpr (8); + restore_gpr (9); + restore_gpr (10); + restore_gpr (11); + restore_gpr (12); + restore_gpr (13); + restore_gpr (14); + restore_gpr (15); + restore_gpr (16); + restore_gpr (17); + restore_gpr (18); + restore_gpr (19); + restore_gpr (20); + restore_gpr (21); + restore_gpr (22); + restore_gpr (23); + restore_gpr (24); + restore_gpr (25); + restore_gpr (26); + restore_gpr (27); + restore_gpr (28); + restore_gpr (29); + restore_gpr (30); + restore_gpr (31); + + /* Return. */ + asm volatile ("bctr"); /* XXX CTR is not restored! */ + + /* NOTREACHED */ + return -1; +} + +weak_alias (__sigreturn, sigreturn) diff --git a/libc/sysdeps/mach/hurd/powerpc/static-start.S b/libc/sysdeps/mach/hurd/powerpc/static-start.S new file mode 100644 index 000000000..3420fcd31 --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/static-start.S @@ -0,0 +1,59 @@ +/* Startup code for statically linked Hurd/PowerPC binaries. + Copyright (C) 1998,2001, 2002 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 <sysdep.h> + + /* These are the various addresses we require. */ + .section ".rodata" + .align 2 + weak_extern(__libc_csu_init) + weak_extern(__libc_csu_fini) +L(start_addresses): + .long _SDA_BASE_ + .long JUMPTARGET(main) + .long JUMPTARGET(__libc_csu_init) + .long JUMPTARGET(__libc_csu_fini) + ASM_SIZE_DIRECTIVE(L(start_addresses)) + + .section ".text" +ENTRY(_start) + /* Save the stack pointer to pass to _hurd_stack_setup. */ + mr r3,r1 + /* Set up an initial stack frame. */ + li r0,0 + stwu r0,-16(r1) + /* Call _hurd_stack_setup. */ + bl JUMPTARGET(_hurd_stack_setup) + /* Pass the argument data to __libc_start_main. */ + addi r9,r1,16 + /* Clear the LR. */ + li r0,0 + mtlr r0 + /* Set r13 to point at the 'small data area', and put the address of + start_addresses in r8... */ + lis r8,L(start_addresses)@ha + lwzu r13,L(start_addresses)@l(r8) + /* and continue in libc-start, in glibc. */ + b JUMPTARGET(__libc_start_main) +END(_start) + +/* Define a symbol for the first piece of initialized data. */ + .section ".data" +__data_start: +weak_alias (__data_start, data_start) diff --git a/libc/sysdeps/mach/hurd/powerpc/trampoline.c b/libc/sysdeps/mach/hurd/powerpc/trampoline.c new file mode 100644 index 000000000..4e1ea4b9d --- /dev/null +++ b/libc/sysdeps/mach/hurd/powerpc/trampoline.c @@ -0,0 +1,257 @@ +/* Set thread_state for sighandler, and sigcontext to recover. For PowerPC. + Copyright (C) 1994,1995,1996,1997,1998,1999,2001,2005 + 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 <hurd/signal.h> +#include <hurd/userlink.h> +#include <thread_state.h> +#include <assert.h> +#include <errno.h> +#include "hurdfault.h" +#include <intr-msg.h> + +struct sigcontext * +_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, + int signo, struct hurd_signal_detail *detail, + volatile int rpc_wait, + struct machine_thread_all_state *state) +{ + void trampoline (void); + void rpc_wait_trampoline (void); + void *volatile sigsp; + struct sigcontext *scp; + + if (ss->context) + { + /* We have a previous sigcontext that sigreturn was about + to restore when another signal arrived. We will just base + our setup on that. */ + if (! _hurdsig_catch_memory_fault (ss->context)) + { + memcpy (&state->basic, &ss->context->sc_ppc_thread_state, + sizeof (state->basic)); + memcpy (&state->exc, &ss->context->sc_ppc_exc_state, + sizeof (state->exc)); + memcpy (&state->fpu, &ss->context->sc_ppc_float_state, + sizeof (state->fpu)); + state->set = (1 << PPC_THREAD_STATE) | (1 << PPC_EXCEPTION_STATE) + | (1 << PPC_FLOAT_STATE); + } + } + + if (! machine_get_basic_state (ss->thread, state)) + return NULL; + + if ((ss->actions[signo].sa_flags & SA_ONSTACK) && + !(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK))) + { + sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size; + ss->sigaltstack.ss_flags |= SS_ONSTACK; + /* XXX need to set up base of new stack for + per-thread variables, cthreads. */ + } + else + sigsp = (char *) state->basic.SP; + + /* Set up the sigcontext structure on the stack. This is all the stack + needs, since the args are passed in registers (below). */ + sigsp -= sizeof (*scp); + scp = sigsp; + sigsp -= 16; /* Reserve some space for a stack frame. */ + + if (_hurdsig_catch_memory_fault (scp)) + { + /* We got a fault trying to write the stack frame. + We cannot set up the signal handler. + Returning NULL tells our caller, who will nuke us with a SIGILL. */ + return NULL; + } + else + { + int ok; + + /* Set up the sigcontext from the current state of the thread. */ + + scp->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0; + + /* struct sigcontext is laid out so that starting at sc_srr0 + mimics a struct ppc_thread_state. */ + memcpy (&scp->sc_ppc_thread_state, + &state->basic, sizeof (state->basic)); + + /* struct sigcontext is laid out so that starting at sc_dar + mimics a struct ppc_exc_state. */ + ok = machine_get_state (ss->thread, state, PPC_EXCEPTION_STATE, + &state->exc, &scp->sc_ppc_exc_state, + sizeof (state->exc)); + + /* struct sigcontext is laid out so that starting at sc_fprs[0] + mimics a struct ppc_float_state. */ + if (ok) + ok = machine_get_state (ss->thread, state, PPC_FLOAT_STATE, + &state->fpu, &scp->sc_ppc_float_state, + sizeof (state->fpu)); + + _hurdsig_end_catch_fault (); + + if (!ok) + return NULL; + } + + /* Modify the thread state to call the trampoline code on the new stack. */ + if (rpc_wait) + { + /* The signalee thread was blocked in a mach_msg_trap system call, + still waiting for a reply. We will have it run the special + trampoline code which retries the message receive before running + the signal handler. + + To do this we change the OPTION argument in its registers to + enable only message reception, since the request message has + already been sent. */ + + /* The system call arguments are stored in consecutive registers + starting with r3. */ + struct mach_msg_trap_args *args = (void *) &state->basic.r3; + + if (_hurdsig_catch_memory_fault (args)) + { + /* Faulted accessing ARGS. Bomb. */ + return NULL; + } + + assert (args->option & MACH_RCV_MSG); + /* Disable the message-send, since it has already completed. The + calls we retry need only wait to receive the reply message. */ + args->option &= ~MACH_SEND_MSG; + + /* Limit the time to receive the reply message, in case the server + claimed that `interrupt_operation' succeeded but in fact the RPC + is hung. */ + args->option |= MACH_RCV_TIMEOUT; + args->timeout = _hurd_interrupted_rpc_timeout; + + _hurdsig_end_catch_fault (); + + state->basic.PC = (int) rpc_wait_trampoline; + /* After doing the message receive, the trampoline code will need to + update the r3 value to be restored by sigreturn. To simplify + the assembly code, we pass the address of its slot in SCP to the + trampoline code in r10. */ + state->basic.r10 = (long int) &scp->sc_gprs[3]; + /* We must preserve the mach_msg_trap args in r3..r9. + Pass the handler args to the trampoline code in r11..r13. */ + state->basic.r11 = signo; + state->basic.r12 = detail->code; + state->basic.r13 = (int) scp; + } + else + { + state->basic.PC = (int) trampoline; + state->basic.r3 = signo; + state->basic.r4 = detail->code; + state->basic.r5 = (int) scp; + } + + state->basic.r1 = (int) sigsp; /* r1 is the stack pointer. */ + + /* We pass the handler function to the trampoline code in ctr. */ + state->basic.ctr = (int) handler; + /* In r15, we store the address of __sigreturn itself, + for the trampoline code to use. */ + state->basic.r15 = (int) &__sigreturn; + /* In r16, we save the SCP value to pass to __sigreturn + after the handler returns. */ + state->basic.r16 = (int) scp; + + /* In r3, we store a pointer to the registers in STATE so that the + trampoline code can load the registers from that. For some reason, + thread_set_state doesn't set all registers. */ + state->basic.r17 = state->basic.r3; /* Store the real r3 in r17. */ + state->basic.r3 = (int) &state->basic.r0; + + return scp; +} + +/* The trampoline code follows. This used to be located inside + _hurd_setup_sighandler, but was optimized away by gcc 2.95. */ + +/* This function sets some registers which the trampoline code uses + and which are not automatically set by thread_set_state. + In r3 we have a pointer to the registers in STATE. */ +asm ("trampoline_load_registers:\n" + "lwz 17,68(3)\n" /* The real r3. */ + "lwz 4,16(3)\n" + "lwz 5,20(3)\n" + "lwz 6,24(3)\n" + "lwz 7,28(3)\n" + "lwz 8,32(3)\n" + "lwz 9,36(3)\n" + "lwz 10,40(3)\n" + "lwz 11,44(3)\n" + "lwz 12,48(3)\n" + "lwz 13,52(3)\n" + "lwz 14,56(3)\n" + "lwz 15,60(3)\n" + "lwz 16,64(3)\n" + "mr 3,17\n" + "blr\n"); + +asm ("rpc_wait_trampoline:\n"); + /* This is the entry point when we have an RPC reply message to receive + before running the handler. The MACH_MSG_SEND bit has already been + cleared in the OPTION argument in our registers. For our convenience, + r10 points to the sc_regs[3] member of the sigcontext (saved r3). */ + +asm (/* Retry the interrupted mach_msg system call. */ + "bl trampoline_load_registers\n" + "li 0, -25\n" /* mach_msg_trap */ + "sc\n" + /* When the sigcontext was saved, r3 was MACH_RCV_INTERRUPTED. But + now the message receive has completed and the original caller of + the RPC (i.e. the code running when the signal arrived) needs to + see the final return value of the message receive in r3. So + store the new r3 value into the sc_regs[3] member of the sigcontext + (whose address is in r10 to make this code simpler). */ + "stw 3, 0(10)\n" + /* Since the argument registers needed to have the mach_msg_trap + arguments, we've stored the arguments to the handler function + in registers r11..r13 of the state structure. */ + "mr 3,11\n" + "mr 4,12\n" + "mr 5,13\n"); + +asm ("trampoline:\n"); + /* Entry point for running the handler normally. The arguments to the + handler function are already in the standard registers: + + r3 SIGNO + r4 SIGCODE + r5 SCP + + r16 also contains SCP; this value is callee-saved (and so should not get + clobbered by running the handler). We use this saved value to pass to + __sigreturn, so the handler can clobber the argument registers if it + likes. */ +asm ("bl trampoline_load_registers\n" + "bctrl\n" /* Call the handler function. */ + "mtctr 15\n" /* Copy &__sigreturn to CTR. */ + "mr 3,16\n" /* Copy the saved SCP to r3. */ + "bctr\n" /* Call __sigreturn (SCP). */ + ); diff --git a/libc/sysdeps/mach/hurd/ppoll.c b/libc/sysdeps/mach/hurd/ppoll.c new file mode 100644 index 000000000..693bc1383 --- /dev/null +++ b/libc/sysdeps/mach/hurd/ppoll.c @@ -0,0 +1,30 @@ +/* poll file descriptors. Hurd version. + Copyright (C) 2006 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 <sys/poll.h> +#include <sys/time.h> +#include <hurd.h> +#include <hurd/fd.h> + +int +ppoll (struct pollfd *fds, nfds_t nfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + return _hurd_select (nfds, fds, NULL, NULL, NULL, timeout, sigmask); +} diff --git a/libc/sysdeps/mach/hurd/pread.c b/libc/sysdeps/mach/hurd/pread.c new file mode 100644 index 000000000..a14553be7 --- /dev/null +++ b/libc/sysdeps/mach/hurd/pread.c @@ -0,0 +1,33 @@ +/* Read block from given position in file without changing file pointer. + Hurd version. + Copyright (C) 1999,2001,02 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 <unistd.h> + +ssize_t +__libc_pread (int fd, void *buf, size_t nbytes, off_t offset) +{ + return __libc_pread64 (fd, buf, nbytes, (off64_t) offset); +} + +#ifndef __libc_pread +strong_alias (__libc_pread, __pread) +weak_alias (__libc_pread, pread) +#endif diff --git a/libc/sysdeps/mach/hurd/pread64.c b/libc/sysdeps/mach/hurd/pread64.c new file mode 100644 index 000000000..fc69ae505 --- /dev/null +++ b/libc/sysdeps/mach/hurd/pread64.c @@ -0,0 +1,39 @@ +/* Read block from given position in file without changing file pointer. + Hurd version. + Copyright (C) 2001,02 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 <unistd.h> +#include <hurd/fd.h> + +ssize_t +__libc_pread64 (int fd, void *buf, size_t nbytes, off64_t offset) +{ + error_t err; + if (offset < 0) + err = EINVAL; + else + err = HURD_FD_USE (fd, _hurd_fd_read (descriptor, buf, &nbytes, offset)); + return err ? __hurd_dfail (fd, err) : nbytes; +} + +#ifndef __libc_pread64 +weak_alias (__libc_pread64, __pread64) +weak_alias (__libc_pread64, pread64) +#endif diff --git a/libc/sysdeps/mach/hurd/prof-freq.c b/libc/sysdeps/mach/hurd/prof-freq.c new file mode 100644 index 000000000..a3707033a --- /dev/null +++ b/libc/sysdeps/mach/hurd/prof-freq.c @@ -0,0 +1,2 @@ +/* __profile_frequency is in sysdeps/mach/hurd/profil.c. This file +is here as a place-holder to prevent the use of sysdeps/generic/prof-freq.c. */ diff --git a/libc/sysdeps/mach/hurd/profil.c b/libc/sysdeps/mach/hurd/profil.c new file mode 100644 index 000000000..0426f67b6 --- /dev/null +++ b/libc/sysdeps/mach/hurd/profil.c @@ -0,0 +1,285 @@ +/* Low-level statistical profiling support function. Mach/Hurd version. + Copyright (C) 1995, 1996, 1997, 2000, 2002, 2005 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 <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <hurd.h> +#include <mach/mach4.h> +#include <mach/pc_sample.h> +#include <cthreads.h> +#include <assert.h> +#include <libc-internal.h> + + +#define MAX_PC_SAMPLES 512 /* XXX ought to be exported in kernel hdr */ + +static thread_t profile_thread = MACH_PORT_NULL; +static u_short *samples; +static size_t maxsamples; +static size_t pc_offset; +static size_t sample_scale; +static sampled_pc_seqno_t seqno; +static spin_lock_t lock = SPIN_LOCK_INITIALIZER; +static mach_msg_timeout_t collector_timeout; /* ms between collections. */ +static int profile_tick; + +/* Reply port used by profiler thread */ +static mach_port_t profil_reply_port; + +/* Forwards */ +static kern_return_t profil_task_get_sampled_pcs (mach_port_t, + sampled_pc_seqno_t *, + sampled_pc_array_t, + mach_msg_type_number_t *); +static void fetch_samples (void); +static void profile_waiter (void); + +/* Enable statistical profiling, writing samples of the PC into at most + SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling + is enabled, the system examines the user PC and increments + SAMPLE_BUFFER[((PC - OFFSET) / 2) * SCALE / 65536]. If SCALE is zero, + disable profiling. Returns zero on success, -1 on error. */ + +static error_t +update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale) +{ + error_t err; + + if (profile_thread == MACH_PORT_NULL) + { + /* Set up the profiling collector thread. */ + err = __thread_create (__mach_task_self (), &profile_thread); + if (! err) + err = __mach_setup_thread (__mach_task_self (), profile_thread, + &profile_waiter, NULL, NULL); + } + else + err = 0; + + if (! err) + { + err = __task_enable_pc_sampling (__mach_task_self (), &profile_tick, + SAMPLED_PC_PERIODIC); + if (!err && sample_scale == 0) + /* Profiling was not turned on, so the collector thread was + suspended. Resume it. */ + err = __thread_resume (profile_thread); + if (! err) + { + samples = sample_buffer; + maxsamples = size / sizeof *sample_buffer; + pc_offset = offset; + sample_scale = scale; + /* Calculate a good period for the collector thread. From TICK + and the kernel buffer size we get the length of time it takes + to fill the buffer; translate that to milliseconds for + mach_msg, and chop it in half for general lag factor. */ + collector_timeout = MAX_PC_SAMPLES * profile_tick / 1000 / 2; + } + } + + return err; +} + +int +__profile_frequency (void) +{ + return profile_tick; +} +libc_hidden_def (__profile_frequency) + +int +__profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale) +{ + error_t err; + + __spin_lock (&lock); + + if (scale == 0) + { + /* Disable profiling. */ + int count; + + if (profile_thread != MACH_PORT_NULL) + __thread_suspend (profile_thread); + + /* Fetch the last set of samples */ + if (sample_scale) + fetch_samples (); + + err = __task_disable_pc_sampling (__mach_task_self (), &count); + sample_scale = 0; + seqno = 0; + } + else + err = update_waiter (sample_buffer, size, offset, scale); + + __spin_unlock (&lock); + + return err ? __hurd_fail (err) : 0; +} +weak_alias (__profil, profil) + +/* Fetch PC samples. This function must be very careful not to depend + on Hurd threadvar variables. We arrange that by using a special + stub arranged for at the end of this file. */ +static void +fetch_samples (void) +{ + sampled_pc_t pc_samples[MAX_PC_SAMPLES]; + mach_msg_type_number_t nsamples, i; + error_t err; + + nsamples = MAX_PC_SAMPLES; + + err = profil_task_get_sampled_pcs (__mach_task_self (), &seqno, + pc_samples, &nsamples); + if (err) + { + static error_t special_profil_failure; + static volatile int a, b, c; + + special_profil_failure = err; + a = 1; + b = 0; + while (1) + c = a / b; + } + + for (i = 0; i < nsamples; ++i) + { + /* Do arithmetic in long long to avoid overflow problems. */ + long long pc_difference = pc_samples[i].pc - pc_offset; + size_t idx = ((pc_difference / 2) * sample_scale) / 65536; + if (idx < maxsamples) + ++samples[idx]; + } +} + + +/* This function must be very careful not to depend on Hurd threadvar + variables. We arrange that by using special stubs arranged for at the + end of this file. */ +static void +profile_waiter (void) +{ + mach_msg_header_t msg; + mach_port_t timeout_reply_port; + + profil_reply_port = __mach_reply_port (); + timeout_reply_port = __mach_reply_port (); + + while (1) + { + __spin_lock (&lock); + + fetch_samples (); + + __spin_unlock (&lock); + + __mach_msg (&msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof msg, + timeout_reply_port, collector_timeout, MACH_PORT_NULL); + } +} + +/* Fork interaction */ + +/* Before fork, lock the interlock so that we are in a clean state. */ +static void +fork_profil_prepare (void) +{ + __spin_lock (&lock); +} +text_set_element (_hurd_fork_prepare_hook, fork_profil_prepare); + +/* In the parent, unlock the interlock once fork is complete. */ +static void +fork_profil_parent (void) +{ + __spin_unlock (&lock); +} +text_set_element (_hurd_fork_parent_hook, fork_profil_parent); + +/* In the childs, unlock the interlock, and start a profiling thread up + if necessary. */ +static void +fork_profil_child (void) +{ + u_short *sb; + size_t n, o, ss; + error_t err; + + __spin_unlock (&lock); + + if (profile_thread != MACH_PORT_NULL) + { + __mach_port_deallocate (__mach_task_self (), profile_thread); + profile_thread = MACH_PORT_NULL; + } + + sb = samples; + samples = NULL; + n = maxsamples; + maxsamples = 0; + o = pc_offset; + pc_offset = 0; + ss = sample_scale; + sample_scale = 0; + + if (ss != 0) + { + err = update_waiter (sb, n * sizeof *sb, o, ss); + assert_perror (err); + } +} +text_set_element (_hurd_fork_child_hook, fork_profil_child); + + + + +/* Special RPC stubs for profile_waiter are made by including the normal + source code, with special CPP state to prevent it from doing the + usual thing. */ + +/* Include these first; then our #define's will take full effect, not + being overridden. */ +#include <mach/mig_support.h> + +/* This need not do anything; it is always associated with errors, which + are fatal in profile_waiter anyhow. */ +#define __mig_put_reply_port(foo) + +/* Use our static variable instead of the usual threadvar mechanism for + this. */ +#define __mig_get_reply_port() profil_reply_port + +/* Make the functions show up as static */ +#define mig_external static + +/* Turn off the attempt to generate ld aliasing records. */ +#undef weak_alias +#define weak_alias(a,b) + +/* And change their names to avoid confusing disasters. */ +#define __vm_deallocate_rpc profil_vm_deallocate +#define __task_get_sampled_pcs profil_task_get_sampled_pcs + +/* And include the source code */ +#include <../mach/RPC_task_get_sampled_pcs.c> diff --git a/libc/sysdeps/mach/hurd/pselect.c b/libc/sysdeps/mach/hurd/pselect.c new file mode 100644 index 000000000..b67122919 --- /dev/null +++ b/libc/sysdeps/mach/hurd/pselect.c @@ -0,0 +1,45 @@ +/* pselect for Hurd. + Copyright (C) 1998 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 <signal.h> +#include <sys/time.h> +#include <sys/select.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Additionally set the sigmask + SIGMASK for this call. Returns the number of ready descriptors, or -1 for + errors. */ +int +__pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask) + int nfds; + fd_set *readfds; + fd_set *writefds; + fd_set *exceptfds; + const struct timespec *timeout; + const sigset_t *sigmask; +{ + return _hurd_select (nfds, NULL, + readfds, writefds, exceptfds, timeout, sigmask); +} +weak_alias (__pselect, pselect) diff --git a/libc/sysdeps/mach/hurd/ptrace.c b/libc/sysdeps/mach/hurd/ptrace.c new file mode 100644 index 000000000..8f04c130f --- /dev/null +++ b/libc/sysdeps/mach/hurd/ptrace.c @@ -0,0 +1,386 @@ +/* Process tracing interface `ptrace' for GNU Hurd. + Copyright (C) 1991, 92, 93, 95, 96, 97 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/ptrace.h> +#include <sys/types.h> +#include <stdarg.h> +#include <hurd.h> +#include <hurd/signal.h> +#include <hurd/msg.h> +#include <thread_state.h> + +/* Perform process tracing functions. REQUEST is one of the values + in <sys/ptrace.h>, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after PID. */ +int +ptrace (enum __ptrace_request request, ... ) +{ + pid_t pid; + void *addr, *addr2; + natural_t data; + va_list ap; + + /* Read data from PID's address space, from ADDR for DATA bytes. */ + error_t read_data (task_t task, vm_address_t *ourpage, vm_size_t *size) + { + /* Read the pages containing the addressed range. */ + error_t err; + *size = round_page (addr + data) - trunc_page (addr); + err = __vm_read (task, trunc_page (addr), *size, ourpage, size); + return err; + } + + /* Fetch the thread port for PID's user thread. */ + error_t fetch_user_thread (task_t task, thread_t *thread) + { + thread_t threadbuf[3], *threads = threadbuf; + mach_msg_type_number_t nthreads = 3, i; + error_t err = __task_threads (task, &threads, &nthreads); + if (err) + return err; + if (nthreads == 0) + return EINVAL; + *thread = threads[0]; /* Assume user thread is first. */ + for (i = 1; i < nthreads; ++i) + __mach_port_deallocate (__mach_task_self (), threads[i]); + if (threads != threadbuf) + __vm_deallocate (__mach_task_self (), + (vm_address_t) threads, nthreads * sizeof threads[0]); + return 0; + } + + /* Fetch a thread state structure from PID and store it at ADDR. */ + int get_regs (int flavor, mach_msg_type_number_t count) + { + error_t err; + task_t task = __pid2task (pid); + thread_t thread; + if (task == MACH_PORT_NULL) + return -1; + err = fetch_user_thread (task, &thread); + __mach_port_deallocate (__mach_task_self (), task); + if (!err) + err = __thread_get_state (thread, flavor, addr, &count); + __mach_port_deallocate (__mach_task_self (), thread); + return err ? __hurd_fail (err) : 0; + } + + + switch (request) + { + case PTRACE_TRACEME: + /* Make this process be traced. */ + __sigfillset (&_hurdsig_traced); + __USEPORT (PROC, __proc_mark_traced (port)); + break; + + case PTRACE_CONT: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + data = va_arg (ap, int); + va_end (ap); + { + /* Send a DATA signal to PID, telling it to take the signal + normally even if it's traced. */ + error_t err; + task_t task = __pid2task (pid); + if (task == MACH_PORT_NULL) + return -1; + if (data == SIGKILL) + err = __task_terminate (task); + else + { + if (addr != (void *) 1) + { + /* Move the user thread's PC to ADDR. */ + thread_t thread; + err = fetch_user_thread (task, &thread); + if (!err) + { + struct machine_thread_state state; + mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT; + err = __thread_get_state (thread, + MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state, &count); + if (!err) + { + MACHINE_THREAD_STATE_SET_PC (&state, addr); + err = __thread_set_state (thread, + MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state, count); + } + + } + __mach_port_deallocate (__mach_task_self (), thread); + } + else + err = 0; + + if (! err) + /* Tell the process to take the signal (or just resume if 0). */ + err = HURD_MSGPORT_RPC + (__USEPORT (PROC, __proc_getmsgport (port, pid, &msgport)), + 0, 0, __msg_sig_post_untraced (msgport, data, 0, task)); + } + __mach_port_deallocate (__mach_task_self (), task); + return err ? __hurd_fail (err) : 0; + } + + case PTRACE_KILL: + va_start (ap, request); + pid = va_arg (ap, pid_t); + va_end (ap); + /* SIGKILL always just terminates the task, + so normal kill is just the same when traced. */ + return kill (pid, SIGKILL); + + case PTRACE_SINGLESTEP: + /* This is a machine-dependent kernel RPC on + machines that support it. Punt. */ + return EOPNOTSUPP; + + case PTRACE_ATTACH: + case PTRACE_DETACH: + va_start (ap, request); + pid = va_arg (ap, pid_t); + va_end (ap); + { + /* Tell PID to set or clear its trace bit. */ + error_t err; + mach_port_t msgport; + task_t task = __pid2task (pid); + if (task == MACH_PORT_NULL) + return -1; + err = __USEPORT (PROC, __proc_getmsgport (port, pid, &msgport)); + if (! err) + { + err = __msg_set_init_int (msgport, task, INIT_TRACEMASK, + request == PTRACE_DETACH ? 0 : + ~(sigset_t) 0); + if (! err) + { + if (request == PTRACE_ATTACH) + /* Now stop the process. */ + err = __msg_sig_post (msgport, SIGSTOP, 0, task); + else + /* Resume the process from tracing stop. */ + err = __msg_sig_post_untraced (msgport, 0, 0, task); + } + __mach_port_deallocate (__mach_task_self (), msgport); + } + __mach_port_deallocate (__mach_task_self (), task); + return err ? __hurd_fail (err) : 0; + } + + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + va_end (ap); + { + /* Read the page (or two pages, if the word lies on a boundary) + containing the addressed word. */ + error_t err; + vm_address_t ourpage; + vm_size_t size; + natural_t word; + task_t task = __pid2task (pid); + if (task == MACH_PORT_NULL) + return -1; + data = sizeof word; + ourpage = 0; + size = 0; + err = read_data (task, &ourpage, &size); + __mach_port_deallocate (__mach_task_self (), task); + if (err) + return __hurd_fail (err); + word = *(natural_t *) ((vm_address_t) addr - trunc_page (addr) + + ourpage); + __vm_deallocate (__mach_task_self (), ourpage, size); + return word; + } + + case PTRACE_PEEKUSER: + case PTRACE_POKEUSER: + /* U area, what's that? */ + return EOPNOTSUPP; + + case PTRACE_GETREGS: + case PTRACE_SETREGS: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + va_end (ap); + return get_regs (MACHINE_THREAD_STATE_FLAVOR, + MACHINE_THREAD_STATE_COUNT); + + case PTRACE_GETFPREGS: + case PTRACE_SETFPREGS: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + va_end (ap); +#ifdef MACHINE_THREAD_FLOAT_STATE_FLAVOR + return get_regs (MACHINE_THREAD_FLOAT_STATE_FLAVOR, + MACHINE_THREAD_FLOAT_STATE_COUNT); +#else + return EOPNOTSUPP; +#endif + + case PTRACE_GETFPAREGS: + case PTRACE_SETFPAREGS: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + va_end (ap); +#ifdef MACHINE_THREAD_FPA_STATE_FLAVOR + return get_regs (MACHINE_THREAD_FPA_STATE_FLAVOR, + MACHINE_THREAD_FPA_STATE_COUNT); +#else + return EOPNOTSUPP; +#endif + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + data = va_arg (ap, int); + va_end (ap); + { + /* Read the page (or two pages, if the word lies on a boundary) + containing the addressed word. */ + error_t err; + vm_address_t ourpage; + vm_size_t size; + task_t task = __pid2task (pid); + if (task == MACH_PORT_NULL) + return -1; + data = sizeof (natural_t); + ourpage = 0; + size = 0; + err = read_data (task, &ourpage, &size); + + if (!err) + { + /* Now modify the specified word and write the page back. */ + *(natural_t *) ((vm_address_t) addr - trunc_page (addr) + + ourpage) = data; + err = __vm_write (task, trunc_page (addr), ourpage, size); + __vm_deallocate (__mach_task_self (), ourpage, size); + } + + __mach_port_deallocate (__mach_task_self (), task); + return err ? __hurd_fail (err) : 0; + } + + case PTRACE_READDATA: + case PTRACE_READTEXT: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + data = va_arg (ap, int); + addr2 = va_arg (ap, void *); + va_end (ap); + { + error_t err; + vm_address_t ourpage; + vm_size_t size; + task_t task = __pid2task (pid); + if (task == MACH_PORT_NULL) + return -1; + if (((vm_address_t) addr2 + data) % __vm_page_size == 0) + { + /* Perhaps we can write directly to the user's buffer. */ + ourpage = (vm_address_t) addr2; + size = data; + } + else + { + ourpage = 0; + size = 0; + } + err = read_data (task, &ourpage, &size); + __mach_port_deallocate (__mach_task_self (), task); + if (!err && ourpage != (vm_address_t) addr2) + { + memcpy (addr2, (void *) ourpage, data); + __vm_deallocate (__mach_task_self (), ourpage, size); + } + return err ? __hurd_fail (err) : 0; + } + + case PTRACE_WRITEDATA: + case PTRACE_WRITETEXT: + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + data = va_arg (ap, int); + addr2 = va_arg (ap, void *); + va_end (ap); + { + error_t err; + vm_address_t ourpage; + vm_size_t size; + task_t task = __pid2task (pid); + if (task == MACH_PORT_NULL) + return -1; + if ((vm_address_t) addr % __vm_page_size == 0 && + (vm_address_t) data % __vm_page_size == 0) + { + /* Writing whole pages; can go directly from the user's buffer. */ + ourpage = (vm_address_t) addr2; + size = data; + err = 0; + } + else + { + /* Read the task's pages and modify our own copy. */ + ourpage = 0; + size = 0; + err = read_data (task, &ourpage, &size); + if (!err) + memcpy ((void *) ((vm_address_t) addr - trunc_page (addr) + + ourpage), + addr2, + data); + } + if (!err) + /* Write back the modified pages. */ + err = __vm_write (task, trunc_page (addr), ourpage, size); + __mach_port_deallocate (__mach_task_self (), task); + return err ? __hurd_fail (err) : 0; + } + + default: + errno = EINVAL; + return -1; + } + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/ptsname.c b/libc/sysdeps/mach/hurd/ptsname.c new file mode 100644 index 000000000..b68cd9c2e --- /dev/null +++ b/libc/sysdeps/mach/hurd/ptsname.c @@ -0,0 +1,65 @@ +/* ptsname -- return the name of a pty slave given an FD to the pty master + Copyright (C) 1999 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 <string.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/term.h> + + +/* Return the pathname of the pseudo terminal slave associated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +char * +ptsname (int fd) +{ + static char peername[1024]; /* XXX */ + error_t err; + + err = __ptsname_r (fd, peername, sizeof (peername)); + if (err) + __set_errno (err); + + return err ? NULL : peername; +} + + +/* 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) +{ + char peername[1024]; /* XXX */ + size_t len; + error_t err; + + peername[0] = '\0'; + if (err = HURD_DPORT_USE (fd, __term_get_peername (port, peername))) + return _hurd_fd_error (fd, err); + + len = strlen (peername) + 1; + if (len > buflen) + return ERANGE; + + memcpy (buf, peername, len); + return 0; +} +weak_alias (__ptsname_r, ptsname_r) diff --git a/libc/sysdeps/mach/hurd/pwrite.c b/libc/sysdeps/mach/hurd/pwrite.c new file mode 100644 index 000000000..42236e4c3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/pwrite.c @@ -0,0 +1,35 @@ +/* Write block at given position in file without changing file pointer. + Hurd version. + Copyright (C) 1999,2001,02 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 <unistd.h> + +/* Write NBYTES of BUF to FD at given position OFFSET without changing + the file position. Return the number written, or -1. */ +ssize_t +__libc_pwrite (int fd, const void *buf, size_t nbytes, off_t offset) +{ + return __libc_pwrite64 (fd, buf, nbytes, (off64_t) offset); +} + +#ifndef __libc_pwrite +strong_alias (__libc_pwrite, __pwrite) +weak_alias (__libc_pwrite, pwrite) +#endif diff --git a/libc/sysdeps/mach/hurd/pwrite64.c b/libc/sysdeps/mach/hurd/pwrite64.c new file mode 100644 index 000000000..2637003ca --- /dev/null +++ b/libc/sysdeps/mach/hurd/pwrite64.c @@ -0,0 +1,40 @@ +/* Write block to given position in file without changing file pointer. + Hurd version. + Copyright (C) 2001,02 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 <unistd.h> +#include <hurd/fd.h> + +ssize_t +__libc_pwrite64 (int fd, const void *buf, size_t nbytes, off64_t offset) +{ + error_t err; + if (offset < 0) + err = EINVAL; + else + err = HURD_FD_USE (fd, _hurd_fd_write (descriptor, buf, &nbytes, offset)); + return err ? __hurd_dfail (fd, err) : nbytes; +} + +#ifndef __libc_pwrite64 +weak_alias (__libc_pwrite64, __pwrite64) +libc_hidden_weak (__pwrite64) +weak_alias (__libc_pwrite64, pwrite64) +#endif diff --git a/libc/sysdeps/mach/hurd/read.c b/libc/sysdeps/mach/hurd/read.c new file mode 100644 index 000000000..d32cb85d7 --- /dev/null +++ b/libc/sysdeps/mach/hurd/read.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1993,94,95,97,98,99,2001,02 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 <unistd.h> +#include <hurd/fd.h> + +/* Read NBYTES into BUF from FD. Return the number read or -1. */ +ssize_t +__libc_read (int fd, void *buf, size_t nbytes) +{ + error_t err = HURD_FD_USE (fd, _hurd_fd_read (descriptor, buf, &nbytes, -1)); + return err ? __hurd_dfail (fd, err) : nbytes; +} +libc_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libc_hidden_weak (__read) +weak_alias (__libc_read, read) diff --git a/libc/sysdeps/mach/hurd/readdir.c b/libc/sysdeps/mach/hurd/readdir.c new file mode 100644 index 000000000..4bf19564d --- /dev/null +++ b/libc/sysdeps/mach/hurd/readdir.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1993,94,95,96,97,2002 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 <stddef.h> +#include <dirent.h> +#include <unistd.h> +#include <endian.h> +#include <assert.h> + +/* Read a directory entry from DIRP. */ +struct dirent * +__readdir (DIR *dirp) +{ + struct dirent64 *entry64 = __readdir64 (dirp); + + if (sizeof (struct dirent64) == sizeof (struct dirent)) + /* We should in fact just be an alias to readdir64 on this machine. */ + return (struct dirent *) entry64; + + /* These are all compile-time constants. We know that d_ino is the first + member and that the layout of the following members matches exactly in + both structures. */ + assert (offsetof (struct dirent, d_ino) == 0); + assert (offsetof (struct dirent64, d_ino) == 0); +# define MATCH(memb) \ + assert (offsetof (struct dirent64, memb) - sizeof (entry64->d_ino) \ + == offsetof (struct dirent, memb) - sizeof (ino_t)) + MATCH (d_reclen); + MATCH (d_type); + MATCH (d_namlen); +# undef MATCH + + if (entry64 == NULL) + return NULL; + + struct dirent *const entry = ((void *) (&entry64->d_ino + 1) + - sizeof entry->d_ino); + const ino_t d_ino = entry64->d_ino; + if (d_ino != entry64->d_ino) + { + __set_errno (EOVERFLOW); + return NULL; + } +# if BYTE_ORDER != BIG_ENDIAN /* We just skipped over the zero high word. */ + entry->d_ino = d_ino; /* ... or the nonzero low word, swap it. */ +# endif + entry->d_reclen -= sizeof entry64->d_ino - sizeof entry->d_ino; + return entry; +} + +weak_alias (__readdir, readdir) diff --git a/libc/sysdeps/mach/hurd/readdir64.c b/libc/sysdeps/mach/hurd/readdir64.c new file mode 100644 index 000000000..1953e81b3 --- /dev/null +++ b/libc/sysdeps/mach/hurd/readdir64.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2001,02 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 <dirent.h> +#include <stddef.h> +#include <hurd.h> +#include <hurd/fs.h> +#include <hurd/fd.h> +#include "dirstream.h" + +/* Read a directory entry from DIRP. */ +struct dirent64 * +__readdir64 (DIR *dirp) +{ + struct dirent64 *dp; + + if (dirp == NULL) + { + errno = EINVAL; + return NULL; + } + + __libc_lock_lock (dirp->__lock); + + do + { + if (dirp->__ptr - dirp->__data >= dirp->__size) + { + /* We've emptied out our buffer. Refill it. */ + + char *data = dirp->__data; + int nentries; + error_t err; + + if (err = HURD_FD_PORT_USE (dirp->__fd, + __dir_readdir (port, + &data, &dirp->__size, + dirp->__entry_ptr, + -1, 0, &nentries))) + { + __hurd_fail (err); + dp = NULL; + break; + } + + /* DATA now corresponds to entry index DIRP->__entry_ptr. */ + dirp->__entry_data = dirp->__entry_ptr; + + if (data != dirp->__data) + { + /* The data was passed out of line, so our old buffer is no + longer useful. Deallocate the old buffer and reset our + information for the new buffer. */ + __vm_deallocate (__mach_task_self (), + (vm_address_t) dirp->__data, + dirp->__allocation); + dirp->__data = data; + dirp->__allocation = round_page (dirp->__size); + } + + /* Reset the pointer into the buffer. */ + dirp->__ptr = dirp->__data; + + if (nentries == 0) + { + /* End of file. */ + dp = NULL; + break; + } + + /* We trust the filesystem to return correct data and so we + ignore NENTRIES. */ + } + + dp = (struct dirent64 *) dirp->__ptr; + dirp->__ptr += dp->d_reclen; + ++dirp->__entry_ptr; + + /* Loop to ignore deleted files. */ + } while (dp->d_fileno == 0); + + __libc_lock_unlock (dirp->__lock); + + return dp; +} + +weak_alias (__readdir64, readdir64) diff --git a/libc/sysdeps/mach/hurd/readdir64_r.c b/libc/sysdeps/mach/hurd/readdir64_r.c new file mode 100644 index 000000000..5b5a7fe36 --- /dev/null +++ b/libc/sysdeps/mach/hurd/readdir64_r.c @@ -0,0 +1,112 @@ +/* Copyright (C) 2001,02 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 <dirent.h> +#include <stddef.h> +#include <string.h> +#include <hurd.h> +#include <hurd/fs.h> +#include <hurd/fd.h> +#include "dirstream.h" + +/* Read a directory entry from DIRP. */ +int +__readdir64_r (DIR *dirp, struct dirent64 *entry, struct dirent64 **result) +{ + struct dirent64 *dp; + error_t err = 0; + + if (dirp == NULL) + { + errno = EINVAL; + return errno; + } + + __libc_lock_lock (dirp->__lock); + + do + { + if (dirp->__ptr - dirp->__data >= dirp->__size) + { + /* We've emptied out our buffer. Refill it. */ + + char *data = dirp->__data; + int nentries; + + if (err = HURD_FD_PORT_USE (dirp->__fd, + __dir_readdir (port, + &data, &dirp->__size, + dirp->__entry_ptr, + -1, 0, &nentries))) + { + __hurd_fail (err); + dp = NULL; + break; + } + + /* DATA now corresponds to entry index DIRP->__entry_ptr. */ + dirp->__entry_data = dirp->__entry_ptr; + + if (data != dirp->__data) + { + /* The data was passed out of line, so our old buffer is no + longer useful. Deallocate the old buffer and reset our + information for the new buffer. */ + __vm_deallocate (__mach_task_self (), + (vm_address_t) dirp->__data, + dirp->__allocation); + dirp->__data = data; + dirp->__allocation = round_page (dirp->__size); + } + + /* Reset the pointer into the buffer. */ + dirp->__ptr = dirp->__data; + + if (nentries == 0) + { + /* End of file. */ + dp = NULL; + break; + } + + /* We trust the filesystem to return correct data and so we + ignore NENTRIES. */ + } + + dp = (struct dirent64 *) dirp->__ptr; + dirp->__ptr += dp->d_reclen; + ++dirp->__entry_ptr; + + /* Loop to ignore deleted files. */ + } while (dp->d_fileno == 0); + + if (dp) + { + *entry = *dp; + memcpy (entry->d_name, dp->d_name, dp->d_namlen + 1); + *result = entry; + } + else + *result = NULL; + + __libc_lock_unlock (dirp->__lock); + + return dp ? 0 : err ? errno : 0; +} + +weak_alias (__readdir64_r, readdir64_r) diff --git a/libc/sysdeps/mach/hurd/readdir_r.c b/libc/sysdeps/mach/hurd/readdir_r.c new file mode 100644 index 000000000..b740721db --- /dev/null +++ b/libc/sysdeps/mach/hurd/readdir_r.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1993,94,95,96,97,2001,02 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 <limits.h> +#include <stddef.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <hurd.h> +#include <hurd/fd.h> +#include "dirstream.h" + + +/* Read a directory entry from DIRP. */ +int +__readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result) +{ + if (sizeof (struct dirent64) == sizeof (struct dirent)) + /* We should in fact just be an alias to readdir64_r on this machine. */ + return __readdir64_r (dirp, + (struct dirent64 *) entry, + (struct dirent64 **) result); + + struct dirent64 *result64; + union + { + struct dirent64 d; + char b[offsetof (struct dirent64, d_name) + UCHAR_MAX + 1]; + } u; + int err; + + err = __readdir64_r (dirp, &u.d, &result64); + if (result64) + { + entry->d_fileno = result64->d_fileno; + entry->d_reclen = result64->d_reclen; + entry->d_type = result64->d_type; + entry->d_namlen = result64->d_namlen; + memcpy (entry->d_name, result64->d_name, result64->d_namlen + 1); + *result = entry; + } + else + *result = NULL; + + return err; +} + +weak_alias (__readdir_r, readdir_r) diff --git a/libc/sysdeps/mach/hurd/readlink.c b/libc/sysdeps/mach/hurd/readlink.c new file mode 100644 index 000000000..f95b6c0b8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/readlink.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1991,92,93,94,95,97,2002 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 <unistd.h> +#include <hurd.h> +#include <hurd/paths.h> +#include <fcntl.h> +#include <string.h> + +/* Read the contents of the symbolic link FILE_NAME into no more than + LEN bytes of BUF. The contents are not null-terminated. + Returns the number of characters read, or -1 for errors. */ +ssize_t +__readlink (file_name, buf, len) + const char *file_name; + char *buf; + size_t len; +{ + error_t err; + file_t file; + struct stat64 st; + + file = __file_name_lookup (file_name, O_READ | O_NOLINK, 0); + if (file == MACH_PORT_NULL) + return -1; + + err = __io_stat (file, &st); + if (! err) + if (S_ISLNK (st.st_mode)) + { + char *rbuf = buf; + + err = __io_read (file, &rbuf, &len, 0, len); + if (!err && rbuf != buf) + { + memcpy (buf, rbuf, len); + __vm_deallocate (__mach_task_self (), (vm_address_t)rbuf, len); + } + } + else + err = EINVAL; + + __mach_port_deallocate (__mach_task_self (), file); + + if (err) + return __hurd_fail (err); + else + return len; +} +weak_alias (__readlink, readlink) diff --git a/libc/sysdeps/mach/hurd/reboot.c b/libc/sysdeps/mach/hurd/reboot.c new file mode 100644 index 000000000..2e43e0d11 --- /dev/null +++ b/libc/sysdeps/mach/hurd/reboot.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1992,93,94,97,98,2001 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 <unistd.h> +#include <hurd.h> +#include <hurd/startup.h> +#include <sys/reboot.h> + +/* Reboot the system. */ +int +reboot (int howto) +{ + error_t err; + startup_t init; + mach_port_t hostpriv; + + err = __get_privileged_ports (&hostpriv, NULL); + if (err) + return __hurd_fail (EPERM); + + err = __USEPORT (PROC, __proc_getmsgport (port, 1, &init)); + if (!err) + { + err = __startup_reboot (init, hostpriv, howto); + __mach_port_deallocate (__mach_task_self (), init); + } + + __mach_port_deallocate (__mach_task_self (), hostpriv); + + if (err) + return __hurd_fail (err); + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/recv.c b/libc/sysdeps/mach/hurd/recv.c new file mode 100644 index 000000000..b001729d1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/recv.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1994,1997,2001,2005 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 <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> +#include <string.h> + +/* Read N bytes into BUF from socket FD. + Returns the number read or -1 for errors. */ + +ssize_t +__recv (fd, buf, n, flags) + int fd; + void *buf; + size_t n; + int flags; +{ + error_t err; + mach_port_t addrport; + char *bufp = buf; + mach_msg_type_number_t nread = n; + mach_port_t *ports; + mach_msg_type_number_t nports; + char *cdata = NULL; + mach_msg_type_number_t clen = 0; + + if (err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport, + flags, &bufp, &nread, + &ports, &nports, + &cdata, &clen, + &flags, + n))) + return __hurd_dfail (fd, err); + + __mach_port_deallocate (__mach_task_self (), addrport); + __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen); + + if (bufp != buf) + { + memcpy (buf, bufp, nread); + __vm_deallocate (__mach_task_self (), (vm_address_t) bufp, nread); + } + + return nread; +} +weak_alias (__recv, recv) diff --git a/libc/sysdeps/mach/hurd/recvfrom.c b/libc/sysdeps/mach/hurd/recvfrom.c new file mode 100644 index 000000000..d5c73f444 --- /dev/null +++ b/libc/sysdeps/mach/hurd/recvfrom.c @@ -0,0 +1,107 @@ +/* Copyright (C) 1994, 1997, 1999, 2001, 2002 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 <string.h> +#include <sys/socket.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> + +/* Read N bytes into BUF through socket FD. + If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of + the sender, and store the actual size of the address in *ADDR_LEN. + Returns the number of bytes read or -1 for errors. */ +ssize_t +__recvfrom (fd, buf, n, flags, addrarg, addr_len) + int fd; + void *buf; + size_t n; + int flags; + __SOCKADDR_ARG addrarg; + socklen_t *addr_len; +{ + error_t err; + mach_port_t addrport; + char *bufp = buf; + mach_msg_type_number_t nread = n; + mach_port_t *ports; + mach_msg_type_number_t nports; + char *cdata = NULL; + mach_msg_type_number_t clen = 0; + struct sockaddr *addr = addrarg.__sockaddr__; + + if (err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport, + flags, &bufp, &nread, + &ports, &nports, + &cdata, &clen, + &flags, + n))) + return __hurd_dfail (fd, err); + + /* Get address data for the returned address port if requested. */ + if (addr != NULL) + { + char *buf = (char *) addr; + mach_msg_type_number_t buflen = *addr_len; + int type; + + err = __socket_whatis_address (addrport, &type, &buf, &buflen); + if (err == EOPNOTSUPP) + /* If the protocol server can't tell us the address, just return a + zero-length one. */ + { + buf = (char *)addr; + buflen = 0; + err = 0; + } + + if (err) + { + __mach_port_deallocate (__mach_task_self (), addrport); + return __hurd_dfail (fd, err); + } + + if (*addr_len > buflen) + *addr_len = buflen; + + if (buf != (char *) addr) + { + memcpy (addr, buf, *addr_len); + __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen); + } + + if (buflen > 0) + addr->sa_family = type; + } + + __mach_port_deallocate (__mach_task_self (), addrport); + + /* Toss control data; we don't care. */ + __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen); + + if (bufp != buf) + { + memcpy (buf, bufp, nread); + __vm_deallocate (__mach_task_self (), (vm_address_t) bufp, nread); + } + + return nread; +} + +weak_alias (__recvfrom, recvfrom) diff --git a/libc/sysdeps/mach/hurd/recvmsg.c b/libc/sysdeps/mach/hurd/recvmsg.c new file mode 100644 index 000000000..c6874e8bd --- /dev/null +++ b/libc/sysdeps/mach/hurd/recvmsg.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2001, 2002 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <string.h> +#include <sys/socket.h> + +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> + +/* Receive a message as described by MESSAGE from socket FD. + Returns the number of bytes read or -1 for errors. */ +ssize_t +__libc_recvmsg (int fd, struct msghdr *message, int flags) +{ + error_t err; + addr_port_t aport; + char *data = NULL; + mach_msg_type_number_t len = 0; + mach_port_t *ports; + mach_msg_type_number_t nports; + char *cdata = NULL; + mach_msg_type_number_t clen = 0; + size_t amount; + char *buf; + int i; + + /* Find the total number of bytes to be read. */ + amount = 0; + for (i = 0; i < message->msg_iovlen; i++) + { + amount += message->msg_iov[i].iov_len; + + /* As an optimization, we set the initial values of DATA and LEN + from the first non-empty iovec. This kicks-in in the case + where the whole packet fits into that iovec buffer. */ + if (data == NULL && message->msg_iov[i].iov_len > 0) + { + data = message->msg_iov[i].iov_base; + len = message->msg_iov[i].iov_len; + } + } + + buf = data; + if (err = HURD_DPORT_USE (fd, __socket_recv (port, &aport, + flags, &data, &len, + &ports, &nports, + &cdata, &clen, + &message->msg_flags, amount))) + return __hurd_dfail (fd, err); + + if (message->msg_name != NULL) + { + char *buf = message->msg_name; + mach_msg_type_number_t buflen = message->msg_namelen; + int type; + + err = __socket_whatis_address (aport, &type, &buf, &buflen); + if (err == EOPNOTSUPP) + /* If the protocol server can't tell us the address, just return a + zero-length one. */ + { + buf = message->msg_name; + buflen = 0; + err = 0; + } + + if (err) + { + __mach_port_deallocate (__mach_task_self (), aport); + return __hurd_dfail (fd, err); + } + + if (message->msg_namelen > buflen) + message->msg_namelen = buflen; + + if (buf != message->msg_name) + { + memcpy (message->msg_name, buf, message->msg_namelen); + __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen); + } + + if (buflen > 0) + ((struct sockaddr *) message->msg_name)->sa_family = type; + } + + __mach_port_deallocate (__mach_task_self (), aport); + + if (buf == data) + buf += len; + else + { + /* Copy the data into MSG. */ + if (len > amount) + message->msg_flags |= MSG_TRUNC; + else + amount = len; + + buf = data; + for (i = 0; i < message->msg_iovlen; i++) + { +#define min(a, b) ((a) > (b) ? (b) : (a)) + size_t copy = min (message->msg_iov[i].iov_len, amount); + + memcpy (message->msg_iov[i].iov_base, buf, copy); + + buf += copy; + amount -= copy; + if (len == 0) + break; + } + + __vm_deallocate (__mach_task_self (), (vm_address_t) data, len); + } + + /* Copy the control message into MSG. */ + if (clen > message->msg_controllen) + message->msg_flags |= MSG_CTRUNC; + else + message->msg_controllen = clen; + memcpy (message->msg_control, cdata, message->msg_controllen); + + __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen); + + return (buf - data); +} + +weak_alias (__libc_recvmsg, recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) diff --git a/libc/sysdeps/mach/hurd/removexattr.c b/libc/sysdeps/mach/hurd/removexattr.c new file mode 100644 index 000000000..bbfee3d30 --- /dev/null +++ b/libc/sysdeps/mach/hurd/removexattr.c @@ -0,0 +1,35 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2005 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> + +ssize_t +removexattr (const char *path, const char *name) +{ + error_t err; + file_t port = __file_name_lookup (path, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = _hurd_xattr_remove (port, name); + __mach_port_deallocate (__mach_task_self (), port); + return __hurd_fail (err); +} diff --git a/libc/sysdeps/mach/hurd/rename.c b/libc/sysdeps/mach/hurd/rename.c new file mode 100644 index 000000000..181c58897 --- /dev/null +++ b/libc/sysdeps/mach/hurd/rename.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991,92,93,94,96,97,99 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 <stdio.h> +#include <hurd.h> + +/* Rename the file OLD to NEW. */ +int +rename (old, new) + const char *old; + const char *new; +{ + error_t err; + file_t olddir, newdir; + const char *oldname, *newname; + + olddir = __directory_name_split (old, (char **) &oldname); + if (olddir == MACH_PORT_NULL) + return -1; + newdir = __directory_name_split (new, (char **) &newname); + if (newdir == MACH_PORT_NULL) + { + __mach_port_deallocate (__mach_task_self (), olddir); + return -1; + } + + err = __dir_rename (olddir, oldname, newdir, newname, 0); + __mach_port_deallocate (__mach_task_self (), olddir); + __mach_port_deallocate (__mach_task_self (), newdir); + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/revoke.c b/libc/sysdeps/mach/hurd/revoke.c new file mode 100644 index 000000000..32b3574ee --- /dev/null +++ b/libc/sysdeps/mach/hurd/revoke.c @@ -0,0 +1,40 @@ +/* Revoke the access of all descriptors currently open on a file. Hurd version + Copyright (C) 1999 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 <unistd.h> +#include <errno.h> +#include <hurd.h> + +int +revoke (file_name) + const char *file_name; +{ + error_t err; + file_t file = __file_name_lookup (file_name, 0, 0); + + if (file == MACH_PORT_NULL) + return -1; + + err = __io_revoke (file); + __mach_port_deallocate (__mach_task_self (), file); + + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/rewinddir.c b/libc/sysdeps/mach/hurd/rewinddir.c new file mode 100644 index 000000000..69564536c --- /dev/null +++ b/libc/sysdeps/mach/hurd/rewinddir.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1994, 1997 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 <stddef.h> +#include <dirent.h> +#include <sys/types.h> +#include <unistd.h> + +/* Rewind DIRP to the beginning of the directory. */ +/* XXX should be __rewinddir ? */ +void +rewinddir (dirp) + DIR *dirp; +{ + seekdir (dirp, (off_t) 0L); +} diff --git a/libc/sysdeps/mach/hurd/rmdir.c b/libc/sysdeps/mach/hurd/rmdir.c new file mode 100644 index 000000000..46bdf46ee --- /dev/null +++ b/libc/sysdeps/mach/hurd/rmdir.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1991,92,93,94,95,97,99 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 <stddef.h> +#include <unistd.h> +#include <hurd.h> + +/* Remove the directory FILE_NAME. */ +int +__rmdir (file_name) + const char *file_name; +{ + error_t err; + const char *name; + file_t parent = __directory_name_split (file_name, (char **) &name); + if (parent == MACH_PORT_NULL) + return -1; + err = __dir_rmdir (parent, name); + __mach_port_deallocate (__mach_task_self (), parent); + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__rmdir, rmdir) diff --git a/libc/sysdeps/mach/hurd/sbrk.c b/libc/sysdeps/mach/hurd/sbrk.c new file mode 100644 index 000000000..a5ca703a4 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sbrk.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991,94,95,97,98,2000,02 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 <hurd.h> +#include <unistd.h> + +/* Extend the process's data space by INCREMENT. + If INCREMENT is negative, shrink data space by - INCREMENT. + Return the address of the start of the new data space, or -1 for errors. */ +void * +__sbrk (intptr_t increment) +{ + void *result; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_brk_lock); + result = (void *) _hurd_brk; + if (increment != 0 && _hurd_set_brk (_hurd_brk + increment) < 0) + result = (void *) -1; + __mutex_unlock (&_hurd_brk_lock); + HURD_CRITICAL_END; + + return result; +} +libc_hidden_def (__sbrk) +weak_alias (__sbrk, sbrk) diff --git a/libc/sysdeps/mach/hurd/seekdir.c b/libc/sysdeps/mach/hurd/seekdir.c new file mode 100644 index 000000000..741824a1d --- /dev/null +++ b/libc/sysdeps/mach/hurd/seekdir.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1993, 94, 95, 96, 97, 99 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 <stddef.h> +#include <dirent.h> +#include <unistd.h> +#include "dirstream.h" + +/* Seek to position POS in DIRP. */ +/* XXX should be __seekdir ? */ +void +seekdir (dirp, pos) + DIR *dirp; + long int pos; +{ + __libc_lock_lock (dirp->__lock); + /* Change our entry index pointer to POS and discard any data already + read. The next `readdir' call will notice the empty block and read + anew from the location in DIRP->__entry_ptr and reset the other state + variables. */ + dirp->__entry_ptr = pos; + dirp->__size = 0; + __libc_lock_unlock (dirp->__lock); +} diff --git a/libc/sysdeps/mach/hurd/select.c b/libc/sysdeps/mach/hurd/select.c new file mode 100644 index 000000000..fb85d0cf8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/select.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,2002 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 <sys/types.h> +#include <sys/time.h> +#include <hurd.h> +#include <hurd/fd.h> + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Returns the number of ready + descriptors, or -1 for errors. */ +int +__select (nfds, readfds, writefds, exceptfds, timeout) + int nfds; + fd_set *readfds; + fd_set *writefds; + fd_set *exceptfds; + struct timeval *timeout; +{ + struct timespec ts, *to; + + if (timeout) + { + to = &ts; + TIMEVAL_TO_TIMESPEC (timeout, to); + } + else + to = NULL; + + return _hurd_select (nfds, NULL, readfds, writefds, exceptfds, to, NULL); +} +libc_hidden_def (__select) +weak_alias (__select, select) diff --git a/libc/sysdeps/mach/hurd/send.c b/libc/sysdeps/mach/hurd/send.c new file mode 100644 index 000000000..4810cd68c --- /dev/null +++ b/libc/sysdeps/mach/hurd/send.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1994,96,97,2001,02 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 <hurd.h> +#include <hurd/socket.h> +#include <hurd/fd.h> + +/* Send N bytes of BUF to socket FD. Returns the number sent or -1. */ +ssize_t +__send (fd, buf, n, flags) + int fd; + const void *buf; + size_t n; + int flags; +{ + error_t err; + size_t wrote; + + err = HURD_DPORT_USE (fd, __socket_send (port, MACH_PORT_NULL, + flags, buf, n, + NULL, MACH_MSG_TYPE_COPY_SEND, 0, + NULL, 0, &wrote)); + + return err ? __hurd_dfail (fd, err) : wrote; +} +libc_hidden_def (__send) +weak_alias (__send, send) diff --git a/libc/sysdeps/mach/hurd/sendfile.c b/libc/sysdeps/mach/hurd/sendfile.c new file mode 100644 index 000000000..683365fc0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sendfile.c @@ -0,0 +1,37 @@ +/* sendfile -- copy data directly from one file descriptor to another + Copyright (C) 2002 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 <sys/sendfile.h> +#include <stddef.h> + +/* Send COUNT bytes from file associated with IN_FD starting at OFFSET to + descriptor OUT_FD. */ +ssize_t +sendfile (int out_fd, int in_fd, off_t *offset, size_t count) +{ + if (offset == NULL || sizeof (off_t) == sizeof (off64_t)) + return sendfile64 (out_fd, in_fd, (off64_t *) offset, count); + else + { + off64_t ofs = *offset; + ssize_t ret = sendfile64 (out_fd, in_fd, &ofs, count); + *offset = ofs; + return ret; + } +} diff --git a/libc/sysdeps/mach/hurd/sendfile64.c b/libc/sysdeps/mach/hurd/sendfile64.c new file mode 100644 index 000000000..1f63d2a2f --- /dev/null +++ b/libc/sysdeps/mach/hurd/sendfile64.c @@ -0,0 +1,60 @@ +/* sendfile -- copy data directly from one file descriptor to another + Copyright (C) 2002 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 <sys/sendfile.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <sys/mman.h> + +/* Send COUNT bytes from file associated with IN_FD starting at OFFSET to + descriptor OUT_FD. */ +ssize_t +sendfile64 (int out_fd, int in_fd, off64_t *offset, size_t count) +{ + /* We just do a vanilla io_read followed by a vanilla io_write here. + In theory the IN_FD filesystem can return us out-of-line data that + we then send out-of-line to the OUT_FD filesystem and no copying + takes place until those pages need to be flushed or packaged by + that filesystem (e.g. packetized by a network socket). However, + we momentarily consume COUNT bytes of our local address space, + which might blow if it's huge or address space is real tight. */ + + char *data = 0; + size_t datalen = 0; + error_t err = HURD_DPORT_USE (in_fd, + __io_read (port, &data, &datalen, + offset ? *offset : (off_t) -1, + count)); + if (err == 0) + { + size_t nwrote; + if (datalen == 0) + return 0; + err = HURD_DPORT_USE (out_fd, __io_write (port, data, datalen, + (off_t) -1, &nwrote)); + munmap (data, datalen); + if (err == 0) + { + if (offset) + *offset += datalen; + return nwrote; + } + } + return __hurd_fail (err); +} diff --git a/libc/sysdeps/mach/hurd/sendmsg.c b/libc/sysdeps/mach/hurd/sendmsg.c new file mode 100644 index 000000000..5fdfd734e --- /dev/null +++ b/libc/sysdeps/mach/hurd/sendmsg.c @@ -0,0 +1,156 @@ +/* Copyright (C) 2001,2002,2004 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/ifsock.h> +#include <hurd/socket.h> + +/* Send a message described MESSAGE on socket FD. + Returns the number of bytes sent, or -1 for errors. */ +ssize_t +__libc_sendmsg (int fd, const struct msghdr *message, int flags) +{ + error_t err = 0; + struct sockaddr_un *addr = message->msg_name; + socklen_t addr_len = message->msg_namelen; + addr_port_t aport = MACH_PORT_NULL; + union + { + char *ptr; + vm_address_t addr; + } data = { .ptr = NULL }; + char data_buf[2048]; + mach_msg_type_number_t len; + mach_msg_type_number_t amount; + int dealloc = 0; + int i; + + /* Find the total number of bytes to be written. */ + len = 0; + for (i = 0; i < message->msg_iovlen; i++) + { + if (message->msg_iov[i].iov_len > 0) + { + /* As an optimization, if we only have a single non-empty + iovec, we set DATA and LEN from it. */ + if (len == 0) + data.ptr = message->msg_iov[i].iov_base; + else + data.ptr = NULL; + + len += message->msg_iov[i].iov_len; + } + } + + if (data.ptr == NULL) + { + size_t to_copy; + char *buf; + + /* Allocate a temporary buffer to hold the data. For small + amounts of data, we allocate a buffer on the stack. Larger + amounts of data are stored in a page-aligned buffer. The + limit of 2048 bytes is inspired by the MiG stubs. */ + if (len > 2048) + { + err = __vm_allocate (__mach_task_self (), &data.addr, len, 1); + if (err) + { + __set_errno (err); + return -1; + } + dealloc = 1; + } + else + data.ptr = data_buf; + + /* Copy the data into DATA. */ + to_copy = len; + buf = data.ptr; + for (i = 0; i < len; i++) + { +#define min(a, b) ((a) > (b) ? (b) : (a)) + size_t copy = min (message->msg_iov[i].iov_len, to_copy); + + buf = __mempcpy (buf, message->msg_iov[i].iov_base, copy); + + to_copy -= copy; + if (to_copy == 0) + break; + } + } + + if (addr) + { + if (addr->sun_family == AF_LOCAL) + { + /* 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); + if (file == MACH_PORT_NULL) + return -1; + err = __ifsock_getsockaddr (file, &aport); + __mach_port_deallocate (__mach_task_self (), file); + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + /* The file did not grok the ifsock protocol. */ + err = ENOTSOCK; + if (err) + return __hurd_fail (err); + } + else + err = EIEIO; + } + + err = HURD_DPORT_USE (fd, + ({ + if (err) + err = __socket_create_address (port, + addr->sun_family, + (char *) addr, + addr_len, + &aport); + if (! err) + { + /* Send the data. */ + err = __socket_send (port, aport, + flags, data.ptr, len, + NULL, + MACH_MSG_TYPE_COPY_SEND, 0, + message->msg_control, + message->msg_controllen, + &amount); + __mach_port_deallocate (__mach_task_self (), + aport); + } + err; + })); + + if (dealloc) + __vm_deallocate (__mach_task_self (), data.addr, len); + + return err ? __hurd_dfail (fd, err) : amount; +} + +weak_alias (__libc_sendmsg, sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) diff --git a/libc/sysdeps/mach/hurd/sendto.c b/libc/sysdeps/mach/hurd/sendto.c new file mode 100644 index 000000000..0a6912a3b --- /dev/null +++ b/libc/sysdeps/mach/hurd/sendto.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1994,95,96,97,99,2001,02 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/un.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/ifsock.h> +#include <hurd/socket.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. */ +ssize_t +__sendto (int fd, + const void *buf, + size_t n, + int flags, + const struct sockaddr_un *addr, + socklen_t addr_len) +{ + addr_port_t aport; + error_t err; + size_t wrote; + + if (addr->sun_family == AF_LOCAL) + { + /* 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); + if (file == MACH_PORT_NULL) + return -1; + err = __ifsock_getsockaddr (file, &aport); + __mach_port_deallocate (__mach_task_self (), file); + if (err == MIG_BAD_ID || err == EOPNOTSUPP) + /* The file did not grok the ifsock protocol. */ + err = ENOTSOCK; + if (err) + return __hurd_fail (err); + } + else + err = EIEIO; + + /* Get an address port for the desired destination address. */ + err = HURD_DPORT_USE (fd, + ({ + if (err) + err = __socket_create_address (port, + addr->sun_family, + (char *) addr, + addr_len, + &aport); + if (! err) + { + /* Send the data. */ + err = __socket_send (port, aport, + flags, buf, n, + NULL, + MACH_MSG_TYPE_COPY_SEND, 0, + NULL, 0, &wrote); + __mach_port_deallocate (__mach_task_self (), + aport); + } + err; + })); + + return err ? __hurd_dfail (fd, err) : wrote; +} + +weak_alias (__sendto, sendto) diff --git a/libc/sysdeps/mach/hurd/setdomain.c b/libc/sysdeps/mach/hurd/setdomain.c new file mode 100644 index 000000000..5bff21d99 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setdomain.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1998 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 <unistd.h> +#include "hurdhost.h" + +/* Set the name of the current YP domain to NAME, which is LEN bytes long. + This call is restricted to the super-user. */ +int +setdomainname (name, len) + const char *name; + size_t len; +{ + /* The NIS domain name is just the contents of the file /etc/nisdomain. */ + ssize_t n = _hurd_set_host_config ("/etc/nisdomain", name, len); + return n < 0 ? -1 : 0; +} diff --git a/libc/sysdeps/mach/hurd/setegid.c b/libc/sysdeps/mach/hurd/setegid.c new file mode 100644 index 000000000..c84b8e2e1 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setegid.c @@ -0,0 +1,69 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <sys/types.h> +#include <hurd/id.h> +#include <string.h> + +/* Set the effective user ID of the calling process to GID. */ +int +setegid (gid) + gid_t gid; +{ + auth_t newauth; + error_t err; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has EGID as the first element in the + list of effective gids. */ + + if (_hurd_id.gen.ngids > 0) + { + _hurd_id.gen.gids[0] = gid; + _hurd_id.valid = 0; + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.uids, _hurd_id.gen.nuids, + _hurd_id.aux.uids, _hurd_id.aux.nuids, + _hurd_id.gen.ngids ? _hurd_id.gen.gids : &gid, + _hurd_id.gen.ngids ?: 1, + _hurd_id.aux.gids, _hurd_id.aux.ngids, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} +libc_hidden_def (setegid) diff --git a/libc/sysdeps/mach/hurd/seteuid.c b/libc/sysdeps/mach/hurd/seteuid.c new file mode 100644 index 000000000..8a6effef8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/seteuid.c @@ -0,0 +1,69 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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 <unistd.h> +#include <hurd.h> +#include <sys/types.h> +#include <hurd/id.h> +#include <string.h> + +/* Set the effective user ID of the calling process to UID. */ +int +seteuid (uid) + uid_t uid; +{ + auth_t newauth; + error_t err; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has EUID as the first element in the + list of effective uids. */ + + if (_hurd_id.gen.nuids > 0) + { + _hurd_id.gen.uids[0] = uid; + _hurd_id.valid = 0; + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.nuids ? _hurd_id.gen.uids : &uid, + _hurd_id.gen.nuids ?: 1, + _hurd_id.aux.uids, _hurd_id.aux.nuids, + _hurd_id.gen.gids, _hurd_id.gen.ngids, + _hurd_id.aux.gids, _hurd_id.aux.ngids, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} +libc_hidden_def (seteuid) diff --git a/libc/sysdeps/mach/hurd/setgid.c b/libc/sysdeps/mach/hurd/setgid.c new file mode 100644 index 000000000..a7f3dda7d --- /dev/null +++ b/libc/sysdeps/mach/hurd/setgid.c @@ -0,0 +1,96 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 <unistd.h> +#include <sys/types.h> +#include <hurd.h> +#include <hurd/id.h> +#include <string.h> + +/* Set the group ID of the calling process to UID. + If the calling process is the super-user, the real + and effective group IDs, and the saved set-group-ID to UID; + if not, the effective group ID is set to GID. */ +int +__setgid (gid) + gid_t gid; +{ + auth_t newauth; + error_t err; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has GID as the real gid, + and as the first element in the list of effective gids. */ + + gid_t *newgen, *newaux, auxbuf[2]; + size_t ngen, naux; + + if (_hurd_id.gen.ngids == 0) + { + /* No effective gids now. The new set will be just GID. */ + newgen = &gid; + ngen = 1; + } + else + { + _hurd_id.gen.gids[0] = gid; + _hurd_id.valid = 0; + newgen = _hurd_id.gen.gids; + ngen = _hurd_id.gen.ngids; + } + + newaux = _hurd_id.aux.gids; + naux = _hurd_id.aux.ngids; + if (_hurd_id.gen.nuids > 0 && _hurd_id.gen.uids[0] == 0) + { + /* We are root; set the real and saved IDs too. */ + _hurd_id.valid = 0; + if (_hurd_id.aux.ngids < 2) + { + newaux = auxbuf; + naux = 2; + } + newaux[0] = newaux[1] = gid; + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.uids, _hurd_id.gen.nuids, + _hurd_id.aux.uids, _hurd_id.aux.nuids, + newgen, ngen, newaux, naux, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} + +weak_alias (__setgid, setgid) diff --git a/libc/sysdeps/mach/hurd/setgroups.c b/libc/sysdeps/mach/hurd/setgroups.c new file mode 100644 index 000000000..d0bd63442 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setgroups.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1993,94,97,2002 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/types.h> +#include <grp.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Set the group set for the current user to GROUPS (N of them). */ +int +setgroups (n, groups) + size_t n; + const gid_t *groups; +{ + error_t err; + auth_t newauth; + size_t i; + gid_t new[n]; + + /* Fault before taking locks. */ + for (i = 0; i < n; ++i) + new[i] = groups[i]; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + if (! err) + { + /* Get a new auth port using those IDs. */ + err = __USEPORT (AUTH, + __auth_makeauth (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.uids, _hurd_id.gen.nuids, + _hurd_id.aux.uids, _hurd_id.aux.nuids, + new, n, + _hurd_id.aux.gids, _hurd_id.aux.ngids, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new auth port and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} +libc_hidden_def (setgroups) diff --git a/libc/sysdeps/mach/hurd/sethostid.c b/libc/sysdeps/mach/hurd/sethostid.c new file mode 100644 index 000000000..5d720ca55 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sethostid.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1993, 1996, 1997 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 <unistd.h> +#include <hurd.h> +#include "hurdhost.h" +#include <stdio-common/_itoa.h> + +/* Set the current machine's Internet number to ID. + This call is restricted to the super-user. */ +/* XXX should be __sethostid? + isn't hostid supposed to be hardwired and unchangeable? */ +int +sethostid (id) + long int id; +{ + char buf[8], *bp; + ssize_t n; + + /* The hostid is kept in the file /etc/hostid, + eight characters of upper-case hexadecimal. */ + + bp = _itoa_word (id, &buf[sizeof buf], 16, 1); + while (bp > buf) + *--bp = '0'; + + n = _hurd_set_host_config ("/etc/hostid", buf, sizeof buf); + return n < 0 ? -1 : 0; +} diff --git a/libc/sysdeps/mach/hurd/sethostname.c b/libc/sysdeps/mach/hurd/sethostname.c new file mode 100644 index 000000000..564d600ef --- /dev/null +++ b/libc/sysdeps/mach/hurd/sethostname.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 92, 93, 94, 96, 97 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 <unistd.h> +#include "hurdhost.h" + +/* Set the name of the current host to NAME, which is LEN bytes long. + This call is restricted to the super-user. */ +/* XXX should be __sethostname ? */ +int +sethostname (name, len) + const char *name; + size_t len; +{ + /* The host name is just the contents of the file /etc/hostname. */ + ssize_t n = _hurd_set_host_config ("/etc/hostname", name, len); + return n < 0 ? -1 : 0; +} diff --git a/libc/sysdeps/mach/hurd/setitimer.c b/libc/sysdeps/mach/hurd/setitimer.c new file mode 100644 index 000000000..fec64a8cb --- /dev/null +++ b/libc/sysdeps/mach/hurd/setitimer.c @@ -0,0 +1,374 @@ +/* Copyright (C) 1994,1995,1996,1997,2000,2001,2005 + 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 <stddef.h> +#include <errno.h> +#include <sys/time.h> +#include <time.h> +#include <hurd.h> +#include <hurd/signal.h> +#include <hurd/sigpreempt.h> +#include <hurd/msg_request.h> +#include <mach/message.h> + +/* XXX Temporary cheezoid implementation of ITIMER_REAL/SIGALRM. */ + +spin_lock_t _hurd_itimer_lock = SPIN_LOCK_INITIALIZER; +struct itimerval _hurd_itimerval; /* Current state of the timer. */ +mach_port_t _hurd_itimer_port; /* Port the timer thread blocks on. */ +thread_t _hurd_itimer_thread; /* Thread waiting for timeout. */ +int _hurd_itimer_thread_suspended; /* Nonzero if that thread is suspended. */ +vm_address_t _hurd_itimer_thread_stack_base; /* Base of its stack. */ +vm_address_t _hurd_itimer_thread_stack_size; /* Size of its stack. */ +struct timeval _hurd_itimer_started; /* Time the thread started waiting. */ + +static void +quantize_timeval (struct timeval *tv) +{ + static time_t quantum = -1; + + if (quantum == -1) + quantum = 1000000 / __getclktck (); + + tv->tv_usec = ((tv->tv_usec + (quantum - 1)) / quantum) * quantum; + if (tv->tv_usec >= 1000000) + { + ++tv->tv_sec; + tv->tv_usec -= 1000000; + } +} + +static inline void +subtract_timeval (struct timeval *from, const struct timeval *subtract) +{ + from->tv_usec -= subtract->tv_usec; + from->tv_sec -= subtract->tv_sec; + while (from->tv_usec < 0) + { + --from->tv_sec; + from->tv_usec += 1000000; + } +} + +/* Function run by the itimer thread. + This code must be very careful not ever to require a MiG reply port. */ + +static void +timer_thread (void) +{ + while (1) + { + error_t err; + /* The only message we ever expect to receive is the reply from the + signal thread to a sig_post call we did. We never examine the + contents. */ + struct + { + mach_msg_header_t header; + error_t return_code; + } msg; + + /* Wait for a message on a port that noone sends to. The purpose is + the receive timeout. Notice interrupts so that if we are + thread_abort'd, we will loop around and fetch new values from + _hurd_itimerval. */ + err = __mach_msg (&msg.header, + MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, _hurd_itimer_port, + _hurd_itimerval.it_value.tv_sec * 1000 + + _hurd_itimerval.it_value.tv_usec / 1000, + MACH_PORT_NULL); + switch (err) + { + case MACH_RCV_TIMED_OUT: + /* We got the expected timeout. Send a message to the signal + thread to tell it to post a SIGALRM signal. We use + _hurd_itimer_port as the reply port just so we will block until + the signal thread has frobnicated things to reload the itimer or + has terminated this thread. */ + __msg_sig_post_request (_hurd_msgport, + _hurd_itimer_port, + MACH_MSG_TYPE_MAKE_SEND_ONCE, + SIGALRM, 0, __mach_task_self ()); + break; + + case MACH_RCV_INTERRUPTED: + /* We were thread_abort'd. This is to tell us that + _hurd_itimerval has changed and we need to reexamine it + and start waiting with the new timeout value. */ + break; + + case MACH_MSG_SUCCESS: + /* We got the reply message from the sig_post_request above. + Ignore it and reexamine the timer value. */ + __mach_msg_destroy (&msg.header); /* Just in case. */ + break; + + default: + /* Unexpected lossage. Oh well, keep trying. */ + break; + } + } +} + + +/* Forward declaration. */ +static int setitimer_locked (const struct itimerval *new, + struct itimerval *old, void *crit); + +static sighandler_t +restart_itimer (struct hurd_signal_preemptor *preemptor, + struct hurd_sigstate *ss, + int *signo, struct hurd_signal_detail *detail) +{ + /* This function gets called in the signal thread + each time a SIGALRM is arriving (even if blocked). */ + struct itimerval it; + + /* 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); + + /* Continue with normal delivery (or hold, etc.) of SIGALRM. */ + return SIG_ERR; +} + + +/* Called before any normal SIGALRM signal is delivered. + Reload the itimer, or disable the itimer. */ + +static int +setitimer_locked (const struct itimerval *new, struct itimerval *old, + void *crit) +{ + struct itimerval newval; + struct timeval now, remaining, elapsed; + struct timeval old_interval; + error_t err; + + inline void kill_itimer_thread (void) + { + __thread_terminate (_hurd_itimer_thread); + __vm_deallocate (__mach_task_self (), + _hurd_itimer_thread_stack_base, + _hurd_itimer_thread_stack_size); + _hurd_itimer_thread = MACH_PORT_NULL; + } + + if (!new) + { + /* Just return the current value in OLD without changing anything. + This is what BSD does, even though it's not documented. */ + if (old) + *old = _hurd_itimerval; + spin_unlock (&_hurd_itimer_lock); + _hurd_critical_section_unlock (crit); + return 0; + } + + newval = *new; + quantize_timeval (&newval.it_interval); + quantize_timeval (&newval.it_value); + if ((newval.it_value.tv_sec | newval.it_value.tv_usec) != 0) + { + /* Make sure the itimer thread is set up. */ + + /* Set up a signal preemptor global for all threads to + run `restart_itimer' each time a SIGALRM would arrive. */ + static struct hurd_signal_preemptor preemptor = + { + __sigmask (SIGALRM), 0, 0, + &restart_itimer, + }; + __mutex_lock (&_hurd_siglock); + if (! preemptor.next && _hurdsig_preemptors != &preemptor) + { + preemptor.next = _hurdsig_preemptors; + _hurdsig_preemptors = &preemptor; + } + __mutex_unlock (&_hurd_siglock); + + if (_hurd_itimer_port == MACH_PORT_NULL) + { + /* Allocate a receive right that the itimer thread will + block waiting for a message on. */ + if (err = __mach_port_allocate (__mach_task_self (), + MACH_PORT_RIGHT_RECEIVE, + &_hurd_itimer_port)) + goto out; + } + + if (_hurd_itimer_thread == MACH_PORT_NULL) + { + /* Start up the itimer thread running `timer_thread' (below). */ + if (err = __thread_create (__mach_task_self (), + &_hurd_itimer_thread)) + return __hurd_fail (err); + _hurd_itimer_thread_stack_base = 0; /* Anywhere. */ + _hurd_itimer_thread_stack_size = __vm_page_size; /* Small stack. */ + if (err = __mach_setup_thread (__mach_task_self (), + _hurd_itimer_thread, + &timer_thread, + &_hurd_itimer_thread_stack_base, + &_hurd_itimer_thread_stack_size)) + { + __thread_terminate (_hurd_itimer_thread); + _hurd_itimer_thread = MACH_PORT_NULL; + goto out; + } + _hurd_itimer_thread_suspended = 1; + } + } + + if ((newval.it_value.tv_sec | newval.it_value.tv_usec) != 0 || old != NULL) + { + /* Calculate how much time is remaining for the pending alarm. */ + if (__gettimeofday (&now, NULL) < 0) + { + __spin_unlock (&_hurd_itimer_lock); + _hurd_critical_section_unlock (crit); + return -1; + } + elapsed = now; + subtract_timeval (&elapsed, &_hurd_itimer_started); + remaining = _hurd_itimerval.it_value; + if (timercmp (&remaining, &elapsed, <)) + { + /* Hmm. The timer should have just gone off, but has not been reset. + This is a possible timing glitch. The alarm will signal soon. */ + /* XXX wrong */ + remaining.tv_sec = 0; + remaining.tv_usec = 0; + } + else + subtract_timeval (&remaining, &elapsed); + + /* Remember the old reload interval before changing it. */ + old_interval = _hurd_itimerval.it_interval; + + /* Record the starting time that the timer interval relates to. */ + _hurd_itimer_started = now; + } + + /* Load the new itimer value. */ + _hurd_itimerval = newval; + + if ((newval.it_value.tv_sec | newval.it_value.tv_usec) == 0) + { + /* Disable the itimer. */ + if (_hurd_itimer_thread && !_hurd_itimer_thread_suspended) + { + /* Suspend the itimer thread so it does nothing. Then abort its + kernel context so that when the thread is resumed, mach_msg + will return to timer_thread (below) and it will fetch new + values from _hurd_itimerval. */ + if ((err = __thread_suspend (_hurd_itimer_thread)) || + (err = __thread_abort (_hurd_itimer_thread))) + /* If we can't save it for later, nuke it. */ + kill_itimer_thread (); + else + _hurd_itimer_thread_suspended = 1; + } + } + /* See if the timeout changed. If so, we must alert the itimer thread. */ + else if (remaining.tv_sec != newval.it_value.tv_sec || + remaining.tv_usec != newval.it_value.tv_usec) + { + /* The timeout value is changing. Tell the itimer thread to + reexamine it and start counting down. If the itimer thread is + marked as suspended, either we just created it, or it was + suspended and thread_abort'd last time the itimer was disabled; + either way it will wake up and start waiting for the new timeout + value when we resume it. If it is not suspended, the itimer + thread is waiting to deliver a pending alarm that we will override + (since it would come later than the new alarm being set); + thread_abort will make mach_msg return MACH_RCV_INTERRUPTED, so it + will loop around and use the new timeout value. */ + if (err = (_hurd_itimer_thread_suspended + ? __thread_resume : __thread_abort) (_hurd_itimer_thread)) + { + kill_itimer_thread (); + goto out; + } + _hurd_itimer_thread_suspended = 0; + } + + __spin_unlock (&_hurd_itimer_lock); + _hurd_critical_section_unlock (crit); + + if (old != NULL) + { + old->it_value = remaining; + old->it_interval = old_interval; + } + return 0; + + out: + __spin_unlock (&_hurd_itimer_lock); + _hurd_critical_section_unlock (crit); + return __hurd_fail (err); +} + +/* Set the timer WHICH to *NEW. If OLD is not NULL, + set *OLD to the old value of timer WHICH. + Returns 0 on success, -1 on errors. */ +int +__setitimer (enum __itimer_which which, const struct itimerval *new, + struct itimerval *old) +{ + void *crit; + + switch (which) + { + default: + return __hurd_fail (EINVAL); + + case ITIMER_VIRTUAL: + case ITIMER_PROF: + return __hurd_fail (ENOSYS); + + case ITIMER_REAL: + break; + } + + crit = _hurd_critical_section_lock (); + __spin_lock (&_hurd_itimer_lock); + return setitimer_locked (new, old, crit); +} + +static void +fork_itimer (void) +{ + /* We must restart the itimer in the child. */ + + struct itimerval it; + + __spin_lock (&_hurd_itimer_lock); + _hurd_itimer_thread = MACH_PORT_NULL; + it = _hurd_itimerval; + it.it_value = it.it_interval; + + setitimer_locked (&it, NULL, NULL); + + (void) &fork_itimer; /* Avoid gcc optimizing out the function. */ +} +text_set_element (_hurd_fork_child_hook, fork_itimer); + +weak_alias (__setitimer, setitimer) diff --git a/libc/sysdeps/mach/hurd/setlogin.c b/libc/sysdeps/mach/hurd/setlogin.c new file mode 100644 index 000000000..2cd438254 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setlogin.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1992, 1993, 1994, 1997 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 <unistd.h> +#include <hurd.h> + +/* Set the login name returned by `getlogin'. */ +int +setlogin (name) + const char *name; +{ + error_t err; + if (err = __USEPORT (PROC, __proc_setlogin (port, name))) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/setpgid.c b/libc/sysdeps/mach/hurd/setpgid.c new file mode 100644 index 000000000..27b15b228 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setpgid.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1993,1994,1995,1996,1997,2002 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 <unistd.h> +#include <hurd.h> +#include <hurd/port.h> + +/* Set the process group ID of the process matching PID to PGID. + If PID is zero, the current process's process group ID is set. + If PGID is zero, the process ID of the process is used. */ +int +__setpgid (pid, pgid) + pid_t pid; + pid_t pgid; +{ + error_t err; + unsigned int stamp; + + stamp = _hurd_pids_changed_stamp; /* Atomic fetch. */ + + if (err = __USEPORT (PROC, __proc_setpgrp (port, pid, pgid))) + return __hurd_fail (err); + + if (pid == 0 || pid == _hurd_pid) + /* Synchronize with the signal thread to make sure we have + received and processed proc_newids before returning to the user. */ + while (_hurd_pids_changed_stamp == stamp) + { +#ifdef noteven + /* XXX we have no need for a mutex, but cthreads demands one. */ + __condition_wait (&_hurd_pids_changed_sync, NULL); +#else + __swtch_pri(0); +#endif + } + + return 0; + +} +libc_hidden_def (__setpgid) +weak_alias (__setpgid, setpgid) diff --git a/libc/sysdeps/mach/hurd/setpriority.c b/libc/sysdeps/mach/hurd/setpriority.c new file mode 100644 index 000000000..bf739aa09 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setpriority.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1994,95,97,2000,02 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 <hurd.h> +#include <hurd/resource.h> + +/* Set the priority of all processes specified by WHICH and WHO + to PRIO. Returns 0 on success, -1 on errors. */ +int +setpriority (enum __priority_which which, id_t who, int prio) +{ + error_t err; + error_t pidloser, priloser; + unsigned int npids, ntasks, nwin, nperm, nacces; + + error_t setonepriority (pid_t pid, struct procinfo *pi) + { + task_t task; + error_t piderr = __USEPORT (PROC, __proc_pid2task (port, pid, &task)); + if (piderr == EPERM) + ++nperm; + if (piderr != ESRCH) + { + ++npids; + if (piderr && piderr != EPERM) + pidloser = piderr; + } + if (! piderr) + { + error_t prierr; + ++ntasks; +#ifdef POLICY_TIMESHARE_BASE_COUNT + { + /* XXX This assumes timeshare policy. */ + struct policy_timeshare_base base + = { NICE_TO_MACH_PRIORITY (prio) }; + prierr = __task_policy (task, POLICY_TIMESHARE, + (policy_base_t) &base, + POLICY_TIMESHARE_BASE_COUNT, + 0, 1); + } +#else + prierr = __task_priority (task, NICE_TO_MACH_PRIORITY (prio), 1); +#endif + __mach_port_deallocate (__mach_task_self (), task); + switch (prierr) + { + case KERN_FAILURE: + ++nacces; + break; + case KERN_SUCCESS: + ++nwin; + break; + case KERN_INVALID_ARGUMENT: /* Task died. */ + --npids; + --ntasks; + break; + default: + priloser = prierr; + } + } + return 0; + } + + npids = ntasks = nwin = nperm = nacces = 0; + pidloser = priloser = 0; + err = _hurd_priority_which_map (which, who, setonepriority, 0); + + if (!err && npids == 0) + /* No error, but no pids found. */ + err = ESRCH; + else if (nperm == npids) + /* Got EPERM from proc_task2pid for every process. */ + err = EPERM; + else if (nacces == ntasks) + /* Got KERN_FAILURE from task_priority for every task. */ + err = EACCES; + else if (nwin == 0) + err = pidloser ?: priloser; + + return err ? __hurd_fail (err) : 0; +} +libc_hidden_def (setpriority) diff --git a/libc/sysdeps/mach/hurd/setregid.c b/libc/sysdeps/mach/hurd/setregid.c new file mode 100644 index 000000000..84d09cc61 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setregid.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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/types.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/id.h> +#include <string.h> + +int +__setregid (rgid, egid) + gid_t rgid; + gid_t egid; +{ + auth_t newauth; + error_t err; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has RGID as the real gid, + and EGID as the first element in the list of effective gids. */ + + gid_t *newgen, *newaux; + size_t ngen, naux; + + newgen = _hurd_id.gen.gids; + ngen = _hurd_id.gen.ngids; + if (egid != -1) + { + if (_hurd_id.gen.ngids == 0) + { + /* No effective gids now. The new set will be just GID. */ + newgen = &egid; + ngen = 1; + } + else + { + _hurd_id.gen.gids[0] = egid; + _hurd_id.valid = 0; + } + } + + newaux = _hurd_id.aux.gids; + naux = _hurd_id.aux.ngids; + if (rgid != -1) + { + if (_hurd_id.aux.ngids == 0) + { + newaux = &rgid; + naux = 1; + } + else + { + _hurd_id.aux.gids[0] = rgid; + _hurd_id.valid = 0; + } + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.uids, _hurd_id.gen.nuids, + _hurd_id.aux.uids, _hurd_id.aux.nuids, + newgen, ngen, newaux, naux, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} + +weak_alias (__setregid, setregid) diff --git a/libc/sysdeps/mach/hurd/setresgid.c b/libc/sysdeps/mach/hurd/setresgid.c new file mode 100644 index 000000000..8fcf26eaf --- /dev/null +++ b/libc/sysdeps/mach/hurd/setresgid.c @@ -0,0 +1,78 @@ +/* setresgid -- set real group ID, effective group ID, and saved-set group ID + Copyright (C) 2002, 2005, 2006 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Set the real group ID, effective group ID, and saved-set group ID, + of the calling process to RGID, EGID, and SGID, respectively. */ +int +__setresgid (gid_t rgid, gid_t egid, gid_t sgid) +{ + auth_t newauth; + error_t err; + gid_t agids[2] = { rgid, sgid }; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has EGID as the first element in the + list of effective gids. */ + + if (_hurd_id.gen.ngids > 0) + { + _hurd_id.gen.gids[0] = egid; + _hurd_id.valid = 0; + } + if (_hurd_id.aux.ngids > 1) + { + _hurd_id.aux.gids[0] = rgid; + _hurd_id.aux.gids[1] = sgid; + _hurd_id.valid = 0; + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.uids, _hurd_id.gen.nuids, + _hurd_id.aux.uids, _hurd_id.aux.nuids, + _hurd_id.gen.ngids ? _hurd_id.gen.gids : &egid, + _hurd_id.gen.ngids ?: 1, + _hurd_id.aux.ngids > 1 ? _hurd_id.aux.gids : agids, + _hurd_id.aux.ngids > 1 ? _hurd_id.aux.ngids : 2, + &newauth)); + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} +libc_hidden_def (__setresgid) +weak_alias (__setresgid, setresgid) diff --git a/libc/sysdeps/mach/hurd/setresuid.c b/libc/sysdeps/mach/hurd/setresuid.c new file mode 100644 index 000000000..ccf8d08d4 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setresuid.c @@ -0,0 +1,78 @@ +/* setresuid -- set real user ID, effective user ID, and saved-set user ID + Copyright (C) 2002, 2005, 2006 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 <unistd.h> +#include <hurd.h> +#include <hurd/id.h> + +/* Set the real user ID, effective user ID, and saved-set user ID, + of the calling process to RUID, EUID, and SUID, respectively. */ +int +__setresuid (uid_t ruid, uid_t euid, uid_t suid) +{ + auth_t newauth; + error_t err; + uid_t auids[2] = { ruid, suid }; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has EUID as the first element in the + list of effective uids. */ + + if (_hurd_id.gen.nuids > 0) + { + _hurd_id.gen.uids[0] = euid; + _hurd_id.valid = 0; + } + if (_hurd_id.aux.nuids > 1) + { + _hurd_id.aux.uids[0] = ruid; + _hurd_id.aux.uids[1] = suid; + _hurd_id.valid = 0; + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.gen.nuids ? _hurd_id.gen.uids : &euid, + _hurd_id.gen.nuids ?: 1, + _hurd_id.aux.nuids > 1 ? _hurd_id.aux.uids : auids, + _hurd_id.aux.nuids > 1 ? _hurd_id.aux.nuids : 2, + _hurd_id.gen.gids, _hurd_id.gen.ngids, + _hurd_id.aux.gids, _hurd_id.aux.ngids, + &newauth)); + } + + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} +libc_hidden_def (__setresuid) +weak_alias (__setresuid, setresuid) diff --git a/libc/sysdeps/mach/hurd/setreuid.c b/libc/sysdeps/mach/hurd/setreuid.c new file mode 100644 index 000000000..b88879f18 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setreuid.c @@ -0,0 +1,98 @@ +/* Copyright (C) 1993, 1994, 1995, 1997 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/types.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/id.h> +#include <string.h> + +int +__setreuid (ruid, euid) + uid_t ruid; + uid_t euid; +{ + auth_t newauth; + error_t err; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has RUID as the real uid, + and EUID as the first element in the list of effective uids. */ + + uid_t *newgen, *newaux; + size_t ngen, naux; + + newgen = _hurd_id.gen.uids; + ngen = _hurd_id.gen.nuids; + if (euid != -1) + { + if (_hurd_id.gen.nuids == 0) + { + /* No effective uids now. The new set will be just UID. */ + newgen = &euid; + ngen = 1; + } + else + { + _hurd_id.gen.uids[0] = euid; + _hurd_id.valid = 0; + } + } + + newaux = _hurd_id.aux.uids; + naux = _hurd_id.aux.nuids; + if (ruid != -1) + { + if (_hurd_id.aux.nuids == 0) + { + newaux = &ruid; + naux = 1; + } + else + { + _hurd_id.aux.uids[0] = ruid; + _hurd_id.valid = 0; + } + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + newgen, ngen, newaux, naux, + _hurd_id.gen.gids, _hurd_id.gen.ngids, + _hurd_id.aux.gids, _hurd_id.aux.ngids, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} + +weak_alias (__setreuid, setreuid) diff --git a/libc/sysdeps/mach/hurd/setrlimit.c b/libc/sysdeps/mach/hurd/setrlimit.c new file mode 100644 index 000000000..29f91cf92 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setrlimit.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1991,92,93,94,97,98,2000,01 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 <hurd.h> +#include <hurd/fd.h> +#include <hurd/resource.h> + +/* Set the soft and hard limits for RESOURCE to *RLIMITS. + Only the super-user can increase hard limits. + Return 0 if successful, -1 if not (and sets errno). */ +int +__setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits) +{ + struct rlimit lim; + + if (rlimits == NULL || (unsigned int) resource >= RLIMIT_NLIMITS) + { + errno = EINVAL; + return -1; + } + + lim = *rlimits; + + /* Even though most limits do nothing, there is no inheritance, and hard + limits are not really hard, we just let any old call succeed to make + life easier for programs that expect normal behavior. */ + + if (lim.rlim_cur > lim.rlim_max) + lim.rlim_cur = lim.rlim_max; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_rlimit_lock); + _hurd_rlimits[resource] = lim; + __mutex_unlock (&_hurd_rlimit_lock); + HURD_CRITICAL_END; + + return 0; +} + +weak_alias (__setrlimit, setrlimit) diff --git a/libc/sysdeps/mach/hurd/setsid.c b/libc/sysdeps/mach/hurd/setsid.c new file mode 100644 index 000000000..e4e3eb92a --- /dev/null +++ b/libc/sysdeps/mach/hurd/setsid.c @@ -0,0 +1,73 @@ +/* Copyright (C) 1993,94,95,97,99 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 <unistd.h> +#include <hurd.h> +#include <hurd/port.h> +#include <hurd/fd.h> + +/* Create a new session with the calling process as its leader. + The process group IDs of the session and the calling process + are set to the process ID of the calling process, which is returned. */ +pid_t +__setsid (void) +{ + error_t err; + unsigned int stamp; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_dtable_lock); + + stamp = _hurd_pids_changed_stamp; /* Atomic fetch. */ + + /* Tell the proc server we want to start a new session. */ + err = __USEPORT (PROC, __proc_setsid (port)); + if (err) + __mutex_unlock (&_hurd_dtable_lock); + else + { + /* Punt our current ctty, and update the dtable accordingly. We hold + the dtable lock from before the proc_setsid call through clearing + the cttyid port and processing the dtable, so that we can be sure + that it's all done by the time the signal thread processes the + pgrp change notification. */ + _hurd_locked_install_cttyid (MACH_PORT_NULL); + + /* Synchronize with the signal thread to make sure we have received + and processed proc_newids before returning to the user. + This is necessary to ensure that _hurd_pgrp (and thus the value + returned by `getpgrp ()' in other threads) has been updated before + we return. */ + while (_hurd_pids_changed_stamp == stamp) + { +#ifdef noteven + /* XXX we have no need for a mutex, but cthreads demands one. */ + __condition_wait (&_hurd_pids_changed_sync, NULL); +#else + __swtch_pri (0); +#endif + } + } + + HURD_CRITICAL_END; + + return err ? __hurd_fail (err) : _hurd_pgrp; +} + +weak_alias (__setsid, setsid) diff --git a/libc/sysdeps/mach/hurd/setsockopt.c b/libc/sysdeps/mach/hurd/setsockopt.c new file mode 100644 index 000000000..8ca7f0c72 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setsockopt.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1992,94,97,98,2002 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 <hurd.h> +#include <hurd/socket.h> +#include <hurd/fd.h> + +/* Set socket FD's option OPTNAME at protocol level LEVEL + to *OPTVAL (which is OPTLEN bytes long). + Returns 0 on success, -1 for errors. */ +int +__setsockopt (int fd, + int level, + int optname, + const void *optval, + socklen_t optlen) +{ + error_t err = HURD_DPORT_USE (fd, __socket_setopt (port, + level, optname, + optval, optlen)); + if (err) + return __hurd_dfail (fd, err); + return 0; +} + +weak_alias (__setsockopt, setsockopt) diff --git a/libc/sysdeps/mach/hurd/settimeofday.c b/libc/sysdeps/mach/hurd/settimeofday.c new file mode 100644 index 000000000..d76041a80 --- /dev/null +++ b/libc/sysdeps/mach/hurd/settimeofday.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991,92,93,94,95,97,2001 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/time.h> +#include <hurd.h> +#include <hurd/port.h> + +/* Set the current time of day and timezone information. + This call is restricted to the super-user. */ +int +__settimeofday (tv, tz) + const struct timeval *tv; + const struct timezone *tz; +{ + error_t err; + mach_port_t hostpriv; + + if (tz != NULL) + { + errno = ENOSYS; + return -1; + } + + err = __get_privileged_ports (&hostpriv, NULL); + if (err) + return __hurd_fail (EPERM); + + /* `time_value_t' and `struct timeval' are in fact identical with the + names changed. */ + err = __host_set_time (hostpriv, *(time_value_t *) tv); + __mach_port_deallocate (__mach_task_self (), hostpriv); + + if (err) + return __hurd_fail (err); + + return 0; +} + +weak_alias (__settimeofday, settimeofday) diff --git a/libc/sysdeps/mach/hurd/setuid.c b/libc/sysdeps/mach/hurd/setuid.c new file mode 100644 index 000000000..3679e8e0f --- /dev/null +++ b/libc/sysdeps/mach/hurd/setuid.c @@ -0,0 +1,101 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 97 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 <unistd.h> +#include <sys/types.h> +#include <hurd.h> +#include <hurd/id.h> +#include <string.h> + +/* Set the user ID of the calling process to UID. + If the calling process is the super-user, the real + and effective user IDs, and the saved set-user-ID to UID; + if not, the effective user ID is set to UID. */ +int +__setuid (uid) + uid_t uid; +{ + auth_t newauth; + error_t err; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); + + if (!err) + { + /* Make a new auth handle which has UID as the real uid, + and as the first element in the list of effective uids. */ + + uid_t *newgen, *newaux, auxbuf[2]; + size_t ngen, naux; + + newaux = _hurd_id.aux.uids; + naux = _hurd_id.aux.nuids; + if (_hurd_id.gen.nuids == 0) + { + /* No effective uids now. The new set will be just UID. */ + newgen = &uid; + ngen = 1; + } + else if (_hurd_id.gen.uids[0] == 0) + { + /* We are root; set the effective, real, and saved to UID. */ + _hurd_id.gen.uids[0] = uid; + _hurd_id.valid = 0; + newgen = _hurd_id.gen.uids; + ngen = _hurd_id.gen.nuids; + if (_hurd_id.aux.nuids < 2) + { + newaux = auxbuf; + naux = 2; + } + newaux[0] = newaux[1] = uid; + } + else + { + /* We are not root; just change the effective UID. */ + /* XXX that implies an unprivileged setuid(0) will give + the caller root, no questions asked! */ + _hurd_id.gen.uids[0] = uid; + _hurd_id.valid = 0; + newgen = _hurd_id.gen.uids; + ngen = _hurd_id.gen.nuids; + } + + err = __USEPORT (AUTH, __auth_makeauth + (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0, + newgen, ngen, newaux, naux, + _hurd_id.gen.gids, _hurd_id.gen.ngids, + _hurd_id.aux.gids, _hurd_id.aux.ngids, + &newauth)); + } + __mutex_unlock (&_hurd_id.lock); + HURD_CRITICAL_END; + + if (err) + return __hurd_fail (err); + + /* Install the new handle and reauthenticate everything. */ + err = __setauth (newauth); + __mach_port_deallocate (__mach_task_self (), newauth); + return err; +} + +weak_alias (__setuid, setuid) diff --git a/libc/sysdeps/mach/hurd/setxattr.c b/libc/sysdeps/mach/hurd/setxattr.c new file mode 100644 index 000000000..afabc8ee0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/setxattr.c @@ -0,0 +1,36 @@ +/* Access to extended attributes on files. Hurd version. + Copyright (C) 2006 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/xattr.h> +#include <hurd.h> +#include <hurd/xattr.h> + +ssize_t +setxattr (const char *path, const char *name, const void *value, size_t size, + int flags) +{ + error_t err; + file_t port = __file_name_lookup (path, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = _hurd_xattr_set (port, name, value, size, flags); + __mach_port_deallocate (__mach_task_self (), port); + return __hurd_fail (err); +} diff --git a/libc/sysdeps/mach/hurd/shutdown.c b/libc/sysdeps/mach/hurd/shutdown.c new file mode 100644 index 000000000..eb425f06e --- /dev/null +++ b/libc/sysdeps/mach/hurd/shutdown.c @@ -0,0 +1,41 @@ +/* Copyright (C) 1992, 1994, 1997 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 <hurd.h> +#include <hurd/socket.h> +#include <hurd/fd.h> + +/* Shut down all or part of the connection open on socket FD. + HOW determines what to shut down: + 0 = No more receptions; + 1 = No more transmissions; + 2 = No more receptions or transmissions. + Returns 0 on success, -1 for errors. */ +/* XXX should be __shutdown ? */ +int +shutdown (fd, how) + int fd; + int how; +{ + error_t err = HURD_DPORT_USE (fd, __socket_shutdown (port, how)); + if (err) + return __hurd_dfail (fd, err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/sigaction.c b/libc/sysdeps/mach/hurd/sigaction.c new file mode 100644 index 000000000..3dc530955 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigaction.c @@ -0,0 +1,94 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,2002 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 <signal.h> +#include <hurd.h> +#include <hurd/signal.h> + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__sigaction (sig, act, oact) + int sig; + const struct sigaction *act; + struct sigaction *oact; +{ + struct hurd_sigstate *ss; + struct sigaction a, old; + sigset_t pending; + + if (sig <= 0 || sig >= NSIG || + (act != NULL && act->sa_handler != SIG_DFL && + ((__sigmask (sig) & _SIG_CANT_MASK) || + act->sa_handler == SIG_ERR))) + { + errno = EINVAL; + return -1; + } + + /* Copy so we fault before taking locks. */ + if (act != NULL) + a = *act; + + ss = _hurd_self_sigstate (); + + __spin_lock (&ss->critical_section_lock); + __spin_lock (&ss->lock); + old = ss->actions[sig]; + if (act != NULL) + ss->actions[sig] = a; + + if (act != NULL && sig == SIGCHLD && + (a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP)) + { + __spin_unlock (&ss->lock); + + /* 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 + SIGCHLD can arrive in the middle and be of indeterminate status. */ + __USEPORT (PROC, + __proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP))); + + __spin_lock (&ss->lock); + pending = ss->pending & ~ss->blocked; + } + else if (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL) + /* We are changing to an action that might be to ignore SIG signals. + If SIG is blocked and pending and the new action is to ignore it, we + must remove it from the pending set now; if the action is changed + 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); + else + pending = 0; + + __spin_unlock (&ss->lock); + __spin_unlock (&ss->critical_section_lock); + + if (pending) + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + + if (oact != NULL) + *oact = old; + + return 0; +} +libc_hidden_def (__sigaction) +weak_alias (__sigaction, sigaction) diff --git a/libc/sysdeps/mach/hurd/sigaltstack.c b/libc/sysdeps/mach/hurd/sigaltstack.c new file mode 100644 index 000000000..5b2f06561 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigaltstack.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1992, 93, 94, 95, 97, 98 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 <hurd.h> +#include <hurd/signal.h> + +/* Run signals handlers on the stack specified by SS (if not NULL). + If OSS is not NULL, it is filled in with the old signal stack status. */ +int +__sigaltstack (argss, oss) + const struct sigaltstack *argss; + struct sigaltstack *oss; +{ + struct hurd_sigstate *s; + struct sigaltstack ss, old; + + /* Fault before taking any locks. */ + if (argss != NULL) + ss = *argss; + if (oss != NULL) + *(volatile struct sigaltstack *) oss = *oss; + + s = _hurd_self_sigstate (); + __spin_lock (&s->lock); + + if (argss != NULL && + (ss.ss_flags & SS_DISABLE) && (s->sigaltstack.ss_flags & SS_ONSTACK)) + { + /* Can't disable a stack that is in use. */ + __spin_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + old = s->sigaltstack; + + if (argss != NULL) + s->sigaltstack = ss; + + __spin_unlock (&s->lock); + + if (oss != NULL) + *oss = old; + + return 0; +} +weak_alias (__sigaltstack, sigaltstack) diff --git a/libc/sysdeps/mach/hurd/siglist.h b/libc/sysdeps/mach/hurd/siglist.h new file mode 100644 index 000000000..75701c874 --- /dev/null +++ b/libc/sysdeps/mach/hurd/siglist.h @@ -0,0 +1,23 @@ +/* Copyright (C) 1999, 2002 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. */ + +/* This file is included multiple times. */ + +#include_next <siglist.h> /* Get the canonical list. */ + +#define OLD_SIGLIST_SIZE 33 /* For GLIBC_2.0 binary compatibility. */ diff --git a/libc/sysdeps/mach/hurd/sigpending.c b/libc/sysdeps/mach/hurd/sigpending.c new file mode 100644 index 000000000..84ac92714 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigpending.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1993, 1994, 1995, 1997 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 <stddef.h> +#include <hurd.h> +#include <hurd/signal.h> + + +/* Store in SET all signals that are blocked and pending. */ +/* XXX should be __sigpending ? */ +int +sigpending (set) + sigset_t *set; +{ + struct hurd_sigstate *ss; + sigset_t pending; + + if (set == NULL) + { + errno = EINVAL; + return -1; + } + + ss = _hurd_self_sigstate (); + __spin_lock (&ss->lock); + pending = ss->pending; + __spin_unlock (&ss->lock); + + *set = pending; + return 0; +} diff --git a/libc/sysdeps/mach/hurd/sigprocmask.c b/libc/sysdeps/mach/hurd/sigprocmask.c new file mode 100644 index 000000000..cbb5ecce2 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigprocmask.c @@ -0,0 +1,87 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,2002 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 <signal.h> +#include <hurd.h> +#include <hurd/signal.h> +#include <hurd/msg.h> + +/* If SET is not NULL, modify the current set of blocked signals + according to HOW, which may be SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK. + If OSET is not NULL, store the old set of blocked signals in *OSET. */ +int +__sigprocmask (how, set, oset) + int how; + const sigset_t *set; + sigset_t *oset; +{ + struct hurd_sigstate *ss; + sigset_t old, new; + sigset_t pending; + + if (set != NULL) + new = *set; + + ss = _hurd_self_sigstate (); + + __spin_lock (&ss->lock); + + old = ss->blocked; + + if (set != NULL) + { + switch (how) + { + case SIG_BLOCK: + __sigorset (&ss->blocked, &ss->blocked, &new); + break; + + case SIG_UNBLOCK: + ss->blocked &= ~new; + break; + + case SIG_SETMASK: + ss->blocked = new; + break; + + default: + __spin_unlock (&ss->lock); + errno = EINVAL; + return -1; + } + + ss->blocked &= ~_SIG_CANT_MASK; + } + + pending = ss->pending & ~ss->blocked; + + __spin_unlock (&ss->lock); + + if (oset != NULL) + *oset = old; + + if (pending) + /* Send a message to the signal thread so it + will wake up and check for pending signals. */ + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + + return 0; +} + +weak_alias (__sigprocmask, sigprocmask) diff --git a/libc/sysdeps/mach/hurd/sigstack.c b/libc/sysdeps/mach/hurd/sigstack.c new file mode 100644 index 000000000..3282da3de --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigstack.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1992,97,98,2000 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 <signal.h> +#include <hurd.h> + +/* Run signals handlers on the stack specified by SS (if not NULL). + If OSS is not NULL, it is filled in with the old signal stack status. */ +int +sigstack (struct sigstack *ss, struct sigstack *oss) +{ + struct sigaltstack as, oas; + + as.ss_sp = ss->ss_sp; + as.ss_size = 0; + as.ss_flags = 0; + + if (__sigaltstack (&as, &oas) < 0) + return -1; + + if (oss != NULL) + { + oss->ss_sp = oas.ss_sp; + oss->ss_onstack = oas.ss_flags & SS_ONSTACK; + } + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/sigsuspend.c b/libc/sysdeps/mach/hurd/sigsuspend.c new file mode 100644 index 000000000..96b3857c7 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigsuspend.c @@ -0,0 +1,83 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,2002 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 <hurd.h> +#include <hurd/signal.h> +#include <hurd/msg.h> + +/* Change the set of blocked signals to SET, + wait until a signal arrives, and restore the set of blocked signals. */ +int +__sigsuspend (set) + const sigset_t *set; +{ + struct hurd_sigstate *ss; + sigset_t newmask, oldmask, pending; + mach_port_t wait; + mach_msg_header_t msg; + + if (set != NULL) + /* Crash before locking. */ + newmask = *set; + + /* Get a fresh port we will wait on. */ + wait = __mach_reply_port (); + + ss = _hurd_self_sigstate (); + + __spin_lock (&ss->lock); + + oldmask = ss->blocked; + if (set != NULL) + /* Change to the new blocked signal mask. */ + ss->blocked = newmask & ~_SIG_CANT_MASK; + + /* Notice if any pending signals just became unblocked. */ + pending = ss->pending & ~ss->blocked; + + /* Tell the signal thread to message us when a signal arrives. */ + ss->suspended = wait; + __spin_unlock (&ss->lock); + + if (pending) + /* Tell the signal thread to check for pending signals. */ + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + + /* Wait for the signal thread's message. */ + __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait, + 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); + + if (pending) + /* Tell the signal thread to check for pending signals. */ + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + + /* We've been interrupted! And a good thing, too. + Otherwise we'd never return. + That's right; this function always returns an error. */ + errno = EINTR; + return -1; +} +libc_hidden_def (__sigsuspend) +weak_alias (__sigsuspend, sigsuspend) diff --git a/libc/sysdeps/mach/hurd/sigwait.c b/libc/sysdeps/mach/hurd/sigwait.c new file mode 100644 index 000000000..9794076be --- /dev/null +++ b/libc/sysdeps/mach/hurd/sigwait.c @@ -0,0 +1,133 @@ +/* Copyright (C) 1996,97,2001,02 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 <hurd.h> +#include <hurd/signal.h> +#include <hurd/msg.h> +#include <hurd/sigpreempt.h> +#include <assert.h> + +/* Select any of pending signals from SET or wait for any to arrive. */ +int +__sigwait (const sigset_t *set, int *sig) +{ + struct hurd_sigstate *ss; + sigset_t mask, ready; + int signo = 0; + struct hurd_signal_preemptor preemptor; + jmp_buf buf; + mach_port_t wait; + mach_msg_header_t msg; + + sighandler_t + preempt_fun (struct hurd_signal_preemptor *pe, + struct hurd_sigstate *ss, + int *sigp, + struct hurd_signal_detail *detail) + { + if (signo) + /* We've already been run; don't interfere. */ + return SIG_ERR; + + signo = *sigp; + + /* Make sure this is all kosher */ + assert (__sigismember (&mask, signo)); + + /* Make sure this signal is unblocked */ + __sigdelset (&ss->blocked, signo); + + return pe->handler; + } + + void + handler (int sig) + { + assert (sig == signo); + longjmp (buf, 1); + } + + wait = __mach_reply_port (); + + if (set != NULL) + /* Crash before locking */ + mask = *set; + else + __sigemptyset (&mask); + + ss = _hurd_self_sigstate (); + __spin_lock (&ss->lock); + + /* See if one of these signals is currently pending. */ + __sigandset (&ready, &ss->pending, &mask); + if (! __sigisemptyset (&ready)) + { + for (signo = 1; signo < NSIG; signo++) + if (__sigismember (&ready, signo)) + { + __sigdelset (&ready, signo); + goto all_done; + } + /* Huh? Where'd it go? */ + abort (); + } + + /* Wait for one of them to show up. */ + + if (!setjmp (buf)) + { + /* Make the preemptor */ + preemptor.signals = mask; + preemptor.first = 0; + preemptor.last = -1; + preemptor.preemptor = preempt_fun; + preemptor.handler = handler; + + /* Install this preemptor */ + preemptor.next = ss->preemptors; + ss->preemptors = &preemptor; + + __spin_unlock (&ss->lock); + + /* Wait. */ + __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + abort (); + } + else + { + assert (signo); + + __spin_lock (&ss->lock); + + /* Delete our preemptor. */ + assert (ss->preemptors == &preemptor); + ss->preemptors = preemptor.next; + } + + +all_done: + spin_unlock (&ss->lock); + + __mach_port_destroy (__mach_task_self (), wait); + *sig = signo; + return 0; +} + +weak_alias (__sigwait, sigwait) diff --git a/libc/sysdeps/mach/hurd/socket.c b/libc/sysdeps/mach/hurd/socket.c new file mode 100644 index 000000000..a707ed90e --- /dev/null +++ b/libc/sysdeps/mach/hurd/socket.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1992, 93, 94, 95, 96, 97, 98 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 <hurd.h> +#include <hurd/socket.h> +#include <hurd/fd.h> +#include <fcntl.h> + +/* Create a new socket of type TYPE in domain DOMAIN, using + protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. + Returns a file descriptor for the new socket, or -1 for errors. */ +int +__socket (domain, type, protocol) + int domain; + int type; + int protocol; +{ + error_t err; + socket_t sock, server; + + /* Find the socket server for DOMAIN. */ + server = _hurd_socket_server (domain, 0); + if (server == MACH_PORT_NULL) + return -1; + + err = __socket_create (server, type, protocol, &sock); + if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED + || err == MIG_BAD_ID || err == EOPNOTSUPP) + { + /* On the first use of the socket server during the operation, + allow for the old server port dying. */ + server = _hurd_socket_server (domain, 1); + if (server == MACH_PORT_NULL) + return -1; + err = __socket_create (server, type, protocol, &sock); + } + + /* These errors all mean that the server node doesn't support the + socket.defs protocol, which we'll take to mean that the protocol + isn't supported. */ + if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED + || err == MIG_BAD_ID || err == EOPNOTSUPP) + err = EPFNOSUPPORT; + + if (err) + return __hurd_fail (err); + + return _hurd_intern_fd (sock, O_IGNORE_CTTY, 1); +} + +weak_alias (__socket, socket) diff --git a/libc/sysdeps/mach/hurd/socketpair.c b/libc/sysdeps/mach/hurd/socketpair.c new file mode 100644 index 000000000..b124d2017 --- /dev/null +++ b/libc/sysdeps/mach/hurd/socketpair.c @@ -0,0 +1,95 @@ +/* Copyright (C) 1992, 94, 95, 96, 97, 2000 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 <fcntl.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/socket.h> + +/* Create two new sockets, of type TYPE in domain DOMAIN and using + protocol PROTOCOL, which are connected to each other, and put file + descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, + one will be chosen automatically. Returns 0 on success, -1 for errors. */ +int +__socketpair (int domain, int type, int protocol, int fds[2]) +{ + error_t err; + socket_t server, sock1, sock2; + int d1, d2; + + if (fds == NULL) + return __hurd_fail (EINVAL); + + /* Find the domain's socket server. */ + server = _hurd_socket_server (domain, 0); + if (server == MACH_PORT_NULL) + return -1; + + /* Create two sockets and connect them together. */ + + err = __socket_create (server, type, protocol, &sock1); + if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED + || err == MIG_BAD_ID || err == EOPNOTSUPP) + { + /* On the first use of the socket server during the operation, + allow for the old server port dying. */ + server = _hurd_socket_server (domain, 1); + if (server == MACH_PORT_NULL) + return -1; + err = __socket_create (server, type, protocol, &sock1); + } + if (err) + return __hurd_fail (err); + if (err = __socket_create (server, type, protocol, &sock2)) + { + __mach_port_deallocate (__mach_task_self (), sock1); + return __hurd_fail (err); + } + if (err = __socket_connect2 (sock1, sock2)) + { + __mach_port_deallocate (__mach_task_self (), sock1); + __mach_port_deallocate (__mach_task_self (), sock2); + return __hurd_fail (err); + } + + /* Put the sockets into file descriptors. */ + + d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1); + if (d1 < 0) + { + __mach_port_deallocate (__mach_task_self (), sock2); + return -1; + } + d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1); + if (d2 < 0) + { + err = errno; + (void) close (d1); + return __hurd_fail (err); + } + + fds[0] = d1; + fds[1] = d2; + return 0; +} + +weak_alias (__socketpair, socketpair) diff --git a/libc/sysdeps/mach/hurd/spawni.c b/libc/sysdeps/mach/hurd/spawni.c new file mode 100644 index 000000000..244ca2d6e --- /dev/null +++ b/libc/sysdeps/mach/hurd/spawni.c @@ -0,0 +1,756 @@ +/* spawn a new process running an executable. Hurd version. + Copyright (C) 2001,02,04 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <spawn.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/signal.h> +#include <hurd/fd.h> +#include <hurd/id.h> +#include <hurd/lookup.h> +#include <hurd/resource.h> +#include <assert.h> +#include <argz.h> +#include "spawn_int.h" + +/* Spawn a new process executing PATH with the attributes describes in *ATTRP. + Before running the process perform the actions described in FILE-ACTIONS. */ +int +__spawni (pid_t *pid, const char *file, + const posix_spawn_file_actions_t *file_actions, + const posix_spawnattr_t *attrp, + char *const argv[], char *const envp[], + int use_path) +{ + pid_t new_pid; + char *path, *p, *name; + size_t len; + size_t pathlen; + short int flags; + + /* The generic POSIX.1 implementation of posix_spawn uses fork and exec. + In traditional POSIX systems (Unix, Linux, etc), the only way to + create a new process is by fork, which also copies all the things from + the parent process that will be immediately wiped and replaced by the + exec. + + This Hurd implementation works by doing an exec on a fresh task, + without ever doing all the work of fork. The only work done by fork + that remains visible after an exec is registration with the proc + server, and the inheritance of various values and ports. All those + inherited values and ports are what get collected up and passed in the + file_exec RPC by an exec call. So we do the proc server registration + here, following the model of fork (see fork.c). We then collect up + the inherited values and ports from this (parent) process following + the model of exec (see hurd/hurdexec.c), modify or replace each value + that fork would (plus the specific changes demanded by ATTRP and + FILE_ACTIONS), and make the file_exec RPC on the requested executable + file with the child process's task port rather than our own. This + should be indistinguishable from the fork + exec implementation, + except that all errors will be detected here (in the parent process) + and return proper errno codes rather than the child dying with 127. + + XXX The one exception to this supposed indistinguishableness is that + when posix_spawn_file_actions_addopen has been used, the parent + process can do various filesystem RPCs on the child's behalf, rather + than the child process doing it. If these block due to a broken or + malicious filesystem server or just a blocked network fs or a serial + port waiting for carrier detect (!!), the parent's posix_spawn call + can block arbitrarily rather than just the child blocking. Possible + solutions include: + * punt to plain fork + exec implementation if addopen was used + ** easy to do + ** gives up all benefits of this implementation in that case + * if addopen was used, don't do any file actions at all here; + instead, exec an installed helper program e.g.: + /libexec/spawn-helper close 3 dup2 1 2 open 0 /file 0x123 0666 exec /bin/foo foo a1 a2 + ** extra exec might be more or less overhead than fork + * could do some weird half-fork thing where the child would inherit + our vm and run some code here, but not do the full work of fork + + XXX Actually, the parent opens the executable file on behalf of + the child, and that has all the same issues. + + I am favoring the half-fork solution. That is, we do task_create with + vm inheritance, and we setjmp/longjmp the child like fork does. But + rather than all the fork hair, the parent just packs up init/dtable + ports and does a single IPC to a receive right inserted in the child. */ + + error_t err; + task_t task; + file_t execfile; + process_t proc; + auth_t auth; + int ints[INIT_INT_MAX]; + file_t *dtable; + unsigned int dtablesize, orig_dtablesize, i; + struct hurd_port **dtable_cells; + char *dtable_cloexec; + struct hurd_userlink *ulink_dtable = NULL; + struct hurd_sigstate *ss; + + /* For POSIX_SPAWN_RESETIDS, this reauthenticates our root/current + directory ports with the new AUTH port. */ + file_t rcrdir = MACH_PORT_NULL, rcwdir = MACH_PORT_NULL; + error_t reauthenticate (int which, file_t *result) + { + error_t err; + mach_port_t ref; + if (*result != MACH_PORT_NULL) + return 0; + ref = __mach_reply_port (); + err = HURD_PORT_USE + (&_hurd_ports[which], + ({ + err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + err = __auth_user_authenticate (auth, + ref, MACH_MSG_TYPE_MAKE_SEND, + result); + err; + })); + __mach_port_destroy (__mach_task_self (), ref); + return err; + } + + /* Reauthenticate one of our file descriptors for the child. A null + element of DTABLE_CELLS indicates a descriptor that was already + reauthenticated, or was newly opened on behalf of the child. */ + error_t reauthenticate_fd (int fd) + { + if (dtable_cells[fd] != NULL) + { + file_t newfile; + mach_port_t ref = __mach_reply_port (); + error_t err = __io_reauthenticate (dtable[fd], + ref, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + err = __auth_user_authenticate (auth, + ref, MACH_MSG_TYPE_MAKE_SEND, + &newfile); + __mach_port_destroy (__mach_task_self (), ref); + if (err) + return err; + _hurd_port_free (dtable_cells[fd], &ulink_dtable[fd], dtable[fd]); + dtable_cells[fd] = NULL; + dtable[fd] = newfile; + } + return 0; + } + + /* These callbacks are for looking up file names on behalf of the child. */ + error_t child_init_port (int which, error_t (*operate) (mach_port_t)) + { + if (flags & POSIX_SPAWN_RESETIDS) + switch (which) + { + case INIT_PORT_AUTH: + return (*operate) (auth); + case INIT_PORT_CRDIR: + return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) + ?: (*operate) (rcrdir)); + case INIT_PORT_CWDIR: + return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) + ?: (*operate) (rcwdir)); + } + assert (which != INIT_PORT_PROC); + return _hurd_ports_use (which, operate); + } + file_t child_fd (int fd) + { + if ((unsigned int) fd < dtablesize && dtable[fd] != MACH_PORT_NULL) + { + if (flags & POSIX_SPAWN_RESETIDS) + { + /* Reauthenticate this descriptor right now, + since it is going to be used on behalf of the child. */ + errno = reauthenticate_fd (fd); + if (errno) + return MACH_PORT_NULL; + } + __mach_port_mod_refs (__mach_task_self (), dtable[fd], + MACH_PORT_RIGHT_SEND, +1); + return dtable[fd]; + } + errno = EBADF; + return MACH_PORT_NULL; + } + inline error_t child_lookup (const char *file, int oflag, mode_t mode, + file_t *result) + { + return __hurd_file_name_lookup (&child_init_port, &child_fd, 0, + file, oflag, mode, result); + } + + + /* Do this once. */ + flags = attrp == NULL ? 0 : attrp->__flags; + + /* Generate the new process. We create a task that does not inherit our + memory, and then register it as our child like fork does. See fork.c + for comments about the sequencing of these proc operations. */ + + err = __task_create (__mach_task_self (), +#ifdef KERN_INVALID_LEDGER + NULL, 0, /* OSF Mach */ +#endif + 0, &task); + if (err) + return __hurd_fail (err); + // From here down we must deallocate TASK and PROC before returning. + proc = MACH_PORT_NULL; + auth = MACH_PORT_NULL; + err = __USEPORT (PROC, __proc_task2pid (port, task, &new_pid)); + if (!err) + err = __USEPORT (PROC, __proc_task2proc (port, task, &proc)); + if (!err) + err = __USEPORT (PROC, __proc_child (port, task)); + if (err) + goto out; + + /* Load up the ints to give the new program. */ + memset (ints, 0, sizeof ints); + ints[INIT_UMASK] = _hurd_umask; + ints[INIT_TRACEMASK] = _hurdsig_traced; + + ss = _hurd_self_sigstate (); + + assert (! __spin_lock_locked (&ss->critical_section_lock)); + __spin_lock (&ss->critical_section_lock); + + __spin_lock (&ss->lock); + ints[INIT_SIGMASK] = ss->blocked; + ints[INIT_SIGPENDING] = ss->pending; + 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 + 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); + + /* Set signal mask. */ + if ((flags & POSIX_SPAWN_SETSIGMASK) != 0) + ints[INIT_SIGMASK] = attrp->__ss; + +#ifdef _POSIX_PRIORITY_SCHEDULING + /* Set the scheduling algorithm and parameters. */ +# error implement me + if ((flags & (POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER)) + == POSIX_SPAWN_SETSCHEDPARAM) + { + if (__sched_setparam (0, &attrp->__sp) == -1) + _exit (SPAWN_ERROR); + } + else if ((flags & POSIX_SPAWN_SETSCHEDULER) != 0) + { + if (__sched_setscheduler (0, attrp->__policy, + (flags & POSIX_SPAWN_SETSCHEDPARAM) != 0 + ? &attrp->__sp : NULL) == -1) + _exit (SPAWN_ERROR); + } +#endif + + /* Set the process group ID. */ + if (!err && (flags & POSIX_SPAWN_SETPGROUP) != 0) + err = __proc_setpgrp (proc, new_pid, attrp->__pgrp); + + /* Set the effective user and group IDs. */ + if (!err && (flags & POSIX_SPAWN_RESETIDS) != 0) + { + /* We need a different auth port for the child. */ + + __mutex_lock (&_hurd_id.lock); + err = _hurd_check_ids (); /* Get _hurd_id up to date. */ + if (!err && _hurd_id.rid_auth == MACH_PORT_NULL) + { + /* Set up _hurd_id.rid_auth. This is a special auth server port + which uses the real uid and gid (the first aux uid and gid) as + the only effective uid and gid. */ + + if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1) + /* We do not have a real UID and GID. Lose, lose, lose! */ + err = EGRATUITOUS; + + /* Create a new auth port using our real UID and GID (the first + auxiliary UID and GID) as the only effective IDs. */ + if (!err) + err = __USEPORT (AUTH, + __auth_makeauth (port, + NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.aux.uids, 1, + _hurd_id.aux.uids, + _hurd_id.aux.nuids, + _hurd_id.aux.gids, 1, + _hurd_id.aux.gids, + _hurd_id.aux.ngids, + &_hurd_id.rid_auth)); + } + if (!err) + { + /* Use the real-ID auth port in place of the normal one. */ + assert (_hurd_id.rid_auth != MACH_PORT_NULL); + auth = _hurd_id.rid_auth; + __mach_port_mod_refs (__mach_task_self (), auth, + MACH_PORT_RIGHT_SEND, +1); + } + __mutex_unlock (&_hurd_id.lock); + } + else + /* Copy our existing auth port. */ + err = __USEPORT (AUTH, __mach_port_mod_refs (__mach_task_self (), + (auth = port), + MACH_PORT_RIGHT_SEND, +1)); + + if (err) + goto out; + + /* Pack up the descriptor table to give the new program. + These descriptors will need to be reauthenticated below + if POSIX_SPAWN_RESETIDS is set. */ + __mutex_lock (&_hurd_dtable_lock); + dtablesize = _hurd_dtablesize; + orig_dtablesize = _hurd_dtablesize; + dtable = __alloca (dtablesize * sizeof (dtable[0])); + ulink_dtable = __alloca (dtablesize * sizeof (ulink_dtable[0])); + dtable_cells = __alloca (dtablesize * sizeof (dtable_cells[0])); + dtable_cloexec = __alloca (dtablesize); + for (i = 0; i < dtablesize; ++i) + { + struct hurd_fd *const d = _hurd_dtable[i]; + if (d == NULL) + { + dtable[i] = MACH_PORT_NULL; + dtable_cells[i] = NULL; + continue; + } + /* Note that this might return MACH_PORT_NULL. */ + dtable[i] = _hurd_port_get (&d->port, &ulink_dtable[i]); + dtable_cells[i] = &d->port; + dtable_cloexec[i] = (d->flags & FD_CLOEXEC) != 0; + } + __mutex_unlock (&_hurd_dtable_lock); + + /* Safe to let signals happen now. */ + _hurd_critical_section_unlock (ss); + + /* Execute the file actions. */ + if (file_actions != NULL) + for (i = 0; i < file_actions->__used; ++i) + { + /* Close a file descriptor in the child. */ + error_t do_close (int fd) + { + if ((unsigned int)fd < dtablesize + && dtable[fd] != MACH_PORT_NULL) + { + if (dtable_cells[fd] == NULL) + __mach_port_deallocate (__mach_task_self (), dtable[fd]); + else + { + _hurd_port_free (dtable_cells[fd], + &ulink_dtable[fd], dtable[fd]); + } + dtable_cells[fd] = NULL; + dtable[fd] = MACH_PORT_NULL; + return 0; + } + return EBADF; + } + + /* Make sure the dtable can hold NEWFD. */ +#define EXPAND_DTABLE(newfd) \ + ({ \ + if ((unsigned int)newfd >= dtablesize \ + && newfd < _hurd_rlimits[RLIMIT_OFILE].rlim_cur) \ + { \ + /* We need to expand the dtable for the child. */ \ + NEW_TABLE (dtable, newfd); \ + NEW_TABLE (ulink_dtable, newfd); \ + NEW_TABLE (dtable_cells, newfd); \ + dtablesize = newfd + 1; \ + } \ + ((unsigned int)newfd < dtablesize ? 0 : EMFILE); \ + }) +#define NEW_TABLE(x, newfd) \ + do { __typeof (x) new_##x = __alloca ((newfd + 1) * sizeof (x[0])); \ + memcpy (new_##x, x, dtablesize * sizeof (x[0])); \ + memset (&new_##x[dtablesize], 0, (newfd + 1 - dtablesize) * sizeof (x[0])); \ + x = new_##x; } while (0) + + struct __spawn_action *action = &file_actions->__actions[i]; + + switch (action->tag) + { + case spawn_do_close: + err = do_close (action->action.close_action.fd); + break; + + case spawn_do_dup2: + if ((unsigned int)action->action.dup2_action.fd < dtablesize + && dtable[action->action.dup2_action.fd] != MACH_PORT_NULL) + { + const int fd = action->action.dup2_action.fd; + const int newfd = action->action.dup2_action.newfd; + // dup2 always clears any old FD_CLOEXEC flag on the new fd. + if (newfd < orig_dtablesize) + dtable_cloexec[newfd] = 0; + if (fd == newfd) + // Same is same as same was. + break; + err = EXPAND_DTABLE (newfd); + if (!err) + { + /* Close the old NEWFD and replace it with FD's + contents, which can be either an original + descriptor (DTABLE_CELLS[FD] != 0) or a new + right that we acquired in this function. */ + do_close (newfd); + dtable_cells[newfd] = dtable_cells[fd]; + if (dtable_cells[newfd] != NULL) + dtable[newfd] = _hurd_port_get (dtable_cells[newfd], + &ulink_dtable[newfd]); + else + { + dtable[newfd] = dtable[fd]; + err = __mach_port_mod_refs (__mach_task_self (), + dtable[fd], + MACH_PORT_RIGHT_SEND, +1); + } + } + } + else + // The old FD specified was bogus. + err = EBADF; + break; + + case spawn_do_open: + /* Open a file on behalf of the child. + + XXX note that this can subject the parent to arbitrary + delays waiting for the files to open. I don't know what the + spec says about this. If it's not permissible, then this + whole forkless implementation is probably untenable. */ + { + const int fd = action->action.open_action.fd; + + do_close (fd); + if (fd < orig_dtablesize) + dtable_cloexec[fd] = 0; + err = EXPAND_DTABLE (fd); + if (err) + break; + + err = child_lookup (action->action.open_action.path, + action->action.open_action.oflag, + action->action.open_action.mode, + &dtable[fd]); + dtable_cells[fd] = NULL; + break; + } + } + + if (err) + goto out; + } + + /* Only now can we perform FD_CLOEXEC. We had to leave the descriptors + unmolested for the file actions to use. Note that the DTABLE_CLOEXEC + array is never expanded by file actions, so it might now have fewer + than DTABLESIZE elements. */ + for (i = 0; i < orig_dtablesize; ++i) + if (dtable[i] != MACH_PORT_NULL && dtable_cloexec[i]) + { + assert (dtable_cells[i] != NULL); + _hurd_port_free (dtable_cells[i], &ulink_dtable[i], dtable[i]); + dtable[i] = MACH_PORT_NULL; + } + + /* Prune trailing null ports from the descriptor table. */ + while (dtablesize > 0 && dtable[dtablesize - 1] == MACH_PORT_NULL) + --dtablesize; + + if (flags & POSIX_SPAWN_RESETIDS) + { + /* Reauthenticate all the child's ports with its new auth handle. */ + + mach_port_t ref; + process_t newproc; + + /* Reauthenticate with the proc server. */ + ref = __mach_reply_port (); + err = __proc_reauthenticate (proc, ref, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + err = __auth_user_authenticate (auth, + ref, MACH_MSG_TYPE_MAKE_SEND, + &newproc); + __mach_port_destroy (__mach_task_self (), ref); + if (!err) + { + __mach_port_deallocate (__mach_task_self (), proc); + proc = newproc; + } + + if (!err) + err = reauthenticate (INIT_PORT_CRDIR, &rcrdir); + if (!err) + err = reauthenticate (INIT_PORT_CWDIR, &rcwdir); + + /* We must reauthenticate all the fds except those that came from + `spawn_do_open' file actions, which were opened using the child's + auth port to begin with. */ + for (i = 0; !err && i < dtablesize; ++i) + err = reauthenticate_fd (i); + } + if (err) + goto out; + + /* Now we are ready to open the executable file using the child's ports. + We do this after performing all the file actions so the order of + events is the same as for a fork, exec sequence. This affects things + like the meaning of a /dev/fd file name, as well as which error + conditions are diagnosed first and what side effects (file creation, + etc) can be observed before what errors. */ + + if (! use_path || strchr (file, '/') != NULL) + /* The FILE parameter is actually a path. */ + err = child_lookup (file, O_EXEC, 0, &execfile); + else + { + /* We have to search for FILE on the path. */ + path = getenv ("PATH"); + if (path == NULL) + { + /* There is no `PATH' in the environment. + The default search path is the current directory + followed by the path `confstr' returns for `_CS_PATH'. */ + len = confstr (_CS_PATH, (char *) NULL, 0); + path = (char *) __alloca (1 + len); + path[0] = ':'; + (void) confstr (_CS_PATH, path + 1, len); + } + + len = strlen (file) + 1; + pathlen = strlen (path); + name = __alloca (pathlen + len + 1); + /* Copy the file name at the top. */ + name = (char *) memcpy (name + pathlen + 1, file, len); + /* And add the slash. */ + *--name = '/'; + + p = path; + do + { + char *startp; + + path = p; + p = __strchrnul (path, ':'); + + if (p == path) + /* Two adjacent colons, or a colon at the beginning or the end + of `PATH' means to search the current directory. */ + startp = name + 1; + else + startp = (char *) memcpy (name - (p - path), path, p - path); + + /* Try to open this file name. */ + err = child_lookup (startp, O_EXEC, 0, &execfile); + switch (err) + { + case EACCES: + case ENOENT: + case ESTALE: + case ENOTDIR: + /* Those errors indicate the file is missing or not executable + by us, in which case we want to just try the next path + directory. */ + continue; + + case 0: /* Success! */ + default: + /* Some other error means we found an executable file, but + something went wrong executing it; return the error to our + caller. */ + break; + } + + // We only get here when we are done looking for the file. + break; + } + while (*p++ != '\0'); + } + if (err) + goto out; + + /* Almost there! */ + { + mach_port_t ports[_hurd_nports]; + struct hurd_userlink ulink_ports[_hurd_nports]; + char *args = NULL, *env = NULL; + size_t argslen = 0, envlen = 0; + + inline error_t exec (file_t file) + { + return __file_exec (file, task, + (__sigismember (&_hurdsig_traced, SIGKILL) + ? EXEC_SIGTRAP : 0), + args, argslen, env, envlen, + dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize, + ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports, + ints, INIT_INT_MAX, + NULL, 0, NULL, 0); + } + + /* Now we are out of things that can fail before the file_exec RPC, + for which everything else must be prepared. The only thing left + to do is packing up the argument and environment strings, + and the array of init ports. */ + + if (argv != NULL) + err = __argz_create (argv, &args, &argslen); + if (!err && envp != NULL) + err = __argz_create (envp, &env, &envlen); + + /* Load up the ports to give to the new program. + Note the loop/switch below must parallel exactly to release refs. */ + for (i = 0; i < _hurd_nports; ++i) + { + switch (i) + { + case INIT_PORT_AUTH: + ports[i] = auth; + continue; + case INIT_PORT_PROC: + ports[i] = proc; + continue; + case INIT_PORT_CRDIR: + if (flags & POSIX_SPAWN_RESETIDS) + { + ports[i] = rcrdir; + continue; + } + break; + case INIT_PORT_CWDIR: + if (flags & POSIX_SPAWN_RESETIDS) + { + ports[i] = rcwdir; + continue; + } + break; + } + ports[i] = _hurd_port_get (&_hurd_ports[i], &ulink_ports[i]); + } + + /* Finally, try executing the file we opened. */ + if (!err) + err = exec (execfile); + __mach_port_deallocate (__mach_task_self (), execfile); + + if (err == ENOEXEC) + { + /* The file is accessible but it is not an executable file. + Invoke the shell to interpret it as a script. */ + err = __argz_insert (&args, &argslen, args, _PATH_BSHELL); + if (!err) + err = child_lookup (_PATH_BSHELL, O_EXEC, 0, &execfile); + if (!err) + { + err = exec (execfile); + __mach_port_deallocate (__mach_task_self (), execfile); + } + } + + /* Release the references just packed up in PORTS. + This switch must always parallel the one above that fills PORTS. */ + for (i = 0; i < _hurd_nports; ++i) + { + switch (i) + { + case INIT_PORT_AUTH: + case INIT_PORT_PROC: + continue; + case INIT_PORT_CRDIR: + if (flags & POSIX_SPAWN_RESETIDS) + continue; + break; + case INIT_PORT_CWDIR: + if (flags & POSIX_SPAWN_RESETIDS) + continue; + break; + } + _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]); + } + + free (args); + free (env); + } + + /* We did it! We have a child! */ + if (pid != NULL) + *pid = new_pid; + + out: + /* Clean up all the references we are now holding. */ + + if (task != MACH_PORT_NULL) + { + if (err) + /* We failed after creating the task, so kill it. */ + __task_terminate (task); + __mach_port_deallocate (__mach_task_self (), task); + } + __mach_port_deallocate (__mach_task_self (), auth); + __mach_port_deallocate (__mach_task_self (), proc); + if (rcrdir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), rcrdir); + if (rcwdir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), rcwdir); + + if (ulink_dtable) + /* Release references to the file descriptor ports. */ + for (i = 0; i < dtablesize; ++i) + if (dtable[i] != MACH_PORT_NULL) + { + if (dtable_cells[i] == NULL) + __mach_port_deallocate (__mach_task_self (), dtable[i]); + else + _hurd_port_free (dtable_cells[i], &ulink_dtable[i], dtable[i]); + } + + if (err) + /* This hack canonicalizes the error code that we return. */ + err = (__hurd_fail (err), errno); + + return err; +} diff --git a/libc/sysdeps/mach/hurd/statfs.c b/libc/sysdeps/mach/hurd/statfs.c new file mode 100644 index 000000000..65956ae66 --- /dev/null +++ b/libc/sysdeps/mach/hurd/statfs.c @@ -0,0 +1,32 @@ +/* statfs -- Return information about the filesystem on which FILE resides. + Copyright (C) 1996,97,2002 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 <sys/statfs.h> + +#include "statfsconv.c" + +/* Return information about the filesystem on which FILE resides. */ +int +__statfs (const char *file, struct statfs *buf) +{ + struct statfs64 buf64; + return __statfs64 (file, &buf64) ?: statfs64_conv (buf, &buf64); +} +libc_hidden_def (__statfs) +weak_alias (__statfs, statfs) diff --git a/libc/sysdeps/mach/hurd/statfs64.c b/libc/sysdeps/mach/hurd/statfs64.c new file mode 100644 index 000000000..2d5b0363e --- /dev/null +++ b/libc/sysdeps/mach/hurd/statfs64.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2001,02 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 <sys/statfs.h> +#include <hurd.h> + +/* Return information about the filesystem on which FILE resides. */ +int +__statfs64 (const char *file, struct statfs64 *buf) +{ + error_t err; + file_t port; + + port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_statfs (port, buf); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} +weak_alias (__statfs64, statfs64) diff --git a/libc/sysdeps/mach/hurd/statfsconv.c b/libc/sysdeps/mach/hurd/statfsconv.c new file mode 100644 index 000000000..57a06c450 --- /dev/null +++ b/libc/sysdeps/mach/hurd/statfsconv.c @@ -0,0 +1,49 @@ +/* Convert between `struct statfs' format, and `struct statfs64' format. + Copyright (C) 2001,02 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 <sys/statfs.h> +#include <errno.h> + +static inline int +statfs64_conv (struct statfs *buf, const struct statfs64 *buf64) +{ +# define DO(memb) \ + buf->memb = buf64->memb; \ + if (sizeof buf->memb != sizeof buf64->memb && buf->memb != buf64->memb) \ + { \ + __set_errno (EOVERFLOW); \ + return -1; \ + } + + DO (f_type); + DO (f_bsize); + DO (f_blocks); + DO (f_bfree); + DO (f_bavail); + DO (f_files); + DO (f_fsid); + DO (f_namelen); + DO (f_favail); + DO (f_frsize); + DO (f_flag); + +# undef DO + + return 0; +} diff --git a/libc/sysdeps/mach/hurd/statvfs.c b/libc/sysdeps/mach/hurd/statvfs.c new file mode 100644 index 000000000..759a7cfe4 --- /dev/null +++ b/libc/sysdeps/mach/hurd/statvfs.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1998, 2001, 2002 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 <sys/statfs.h> +#include <sys/statvfs.h> + +int +statvfs (const char *file, struct statvfs *buf) +{ + /* `struct statvfs' is in fact identical to `struct statfs' so we + can simply call statfs. */ + return __statfs (file, (struct statfs *)buf); +} +libc_hidden_def (statvfs) diff --git a/libc/sysdeps/mach/hurd/statvfs64.c b/libc/sysdeps/mach/hurd/statvfs64.c new file mode 100644 index 000000000..6f1940772 --- /dev/null +++ b/libc/sysdeps/mach/hurd/statvfs64.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 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 <sys/statfs.h> +#include <sys/statvfs.h> + +int +statvfs64 (const char *file, struct statvfs64 *buf) +{ + /* `struct statvfs64' is in fact identical to `struct statfs64' so + we can simply call statfs64. */ + return __statfs64 (file, (struct statfs64 *)buf); +} diff --git a/libc/sysdeps/mach/hurd/symlink.c b/libc/sysdeps/mach/hurd/symlink.c new file mode 100644 index 000000000..857e236b8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/symlink.c @@ -0,0 +1,69 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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 <string.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/paths.h> +#include <fcntl.h> + +/* Make a link to FROM called TO. */ +int +__symlink (from, to) + const char *from; + const char *to; +{ + error_t err; + file_t dir, node; + char *name; + const size_t len = strlen (from) + 1; + char buf[sizeof (_HURD_SYMLINK) + len]; + + /* A symlink is a file whose translator is "/hurd/symlink\0target\0". */ + + memcpy (buf, _HURD_SYMLINK, sizeof (_HURD_SYMLINK)); + memcpy (&buf[sizeof (_HURD_SYMLINK)], from, len); + + dir = __file_name_split (to, &name); + if (dir == MACH_PORT_NULL) + return -1; + + /* Create a new, unlinked node in the target directory. */ + err = __dir_mkfile (dir, O_WRITE, 0777 & ~_hurd_umask, &node); + + if (! err) + /* Set the node's translator to make it a symlink. */ + err = __file_set_translator (node, + FS_TRANS_EXCL|FS_TRANS_SET, + FS_TRANS_EXCL|FS_TRANS_SET, 0, + buf, sizeof (_HURD_SYMLINK) + len, + MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); + + if (! err) + /* Link the node, now a valid symlink, into the target directory. */ + err = __dir_link (dir, node, name, 1); + + __mach_port_deallocate (__mach_task_self (), dir); + __mach_port_deallocate (__mach_task_self (), node); + + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__symlink, symlink) diff --git a/libc/sysdeps/mach/hurd/symlinkat.c b/libc/sysdeps/mach/hurd/symlinkat.c new file mode 100644 index 000000000..9a51c66d8 --- /dev/null +++ b/libc/sysdeps/mach/hurd/symlinkat.c @@ -0,0 +1,74 @@ +/* Create a symbolic link named relative to an open directory. Hurd version. + Copyright (C) 1991,1992,1993,1994,1995,1996,1997,2006 + 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 <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/paths.h> +#include <hurd/fd.h> +#include <string.h> + + +/* Make a link to FROM called TO relative to FD. */ +int +symlinkat (from, fd, to) + const char *from; + int fd; + const char *to; +{ + error_t err; + file_t dir, node; + char *name; + const size_t len = strlen (from) + 1; + char buf[sizeof (_HURD_SYMLINK) + len]; + + /* A symlink is a file whose translator is "/hurd/symlink\0target\0". */ + + memcpy (buf, _HURD_SYMLINK, sizeof (_HURD_SYMLINK)); + memcpy (&buf[sizeof (_HURD_SYMLINK)], from, len); + + dir = __file_name_split_at (fd, to, &name); + if (dir == MACH_PORT_NULL) + return -1; + + /* Create a new, unlinked node in the target directory. */ + err = __dir_mkfile (dir, O_WRITE, 0777 & ~_hurd_umask, &node); + + if (! err) + /* Set the node's translator to make it a symlink. */ + err = __file_set_translator (node, + FS_TRANS_EXCL|FS_TRANS_SET, + FS_TRANS_EXCL|FS_TRANS_SET, 0, + buf, sizeof (_HURD_SYMLINK) + len, + MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); + + if (! err) + /* Link the node, now a valid symlink, into the target directory. */ + err = __dir_link (dir, node, name, 1); + + __mach_port_deallocate (__mach_task_self (), dir); + __mach_port_deallocate (__mach_task_self (), node); + + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/sync.c b/libc/sysdeps/mach/hurd/sync.c new file mode 100644 index 000000000..4a97e48dd --- /dev/null +++ b/libc/sysdeps/mach/hurd/sync.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991,1992,1993,1994,1997,2001 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 <unistd.h> +#include <hurd.h> + +/* Make all changes done to all files actually appear on disk. */ +void +sync () +{ + /* This is not actually synchronous; we don't wait. */ + error_t err = __USEPORT (CRDIR, __file_syncfs (port, 0, 1)); + if (err) + (void) __hurd_fail (err); +} diff --git a/libc/sysdeps/mach/hurd/sys/param.h b/libc/sysdeps/mach/hurd/sys/param.h new file mode 100644 index 000000000..699ba3510 --- /dev/null +++ b/libc/sysdeps/mach/hurd/sys/param.h @@ -0,0 +1,132 @@ +/* Copyright (C) 1993, 1994, 1995, 1997, 1999 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. */ + +/* This file is deprecated and is provided only for compatibility with + Unix systems. It is unwise to include this file on programs which + are intended only for GNU systems. + + Parts from: + + * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)param.h 7.23 (Berkeley) 5/6/91 + */ + + +#ifndef _SYS_PARAM_H + +#define _SYS_PARAM_H 1 +#include <features.h> + +#define __need_NULL +#include <stddef.h> + +#include <sys/types.h> +#include <errno.h> +#include <signal.h> +#include <endian.h> +#include <limits.h> +#ifdef notyet +# include <ufs/param.h> +#endif + + +/* What versions of BSD we are compatible with. */ +#define BSD 199306 /* System version (year & month). */ +#define BSD4_3 1 +#define BSD4_4 1 + +#define GNU 1994100 /* GNU version (year, month, and release). */ + + +/* BSD names for some <limits.h> values. We do not define the BSD names + for the values which are not statically limited, such as NOFILE. */ + +#define NBBY CHAR_BIT +#define NGROUPS NGROUPS_MAX +#define MAXSYMLINKS SYMLOOP_MAX +#define CANBSIZ MAX_CANON /* XXX ? */ + +/* ARG_MAX is unlimited, but we define NCARGS for BSD programs that want to + compare against some fixed limit. */ +#define NCARGS INT_MAX + +/* There is nothing quite equivalent in GNU to Unix "mounts", but there is + no limit on the number of simultaneously attached filesystems. */ +#define NMOUNT INT_MAX + + +/* Magical constants. */ +#define NOGROUP 65535 /* Marker for empty group set member. */ +#define NODEV ((dev_t) -1) /* Non-existent device. */ + + +/* Bit map related macros. */ +#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) + +/* Macros for counting and rounding. */ +#ifndef howmany +# define howmany(x, y) (((x)+((y)-1))/(y)) +#endif +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#define powerof2(x) ((((x)-1)&(x))==0) + +/* Macros for min/max. */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + + +/* Scale factor for scaled integers used to count %cpu time and load avgs. + + The number of CPU `tick's that map to a unique `%age' can be expressed + by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that + can be calculated (assuming 32 bits) can be closely approximated using + the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). */ + +#define FSHIFT 11 /* Bits to right of fixed binary point. */ +#define FSCALE (1<<FSHIFT) + +#endif /* sys/param.h */ diff --git a/libc/sysdeps/mach/hurd/telldir.c b/libc/sysdeps/mach/hurd/telldir.c new file mode 100644 index 000000000..8a889f4bf --- /dev/null +++ b/libc/sysdeps/mach/hurd/telldir.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1993, 1994, 1995, 1997, 1999 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 <stddef.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include "dirstream.h" + +/* Return the current position of DIRP. */ +/* XXX should be __telldir ? */ +long int +telldir (dirp) + DIR *dirp; +{ + return dirp->__entry_ptr; +} diff --git a/libc/sysdeps/mach/hurd/times.c b/libc/sysdeps/mach/hurd/times.c new file mode 100644 index 000000000..deab40e5e --- /dev/null +++ b/libc/sysdeps/mach/hurd/times.c @@ -0,0 +1,75 @@ +/* Return CPU and real time used by process and its children. Hurd version. + Copyright (C) 2001,2002,2003,2004 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 <stddef.h> +#include <sys/resource.h> +#include <sys/times.h> +#include <sys/time.h> +#include <time.h> +#include <mach.h> +#include <mach/task_info.h> +#include <hurd.h> + +static inline clock_t +clock_from_time_value (const time_value_t *t) +{ + return t->seconds * 1000000 + t->microseconds; +} + +/* Store the CPU time used by this process and all its + dead children (and their dead children) in BUFFER. + Return the elapsed real time, or (clock_t) -1 for errors. + All times are in CLK_TCKths of a second. */ +clock_t +__times (struct tms *tms) +{ + struct task_basic_info bi; + struct task_thread_times_info tti; + mach_msg_type_number_t count; + union { time_value_t tvt; struct timeval tv; } now; + error_t err; + + count = TASK_BASIC_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_BASIC_INFO, + (task_info_t) &bi, &count); + if (err) + return __hurd_fail (err); + + count = TASK_THREAD_TIMES_INFO_COUNT; + err = __task_info (__mach_task_self (), TASK_THREAD_TIMES_INFO, + (task_info_t) &tti, &count); + if (err) + return __hurd_fail (err); + + tms->tms_utime = (clock_from_time_value (&bi.user_time) + + clock_from_time_value (&tti.user_time)); + tms->tms_stime = (clock_from_time_value (&bi.system_time) + + clock_from_time_value (&tti.system_time)); + + /* XXX This can't be implemented until getrusage(RUSAGE_CHILDREN) can be. */ + tms->tms_cutime = tms->tms_cstime = 0; + + if (__gettimeofday (&now.tv, NULL) < 0) + return -1; + + return (clock_from_time_value (&now.tvt) + - clock_from_time_value (&bi.creation_time)); +} +weak_alias (__times, times) diff --git a/libc/sysdeps/mach/hurd/tls.h b/libc/sysdeps/mach/hurd/tls.h new file mode 100644 index 000000000..cce42ef37 --- /dev/null +++ b/libc/sysdeps/mach/hurd/tls.h @@ -0,0 +1,77 @@ +/* Definitions for thread-local data handling. Hurd version. + Copyright (C) 2003, 2005 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 _TLS_H +#define _TLS_H + +#if defined HAVE_TLS_SUPPORT && !defined ASSEMBLER + +# include <stddef.h> +# include <stdbool.h> +# include <mach/mig_errors.h> +# include <mach.h> + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +/* Type of the TCB. */ +typedef struct +{ + void *tcb; /* Points to this structure. */ + dtv_t *dtv; /* Vector of pointers to TLS data. */ + thread_t self; /* This thread's control port. */ +} tcbhead_t; + + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE TLS_INIT_TCB_SIZE /* XXX */ + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN TLS_INIT_TCB_ALIGN /* XXX */ + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +#endif /* HAVE_TLS_SUPPORT */ + + +#endif /* tls.h */ diff --git a/libc/sysdeps/mach/hurd/tmpfile.c b/libc/sysdeps/mach/hurd/tmpfile.c new file mode 100644 index 000000000..ea32d4a99 --- /dev/null +++ b/libc/sysdeps/mach/hurd/tmpfile.c @@ -0,0 +1,69 @@ +/* Open a stdio stream on an anonymous temporary file. Hurd version. + Copyright (C) 2001,2002,2003 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 <stdio.h> +#include <hurd.h> +#include <hurd/fs.h> +#include <hurd/fd.h> +#include <fcntl.h> +#include <unistd.h> +#include <iolibio.h> + +/* This returns a new stream opened on a temporary file (generated + by tmpnam). The file is opened with mode "w+b" (binary read/write). + If we couldn't generate a unique filename or the file couldn't + be opened, NULL is returned. */ +FILE * +__tmpfile (void) +{ + error_t err; + file_t file; + int fd; + FILE *f; + + /* Get a port to the directory that will contain the file. */ + const char *dirname = __secure_getenv ("TMPDIR") ?: P_tmpdir; + file_t dir = __file_name_lookup (dirname, 0, 0); + if (dir == MACH_PORT_NULL) + return NULL; + + /* Create an unnamed file in the temporary directory. */ + err = __dir_mkfile (dir, O_RDWR, S_IRUSR | S_IWUSR, &file); + __mach_port_deallocate (__mach_task_self (), dir); + if (err) + return __hurd_fail (err), NULL; + + /* Get a file descriptor for that port. POSIX.1 requires that streams + returned by tmpfile allocate file descriptors as fopen would. */ + fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */ + if (fd < 0) + return NULL; + + /* Open a stream on the unnamed file. + It will cease to exist when this stream is closed. */ + if ((f = INTUSE(_IO_fdopen) (fd, "w+b")) == NULL) + __close (fd); + + return f; +} + +#include <shlib-compat.h> +versioned_symbol (libc, __tmpfile, tmpfile, GLIBC_2_1); + +weak_alias (__tmpfile, tmpfile64) diff --git a/libc/sysdeps/mach/hurd/tmpfile64.c b/libc/sysdeps/mach/hurd/tmpfile64.c new file mode 100644 index 000000000..094304a07 --- /dev/null +++ b/libc/sysdeps/mach/hurd/tmpfile64.c @@ -0,0 +1 @@ +/* tmpfile64 is an alias for tmpfile, defined in tmpfile.c. */ diff --git a/libc/sysdeps/mach/hurd/truncate.c b/libc/sysdeps/mach/hurd/truncate.c new file mode 100644 index 000000000..aaca1b2fc --- /dev/null +++ b/libc/sysdeps/mach/hurd/truncate.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991,92,93,94,95,97,98,2004 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 <fcntl.h> +#include <sys/types.h> +#include <unistd.h> +#include <hurd.h> + +/* Truncate FILE_NAME to LENGTH bytes. */ +int +__truncate (file_name, length) + const char *file_name; + off_t length; +{ + error_t err; + file_t file = __file_name_lookup (file_name, O_WRITE, 0); + + if (file == MACH_PORT_NULL) + return -1; + + err = __file_set_size (file, length); + __mach_port_deallocate (__mach_task_self (), file); + + if (err) + return __hurd_fail (err); + return 0; +} +weak_alias (__truncate, truncate) diff --git a/libc/sysdeps/mach/hurd/ttyname.c b/libc/sysdeps/mach/hurd/ttyname.c new file mode 100644 index 000000000..927851e2e --- /dev/null +++ b/libc/sysdeps/mach/hurd/ttyname.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1994, 1997 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 <unistd.h> +#include <hurd.h> +#include <hurd/term.h> +#include <hurd/fd.h> + +/* Return the pathname of the terminal FD is open on, or NULL on errors. + The returned storage is good only until the next call to this function. */ +char * +ttyname (int fd) +{ + error_t err; + static char nodename[1024]; /* XXX */ + + nodename[0] = '\0'; + if (err = HURD_DPORT_USE (fd, __term_get_nodename (port, nodename))) + return __hurd_dfail (fd, err), NULL; + + return nodename; +} diff --git a/libc/sysdeps/mach/hurd/ttyname_r.c b/libc/sysdeps/mach/hurd/ttyname_r.c new file mode 100644 index 000000000..7313b9afc --- /dev/null +++ b/libc/sysdeps/mach/hurd/ttyname_r.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1994, 95, 96, 98 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 <string.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/term.h> +#include <hurd/fd.h> + +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, -1 otherwise. */ +int +__ttyname_r (int fd, char *buf, size_t buflen) +{ + error_t err; + char nodename[1024]; /* XXX */ + size_t len; + + nodename[0] = '\0'; + if (err = HURD_DPORT_USE (fd, __term_get_nodename (port, nodename))) + return __hurd_dfail (fd, err), -1; + + len = strlen (nodename) + 1; + if (len > buflen) + { + errno = EINVAL; + return -1; + } + + memcpy (buf, nodename, len); + return 0; +} + +weak_alias (__ttyname_r, ttyname_r) diff --git a/libc/sysdeps/mach/hurd/umask.c b/libc/sysdeps/mach/hurd/umask.c new file mode 100644 index 000000000..1a6d3adca --- /dev/null +++ b/libc/sysdeps/mach/hurd/umask.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1992, 1995, 1997 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 <sys/stat.h> +#include <hurd.h> + +/* Set the file creation mask to MASK, returning the old mask. */ +mode_t +__umask (mask) + mode_t mask; +{ + mode_t omask; + mask &= 0777; + omask = _hurd_umask; + _hurd_umask = mask; + return omask; +} + +weak_alias (__umask, umask) diff --git a/libc/sysdeps/mach/hurd/uname.c b/libc/sysdeps/mach/hurd/uname.c new file mode 100644 index 000000000..8077e1497 --- /dev/null +++ b/libc/sysdeps/mach/hurd/uname.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1992,93,94,96,97,2000,02 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 <unistd.h> +#include <sys/utsname.h> +#include <hurd.h> +#include <hurd/startup.h> + +int +__uname (struct utsname *uname) +{ + error_t err; + + if (err = __USEPORT (PROC, __proc_uname (port, uname))) + return __hurd_fail (err); + + /* Fill in the hostname, which the proc server doesn't know. */ + err = errno; + if (__gethostname (uname->nodename, sizeof uname->nodename) < 0) + { + if (errno == ENAMETOOLONG) + /* Ignore the error of the buffer being too small. + It is of fixed size, nothing to do about it. */ + errno = err; + else + return -1; + } + + return 0; +} +weak_alias (__uname, uname) +libc_hidden_def (__uname) +libc_hidden_def (uname) diff --git a/libc/sysdeps/mach/hurd/unlink.c b/libc/sysdeps/mach/hurd/unlink.c new file mode 100644 index 000000000..959c2f8d0 --- /dev/null +++ b/libc/sysdeps/mach/hurd/unlink.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991,92,93,94,95,97,2002 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 <stddef.h> +#include <unistd.h> +#include <hurd.h> + + +/* Remove the link named NAME. */ +int +__unlink (name) + const char *name; +{ + error_t err; + file_t dir; + const char *file; + + dir = __directory_name_split (name, (char **) &file); + if (dir == MACH_PORT_NULL) + return -1; + + err = __dir_unlink (dir, file); + __mach_port_deallocate (__mach_task_self (), dir); + + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__unlink, unlink) diff --git a/libc/sysdeps/mach/hurd/unlinkat.c b/libc/sysdeps/mach/hurd/unlinkat.c new file mode 100644 index 000000000..7740c5a29 --- /dev/null +++ b/libc/sysdeps/mach/hurd/unlinkat.c @@ -0,0 +1,55 @@ +/* unlinkat -- Remove a name relative to an open directory. Hurd version. + Copyright (C) 2006 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 <fcntl.h> +#include <stddef.h> +#include <unistd.h> +#include <hurd.h> +#include <hurd/fd.h> + + +/* Remove the link named NAME. */ +int +unlinkat (fd, name, flag) + int fd; + const char *name; + int flag; +{ + error_t err; + file_t dir; + const char *file; + + if ((flag &~ AT_REMOVEDIR) != 0) + { + __set_errno (EINVAL); + return -1; + } + + dir = __directory_name_split_at (fd, name, (char **) &file); + if (dir == MACH_PORT_NULL) + return -1; + + err = ((flag & AT_REMOVEDIR) ? __dir_rmdir : __dir_unlink) (dir, file); + __mach_port_deallocate (__mach_task_self (), dir); + + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/utimes.c b/libc/sysdeps/mach/hurd/utimes.c new file mode 100644 index 000000000..74f3a342f --- /dev/null +++ b/libc/sysdeps/mach/hurd/utimes.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991-1995, 97, 99, 2000 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 <sys/time.h> +#include <errno.h> +#include <stddef.h> +#include <hurd.h> + +/* Change the access time of FILE to TVP[0] and + the modification time of FILE to TVP[1]. */ +int +__utimes (file, tvp) + const char *file; + const struct timeval tvp[2]; +{ + struct timeval timevals[2]; + error_t err; + file_t port; + + if (tvp == NULL) + { + /* Setting the number of microseconds to `-1' tells the + underlying filesystems to use the current time. */ + timevals[1].tv_usec = timevals[0].tv_usec = (time_t)-1; + tvp = timevals; + } + + port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __file_utimes (port, + *(time_value_t *) &tvp[0], *(time_value_t *) &tvp[1]); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} + +weak_alias (__utimes, utimes) diff --git a/libc/sysdeps/mach/hurd/wait4.c b/libc/sysdeps/mach/hurd/wait4.c new file mode 100644 index 000000000..d9e23412e --- /dev/null +++ b/libc/sysdeps/mach/hurd/wait4.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1993,94,95,96,97,98,99,2002 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 <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <hurd.h> +#include <hurd/port.h> + +pid_t +__wait4 (pid_t pid, __WAIT_STATUS_DEFN stat_loc, int options, + struct rusage *usage) +{ + pid_t dead; + error_t err; + struct rusage ignored; + int sigcode; + int dummy; + + err = __USEPORT (PROC, __proc_wait (port, pid, options, + stat_loc ?: &dummy, &sigcode, + usage ?: &ignored, &dead)); + switch (err) + { + case 0: /* Got a child. */ + return dead; + case EAGAIN: + /* The RPC returns this error when the WNOHANG flag is set and no + selected children are dead (but some are living). In that + situation, our return value is zero. (The RPC can't return zero + for DEAD without also returning some garbage for the other out + parameters, so an error return is much more natural here. Hence + the difference between the RPC and the POSIX.1 interface. */ + return (pid_t) 0; + default: + return (pid_t) __hurd_fail (err); + } +} + +weak_alias (__wait4, wait4) diff --git a/libc/sysdeps/mach/hurd/write.c b/libc/sysdeps/mach/hurd/write.c new file mode 100644 index 000000000..514e46093 --- /dev/null +++ b/libc/sysdeps/mach/hurd/write.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991-1999,2001,2002 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 <unistd.h> +#include <hurd/fd.h> + +ssize_t +__libc_write (int fd, const void *buf, size_t nbytes) +{ + error_t err = HURD_FD_USE (fd, _hurd_fd_write (descriptor, + buf, &nbytes, -1)); + return err ? __hurd_dfail (fd, err) : nbytes; +} +libc_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libc_hidden_weak (__write) +weak_alias (__libc_write, write) diff --git a/libc/sysdeps/mach/hurd/xmknod.c b/libc/sysdeps/mach/hurd/xmknod.c new file mode 100644 index 000000000..5f40188fb --- /dev/null +++ b/libc/sysdeps/mach/hurd/xmknod.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005,2006 + 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 <fcntl.h> +#include <stddef.h> +#include <sys/types.h> +#include <sys/stat.h> + + +/* Create a device file named FILE_NAME, with permission and special bits MODE + and device number DEV (which can be constructed from major and minor + device numbers with the `makedev' macro above). */ +int +__xmknod (int vers, const char *file_name, mode_t mode, dev_t *dev) +{ + return __xmknodat (vers, AT_FDCWD, file_name, mode, dev); +} +libc_hidden_def (__xmknod) diff --git a/libc/sysdeps/mach/hurd/xmknodat.c b/libc/sysdeps/mach/hurd/xmknodat.c new file mode 100644 index 000000000..b2227593c --- /dev/null +++ b/libc/sysdeps/mach/hurd/xmknodat.c @@ -0,0 +1,118 @@ +/* Create a device file relative to an open directory. Hurd version. + Copyright (C) 1991,1992,1993,1994,1995,1996,1999,2002,2005,2006 + 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/stat.h> +#include <hurd.h> +#include <hurd/fd.h> +#include <hurd/paths.h> +#include <fcntl.h> +#include "stdio-common/_itoa.h" +#include <string.h> +#include <sys/types.h> + +/* Create a device file named PATH relative to FD, with permission and + special bits MODE and device number DEV (which can be constructed + from major and minor device numbers with the `makedev' macro + above). */ +int +__xmknodat (int vers, int fd, const char *path, mode_t mode, dev_t *dev) +{ + error_t err; + file_t dir, node; + char *name; + char buf[100], *bp; + const char *translator; + size_t len; + + if (vers != _MKNOD_VER) + return __hurd_fail (EINVAL); + + if (S_ISCHR (mode)) + { + translator = _HURD_CHRDEV; + len = sizeof (_HURD_CHRDEV); + } + else if (S_ISBLK (mode)) + { + translator = _HURD_BLKDEV; + len = sizeof (_HURD_BLKDEV); + } + else if (S_ISFIFO (mode)) + { + translator = _HURD_FIFO; + len = sizeof (_HURD_FIFO); + } + else if (S_ISREG (mode)) + { + translator = NULL; + len = 0; + } + else + { + errno = EINVAL; + return -1; + } + + if (translator != NULL && ! S_ISFIFO (mode)) + { + /* We set the translator to "ifmt\0major\0minor\0", where IFMT + depends on the S_IFMT bits of our MODE argument, and MAJOR and + MINOR are ASCII decimal (octal or hex would do as well) + representations of our arguments. Thus the convention is that + CHRDEV and BLKDEV translators are invoked with two non-switch + arguments, giving the major and minor device numbers in %i format. */ + + bp = buf + sizeof (buf); + *--bp = '\0'; + bp = _itoa (minor (*dev), bp, 10, 0); + *--bp = '\0'; + bp = _itoa (major (*dev), bp, 10, 0); + memcpy (bp - len, translator, len); + translator = bp - len; + len = buf + sizeof (buf) - translator; + } + + dir = __file_name_split_at (fd, path, &name); + if (dir == MACH_PORT_NULL) + return -1; + + /* Create a new, unlinked node in the target directory. */ + err = __dir_mkfile (dir, O_WRITE, (mode & ~S_IFMT) & ~_hurd_umask, &node); + + if (! err && translator != NULL) + /* Set the node's translator to make it a device. */ + err = __file_set_translator (node, + FS_TRANS_EXCL | FS_TRANS_SET, + FS_TRANS_EXCL | FS_TRANS_SET, 0, + translator, len, + MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); + + if (! err) + /* Link the node, now a valid device, into the target directory. */ + err = __dir_link (dir, node, name, 1); + + __mach_port_deallocate (__mach_task_self (), dir); + __mach_port_deallocate (__mach_task_self (), node); + + if (err) + return __hurd_fail (err); + return 0; +} diff --git a/libc/sysdeps/mach/hurd/xstat.c b/libc/sysdeps/mach/hurd/xstat.c new file mode 100644 index 000000000..97719b082 --- /dev/null +++ b/libc/sysdeps/mach/hurd/xstat.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1992,93,94,95,96,97,2002 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/stat.h> + +#include "xstatconv.c" + +/* Get file information about FILE in BUF. */ +int +__xstat (int vers, const char *file, struct stat *buf) +{ + struct stat64 buf64; + return __xstat64 (vers, file, &buf64) ?: xstat64_conv (buf, &buf64); +} +hidden_def (__xstat) +weak_alias (__xstat, _xstat) diff --git a/libc/sysdeps/mach/hurd/xstat64.c b/libc/sysdeps/mach/hurd/xstat64.c new file mode 100644 index 000000000..572ae4e59 --- /dev/null +++ b/libc/sysdeps/mach/hurd/xstat64.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2000,02 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 RTLD_STAT64 /* dl-xstat64.c, but we don't want it. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/stat.h> +#include <hurd.h> + +/* Get information about the file descriptor FD in BUF. */ +int +__xstat64 (int vers, const char *file, struct stat64 *buf) +{ + error_t err; + file_t port; + + if (vers != _STAT_VER) + return __hurd_fail (EINVAL); + + port = __file_name_lookup (file, 0, 0); + if (port == MACH_PORT_NULL) + return -1; + err = __io_stat (port, buf); + __mach_port_deallocate (__mach_task_self (), port); + if (err) + return __hurd_fail (err); + return 0; +} +hidden_def (__xstat64) + +#endif diff --git a/libc/sysdeps/mach/hurd/xstatconv.c b/libc/sysdeps/mach/hurd/xstatconv.c new file mode 100644 index 000000000..e28643cd5 --- /dev/null +++ b/libc/sysdeps/mach/hurd/xstatconv.c @@ -0,0 +1,68 @@ +/* Convert between `struct stat' format, and `struct stat64' format. + Copyright (C) 2000,01,02 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/stat.h> + +static inline int +xstat64_conv (struct stat *buf, const struct stat64 *buf64) +{ + if (sizeof *buf == sizeof *buf64 + && sizeof buf->st_ino == sizeof buf64->st_ino + && sizeof buf->st_size == sizeof buf64->st_size + && sizeof buf->st_blocks == sizeof buf64->st_blocks) + { + *buf = *(struct stat *) buf64; + return 0; + } + + buf->st_fstype = buf64->st_fstype; + buf->st_fsid = buf64->st_fsid; + buf->st_ino = buf64->st_ino; + buf->st_gen = buf64->st_gen; + buf->st_rdev = buf64->st_rdev; + buf->st_mode = buf64->st_mode; + buf->st_nlink = buf64->st_nlink; + buf->st_uid = buf64->st_uid; + buf->st_gid = buf64->st_gid; + buf->st_size = buf64->st_size; + buf->st_atime = buf64->st_atime; + buf->st_atime_usec = buf64->st_atime_usec; + buf->st_mtime = buf64->st_mtime; + buf->st_mtime_usec = buf64->st_mtime_usec; + buf->st_ctime = buf64->st_ctime; + buf->st_ctime_usec = buf64->st_ctime_usec; + buf->st_blksize = buf64->st_blksize; + buf->st_blocks = buf64->st_blocks; + buf->st_author = buf64->st_author; + buf->st_flags = buf64->st_flags; + + if ((sizeof buf->st_ino != sizeof buf64->st_ino + && buf->st_ino != buf64->st_ino) + || (sizeof buf->st_size != sizeof buf64->st_size + && buf->st_size != buf64->st_size) + || (sizeof buf->st_blocks != sizeof buf64->st_blocks + && buf->st_blocks != buf64->st_blocks)) + { + __set_errno (EOVERFLOW); + return -1; + } + + return 0; +} diff --git a/libc/sysdeps/mach/i386/machine-lock.h b/libc/sysdeps/mach/i386/machine-lock.h new file mode 100644 index 000000000..7c23fba8c --- /dev/null +++ b/libc/sysdeps/mach/i386/machine-lock.h @@ -0,0 +1,66 @@ +/* Machine-specific definition for spin locks. i386 version. + Copyright (C) 1994, 1997 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 _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0 + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + register int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0)); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (__spin_lock_t *__lock) +{ + register int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1)); + return !__locked; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return *__lock != 0; +} + + +#endif /* machine-lock.h */ diff --git a/libc/sysdeps/mach/i386/machine-sp.h b/libc/sysdeps/mach/i386/machine-sp.h new file mode 100644 index 000000000..536f69021 --- /dev/null +++ b/libc/sysdeps/mach/i386/machine-sp.h @@ -0,0 +1,31 @@ +/* Machine-specific function to return the stack pointer. i386 version. + Copyright (C) 1994,97,2001 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 _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#define __thread_stack_pointer() ({ \ + void *__sp__; \ + __asm__ ("movl %%esp, %0" : "=r" (__sp__)); \ + __sp__; \ +}) + +#endif /* machine-sp.h */ diff --git a/libc/sysdeps/mach/i386/syscall.S b/libc/sysdeps/mach/i386/syscall.S new file mode 100644 index 000000000..ff50e971c --- /dev/null +++ b/libc/sysdeps/mach/i386/syscall.S @@ -0,0 +1,27 @@ +/* Copyright (C) 1993, 1997, 2005 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 <sysdep.h> + +ENTRY (syscall) + popl %ecx /* Pop return address into %ecx. */ + popl %eax /* Pop syscall number into %eax. */ + pushl %ecx /* Push back return address. */ + .byte 0x9a, 0, 0, 0, 0, 7, 0 /* lcall $7, $0 -- gas bug */ + ret +END (syscall) diff --git a/libc/sysdeps/mach/i386/sysdep.h b/libc/sysdeps/mach/i386/sysdep.h new file mode 100644 index 000000000..1f138f475 --- /dev/null +++ b/libc/sysdeps/mach/i386/sysdep.h @@ -0,0 +1,60 @@ +/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 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. */ + +#define LOSE asm volatile ("hlt") + +#define SNARF_ARGS(entry_sp, argc, argv, envp) \ + do \ + { \ + register char **p; \ + argc = (int) *entry_sp; \ + argv = (char **) (entry_sp + 1); \ + p = argv; \ + while (*p++ != NULL) \ + ; \ + if (p >= (char **) argv[0]) \ + --p; \ + envp = p; \ + } while (0) + +#define CALL_WITH_SP(fn, info, sp) \ + do { \ + void **ptr = (void **) sp; \ + *--(__typeof (info) *) ptr = info; \ + ptr[-1] = ptr; \ + --ptr; \ + asm volatile ("movl %0, %%esp; call %1" : : \ + "g" (ptr), "m" (*(long int *) (fn)) : "%esp"); \ + } while (0) + +#define RETURN_TO(sp, pc, retval) \ + asm volatile ("movl %0, %%esp; jmp %*%1 # %2" \ + : : "g" (sp), "r" (pc), "a" (retval)) + + +#define STACK_GROWTH_DOWN + +/* Get the machine-independent Mach definitions. */ +#include <sysdeps/mach/sysdep.h> + + +/* This should be rearranged, but at the moment this file provides + the most useful definitions for assembler syntax details. */ +#undef ENTRY +#undef ALIGN +#include <sysdeps/unix/i386/sysdep.h> diff --git a/libc/sysdeps/mach/i386/thread_state.h b/libc/sysdeps/mach/i386/thread_state.h new file mode 100644 index 000000000..cefea2cfb --- /dev/null +++ b/libc/sysdeps/mach/i386/thread_state.h @@ -0,0 +1,38 @@ +/* Mach thread state definitions for machine-independent code. i386 version. + Copyright (C) 1994, 1997 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 <mach/machine/thread_status.h> + +#define MACHINE_THREAD_STATE_FLAVOR i386_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT + +#define machine_thread_state i386_thread_state + +#define PC eip +#define SP uesp +#define SYSRETURN eax + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct i386_thread_state basic; + struct i386_float_state fpu; + }; + +#include <sysdeps/mach/thread_state.h> diff --git a/libc/sysdeps/mach/mprotect.c b/libc/sysdeps/mach/mprotect.c new file mode 100644 index 000000000..a003cd434 --- /dev/null +++ b/libc/sysdeps/mach/mprotect.c @@ -0,0 +1,51 @@ +/* Copyright (C) 1994, 1996, 1997 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 <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <mach.h> + +/* Change the memory protection of the region starting at ADDR and + extending LEN bytes to PROT. Returns 0 if successful, -1 for errors + (and sets errno). */ + +int +__mprotect (__ptr_t addr, size_t len, int prot) +{ + kern_return_t err; + vm_prot_t vmprot; + + vmprot = VM_PROT_NONE; + if (prot & PROT_READ) + vmprot |= VM_PROT_READ; + if (prot & PROT_WRITE) + vmprot |= VM_PROT_WRITE; + if (prot & PROT_EXEC) + vmprot |= VM_PROT_EXECUTE; + + if (err = __vm_protect (__mach_task_self (), + (vm_address_t) addr, (vm_size_t) len, + 0, vmprot)) + { + errno = err; + return -1; + } + return 0; +} +weak_alias (__mprotect, mprotect) diff --git a/libc/sysdeps/mach/msync.c b/libc/sysdeps/mach/msync.c new file mode 100644 index 000000000..567143f72 --- /dev/null +++ b/libc/sysdeps/mach/msync.c @@ -0,0 +1,57 @@ +/* msync -- Synchronize mapped memory to external storage. Mach version. + Copyright (C) 2002, 2005 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 <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <mach.h> + +/* Some Mach variants have vm_msync and some don't. Those that have it + define the VM_SYNC_* bits when we include <mach/mach_types.h>. */ + +#ifndef VM_SYNC_SYNCHRONOUS +# include <misc/msync.c> +#else + +/* Synchronize the region starting at ADDR and extending LEN bytes with the + file it maps. Filesystem operations on a file being mapped are + unpredictable before this is done. */ + +int +msync (__ptr_t addr, size_t len, int flags) +{ + vm_sync_t sync_flags = 0; + kern_return_t err; + + if (flags & MS_SYNC) + sync_flags |= VM_SYNC_SYNCHRONOUS; + if (flags & MS_ASYNC) + sync_flags |= VM_SYNC_ASYNCHRONOUS; + if (flags & MS_INVALIDATE) + sync_flags |= VM_SYNC_INVALIDATE; + + if (err = __vm_msync (__mach_task_self (), + (vm_address_t) addr, (vm_size_t) len, sync_flags)) + { + errno = err; + return -1; + } + return 0; +} +#endif diff --git a/libc/sysdeps/mach/munmap.c b/libc/sysdeps/mach/munmap.c new file mode 100644 index 000000000..03a9c6070 --- /dev/null +++ b/libc/sysdeps/mach/munmap.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1994, 1995, 1997 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 <sys/types.h> +#include <sys/mman.h> +#include <errno.h> +#include <mach.h> + +/* Deallocate any mapping for the region starting at ADDR and extending LEN + bytes. Returns 0 if successful, -1 for errors (and sets errno). */ + +int +__munmap (__ptr_t addr, size_t len) +{ + kern_return_t err; + if (err = __vm_deallocate (__mach_task_self (), + (vm_address_t) addr, (vm_size_t) len)) + { + errno = err; + return -1; + } + return 0; +} + +weak_alias (__munmap, munmap) diff --git a/libc/sysdeps/mach/nanosleep.c b/libc/sysdeps/mach/nanosleep.c new file mode 100644 index 000000000..e433adb8b --- /dev/null +++ b/libc/sysdeps/mach/nanosleep.c @@ -0,0 +1,54 @@ +/* nanosleep -- sleep for a period specified with a struct timespec + Copyright (C) 2002 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 <mach.h> +#include <sys/time.h> +#include <unistd.h> + +int +__nanosleep (const struct timespec *requested_time, + struct timespec *remaining) +{ + mach_port_t recv; + struct timeval before, after; + const mach_msg_timeout_t ms + = requested_time->tv_sec * 1000 + + (requested_time->tv_nsec + 999999) / 1000000; + + recv = __mach_reply_port (); + + if (remaining && __gettimeofday (&before, NULL) < 0) + return -1; + (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, recv, ms, MACH_PORT_NULL); + __mach_port_destroy (mach_task_self (), recv); + if (remaining && __gettimeofday (&after, NULL) < 0) + return -1; + + if (remaining) + { + timersub (&after, &before, &after); + TIMEVAL_TO_TIMESPEC (&after, remaining); + } + + return 0; +} +libc_hidden_def (__nanosleep) +weak_alias (__nanosleep, nanosleep) diff --git a/libc/sysdeps/mach/pagecopy.h b/libc/sysdeps/mach/pagecopy.h new file mode 100644 index 000000000..1d0c9d135 --- /dev/null +++ b/libc/sysdeps/mach/pagecopy.h @@ -0,0 +1,36 @@ +/* Macros for copying by pages; used in memcpy, memmove. Mach version. + Copyright (C) 1995, 1997 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 <mach.h> + +/* 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_SIZE __vm_page_size +#define PAGE_COPY_FWD(dstp, srcp, nbytes_left, nbytes) \ + ((nbytes_left) = ((nbytes) - \ + (__vm_copy (__mach_task_self (), \ + (vm_address_t) srcp, trunc_page (nbytes), \ + (vm_address_t) dstp) == KERN_SUCCESS \ + ? trunc_page (nbytes) \ + : 0))) + +/* Get the generic macro. */ +#include <sysdeps/generic/pagecopy.h> diff --git a/libc/sysdeps/mach/powerpc/machine-lock.h b/libc/sysdeps/mach/powerpc/machine-lock.h new file mode 100644 index 000000000..cba6b0a6e --- /dev/null +++ b/libc/sysdeps/mach/powerpc/machine-lock.h @@ -0,0 +1,78 @@ +/* Machine-specific definition for spin locks. PowerPC version. + Copyright (C) 1994,97,2002 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 _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile long int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0L + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + long int __locked; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__locked) : "r" (__lock), "r" (0) : "cr0"); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %2,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock), "r" (1) : "cr0"); + return !__rtn; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + long int __rtn; + __asm__ __volatile__ ("\ +0: lwarx %0,0,%1\n\ + stwcx. %0,0,%1\n\ + bne- 0b\n\ +" : "=&r" (__rtn) : "r" (__lock) : "cr0"); + return __rtn; +} + + +#endif /* machine-lock.h */ diff --git a/libc/sysdeps/mach/powerpc/machine-sp.h b/libc/sysdeps/mach/powerpc/machine-sp.h new file mode 100644 index 000000000..cf5341cb9 --- /dev/null +++ b/libc/sysdeps/mach/powerpc/machine-sp.h @@ -0,0 +1,42 @@ +/* Machine-specific function to return the stack pointer. PowerPC version. + Copyright (C) 2001 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#ifndef _EXTERN_INLINE +/* Make sure this function is included in hurd/threadvar-inlines.c. */ +# ifdef _HURD_THREADVAR_H_EXTERN_INLINE +# define _EXTERN_INLINE _HURD_THREADVAR_H_EXTERN_INLINE +# else +# define _EXTERN_INLINE extern __inline +# endif +#endif + +_EXTERN_INLINE void * +__thread_stack_pointer (void) +{ + register void *__sp__; + __asm__ ("mr %0, 1" : "=r" (__sp__)); + return __sp__; +} + +#endif /* machine-sp.h */ diff --git a/libc/sysdeps/mach/powerpc/syscall.S b/libc/sysdeps/mach/powerpc/syscall.S new file mode 100644 index 000000000..6482f0d72 --- /dev/null +++ b/libc/sysdeps/mach/powerpc/syscall.S @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 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 <sysdep.h> + +ENTRY (syscall) + mr r0,r3 + mr r3,r4 + mr r4,r5 + mr r5,r6 + mr r6,r7 + mr r7,r8 + sc + blr +END (syscall) diff --git a/libc/sysdeps/mach/powerpc/sysdep.h b/libc/sysdeps/mach/powerpc/sysdep.h new file mode 100644 index 000000000..acfacc473 --- /dev/null +++ b/libc/sysdeps/mach/powerpc/sysdep.h @@ -0,0 +1,51 @@ +/* system call details for Mach on PowerPC + Copyright (C) 2001,02 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _MACH_POWERPC_SYSDEP_H +#define _MACH_POWERPC_SYSDEP_H + +#define START_ARGS char **sparg +#define SNARF_ARGS(argc, argv, envp) \ + do { \ + argv = &sparg[1]; \ + argc = *(int *)sparg; \ + envp = &argv[argc + 1]; \ + } while (0) + +#define CALL_WITH_SP(fn, sp) \ + do { \ + register long __sp = (long) sp, __fn = (long) fn; \ + asm volatile ("mr 1, %0; mtlr %1; blr" \ + : : "r" (__sp), "r" (__fn)); \ + } while (0) + +#define STACK_GROWTH_DOWN + +#define RETURN_TO(sp, pc, retval) \ + asm volatile ("mr 1, %0; mtctr %1; mr 3, %2; bctr" \ + : : "r" (sp), "r" (pc), "r" (retval)) + +/* Get the machine-independent Mach definitions. */ +#define _MACH_MACHINE_ASM_H 1 /* Kludge to avoid bad Darwin header file. */ +#include <sysdeps/mach/sysdep.h> + +#undef ENTRY +#include <sysdeps/unix/powerpc/sysdep.h> + +#endif /* _MACH_POWERPC_SYSDEP_H */ diff --git a/libc/sysdeps/mach/powerpc/thread_state.h b/libc/sysdeps/mach/powerpc/thread_state.h new file mode 100644 index 000000000..e6ca1042f --- /dev/null +++ b/libc/sysdeps/mach/powerpc/thread_state.h @@ -0,0 +1,39 @@ +/* Mach thread state definitions for machine-independent code. PowerPC version + Copyright (C) 2001 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <mach/machine/thread_status.h> + +#define MACHINE_THREAD_STATE_FLAVOR PPC_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT + +#define machine_thread_state ppc_thread_state + +#define PC srr0 +#define SP r1 +#define SYSRETURN r3 + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct ppc_thread_state basic; + struct ppc_exception_state exc; + struct ppc_float_state fpu; + }; + +#include <sysdeps/mach/thread_state.h> diff --git a/libc/sysdeps/mach/readonly-area.c b/libc/sysdeps/mach/readonly-area.c new file mode 100644 index 000000000..afee7a4bd --- /dev/null +++ b/libc/sysdeps/mach/readonly-area.c @@ -0,0 +1,57 @@ +/* Test if a memory region is wholly unwritable. Mach version. + Copyright (C) 2004 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 <stdlib.h> +#include <stdint.h> +#include <mach.h> + +/* Return 1 if the whole area PTR .. PTR+SIZE is not writable. + Return -1 if it is writable. */ + +int +__readonly_area (const char *ptr, size_t size) +{ + vm_address_t region_address = (uintptr_t) ptr; + vm_size_t region_length = size; + vm_prot_t protection; + vm_prot_t max_protection; + vm_inherit_t inheritance; + boolean_t is_shared; + mach_port_t object_name; + vm_offset_t offset; + + while (__vm_region (__mach_task_self (), + ®ion_address, ®ion_length, + &protection, &max_protection, &inheritance, &is_shared, + &object_name, &offset) == KERN_SUCCESS + && region_address <= (uintptr_t) ptr) + { + region_address += region_length; + if (region_address < (uintptr_t) ptr) + continue; + + if (protection & VM_PROT_WRITE) + return -1; + + if (region_address - (uintptr_t) ptr >= size) + break; + } + + return 1; +} diff --git a/libc/sysdeps/mach/sched_yield.c b/libc/sysdeps/mach/sched_yield.c new file mode 100644 index 000000000..0c35ef098 --- /dev/null +++ b/libc/sysdeps/mach/sched_yield.c @@ -0,0 +1,32 @@ +/* sched_yield -- yield the processor. Mach version. + Copyright (C) 2000, 2006 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 <sched.h> +#include <mach.h> + +/* Yield the processor. */ +int +__sched_yield (void) +{ + (void) __swtch (); + return 0; +} +libc_hidden_def (__sched_yield) +weak_alias (__sched_yield, sched_yield) diff --git a/libc/sysdeps/mach/sleep.c b/libc/sysdeps/mach/sleep.c new file mode 100644 index 000000000..93e70f662 --- /dev/null +++ b/libc/sysdeps/mach/sleep.c @@ -0,0 +1,45 @@ +/* Copyright (C) 1992, 1993, 1994, 1997 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 <signal.h> +#include <time.h> +#include <unistd.h> +#include <mach.h> + +/* Make the process sleep for SECONDS seconds, or until a signal arrives + and is not ignored. The function returns the number of seconds less + than SECONDS which it actually slept (zero if it slept the full time). + There is no return value to indicate error, but if `sleep' returns + SECONDS, it probably didn't work. */ +unsigned int +__sleep (unsigned int seconds) +{ + time_t before, after; + mach_port_t recv; + + recv = __mach_reply_port (); + + before = time ((time_t *) NULL); + (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, recv, seconds * 1000, MACH_PORT_NULL); + after = time ((time_t *) NULL); + __mach_port_destroy (__mach_task_self (), recv); + + return seconds - (after - before); +} +weak_alias (__sleep, sleep) diff --git a/libc/sysdeps/mach/start.c b/libc/sysdeps/mach/start.c new file mode 100644 index 000000000..92d2a8273 --- /dev/null +++ b/libc/sysdeps/mach/start.c @@ -0,0 +1,104 @@ +/* Copyright (C) 1992, 1993, 1994, 1995, 1997 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 <stddef.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sysdep.h> + +#ifndef __GNUC__ + #error This file uses GNU C extensions; you must compile with GCC. +#endif + +/* The first piece of initialized data. */ +int __data_start = 0; + +#ifndef _HURD_THREADVAR_H +volatile int errno; +#endif + +extern void __mach_init (void); +extern void __libc_init (int argc, char **argv, char **envp); +extern int main (int argc, char **argv, char **envp); + +/* These are uninitialized common definitions so they will be zero + by default. If the user links in C threads, that will provide initialized + definitions that override these. */ +void *(*_cthread_init_routine) (void); /* Returns new SP to use. */ +void (*_cthread_exit_routine) (int status); + + +/* These are for communication from _start to start1, + where we cannot use the stack for anything. */ +static int start_argc; +static char **start_argv; + +/* _start calls this on the new stack. */ +static volatile void +start1 (void) +{ + __libc_init (start_argc, start_argv, __environ); + + (_cthread_exit_routine != NULL ? *_cthread_exit_routine : exit) + (main (start_argc, start_argv, __environ)); + + /* Should never get here. */ + LOSE; +} + +#ifndef START_ARGS +#define START_ARGS void +#endif +#ifdef START_MACHDEP +START_MACHDEP +#define _start _start0 +#endif + +void +_start (START_ARGS) +{ + SNARF_ARGS (start_argc, start_argv, __environ); + + __mach_init (); + + if (_cthread_init_routine != NULL) + CALL_WITH_SP (start1, (*_cthread_init_routine) ()); + else + start1 (); + + /* Should never get here. */ + LOSE; +} diff --git a/libc/sysdeps/mach/sys/reboot.h b/libc/sysdeps/mach/sys/reboot.h new file mode 100644 index 000000000..fc7308929 --- /dev/null +++ b/libc/sysdeps/mach/sys/reboot.h @@ -0,0 +1,171 @@ +/* + * Mach Operating System + * Copyright (C) 1993,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * (pre-GNU) HISTORY + * + * Revision 2.8 93/03/11 13:46:40 danner + * u_long -> u_int. + * [93/03/09 danner] + * + * Revision 2.7 92/05/21 17:25:11 jfriedl + * Appended 'U' to constants that would otherwise be signed. + * [92/05/16 jfriedl] + * + * Revision 2.6 91/06/19 11:59:44 rvb + * Second byte of boothowto is flags for "startup" program. + * [91/06/18 rvb] + * Add ifndef __ASSEMBLER__ so that vax_init.s can include it. + * [91/06/11 rvb] + * + * Revision 2.5 91/05/14 17:40:11 mrt + * Correcting copyright + * + * Revision 2.4 91/02/05 17:56:48 mrt + * Changed to new Mach copyright + * [91/02/01 17:49:12 mrt] + * + * Revision 2.3 90/08/27 22:12:56 dbg + * Added definitions used by Mach Kernel: RB_DEBUGGER, RB_UNIPROC, + * RB_NOBOOTRC, RB_ALTBOOT. Moved RB_KDB to 0x04 (Mach value). + * Removed RB_RDONLY, RB_DUMP, RB_NOSYNC. + * [90/08/14 dbg] + * + */ + +/* + Copyright (C) 1982, 1986, 1988 Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE.*/ + +/* + * @(#)reboot.h 7.5 (Berkeley) 6/27/88 + */ + +#ifndef _SYS_REBOOT_H_ +#define _SYS_REBOOT_H_ + +#include <features.h> + +/* + * Arguments to reboot system call. + * These are converted to switches, and passed to startup program, + * and on to init. + */ +#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */ + +#define RB_ASKNAME 0x01 /* -a: ask for file name to reboot from */ +#define RB_SINGLE 0x02 /* -s: reboot to single user only */ +#define RB_KDB 0x04 /* -d: kernel debugger symbols loaded */ +#define RB_HALT 0x08 /* -h: enter KDB at bootup */ + /* for host_reboot(): don't reboot, + just halt */ +#define RB_INITNAME 0x10 /* -i: name given for /etc/init (unused) */ +#define RB_DFLTROOT 0x20 /* use compiled-in rootdev */ +#define RB_NOBOOTRC 0x20 /* -b: don't run /etc/rc.boot */ +#define RB_ALTBOOT 0x40 /* use /boot.old vs /boot */ +#define RB_UNIPROC 0x80 /* -u: start only one processor */ + +#define RB_SHIFT 8 /* second byte is for ux */ + +#define RB_DEBUGGER 0x1000 /* for host_reboot(): enter kernel + debugger from user level */ + +/* + * Constants for converting boot-style device number to type, + * adaptor (uba, mba, etc), unit number and partition number. + * Type (== major device number) is in the low byte + * for backward compatibility. Except for that of the "magic + * number", each mask applies to the shifted value. + * Format: + * (4) (4) (4) (4) (8) (8) + * -------------------------------- + * |MA | AD| CT| UN| PART | TYPE | + * -------------------------------- + */ +#define B_ADAPTORSHIFT 24 +#define B_ADAPTORMASK 0x0f +#define B_ADAPTOR(val) (((val) >> B_ADAPTORSHIFT) & B_ADAPTORMASK) +#define B_CONTROLLERSHIFT 20 +#define B_CONTROLLERMASK 0xf +#define B_CONTROLLER(val) (((val)>>B_CONTROLLERSHIFT) & B_CONTROLLERMASK) +#define B_UNITSHIFT 16 +#define B_UNITMASK 0xf +#define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK) +#define B_PARTITIONSHIFT 8 +#define B_PARTITIONMASK 0xff +#define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK) +#define B_TYPESHIFT 0 +#define B_TYPEMASK 0xff +#define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK) + +#define B_MAGICMASK ((u_int)0xf0000000U) +#define B_DEVMAGIC ((u_int)0xa0000000U) + +#define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \ + (((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \ + ((controller) << B_CONTROLLERSHIFT) | ((unit) << B_UNITSHIFT) | \ + ((partition) << B_PARTITIONSHIFT) | B_DEVMAGIC) + + +#ifdef KERNEL +#ifndef __ASSEMBLER__ +extern int boothowto; +#endif /* __ASSEMBLER__ */ +#endif + +__BEGIN_DECLS + +/* Reboot or halt the system. */ +extern int reboot (int __howto) __THROW; + +__END_DECLS + + +#endif /* _SYS_REBOOT_H_ */ diff --git a/libc/sysdeps/mach/sys/syscall.h b/libc/sysdeps/mach/sys/syscall.h new file mode 100644 index 000000000..6e4ed4d64 --- /dev/null +++ b/libc/sysdeps/mach/sys/syscall.h @@ -0,0 +1 @@ +/* The Mach syscalls are in <mach/syscall_sw.h>. */ diff --git a/libc/sysdeps/mach/sysdep.h b/libc/sysdeps/mach/sysdep.h new file mode 100644 index 000000000..825198c79 --- /dev/null +++ b/libc/sysdeps/mach/sysdep.h @@ -0,0 +1,93 @@ +/* Copyright (C) 1994, 1995, 1997 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. */ + +#ifdef __ASSEMBLER__ + +/* Get the Mach definitions of ENTRY and kernel_trap. */ +#include <mach/machine/syscall_sw.h> + +/* The Mach definitions assume underscores should be prepended to + symbol names. Redefine them to do so only when appropriate. */ +#undef EXT +#undef LEXT +#define EXT(x) C_SYMBOL_NAME(x) +#define LEXT(x) C_SYMBOL_NAME(x##:) + +#ifdef HAVE_ELF +/* For ELF we need to add the `.type' directive to make shared libraries + work right. */ +#undef ENTRY +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE name; \ + .align ALIGN; \ + .type name,@function; \ + name: +#endif + +#endif + +/* This is invoked by things run when there is random lossage, before they + try to do anything else. Just to be safe, deallocate the reply port so + bogons arriving on it don't foul up future RPCs. */ + +#ifndef __ASSEMBLER__ +#define FATAL_PREPARE_INCLUDE <mach/mig_support.h> +#define FATAL_PREPARE __mig_dealloc_reply_port (MACH_PORT_NULL) +#endif + +/* sysdeps/mach/MACHINE/sysdep.h should define the following macros. */ + +/* Produce a text assembler label for the C global symbol NAME. */ +#ifndef ENTRY +#define ENTRY(name) .error ENTRY not defined by sysdeps/mach/MACHINE/sysdep.h +/* This is not used on all machines. */ +#endif + +/* Set variables ARGC, ARGV, and ENVP for the arguments + left on the stack by the microkernel. */ +#ifndef SNARF_ARGS +#define SNARF_ARGS(argc, argv, envp) +#error SNARF_ARGS not defined by sysdeps/mach/MACHINE/sysdep.h +#endif + +/* Call the C function FN with no arguments, + on a stack starting at SP (as returned by *_cthread_init_routine). + You don't need to deal with FN returning; it shouldn't. */ +#ifndef CALL_WITH_SP +#define CALL_WITH_SP(fn, sp) +#error CALL_WITH_SP not defined by sysdeps/mach/MACHINE/sysdep.h +#endif + +/* LOSE can be defined as the `halt' instruction or something + similar which will cause the process to die in a characteristic + way suggesting a bug. */ +#ifndef LOSE +#define LOSE ({ volatile int zero = 0; zero / zero; }) +#endif + +/* One of these should be defined to specify the stack direction. */ +#if !defined (STACK_GROWTH_UP) && !defined (STACK_GROWTH_DOWN) +#error stack direction unspecified +#endif + +/* Used by some assembly code. */ +#ifdef NO_UNDERSCORES +#define C_SYMBOL_NAME(name) name +#else +#define C_SYMBOL_NAME(name) _##name +#endif diff --git a/libc/sysdeps/mach/thread_state.h b/libc/sysdeps/mach/thread_state.h new file mode 100644 index 000000000..38effdf5e --- /dev/null +++ b/libc/sysdeps/mach/thread_state.h @@ -0,0 +1,87 @@ +/* Generic definitions for dealing with Mach thread states. + Copyright (C) 1994, 1996 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. */ + + +/* Everything else is called `thread_state', but CMU's header file is + called `thread_status'. Oh boy. */ +#include <mach/thread_status.h> + +/* The machine-dependent thread_state.h file can either define these + macros, or just define PC and SP to the register names. */ + +#ifndef MACHINE_THREAD_STATE_SET_PC +#define MACHINE_THREAD_STATE_SET_PC(ts, pc) \ + ((ts)->PC = (unsigned long int) (pc)) +#endif +#ifndef MACHINE_THREAD_STATE_SET_SP +#ifdef STACK_GROWTH_UP +#define MACHINE_THREAD_STATE_SET_SP(ts, stack, size) \ + ((ts)->SP = (unsigned long int) (stack)) +#else +#define MACHINE_THREAD_STATE_SET_SP(ts, stack, size) \ + ((ts)->SP = (unsigned long int) (stack) + (size)) +#endif +#endif + +/* These functions are of use in machine-dependent signal trampoline + implementations. */ + +#include <string.h> /* size_t, memcpy */ +#include <mach/mach_interface.h> /* __thread_get_state */ + +static inline int +machine_get_state (thread_t thread, struct machine_thread_all_state *state, + int flavor, void *stateptr, void *scpptr, size_t size) +{ + if (state->set & (1 << flavor)) + { + /* Copy the saved state. */ + memcpy (scpptr, stateptr, size); + return 1; + } + else + { + /* No one asked about this flavor of state before; fetch the state + directly from the kernel into the sigcontext. */ + mach_msg_type_number_t got = (size / sizeof (int)); + return (! __thread_get_state (thread, flavor, scpptr, &got) + && got == (size / sizeof (int))); + } +} + +static inline int +machine_get_basic_state (thread_t thread, + struct machine_thread_all_state *state) +{ + mach_msg_type_number_t count; + + if (state->set & (1 << MACHINE_THREAD_STATE_FLAVOR)) + return 1; + + count = MACHINE_THREAD_STATE_COUNT; + if (__thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state->basic, + &count) != KERN_SUCCESS || + count != MACHINE_THREAD_STATE_COUNT) + /* What kind of thread?? */ + return 0; /* XXX */ + + state->set |= 1 << MACHINE_THREAD_STATE_FLAVOR; + return 1; +} diff --git a/libc/sysdeps/mach/usleep.c b/libc/sysdeps/mach/usleep.c new file mode 100644 index 000000000..ecbd2ed41 --- /dev/null +++ b/libc/sysdeps/mach/usleep.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1992, 93, 94, 97, 98, 99, 2001 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 <mach.h> +#include <sys/time.h> +#include <unistd.h> + +/* Sleep USECONDS microseconds, or until a previously set timer goes off. */ +int +usleep (useconds_t useconds) +{ + mach_port_t recv; + struct timeval before, after; + + recv = __mach_reply_port (); + + if (__gettimeofday (&before, NULL) < 0) + return -1; + (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, recv, (useconds + 999) / 1000, MACH_PORT_NULL); + __mach_port_destroy (mach_task_self (), recv); + if (__gettimeofday (&after, NULL) < 0) + return -1; + + return 0; +} diff --git a/libc/sysdeps/mach/xpg-strerror.c b/libc/sysdeps/mach/xpg-strerror.c new file mode 100644 index 000000000..8d0b31e60 --- /dev/null +++ b/libc/sysdeps/mach/xpg-strerror.c @@ -0,0 +1,83 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2002, 2004 + 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 <libintl.h> +#include <stdio.h> +#include <string.h> +#include <mach/error.h> +#include <errorlib.h> +#include <sys/param.h> +#include <stdio-common/_itoa.h> + +/* It is critical here that we always use the `dcgettext' function for + the message translation. Since <libintl.h> only defines the macro + `dgettext' to use `dcgettext' for optimizing programs this is not + always guaranteed. */ +#ifndef dgettext +# include <locale.h> /* We need LC_MESSAGES. */ +# define dgettext(domainname, msgid) dcgettext (domainname, msgid, LC_MESSAGES) +#endif + +/* Fill buf with a string describing the errno code in ERRNUM. */ +int +__xpg_strerror_r (int errnum, char *buf, size_t buflen) +{ + int system; + int sub; + int code; + const struct error_system *es; + extern void __mach_error_map_compat (int *); + const char *estr; + + __mach_error_map_compat (&errnum); + + system = err_get_system (errnum); + sub = err_get_sub (errnum); + code = err_get_code (errnum); + + if (system > err_max_system || ! __mach_error_systems[system].bad_sub) + { + __set_errno (EINVAL); + return -1; + } + + es = &__mach_error_systems[system]; + + if (sub >= es->max_sub) + estr = (const char *) es->bad_sub; + else if (code >= es->subsystem[sub].max_code) + { + __set_errno (EINVAL); + return -1; + } + else + estr = (const char *) _(es->subsystem[sub].codes[code]); + + size_t estrlen = strlen (estr) + 1; + + if (buflen < estrlen) + { + __set_errno (ERANGE); + return -1; + } + + memcpy (buf, estr, estrlen); + return 0; +} |