Botan  2.8.0
Crypto and TLS for C++11
filesystem.cpp
Go to the documentation of this file.
1 /*
2 * (C) 2015,2017 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 
12 #if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
13  #include <filesystem>
14 #elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
15  #include <boost/filesystem.hpp>
16 #elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
17  #include <sys/types.h>
18  #include <sys/stat.h>
19  #include <dirent.h>
20  #include <deque>
21  #include <memory>
22  #include <functional>
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  #include <deque>
28  #include <memory>
29 #endif
30 
31 namespace Botan {
32 
33 namespace {
34 
35 #if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
36 std::vector<std::string> impl_stl_filesystem(const std::string& dir)
37  {
38 #if (_MSVC_LANG >= 201703L)
39  using namespace std::filesystem;
40 #else
41  using namespace std::tr2::sys;
42 #endif
43 
44  std::vector<std::string> out;
45 
46  path p(dir);
47 
48  if(is_directory(p))
49  {
50  for(recursive_directory_iterator itr(p), end; itr != end; ++itr)
51  {
52  if(is_regular_file(itr->path()))
53  {
54  out.push_back(itr->path().string());
55  }
56  }
57  }
58 
59  return out;
60  }
61 
62 #elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
63 
64 std::vector<std::string> impl_boost_filesystem(const std::string& dir_path)
65 {
66  namespace fs = boost::filesystem;
67 
68  std::vector<std::string> out;
69 
70  for(fs::recursive_directory_iterator dir(dir_path), end; dir != end; ++dir)
71  {
72  if(fs::is_regular_file(dir->path()))
73  {
74  out.push_back(dir->path().string());
75  }
76  }
77 
78  return out;
79 }
80 
81 #elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
82 
83 std::vector<std::string> impl_readdir(const std::string& dir_path)
84  {
85  std::vector<std::string> out;
86  std::deque<std::string> dir_list;
87  dir_list.push_back(dir_path);
88 
89  while(!dir_list.empty())
90  {
91  const std::string cur_path = dir_list[0];
92  dir_list.pop_front();
93 
94  std::unique_ptr<DIR, std::function<int (DIR*)>> dir(::opendir(cur_path.c_str()), ::closedir);
95 
96  if(dir)
97  {
98  while(struct dirent* dirent = ::readdir(dir.get()))
99  {
100  const std::string filename = dirent->d_name;
101  if(filename == "." || filename == "..")
102  continue;
103  const std::string full_path = cur_path + "/" + filename;
104 
105  struct stat stat_buf;
106 
107  if(::stat(full_path.c_str(), &stat_buf) == -1)
108  continue;
109 
110  if(S_ISDIR(stat_buf.st_mode))
111  dir_list.push_back(full_path);
112  else if(S_ISREG(stat_buf.st_mode))
113  out.push_back(full_path);
114  }
115  }
116  }
117 
118  return out;
119  }
120 
121 #elif defined(BOTAN_TARGET_OS_HAS_WIN32)
122 
123 std::vector<std::string> impl_win32(const std::string& dir_path)
124  {
125  std::vector<std::string> out;
126  std::deque<std::string> dir_list;
127  dir_list.push_back(dir_path);
128 
129  while(!dir_list.empty())
130  {
131  const std::string cur_path = dir_list[0];
132  dir_list.pop_front();
133 
134  WIN32_FIND_DATAA find_data;
135  HANDLE dir = ::FindFirstFileA((cur_path + "/*").c_str(), &find_data);
136 
137  if(dir != INVALID_HANDLE_VALUE)
138  {
139  do
140  {
141  const std::string filename = find_data.cFileName;
142  if(filename == "." || filename == "..")
143  continue;
144  const std::string full_path = cur_path + "/" + filename;
145 
146  if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
147  {
148  dir_list.push_back(full_path);
149  }
150  else
151  {
152  out.push_back(full_path);
153  }
154  }
155  while(::FindNextFileA(dir, &find_data));
156  }
157 
158  ::FindClose(dir);
159  }
160 
161  return out;
162 }
163 #endif
164 
165 }
166 
168  {
169 #if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
170  return true;
171 #elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
172  return true;
173 #elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
174  return true;
175 #elif defined(BOTAN_TARGET_OS_HAS_WIN32)
176  return true;
177 #else
178  return false;
179 #endif
180  }
181 
182 std::vector<std::string> get_files_recursive(const std::string& dir)
183  {
184  std::vector<std::string> files;
185 
186 #if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
187  files = impl_stl_filesystem(dir);
188 #elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
189  files = impl_boost_filesystem(dir);
190 #elif defined(BOTAN_TARGET_OS_HAS_POSIX1)
191  files = impl_readdir(dir);
192 #elif defined(BOTAN_TARGET_OS_HAS_WIN32)
193  files = impl_win32(dir);
194 #else
195  BOTAN_UNUSED(dir);
196  throw No_Filesystem_Access();
197 #endif
198 
199  std::sort(files.begin(), files.end());
200 
201  return files;
202  }
203 
204 }
bool has_filesystem_impl()
Definition: filesystem.cpp:167
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:142
std::vector< std::string > get_files_recursive(const std::string &dir)
Definition: filesystem.cpp:182