svn commit: trunk/uClibc: libc/sysdeps/linux/common libpthread/lin etc...

carmelo at uclibc.org carmelo at uclibc.org
Tue Sep 9 12:01:38 UTC 2008


Author: carmelo
Date: 2008-09-09 05:01:37 -0700 (Tue, 09 Sep 2008)
New Revision: 23363

Log:
Use getdents syscall if kernel provide supports for this
instead of relying upon getdents64.

Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono at st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>


Modified:
   trunk/uClibc/libc/sysdeps/linux/common/getdents.c
   trunk/uClibc/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h


Changeset:
Modified: trunk/uClibc/libc/sysdeps/linux/common/getdents.c
===================================================================
--- trunk/uClibc/libc/sysdeps/linux/common/getdents.c	2008-09-09 08:50:18 UTC (rev 23362)
+++ trunk/uClibc/libc/sysdeps/linux/common/getdents.c	2008-09-09 12:01:37 UTC (rev 23363)
@@ -18,8 +18,7 @@
 #include <bits/kernel_types.h>
 
 /* With newer versions of linux, the getdents syscall returns d_type
- * information after the name field.  Someday, we should add support for
- * that instead of always calling getdents64 ...
+ * information after the name field.
  *
  * See __ASSUME_GETDENTS32_D_TYPE in glibc's kernel-features.h for specific
  * version / arch details.
@@ -39,14 +38,42 @@
 
 ssize_t __getdents (int fd, char *buf, size_t nbytes) attribute_hidden;
 
-#if ! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64
+#define __NR___syscall_getdents __NR_getdents
+static inline _syscall3(int, __syscall_getdents, int, fd, unsigned char *, kdirp, size_t, count);
 
+#ifdef __ASSUME_GETDENTS32_D_TYPE
+ssize_t __getdents (int fd, char *buf, size_t nbytes)
+{
+	ssize_t retval;
+
+	retval = __syscall_getdents(fd, (unsigned char *)buf, nbytes);
+
+	/* The kernel added the d_type value after the name.  Change
+	this now.  */
+	if (retval != -1) {
+		union {
+			struct kernel_dirent k;
+			struct dirent u;
+		} *kbuf = (void *) buf;
+
+		while ((char *) kbuf < buf + retval) {
+			char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
+			memmove (kbuf->u.d_name, kbuf->k.d_name,
+			strlen (kbuf->k.d_name) + 1);
+			kbuf->u.d_type = d_type;
+
+			kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
+		}
+	}
+
+	return retval;
+}
+
+#elif ! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64
+
 /* Experimentally off - libc_hidden_proto(memcpy) */
 libc_hidden_proto(lseek)
 
-#define __NR___syscall_getdents __NR_getdents
-static __inline__ _syscall3(int, __syscall_getdents, int, fd, unsigned char *, kdirp, size_t, count);
-
 ssize_t __getdents (int fd, char *buf, size_t nbytes)
 {
     struct dirent *dp;

Modified: trunk/uClibc/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h
===================================================================
--- trunk/uClibc/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h	2008-09-09 08:50:18 UTC (rev 23362)
+++ trunk/uClibc/libpthread/linuxthreads/sysdeps/pthread/kernel-features.h	2008-09-09 12:01:37 UTC (rev 23363)
@@ -62,6 +62,14 @@
 # define __ASSUME_VFORK_SYSCALL		1
 #endif
 
+/* Starting with version 2.6.4-rc1 the getdents syscall returns d_type
+ *    information as well and in between 2.6.5 and 2.6.8 most compat wrappers
+ *       were fixed too.  Except s390{,x} which was fixed in 2.6.11.  */
+#if (__LINUX_KERNEL_VERSION >= 0x020608 && !defined __s390__) \
+    || (__LINUX_KERNEL_VERSION >= 0x02060b && defined __s390__)
+# define __ASSUME_GETDENTS32_D_TYPE 1
+#endif
+
 /* These features were surely available with 2.4.12.  */
 #if __LINUX_KERNEL_VERSION >= 132108 && defined __mc68000__
 # define __ASSUME_MMAP2_SYSCALL		1




More information about the uClibc-cvs mailing list