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