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