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