File klibc-2.0.4-git.patch of Package klibc

diff --git a/scripts/Kbuild.install b/scripts/Kbuild.install
index 78c30aa..8af5697 100644
--- a/scripts/Kbuild.install
+++ b/scripts/Kbuild.install
@@ -97,7 +97,7 @@ header:
 	$(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)bin
 	$(Q)$(MAKE) -C $(KLIBCKERNELSRC) ARCH=$(KLIBCARCH) INSTALL_HDR_PATH=$(INSTALLROOT)$(INSTALLDIR)/$(KCROSS) headers_install
 	$(Q)cp -rf usr/include/. $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include/.
-	$(Q)chmod -R a+rX $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include
+	$(Q)chmod -R a+rX,go-w $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include
 	$(Q)$(install-data) $(srctree)/klcc/klcc.1 $(INSTALLROOT)$(mandir)/man1/$(KCROSS)klcc.1
 	$(Q)$(install-bin) $(objtree)/klcc/$(KCROSS)klcc $(INSTALLROOT)$(bindir)
 
diff --git a/scripts/Kbuild.klibc.include b/scripts/Kbuild.klibc.include
new file mode 100644
index 0000000..b317286
--- /dev/null
+++ b/scripts/Kbuild.klibc.include
@@ -0,0 +1,11 @@
+
+# klibc-cc-option
+# Usage: cflags-y += $(call klibc-cc-option,-march=winchip-c6,-march=i586)
+
+klibc-cc-option = $(call try-run,\
+	$(CC) $(KLIBCCPPFLAGS) $(KLIBCCFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
+
+# klibc-cc-option-yn
+# Usage: flag := $(call klibc-cc-option-yn,-march=winchip-c6)
+klibc-cc-option-yn = $(call try-run,\
+	$(CC) $(KLIBCCPPFLAGS) $(KLIBCCFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
diff --git a/usr/dash/mkbuiltins b/usr/dash/mkbuiltins
index f562ae2..70308bd 100644
--- a/usr/dash/mkbuiltins
+++ b/usr/dash/mkbuiltins
@@ -78,7 +78,7 @@ awk '{	for (i = 2 ; i <= NF ; i++) {
 		if ($i ~ /^-/)
 			line = $(++i) "\t" line
 		print line
-	}}' $temp | LC_COLLATE=C sort -k 1,1 | tee $temp2 | awk '{
+	}}' $temp | LC_ALL=C sort -k 1,1 | tee $temp2 | awk '{
 		opt = ""
 		if (NF > 2) {
 			opt = substr($2, 2)
diff --git a/usr/gzip/gzip.c b/usr/gzip/gzip.c
index ab73de0..d0c7e00 100644
--- a/usr/gzip/gzip.c
+++ b/usr/gzip/gzip.c
@@ -90,8 +90,11 @@ int level = 6;        /* compression level */
 #endif
 
 int to_stdout;        /* output to stdout (-c) */
-#ifndef decompress
+#ifdef decompress
+int decompress_wanted;
+#else
 int decompress;       /* decompress (-d) */
+#define decompress_wanted decompress
 #endif
 int force;            /* don't ask questions, compress links (-f) */
 int no_name = -1;     /* don't save or restore the original file name */
@@ -259,17 +262,13 @@ int main (argc, argv)
      * Systems which do not support links can still use -d or -dc.
      * Ignore an .exe extension for MSDOS, OS/2 and VMS.
      */
-#ifndef decompress
     if (  strncmp(progname, "un",  2) == 0     /* ungzip, uncompress */
        || strncmp(progname, "gun", 3) == 0) {  /* gunzip */
-	decompress = 1;
+	decompress_wanted = 1;
     }
-#endif
     if (strequ(progname+1, "cat")       /* zcat, pcat, gcat */
 	|| strequ(progname, "gzcat")) {    /* gzcat */
-#ifndef decompress
-	decompress = 1;
-#endif
+	decompress_wanted = 1;
 	to_stdout = 1;
     }
 #endif
@@ -282,9 +281,7 @@ int main (argc, argv)
 	case 'c':
 	    to_stdout = 1; break;
 	case 'd':
-#ifndef decompress
-	    decompress = 1;
-#endif
+	    decompress_wanted = 1;
 	    break;
 	case 'f':
 	    force++; break;
@@ -308,9 +305,7 @@ int main (argc, argv)
             break;
 	case 't':
 	    test = to_stdout = 1;
-#ifndef decompress
-	    decompress = 1;
-#endif
+	    decompress_wanted = 1;
 	    break;
 	case 'v':
 	    verbose++; quiet = 0; break;
@@ -329,6 +324,14 @@ int main (argc, argv)
 	}
     } /* loop on all arguments */
 
+#ifndef SUPPORT_ZIP
+    if (!decompress_wanted) {
+	fprintf(stderr, "%s: this version does not support compression\n",
+		progname);
+	do_exit(ERROR);
+    }
+#endif
+
     /* By default, save name and timestamp on compression but do not
      * restore them on decompression.
      */
diff --git a/usr/include/arch/i386/klibc/archconfig.h b/usr/include/arch/i386/klibc/archconfig.h
index d8db763..f070f5b 100644
--- a/usr/include/arch/i386/klibc/archconfig.h
+++ b/usr/include/arch/i386/klibc/archconfig.h
@@ -12,7 +12,7 @@
 /* The i386 <asm/signal.h> is still not clean enough for this... */
 #define _KLIBC_USE_RT_SIG 0
 
-/* We have __libc_arch_init() */
+/* We have klibc/archinit.h and __libc_archinit() */
 #define _KLIBC_HAS_ARCHINIT 1
 
 #endif				/* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/i386/klibc/archinit.h b/usr/include/arch/i386/klibc/archinit.h
new file mode 100644
index 0000000..8995ebf
--- /dev/null
+++ b/usr/include/arch/i386/klibc/archinit.h
@@ -0,0 +1,18 @@
+/*
+ * arch/i386/include/klibc/archinit.h
+ *
+ * Architecture-specific libc initialization
+ */
+
+#include <stdint.h>
+#include <klibc/compiler.h>
+#include <elf.h>
+#include <sys/auxv.h>
+
+extern void (*__syscall_entry)(int, ...);
+
+static inline void __libc_archinit(void)
+{
+	if (__auxval[AT_SYSINFO])
+		__syscall_entry = (void (*)(int, ...)) __auxval[AT_SYSINFO];
+}
diff --git a/usr/include/arch/mips/klibc/archfcntl.h b/usr/include/arch/mips/klibc/archfcntl.h
index 2e57116..586afb4 100644
--- a/usr/include/arch/mips/klibc/archfcntl.h
+++ b/usr/include/arch/mips/klibc/archfcntl.h
@@ -19,7 +19,6 @@
 #define O_WRONLY	0x0001
 #define O_RDWR		0x0002
 #define O_APPEND	0x0008
-#define O_SYNC		0x0010
 #define O_NONBLOCK	0x0080
 #define O_CREAT         0x0100
 #define O_TRUNC		0x0200
@@ -27,11 +26,14 @@
 #define O_NOCTTY	0x0800
 #define FASYNC		0x1000
 #define O_LARGEFILE	0x2000
+#define O_SYNC		0x4010
 #define O_DIRECT	0x8000
 #define O_DIRECTORY	0x10000
 #define O_NOFOLLOW	0x20000
 #define O_NOATIME	0x40000
 #define O_CLOEXEC	0x80000
+#define O_PATH		0x200000
+#define O_TMPFILE	0x410000
 
 #define O_NDELAY	O_NONBLOCK
 
@@ -53,6 +55,24 @@
 #define F_SETLK64	34
 #define F_SETLKW64	35
 
+#define F_SETOWN_EX	15
+#define F_GETOWN_EX	16
+
+#define F_GETOWNER_UIDS	17
+
+#define F_OFD_GETLK	36
+#define F_OFD_SETLK	37
+#define F_OFD_SETLKW	38
+
+#define F_OWNER_TID	0
+#define F_OWNER_PID	1
+#define F_OWNER_PGRP	2
+
+struct f_owner_ex {
+	int	type;
+	pid_t	pid;
+};
+
 #define FD_CLOEXEC	1
 
 #define F_RDLCK		0
diff --git a/usr/include/arch/mips64/klibc/archconfig.h b/usr/include/arch/mips64/klibc/archconfig.h
index 4d856a5..df3cf1c 100644
--- a/usr/include/arch/mips64/klibc/archconfig.h
+++ b/usr/include/arch/mips64/klibc/archconfig.h
@@ -12,7 +12,12 @@
 /* MIPS has nonstandard socket definitions */
 #define _KLIBC_HAS_ARCHSOCKET_H 1
 
+#define _KLIBC_STATFS_F_TYPE_64 1
+
 /* We can use RT signals on MIPS */
 #define _KLIBC_USE_RT_SIG 1
 
+/* MIPS has architecture-specific code for vfork() */
+#define _KLIBC_REAL_VFORK 1
+
 #endif				/* _KLIBC_ARCHCONFIG_H */
diff --git a/usr/include/arch/mips64/klibc/archsetjmp.h b/usr/include/arch/mips64/klibc/archsetjmp.h
new file mode 100644
index 0000000..c4587dc
--- /dev/null
+++ b/usr/include/arch/mips64/klibc/archsetjmp.h
@@ -0,0 +1,26 @@
+/*
+ * arch/mips64/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+	unsigned long __s0;
+	unsigned long __s1;
+	unsigned long __s2;
+	unsigned long __s3;
+	unsigned long __s4;
+	unsigned long __s5;
+	unsigned long __s6;
+	unsigned long __s7;
+	unsigned long __gp;
+	unsigned long __sp;
+	unsigned long __s8;
+	unsigned long __ra;
+	unsigned long __unused;
+} __attribute__ ((aligned(8)));
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif				/* _KLIBC_ARCHSETJMP_H */
diff --git a/usr/include/arch/mips64/machine/asm.h b/usr/include/arch/mips64/machine/asm.h
new file mode 100644
index 0000000..42dcaa4
--- /dev/null
+++ b/usr/include/arch/mips64/machine/asm.h
@@ -0,0 +1,82 @@
+/*
+ * arch/mips64/include/machine/asm.h
+ */
+
+#ifndef _MACHINE_ASM_H
+#define _MACHINE_ASM_H
+
+/*
+ * Symbolic register names for 64 bit ABI
+ */
+
+
+#define zero    $0      /* wired zero */
+#define AT      $at     /* assembler temp - uppercase because of ".set at" */
+#define v0      $2      /* return value - caller saved */
+#define v1      $3
+#define a0      $4      /* argument registers */
+#define a1      $5
+#define a2      $6
+#define a3      $7
+#define a4      $8      /* arg reg 64 bit; caller saved in 32 bit */
+#define ta0     $8
+#define a5      $9
+#define ta1     $9
+#define a6      $10
+#define ta2     $10
+#define a7      $11
+#define ta3     $11
+#define t4      $12     /* caller saved */
+#define t5      $13
+#define t6      $14
+#define t7      $15
+#define s0      $16     /* callee saved */
+#define s1      $17
+#define s2      $18
+#define s3      $19
+#define s4      $20
+#define s5      $21
+#define s6      $22
+#define s7      $23
+#define t8      $24     /* caller saved */
+#define t9      $25     /* callee address for PIC/temp */
+#define jp      $25     /* PIC jump register */
+#define k0      $26     /* kernel temporary */
+#define k1      $27
+#define gp      $28     /* global pointer - caller saved for PIC */
+#define sp      $29     /* stack pointer */
+#define fp      $30     /* frame pointer */
+#define s8      $30     /* callee saved */
+#define ra      $31     /* return address */
+
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define LEAF(symbol)                                    \
+		.globl  symbol;                         \
+		.align  2;                              \
+		.type   symbol,@function;               \
+		.ent    symbol,0;                       \
+symbol:		.frame  sp,0,ra
+
+
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define NESTED(symbol, framesize, rpc)                  \
+		.globl  symbol;                         \
+		.align  2;                              \
+		.type   symbol,@function;               \
+		.ent    symbol,0;                       \
+symbol:		.frame  sp, framesize, rpc
+
+/*
+ * END - mark end of function
+ */
+#define END(function)                                   \
+		.end    function;                       \
+		.size   function,.-function
+
+
+#endif				/* _MACHINE_ASM_H */
diff --git a/usr/include/arch/ppc64/klibc/archstat.h b/usr/include/arch/ppc64/klibc/archstat.h
index 918d810..0bbbff3 100644
--- a/usr/include/arch/ppc64/klibc/archstat.h
+++ b/usr/include/arch/ppc64/klibc/archstat.h
@@ -12,6 +12,7 @@ struct stat {
 	mode_t		st_mode;
 	uid_t 		st_uid;
 	gid_t 		st_gid;
+	unsigned int	__pad1;
 	__stdev64	(st_rdev);
 	off_t		st_size;
 	unsigned long  	st_blksize;
diff --git a/usr/include/endian.h b/usr/include/endian.h
index a6cd6d9..61cda3a 100644
--- a/usr/include/endian.h
+++ b/usr/include/endian.h
@@ -12,4 +12,10 @@
 #define PDP_ENDIAN	__PDP_ENDIAN
 #define BYTE_ORDER	__BYTE_ORDER
 
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define __LONG_LONG_PAIR(HI, LO) LO, HI
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define __LONG_LONG_PAIR(HI, LO) HI, LO
+#endif
+
 #endif				/* _ENDIAN_H */
diff --git a/usr/include/fcntl.h b/usr/include/fcntl.h
index bbd6917..16128f8 100644
--- a/usr/include/fcntl.h
+++ b/usr/include/fcntl.h
@@ -9,7 +9,7 @@
 #include <klibc/compiler.h>
 #include <klibc/seek.h>
 #include <sys/types.h>
-#if defined(__mips__) && !defined(__mips64__)
+#if defined(__mips__) && ! defined(__mips64)
 # include <klibc/archfcntl.h>
 #endif
 #include <linux/fcntl.h>
diff --git a/usr/include/klibc/sysconfig.h b/usr/include/klibc/sysconfig.h
index ab947c0..c91d5b8 100644
--- a/usr/include/klibc/sysconfig.h
+++ b/usr/include/klibc/sysconfig.h
@@ -219,7 +219,7 @@
 /*
  * _KLIBC_HAS_ARCHINIT
  *
- *	This architecture uses __libc_archinit()
+ *	This architecture has klibc/archinit.h and __libc_archinit()
  */
 #ifndef _KLIBC_HAS_ARCHINIT
 # define _KLIBC_HAS_ARCHINIT 0
diff --git a/usr/include/stdlib.h b/usr/include/stdlib.h
index 406f446..123eddc 100644
--- a/usr/include/stdlib.h
+++ b/usr/include/stdlib.h
@@ -10,6 +10,7 @@
 #include <stddef.h>
 
 #include <malloc.h>
+#include <fcntl.h>
 
 #define EXIT_FAILURE 1
 #define EXIT_SUCCESS 0
@@ -83,8 +84,14 @@ static __inline__ void srandom(unsigned int __s)
 
 __extern int unlockpt(int);
 __extern char *ptsname(int);
-__extern int getpt(void);
-__extern int posix_openpt(int);
+
+static __inline__ int posix_openpt(int __mode)
+{
+	__extern int open(const char *, int, ...);
+
+	__mode &= ~(O_CREAT | O_TMPFILE);
+	return open("/dev/ptmx", __mode);
+}
 
 static __inline__ int grantpt(int __fd)
 {
@@ -92,4 +99,6 @@ static __inline__ int grantpt(int __fd)
 	return 0;		/* devpts does this all for us! */
 }
 
+__extern char *realpath(const char *, char *);
+
 #endif				/* _STDLIB_H */
diff --git a/usr/include/sys/socket.h b/usr/include/sys/socket.h
index 3334212..d0ba9eb 100644
--- a/usr/include/sys/socket.h
+++ b/usr/include/sys/socket.h
@@ -251,6 +251,7 @@ __extern int bind(int, const struct sockaddr *, int);
 __extern int connect(int, const struct sockaddr *, socklen_t);
 __extern int listen(int, int);
 __extern int accept(int, struct sockaddr *, socklen_t *);
+__extern int accept4(int, struct sockaddr *, socklen_t *, int);
 __extern int getsockname(int, struct sockaddr *, socklen_t *);
 __extern int getpeername(int, struct sockaddr *, socklen_t *);
 __extern int socketpair(int, int, int, int *);
diff --git a/usr/include/sys/socketcalls.h b/usr/include/sys/socketcalls.h
deleted file mode 100644
index 1c4367d..0000000
--- a/usr/include/sys/socketcalls.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * sys/socketcalls.h
- */
-
-#ifndef _SYS_SOCKETCALLS_H
-#define _SYS_SOCKETCALLS_H
-
-/* socketcalls by number, since <linux/net.h> isn't usable for assembly */
-
-#define SYS_SOCKET      1	/* sys_socket(2)                */
-#define SYS_BIND        2	/* sys_bind(2)                  */
-#define SYS_CONNECT     3	/* sys_connect(2)               */
-#define SYS_LISTEN      4	/* sys_listen(2)                */
-#define SYS_ACCEPT      5	/* sys_accept(2)                */
-#define SYS_GETSOCKNAME 6	/* sys_getsockname(2)           */
-#define SYS_GETPEERNAME 7	/* sys_getpeername(2)           */
-#define SYS_SOCKETPAIR  8	/* sys_socketpair(2)            */
-#define SYS_SEND        9	/* sys_send(2)                  */
-#define SYS_RECV        10	/* sys_recv(2)                  */
-#define SYS_SENDTO      11	/* sys_sendto(2)                */
-#define SYS_RECVFROM    12	/* sys_recvfrom(2)              */
-#define SYS_SHUTDOWN    13	/* sys_shutdown(2)              */
-#define SYS_SETSOCKOPT  14	/* sys_setsockopt(2)            */
-#define SYS_GETSOCKOPT  15	/* sys_getsockopt(2)            */
-#define SYS_SENDMSG     16	/* sys_sendmsg(2)               */
-#define SYS_RECVMSG     17	/* sys_recvmsg(2)               */
-
-#endif				/* _SYS_SOCKETCALLS_H */
diff --git a/usr/include/unistd.h b/usr/include/unistd.h
index 6c08d4e..0e26f5e 100644
--- a/usr/include/unistd.h
+++ b/usr/include/unistd.h
@@ -90,7 +90,6 @@ __extern int open(const char *, int, ...);
 __extern int openat(int, const char *, int, ...);
 #endif
 __extern int creat(const char *, mode_t);
-__extern int open_cloexec(const char *, int, mode_t);
 __extern int close(int);
 __extern off_t lseek(int, off_t, int);
 /* off_t is 64 bits now even on 32-bit platforms; see llseek.c */
diff --git a/usr/kinit/initrd.c b/usr/kinit/initrd.c
index d2efc59..7eece2c 100644
--- a/usr/kinit/initrd.c
+++ b/usr/kinit/initrd.c
@@ -103,8 +103,8 @@ static int run_linuxrc(int argc, char *argv[], dev_t root_dev)
 	fclose(fp);
 
 	mkdir("/old", 0700);
-	root_fd = open_cloexec("/", O_RDONLY | O_DIRECTORY, 0);
-	old_fd = open_cloexec("/old", O_RDONLY | O_DIRECTORY, 0);
+	root_fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0);
+	old_fd = open("/old", O_RDONLY|O_DIRECTORY|O_CLOEXEC, 0);
 
 	if (root_fd < 0 || old_fd < 0)
 		return -errno;
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index 40d43c7..eba6add 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -27,7 +27,7 @@ klib-y += vsnprintf.o snprintf.o vsprintf.o sprintf.o \
 	  setpgrp.o getpgrp.o daemon.o \
 	  printf.o vprintf.o fprintf.o vfprintf.o perror.o \
 	  statfs.o fstatfs.o umount.o \
-	  creat.o open.o openat.o open_cloexec.o \
+	  creat.o open.o openat.o \
 	  fread2.o fwrite2.o fgets.o fputc.o fputs.o puts.o putchar.o \
 	  sleep.o usleep.o strtotimespec.o strtotimeval.o \
 	  raise.o abort.o assert.o alarm.o pause.o \
@@ -35,6 +35,7 @@ klib-y += vsnprintf.o snprintf.o vsprintf.o sprintf.o \
 	  siglongjmp.o \
 	  sigaction.o sigpending.o sigprocmask.o sigsuspend.o \
 	  pselect.o ppoll.o \
+	  pread.o pwrite.o \
 	  brk.o sbrk.o malloc.o realloc.o zalloc.o calloc.o \
 	  mmap.o shm_open.o shm_unlink.o \
 	  memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \
@@ -51,16 +52,16 @@ klib-y += vsnprintf.o snprintf.o vsprintf.o sprintf.o \
 	  getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
 	  clearenv.o nullenv.o \
 	  getopt.o getopt_long.o readdir.o scandir.o alphasort.o remove.o \
-	  syslog.o closelog.o pty.o getpt.o posix_openpt.o isatty.o reboot.o \
+	  syslog.o closelog.o pty.o isatty.o reboot.o \
 	  time.o utime.o lseek.o nice.o getpriority.o \
 	  qsort.o bsearch.o \
 	  lrand48.o jrand48.o mrand48.o nrand48.o srand48.o seed48.o \
 	  inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \
 	  inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \
-	  send.o recv.o \
+	  accept.o send.o recv.o \
 	  access.o chmod.o chown.o dup2.o mknod.o poll.o rename.o stat.o \
 	  lchown.o link.o rmdir.o unlink.o utimes.o lstat.o mkdir.o \
-	  readlink.o select.o symlink.o pipe.o \
+	  readlink.o realpath.o select.o symlink.o pipe.o \
 	  ctype/isalnum.o ctype/isalpha.o ctype/isascii.o \
 	  ctype/isblank.o ctype/iscntrl.o ctype/isdigit.o \
 	  ctype/isgraph.o ctype/islower.o ctype/isprint.o \
diff --git a/usr/klibc/README.klibc b/usr/klibc/README.klibc
index c72ae47..63a149b 100644
--- a/usr/klibc/README.klibc
+++ b/usr/klibc/README.klibc
@@ -10,9 +10,12 @@ this:
 a) Extract a recent Linux kernel into a directory and run
    "make headers_install".
    Now enter the klibc dir and point KLIBCKERNELSRC to the
