uxshm.c (16486B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /* 7 ** uxshm.c -- Unix Implementations NSPR Named Shared Memory 8 ** 9 ** 10 ** lth. Jul-1999. 11 ** 12 */ 13 #include <string.h> 14 #include <prshm.h> 15 #include <prerr.h> 16 #include <prmem.h> 17 #include "primpl.h" 18 #include <fcntl.h> 19 20 extern PRLogModuleInfo* _pr_shm_lm; 21 22 #define NSPR_IPC_SHM_KEY 'b' 23 /* 24 ** Implementation for System V 25 */ 26 #if defined PR_HAVE_SYSV_NAMED_SHARED_MEMORY 27 # include <sys/ipc.h> 28 # include <sys/shm.h> 29 # include <sys/types.h> 30 # include <sys/stat.h> 31 32 # define _MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory 33 # define _MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory 34 # define _MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory 35 # define _MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory 36 # define _MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory 37 38 extern PRSharedMemory* _MD_OpenSharedMemory(const char* name, PRSize size, 39 PRIntn flags, PRIntn mode) { 40 PRStatus rc = PR_SUCCESS; 41 key_t key; 42 PRSharedMemory* shm; 43 char ipcname[PR_IPC_NAME_SIZE]; 44 45 rc = _PR_MakeNativeIPCName(name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm); 46 if (PR_FAILURE == rc) { 47 _PR_MD_MAP_DEFAULT_ERROR(errno); 48 PR_LOG( 49 _pr_shm_lm, PR_LOG_DEBUG, 50 ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name)); 51 return (NULL); 52 } 53 54 shm = PR_NEWZAP(PRSharedMemory); 55 if (NULL == shm) { 56 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 57 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 58 ("PR_OpenSharedMemory: New PRSharedMemory out of memory")); 59 return (NULL); 60 } 61 62 shm->ipcname = (char*)PR_MALLOC(strlen(ipcname) + 1); 63 if (NULL == shm->ipcname) { 64 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 65 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 66 ("PR_OpenSharedMemory: New shm->ipcname out of memory")); 67 PR_DELETE(shm); 68 return (NULL); 69 } 70 71 /* copy args to struct */ 72 strcpy(shm->ipcname, ipcname); 73 shm->size = size; 74 shm->mode = mode; 75 shm->flags = flags; 76 shm->ident = _PR_SHM_IDENT; 77 78 /* create the file first */ 79 if (flags & PR_SHM_CREATE) { 80 int osfd = open(shm->ipcname, (O_RDWR | O_CREAT), shm->mode); 81 if (-1 == osfd) { 82 _PR_MD_MAP_OPEN_ERROR(errno); 83 PR_FREEIF(shm->ipcname); 84 PR_DELETE(shm); 85 return (NULL); 86 } 87 if (close(osfd) == -1) { 88 _PR_MD_MAP_CLOSE_ERROR(errno); 89 PR_FREEIF(shm->ipcname); 90 PR_DELETE(shm); 91 return (NULL); 92 } 93 } 94 95 /* hash the shm.name to an ID */ 96 key = ftok(shm->ipcname, NSPR_IPC_SHM_KEY); 97 if (-1 == key) { 98 rc = PR_FAILURE; 99 _PR_MD_MAP_DEFAULT_ERROR(errno); 100 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 101 ("_MD_OpenSharedMemory(): ftok() failed on name: %s", shm->ipcname)); 102 PR_FREEIF(shm->ipcname); 103 PR_DELETE(shm); 104 return (NULL); 105 } 106 107 /* get the shared memory */ 108 if (flags & PR_SHM_CREATE) { 109 shm->id = shmget(key, shm->size, (shm->mode | IPC_CREAT | IPC_EXCL)); 110 if (shm->id >= 0) { 111 return (shm); 112 } 113 if ((errno == EEXIST) && (flags & PR_SHM_EXCL)) { 114 PR_SetError(PR_FILE_EXISTS_ERROR, errno); 115 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 116 ("_MD_OpenSharedMemory(): shmget() exclusive failed, errno: %d", 117 errno)); 118 PR_FREEIF(shm->ipcname); 119 PR_DELETE(shm); 120 return (NULL); 121 } 122 } 123 124 shm->id = shmget(key, shm->size, shm->mode); 125 if (-1 == shm->id) { 126 _PR_MD_MAP_DEFAULT_ERROR(errno); 127 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 128 ("_MD_OpenSharedMemory(): shmget() failed, errno: %d", errno)); 129 PR_FREEIF(shm->ipcname); 130 PR_DELETE(shm); 131 return (NULL); 132 } 133 134 return (shm); 135 } /* end _MD_OpenSharedMemory() */ 136 137 extern void* _MD_AttachSharedMemory(PRSharedMemory* shm, PRIntn flags) { 138 void* addr; 139 PRUint32 aFlags = shm->mode; 140 141 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 142 143 aFlags |= (flags & PR_SHM_READONLY) ? SHM_RDONLY : 0; 144 145 addr = shmat(shm->id, NULL, aFlags); 146 if ((void*)-1 == addr) { 147 _PR_MD_MAP_DEFAULT_ERROR(errno); 148 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 149 ("_MD_AttachSharedMemory(): shmat() failed on name: %s, OsError: %d", 150 shm->ipcname, PR_GetOSError())); 151 addr = NULL; 152 } 153 154 return addr; 155 } 156 157 extern PRStatus _MD_DetachSharedMemory(PRSharedMemory* shm, void* addr) { 158 PRStatus rc = PR_SUCCESS; 159 PRIntn urc; 160 161 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 162 163 urc = shmdt(addr); 164 if (-1 == urc) { 165 rc = PR_FAILURE; 166 _PR_MD_MAP_DEFAULT_ERROR(errno); 167 PR_LOG( 168 _pr_shm_lm, PR_LOG_DEBUG, 169 ("_MD_DetachSharedMemory(): shmdt() failed on name: %s", shm->ipcname)); 170 } 171 172 return rc; 173 } 174 175 extern PRStatus _MD_CloseSharedMemory(PRSharedMemory* shm) { 176 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 177 178 PR_FREEIF(shm->ipcname); 179 PR_DELETE(shm); 180 181 return PR_SUCCESS; 182 } 183 184 extern PRStatus _MD_DeleteSharedMemory(const char* name) { 185 PRStatus rc = PR_SUCCESS; 186 key_t key; 187 int id; 188 PRIntn urc; 189 char ipcname[PR_IPC_NAME_SIZE]; 190 191 rc = _PR_MakeNativeIPCName(name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm); 192 if (PR_FAILURE == rc) { 193 PR_SetError(PR_UNKNOWN_ERROR, errno); 194 PR_LOG( 195 _pr_shm_lm, PR_LOG_DEBUG, 196 ("_MD_DeleteSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name)); 197 return (PR_FAILURE); 198 } 199 200 /* create the file first */ 201 { 202 int osfd = open(ipcname, (O_RDWR | O_CREAT), 0666); 203 if (-1 == osfd) { 204 _PR_MD_MAP_OPEN_ERROR(errno); 205 return (PR_FAILURE); 206 } 207 if (close(osfd) == -1) { 208 _PR_MD_MAP_CLOSE_ERROR(errno); 209 return (PR_FAILURE); 210 } 211 } 212 213 /* hash the shm.name to an ID */ 214 key = ftok(ipcname, NSPR_IPC_SHM_KEY); 215 if (-1 == key) { 216 rc = PR_FAILURE; 217 _PR_MD_MAP_DEFAULT_ERROR(errno); 218 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 219 ("_MD_DeleteSharedMemory(): ftok() failed on name: %s", ipcname)); 220 } 221 222 id = shmget(key, 0, 0); 223 if (-1 == id) { 224 _PR_MD_MAP_DEFAULT_ERROR(errno); 225 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 226 ("_MD_DeleteSharedMemory(): shmget() failed, errno: %d", errno)); 227 return (PR_FAILURE); 228 } 229 230 urc = shmctl(id, IPC_RMID, NULL); 231 if (-1 == urc) { 232 _PR_MD_MAP_DEFAULT_ERROR(errno); 233 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 234 ("_MD_DeleteSharedMemory(): shmctl() failed on name: %s", ipcname)); 235 return (PR_FAILURE); 236 } 237 238 urc = unlink(ipcname); 239 if (-1 == urc) { 240 _PR_MD_MAP_UNLINK_ERROR(errno); 241 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 242 ("_MD_DeleteSharedMemory(): unlink() failed: %s", ipcname)); 243 return (PR_FAILURE); 244 } 245 246 return rc; 247 } /* end _MD_DeleteSharedMemory() */ 248 249 /* 250 ** Implementation for Posix 251 */ 252 #elif defined PR_HAVE_POSIX_NAMED_SHARED_MEMORY 253 # include <sys/mman.h> 254 255 # define _MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory 256 # define _MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory 257 # define _MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory 258 # define _MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory 259 # define _MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory 260 261 struct _MDSharedMemory { 262 int handle; 263 }; 264 265 extern PRSharedMemory* _MD_OpenSharedMemory(const char* name, PRSize size, 266 PRIntn flags, PRIntn mode) { 267 PRStatus rc = PR_SUCCESS; 268 PRInt32 end; 269 PRSharedMemory* shm; 270 char ipcname[PR_IPC_NAME_SIZE]; 271 272 rc = _PR_MakeNativeIPCName(name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm); 273 if (PR_FAILURE == rc) { 274 PR_SetError(PR_UNKNOWN_ERROR, errno); 275 PR_LOG( 276 _pr_shm_lm, PR_LOG_DEBUG, 277 ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name)); 278 return (NULL); 279 } 280 281 shm = PR_NEWZAP(PRSharedMemory); 282 if (NULL == shm) { 283 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 284 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 285 ("PR_OpenSharedMemory: New PRSharedMemory out of memory")); 286 return (NULL); 287 } 288 289 shm->ipcname = PR_MALLOC(strlen(ipcname) + 1); 290 if (NULL == shm->ipcname) { 291 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); 292 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 293 ("PR_OpenSharedMemory: New shm->ipcname out of memory")); 294 return (NULL); 295 } 296 297 /* copy args to struct */ 298 strcpy(shm->ipcname, ipcname); 299 shm->size = size; 300 shm->mode = mode; 301 shm->flags = flags; 302 shm->ident = _PR_SHM_IDENT; 303 304 /* 305 ** Create the shared memory 306 */ 307 if (flags & PR_SHM_CREATE) { 308 int oflag = (O_CREAT | O_RDWR); 309 310 if (flags & PR_SHM_EXCL) { 311 oflag |= O_EXCL; 312 } 313 shm->id = shm_open(shm->ipcname, oflag, shm->mode); 314 } else { 315 shm->id = shm_open(shm->ipcname, O_RDWR, shm->mode); 316 } 317 318 if (-1 == shm->id) { 319 _PR_MD_MAP_DEFAULT_ERROR(errno); 320 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 321 ("_MD_OpenSharedMemory(): shm_open failed: %s, OSError: %d", 322 shm->ipcname, PR_GetOSError())); 323 PR_DELETE(shm->ipcname); 324 PR_DELETE(shm); 325 return (NULL); 326 } 327 328 end = ftruncate(shm->id, shm->size); 329 if (-1 == end) { 330 _PR_MD_MAP_DEFAULT_ERROR(errno); 331 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 332 ("_MD_OpenSharedMemory(): ftruncate failed, OSError: %d", 333 PR_GetOSError())); 334 PR_DELETE(shm->ipcname); 335 PR_DELETE(shm); 336 return (NULL); 337 } 338 339 return (shm); 340 } /* end _MD_OpenSharedMemory() */ 341 342 extern void* _MD_AttachSharedMemory(PRSharedMemory* shm, PRIntn flags) { 343 void* addr; 344 PRIntn prot = (PROT_READ | PROT_WRITE); 345 346 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 347 348 if (PR_SHM_READONLY == flags) { 349 prot ^= PROT_WRITE; 350 } 351 352 addr = mmap((void*)0, shm->size, prot, MAP_SHARED, shm->id, 0); 353 if ((void*)-1 == addr) { 354 _PR_MD_MAP_DEFAULT_ERROR(errno); 355 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 356 ("_MD_AttachSharedMemory(): mmap failed: %s, errno: %d", 357 shm->ipcname, PR_GetOSError())); 358 addr = NULL; 359 } else { 360 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 361 ("_MD_AttachSharedMemory(): name: %s, attached at: %p", shm->ipcname, 362 addr)); 363 } 364 365 return addr; 366 } 367 368 extern PRStatus _MD_DetachSharedMemory(PRSharedMemory* shm, void* addr) { 369 PRStatus rc = PR_SUCCESS; 370 PRIntn urc; 371 372 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 373 374 urc = munmap(addr, shm->size); 375 if (-1 == urc) { 376 rc = PR_FAILURE; 377 _PR_MD_MAP_DEFAULT_ERROR(errno); 378 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 379 ("_MD_DetachSharedMemory(): munmap failed: %s, errno: %d", 380 shm->ipcname, PR_GetOSError())); 381 } 382 return rc; 383 } 384 385 extern PRStatus _MD_CloseSharedMemory(PRSharedMemory* shm) { 386 int urc; 387 388 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 389 390 urc = close(shm->id); 391 if (-1 == urc) { 392 _PR_MD_MAP_CLOSE_ERROR(errno); 393 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 394 ("_MD_CloseSharedMemory(): close() failed, error: %d", 395 PR_GetOSError())); 396 return (PR_FAILURE); 397 } 398 PR_DELETE(shm->ipcname); 399 PR_DELETE(shm); 400 return PR_SUCCESS; 401 } 402 403 extern PRStatus _MD_DeleteSharedMemory(const char* name) { 404 PRStatus rc = PR_SUCCESS; 405 PRUintn urc; 406 char ipcname[PR_IPC_NAME_SIZE]; 407 408 rc = _PR_MakeNativeIPCName(name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm); 409 if (PR_FAILURE == rc) { 410 PR_SetError(PR_UNKNOWN_ERROR, errno); 411 PR_LOG( 412 _pr_shm_lm, PR_LOG_DEBUG, 413 ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name)); 414 return rc; 415 } 416 417 urc = shm_unlink(ipcname); 418 if (-1 == urc) { 419 rc = PR_FAILURE; 420 _PR_MD_MAP_DEFAULT_ERROR(errno); 421 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 422 ("_MD_DeleteSharedMemory(): shm_unlink failed: %s, errno: %d", 423 ipcname, PR_GetOSError())); 424 } else { 425 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 426 ("_MD_DeleteSharedMemory(): %s, success", ipcname)); 427 } 428 429 return rc; 430 } /* end _MD_DeleteSharedMemory() */ 431 #endif 432 433 /* 434 ** Unix implementation for anonymous memory (file) mapping 435 */ 436 extern PRLogModuleInfo* _pr_shma_lm; 437 438 #include <unistd.h> 439 440 extern PRFileMap* _md_OpenAnonFileMap(const char* dirName, PRSize size, 441 PRFileMapProtect prot) { 442 PRFileMap* fm = NULL; 443 PRFileDesc* fd; 444 int osfd; 445 PRIntn urc; 446 PRIntn mode = 0600; 447 char* genName; 448 pid_t pid = getpid(); /* for generating filename */ 449 PRThread* tid = PR_GetCurrentThread(); /* for generating filename */ 450 int incr; /* for generating filename */ 451 const int maxTries = 20; /* maximum # attempts at a unique filename */ 452 PRInt64 size64; /* 64-bit version of 'size' */ 453 454 /* 455 ** generate a filename from input and runtime environment 456 ** open the file, unlink the file. 457 ** make maxTries number of attempts at uniqueness in the filename 458 */ 459 for (incr = 0; incr < maxTries; incr++) { 460 #define NSPR_AFM_FILENAME "%s/.NSPR-AFM-%d-%p.%d" 461 genName = PR_smprintf(NSPR_AFM_FILENAME, dirName, (int)pid, tid, incr); 462 if (NULL == genName) { 463 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 464 ("_md_OpenAnonFileMap(): PR_snprintf(): failed, generating " 465 "filename")); 466 goto Finished; 467 } 468 469 /* create the file */ 470 osfd = open(genName, (O_CREAT | O_EXCL | O_RDWR), mode); 471 if (-1 == osfd) { 472 if (EEXIST == errno) { 473 PR_smprintf_free(genName); 474 continue; /* name exists, try again */ 475 } 476 _PR_MD_MAP_OPEN_ERROR(errno); 477 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 478 ("_md_OpenAnonFileMap(): open(): failed, filename: %s, errno: %d", 479 genName, PR_GetOSError())); 480 PR_smprintf_free(genName); 481 goto Finished; 482 } 483 break; /* name generation and open successful, break; */ 484 } /* end for() */ 485 486 if (incr == maxTries) { 487 PR_ASSERT(-1 == osfd); 488 PR_ASSERT(EEXIST == errno); 489 _PR_MD_MAP_OPEN_ERROR(errno); 490 goto Finished; 491 } 492 493 urc = unlink(genName); 494 if (-1 == urc) { 495 _PR_MD_MAP_UNLINK_ERROR(errno); 496 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 497 ("_md_OpenAnonFileMap(): failed on unlink(), errno: %d", errno)); 498 PR_smprintf_free(genName); 499 close(osfd); 500 goto Finished; 501 } 502 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 503 ("_md_OpenAnonFileMap(): unlink(): %s", genName)); 504 505 PR_smprintf_free(genName); 506 507 fd = PR_ImportFile(osfd); 508 if (NULL == fd) { 509 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 510 ("_md_OpenAnonFileMap(): PR_ImportFile(): failed")); 511 goto Finished; 512 } 513 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): fd: %p", fd)); 514 515 urc = ftruncate(fd->secret->md.osfd, size); 516 if (-1 == urc) { 517 _PR_MD_MAP_DEFAULT_ERROR(errno); 518 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 519 ("_md_OpenAnonFileMap(): failed on ftruncate(), errno: %d", errno)); 520 PR_Close(fd); 521 goto Finished; 522 } 523 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 524 ("_md_OpenAnonFileMap(): ftruncate(): size: %d", size)); 525 526 LL_UI2L(size64, size); /* PRSize (size_t) is unsigned */ 527 fm = PR_CreateFileMap(fd, size64, prot); 528 if (NULL == fm) { 529 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, ("PR_OpenAnonFileMap(): failed")); 530 PR_Close(fd); 531 goto Finished; 532 } 533 fm->md.isAnonFM = PR_TRUE; /* set fd close */ 534 535 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 536 ("_md_OpenAnonFileMap(): PR_CreateFileMap(): fm: %p", fm)); 537 538 Finished: 539 return (fm); 540 } /* end md_OpenAnonFileMap() */ 541 542 /* 543 ** _md_ExportFileMapAsString() 544 ** 545 ** 546 */ 547 extern PRStatus _md_ExportFileMapAsString(PRFileMap* fm, PRSize bufSize, 548 char* buf) { 549 PRIntn written; 550 PRIntn prot = (PRIntn)fm->prot; 551 552 written = PR_snprintf(buf, bufSize, "%ld:%d", fm->fd->secret->md.osfd, prot); 553 554 return ((written == -1) ? PR_FAILURE : PR_SUCCESS); 555 } /* end _md_ExportFileMapAsString() */ 556 557 extern PRFileMap* _md_ImportFileMapFromString(const char* fmstring) { 558 PRStatus rc; 559 PRInt32 osfd; 560 PRIntn prot; /* really: a PRFileMapProtect */ 561 PRFileDesc* fd; 562 PRFileMap* fm = NULL; /* default return value */ 563 PRFileInfo64 info; 564 565 PR_sscanf(fmstring, "%ld:%d", &osfd, &prot); 566 567 /* import the os file descriptor */ 568 fd = PR_ImportFile(osfd); 569 if (NULL == fd) { 570 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 571 ("_md_ImportFileMapFromString(): PR_ImportFile() failed")); 572 goto Finished; 573 } 574 575 rc = PR_GetOpenFileInfo64(fd, &info); 576 if (PR_FAILURE == rc) { 577 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 578 ("_md_ImportFileMapFromString(): PR_GetOpenFileInfo64() failed")); 579 goto Finished; 580 } 581 582 fm = PR_CreateFileMap(fd, info.size, (PRFileMapProtect)prot); 583 if (NULL == fm) { 584 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 585 ("_md_ImportFileMapFromString(): PR_CreateFileMap() failed")); 586 } 587 588 Finished: 589 return (fm); 590 } /* end _md_ImportFileMapFromString() */