jorton dd6328
--- apr-1.2.2/include/arch/unix/apr_arch_file_io.h.readdir64
jorton dd6328
+++ apr-1.2.2/include/arch/unix/apr_arch_file_io.h
jorton dd6328
@@ -121,11 +124,21 @@
jorton dd6328
 typedef struct stat struct_stat;
jorton dd6328
 #endif
jorton dd6328
 
jorton dd6328
+/* readdir64_r is only used in specific cases: */
jorton dd6328
+#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
jorton dd6328
+    && !defined(READDIR_IS_THREAD_SAFE) && defined(HAVE_READDIR64_R)
jorton dd6328
+#define APR_USE_READDIR64_R
jorton dd6328
+#endif
jorton dd6328
+
jorton dd6328
 struct apr_dir_t {
jorton dd6328
     apr_pool_t *pool;
jorton dd6328
     char *dirname;
jorton dd6328
     DIR *dirstruct;
jorton dd6328
+#ifdef APR_USE_READDIR64_R
jorton dd6328
+    struct dirent64 *entry;
jorton dd6328
+#else
jorton dd6328
     struct dirent *entry;
jorton dd6328
+#endif
jorton dd6328
 };
jorton dd6328
 
jorton dd6328
 apr_status_t apr_unix_file_cleanup(void *);
jorton dd6328
--- apr-1.2.2/file_io/unix/dir.c.readdir64
jorton dd6328
+++ apr-1.2.2/file_io/unix/dir.c
jorton dd6328
@@ -77,8 +77,8 @@
jorton f0cc37
      * one-byte array.  Note: gcc evaluates this at compile time.
jorton f0cc37
      */
jorton f0cc37
     apr_size_t dirent_size = 
jorton f0cc37
-        (sizeof((*new)->entry->d_name) > 1 ? 
jorton f0cc37
-         sizeof(struct dirent) : sizeof (struct dirent) + 255);
jorton f0cc37
+        sizeof(*(*new)->entry) +
jorton f0cc37
+        (sizeof((*new)->entry->d_name) > 1 ? 0 : 255);
jorton dd6328
     DIR *dir = opendir(dirname);
jorton f0cc37
 
jorton dd6328
     if (!dir) {
jorton dd6328
@@ -139,15 +139,34 @@
jorton f0cc37
 #endif
jorton f0cc37
 #if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
jorton f0cc37
                     && !defined(READDIR_IS_THREAD_SAFE)
jorton dd6328
+#ifdef APR_USE_READDIR64_R
jorton f0cc37
+    struct dirent64 *retent;
jorton f0cc37
+
jorton f0cc37
+    /* If LFS is enabled and readdir64_r is available, readdir64_r is
jorton f0cc37
+     * used in preference to readdir_r.  This allows directories to be
jorton f0cc37
+     * read which contain a (64-bit) inode number which doesn't fit
jorton f0cc37
+     * into the 32-bit apr_ino_t, iff the caller doesn't actually care
jorton f0cc37
+     * about the inode number (i.e. wanted & APR_FINFO_INODE == 0).
jorton f0cc37
+     * (such inodes may be seen in some wonky NFS environments)
jorton f0cc37
+     *
jorton f0cc37
+     * Similarly, if the d_off field cannot be reprented in a 32-bit
jorton f0cc37
+     * offset, the libc readdir_r() would barf; using readdir64_r
jorton f0cc37
+     * bypasses that case entirely since APR does not care about
jorton f0cc37
+     * d_off. */
jorton f0cc37
+
jorton f0cc37
+    ret = readdir64_r(thedir->dirstruct, thedir->entry, &retent);
jorton f0cc37
+#else
jorton f0cc37
+
jorton f0cc37
     struct dirent *retent;
jorton f0cc37
 
jorton f0cc37
     ret = readdir_r(thedir->dirstruct, thedir->entry, &retent);
jorton f0cc37
+#endif
jorton f0cc37
 
jorton dd6328
-    /* Avoid the Linux problem where at end-of-directory thedir->entry
jorton dd6328
-     * is set to NULL, but ret = APR_SUCCESS.
jorton dd6328
-     */
jorton dd6328
-    if(!ret && thedir->entry != retent)
jorton dd6328
+    /* POSIX treats "end of directory" as a non-error case, so ret
jorton dd6328
+     * will be zero and retent will be set to NULL in that case. */
jorton dd6328
+    if (!ret && retent == NULL) {
jorton dd6328
         ret = APR_ENOENT;
jorton dd6328
+    }
jorton dd6328
 
jorton dd6328
     /* Solaris is a bit strange, if there are no more entries in the
jorton dd6328
      * directory, it returns EINVAL.  Since this is against POSIX, we
jorton dd6328
@@ -191,21 +210,38 @@
jorton f0cc37
 #endif
jorton f0cc37
 #ifdef DIRENT_INODE
jorton f0cc37
     if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) {
jorton dd6328
+#ifdef APR_USE_READDIR64_R
jorton f0cc37
+        /* If readdir64_r is used, check for the overflow case of trying
jorton f0cc37
+         * to fit a 64-bit integer into a 32-bit integer. */
jorton f0cc37
+        if (sizeof(apr_ino_t) >= sizeof(retent->DIRENT_INODE)
jorton f0cc37
+            || (apr_ino_t)retent->DIRENT_INODE == retent->DIRENT_INODE) {
jorton f0cc37
+            wanted &= ~APR_FINFO_INODE;
jorton f0cc37
+        } else {
jorton f0cc37
+            /* Prevent the fallback code below from filling in the
jorton f0cc37
+             * inode if the stat call fails. */
jorton f0cc37
+            retent->DIRENT_INODE = 0;
jorton f0cc37
+        }
jorton f0cc37
+#else
jorton f0cc37
         wanted &= ~APR_FINFO_INODE;
jorton dd6328
+#endif /* APR_USE_READDIR64_R */
jorton f0cc37
     }