-   path of the configured linux tree
+   usr subdirectory of the configured linux tree
    "make  KLIBCKERNELSRC=`pwd`/../linux/usr/".
 
+   It is also possible to install the kernel headers elsewhere and
+   point to them there.
+
 
 b) If you're cross-compiling, you need to set KLIBCARCH to the
    appropriate architecture, and set CROSS_COMPILE to your toolchain
@@ -45,7 +48,7 @@ b) If you're cross-compiling, you need to set KLIBCARCH to the
    m32r:	 Untested
    m68k:	 Working
    mips:	 Working
-   mips64:	 Not yet ported
+   mips64:	 Working
    parisc:	 Untested
    parisc64:	 Not yet ported
    ppc:		 Working
diff --git a/usr/klibc/SOCKETCALLS.def b/usr/klibc/SOCKETCALLS.def
index 39f7db5..97413de 100644
--- a/usr/klibc/SOCKETCALLS.def
+++ b/usr/klibc/SOCKETCALLS.def
@@ -9,6 +9,7 @@
 <?> int connect(int, const struct sockaddr *, socklen_t);
 <?> int listen(int, int);
 <?> int accept(int, struct sockaddr *, socklen_t *);
+<?> int accept4(int, struct sockaddr *, socklen_t *, int);
 <?> int getsockname(int, struct sockaddr *, socklen_t *);
 <?> int getpeername(int, struct sockaddr *, socklen_t *);
 <?> int socketpair(int, int, int, int *);
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 41cfa17..c56e8f9 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -189,8 +189,10 @@ int fdatasync,fsync::fdatasync(int);
 int readv(int, const struct iovec *, int);
 int writev(int, const struct iovec *, int);
 int ftruncate64,ftruncate::ftruncate(int, off_t);
