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