diff --git a/daemon/src/dht/dhtaccount.cpp b/daemon/src/dht/dhtaccount.cpp index 65400929cde4fc58293a123cd27293c2d5fde6b0..8ff471d02178a0d59b89e4df7beec5a61d5997c7 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 c32beb33eac9049da1140070397a766342ba0551..02a009aa857daee0d8c769991725b697f97d0aaf 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 c981f5f980c69d8e4e22908267b90a9859e1aa0d..17602d6f1320adb7b210dcc4f319a038b64a5398 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;