[libc-commits] [libc] Nftw (PR #120969)
Jeff Bailey via libc-commits
libc-commits at lists.llvm.org
Mon Dec 23 06:17:45 PST 2024
https://github.com/kaladron created https://github.com/llvm/llvm-project/pull/120969
None
>From 33312f1c705395c6b6b65f594291332365a4a7bb Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Wed, 11 Sep 2024 09:21:08 +0000
Subject: [PATCH 1/7] Initial check-in of infrastructure to support ftw/nftw
---
libc/config/linux/x86_64/entrypoints.txt | 5 ++++-
libc/include/CMakeLists.txt | 9 +++++++++
libc/include/ftw.h.def | 16 ++++++++++++++++
libc/newhdrgen/yaml/ftw.h | 15 +++++++++++++++
libc/src/CMakeLists.txt | 1 +
libc/src/ftw/CMakeLists.txt | 11 +++++++++++
libc/src/ftw/ftw.cpp | 1 +
libc/src/ftw/ftw.h | 20 ++++++++++++++++++++
libc/test/src/CMakeLists.txt | 1 +
libc/test/src/ftw/CMakeLists.txt | 11 +++++++++++
libc/test/src/ftw/ftw_test.cpp | 1 +
11 files changed, 90 insertions(+), 1 deletion(-)
create mode 100644 libc/include/ftw.h.def
create mode 100644 libc/newhdrgen/yaml/ftw.h
create mode 100644 libc/src/ftw/CMakeLists.txt
create mode 100644 libc/src/ftw/ftw.cpp
create mode 100644 libc/src/ftw/ftw.h
create mode 100644 libc/test/src/ftw/CMakeLists.txt
create mode 100644 libc/test/src/ftw/ftw_test.cpp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3fd88fc0020e55..26226215b36394 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -32,6 +32,9 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.fcntl.open
libc.src.fcntl.openat
+ # ftw.h entrypoints
+ libc.src.ftw.ftw
+
# sched.h entrypoints
libc.src.sched.sched_get_priority_max
libc.src.sched.sched_get_priority_min
@@ -408,7 +411,7 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fabs
libc.src.math.fabsf
libc.src.math.fabsl
- libc.src.math.fadd
+ libc.src.math.fadd
libc.src.math.faddl
libc.src.math.fadd
libc.src.math.fdim
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index dfa5063889e8ab..c281d9d9f76c07 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -76,6 +76,15 @@ add_header_macro(
.llvm_libc_common_h
)
+add_header_macro(
+ ftw
+ ../libc/newhdrgen/yaml/ftw.yaml
+ ftw.h.def
+ ftw.h
+ DEPENDS
+ .llvm_libc_common_h
+)
+
add_header_macro(
dlfcn
../libc/newhdrgen/yaml/dlfcn.yaml
diff --git a/libc/include/ftw.h.def b/libc/include/ftw.h.def
new file mode 100644
index 00000000000000..af3be565653192
--- /dev/null
+++ b/libc/include/ftw.h.def
@@ -0,0 +1,16 @@
+//===-- C standard library header ftw.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_FTW_H
+#define LLVM_LIBC_FTW_H
+
+#include "__llvm-libc-common.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_FTW_H
diff --git a/libc/newhdrgen/yaml/ftw.h b/libc/newhdrgen/yaml/ftw.h
new file mode 100644
index 00000000000000..37b44834d56c35
--- /dev/null
+++ b/libc/newhdrgen/yaml/ftw.h
@@ -0,0 +1,15 @@
+header: fcntl.h
+macros: []
+types: []
+enums: []
+objects: []
+functions:
+ - name: ftw
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: const char *
+ - type: int
+ - type: int
+
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index d554c12fb1ec89..3a3b19482dae3a 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -4,6 +4,7 @@ add_subdirectory(ctype)
add_subdirectory(dlfcn)
add_subdirectory(errno)
add_subdirectory(fenv)
+add_subdirectory(ftw)
add_subdirectory(inttypes)
add_subdirectory(math)
add_subdirectory(stdbit)
diff --git a/libc/src/ftw/CMakeLists.txt b/libc/src/ftw/CMakeLists.txt
new file mode 100644
index 00000000000000..a9e219b8bdb45a
--- /dev/null
+++ b/libc/src/ftw/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_entrypoint_object(
+ ftw
+ SRCS
+ ftw.cpp
+ HDRS
+ ftw.h
+ DEPENDS
+ libc.src.__support.FPUtil.fenv_impl
+ COMPILE_OPTIONS
+ -O2
+)
diff --git a/libc/src/ftw/ftw.cpp b/libc/src/ftw/ftw.cpp
new file mode 100644
index 00000000000000..44833b1b607bcc
--- /dev/null
+++ b/libc/src/ftw/ftw.cpp
@@ -0,0 +1 @@
+#error "I got here!"
diff --git a/libc/src/ftw/ftw.h b/libc/src/ftw/ftw.h
new file mode 100644
index 00000000000000..107bd97fc1a2e7
--- /dev/null
+++ b/libc/src/ftw/ftw.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of ftw ----------------------------*- 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_FTW_FTW_H
+#define LLVM_LIBC_SRC_FTW_FTW_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int ftw(const char* dirpath, int noopenfd, int flags);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_FTW_FTW_H
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index ddc6a5c7f6965f..9fc89f88492a15 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -50,6 +50,7 @@ add_subdirectory(__support)
add_subdirectory(ctype)
add_subdirectory(errno)
add_subdirectory(fenv)
+add_subdirectory(ftw)
add_subdirectory(math)
add_subdirectory(search)
add_subdirectory(stdbit)
diff --git a/libc/test/src/ftw/CMakeLists.txt b/libc/test/src/ftw/CMakeLists.txt
new file mode 100644
index 00000000000000..a2b655f6ff272b
--- /dev/null
+++ b/libc/test/src/ftw/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_custom_target(libc_ftw_unittests)
+
+add_libc_unittest(
+ ftw_test
+ SUITE
+ libc_ftw_unittests
+ SRCS
+ ftw_test.cpp
+ DEPENDS
+ libc.src.errno.errno
+)
diff --git a/libc/test/src/ftw/ftw_test.cpp b/libc/test/src/ftw/ftw_test.cpp
new file mode 100644
index 00000000000000..44833b1b607bcc
--- /dev/null
+++ b/libc/test/src/ftw/ftw_test.cpp
@@ -0,0 +1 @@
+#error "I got here!"
>From bc9626810e2eefde2dc93d723b4797e026d5a620 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Thu, 12 Sep 2024 10:27:43 +0000
Subject: [PATCH 2/7] Move raman's code into the empty files.
This currently doesn't build - it's just in the right places to work on it more.
---
libc/src/ftw/ftw.cpp | 194 ++++++++++++++++++++++++++-
libc/test/src/ftw/ftw_test.cpp | 237 ++++++++++++++++++++++++++++++++-
2 files changed, 429 insertions(+), 2 deletions(-)
diff --git a/libc/src/ftw/ftw.cpp b/libc/src/ftw/ftw.cpp
index 44833b1b607bcc..97018a198516d7 100644
--- a/libc/src/ftw/ftw.cpp
+++ b/libc/src/ftw/ftw.cpp
@@ -1 +1,193 @@
-#error "I got here!"
+//
+// https://man7.org/linux/man-pages/man3/ftw.3.html
+//
+
+/*
+ * -----
+ * Build
+ * -----
+ * cd ..../google3/experimental/users/rtenneti/llvm_libc/
+ * make
+ *
+ * ------------
+ * How to Test:
+ * ------------
+ * make test
+ */
+
+#include "nftw.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stddef.h> // size_t
+#include <stdint.h> // int8_t, int16_t and int32_t
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <cstdio>
+#include <cstring>
+#include <filesystem> // NOLINT
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <optional>
+#include <string_view>
+
+namespace {
+class Func {
+ public:
+ virtual int call(const char*, const struct stat*, int, struct FTW*) = 0;
+};
+
+using nftwFn = int (*)(const char* filePath, const struct stat* statBuf,
+ int tFlag, struct FTW* ftwbuf);
+
+using ftwFn = int (*)(const char* filePath, const struct stat* statBuf,
+ int tFlag);
+
+class NftwFunc : public Func {
+ public:
+ NftwFunc(nftwFn fn) : fn(fn) {}
+ virtual int call(const char* dirPath, const struct stat* statBuf, int tFlag,
+ struct FTW* ftwBuf) override {
+ return fn(dirPath, statBuf, tFlag, ftwBuf);
+ }
+
+ private:
+ const nftwFn fn;
+};
+
+class FtwFunc : public Func {
+ public:
+ FtwFunc(ftwFn fn) : fn(fn) {}
+ virtual int call(const char* dirPath, const struct stat* statBuf, int tFlag,
+ struct FTW*) override {
+ return fn(dirPath, statBuf, tFlag);
+ }
+
+ private:
+ const ftwFn fn;
+};
+
+int doMergedFtw(const std::string& dirPath, Func& fn, int fdLimit, int flags,
+ int level) {
+ // fdLimit specifies the maximum number of directories that ftw()
+ // will hold open simultaneously. When a directory is opened, fdLimit is
+ // decreased and if it becomes 0 or less, we won't open any more directories.
+ if (fdLimit <= 0) {
+ return 0;
+ }
+
+ // Determine the type of path that is passed.
+ int typeFlag;
+ struct stat statBuf;
+ if (flags & FTW_PHYS) {
+ if (lstat(dirPath.c_str(), &statBuf) < 0) return -1;
+ } else {
+ if (stat(dirPath.c_str(), &statBuf) < 0) {
+ if (!lstat(dirPath.c_str(), &statBuf)) {
+ typeFlag = FTW_SLN; /* Symbolic link pointing to a nonexistent file. */
+ } else if (errno != EACCES) {
+ /* stat failed with an errror that is not Permission denied */
+ return -1;
+ } else {
+ /* The probable cause for the failure is that the caller had read
+ * permission on the parent directory, so that the filename fpath could
+ * be seen, but did not have execute permission on the directory.
+ */
+ typeFlag = FTW_NS;
+ }
+ }
+ }
+
+ if (S_ISDIR(statBuf.st_mode)) {
+ if (flags & FTW_DEPTH) {
+ typeFlag = FTW_DP; /* Directory, all subdirs have been visited. */
+ } else {
+ typeFlag = FTW_D; /* Directory. */
+ }
+ } else if (S_ISLNK(statBuf.st_mode)) {
+ if (flags & FTW_PHYS) {
+ typeFlag = FTW_SL; /* Symbolic link. */
+ } else {
+ typeFlag = FTW_SLN; /* Symbolic link pointing to a nonexistent file. */
+ }
+ } else {
+ typeFlag = FTW_F; /* Regular file. */
+ }
+
+ struct FTW ftwBuf;
+ // Find the base by finding the last slash.
+ std::size_t slash_found = dirPath.rfind("/");
+ if (slash_found != std::string::npos) {
+ ftwBuf.base = slash_found + 1;
+ }
+
+ ftwBuf.level = level;
+
+ // If the dirPath is a file, call the function on it and return.
+ if ((typeFlag == FTW_SL) || (typeFlag == FTW_F)) {
+ int returnValue = fn.call(dirPath.c_str(), &statBuf, typeFlag, &ftwBuf);
+ if (returnValue) {
+ return returnValue;
+ }
+ return 0;
+ }
+
+ // If FTW_DEPTH is not set, nftw() shall report any directory before reporting
+ // the files in that directory.
+ if (!(flags & FTW_DEPTH)) {
+ // Call the function on the directory.
+ int directory_fd = open(dirPath.c_str(), O_RDONLY);
+ if (directory_fd < 0 && errno == EACCES) {
+ typeFlag = FTW_DNR; /* Directory can't be read. */
+ }
+ close(directory_fd);
+
+ int returnValue = fn.call(dirPath.c_str(), &statBuf, typeFlag, &ftwBuf);
+ if (returnValue) {
+ return returnValue;
+ }
+ }
+
+ for (std::error_code ec; auto const& dir_entry :
+ std::filesystem::directory_iterator(dirPath, ec)) {
+ if (ec) continue;
+ int returnValue =
+ doMergedFtw(dir_entry.path(), fn, fdLimit - 1, flags, ftwBuf.level + 1);
+ if (returnValue) {
+ return returnValue;
+ }
+ }
+
+ // If FTW_DEPTH is set, nftw() shall report all files in a directory before
+ // reporting the directory itself.
+ if (flags & FTW_DEPTH) {
+ // Call the function on the directory.
+ return fn.call(dirPath.c_str(), &statBuf, typeFlag, &ftwBuf);
+ }
+ return 0;
+}
+} // namespace
+
+int llvm_libc_nftw(const std::string& dirPath,
+ int (*fn)(const char* filePath, const struct stat* statBuf,
+ int tFlag, struct FTW* ftwbuf),
+ int fdLimit, int flags) {
+ NftwFunc wrappedFn{fn};
+ return doMergedFtw(dirPath, wrappedFn, fdLimit, flags, 0);
+}
+
+int llvm_libc_ftw(const std::string &dirPath,
+ int (*fn)(const char *filePath, const struct stat *statBuf,
+ int tFlag),
+ int fdLimit) {
+ return llvm_libc_nftw(dirPath, (int (*)())fn, fdLimit, FTW_PHYS, 0);
+}
diff --git a/libc/test/src/ftw/ftw_test.cpp b/libc/test/src/ftw/ftw_test.cpp
index 44833b1b607bcc..9b93e49cb36bce 100644
--- a/libc/test/src/ftw/ftw_test.cpp
+++ b/libc/test/src/ftw/ftw_test.cpp
@@ -1 +1,236 @@
-#error "I got here!"
+// Test code starts here
+
+//nftw test code:
+
+namespace fs = std::filesystem;
+
+class TemporaryDirectory {
+ public:
+ TemporaryDirectory() {
+ fs::path temp_path = fs::temp_directory_path();
+ std::string temp_path_prefix = temp_path.string() + "/tmpdir.XXXXXX";
+ // Use data() to get a writable string. mkdtemp doesn't write beyond the
+ // allocated data.
+ char* dir_name = mkdtemp(temp_path_prefix.data());
+ _path = dir_name;
+ fs::current_path(_path);
+ }
+
+ ~TemporaryDirectory() {
+ fs::current_path(_path);
+ fs::remove_all(_path);
+ }
+ const std::string GetDirectoryPath() { return _path.c_str(); }
+
+ private:
+ fs::path _path;
+};
+
+static void setupTestData() {
+ fs::create_directories("sandbox");
+ fs::create_directory("sandbox/owner_all_group_read_others_read_dir");
+ fs::permissions("sandbox/owner_all_group_read_others_read_dir",
+ fs::perms::owner_all | fs::perms::group_read |
+ fs::perms::group_exec | fs::perms::others_read |
+ fs::perms::others_exec,
+ fs::perm_options::add);
+ fs::create_directory(
+ "sandbox/owner_all_group_read_others_read_dir/"
+ "owner_read_group_read_others_read_dir");
+ fs::permissions(
+ "sandbox/owner_all_group_read_others_read_dir/"
+ "owner_read_group_read_others_read_dir",
+ fs::perms::owner_read | fs::perms::owner_exec | fs::perms::group_read |
+ fs::perms::group_exec | fs::perms::others_read |
+ fs::perms::others_exec,
+ fs::perm_options::add);
+ fs::create_directory("sandbox/no_perm_dir");
+ fs::permissions("sandbox/no_perm_dir", fs::perms::none,
+ fs::perm_options::add);
+
+ fs::create_symlink("invalid_target", "sandbox/sym1");
+ fs::create_directory_symlink("owner_all_group_read_others_read_dir",
+ "sandbox/sym2");
+
+ std::ofstream ofs("sandbox/file"); // create regular file
+}
+
+static bool isReadable(const fs::path& p) {
+ std::error_code ec; // For noexcept overload usage.
+ auto perms = fs::status(p, ec).permissions();
+ if ((perms & fs::perms::owner_read) != fs::perms::none &&
+ (perms & fs::perms::group_read) != fs::perms::none &&
+ (perms & fs::perms::others_read) != fs::perms::none) {
+ return true;
+ }
+ return false;
+}
+
+static int checkNftw(const char* arg_fpath, const struct stat* statBuf,
+ int typeFlag, struct FTW* ftwbuf) {
+ displayInfo(arg_fpath, statBuf, typeFlag, ftwbuf);
+ if (arg_fpath == NULL) {
+ std::cout << " fpath is null\n";
+ return -1;
+ }
+ std::string fpath = arg_fpath;
+ if (statBuf == NULL) {
+ std::cout << " stat is null " << fpath << "\n";
+ return -1;
+ }
+
+ const fs::path path = fpath;
+
+ // status says we don't know the status of this file.
+ if (typeFlag == FTW_NS || typeFlag == FTW_SLN) {
+ struct stat sb;
+ // Verify we can't stat the path.
+ if (-1 != stat(arg_fpath, &sb)) {
+ std::cout << "status doesn't match for " << arg_fpath << "\n";
+ return -1;
+ }
+ return 0;
+ }
+
+ // If it is directory
+ if (S_ISDIR(statBuf->st_mode)) {
+ if (!fs::is_directory(fs::status(path))) {
+ std::cout << "Is not directory> " << fpath << "\n";
+ return -1;
+ }
+ if (isReadable(fpath)) {
+ // It is readable, verify typeFlag is correct.
+ if (typeFlag != FTW_D && typeFlag != FTW_DP) {
+ std::cout << "typeFlag != FTW_D && typeFlag != FTW_DP " << fpath
+ << "\n";
+ return -1;
+ }
+ return 0;
+ }
+ // It is not readable, and verify typeFlag is correct.
+ if (typeFlag != FTW_DNR && typeFlag != FTW_D) {
+ std::cout << "typeFlag != FTW_DNR && typeFlag != FTW_D " << fpath << "\n";
+ return -1;
+ }
+ return 0;
+ }
+
+ // If it symlink, verify the filestatus and verify typeFlag is correct.
+ if (S_ISLNK(statBuf->st_mode)) {
+ if (!fs::is_symlink(fs::status(path))) {
+ std::cout << "Is not symlink" << fpath << "\n";
+ return -1;
+ }
+ if (FTW_SL != typeFlag) {
+ std::cout << " FTW_SL != typeFlag " << fpath << "\n";
+ return -1;
+ }
+ return 0;
+ }
+
+ if (!fs::is_regular_file(fs::status(path))) {
+ std::cout << " is not a regular file " << fpath << "\n";
+ return -1;
+ }
+ if (FTW_F != typeFlag) {
+ std::cout << " FTW_SL != typeFlag " << fpath << "\n";
+ return -1;
+ }
+ return 0; /* To tell llvm_libc_nftw() to continue */
+}
+
+static void testNftw() {
+ std::cout << std::endl << "Calling testNftw: " << std::endl;
+ TemporaryDirectory tmpDir = TemporaryDirectory();
+ setupTestData();
+ int flags = 0;
+ llvm_libc_nftw(tmpDir.GetDirectoryPath(), checkNftw, 128, flags);
+ std::cout << "All testNftw tests have passed: " << std::endl;
+}
+
+int main(int argc, char* argv[]) {
+ std::cout << "ftw called with args: " << argv[1] << std::endl;
+
+ int flags = 0;
+
+ if (argc > 2) {
+ if (strchr(argv[2], 'p') != NULL) flags |= FTW_PHYS;
+ if (strchr(argv[2], 'd') != NULL) flags |= FTW_DEPTH;
+ } else {
+ flags |= FTW_DEPTH;
+ }
+
+ std::cout << "Calling nftw: " << std::endl;
+ if (nftw((argc < 2) ? "." : argv[1], displayInfo, 20, flags) == -1) {
+ perror("nftw");
+ exit(EXIT_FAILURE);
+ }
+
+ std::cout << "Calling llvm_libc_nftw: " << std::endl;
+ std::string_view dirPath(argv[1]);
+ if (llvm_libc_nftw((argc < 2) ? "." : argv[1], displayInfo, 20, flags) ==
+ -1) {
+ perror("llvm_libc_nftw");
+ exit(EXIT_FAILURE);
+ }
+
+ // Unit tests for FTW.
+ testNftw();
+
+ exit(EXIT_SUCCESS);
+}
+
+// ftw test code:
+
+
+static int display_info(const char *filePath, const struct stat *sb, int tflag,
+ struct FTW *ftwbuf) {
+ printf("%-3s %2d ",
+ (tflag == FTW_D) ? "d"
+ : (tflag == FTW_DNR) ? "dnr"
+ : (tflag == FTW_DP) ? "dp"
+ : (tflag == FTW_F) ? "f"
+ : (tflag == FTW_NS) ? "ns"
+ : (tflag == FTW_SL) ? "sl"
+ : (tflag == FTW_SLN) ? "sln"
+ : "???",
+ ftwbuf->level);
+
+ if (tflag == FTW_NS)
+ printf("-------");
+ else
+ printf("%7jd", (intmax_t)sb->st_size);
+
+ printf(" %-40s %d %s\n", filePath, ftwbuf->base, filePath + ftwbuf->base);
+
+ return 0; /* To tell llvm_libc_nftw() to continue */
+}
+
+int main(int argc, char *argv[]) {
+ std::cout << "ftw called with args: " << argv[1] << std::endl;
+
+ int flags = 0;
+
+ if (argc > 2) {
+ if (strchr(argv[2], 'p') != NULL) flags |= FTW_PHYS;
+ if (strchr(argv[2], 'd') != NULL) flags |= FTW_DEPTH;
+ } else {
+ flags |= FTW_DEPTH;
+ }
+
+ std::cout << "Calling nftw: " << std::endl;
+ if (ftw((argc < 2) ? "." : argv[1], display_info, 20) == -1) {
+ perror("nftw");
+ exit(EXIT_FAILURE);
+ }
+
+ std::cout << "Calling llvm_libc_nftw: " << std::endl;
+ std::string_view dirPath(argv[1]);
+ if (llvm_libc_ftw((argc < 2) ? "." : argv[1], display_info, 20) == -1) {
+ perror("llvm_libc_nftw");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
>From 975b3a1a2cbd6d7a1fa36232a0761a68752aef73 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Fri, 13 Sep 2024 09:55:26 +0000
Subject: [PATCH 3/7] Fix comment header, replace includes with llvm libc
includes. Fix namespace for some things (we don't use std::) Add virtual
destructors for Func. Fixup ftw to call domerged directly.
---
libc/src/ftw/ftw.cpp | 82 +++++++++++++++++---------------------------
1 file changed, 32 insertions(+), 50 deletions(-)
diff --git a/libc/src/ftw/ftw.cpp b/libc/src/ftw/ftw.cpp
index 97018a198516d7..626acd6d2105a7 100644
--- a/libc/src/ftw/ftw.cpp
+++ b/libc/src/ftw/ftw.cpp
@@ -1,49 +1,26 @@
+//===-- Implementation of ftw function ------------------------------------===//
//
-// https://man7.org/linux/man-pages/man3/ftw.3.html
+// 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
//
+//===----------------------------------------------------------------------===//
-/*
- * -----
- * Build
- * -----
- * cd ..../google3/experimental/users/rtenneti/llvm_libc/
- * make
- *
- * ------------
- * How to Test:
- * ------------
- * make test
- */
-
-#include "nftw.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <pthread.h>
-#include <stddef.h> // size_t
-#include <stdint.h> // int8_t, int16_t and int32_t
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
+#include "src/ftw/ftw.h"
+
+#include "src/__support/common.h"
+#include "src/__support/CPP/string.h"
+#include "src/errno/libc_errno.h"
+
+#include <stddef.h>
#include <sys/stat.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <cstdio>
-#include <cstring>
-#include <filesystem> // NOLINT
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <optional>
-#include <string_view>
-
-namespace {
+
+
+namespace LIBC_NAMESPACE_DECL {
class Func {
public:
virtual int call(const char*, const struct stat*, int, struct FTW*) = 0;
+ virtual ~Func() = 0;
};
using nftwFn = int (*)(const char* filePath, const struct stat* statBuf,
@@ -59,6 +36,7 @@ class NftwFunc : public Func {
struct FTW* ftwBuf) override {
return fn(dirPath, statBuf, tFlag, ftwBuf);
}
+ virtual ~NftwFunc() {}
private:
const nftwFn fn;
@@ -71,12 +49,13 @@ class FtwFunc : public Func {
struct FTW*) override {
return fn(dirPath, statBuf, tFlag);
}
+ virtual ~FtwFunc() {}
private:
const ftwFn fn;
};
-int doMergedFtw(const std::string& dirPath, Func& fn, int fdLimit, int flags,
+int doMergedFtw(const cpp::string& dirPath, Func& fn, int fdLimit, int flags,
int level) {
// fdLimit specifies the maximum number of directories that ftw()
// will hold open simultaneously. When a directory is opened, fdLimit is
@@ -125,8 +104,8 @@ int doMergedFtw(const std::string& dirPath, Func& fn, int fdLimit, int flags,
struct FTW ftwBuf;
// Find the base by finding the last slash.
- std::size_t slash_found = dirPath.rfind("/");
- if (slash_found != std::string::npos) {
+ size_t slash_found = dirPath.rfind("/");
+ if (slash_found != cpp::string::npos) {
ftwBuf.base = slash_found + 1;
}
@@ -175,19 +154,22 @@ int doMergedFtw(const std::string& dirPath, Func& fn, int fdLimit, int flags,
}
return 0;
}
-} // namespace
-int llvm_libc_nftw(const std::string& dirPath,
- int (*fn)(const char* filePath, const struct stat* statBuf,
- int tFlag, struct FTW* ftwbuf),
- int fdLimit, int flags) {
+LLVM_LIBC_FUNCTION(int, nftw, (const char *dirPath,
+ int (*fn)(const char *filePath, const struct stat *statBuf,
+ int tFlag, struct FTW *ftwbuf),
+ int fdLimit, int flags)) {
NftwFunc wrappedFn{fn};
return doMergedFtw(dirPath, wrappedFn, fdLimit, flags, 0);
}
-int llvm_libc_ftw(const std::string &dirPath,
+LLVM_LIBC_FUNCTION(int, ftw, (const char *dirPath,
int (*fn)(const char *filePath, const struct stat *statBuf,
int tFlag),
- int fdLimit) {
- return llvm_libc_nftw(dirPath, (int (*)())fn, fdLimit, FTW_PHYS, 0);
+ int fdLimit)) {
+ FtwFunc wrappedFn{fn};
+ return doMergedFtw(dirPath, wrappedFn, fdLimit, FTW_PHYS, 0);
}
+
+} // namespace LIBC_NAMESPACE_DECL
+
>From 7e3a80e5598b82b2168e4ddd46f35291eefad965 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Mon, 16 Sep 2024 10:04:52 +0000
Subject: [PATCH 4/7] [libc][nfc] Fix typo in header generation message.
---
libc/cmake/modules/LLVMLibCHeaderRules.cmake | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
index c2c675bda26d31..76c4e1f2d3244c 100644
--- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake
+++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake
@@ -118,7 +118,7 @@ function(add_gen_header2 target_name)
${entry_points}
--output_dir ${out_file}
DEPENDS ${yaml_file} ${def_file} ${fq_data_files}
- COMMENT "Generating header ${ADD_GEN_HDR2_GE2N_HDR} from ${yaml_file} and ${def_file}"
+ COMMENT "Generating header ${ADD_GEN_HDR2_GEN_HDR} from ${yaml_file} and ${def_file}"
)
if(LIBC_TARGET_OS_IS_GPU)
file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/llvm-libc-decls)
@@ -135,7 +135,7 @@ function(add_gen_header2 target_name)
DEPENDS ${yaml_file} ${fq_data_files}
)
endif()
-
+
if(ADD_GEN_HDR2_DEPENDS)
get_fq_deps_list(fq_deps_list ${ADD_GEN_HDR2_DEPENDS})
# Dependencies of a add_header target can only be another add_gen_header target
>From 94f7ca8e54988470d2c8ed335db9cde317b55f12 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Mon, 16 Sep 2024 10:09:38 +0000
Subject: [PATCH 5/7] Checkpoint in-progress header work
---
libc/config/linux/api.td | 3 +++
libc/newhdrgen/yaml/ftw.yaml | 15 +++++++++++++++
libc/spec/posix.td | 32 ++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+)
create mode 100644 libc/newhdrgen/yaml/ftw.yaml
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 6a7c64296bf922..80b4da9e404a5d 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -19,6 +19,9 @@ def FCntlAPI : PublicAPI<"fcntl.h"> {
];
}
+def FTWAPI : PublicAPI<"ftw.h"> {
+}
+
def IntTypesAPI : PublicAPI<"inttypes.h"> {
let Types = ["imaxdiv_t"];
}
diff --git a/libc/newhdrgen/yaml/ftw.yaml b/libc/newhdrgen/yaml/ftw.yaml
new file mode 100644
index 00000000000000..37b44834d56c35
--- /dev/null
+++ b/libc/newhdrgen/yaml/ftw.yaml
@@ -0,0 +1,15 @@
+header: fcntl.h
+macros: []
+types: []
+enums: []
+objects: []
+functions:
+ - name: ftw
+ standards:
+ - POSIX
+ return_type: int
+ arguments:
+ - type: const char *
+ - type: int
+ - type: int
+
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 085f2ec34ab346..85a1372bde2288 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -291,6 +291,37 @@ def POSIX : StandardSpec<"POSIX"> {
]
>;
+ HeaderSpec FTW = HeaderSpec<
+ "ftw.h",
+ [], // Macros
+ [], // Types
+ [
+ EnumeratedNameValue<"FTW_CHDIR">,
+ EnumeratedNameValue<"FTW_DEPTH">,
+ EnumeratedNameValue<"FTW_MOUNT">,
+ EnumeratedNameValue<"FTW_PHYS">,
+ EnumeratedNameValue<"FTW_F">,
+ EnumeratedNameValue<"FTW_D">,
+ EnumeratedNameValue<"FTW_DP">,
+ EnumeratedNameValue<"FTW_SL">,
+ EnumeratedNameValue<"FTW_SLN">,
+ EnumeratedNameValue<"FTW_DNR">,
+ EnumeratedNameValue<"FTW_SLN">
+ ], // Enumerations
+ [
+ FunctionSpec<
+ "ftw",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "nftw",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>]
+ >
+ ]
+ >;
+
HeaderSpec SysMMan = HeaderSpec<
"sys/mman.h",
[
@@ -1771,6 +1802,7 @@ def POSIX : StandardSpec<"POSIX"> {
DlFcn,
Errno,
FCntl,
+ FTW,
PThread,
Sched,
Signal,
>From ebdab6b2273d6f9c02ef70d3086dbfc5dde4a57a Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Wed, 18 Sep 2024 13:20:19 +0000
Subject: [PATCH 6/7] Add some enums for ftw headers.
---
libc/include/ftw.h.def | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/libc/include/ftw.h.def b/libc/include/ftw.h.def
index af3be565653192..146de47de9191f 100644
--- a/libc/include/ftw.h.def
+++ b/libc/include/ftw.h.def
@@ -11,6 +11,33 @@
#include "__llvm-libc-common.h"
+/* macros needed */
+
+enum {
+ FTW_D,
+ FTW_DNR,
+ FTW_F,
+ FTW_DP,
+ FTW_SL,
+ FTW_NS,
+ FTW_SLN
+}; // typeflag
+
+enum {
+ FTW_ACTIONRETVAL,
+ FTW_CHDIR,
+ FTW_DEPTH,
+ FTW_MOUNT,
+ FTW_PHYS
+}; // flags
+
+enum {
+ FTW_CONTINUE,
+ FTW_SKIP_SIBLINGS,
+ FTW_SKIP_SUBTREE,
+ FTW_STOP
+}; /* fn return */
+
%%public_api()
#endif // LLVM_LIBC_FTW_H
>From af4e30c15e536a465e6c98c578f9b7d146e38837 Mon Sep 17 00:00:00 2001
From: Jeff Bailey <jeffbailey at google.com>
Date: Mon, 30 Sep 2024 16:45:34 +0000
Subject: [PATCH 7/7] Fix errno, open and close.
---
libc/src/ftw/CMakeLists.txt | 7 +++++--
libc/src/ftw/ftw.cpp | 7 +++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/libc/src/ftw/CMakeLists.txt b/libc/src/ftw/CMakeLists.txt
index a9e219b8bdb45a..e0a45d6ee0fb97 100644
--- a/libc/src/ftw/CMakeLists.txt
+++ b/libc/src/ftw/CMakeLists.txt
@@ -5,7 +5,10 @@ add_entrypoint_object(
HDRS
ftw.h
DEPENDS
+ libc.include.ftw
libc.src.__support.FPUtil.fenv_impl
- COMPILE_OPTIONS
- -O2
+ libc.src.errno.errno
+ libc.src.fcntl.open
+ libc.src.unistd.close
+
)
diff --git a/libc/src/ftw/ftw.cpp b/libc/src/ftw/ftw.cpp
index 626acd6d2105a7..dabd9b2c864458 100644
--- a/libc/src/ftw/ftw.cpp
+++ b/libc/src/ftw/ftw.cpp
@@ -11,7 +11,10 @@
#include "src/__support/common.h"
#include "src/__support/CPP/string.h"
#include "src/errno/libc_errno.h"
+#include "src/fcntl/open.h"
+#include "src/unistd/close.h"
+#include <ftw.h>
#include <stddef.h>
#include <sys/stat.h>
@@ -73,7 +76,7 @@ int doMergedFtw(const cpp::string& dirPath, Func& fn, int fdLimit, int flags,
if (stat(dirPath.c_str(), &statBuf) < 0) {
if (!lstat(dirPath.c_str(), &statBuf)) {
typeFlag = FTW_SLN; /* Symbolic link pointing to a nonexistent file. */
- } else if (errno != EACCES) {
+ } else if (libc_errno != EACCES) {
/* stat failed with an errror that is not Permission denied */
return -1;
} else {
@@ -125,7 +128,7 @@ int doMergedFtw(const cpp::string& dirPath, Func& fn, int fdLimit, int flags,
if (!(flags & FTW_DEPTH)) {
// Call the function on the directory.
int directory_fd = open(dirPath.c_str(), O_RDONLY);
- if (directory_fd < 0 && errno == EACCES) {
+ if (directory_fd < 0 && libc_errno == EACCES) {
typeFlag = FTW_DNR; /* Directory can't be read. */
}
close(directory_fd);
More information about the libc-commits
mailing list