Botan  1.10.9
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 */
145  {
146  delete dir;
147  }
148 
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 }
void poll(Entropy_Accumulator &accum)
Definition: es_ftw.cpp:149
MemoryRegion< byte > & get_io_buffer(size_t size)
Definition: entropy_src.h:38
void add(const void *bytes, size_t length, double entropy_bits_per_byte)
Definition: entropy_src.h:70
std::pair< DIR *, std::string > m_cur_dir
Definition: es_ftw.cpp:66
#define O_NOCTTY
std::deque< std::string > m_dirlist
Definition: es_ftw.cpp:67
FTW_EntropySource(const std::string &root_dir)
Definition: es_ftw.cpp:136
bool polling_goal_achieved() const
Definition: entropy_src.h:50
size_t size() const
Definition: secmem.h:29