Skip to content

Commit 9cfc2aa

Browse files
committed
Fix directory enumeration on Mac OS X, which had started returning
"Bad file descriptor" in newer Mac OS X versions.
1 parent 938b845 commit 9cfc2aa

File tree

3 files changed

+27
-13
lines changed

3 files changed

+27
-13
lines changed

include/llfio/revision.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
2-
#define LLFIO_PREVIOUS_COMMIT_REF dfe95ff5e36c495df11f9a4420ddeb866be4d658
3-
#define LLFIO_PREVIOUS_COMMIT_DATE "2024-08-20 07:56:43 +00:00"
4-
#define LLFIO_PREVIOUS_COMMIT_UNIQUE dfe95ff5
2+
#define LLFIO_PREVIOUS_COMMIT_REF 938b8456e9d575c4455ddeca5fbe808c040b8c88
3+
#define LLFIO_PREVIOUS_COMMIT_DATE "2024-08-20 11:29:01 +00:00"
4+
#define LLFIO_PREVIOUS_COMMIT_UNIQUE 938b8456

include/llfio/v2.0/detail/impl/posix/directory_handle.ipp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* A handle to a directory
2-
(C) 2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
2+
(C) 2017-2024 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
33
File Created: Aug 2017
44
55
@@ -37,6 +37,11 @@ http://www.boost.org/LICENSE_1_0.txt)
3737
#include <sys/stat.h>
3838
#include <sys/syscall.h>
3939

40+
#ifdef __APPLE__
41+
extern "C" int _getdirentries(int, char *, int, long *);
42+
extern "C" size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep);
43+
#endif
44+
4045
LLFIO_V2_NAMESPACE_BEGIN
4146

4247
result<directory_handle> directory_handle::directory(const path_handle &base, path_view_type path, mode _mode, creation _creation, caching _caching,
@@ -71,7 +76,7 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
7176
#ifdef O_DIRECTORY
7277
attribs |= O_DIRECTORY;
7378
#endif
74-
#ifdef O_SEARCH
79+
#if defined(O_SEARCH) && !defined(__APPLE__) // Newer Mac OS defines this, but setting it breaks enumeration
7580
attribs |= O_SEARCH;
7681
#endif
7782
if(base.is_valid() && path.empty())
@@ -81,7 +86,8 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
8186
path = ".";
8287
}
8388
path_view::zero_terminated_rendered_path<> zpath(path);
84-
auto rename_random_dir_over_existing_dir = [_mode, _caching, flags](const path_handle &base, path_view_type path) -> result<directory_handle> {
89+
auto rename_random_dir_over_existing_dir = [_mode, _caching, flags](const path_handle &base, path_view_type path) -> result<directory_handle>
90+
{
8591
// Take a path handle to the directory containing the file
8692
auto path_parent = path.parent_path();
8793
path_handle dirh;
@@ -343,11 +349,19 @@ result<directory_handle::buffers_type> directory_handle::read(io_request<buffers
343349
using dirent = dirent64;
344350
#endif
345351
#ifdef __APPLE__
346-
// OS X defines a getdirentries64() kernel syscall which can emulate getdents
347352
typedef int (*getdents_emulation_t)(int, char *, unsigned);
348-
static getdents_emulation_t getdents = static_cast<getdents_emulation_t>([](int fd, char *buf, unsigned count) -> int {
349-
off_t foo;
350-
return syscall(SYS_getdirentries64, fd, buf, count, &foo);
353+
static getdents_emulation_t getdents = static_cast<getdents_emulation_t>(
354+
[](int fd, char *buf, unsigned count) -> int
355+
{
356+
#if __DARWIN_64_BIT_INO_T
357+
__darwin_off_t foo = 0;
358+
uint64_t *flags = (uint64_t *) (buf + count - sizeof(uint64_t));
359+
*flags = 0;
360+
return (int) __getdirentries64(fd, buf, count, &foo);
361+
#else
362+
long foo = 0;
363+
return _getdirentries(fd, buf, (int) count, &foo);
364+
#endif
351365
});
352366
#endif
353367
if(!req.buffers._kernel_buffer && req.kernelbuffer.empty())

include/llfio/v2.0/detail/impl/posix/import.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,16 @@ inline result<int> attribs_from_handle_mode_caching_and_flags(native_handle_type
4848
break;
4949
case handle::mode::attr_read:
5050
case handle::mode::read:
51-
attribs = O_RDONLY;
51+
attribs |= O_RDONLY;
5252
nativeh.behaviour |= native_handle_type::disposition::seekable | native_handle_type::disposition::readable;
5353
break;
5454
case handle::mode::attr_write:
5555
case handle::mode::write:
56-
attribs = O_RDWR;
56+
attribs |= O_RDWR;
5757
nativeh.behaviour |= native_handle_type::disposition::seekable | native_handle_type::disposition::readable | native_handle_type::disposition::writable;
5858
break;
5959
case handle::mode::append:
60-
attribs = O_WRONLY | O_APPEND;
60+
attribs |= O_WRONLY | O_APPEND;
6161
nativeh.behaviour |= native_handle_type::disposition::writable | native_handle_type::disposition::append_only;
6262
break;
6363
}

0 commit comments

Comments
 (0)