-ssize_t pread64,pread::pread(int, void *, size_t, off_t);
-ssize_t pwrite64,pwrite::pwrite(int, void *, size_t, off_t);
+<parisc> ssize_t pread64,pread::__pread(int, void *, size_t, off_t);
+<parisc> ssize_t pwrite64,pwrite::__pwrite(int, void *, size_t, off_t);
+<!parisc> ssize_t pread64,pread::pread(int, void *, size_t, off_t);
+<!parisc> ssize_t pwrite64,pwrite::pwrite(int, void *, size_t, off_t);
 int sync_file_range,fdatasync,fsync::sync_file_range(int, off_t, off_t, unsigned int);
 <?> int splice(int, off_t *, int, off_t *, size_t, unsigned int);
 <?> int tee(int, int, size_t, unsigned int);
diff --git a/usr/klibc/accept.c b/usr/klibc/accept.c
new file mode 100644
index 0000000..6057544
--- /dev/null
+++ b/usr/klibc/accept.c
@@ -0,0 +1,16 @@
+/*
+ * accept.c
+ *
+ * Some architectures need to wrap the system call
+ */
+
+#include <sys/socket.h>
+
+#if !_KLIBC_SYS_SOCKETCALL && defined(__NR_accept4) && !defined(__NR_accept)
+
+int accept(int socket, struct sockaddr *address, socklen_t *addr_len)
+{
+	return accept4(socket, address, addr_len, 0);
+}
+
+#endif
diff --git a/usr/klibc/arch/i386/Kbuild b/usr/klibc/arch/i386/Kbuild
index 1642374..de237be 100644
--- a/usr/klibc/arch/i386/Kbuild
+++ b/usr/klibc/arch/i386/Kbuild
@@ -2,7 +2,7 @@
 # klibc .o files for i386
 #
 
