Coverage Report

Created: 2025-07-11 06:15

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