Botan  2.4.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_READDIR)
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_TYPE_IS_WINDOWS)
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  using namespace std::tr2::sys;
39 
40  std::vector<std::string> out;
41 
42  path p(dir);
43 
44  if (is_directory(p))
45  {
46  for (recursive_directory_iterator itr(p), end; itr != end; ++itr)
47  {
48  if (is_regular_file(itr->path()))
49  {
50  out.push_back(itr->path().string());
51  }
52  }
53  }
54 
55  return out;
56  }
57 
58 #elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
59 
60 std::vector<std::string> impl_boost_filesystem(const std::string& dir_path)
61 {
62  namespace fs = boost::filesystem;
63 
64  std::vector<std::string> out;
65 
66  for(fs::recursive_directory_iterator dir(dir_path), end; dir != end; ++dir)
67  {
68  if(fs::is_regular_file(dir->path()))
69  {
70  out.push_back(dir->path().string());
71  }
72  }
73 
74  return out;
75 }
76 
77 #elif defined(BOTAN_TARGET_OS_HAS_READDIR)
78 std::vector<std::string> impl_readdir(const std::string& dir_path)
79  {
80  std::vector<std::string> out;
81  std::deque<std::string> dir_list;
82  dir_list.push_back(dir_path);
83 
84  while(!dir_list.empty())
85  {
86  const std::string cur_path = dir_list[0];
87  dir_list.pop_front();
88 
89  std::unique_ptr<DIR, std::function<int (DIR*)>> dir(::opendir(cur_path.c_str()), ::closedir);
90 
91  if(dir)
92  {
93  while(struct dirent* dirent = ::readdir(dir.get()))
94  {
95  const std::string filename = dirent->d_name;
96  if(filename == "." || filename == "..")
97  continue;
98  const std::string full_path = cur_path + "/" + filename;
99 
100  struct stat stat_buf;
101 
102  if(::stat(full_path.c_str(), &stat_buf) == -1)
103  continue;
104 
105  if(S_ISDIR(stat_buf.st_mode))
106  dir_list.push_back(full_path);
107  else if(S_ISREG(stat_buf.st_mode))
108  out.push_back(full_path);
109  }
110  }
111  }
112 
113  return out;
114  }
115 
116 #elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
117 
118 std::vector<std::string> impl_win32(const std::string& dir_path)
119  {
120  std::vector<std::string> out;
121  std::deque<std::string> dir_list;
122  dir_list.push_back(dir_path);
123 
124  while(!dir_list.empty())
125  {
126  const std::string cur_path = dir_list[0];
127  dir_list.pop_front();
128 
129  WIN32_FIND_DATA find_data;
130  HANDLE dir = ::FindFirstFile((cur_path + "/*").c_str(), &find_data);
131 
132  if(dir != INVALID_HANDLE_VALUE)
133  {
134  do
135  {
136  const std::string filename = find_data.cFileName;
137  if(filename == "." || filename == "..")
138  continue;
139  const std::string full_path = cur_path + "/" + filename;
140 
141  if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
142  {
143  dir_list.push_back(full_path);
144  }
145  else
146  {
147  out.push_back(full_path);
148  }
149  }
150  while(::FindNextFile(dir, &find_data));
151  }
152 
153  ::FindClose(dir);
154  }
155 
156  return out;
157 }
158 #endif
159 
160 }
161 
162 std::vector<std::string> get_files_recursive(const std::string& dir)
163  {
164  std::vector<std::string> files;
165 
166 #if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC)
167  files = impl_stl_filesystem(dir);
168 #elif defined(BOTAN_HAS_BOOST_FILESYSTEM)
169  files = impl_boost_filesystem(dir);
170 #elif defined(BOTAN_TARGET_OS_HAS_READDIR)
171  files = impl_readdir(dir);
172 #elif defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS)
173  files = impl_win32(dir);
174 #else
175  BOTAN_UNUSED(dir);
176  throw No_Filesystem_Access();
177 #endif
178 
179  std::sort(files.begin(), files.end());
180 
181  return files;
182  }
183 
184 }
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:106
std::vector< std::string > get_files_recursive(const std::string &dir)
Definition: filesystem.cpp:162