Coverage Report

Created: 2025-04-11 06:34

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