diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r-- | sysdeps/unix/sysv/linux/Dist | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/fcntlbits.h | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/fcntlbits.h | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/net/if_ppp.h | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/clone.S | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c | 237 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/kernel_termios.h | 25 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/socket.S | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/statbuf.h | 79 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/syscall.S | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/sysdep.h | 12 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/termbits.h | 82 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/readv.c | 71 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/syscalls.list | 5 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/writev.c | 68 |
15 files changed, 512 insertions, 84 deletions
diff --git a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist index 7b94300c6a..d4b6bac217 100644 --- a/sysdeps/unix/sysv/linux/Dist +++ b/sysdeps/unix/sysv/linux/Dist @@ -21,6 +21,7 @@ netinet/igmp.h netinet/in_systm.h netinet/ip_fw.h netinet/ip_icmp.h +netinet/tcp.h netinet/udp.h netipx/ipx.h nfs/nfs.h diff --git a/sysdeps/unix/sysv/linux/alpha/fcntlbits.h b/sysdeps/unix/sysv/linux/alpha/fcntlbits.h index faf198393f..6e1c843ccb 100644 --- a/sysdeps/unix/sysv/linux/alpha/fcntlbits.h +++ b/sysdeps/unix/sysv/linux/alpha/fcntlbits.h @@ -27,7 +27,6 @@ #ifdef __USE_GNU #define O_READ O_RDONLY /* Open for reading. */ #define O_WRITE O_WRONLY /* Open for writing. */ -#define O_NORW 0 /* Open without R/W access. */ #endif /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ diff --git a/sysdeps/unix/sysv/linux/fcntlbits.h b/sysdeps/unix/sysv/linux/fcntlbits.h index fdc67ce4eb..f6ba880459 100644 --- a/sysdeps/unix/sysv/linux/fcntlbits.h +++ b/sysdeps/unix/sysv/linux/fcntlbits.h @@ -27,7 +27,6 @@ #ifdef __USE_GNU #define O_READ O_RDONLY /* Open for reading. */ #define O_WRITE O_WRONLY /* Open for writing. */ -#define O_NORW 0 /* Open without R/W access. */ #endif /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ diff --git a/sysdeps/unix/sysv/linux/net/if_ppp.h b/sysdeps/unix/sysv/linux/net/if_ppp.h index 567dccebe3..0f2a979cd6 100644 --- a/sysdeps/unix/sysv/linux/net/if_ppp.h +++ b/sysdeps/unix/sysv/linux/net/if_ppp.h @@ -51,7 +51,7 @@ __BEGIN_DECLS #define PPP_MTU 1500 /* Default MTU (size of Info field) */ #define PPP_MAXMRU 65000 /* Largest MRU we allow */ -#define PPP_VERSION "2.3.0" +#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 */ diff --git a/sysdeps/unix/sysv/linux/powerpc/clone.S b/sysdeps/unix/sysv/linux/powerpc/clone.S index e5fa16d8c5..0afd0717f4 100644 --- a/sysdeps/unix/sysv/linux/powerpc/clone.S +++ b/sysdeps/unix/sysv/linux/powerpc/clone.S @@ -71,4 +71,8 @@ child: badargs: li 3,-EINVAL error: +#ifdef PIC + b __syscall_error@plt +#else b __syscall_error +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c new file mode 100644 index 0000000000..eb732d6fb1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c @@ -0,0 +1,237 @@ +/* Operating system support for run-time dynamic linker. Linux/PPC version. + Copyright (C) 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 Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <elf.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <link.h> +#include <unistd.h> +#include <stdarg.h> +#include <string.h> + + +extern int _dl_argc; +extern char **_dl_argv; +extern char **_environ; +extern size_t _dl_pagesize; +extern void _end; +extern void _start (void); + +int __libc_enable_secure; +int __libc_multiple_libcs; /* Defining this here avoids the inclusion + of init-first. */ + +ElfW(Addr) +_dl_sysdep_start (void **start_argptr, + void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum, + ElfW(Addr) *user_entry)) +{ + const ElfW(Phdr) *phdr = NULL; + ElfW(Word) phnum = 0; + ElfW(Addr) user_entry; + ElfW(auxv_t) *av; + uid_t uid = 0; + uid_t euid = 0; + gid_t gid = 0; + gid_t egid = 0; + unsigned int seen; + + user_entry = (ElfW(Addr)) &_start; + _dl_argc = *(long *) start_argptr; + _dl_argv = (char **) start_argptr + 1; + _environ = &_dl_argv[_dl_argc + 1]; + start_argptr = (void **) _environ; + while (*start_argptr) + ++start_argptr; + ++start_argptr; + + if (*start_argptr == 0 && + ((unsigned)(char *)start_argptr & 0xF) != 0) + { + unsigned test_sap = (int)(char *)start_argptr; + test_sap = test_sap + 0xF & ~0xF; + if (*(long *)(char *)test_sap == AT_PHDR) + start_argptr = (void **)(char *)test_sap; + } + + seen = 0; +#define M(type) (1 << (type)) + + for (av = (void *) start_argptr; + av->a_type != AT_NULL; + seen |= M ((++av)->a_type)) + switch (av->a_type) + { + case AT_PHDR: + phdr = av->a_un.a_ptr; + break; + case AT_PHNUM: + phnum = av->a_un.a_val; + break; + case AT_PAGESZ: + _dl_pagesize = av->a_un.a_val; + break; + case AT_ENTRY: + user_entry = av->a_un.a_val; + break; + case AT_UID: + uid = av->a_un.a_val; + break; + case AT_GID: + gid = av->a_un.a_val; + break; + case AT_EUID: + euid = av->a_un.a_val; + break; + case AT_EGID: + egid = av->a_un.a_val; + break; + } + + /* Linux doesn't provide us with any of these values on the stack + when the dynamic linker is run directly as a program. */ + +#define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid () + SEE (UID, uid); + SEE (GID, gid); + SEE (EUID, euid); + SEE (EGID, egid); + + + __libc_enable_secure = uid != euid || gid != egid; + + __brk (0); /* Initialize the break. */ + + if (__sbrk (0) == &_end) + { + /* The dynamic linker was run as a program, and so the initial break + starts just after our bss, at &_end. The malloc in dl-minimal.c + will consume the rest of this page, so tell the kernel to move the + break up that far. When the user program examines its break, it + will see this new value and not clobber our data. */ + size_t pg = __getpagesize (); + + __sbrk (pg - ((&_end - (void *) 0) & pg)); + __sbrk (pg - ((&_end - (void *) 0) & (pg - 1))); + } + + (*dl_main) (phdr, phnum, &user_entry); + return user_entry; +} + +void +_dl_sysdep_start_cleanup (void) +{ +} + +#ifndef MAP_ANON +/* This is only needed if the system doesn't support MAP_ANON. */ + +int +_dl_sysdep_open_zero_fill (void) +{ + return __open ("/dev/zero", O_RDONLY); +} +#endif + +/* Read the whole contents of FILE into new mmap'd space with given + protections. *SIZEP gets the size of the file. */ + +void * +_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) +{ + void *result; + struct stat st; + int fd = __open (file, O_RDONLY); + if (fd < 0) + return NULL; + if (__fstat (fd, &st) < 0) + result = NULL; + else + { + /* Map a copy of the file contents. */ + result = __mmap (0, st.st_size, prot, +#ifdef MAP_COPY + MAP_COPY +#else + MAP_PRIVATE +#endif +#ifdef MAP_FILE + | MAP_FILE +#endif + , fd, 0); + if (result == (void *) -1) + result = NULL; + else + *sizep = st.st_size; + } + __close (fd); + return result; +} + +void +_dl_sysdep_fatal (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + do + { + size_t len = strlen (msg); + __write (STDERR_FILENO, msg, len); + msg = va_arg (ap, const char *); + } while (msg); + va_end (ap); + + _exit (127); +} + + +void +_dl_sysdep_error (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + do + { + size_t len = strlen (msg); + __write (STDERR_FILENO, msg, len); + msg = va_arg (ap, const char *); + } while (msg); + va_end (ap); +} + + +void +_dl_sysdep_message (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + do + { + size_t len = strlen (msg); + __write (STDOUT_FILENO, msg, len); + msg = va_arg (ap, const char *); + } while (msg); + va_end (ap); +} diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h new file mode 100644 index 0000000000..acf62a42ca --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h @@ -0,0 +1,25 @@ +#ifndef _SYS_KERNEL_TERMIOS_H +#define _SYS_KERNEL_TERMIOS_H 1 +/* The following corresponds to the values from the Linux 2.0.28 kernel. */ + +/* We need the definition of tcflag_t, cc_t, and speed_t. */ +#include <termbits.h> + +#define __KERNEL_NCCS 19 + +struct __kernel_termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + int c_ispeed; /* input speed */ + int c_ospeed; /* output speed */ + }; + +#define _HAVE_C_ISPEED 1 +#define _HAVE_C_OSPEED 1 + +#endif /* sys/kernel_termios.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/socket.S b/sysdeps/unix/sysv/linux/powerpc/socket.S index 32bb8f64cd..12417faac6 100644 --- a/sysdeps/unix/sysv/linux/powerpc/socket.S +++ b/sysdeps/unix/sysv/linux/powerpc/socket.S @@ -76,7 +76,11 @@ ENTRY(P(__,socket)) DO_CALL(SYS_ify(socketcall)) addi 1,1,48 bnslr +#ifdef PIC + b __syscall_error@plt +#else b __syscall_error +#endif PSEUDO_END (P(__,socket)) diff --git a/sysdeps/unix/sysv/linux/powerpc/statbuf.h b/sysdeps/unix/sysv/linux/powerpc/statbuf.h new file mode 100644 index 0000000000..5be5736931 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/statbuf.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1992, 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 Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 _STATBUF_H +#define _STATBUF_H 1 + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + unsigned int st_dev; /* Device. */ + unsigned int st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned short int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group.*/ + unsigned int st_rdev; /* Device number, if device. */ + long int st_size; /* Size of file, in bytes. */ + unsigned long int st_blksize; /* Optimal block size for I/O. */ +#define _STATBUF_ST_BLKSIZE /* Tell code we have this member. */ + + unsigned long int st_blocks; /* Number of 512-byte blocks allocated. */ + unsigned long int st_atime; /* Time of last access. */ + unsigned long int __unused1; + unsigned long int st_mtime; /* Time of last modification. */ + unsigned long int __unused2; + unsigned long int st_ctime; /* Time of last status change. */ + unsigned long int __unused3; + unsigned long int __unused4; + unsigned long int __unused5; + }; + +/* 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_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* 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 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#endif /* statbuf.h */ diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S index 9b3f66682e..441dd5d433 100644 --- a/sysdeps/unix/sysv/linux/powerpc/syscall.S +++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S @@ -28,5 +28,9 @@ ENTRY (syscall) mr 7,8 sc bnslr +#ifdef PIC + b __syscall_error@plt +#else b __syscall_error +#endif PSEUDO_END (syscall) diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h index c08e3d8060..d6d33bf7af 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h @@ -41,13 +41,21 @@ li 0,syscall; \ sc +#ifdef PIC +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); \ + bnslr; \ + b __syscall_error@plt +#else #define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (SYS_ify (syscall_name)); \ - bnslr; \ + bnslr; \ b __syscall_error - +#endif #define ret /* Nothing (should be 'blr', but never reached). */ #endif /* ASSEMBLER */ diff --git a/sysdeps/unix/sysv/linux/powerpc/termbits.h b/sysdeps/unix/sysv/linux/powerpc/termbits.h index d1b0a3e3cb..4c6073bfc2 100644 --- a/sysdeps/unix/sysv/linux/powerpc/termbits.h +++ b/sysdeps/unix/sysv/linux/powerpc/termbits.h @@ -17,9 +17,7 @@ Boston, MA 02111-1307, USA. */ #ifndef _TERMBITS_H -#define _TERMBITS_H - -#include <linux/posix_types.h> +#define _TERMBITS_H 1 typedef unsigned char cc_t; typedef unsigned int speed_t; @@ -31,14 +29,14 @@ typedef unsigned int tcflag_t; * concerning namespace pollution. */ -#define NCCS 19 +#define NCCS 32 struct termios { tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ - cc_t c_cc[NCCS]; /* control characters */ cc_t c_line; /* line discipline (== c_cc[19]) */ + cc_t c_cc[NCCS]; /* control characters */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */ }; @@ -219,80 +217,6 @@ struct ltchars { char t_lnextc; }; -#define FIOCLEX _IO('f', 1) -#define FIONCLEX _IO('f', 2) -#define FIOASYNC _IOW('f', 125, int) -#define FIONBIO _IOW('f', 126, int) -#define FIONREAD _IOR('f', 127, int) -#define TIOCINQ FIONREAD - -#define TIOCGETP _IOR('t', 8, struct sgttyb) -#define TIOCSETP _IOW('t', 9, struct sgttyb) -#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ - -#define TIOCSETC _IOW('t', 17, struct tchars) -#define TIOCGETC _IOR('t', 18, struct tchars) -#define TCGETS _IOR('t', 19, struct termios) -#define TCSETS _IOW('t', 20, struct termios) -#define TCSETSW _IOW('t', 21, struct termios) -#define TCSETSF _IOW('t', 22, struct termios) - -#define TCGETA _IOR('t', 23, struct termio) -#define TCSETA _IOW('t', 24, struct termio) -#define TCSETAW _IOW('t', 25, struct termio) -#define TCSETAF _IOW('t', 28, struct termio) - -#define TCSBRK _IO('t', 29) -#define TCXONC _IO('t', 30) -#define TCFLSH _IO('t', 31) - -#define TIOCSWINSZ _IOW('t', 103, struct winsize) -#define TIOCGWINSZ _IOR('t', 104, struct winsize) -#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ -#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ -#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ - -#define TIOCGLTC _IOR('t', 116, struct ltchars) -#define TIOCSLTC _IOW('t', 117, struct ltchars) -#define TIOCSPGRP _IOW('t', 118, int) -#define TIOCGPGRP _IOR('t', 119, int) - -#define TIOCEXCL 0x540C -#define TIOCNXCL 0x540D -#define TIOCSCTTY 0x540E - -#define TIOCSTI 0x5412 -#define TIOCMGET 0x5415 -#define TIOCMBIS 0x5416 -#define TIOCMBIC 0x5417 -#define TIOCMSET 0x5418 -#define TIOCGSOFTCAR 0x5419 -#define TIOCSSOFTCAR 0x541A -#define TIOCLINUX 0x541C -#define TIOCCONS 0x541D -#define TIOCGSERIAL 0x541E -#define TIOCSSERIAL 0x541F -#define TIOCPKT 0x5420 - -#define TIOCNOTTY 0x5422 -#define TIOCSETD 0x5423 -#define TIOCGETD 0x5424 -#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ -#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ - -#define TIOCSERCONFIG 0x5453 -#define TIOCSERGWILD 0x5454 -#define TIOCSERSWILD 0x5455 -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ -#define TIOCSERGETLSR 0x5459 /* Get line status register */ -#define TIOCSERGETMULTI 0x545A /* Get multiport config */ -#define TIOCSERSETMULTI 0x545B /* Set multiport config */ - -#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ - /* Used for packet mode */ #define TIOCPKT_DATA 0 #define TIOCPKT_FLUSHREAD 1 diff --git a/sysdeps/unix/sysv/linux/readv.c b/sysdeps/unix/sysv/linux/readv.c new file mode 100644 index 0000000000..458e8ffb38 --- /dev/null +++ b/sysdeps/unix/sysv/linux/readv.c @@ -0,0 +1,71 @@ +/* readv supports all Linux kernels >= 2.0. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + read to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <stddef.h> +#include <sys/param.h> +#include <sys/uio.h> + +extern ssize_t __syscall_readv __P ((int, __const struct iovec *, int)); + + +/* Not all versions of the kernel support the large number of records. */ +#undef MAX_IOVEC +#ifdef UIO_FASTIOV +# define MAX_IOVEC UIO_FASTIOV +#else +# define MAX_IOVEC 8 /* 8 is a safe number. */ +#endif + + +/* We should deal with kernel which have a smaller UIO_MAXIOV as well + as a very big count. */ +ssize_t +readv (fd, vector, count) + int fd; + const struct iovec *vector; + int count; +{ + int errno_saved = errno; + ssize_t bytes_read; + + bytes_read = __syscall_readv (fd, vector, count); + + if (bytes_read < 0 && errno == EINVAL && count > MAX_IOVEC) + { + int i; + + /* Restore the old error value as if nothing happened. */ + __set_errno (errno_saved); + + bytes_read = 0; + for (i = 0; i < count; i += MAX_IOVEC) + { + ssize_t bytes = __syscall_readv (fd, vector + i, + MIN (count - i, MAX_IOVEC)); + + if (bytes < 0) + return bytes; + + bytes_read += bytes; + } + } + + return bytes_read; +} diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 4e92f6d35c..f8644c2705 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -56,7 +56,12 @@ setresuid EXTRA setresuid 3 setresuid sigpending - sigpending 1 sigpending sigprocmask - sigprocmask 3 __sigprocmask sigprocmask sigreturn - sigreturn 1 __sigreturn sigreturn +sys_fstat fxstat fstat 2 __syscall_fstat sys_mknod xmknod mknod 3 __syscall_mknod +sys_lstat lxstat lstat 2 __syscall_lstat +sys_readv readv readv 3 __syscall_readv +sys_stat xstat stat 2 __syscall_stat +sys_writev writev writev 3 __syscall_writev sysinfo EXTRA sysinfo 1 sysinfo swapon - swapon 2 swapon umount EXTRA umount 1 __umount umount diff --git a/sysdeps/unix/sysv/linux/writev.c b/sysdeps/unix/sysv/linux/writev.c new file mode 100644 index 0000000000..11afd81d2e --- /dev/null +++ b/sysdeps/unix/sysv/linux/writev.c @@ -0,0 +1,68 @@ +/* writev supports all Linux kernels >= 2.0. + 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 Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library 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 <stddef.h> +#include <sys/param.h> +#include <sys/uio.h> + +extern ssize_t __syscall_writev __P ((int, const struct iovec *, int)); + +/* Not all versions of the kernel support the large number of records. */ +#undef MAX_IOVEC +#ifdef UIO_FASTIOV +# define MAX_IOVEC UIO_FASTIOV +#else +# define MAX_IOVEC 8 /* 8 is a safe number. */ +#endif + + +/* We should deal with kernel which have a smaller UIO_MAXIOV as well + as a very big count. */ +ssize_t +writev (fd, vector, count) + int fd; + const struct iovec *vector; + int count; +{ + int errno_saved = errno; + ssize_t bytes_written; + + bytes_written = __syscall_writev (fd, vector, count); + + if (bytes_written < 0 && errno == EINVAL && count > MAX_IOVEC) + { + int i; + + /* Restore the old error value as if nothing happened. */ + __set_errno (errno_saved); + + bytes_written = 0; + for (i = 0; i < count; i += MAX_IOVEC) + { + ssize_t bytes = __syscall_writev (fd, vector + i, + MIN (count - i, MAX_IOVEC)); + + if (bytes < 0) + return bytes_written > 0 ? bytes_written : bytes; + } + } + + return bytes_written; +} |