Make Object layer non-persistent in symtabAPI. Adds MappedFile, a (duh) mapped file...
[dyninst.git] / common / src / MappedFile.C
1 #include "common/h/MappedFile.h"
2
3 MappedFile *MappedFile::createMappedFile(std::string fullpath_)
4 {
5    bool ok = false;
6    MappedFile *mf = new MappedFile(fullpath_, ok);
7    if (!mf) {
8      fprintf(stderr, "%s[%d]:  error mapping file %s\n", 
9            FILE__, __LINE__, fullpath_.c_str());
10      mf = NULL;
11   }
12
13   return mf;
14 }
15
16 MappedFile::MappedFile(std::string fullpath_, bool &ok) :
17    fullpath(std::string(fullpath_)),
18    did_mmap(false),
19    did_open(false)
20 {
21   ok = check_path(fullpath);
22   if (!ok) return;
23   ok = open_file();
24   if (!ok) return;
25   ok = map_file();
26
27   //  I think on unixes we can close the fd after mapping the file, 
28   //  but is this really somehow better?
29 }
30
31 MappedFile *MappedFile::createMappedFile(void *loc)
32 {
33    bool ok = false;
34    MappedFile *mf = new MappedFile(loc, ok);
35    if (!ok) {
36      fprintf(stderr, "%s[%d]:  error mapping file at %p", 
37            FILE__, __LINE__, loc);
38      mf = NULL;
39   }
40
41   return mf;
42 }
43
44 MappedFile::MappedFile(void *loc, bool &ok) :
45    fullpath("in_memory_file"),
46    did_mmap(false),
47    did_open(false)
48 {
49   ok = open_file(loc);
50   if (!ok) return;
51   ok = map_file();
52 }
53
54 bool MappedFile::clean_up()
55 {
56    if (did_mmap) {
57       if (!unmap_file()) goto err;
58    }
59    if (did_open) {
60       if (!close_file()) goto err;
61    }
62    return true;
63
64 err:
65    fprintf(stderr, "%s[%d]:  error unmapping file %s\n", 
66          FILE__, __LINE__, fullpath.c_str() );
67    return false;
68 }
69
70 MappedFile::~MappedFile()
71 {
72   //  warning, destructor should not allowed to throw exceptions
73    if (did_mmap) 
74       unmap_file();
75    if (did_open) 
76       close_file();
77 }
78
79 std::string MappedFile::filename()
80 {
81   return extract_pathname_tail(fullpath);
82 }
83
84 bool MappedFile::check_path(std::string &filename)
85 {
86    struct stat statbuf;
87    if (0 != stat(filename.c_str(), &statbuf)) {
88       char ebuf[1024];
89 #if defined(os_windows)
90       LPVOID lpMsgBuf;
91       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
92             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
93             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
94             &lpMsgBuf,    0,    NULL );
95
96       sprintf(ebuf, "stat: %s", (char *) lpMsgBuf);
97       LocalFree(lpMsgBuf);
98 #else
99       sprintf(ebuf, "stat: %s", strerror(errno));
100 #endif
101       goto err;
102    }
103
104    file_size = statbuf.st_size;
105
106    return true;
107
108 err:
109    fprintf(stderr, "%s[%d]: bad path: %s\n", FILE__, __LINE__, filename.c_str());
110    return false;
111 }
112
113 bool MappedFile::open_file(void *loc)
114 {
115 #if defined(os_windows)
116    hFile = LocalHandle( loc );  //For a mem image
117    if (!hFile) {
118       LPVOID lpMsgBuf;
119       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
120             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
121             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
122             &lpMsgBuf,    0,    NULL );
123
124       char ebuf[1024];
125       sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
126       LocalFree(lpMsgBuf);
127       goto err;
128    }
129    did_open = true;
130 #else
131    did_open = false;
132    fd = -1;
133 #endif
134
135    return true;
136
137 err:
138    fprintf(stderr, "%s[%d]: failed to open file\n", FILE__, __LINE__);
139    return false;
140 }
141
142 bool MappedFile::open_file()
143 {
144 #if defined(os_windows)
145    hFile = CreateFile(fullpath.c_str(), GENERIC_READ, FILE_SHARE_READ,
146          NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
147    if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
148       LPVOID lpMsgBuf;
149       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
150             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
151             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
152             &lpMsgBuf,    0,    NULL );
153
154       char ebuf[1024];
155       sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
156       LocalFree(lpMsgBuf);
157       goto err;
158    }
159 #else
160    fd = open(fullpath.c_str(), O_RDONLY);
161    if (-1 == fd) {
162       char ebuf[1024];
163       sprintf(ebuf, "open(%s) failed: %s", fullpath.c_str(), strerror(errno));
164       goto err;
165    }
166 #endif
167
168    did_open = true;
169    return true;
170 err:
171    fprintf(stderr, "%s[%d]: failed to open file\n", FILE__, __LINE__);
172    return false;
173 }
174
175 bool MappedFile::map_file()
176 {
177    char ebuf[1024];
178 #if defined(os_windows)
179
180    // map the file to our address space
181    // first, create a file mapping object
182    
183    hMap = CreateFileMapping( hFile,
184          NULL,           // security attrs
185          PAGE_READONLY,  // protection flags
186          0,              // max size - high DWORD
187          0,              // max size - low DWORD
188          NULL );         // mapping name - not used
189
190    if (!hMap) {
191       LPVOID lpMsgBuf;
192       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
193             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
194             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
195             &lpMsgBuf,    0,    NULL );
196
197       sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
198       LocalFree(lpMsgBuf);
199       goto err;
200    }
201
202    // next, map the file to our address space
203
204    mapAddr = MapViewOfFileEx( hMap,             // mapping object
205          FILE_MAP_READ,  // desired access
206          0,              // loc to map - hi DWORD
207          0,              // loc to map - lo DWORD
208          0,              // #bytes to map - 0=all
209          NULL );         // suggested map addr
210
211    if (!mapAddr) {
212       LPVOID lpMsgBuf;
213       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
214             |     FORMAT_MESSAGE_IGNORE_INSERTS,    NULL,
215             GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
216             &lpMsgBuf,    0,    NULL );
217
218       sprintf(ebuf, "MapViewOfFileEx failed: %s", (char *) lpMsgBuf);
219       LocalFree(lpMsgBuf);
220       goto err;
221    }
222
223 #else
224
225    map_addr = mmap(0, file_size, PROT_READ, MAP_SHARED, fd, 0);
226    if (MAP_FAILED == map_addr) {
227       sprintf(ebuf, "mmap(0, %d, PROT_READ, MAP_SHARED, %d, 0): %s", 
228             file_size, fd, strerror(errno));
229       goto err;
230    }
231
232 #endif
233
234    did_mmap = true;
235    return true;
236 err:
237    fprintf(stderr, "%s[%d]: failed to open file: %s\n", FILE__, __LINE__, ebuf);
238    return false;
239 }
240
241 bool MappedFile::unmap_file()
242 {
243 #if defined(os_windows)
244
245    UnmapViewOfFile(mapAddr);
246    CloseHandle(hMap);
247
248 #else
249
250    if ( 0 != munmap(map_addr, file_size))  {
251       fprintf(stderr, "%s[%d]: failed to unmap file\n", FILE__, __LINE__);
252       return false;
253    }
254    
255 #endif
256    return true;
257 }
258
259 bool MappedFile::close_file()
260 {
261 #if defined (os_windows)
262
263    CloseHandle(hFile);
264
265 #else
266
267    if (-1 == close(fd)) {
268       fprintf(stderr, "%s[%d]: failed to close file\n", FILE__, __LINE__);
269       return false;
270    }
271
272 #endif
273    return true;
274 }
275