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