Botan: src/alloc/alloc_mmap/mmap_mem.cpp Source File

Botan 1.10.12

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

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 }
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