summaryrefslogtreecommitdiff
path: root/libc/sysdeps
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-02-15 00:43:42 +0000
committerMike Frysinger <vapier@gentoo.org>2006-02-15 00:43:42 +0000
commit40699dc7136c0ffa1d380727a74d7062c4c9557f (patch)
treed9d0be21180d380f65090dfb970b5dad2935f20d /libc/sysdeps
parent45fbae2fffd0d49dd6f07194407c193e2f4bd6ae (diff)
we cant simply alias getdents to getdents64 as they deal with structures of different sizes on 32bit hosts
Diffstat (limited to 'libc/sysdeps')
-rw-r--r--libc/sysdeps/linux/common/getdents.c39
-rw-r--r--libc/sysdeps/linux/common/getdents64.c2
2 files changed, 36 insertions, 5 deletions
diff --git a/libc/sysdeps/linux/common/getdents.c b/libc/sysdeps/linux/common/getdents.c
index 0c6eba658..3faef4bfe 100644
--- a/libc/sysdeps/linux/common/getdents.c
+++ b/libc/sysdeps/linux/common/getdents.c
@@ -24,8 +24,6 @@
* version / arch details.
*/
-#if ! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64
-
libc_hidden_proto(memcpy)
libc_hidden_proto(lseek)
@@ -41,11 +39,14 @@ struct kernel_dirent
char d_name[256];
};
+ssize_t attribute_hidden __getdents (int fd, char *buf, size_t nbytes);
+
+#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);
-ssize_t attribute_hidden __getdents (int fd, char *buf, size_t nbytes);
-ssize_t attribute_hidden __getdents (int fd, char *buf, size_t nbytes)
+ssize_t __getdents (int fd, char *buf, size_t nbytes)
{
struct dirent *dp;
off_t last_offset = -1;
@@ -100,6 +101,34 @@ ssize_t attribute_hidden __getdents (int fd, char *buf, size_t nbytes)
return (char *) dp - buf;
}
-attribute_hidden strong_alias(__getdents,__getdents64)
+#elif __WORDSIZE == 32
+
+libc_hidden_proto(memmove)
+
+extern attribute_hidden __typeof(__getdents) __getdents64;
+ssize_t __getdents (int fd, char *buf, size_t nbytes)
+{
+ struct dirent *dp;
+ struct dirent64 *dp64;
+ ssize_t ret = __getdents64 (fd, buf, nbytes);
+
+ if (ret <= 0)
+ return ret;
+
+ dp64 = (struct dirent64 *) buf;
+ buf += ret;
+ while ((void *) dp64 < (void *) buf) {
+ dp = (struct dirent *) dp64;
+ dp->d_ino = dp64->d_ino;
+ dp->d_off = dp64->d_off;
+ dp->d_reclen = dp64->d_reclen;
+ dp->d_type = dp64->d_type;
+ memmove (dp->d_name, dp64->d_name, dp->d_reclen - offsetof (struct dirent64, d_name));
+ memmove (dp64, dp, dp->d_reclen);
+ dp64 = ((void *) dp64) + dp->d_reclen;
+ }
+
+ return ret;
+}
#endif
diff --git a/libc/sysdeps/linux/common/getdents64.c b/libc/sysdeps/linux/common/getdents64.c
index da193ebab..fcc6903b5 100644
--- a/libc/sysdeps/linux/common/getdents64.c
+++ b/libc/sysdeps/linux/common/getdents64.c
@@ -95,8 +95,10 @@ ssize_t attribute_hidden __getdents64 (int fd, char *buf, size_t nbytes)
return (char *) dp - buf;
}
+#if __WORDSIZE == 64
/* since getdents doesnt give us d_type but getdents64 does, try and
* use getdents64 as much as possible */
attribute_hidden strong_alias(__getdents64,__getdents)
+#endif
#endif /* __UCLIBC_HAS_LFS__ */