Botan  1.10.9
mmap_mem.cpp
Go to the documentation of this file.
1 /*
2 * Memory Mapping Allocator
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/internal/mmap_mem.h>
9 #include <vector>
10 #include <cstring>
11 
12 #include <sys/types.h>
13 #include <sys/mman.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 
20 #ifndef MAP_FAILED
21  #define MAP_FAILED -1
22 #endif
23 
24 namespace Botan {
25 
26 namespace {
27 
28 /*
29 * MemoryMapping_Allocator Exception
30 */
31 class BOTAN_DLL MemoryMapping_Failed : public Exception
32  {
33  public:
34  MemoryMapping_Failed(const std::string& msg) :
35  Exception("MemoryMapping_Allocator: " + msg) {}
36  };
37 
38 }
39 
40 /*
41 * Memory Map a File into Memory
42 */
43 void* MemoryMapping_Allocator::alloc_block(size_t n)
44  {
45  class TemporaryFile
46  {
47  public:
48  int get_fd() const { return fd; }
49 
50  TemporaryFile(const std::string& base)
51  {
52  const std::string mkstemp_template = base + "XXXXXX";
53 
54  std::vector<char> filepath(mkstemp_template.begin(),
55  mkstemp_template.end());
56  filepath.push_back(0); // add terminating NULL
57 
58  mode_t old_umask = ::umask(077);
59  fd = ::mkstemp(&filepath[0]);
60  ::umask(old_umask);
61 
62  if(fd == -1)
63  throw MemoryMapping_Failed("Temporary file allocation failed");
64 
65  if(::unlink(&filepath[0]) != 0)
66  throw MemoryMapping_Failed("Could not unlink temporary file");
67  }
68 
69  ~TemporaryFile()
70  {
71  /*
72  * We can safely close here, because post-mmap the file
73  * will continue to exist until the mmap is unmapped from
74  * our address space upon deallocation (or process exit).
75  */
76  if(fd != -1 && ::close(fd) == -1)
77  throw MemoryMapping_Failed("Could not close file");
78  }
79  private:
80  int fd;
81  };
82 
83  TemporaryFile file("/tmp/botan_");
84 
85  if(file.get_fd() == -1)
86  throw MemoryMapping_Failed("Could not create file");
87 
88  std::vector<byte> zeros(4096);
89 
90  size_t remaining = n;
91 
92  while(remaining)
93  {
94  const size_t write_try = std::min(zeros.size(), remaining);
95 
96  ssize_t wrote_got = ::write(file.get_fd(),
97  &zeros[0],
98  write_try);
99 
100  if(wrote_got == -1 && errno != EINTR)
101  throw MemoryMapping_Failed("Could not write to file");
102 
103  remaining -= wrote_got;
104  }
105 
106 #ifndef MAP_NOSYNC
107  #define MAP_NOSYNC 0
108 #endif
109 
110  void* ptr = ::mmap(0, n,
111  PROT_READ | PROT_WRITE,
112  MAP_SHARED | MAP_NOSYNC,
113  file.get_fd(), 0);
114 
115  if(ptr == static_cast<void*>(MAP_FAILED))
116  throw MemoryMapping_Failed("Could not map file");
117 
118  return ptr;
119  }
120 
121 /*
122 * Remove a Memory Mapping
123 */
124 void MemoryMapping_Allocator::dealloc_block(void* ptr, size_t n)
125  {
126  if(ptr == 0)
127  return;
128 
129  const byte PATTERNS[] = { 0x00, 0xF5, 0x5A, 0xAF, 0x00 };
130 
131  // The char* casts are for Solaris, args are void* on most other systems
132 
133  for(size_t i = 0; i != sizeof(PATTERNS); ++i)
134  {
135  std::memset(ptr, PATTERNS[i], n);
136 
137  if(::msync(static_cast<char*>(ptr), n, MS_SYNC))
138  throw MemoryMapping_Failed("Sync operation failed");
139  }
140 
141  if(::munmap(static_cast<char*>(ptr), n))
142  throw MemoryMapping_Failed("Could not unmap file");
143  }
144 
145 }
BigInt n
Definition: numthry.cpp:26
unsigned char byte
Definition: types.h:22
#define MAP_FAILED
Definition: mmap_mem.cpp:21
#define MAP_NOSYNC
std::runtime_error Exception
Definition: exceptn.h:19
GMP_MPZ base
Definition: gmp_powm.cpp:29