Преглед на файлове

we cant simply alias getdents to getdents64 as they deal with structures of different sizes on 32bit hosts

Mike Frysinger преди 20 години
родител
ревизия
40699dc713
променени са 2 файла, в които са добавени 36 реда и са изтрити 5 реда
  1. 34 5
      libc/sysdeps/linux/common/getdents.c
  2. 2 0
      libc/sysdeps/linux/common/getdents64.c

+ 34 - 5
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

+ 2 - 0
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__ */