tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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() */