00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "common/h/MappedFile.h"
00031 #include "common/h/pathName.h"
00032 #include <iostream>
00033 using namespace std;
00034
00035 dyn_hash_map<std::string, MappedFile *> MappedFile::mapped_files;
00036
00037 MappedFile *MappedFile::createMappedFile(std::string fullpath_)
00038 {
00039
00040 if (mapped_files.find(fullpath_) != mapped_files.end()) {
00041
00042 MappedFile *ret = mapped_files[fullpath_];
00043 if (ret->can_share) {
00044 ret->refCount++;
00045 return ret;
00046 }
00047 }
00048
00049 bool ok = false;
00050 MappedFile *mf = new MappedFile(fullpath_, ok);
00051 if (!mf) {
00052 return NULL;
00053 }
00054
00055 if (!ok) {
00056
00057 #if defined(os_vxworks)
00058
00059
00060 mf->remote_file = true;
00061 mf->can_share = true;
00062 mf->map_addr = 0x0;
00063 mf->fd = -1;
00064
00065 ok = true;
00066 #elif defined(os_windows)
00067 if (std::string::npos != fullpath_.find(".dll") &&
00068 std::string::npos == fullpath_.find("\\"))
00069 {
00070 size_t envLen = 64;
00071 char *buf = (char*) malloc(envLen);
00072 bool repeat = false;
00073 do {
00074 repeat = false;
00075 if (getenv_s(&envLen, buf, envLen, "windir")) {
00076 if (envLen > 64) {
00077 repeat = true;
00078 free(buf);
00079 buf = (char*) malloc(envLen);
00080 }
00081 }
00082 } while(repeat);
00083 fullpath_ = buf + ("\\system32\\" + fullpath_);
00084 free(buf);
00085 return MappedFile::createMappedFile(fullpath_);
00086 }
00087 else {
00088 delete mf;
00089 return NULL;
00090 }
00091 #else
00092 delete mf;
00093 return NULL;
00094 #endif
00095 }
00096
00097 mapped_files[fullpath_] = mf;
00098
00099
00100 return mf;
00101 }
00102
00103 MappedFile::MappedFile(std::string fullpath_, bool &ok) :
00104 fullpath(fullpath_),
00105 map_addr(NULL),
00106 #if defined(os_windows)
00107 hMap(NULL),
00108 hFile(NULL),
00109 #endif
00110 remote_file(false),
00111 did_mmap(false),
00112 did_open(false),
00113 can_share(true),
00114 refCount(1)
00115 {
00116 ok = check_path(fullpath);
00117 if (!ok) {
00118 return;
00119 }
00120 ok = open_file();
00121 if (!ok) return;
00122 ok = map_file();
00123
00124
00125
00126 }
00127
00128 MappedFile *MappedFile::createMappedFile(void *loc, unsigned long size_, const std::string &name)
00129 {
00130 bool ok = false;
00131 MappedFile *mf = new MappedFile(loc, size_, name, ok);
00132 if (!mf || !ok) {
00133 if (mf)
00134 delete mf;
00135 return NULL;
00136 }
00137
00138 return mf;
00139 }
00140
00141 MappedFile::MappedFile(void *loc, unsigned long size_, const std::string &name, bool &ok) :
00142 fullpath(name),
00143 map_addr(NULL),
00144 #if defined(os_windows)
00145 hMap(NULL),
00146 hFile(NULL),
00147 #endif
00148 remote_file(false),
00149 did_mmap(false),
00150 did_open(false),
00151 can_share(true),
00152 refCount(1)
00153 {
00154 ok = open_file(loc, size_);
00155 #if defined(os_windows)
00156 if (!ok) {
00157 return;
00158 }
00159
00160 map_addr = loc;
00161 this->file_size = size_;
00162 #endif
00163 }
00164
00165 void MappedFile::closeMappedFile(MappedFile *&mf)
00166 {
00167 if (!mf)
00168 {
00169 fprintf(stderr, "%s[%d]: BAD NEWS: called closeMappedFile(NULL)\n", FILE__, __LINE__);
00170 return;
00171 }
00172
00173
00174 mf->refCount--;
00175
00176 if (mf->refCount <= 0)
00177 {
00178 dyn_hash_map<std::string, MappedFile *>::iterator iter;
00179 iter = mapped_files.find(mf->pathname());
00180
00181 if (iter != mapped_files.end())
00182 {
00183 mapped_files.erase(iter);
00184 }
00185
00186
00187
00188
00189 delete mf;
00190 mf = NULL;
00191 }
00192 }
00193
00194 bool MappedFile::clean_up()
00195 {
00196 if (did_mmap) {
00197 if (!unmap_file()) goto err;
00198 }
00199 if (did_open) {
00200 if (!close_file()) goto err;
00201 }
00202 return true;
00203
00204 err:
00205 fprintf(stderr, "%s[%d]: error unmapping file %s\n",
00206 FILE__, __LINE__, fullpath.c_str() );
00207 return false;
00208 }
00209
00210 MappedFile::~MappedFile()
00211 {
00212
00213 if (did_mmap) {
00214
00215 unmap_file();
00216 }
00217 if (did_open)
00218 close_file();
00219 }
00220
00221 bool MappedFile::check_path(std::string &filename)
00222 {
00223 struct stat statbuf;
00224 if (0 != stat(filename.c_str(), &statbuf)) {
00225 char ebuf[1024];
00226 #if defined(os_windows)
00227 LPVOID lpMsgBuf;
00228 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00229 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
00230 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00231 &lpMsgBuf, 0, NULL );
00232
00233 sprintf(ebuf, "stat: %s", (char *) lpMsgBuf);
00234 LocalFree(lpMsgBuf);
00235 #else
00236 sprintf(ebuf, "stat: %s", strerror(errno));
00237 #endif
00238 goto err;
00239 }
00240
00241 file_size = statbuf.st_size;
00242
00243 return true;
00244
00245 err:
00246 return false;
00247 }
00248
00249 bool MappedFile::open_file(void *loc, unsigned long size_)
00250 {
00251 #if defined(os_windows)
00252 hFile = LocalHandle( loc );
00253 if (!hFile) {
00254 LPVOID lpMsgBuf;
00255 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
00256 FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
00257 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00258 (LPTSTR) &lpMsgBuf, 0, NULL);
00259
00260 char ebuf[1024];
00261 sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
00262 LocalFree(lpMsgBuf);
00263 goto err;
00264 }
00265 did_open = true;
00266
00267 return true;
00268 err:
00269 fprintf(stderr, "%s[%d]: failed to open file\n", FILE__, __LINE__);
00270 return false;
00271 #else
00272 map_addr = loc;
00273 file_size = size_;
00274 did_open = false;
00275 fd = -1;
00276 return true;
00277 #endif
00278 }
00279
00280 bool MappedFile::open_file()
00281 {
00282 #if defined(os_windows)
00283 hFile = CreateFile(fullpath.c_str(), GENERIC_READ, FILE_SHARE_READ,
00284 NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
00285 if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
00286 LPVOID lpMsgBuf;
00287 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00288 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
00289 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00290 &lpMsgBuf, 0, NULL );
00291
00292 char ebuf[1024];
00293 sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
00294 LocalFree(lpMsgBuf);
00295 goto err;
00296 }
00297 #else
00298 fd = open(fullpath.c_str(), O_RDONLY);
00299 if (-1 == fd) {
00300 char ebuf[1024];
00301 sprintf(ebuf, "open(%s) failed: %s", fullpath.c_str(), strerror(errno));
00302 goto err;
00303 }
00304 #endif
00305
00306 did_open = true;
00307 return true;
00308 err:
00309 fprintf(stderr, "%s[%d]: failed to open file\n", FILE__, __LINE__);
00310 return false;
00311 }
00312
00313 bool MappedFile::map_file()
00314 {
00315 char ebuf[1024];
00316 #if defined(os_windows)
00317
00318
00319
00320
00321 hMap = CreateFileMapping( hFile,
00322 NULL,
00323 PAGE_READONLY,
00324 0,
00325 0,
00326 NULL );
00327
00328 if (!hMap) {
00329 LPVOID lpMsgBuf;
00330 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00331 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
00332 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00333 &lpMsgBuf, 0, NULL );
00334
00335 sprintf(ebuf, "CreateFileMapping failed: %s", (char *) lpMsgBuf);
00336 LocalFree(lpMsgBuf);
00337 goto err;
00338 }
00339
00340
00341
00342 map_addr = MapViewOfFileEx( hMap,
00343 FILE_MAP_COPY,
00344 0,
00345 0,
00346 0,
00347 NULL );
00348 if (!map_addr) {
00349 LPVOID lpMsgBuf;
00350 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
00351 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
00352 GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)
00353 &lpMsgBuf, 0, NULL );
00354
00355 sprintf(ebuf, "MapViewOfFileEx failed: %s", (char *) lpMsgBuf);
00356 LocalFree(lpMsgBuf);
00357 goto err;
00358 }
00359
00360 #else
00361
00362 int mmap_prot = PROT_READ;
00363 int mmap_flags = MAP_SHARED;
00364
00365 #if defined(os_vxworks)
00366
00367
00368
00369
00370
00371
00372 mmap_prot = PROT_READ | PROT_WRITE;
00373 mmap_flags = MAP_PRIVATE;
00374 #endif
00375
00376 map_addr = mmap(0, file_size, mmap_prot, mmap_flags, fd, 0);
00377 if (MAP_FAILED == map_addr) {
00378 sprintf(ebuf, "mmap(0, %lu, prot=0x%x, flags=0x%x, %d, 0): %s",
00379 file_size, mmap_prot, mmap_flags, fd, strerror(errno));
00380 goto err;
00381 }
00382
00383 #endif
00384
00385 did_mmap = true;
00386 return true;
00387 err:
00388 return false;
00389 }
00390
00391 bool MappedFile::unmap_file()
00392 {
00393 if (remote_file) {
00394 return true;
00395 }
00396
00397 #if defined(os_windows)
00398
00399 UnmapViewOfFile(map_addr);
00400 CloseHandle(hMap);
00401
00402 #else
00403
00404 if ( 0 != munmap(map_addr, file_size)) {
00405 fprintf(stderr, "%s[%d]: failed to unmap file\n", FILE__, __LINE__);
00406 return false;
00407 }
00408
00409 map_addr = NULL;
00410 #endif
00411 return true;
00412 }
00413
00414 bool MappedFile::close_file()
00415 {
00416 if (remote_file) {
00417 return true;
00418 }
00419
00420 #if defined (os_windows)
00421
00422 CloseHandle(hFile);
00423
00424 #else
00425
00426 if (-1 == close(fd)) {
00427 fprintf(stderr, "%s[%d]: failed to close file\n", FILE__, __LINE__);
00428 return false;
00429 }
00430
00431 #endif
00432 return true;
00433 }
00434
00435 std::string MappedFile::pathname()
00436 {
00437 return fullpath;
00438 }
00439
00440 std::string MappedFile::filename()
00441 {
00442 return extract_pathname_tail(fullpath);
00443 }
00444
00445 void MappedFile::setSharing(bool s)
00446 {
00447 can_share = s;
00448 }
00449
00450 bool MappedFile::canBeShared()
00451 {
00452 return can_share;
00453 }