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