+ /*
+ * sufficiently recent kernels when the buffer is large enough,
+ * will use the last bytes of the buffer to return status.
+ *
+ * To support older kernels:
+ * - make sure it's 0 initialized
+ * - make sure it's past `dd_size` before reading it
+ */
+ getdirentries64_flags_t *gdeflags =
+ (getdirentries64_flags_t *)(dirp->dd_buf + dirp->dd_len -
+ sizeof(getdirentries64_flags_t));
+ *gdeflags = 0;
+ dirp->dd_size = (long)__getdirentries64(dirp->dd_fd,
+ dirp->dd_buf, dirp->dd_len, &dirp->dd_td->seekoff);
+ if (dirp->dd_size >= 0 &&
+ dirp->dd_size <= dirp->dd_len - sizeof(getdirentries64_flags_t)) {
+ if (*gdeflags & GETDIRENTRIES64_EOF) {
+ dirp->dd_flags |= __DTF_ATEND;
+ }
+ }
+#else /* !__DARWIN_64_BIT_INO_T */
+ dirp->dd_size = _getdirentries(dirp->dd_fd,
+ dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
+#endif /* __DARWIN_64_BIT_INO_T */
+ if (dirp->dd_size < 0) {
+ if (errno == EINVAL)
+ errno = ENOTDIR;
+ goto fail;
+ }
+ dirp->dd_flags |= __DTF_SKIPREAD;
+ } else {
+ dirp->dd_size = 0;
+#if __DARWIN_64_BIT_INO_T
+ dirp->dd_td->seekoff = 0;