];
}
+def DirentAPI : PublicAPI<"dirent.h"> {
+ let Types = [
+ "ino_t",
+ "DIR",
+ "struct dirent",
+ ];
+}
+
def UniStdAPI : PublicAPI<"unistd.h"> {
let Types = ["off_t", "size_t", "ssize_t"];
}
# assert.h entrypoints
# libc.src.assert.__assert_fail
+ # dirent.h entrypoints
+ libc.src.dirent.closedir
+ libc.src.dirent.dirfd
+ libc.src.dirent.opendir
+ libc.src.dirent.readdir
+
# pthread.h entrypoints
libc.src.pthread.pthread_attr_destroy
libc.src.pthread.pthread_attr_init
.llvm_libc_common_h
)
+add_gen_header(
+ dirent
+ DEF_FILE dirent.h.def
+ GEN_HDR dirent.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-types.DIR
+ .llvm-libc-types.ino_t
+ .llvm-libc-types.struct_dirent
+)
+
add_gen_header(
fcntl
DEF_FILE fcntl.h.def
--- /dev/null
+//===-- POSIX header dirent.h ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_DIRENT_H
+#define LLVM_LIBC_DIRENT_H
+
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_DIRENT_H
add_header(cnd_t HDR cnd_t.h)
add_header(cookie_io_functions_t HDR cookie_io_functions_t.h DEPENDS .off64_t)
add_header(double_t HDR double_t.h)
+add_header(DIR HDR DIR.h)
add_header(div_t HDR div_t.h)
add_header(ldiv_t HDR ldiv_t.h)
add_header(lldiv_t HDR lldiv_t.h)
add_header(fexcept_t HDR fexcept_t.h)
add_header(float_t HDR float_t.h)
add_header(imaxdiv_t HDR imaxdiv_t.h)
+add_header(ino_t HDR ino_t.h)
add_header(mode_t HDR mode_t.h)
add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type)
add_header(off_t HDR off_t.h)
add_header(pthread_mutexattr_t HDR pthread_mutexattr_t.h)
add_header(size_t HDR size_t.h)
add_header(ssize_t HDR ssize_t.h)
+add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t)
add_header(struct_sigaction HDR struct_sigaction.h)
add_header(struct_tm HDR struct_tm.h)
add_header(thrd_start_t HDR thrd_start_t.h)
--- /dev/null
+//===-- Definition of the type DIR ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_DIR_H__
+#define __LLVM_LIBC_TYPES_DIR_H__
+
+typedef struct DIR DIR;
+
+#endif // __LLVM_LIBC_TYPES_DIR_H__
--- /dev/null
+//===-- Definition of type ino_t ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_INO_T_H__
+#define __LLVM_LIBC_TYPES_INO_T_H__
+
+typedef unsigned long ino_t;
+
+#endif // __LLVM_LIBC_TYPES_INO_T_H__
--- /dev/null
+//===-- Definition of type struct dirent ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_TYPES_STRUCT_DIRENT_H__
+#define __LLVM_LIBC_TYPES_STRUCT_DIRENT_H__
+
+#include <llvm-libc-types/ino_t.h>
+#include <llvm-libc-types/off_t.h>
+
+struct dirent {
+ ino_t d_ino;
+#ifdef __unix__
+ off_t d_off;
+ unsigned short d_reclen;
+#endif
+ // The user code should use strlen to determine actual the size of d_name.
+ // Likewise, it is incorrect and prohibited by the POSIX standard to detemine
+ // the size of struct dirent type using sizeof. The size should be got using
+ // a different method, for example, from the d_reclen field on Linux.
+ char d_name[1];
+};
+
+#endif // __LLVM_LIBC_TYPES_STRUCT_DIRENT_H__
def PThreadStartT : NamedType<"__pthread_start_t">;
+def InoT : NamedType<"ino_t">;
+def DIR : NamedType<"DIR">;
+def DIRPtr : PtrType<DIR>;
+def DIRRestrictedPtr : RestrictedPtrType<DIR>;
+def StructDirent : NamedType<"struct dirent">;
+def StructDirentPtr : PtrType<StructDirent>;
+def StructDirentPtrPtr : PtrType<StructDirentPtr>;
+def ConstStructDirentPtrPtr : ConstType<StructDirentPtrPtr>;
+
def POSIX : StandardSpec<"POSIX"> {
PtrType CharPtr = PtrType<CharType>;
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
]
>;
+ HeaderSpec Dirent = HeaderSpec<
+ "dirent.h",
+ [], // Macros
+ [InoT, StructDirent, DIR], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "alphasort",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstStructDirentPtrPtr>, ArgSpec<ConstStructDirentPtrPtr>]
+ >,
+ FunctionSpec<
+ "closedir",
+ RetValSpec<IntType>,
+ [ArgSpec<DIRPtr>]
+ >,
+ FunctionSpec<
+ "dirfd",
+ RetValSpec<IntType>,
+ [ArgSpec<DIRPtr>]
+ >,
+ FunctionSpec<
+ "fdopendir",
+ RetValSpec<DIRPtr>,
+ [ArgSpec<IntType>]
+ >,
+ FunctionSpec<
+ "opendir",
+ RetValSpec<DIRPtr>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "readdir",
+ RetValSpec<StructDirentPtr>,
+ [ArgSpec<DIRPtr>]
+ >,
+ ]
+ >;
+
let Headers = [
CType,
+ Dirent,
Errno,
FCntl,
PThread,
add_subdirectory(stdlib)
if(${LIBC_TARGET_OS} STREQUAL "linux")
+ add_subdirectory(dirent)
add_subdirectory(fcntl)
add_subdirectory(pthread)
add_subdirectory(sys)
libc.src.errno.errno
)
+add_object_library(
+ dir
+ SRCS
+ dir.cpp
+ HDRS
+ dir.h
+ DEPENDS
+ libc.src.__support.CPP.array_ref
+ libc.src.__support.threads.mutex
+)
+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}_file.cpp)
add_object_library(
platform_file
)
endif()
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}_dir.cpp)
+ add_object_library(
+ platform_dir
+ SRCS
+ ${LIBC_TARGET_OS}_dir.cpp
+ DEPENDS
+ .dir
+ libc.include.errno
+ libc.include.fcntl
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+ )
+endif()
--- /dev/null
+//===--- Implementation of a platform independent Dir data structure ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "dir.h"
+
+#include <stdlib.h>
+
+namespace __llvm_libc {
+
+Dir *Dir::open(const char *path) {
+ int fd = platform_opendir(path);
+ if (fd < 0)
+ return nullptr;
+
+ Dir *dir = reinterpret_cast<Dir *>(malloc(sizeof(Dir)));
+ dir->fd = fd;
+ dir->readptr = 0;
+ dir->fillsize = 0;
+ Mutex::init(&dir->mutex, false, false, false);
+
+ return dir;
+}
+
+struct ::dirent *Dir::read() {
+ MutexLock lock(&mutex);
+ if (readptr >= fillsize) {
+ fillsize = platform_fetch_dirents(
+ fd, cpp::MutableArrayRef<uint8_t>(buffer, BUFSIZE));
+ if (fillsize == 0)
+ return nullptr;
+ readptr = 0;
+ }
+ struct ::dirent *d = reinterpret_cast<struct ::dirent *>(buffer + readptr);
+#ifdef __unix__
+ // The d_reclen field is available on Linux but not required by POSIX.
+ readptr += d->d_reclen;
+#else
+ // Other platforms have to implement how the read pointer is to be updated.
+#error "DIR read pointer update is missing."
+#endif
+ return d;
+}
+
+int Dir::close() {
+ {
+ MutexLock lock(&mutex);
+ if (!platform_closedir(fd))
+ return -1;
+ }
+ free(this);
+ return 0;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===--- A platform independent Dir class ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_FILE_DIR_H
+#define LLVM_LIBC_SRC_SUPPORT_FILE_DIR_H
+
+#include "src/__support/CPP/ArrayRef.h"
+#include "src/__support/threads/mutex.h"
+
+#include <dirent.h>
+#include <stdlib.h>
+
+namespace __llvm_libc {
+
+// Platform specific function which will open the directory |name|
+// and return its file descriptor. Upon failure, this function sets the errno
+// value as suitable.
+int platform_opendir(const char *name);
+
+// Platform specific function which will close the directory with
+// file descriptor |fd|. Returns true on success, false on failure.
+bool platform_closedir(int fd);
+
+// Platform specific function which will fetch dirents in to buffer.
+// Returns the number of bytes written into buffer
+size_t platform_fetch_dirents(int fd, cpp::MutableArrayRef<uint8_t> buffer);
+
+// This class is designed to allow implementation of the POSIX dirent.h API.
+// By itself, it is platform independent but calls platform specific
+// functions to perform OS operations.
+class Dir {
+ static constexpr size_t BUFSIZE = 1024;
+ int fd;
+ size_t readptr = 0; // The current read pointer.
+ size_t fillsize = 0; // The number of valid bytes availabe in the buffer.
+
+ // This is a buffer of struct dirent values which will be fetched
+ // from the OS. Since the d_name of struct dirent can be of a variable
+ // size, we store the data in a byte array.
+ uint8_t buffer[BUFSIZE];
+
+ Mutex mutex;
+
+public:
+ // A directory is to be opened by the static method open and closed
+ // by the close method. So, all constructors and destructor are declared
+ // as deleted.
+ Dir() = delete;
+ Dir(const Dir &) = delete;
+ ~Dir() = delete;
+
+ Dir &operator=(const Dir &) = delete;
+
+ static Dir *open(const char *path);
+
+ struct ::dirent *read();
+
+ int close();
+
+ int getfd() { return fd; }
+};
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SUPPORT_FILE_DIR_H
--- /dev/null
+//===--- Linux implementation of the Dir helpers --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "dir.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+
+#include <errno.h>
+#include <fcntl.h> // For open flags
+#include <sys/syscall.h> // For syscall numbers
+
+namespace __llvm_libc {
+
+int platform_opendir(const char *name) {
+ int open_flags = O_RDONLY | O_DIRECTORY | O_CLOEXEC;
+#ifdef SYS_open
+ int fd = __llvm_libc::syscall(SYS_open, name, open_flags);
+#elif defined(SYS_openat)
+ int fd = __llvm_libc::syscall(SYS_openat, AT_FDCWD, name, open_flags);
+#else
+#error \
+ "SYS_open and SYS_openat syscalls not available to perform an open operation."
+#endif
+
+ if (fd < 0) {
+ errno = -fd;
+ return -1;
+ }
+ return fd;
+}
+
+size_t platform_fetch_dirents(int fd, cpp::MutableArrayRef<uint8_t> buffer) {
+ long size =
+ __llvm_libc::syscall(SYS_getdents, fd, buffer.data(), buffer.size());
+ if (size < 0) {
+ errno = -size;
+ return 0;
+ }
+ return size;
+}
+
+bool platform_closedir(int fd) {
+ long ret = __llvm_libc::syscall(SYS_close, fd);
+ if (ret < 0) {
+ errno = -ret;
+ return false;
+ }
+ return true;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+add_entrypoint_object(
+ opendir
+ SRCS
+ opendir.cpp
+ HDRS
+ opendir.h
+ DEPENDS
+ libc.include.dirent
+ libc.src.__support.File.dir
+ libc.src.__support.File.platform_dir
+)
+
+add_entrypoint_object(
+ dirfd
+ SRCS
+ dirfd.cpp
+ HDRS
+ dirfd.h
+ DEPENDS
+ libc.include.dirent
+ libc.src.__support.File.dir
+ libc.src.__support.File.platform_dir
+)
+
+add_entrypoint_object(
+ closedir
+ SRCS
+ closedir.cpp
+ HDRS
+ closedir.h
+ DEPENDS
+ libc.include.dirent
+ libc.src.__support.File.dir
+ libc.src.__support.File.platform_dir
+)
+
+add_entrypoint_object(
+ readdir
+ SRCS
+ readdir.cpp
+ HDRS
+ readdir.h
+ DEPENDS
+ libc.include.dirent
+ libc.src.__support.File.dir
+ libc.src.__support.File.platform_dir
+)
--- /dev/null
+//===-- Implementation of closedir ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "closedir.h"
+
+#include "src/__support/File/dir.h"
+#include "src/__support/common.h"
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, closedir, (::DIR * dir)) {
+ auto *d = reinterpret_cast<__llvm_libc::Dir *>(dir);
+ return d->close();
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header of closedir -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_DIRENT_CLOSEDIR_H
+#define LLVM_LIBC_SRC_DIRENT_CLOSEDIR_H
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+int closedir(::DIR *dir);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_DIRENT_CLOSEDIR_H
--- /dev/null
+//===-- Implementation of dirfd -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "dirfd.h"
+
+#include "src/__support/File/dir.h"
+#include "src/__support/common.h"
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, dirfd, (::DIR * dir)) {
+ auto *d = reinterpret_cast<__llvm_libc::Dir *>(dir);
+ return d->getfd();
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header of dirfd --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_DIRENT_DIRFD_H
+#define LLVM_LIBC_SRC_DIRENT_DIRFD_H
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+int dirfd(::DIR *dir);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_DIRENT_DIRFD_H
--- /dev/null
+//===-- Implementation of opendir -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "opendir.h"
+
+#include "src/__support/File/dir.h"
+#include "src/__support/common.h"
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(::DIR *, opendir, (const char *name)) {
+ return reinterpret_cast<::DIR *>(Dir::open(name));
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header of opendir ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_DIRENT_OPENDIR_H
+#define LLVM_LIBC_SRC_DIRENT_OPENDIR_H
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+::DIR *opendir(const char *name);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_DIRENT_OPENDIR_H
--- /dev/null
+//===-- Implementation of readdir -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "readdir.h"
+
+#include "src/__support/File/dir.h"
+#include "src/__support/common.h"
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(struct ::dirent *, readdir, (::DIR * dir)) {
+ auto *d = reinterpret_cast<__llvm_libc::Dir *>(dir);
+ return d->read();
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header of readdir ------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_DIRENT_READDIR_H
+#define LLVM_LIBC_SRC_DIRENT_READDIR_H
+
+#include <dirent.h>
+
+namespace __llvm_libc {
+
+struct ::dirent *readdir(DIR *dir);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_DIRENT_READDIR_H
return()
endif()
+add_subdirectory(dirent)
# The signal API is currently disabled as signal.h is incorrect.
# since assert uses the signal API, we disable assert also.
# add_subdirectory(assert)
--- /dev/null
+add_subdirectory(testdata)
+add_libc_testsuite(libc_dirent_unittests)
+
+add_libc_unittest(
+ dirent_test
+ SUITE
+ libc_dirent_unittests
+ SRCS
+ dirent_test.cpp
+ DEPENDS
+ libc.include.dirent
+ libc.src.__support.CPP.string_view
+ libc.src.dirent.closedir
+ libc.src.dirent.dirfd
+ libc.src.dirent.opendir
+ libc.src.dirent.readdir
+)
+
--- /dev/null
+//===-- Unittests for functions from POSIX dirent.h -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/StringView.h"
+#include "src/dirent/closedir.h"
+#include "src/dirent/dirfd.h"
+#include "src/dirent/opendir.h"
+#include "src/dirent/readdir.h"
+
+#include "utils/UnitTest/Test.h"
+
+#include <dirent.h>
+#include <errno.h>
+
+using StringView = __llvm_libc::cpp::StringView;
+
+TEST(LlvmLibcDirentTest, SimpleOpenAndRead) {
+ ::DIR *dir = __llvm_libc::opendir("testdata");
+ ASSERT_TRUE(dir != nullptr);
+ // The file descriptors 0, 1 and 2 are reserved for standard streams.
+ // So, the file descriptor for the newly opened directory should be
+ // greater than 2.
+ ASSERT_GT(__llvm_libc::dirfd(dir), 2);
+
+ struct ::dirent *file1, *file2, *dir1, *dir2;
+ while (true) {
+ struct ::dirent *d = __llvm_libc::readdir(dir);
+ if (d == nullptr)
+ break;
+ if (StringView(d->d_name).equals("file1.txt"))
+ file1 = d;
+ if (StringView(d->d_name).equals("file2.txt"))
+ file2 = d;
+ if (StringView(d->d_name).equals("dir1"))
+ dir1 = d;
+ if (StringView(d->d_name).equals("dir2.txt"))
+ dir2 = d;
+ }
+
+ // Verify that we don't break out of the above loop in error.
+ ASSERT_EQ(errno, 0);
+
+ ASSERT_TRUE(file1 != nullptr);
+ ASSERT_TRUE(file2 != nullptr);
+ ASSERT_TRUE(dir1 != nullptr);
+ ASSERT_TRUE(dir2 != nullptr);
+
+ ASSERT_EQ(__llvm_libc::closedir(dir), 0);
+}
+
+TEST(LlvmLibcDirentTest, OpenNonExistentDir) {
+ errno = 0;
+ ::DIR *dir = __llvm_libc::opendir("___xyz123__.non_existent__");
+ ASSERT_TRUE(dir == nullptr);
+ ASSERT_EQ(errno, ENOENT);
+ errno = 0;
+}
+
+TEST(LlvmLibcDirentTest, OpenFile) {
+ errno = 0;
+ ::DIR *dir = __llvm_libc::opendir("testdata/file1.txt");
+ ASSERT_TRUE(dir == nullptr);
+ ASSERT_EQ(errno, ENOTDIR);
+ errno = 0;
+}
--- /dev/null
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/file1.txt)
+file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/file2.txt)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dir1)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dir2)