Botan 3.4.0
Crypto and TLS for C&
filesystem.cpp
Go to the documentation of this file.
1/*
2* (C) 2015,2017,2019 Jack Lloyd
3* (C) 2015 Simon Warta (Kullo GmbH)
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/exceptn.h>
9
10#include <botan/internal/filesystem.h>
11#include <algorithm>
12#include <deque>
13#include <memory>
14#include <sstream>
15
16#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
17 #include <dirent.h>
18 #include <functional>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
22 #define NOMINMAX 1
23 #define _WINSOCKAPI_ // stop windows.h including winsock.h
24 #include <windows.h>
25#endif
26
27namespace Botan {
28
29namespace {
30
31#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
32
33std::vector<std::string> impl_readdir(std::string_view dir_path) {
34 std::vector<std::string> out;
35 std::deque<std::string> dir_list;
36 dir_list.push_back(std::string(dir_path));
37
38 while(!dir_list.empty()) {
39 const std::string cur_path = dir_list[0];
40 dir_list.pop_front();
41
42 std::unique_ptr<DIR, std::function<int(DIR*)>> dir(::opendir(cur_path.c_str()), ::closedir);
43
44 if(dir) {
45 while(struct dirent* dirent = ::readdir(dir.get())) {
46 const std::string filename = dirent->d_name;
47 if(filename == "." || filename == "..") {
48 continue;
49 }
50
51 std::ostringstream full_path_sstr;
52 full_path_sstr << cur_path << "/" << filename;
53 const std::string full_path = full_path_sstr.str();
54
55 struct stat stat_buf;
56
57 if(::stat(full_path.c_str(), &stat_buf) == -1) {
58 continue;
59 }
60
61 if(S_ISDIR(stat_buf.st_mode)) {
62 dir_list.push_back(full_path);
63 } else if(S_ISREG(stat_buf.st_mode)) {
64 out.push_back(full_path);
65 }
66 }
67 }
68 }
69
70 return out;
71}
72
73#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
74
75std::vector<std::string> impl_win32(std::string_view dir_path) {
76 std::vector<std::string> out;
77 std::deque<std::string> dir_list;
78 dir_list.push_back(std::string(dir_path));
79
80 while(!dir_list.empty()) {
81 const std::string cur_path = dir_list[0];
82 dir_list.pop_front();
83
84 WIN32_FIND_DATAA find_data;
85 HANDLE dir = ::FindFirstFileA((cur_path + "/*").c_str(), &find_data);
86
87 if(dir != INVALID_HANDLE_VALUE) {
88 do {
89 const std::string filename = find_data.cFileName;
90 if(filename == "." || filename == "..")
91 continue;
92 const std::string full_path = cur_path + "/" + filename;
93
94 if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
95 dir_list.push_back(full_path);
96 } else {
97 out.push_back(full_path);
98 }
99 } while(::FindNextFileA(dir, &find_data));
100 }
101
102 ::FindClose(dir);
103 }
104
105 return out;
106}
107#endif
108
109} // namespace
110
112#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
113 return true;
114#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
115 return true;
116#else
117 return false;
118#endif
119}
120
121std::vector<std::string> get_files_recursive(std::string_view dir) {
122 std::vector<std::string> files;
123
124#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
125 files = impl_readdir(dir);
126#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
127 files = impl_win32(dir);
128#else
129 BOTAN_UNUSED(dir);
130 throw No_Filesystem_Access();
131#endif
132
133 std::sort(files.begin(), files.end());
134
135 return files;
136}
137
138} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
bool has_filesystem_impl()
std::vector< std::string > get_files_recursive(std::string_view dir)