-klib-y := archinit.o socketcall.o setjmp.o syscall.o varsyscall.o
+klib-y := setjmp.o syscall.o varsyscall.o
 klib-y += open.o openat.o vfork.o
 klib-y += libgcc/__ashldi3.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o
 klib-y += libgcc/__muldi3.o  libgcc/__negdi2.o
diff --git a/usr/klibc/arch/i386/archinit.c b/usr/klibc/arch/i386/archinit.c
deleted file mode 100644
index 111d130..0000000
--- a/usr/klibc/arch/i386/archinit.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * arch/i386/archinit.c
- *
- * Architecture-specific libc initialization
- */
-
-#include <stdint.h>
-#include <klibc/compiler.h>
-#include <elf.h>
-#include <sys/auxv.h>
-
-extern void (*__syscall_entry)(int, ...);
-
-void __libc_archinit(void)
-{
-	if (__auxval[AT_SYSINFO])
-		__syscall_entry = (void (*)(int, ...)) __auxval[AT_SYSINFO];
-}
diff --git a/usr/klibc/arch/i386/socketcall.S b/usr/klibc/arch/i386/socketcall.S
deleted file mode 100644
index 44e2004..0000000
--- a/usr/klibc/arch/i386/socketcall.S
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# socketcall.S
-#
-# Socketcalls use the following convention:
-# %eax = __NR_socketcall
-# %ebx = socketcall number
-# %ecx = pointer to arguments (up to 6)
-#
-
-#include <asm/unistd.h>
-
-#ifdef __i386__
-
-	.text
-	.align 4
-	.globl __socketcall_common
-	.type __socketcall_common, @function
-
-__socketcall_common:
-	xchgl	%ebx,(%esp)	# The stub passes the socketcall # on stack
-
-#ifdef	_REGPARM
-	pushl	16(%esp)	# Arg 6
-	pushl	16(%esp)	# Arg 5
-	pushl	16(%esp)	# Arg 4
-	pushl	%ecx
-	pushl	%edx
-	pushl	%eax
-	movl	%esp,%ecx
-#else
-	leal	8(%esp),%ecx	# Arguments already contiguous on-stack
-#endif
-
-	movl	$__NR_socketcall,%eax
-	call	*__syscall_entry
-
-#ifdef	_REGPARM
-	addl	$6*4, %esp
-#endif
-
-	cmpl	$-4095,%eax	# Error return?
-
-	popl	%ebx
-
-	jb	1f
-
-	negl	%eax
-	movl	%eax,errno
-	orl	$-1,%eax	# Return -1
-1:
-	ret
-
-	.size __socketcall_common,.-__socketcall_common
-
-#endif
diff --git a/usr/klibc/arch/mips64/Kbuild b/usr/klibc/arch/mips64/Kbuild
index 970c0f8..6fe3b53 100644
--- a/usr/klibc/arch/mips64/Kbuild
+++ b/usr/klibc/arch/mips64/Kbuild
@@ -1,3 +1,14 @@
 #
 # klibc files for mips64
 #
