Coverage Report

Created: 2020-03-26 13:53

/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
#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
25
namespace Botan {
26
27
namespace {
28
29
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
30
31
std::vector<std::string> impl_readdir(const std::string& dir_path)
32
0
   {
33
0
   std::vector<std::string> out;
34
0
   std::deque<std::string> dir_list;
35
0
   dir_list.push_back(dir_path);
36
0
37
0
   while(!dir_list.empty())
38
0
      {
39
0
      const std::string cur_path = dir_list[0];
40
0
      dir_list.pop_front();
41
0
42
0
      std::unique_ptr<DIR, std::function<int (DIR*)>> dir(::opendir(cur_path.c_str()), ::closedir);
43
0
44
0
      if(dir)
45
0
         {
46
0
         while(struct dirent* dirent = ::readdir(dir.get()))
47
0
            {
48
0
            const std::string filename = dirent->d_name;
49
0
            if(filename == "." || filename == "..")
50
0
               continue;
51
0
            const std::string full_path = cur_path + "/" + filename;
52
0
53
0
            struct stat stat_buf;
54
0
55
0
            if(::stat(full_path.c_str(), &stat_buf) == -1)
56
0
               continue;
57
0
58
0
            if(S_ISDIR(stat_buf.st_mode))
59
0
               dir_list.push_back(full_path);
60
0
            else if(S_ISREG(stat_buf.st_mode))
61
0
               out.push_back(full_path);
62
0
            }
63
0
         }
64
0
      }
65
0
66
0
   return out;
67
0
   }
68
69
#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
70
71
std::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
115
bool has_filesystem_impl()
116
0
   {
117
0
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
118
0
   return true;
119
#elif defined(BOTAN_TARGET_OS_HAS_WIN32)
120
   return true;
121
#else
122
   return false;
123
#endif
124
   }
125
126
std::vector<std::string> get_files_recursive(const std::string& dir)
127
0
   {
128
0
   std::vector<std::string> files;
129
0
130
0
#if defined(BOTAN_TARGET_OS_HAS_POSIX1)
131
0
   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
0
   std::sort(files.begin(), files.end());
140
0
141
0
   return files;
142
0
   }
143
144
}