apr-0.9.6-readdir64.patch 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. --- apr-1.2.2/include/arch/unix/apr_arch_file_io.h.readdir64
  2. +++ apr-1.2.2/include/arch/unix/apr_arch_file_io.h
  3. @@ -121,11 +124,21 @@
  4. typedef struct stat struct_stat;
  5. #endif
  6. +/* readdir64_r is only used in specific cases: */
  7. +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
  8. + && !defined(READDIR_IS_THREAD_SAFE) && defined(HAVE_READDIR64_R)
  9. +#define APR_USE_READDIR64_R
  10. +#endif
  11. +
  12. struct apr_dir_t {
  13. apr_pool_t *pool;
  14. char *dirname;
  15. DIR *dirstruct;
  16. +#ifdef APR_USE_READDIR64_R
  17. + struct dirent64 *entry;
  18. +#else
  19. struct dirent *entry;
  20. +#endif
  21. };
  22. apr_status_t apr_unix_file_cleanup(void *);
  23. --- apr-1.2.2/file_io/unix/dir.c.readdir64
  24. +++ apr-1.2.2/file_io/unix/dir.c
  25. @@ -77,8 +77,8 @@
  26. * one-byte array. Note: gcc evaluates this at compile time.
  27. */
  28. apr_size_t dirent_size =
  29. - (sizeof((*new)->entry->d_name) > 1 ?
  30. - sizeof(struct dirent) : sizeof (struct dirent) + 255);
  31. + sizeof(*(*new)->entry) +
  32. + (sizeof((*new)->entry->d_name) > 1 ? 0 : 255);
  33. DIR *dir = opendir(dirname);
  34. if (!dir) {
  35. @@ -139,15 +139,34 @@
  36. #endif
  37. #if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \
  38. && !defined(READDIR_IS_THREAD_SAFE)
  39. +#ifdef APR_USE_READDIR64_R
  40. + struct dirent64 *retent;
  41. +
  42. + /* If LFS is enabled and readdir64_r is available, readdir64_r is
  43. + * used in preference to readdir_r. This allows directories to be
  44. + * read which contain a (64-bit) inode number which doesn't fit
  45. + * into the 32-bit apr_ino_t, iff the caller doesn't actually care
  46. + * about the inode number (i.e. wanted & APR_FINFO_INODE == 0).
  47. + * (such inodes may be seen in some wonky NFS environments)
  48. + *
  49. + * Similarly, if the d_off field cannot be reprented in a 32-bit
  50. + * offset, the libc readdir_r() would barf; using readdir64_r
  51. + * bypasses that case entirely since APR does not care about
  52. + * d_off. */
  53. +
  54. + ret = readdir64_r(thedir->dirstruct, thedir->entry, &retent);
  55. +#else
  56. +
  57. struct dirent *retent;
  58. ret = readdir_r(thedir->dirstruct, thedir->entry, &retent);
  59. +#endif
  60. - /* Avoid the Linux problem where at end-of-directory thedir->entry
  61. - * is set to NULL, but ret = APR_SUCCESS.
  62. - */
  63. - if(!ret && thedir->entry != retent)
  64. + /* POSIX treats "end of directory" as a non-error case, so ret
  65. + * will be zero and retent will be set to NULL in that case. */
  66. + if (!ret && retent == NULL) {
  67. ret = APR_ENOENT;
  68. + }
  69. /* Solaris is a bit strange, if there are no more entries in the
  70. * directory, it returns EINVAL. Since this is against POSIX, we
  71. @@ -191,21 +210,38 @@
  72. #endif
  73. #ifdef DIRENT_INODE
  74. if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) {
  75. +#ifdef APR_USE_READDIR64_R
  76. + /* If readdir64_r is used, check for the overflow case of trying
  77. + * to fit a 64-bit integer into a 32-bit integer. */
  78. + if (sizeof(apr_ino_t) >= sizeof(retent->DIRENT_INODE)
  79. + || (apr_ino_t)retent->DIRENT_INODE == retent->DIRENT_INODE) {
  80. + wanted &= ~APR_FINFO_INODE;
  81. + } else {
  82. + /* Prevent the fallback code below from filling in the
  83. + * inode if the stat call fails. */
  84. + retent->DIRENT_INODE = 0;
  85. + }
  86. +#else
  87. wanted &= ~APR_FINFO_INODE;
  88. +#endif /* APR_USE_READDIR64_R */
  89. }
  90. -#endif
  91. +#endif /* DIRENT_INODE */
  92. wanted &= ~APR_FINFO_NAME;
  93. if (wanted)
  94. {
  95. char fspec[APR_PATH_MAX];
  96. - int off;
  97. - apr_cpystrn(fspec, thedir->dirname, sizeof(fspec));
  98. - off = strlen(fspec);
  99. - if ((fspec[off - 1] != '/') && (off + 1 < sizeof(fspec)))
  100. - fspec[off++] = '/';
  101. - apr_cpystrn(fspec + off, thedir->entry->d_name, sizeof(fspec) - off);
  102. + char *end;
  103. +
  104. + end = apr_cpystrn(fspec, thedir->dirname, sizeof fspec);
  105. +
  106. + if (end > fspec && end[-1] != '/' && (end < fspec + APR_PATH_MAX))
  107. + *end++ = '/';
  108. +
  109. + apr_cpystrn(end, thedir->entry->d_name,
  110. + sizeof fspec - (end - fspec));
  111. +
  112. ret = apr_stat(finfo, fspec, APR_FINFO_LINK | wanted, thedir->pool);
  113. /* We passed a stack name that will disappear */
  114. finfo->fname = NULL;
  115. --- apr-1.2.2/file_io/unix/filestat.c.readdir64
  116. +++ apr-1.2.2/file_io/unix/filestat.c
  117. @@ -77,9 +77,18 @@
  118. finfo->user = info->st_uid;
  119. finfo->group = info->st_gid;
  120. finfo->size = info->st_size;
  121. - finfo->inode = info->st_ino;
  122. finfo->device = info->st_dev;
  123. finfo->nlink = info->st_nlink;
  124. +
  125. + /* Check for overflow if storing a 64-bit st_ino in a 32-bit
  126. + * apr_ino_t for LFS builds: */
  127. + if (sizeof(apr_ino_t) >= sizeof(info->st_ino)
  128. + || (apr_ino_t)info->st_ino == info->st_ino) {
  129. + finfo->inode = info->st_ino;
  130. + } else {
  131. + finfo->valid &= ~APR_FINFO_INODE;
  132. + }
  133. +
  134. apr_time_ansi_put(&finfo->atime, info->st_atime);
  135. apr_time_ansi_put(&finfo->mtime, info->st_mtime);
  136. apr_time_ansi_put(&finfo->ctime, info->st_ctime);
  137. --- apr-1.2.2/configure.in.readdir64
  138. +++ apr-1.2.2/configure.in
  139. @@ -1382,6 +1382,10 @@
  140. AC_CHECK_FUNCS(memchr, have_memchr="1", have_memchr="0")
  141. AC_CHECK_FUNC($int64_strfn, have_int64_strfn="1", have_int64_strfn="0")
  142. +if test "$ac_cv_sizeof_long" = "4"; then
  143. + AC_CHECK_FUNCS([readdir64_r])
  144. +fi
  145. +
  146. dnl ----------------------------- We have a fallback position
  147. if test "$have_int64_strfn" = "0" && test "$int64_strfn" = "strtoll"; then
  148. int64_strfn="strtoq"