From aef7652011eb3e25095d40ad1ff751c97d75b863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Wed, 12 Nov 2014 18:25:18 -0500 Subject: [PATCH] fileutils: add readDirectory Create an abstraction layer to access directory content Change-Id: I551475db784c0348f19cfe1d674131382c68a90c --- daemon/src/dht/dhtaccount.cpp | 16 ++--------- daemon/src/fileutils.cpp | 50 +++++++++++++++++++++++++++++++++++ daemon/src/fileutils.h | 9 +++++++ 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/daemon/src/dht/dhtaccount.cpp b/daemon/src/dht/dhtaccount.cpp index 65400929cd..8ff471d021 100644 --- a/daemon/src/dht/dhtaccount.cpp +++ b/daemon/src/dht/dhtaccount.cpp @@ -65,7 +65,6 @@ #include <unistd.h> #include <pwd.h> -#include <dirent.h> #include <algorithm> #include <array> @@ -614,19 +613,10 @@ DHTAccount::loadNodes() const std::vector<dht::Dht::ValuesExport> DHTAccount::loadValues() const { - struct dirent *entry; - DIR *dp = opendir(dataPath_.c_str()); - if (!dp) { - SFL_ERR("Could not load values from %s", dataPath_.c_str()); - return {}; - } - std::vector<dht::Dht::ValuesExport> values; - while ((entry = readdir(dp))) { + const auto dircontent(fileutils::readDirectory(dataPath_)); + for (const auto& fname : dircontent) { try { - const std::string fname {entry->d_name}; - if (fname == "." || fname == "..") - continue; std::ifstream ifs(dataPath_+DIR_SEPARATOR_STR+fname, std::ifstream::in | std::ifstream::binary); std::istreambuf_iterator<char> begin(ifs), end; values.push_back({{fname}, std::vector<uint8_t>{begin, end}}); @@ -635,8 +625,6 @@ DHTAccount::loadValues() const continue; } } - closedir(dp); - return values; } diff --git a/daemon/src/fileutils.cpp b/daemon/src/fileutils.cpp index c32beb33ea..02a009aa85 100644 --- a/daemon/src/fileutils.cpp +++ b/daemon/src/fileutils.cpp @@ -58,6 +58,7 @@ #include <cstdlib> #include <cstring> #include <cerrno> +#include <cstddef> namespace fileutils { // returns true if directory exists @@ -210,6 +211,55 @@ bool isDirectoryWritable(const std::string &directory) return access(directory.c_str(), W_OK) == 0; } +static size_t +dirent_buf_size(DIR * dirp) +{ + long name_max; +#if defined(HAVE_FPATHCONF) && defined(HAVE_DIRFD) && defined(_PC_NAME_MAX) + name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); + if (name_max == -1) +#if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +#else + return (size_t)(-1); +#endif +#else +#if defined(NAME_MAX) + name_max = (NAME_MAX > 255) ? NAME_MAX : 255; +#else +#error "buffer size for readdir_r cannot be determined" +#endif +#endif + size_t name_end = (size_t) offsetof(struct dirent, d_name) + name_max + 1; + return name_end > sizeof(struct dirent) ? name_end : sizeof(struct dirent); +} + +std::vector<std::string> +readDirectory(const std::string& dir) +{ + DIR *dp = opendir(dir.c_str()); + if (!dp) { + SFL_ERR("Could not open %s", dir.c_str()); + return {}; + } + + size_t size = dirent_buf_size(dp); + if (size == -1) + return {}; + std::vector<uint8_t> buf(size); + dirent* entry; + + std::vector<std::string> files; + while (!readdir_r(dp, reinterpret_cast<dirent*>(buf.data()), &entry) && entry) { + const std::string fname {entry->d_name}; + if (fname == "." || fname == "..") + continue; + files.push_back(std::move(fname)); + } + closedir(dp); + return files; +} + FileHandle::FileHandle(const std::string &n) : fd(-1), name(n) {} diff --git a/daemon/src/fileutils.h b/daemon/src/fileutils.h index c981f5f980..17602d6f13 100644 --- a/daemon/src/fileutils.h +++ b/daemon/src/fileutils.h @@ -32,6 +32,7 @@ #define FILEUTILS_H_ #include <string> +#include <vector> #define PROTECTED_GETENV(str) ({char *envvar_ = getenv((str)); \ envvar_ ? envvar_ : "";}) @@ -56,6 +57,14 @@ namespace fileutils { std::string get_ringtone_dir(); std::string expand_path(const std::string &path); bool isDirectoryWritable(const std::string &directory); + + /** + * Read content of the directory. + * The result is a list of full paths of files in the directory, + * without "." and "..". + */ + std::vector<std::string> readDirectory(const std::string &dir); + struct FileHandle { int fd; const std::string name; -- GitLab