Botan 1.10.17

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 fd != -1 && ::close(fd);
77 }
78 private:
79 int fd;
80 };
81
82 TemporaryFile file("/tmp/botan_");
83
84 if(file.get_fd() == -1)
85 throw MemoryMapping_Failed("Could not create file");
86
87 std::vector<byte> zeros(4096);
88
89 size_t remaining = n;
90
91 while(remaining)
92 {
93 const size_t write_try = std::min(zeros.size(), remaining);
94
95 ssize_t wrote_got = ::write(file.get_fd(),
96 &zeros[0],
97 write_try);
98
99 if(wrote_got == -1 && errno != EINTR)
100 throw MemoryMapping_Failed("Could not write to file");
101
102 remaining -= wrote_got;
103 }
104
105 #ifndef MAP_NOSYNC
106 #define MAP_NOSYNC 0
107 #endif
108
109 void* ptr = ::mmap(0, n,
110 PROT_READ | PROT_WRITE,
111 MAP_SHARED | MAP_NOSYNC,
112 file.get_fd(), 0);
113
114 if(ptr == static_cast<void*>(MAP_FAILED))
115 throw MemoryMapping_Failed("Could not map file");
116
117 return ptr;
118 }
119
120 /*
121 * Remove a Memory Mapping
122 */
123 void MemoryMapping_Allocator::dealloc_block(void* ptr, size_t n)
124 {
125 if(ptr == 0)
126 return;
127
128 const byte PATTERNS[] = { 0x00, 0xF5, 0x5A, 0xAF, 0x00 };
129
130 // The char* casts are for Solaris, args are void* on most other systems
131
132 for(size_t i = 0; i != sizeof(PATTERNS); ++i)
133 {
134 std::memset(ptr, PATTERNS[i], n);
135
136 if(::msync(static_cast<char*>(ptr), n, MS_SYNC))
137 throw MemoryMapping_Failed("Sync operation failed");
138 }
139
140 if(::munmap(static_cast<char*>(ptr), n))
141 throw MemoryMapping_Failed("Could not unmap file");
142 }
143
144 }
Botan::byte
unsigned char byte
Definition: types.h:22
MAP_FAILED
#define MAP_FAILED
Definition: mmap_mem.cpp:21
MAP_NOSYNC
#define MAP_NOSYNC
Botan::Exception
std::runtime_error Exception
Definition: exceptn.h:19
Botan
Definition: algo_base.h:14
Botan::CT::min
T min(T a, T b)
Definition: ct_utils.h:127