+
+klib-y := ../mips/pipe.o ../mips/vfork.o setjmp.o ../mips/syscall.o
+
+klib-y += ../../libgcc/__clzsi2.o     ../../libgcc/__ashldi3.o
+klib-y += ../../libgcc/__ashrdi3.o    ../../libgcc/__lshrdi3.o
+klib-y += ../../libgcc/__divdi3.o     ../../libgcc/__moddi3.o
+klib-y += ../../libgcc/__udivdi3.o    ../../libgcc/__umoddi3.o
+klib-y += ../../libgcc/__udivmoddi4.o
+
+always  := crt0.o
+targets := crt0.o
diff --git a/usr/klibc/arch/mips64/MCONFIG b/usr/klibc/arch/mips64/MCONFIG
index 5c50b8d..b37cc6a 100644
--- a/usr/klibc/arch/mips64/MCONFIG
+++ b/usr/klibc/arch/mips64/MCONFIG
@@ -9,3 +9,5 @@
 
 KLIBCOPTFLAGS += -Os
 KLIBCBITSIZE  = 64
+
+KLIBCSHAREDFLAGS  = -T $(src)/arch/mips/klibc.ld
diff --git a/usr/klibc/arch/mips64/crt0.S b/usr/klibc/arch/mips64/crt0.S
new file mode 100644
index 0000000..775a919
--- /dev/null
+++ b/usr/klibc/arch/mips64/crt0.S
@@ -0,0 +1,31 @@
+#
+# arch/mips64/crt0.S
+#
+# Does arch-specific initialization and invokes __libc_init
+# with the appropriate arguments.
+#
+# See __static_init.c or __shared_init.c for the expected
+# arguments.
+#
+
+#include <machine/asm.h>
+
+NESTED(__start, 64, sp)
+	daddiu  sp,sp,-64
+	sd	zero, 32(sp)
+
+					# Initialize gp
+	lui gp,%highest(_gp) 		# load highest "halfword"
+	daddiu gp,gp,%higher(_gp) 	# merge next "halfword"
+	dsll gp,gp,16 			# shift by one halfword
+	daddiu gp,gp,%hi(_gp) 		# merge next "halfword"
+	dsll gp,gp,16 			# shift into final position
+	daddiu gp,gp,%lo(_gp) 		# merge lowest "halfword"
+
+	daddiu	a0, sp, 64		# Pointer to ELF entry structure
+	move	a1, v0			# Kernel-provided atexit() pointer
+
+	ld  t9, %call16(__libc_init)(gp)
+	jalr t9
+
+	END(__start)
diff --git a/usr/klibc/arch/mips64/setjmp.S b/usr/klibc/arch/mips64/setjmp.S
new file mode 100644
index 0000000..5d902e2
--- /dev/null
+++ b/usr/klibc/arch/mips64/setjmp.S
@@ -0,0 +1,50 @@
+#
+# arch/mips64/setjmp.S
+#
+# setjmp/longjmp for the MIPS architecture
+#
+# The jmp_buf is assumed to contain the following, in order:
+#	s0..s7
+#	gp
+#	sp
+#	s8
+#	ra
+#
+
+#include <machine/asm.h>
+
+LEAF(setjmp)
+	sd	s0,  0(a0)
+	sd	s1,  8(a0)
+	sd	s2, 16(a0)
+	sd	s3, 24(a0)
+	sd	s4, 32(a0)
+	sd	s5, 40(a0)
+	sd	s6, 48(a0)
+	sd	s7, 56(a0)
+	sd	gp, 64(a0)
+	sd	sp, 72(a0)
+	sd	s8, 80(a0)
+	sd	ra, 88(a0)
+	move	v0, zero
+	jr	ra
+
+	END(setjmp)
+
+LEAF(longjmp)
+	ld	s0,  0(a0)
+	ld	s1,  8(a0)
+	ld	s2, 16(a0)
+	ld	s3, 24(a0)
+	ld	s4, 32(a0)
+	ld	s5, 40(a0)
+	ld	s6, 48(a0)
+	ld	s7, 56(a0)
+	ld	gp, 64(a0)
+	ld	sp, 72(a0)
+	ld	s8, 80(a0)
+	ld	ra, 88(a0)
+	move	v0, a1
+	jr	ra
+
+	END(longjmp)
diff --git a/usr/klibc/arch/mips64/sysstub.ph b/usr/klibc/arch/mips64/sysstub.ph
new file mode 100644
index 0000000..e8a0200
--- /dev/null
+++ b/usr/klibc/arch/mips64/sysstub.ph
@@ -0,0 +1,29 @@
+# -*- perl -*-
+#
+# arch/mips64/sysstub.ph
+#
+# Script to generate system call stubs
+#
+
+# On MIPS, most system calls follow the standard convention, with the
+# system call number in r0 (v0), return an error value in r19 (a3) as
+# well as the return value in r0 (v0).
+
+sub make_sysstub($$$$$@) {
+    my($outputdir, $fname, $type, $sname, $stype, @args) = @_;
+
+    $stype = $stype || 'common';
+    open(OUT, '>', "${outputdir}/${fname}.S");
+    print OUT "#include <machine/asm.h>\n";
+    print OUT "#include <asm/unistd.h>\n";
+    print OUT "\n";
+    print OUT "\t.set noreorder\n";
+    print OUT "\n";
+    print OUT "LEAF(${fname})\n";
+    print OUT "\tj\t__syscall_${stype}\n";
+    print OUT "\t  li\tv0, __NR_${sname}\n";
+    print OUT "\tEND(${fname})\n";
+    close(OUT);
+}
+
+1;
diff --git a/usr/klibc/arch/ppc64/sysstub.ph b/usr/klibc/arch/ppc64/sysstub.ph
index b3f6e38..a0c6d41 100644
--- a/usr/klibc/arch/ppc64/sysstub.ph
+++ b/usr/klibc/arch/ppc64/sysstub.ph
@@ -18,6 +18,9 @@ sub make_sysstub($$$$$@) {
 #if _CALL_ELF == 2
 	.type ${fname},\@function
 ${fname}:
+0:	addis	2,12,(.TOC.-0b)\@ha
+	addi	2,2,(.TOC.-0b)\@l
+	.localentry ${fname},.-${fname}
 #else
 	.section ".opd","aw"
 	.balign 8
diff --git a/usr/klibc/asprintf.c b/usr/klibc/asprintf.c
index a3f5f00..ce3aa76 100644
--- a/usr/klibc/asprintf.c
+++ b/usr/klibc/asprintf.c
@@ -8,22 +8,13 @@
 
 int asprintf(char **bufp, const char *format, ...)
 {
-	va_list ap, ap1;
+	va_list ap;
 	int rv;
 	int bytes;
 	char *p;
 
 	va_start(ap, format);
-	va_copy(ap1, ap);
-
-	bytes = vsnprintf(NULL, 0, format, ap1) + 1;
-	va_end(ap1);
-
-	*bufp = p = malloc(bytes);
-	if (!p)
-		return -1;
-
-	rv = vsnprintf(p, bytes, format, ap);
+	rv = vasprintf(bufp, format, ap);
 	va_end(ap);
 
 	return rv;
diff --git a/usr/klibc/getpt.c b/usr/klibc/getpt.c
deleted file mode 100644
index 8d2a536..0000000
--- a/usr/klibc/getpt.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * getpt.c
- *
- * GNU extension to the standard Unix98 pty suite
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <termios.h>
-#include <fcntl.h>
-
-int getpt(void)
-{
-	return open("/dev/ptmx", O_RDWR | O_NOCTTY);
-}
diff --git a/usr/klibc/libc_init.c b/usr/klibc/libc_init.c
index c54d022..c5b9bab 100644
--- a/usr/klibc/libc_init.c
+++ b/usr/klibc/libc_init.c
@@ -28,6 +28,12 @@
 #include <klibc/sysconfig.h>
 #include "atexit.h"
 
+#if _KLIBC_HAS_ARCHINIT
+# include "klibc/archinit.h"
+#else
+# define __libc_archinit() ((void)0)
+#endif
+
 /* This file is included from __static_init.c or __shared_init.c */
 #ifndef SHARED
 # error "SHARED should be defined to 0 or 1"
@@ -42,7 +48,6 @@ struct auxentry {
 };
 
 extern void __libc_init_stdio(void);
-extern void __libc_archinit(void);
 
 unsigned long __auxval[_AUXVAL_MAX];
 
diff --git a/usr/klibc/open_cloexec.c b/usr/klibc/open_cloexec.c
deleted file mode 100644
index e30b09d..0000000
--- a/usr/klibc/open_cloexec.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * open_cloexec.c
- *
- * A quick hack to do an open() and set the cloexec flag
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-
-int open_cloexec(const char *path, int flags, mode_t mode)
-{
-	int fd = open(path, flags, mode);
-
-	if (fd >= 0)
-		fcntl(fd, F_SETFD, FD_CLOEXEC);
-
-	return fd;
-}
diff --git a/usr/klibc/posix_openpt.c b/usr/klibc/posix_openpt.c
deleted file mode 100644
index 794ca46..0000000
--- a/usr/klibc/posix_openpt.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * posix_openpt.c
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <termios.h>
-#include <fcntl.h>
-
-int posix_openpt(int oflag)
-{
-	return open("/dev/ptmx", oflag);
-}
diff --git a/usr/klibc/pread.c b/usr/klibc/pread.c
new file mode 100644
index 0000000..0d8c3b1
--- /dev/null
+++ b/usr/klibc/pread.c
@@ -0,0 +1,29 @@
+/*
+ * pread.c
+ *
+ * Some architectures need to wrap the system call
+ */
+
+#include <endian.h>
+#include <sys/syscall.h>
+
+#if defined(__hppa__)
+
+#if _BITSIZE == 32
+extern size_t __pread(int, void *, size_t, unsigned int, unsigned int);
+#else
+extern size_t __pread(int, void *, size_t, off_t);
+#endif
+
+size_t pread(int fd, void *buf, size_t count, off_t offset)
+{
+#if _BITSIZE == 32
+	unsigned int hi = offset >> 32;
+	unsigned int lo = (unsigned int) offset;
+	return __pread(fd, buf, count, __LONG_LONG_PAIR(hi, lo));
+#else
+	return __pread(fd, buf, count, offset);
+#endif
+}
+
+#endif
diff --git a/usr/klibc/pwrite.c b/usr/klibc/pwrite.c
new file mode 100644
index 0000000..691d0e4
--- /dev/null
+++ b/usr/klibc/pwrite.c
@@ -0,0 +1,29 @@
+/*
+ * pwrite.c
+ *
+ * Some architectures need to wrap the system call
+ */
+
+#include <endian.h>
+#include <sys/syscall.h>
+
+#if defined(__hppa__)
+
+#if _BITSIZE == 32
+extern ssize_t __pwrite(int, const void *, size_t, unsigned int, unsigned int);
+#else
+extern ssize_t __pwrite(int, const void *, size_t, off_t);
+#endif
+
+size_t pwrite(int fd, void *buf, size_t count, off_t offset)
+{
+#if _BITSIZE == 32
+	unsigned int hi = offset >> 32;
+	unsigned int lo = (unsigned int) offset;
+	return __pwrite(fd, buf, count, __LONG_LONG_PAIR(hi, lo));
+#else
+	return __pwrite(fd, buf, count, offset);
+#endif
+}
+
+#endif
diff --git a/usr/klibc/realpath.c b/usr/klibc/realpath.c
new file mode 100644
index 0000000..1474b1e
--- /dev/null
+++ b/usr/klibc/realpath.c
@@ -0,0 +1,49 @@
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * Note that this requires name to refer to an existing file.  This is
+ * correct according to POSIX.  However, BSD and GNU implementations
+ * also allow name to refer to a non-existing file in an existing
+ * directory.
+ */
+
+char *realpath(const char *name, char *resolved_name)
+{
+	static const char proc_fd_prefix[] = "/proc/self/fd/";
+	char proc_fd_name[sizeof(proc_fd_prefix) + sizeof(int) * 3];
+	int allocated = 0;
+	int fd;
+	ssize_t len;
+
+	/* Open for path lookup only */
+	fd = open(name, O_PATH);
+	if (fd < 0)
+		return NULL;
+
+	if (!resolved_name) {
+		resolved_name = malloc(PATH_MAX);
+		if (!resolved_name)
+			goto out_close;
+		allocated = 1;
+	}
+
+	/* Use procfs to read back the resolved name */
+	sprintf(proc_fd_name, "%s%d", proc_fd_prefix, fd);
+	len = readlink(proc_fd_name, resolved_name, PATH_MAX - 1);
+	if (len < 0) {
+		if (allocated)
+			free(resolved_name);
+		resolved_name = NULL;
+	} else {
+		resolved_name[len] = 0;
+	}
+
+out_close:
+	close(fd);
+	return resolved_name;
+}
diff --git a/usr/klibc/shm_open.c b/usr/klibc/shm_open.c
index 8fe93aa..a54e246 100644
--- a/usr/klibc/shm_open.c
+++ b/usr/klibc/shm_open.c
@@ -19,5 +19,5 @@ int shm_open(const char *path, int oflag, mode_t mode)
 	memcpy(pathbuf, "/dev/shm/", 9);
 	memcpy(pathbuf+9, path, len+1);
 
-	return open_cloexec(path, oflag, mode);
+	return open(path, oflag, mode|O_CLOEXEC);
 }
diff --git a/usr/klibc/socketcalls.pl b/usr/klibc/socketcalls.pl
index 3dac096..70ded0b 100644
--- a/usr/klibc/socketcalls.pl
+++ b/usr/klibc/socketcalls.pl
@@ -42,44 +42,38 @@ while ( defined($line = <FILE>) ) {
 	$nargs = $i;
 	print " \\\n\t${name}.o";
 
-	if ( $arch eq 'i386' ) {
-	    open(OUT, "> ${outputdir}/${name}.S")
-		or die "$0: Cannot open ${outputdir}/${name}.S\n";
+	open(OUT, "> ${outputdir}/${name}.c")
+	    or die "$0: Cannot open ${outputdir}/${name}.c\n";
 
-	    print OUT "#include <sys/socketcalls.h>\n";
-	    print OUT "\n";
-	    print OUT "\t.text\n";
-	    print OUT "\t.align	4\n";
-	    print OUT "\t.globl	${name}\n";
-	    print OUT "\t.type	${name},\@function\n";
-	    print OUT "${name}:\n";
-	    print OUT "\tpushl	\$SYS_\U${name}\n";
-	    print OUT "\tjmp	__socketcall_common\n";
-	    print OUT "\t.size ${name},.-${name}\n";
-	    close(OUT);
-	} else {
-	    open(OUT, "> ${outputdir}/${name}.c")
-		or die "$0: Cannot open ${outputdir}/${name}.c\n";
+	print OUT "#include \"socketcommon.h\"\n";
+	print OUT "\n";
+	print OUT "#if _KLIBC_SYS_SOCKETCALL\n";
+	print OUT "# define DO_THIS_SOCKETCALL\n";
+	print OUT "#else\n";
+	print OUT "# if !defined(__NR_${name})";
+	if ($name eq 'accept') {
+	    print OUT " && !defined(__NR_accept4)";
+	}
+	print OUT "\n#  define DO_THIS_SOCKETCALL\n";
+	print OUT "# endif\n";
+	print OUT "#endif\n\n";
 
-	    print OUT "#include \"socketcommon.h\"\n";
-	    print OUT "\n";
-	    print OUT "#if _KLIBC_SYS_SOCKETCALL || !defined(__NR_${name})\n\n";
+	print OUT "#if defined(DO_THIS_SOCKETCALL) && defined(SYS_\U${name}\E)\n\n";
 
-	    print OUT "extern long __socketcall(int, const unsigned long *);\n\n";
+	print OUT "extern long __socketcall(int, const unsigned long *);\n\n";
 
-	    print OUT "$type $name (", join(', ', @cargs), ")\n";
-	    print OUT "{\n";
-	    print OUT "    unsigned long args[$nargs];\n";
-	    for ( $i = 0 ; $i < $nargs ; $i++ ) {
-		print OUT "    args[$i] = (unsigned long)a$i;\n";
-	    }
-	    print OUT "    return ($type) __socketcall(SYS_\U${name}\E, args);\n";
-	    print OUT "}\n\n";
+	print OUT "$type ${name}(", join(', ', @cargs), ")\n";
+	print OUT "{\n";
+	print OUT "    unsigned long args[$nargs];\n";
+	for ( $i = 0 ; $i < $nargs ; $i++ ) {
+	    print OUT "    args[$i] = (unsigned long)a$i;\n";
+	}
+	print OUT "    return ($type) __socketcall(SYS_\U${name}\E, args);\n";
+	print OUT "}\n\n";
 
-	    print OUT "#endif\n";
+	print OUT "#endif\n";
 
-	    close(OUT);
-	}
+	close(OUT);
     } else {
 	die "$file:$.: Could not parse input\n";
     }
diff --git a/usr/klibc/socketcalls/socketcommon.h b/usr/klibc/socketcalls/socketcommon.h
index 9c4b11f..7fdd547 100644
--- a/usr/klibc/socketcalls/socketcommon.h
+++ b/usr/klibc/socketcalls/socketcommon.h
@@ -13,4 +13,3 @@
 #include <sys/time.h>
 #include <sys/socket.h>
 #include <linux/net.h>
-#include <sys/socketcalls.h>
diff --git a/usr/klibc/stdio/fwrite.c b/usr/klibc/stdio/fwrite.c
index 71ee75c..9f32ae4 100644
--- a/usr/klibc/stdio/fwrite.c
+++ b/usr/klibc/stdio/fwrite.c
@@ -14,14 +14,15 @@ static size_t fwrite_noflush(const void *buf, size_t count,
 	ssize_t rv;
 
 	while (count) {
-		if (f->ibytes || f->obytes >= f->bufsiz)
+		if (f->ibytes || f->obytes >= f->bufsiz ||
+		    (f->obytes && count >= f->bufsiz))
 			if (__fflush(f))
 				break;
 
-		if (f->obytes == 0 && count >= f->bufsiz) {
+		if (count >= f->bufsiz) {
 			/*
-			 * The buffer is empty and the write is large,
-			 * so bypass the buffering entirely.
+			 * The write is large, so bypass
+			 * buffering entirely.
 			 */
 			rv = write(f->pub._IO_fileno, p, count);
 			if (rv == -1) {
diff --git a/usr/klibc/version b/usr/klibc/version
index 2165f8f..e010258 100644
--- a/usr/klibc/version
+++ b/usr/klibc/version
@@ -1 +1 @@
-2.0.4
+2.0.5
diff --git a/usr/utils/mount_opts.c b/usr/utils/mount_opts.c
index 05d1729..bb26c7d 100644
--- a/usr/utils/mount_opts.c
+++ b/usr/utils/mount_opts.c
@@ -89,8 +89,13 @@ parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra)
 				break;
 		}
 
-		if (res != 0 && s[0])
-			add_extra_option(extra, opt);
+		if (res != 0 && s[0]) {
+			if (!strcmp(opt, "defaults"))
+				rwflag &= ~(MS_RDONLY|MS_NOSUID|MS_NODEV|
+					    MS_NOEXEC|MS_SYNCHRONOUS);
+			else
+				add_extra_option(extra, opt);
+		}
 	}
 
 	return rwflag;
diff --git a/usr/utils/readlink.c b/usr/utils/readlink.c
index 4e3cfcb..ffb0b1f 100644
--- a/usr/utils/readlink.c
+++ b/usr/utils/readlink.c
@@ -7,24 +7,45 @@ const char *progname;
 
 static __noreturn usage(void)
 {
-	fprintf(stderr, "Usage: %s link...\n", progname);
+	fprintf(stderr, "Usage: %s [-f] link...\n", progname);
 	exit(1);
 }
 
 int main(int argc, char *argv[])
 {
+	int c, f_flag = 0;
 	const char *name;
 	char link_name[PATH_MAX];
 	int rv;
 	int i;
 
-	progname = *argv++;
+	progname = argv[0];
 
-	if (argc < 2)
+	do {
+		c = getopt(argc, argv, "f");
+		if (c == EOF)
+			break;
+		switch (c) {
+		case 'f':
+			f_flag = 1;
+			break;
+
+		case '?':
+			fprintf(stderr, "%s: invalid option -%c\n",
+				progname, optopt);
+			usage();
+		}
+	} while (1);
+
+	if (optind == argc)
 		usage();
 
+	argv += optind;
 	while ((name = *argv++)) {
-		rv = readlink(name, link_name, sizeof link_name - 1);
+		if (f_flag)
+			rv = realpath(name, link_name) ? strlen(link_name) : -1;
+		else
+			rv = readlink(name, link_name, sizeof link_name - 1);
 		if (rv < 0) {
 			perror(name);
 			exit(1);
openSUSE Build Service is sponsored by