jorton f0cc37
-#endif
jorton f0cc37
+#endif /* DIRENT_INODE */
jorton f0cc37
 
jorton f0cc37
     wanted &= ~APR_FINFO_NAME;
jorton f0cc37
 
jorton dd6328
     if (wanted)
jorton dd6328
     {
jorton dd6328
         char fspec[APR_PATH_MAX];
jorton dd6328
-        int off;
jorton dd6328
-        apr_cpystrn(fspec, thedir->dirname, sizeof(fspec));
jorton dd6328
-        off = strlen(fspec);
jorton dd6328
-        if ((fspec[off - 1] != '/') && (off + 1 < sizeof(fspec)))
jorton dd6328
-            fspec[off++] = '/';
jorton dd6328
-        apr_cpystrn(fspec + off, thedir->entry->d_name, sizeof(fspec) - off);
jorton dd6328
+        char *end;
jorton dd6328
+
jorton dd6328
+        end = apr_cpystrn(fspec, thedir->dirname, sizeof fspec);
jorton dd6328
+
jorton dd6328
+        if (end > fspec && end[-1] != '/' && (end < fspec + APR_PATH_MAX))
jorton dd6328
+            *end++ = '/';
jorton dd6328
+
jorton dd6328
+        apr_cpystrn(end, thedir->entry->d_name, 
jorton dd6328
+                    sizeof fspec - (end - fspec));
jorton dd6328
+
jorton dd6328
         ret = apr_stat(finfo, fspec, APR_FINFO_LINK | wanted, thedir->pool);
jorton dd6328
         /* We passed a stack name that will disappear */
jorton dd6328
         finfo->fname = NULL;
jorton dd6328
--- apr-1.2.2/file_io/unix/filestat.c.readdir64
jorton dd6328
+++ apr-1.2.2/file_io/unix/filestat.c
jorton f0cc37
@@ -77,9 +77,18 @@
jorton f0cc37
     finfo->user = info->st_uid;
jorton f0cc37
     finfo->group = info->st_gid;
jorton f0cc37
     finfo->size = info->st_size;
jorton f0cc37
-    finfo->inode = info->st_ino;
jorton f0cc37
     finfo->device = info->st_dev;
jorton f0cc37
     finfo->nlink = info->st_nlink;
jorton f0cc37
+
jorton f0cc37
+    /* Check for overflow if storing a 64-bit st_ino in a 32-bit
jorton f0cc37
+     * apr_ino_t for LFS builds: */
jorton f0cc37
+    if (sizeof(apr_ino_t) >= sizeof(info->st_ino)
jorton f0cc37
+        || (apr_ino_t)info->st_ino == info->st_ino) {
jorton f0cc37
+        finfo->inode = info->st_ino;
jorton f0cc37
+    } else {
jorton f0cc37
+        finfo->valid &= ~APR_FINFO_INODE;
jorton f0cc37
+    }
jorton f0cc37
+
jorton f0cc37
     apr_time_ansi_put(&finfo->atime, info->st_atime);
jorton f0cc37
     apr_time_ansi_put(&finfo->mtime, info->st_mtime);
jorton f0cc37
     apr_time_ansi_put(&finfo->ctime, info->st_ctime);
jorton dd6328
--- apr-1.2.2/configure.in.readdir64
jorton dd6328
+++ apr-1.2.2/configure.in
jorton dd6328
@@ -1382,6 +1382,10 @@
jorton f0cc37
 AC_CHECK_FUNCS(memchr, have_memchr="1", have_memchr="0")
jorton dd6328
 AC_CHECK_FUNC($int64_strfn, have_int64_strfn="1", have_int64_strfn="0")
jorton f0cc37
 
jorton f0cc37
+if test "$ac_cv_sizeof_long" = "4"; then
jorton f0cc37
+   AC_CHECK_FUNCS([readdir64_r])
jorton f0cc37
+fi
jorton f0cc37
+
jorton f0cc37
 dnl ----------------------------- We have a fallback position
jorton f0cc37
 if test "$have_int64_strfn" = "0" && test "$int64_strfn" = "strtoll"; then
jorton f0cc37
     int64_strfn="strtoq"