]> Git Repo - uclibc-ng.git/commitdiff
getdents: Use getdents64 if arch does not have the getdents syscall
authorMarkos Chandras <[email protected]>
Thu, 11 Oct 2012 10:30:59 +0000 (11:30 +0100)
committerBernhard Reutner-Fischer <[email protected]>
Wed, 20 Feb 2013 12:45:12 +0000 (13:45 +0100)
Signed-off-by: Markos Chandras <[email protected]>
Signed-off-by: Bernhard Reutner-Fischer <[email protected]>
libc/sysdeps/linux/common/getdents.c
libc/sysdeps/linux/common/getdents64.c

index f4fb7476e26b7f08ee50450762efeab979360279..b65524eee0ca0981f6981ba18f78166c529b6a95 100644 (file)
@@ -26,6 +26,7 @@
  * version / arch details.
  */
 
+# ifdef __ARCH_HAS_DEPRECATED_SYSCALLS__
 struct kernel_dirent
 {
        long int d_ino;
@@ -33,11 +34,16 @@ struct kernel_dirent
        unsigned short int d_reclen;
        char d_name[256];
 };
+# else
+#  define kernel_dirent dirent
+# endif
 
-#define __NR___syscall_getdents __NR_getdents
+# if defined __NR_getdents
+#  define __NR___syscall_getdents __NR_getdents
 static __always_inline _syscall3(int, __syscall_getdents, int, fd, unsigned char *, kdirp, size_t, count)
+# endif
 
-#if defined __ASSUME_GETDENTS32_D_TYPE
+# if defined __ASSUME_GETDENTS32_D_TYPE && defined __NR_getdents
 
 ssize_t __getdents (int fd, char *buf, size_t nbytes)
 {
@@ -66,14 +72,14 @@ ssize_t __getdents (int fd, char *buf, size_t nbytes)
        return retval;
 }
 
-#elif ! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64
+# elif ! defined __UCLIBC_HAS_LFS__ || !defined __NR_getdents64
 
-# include <assert.h>
-# include <stddef.h>
-# include <errno.h>
-# include <unistd.h>
-# include <sys/param.h>
-# include <bits/uClibc_alloc.h>
+#  include <assert.h>
+#  include <stddef.h>
+#  include <errno.h>
+#  include <unistd.h>
+#  include <sys/param.h>
+#  include <bits/uClibc_alloc.h>
 
 ssize_t __getdents (int fd, char *buf, size_t nbytes)
 {
@@ -85,6 +91,7 @@ ssize_t __getdents (int fd, char *buf, size_t nbytes)
     const size_t size_diff = (offsetof (struct dirent, d_name)
            - offsetof (struct kernel_dirent, d_name));
 
+#  ifdef __ARCH_HAS_DEPRECATED_SYSCALLS__
     red_nbytes = MIN (nbytes - ((nbytes /
                    (offsetof (struct dirent, d_name) + 14)) * size_diff),
            nbytes - size_diff);
@@ -93,6 +100,21 @@ ssize_t __getdents (int fd, char *buf, size_t nbytes)
     skdp = kdp = stack_heap_alloc(red_nbytes);
 
     retval = __syscall_getdents(fd, (unsigned char *)kdp, red_nbytes);
+#  else
+
+    dp = (struct dirent *) buf;
+    skdp = kdp = stack_heap_alloc(nbytes);
+
+    retval = INLINE_SYSCALL(getdents64, 3, fd, (unsigned char *)kdp, nbytes);
+    if (retval > 0) {
+           /* Did we overflow? */
+           if (kdp->__pad1 || kdp->__pad2) {
+                   __set_errno(EINVAL);
+                   return -1;
+           }
+    }
+#  endif
+
     if (retval == -1) {
        stack_heap_free(skdp);
        return -1;
@@ -134,9 +156,9 @@ ssize_t __getdents (int fd, char *buf, size_t nbytes)
     return (char *) dp - buf;
 }
 
-#elif __WORDSIZE == 32
+# elif __WORDSIZE == 32 && !defined __NR_getdents64
 
-# include <stddef.h>
+#  include <stddef.h>
 
 ssize_t __getdents (int fd, char *buf, size_t nbytes)
 {
@@ -163,10 +185,10 @@ ssize_t __getdents (int fd, char *buf, size_t nbytes)
     return ret;
 }
 
-#endif
+# endif
 
-#if defined __UCLIBC_HAS_LFS__ && ! defined __NR_getdents64
+# if defined __UCLIBC_HAS_LFS__ && ! defined __NR_getdents64
 strong_alias(__getdents,__getdents64)
-#endif
+# endif
 
 #endif
index aacbe97cc0292405601ecb617ef2fb4022fcaf90..017fa63c186d3ad12b5d26900d492e0731a76127 100644 (file)
@@ -91,7 +91,7 @@ ssize_t __getdents64 (int fd, char *buf, size_t nbytes)
     return (char *) dp - buf;
 }
 
-#if __WORDSIZE == 64
+#if __WORDSIZE == 64 || (defined __UCLIBC_HAS_LFS__ && !defined __NR_getdents)
 /* since getdents doesnt give us d_type but getdents64 does, try and
  * use getdents64 as much as possible */
 strong_alias(__getdents64,__getdents)
This page took 0.032225 seconds and 4 git commands to generate.