Botan 1.10.17

es_ftw.cpp
Go to the documentation of this file.
1 /*
2 * FTW EntropySource
3 * (C) 1999-2008,2012 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7
8 #include <botan/internal/es_ftw.h>
9 #include <botan/secmem.h>
10 #include <cstring>
11 #include <deque>
12
13 #ifndef _POSIX_C_SOURCE
14 #define _POSIX_C_SOURCE 199309
15 #endif
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22
23 namespace Botan {
24
25 /**
26 * Returns file descriptors. Until it doesn't
27 */
28 class File_Descriptor_Source
29 {
30 public:
31 /**
32 * @return next file descriptor, or -1 if done
33 */
34 virtual int next_fd() = 0;
35
36 virtual ~File_Descriptor_Source() {}
37 };
38
39 namespace {
40
41 class Directory_Walker : public File_Descriptor_Source
42 {
43 public:
44 Directory_Walker(const std::string& root) :
45 m_cur_dir(std::make_pair<DIR*, std::string>(0, ""))
46 {
47 if(DIR* root_dir = ::opendir(root.c_str()))
48 m_cur_dir = std::make_pair(root_dir, root);
49 }
50
51 ~Directory_Walker()
52 {
53 if(m_cur_dir.first)
54 ::closedir(m_cur_dir.first);
55 }
56
57 int next_fd();
58 private:
59 void add_directory(const std::string& dirname)
60 {
61 m_dirlist.push_back(dirname);
62 }
63
64 std::pair<struct dirent*, std::string> get_next_dirent();
65
66 std::pair<DIR*, std::string> m_cur_dir;
67 std::deque<std::string> m_dirlist;
68 };
69
70 std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent()
71 {
72 while(m_cur_dir.first)
73 {
74 struct dirent* dir = ::readdir(m_cur_dir.first);
75
76 if(dir)
77 return std::make_pair(dir, m_cur_dir.second);
78
79 ::closedir(m_cur_dir.first);
80 m_cur_dir = std::make_pair<DIR*, std::string>(0, "");
81
82 while(!m_dirlist.empty() && m_cur_dir.first == 0)
83 {
84 const std::string next_dir_name = m_dirlist[0];
85 m_dirlist.pop_front();
86
87 if(DIR* next_dir = ::opendir(next_dir_name.c_str()))
88 m_cur_dir = std::make_pair(next_dir, next_dir_name);
89 }
90 }
91
92 return std::make_pair<struct dirent*, std::string>(0, ""); // nothing left
93 }
94
95 int Directory_Walker::next_fd()
96 {
97 while(true)
98 {
99 std::pair<struct dirent*, std::string> entry = get_next_dirent();
100
101 if(!entry.first)
102 break; // no more dirs
103
104 const std::string filename = entry.first->d_name;
105
106 if(filename == "." || filename == "..")
107 continue;
108
109 const std::string full_path = entry.second + '/' + filename;
110
111 struct stat stat_buf;
112 if(::lstat(full_path.c_str(), &stat_buf) == -1)
113 continue;
114
115 if(S_ISDIR(stat_buf.st_mode))
116 {
117 add_directory(full_path);
118 }
119 else if(S_ISREG(stat_buf.st_mode) && (stat_buf.st_mode & S_IROTH))
120 {
121 int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY);
122
123 if(fd >= 0)
124 return fd;
125 }
126 }
127
128 return -1;
129 }
130
131 }
132
133 /**
134 * FTW_EntropySource Constructor
135 */
136 FTW_EntropySource::FTW_EntropySource(const std::string& p) : path(p)
137 {
138 dir = 0;
139 }
140
141 /**
142 * FTW_EntropySource Destructor
143 */
144 FTW_EntropySource::~FTW_EntropySource()
145 {
146 delete dir;
147 }
148
149 void FTW_EntropySource::poll(Entropy_Accumulator& accum)
150 {
151 const size_t MAX_FILES_READ_PER_POLL = 2048;
152
153 if(!dir)
154 dir = new Directory_Walker(path);
155
156 MemoryRegion<byte>& io_buffer = accum.get_io_buffer(4096);
157
158 for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i)
159 {
160 int fd = dir->next_fd();
161
162 // If we've exhaused this walk of the directory, halt the poll
163 if(fd == -1)
164 {
165 delete dir;
166 dir = 0;
167 break;
168 }
169
170 ssize_t got = ::read(fd, &io_buffer[0], io_buffer.size());
171 ::close(fd);
172
173 if(got > 0)
174 accum.add(&io_buffer[0], got, .001);
175
176 if(accum.polling_goal_achieved())
177 break;
178 }
179 }
180
181 }
Botan::FTW_EntropySource::~FTW_EntropySource
~FTW_EntropySource()
Definition: es_ftw.cpp:144
Botan::FTW_EntropySource::poll
void poll(Entropy_Accumulator &accum)
Definition: es_ftw.cpp:149
Botan::Entropy_Accumulator::get_io_buffer
MemoryRegion< byte > & get_io_buffer(size_t size)
Definition: entropy_src.h:38
Botan::Entropy_Accumulator::add
void add(const void *bytes, size_t length, double entropy_bits_per_byte)
Definition: entropy_src.h:70
O_NOCTTY
#define O_NOCTTY
Botan::FTW_EntropySource::FTW_EntropySource
FTW_EntropySource(const std::string &root_dir)
Definition: es_ftw.cpp:136
Botan::MemoryRegion< byte >
Botan
Definition: algo_base.h:14
Botan::Entropy_Accumulator::polling_goal_achieved
bool polling_goal_achieved() const
Definition: entropy_src.h:50
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::Entropy_Accumulator
Definition: entropy_src.h:19