/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: anonfm.c ** Description: Test anonymous file map ** ** Synopsis: anonfm [options] [dirName] ** ** Options: ** -d enable debug mode ** -h display a help message ** -s size of the anonymous memory map, in KBytes. default: 100KBytes. ** -C 1 Operate this process as ClientOne() ** -C 2 Operate this process as ClientTwo() ** ** anonfn.c contains two tests, corresponding to the two protocols for ** passing an anonymous file map to a child process. ** ** ServerOne()/ClientOne() tests the passing of "raw" file map; it uses ** PR_CreateProcess() [for portability of the test case] to create the ** child process, but does not use the PRProcessAttr structure for ** passing the file map data. ** ** ServerTwo()/ClientTwo() tests the passing of the file map using the ** PRProcessAttr structure. ** */ #include #include #include #include #include #include /* ** Test harness infrastructure */ PRLogModuleInfo *lm; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRUint32 failed_already = 0; PRIntn debug = 0; PRIntn client = 0; /* invoke client, style */ char dirName[512] = "."; /* directory name to contain anon mapped file */ PRSize fmSize = (100 * 1024 ); PRUint32 fmMode = 0600; PRFileMapProtect fmProt = PR_PROT_READWRITE; const char *fmEnvName = "nsprFileMapEnvVariable"; /* ** Emit help text for this test */ static void Help( void ) { printf("anonfm [options] [dirName]\n"); printf("-d -- enable debug mode\n"); printf("dirName is alternate directory name. Default: . (current directory)\n"); exit(1); } /* end Help() */ /* ** ClientOne() -- */ static void ClientOne( void ) { PRFileMap *fm; char *fmString; char *addr; PRStatus rc; PR_LOG(lm, msgLevel, ("ClientOne() starting")); fmString = PR_GetEnv( fmEnvName ); if ( NULL == fmString ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv() failed")); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv(): found: %s", fmString)); fm = PR_ImportFileMapFromString( fmString ); if ( NULL == fm ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_ImportFileMapFromString() failed")); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_ImportFileMapFromString(): fm: %p", fm )); addr = PR_MemMap( fm, LL_ZERO, fmSize ); if ( NULL == addr ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemMap() failed, OSError: %d", PR_GetOSError() )); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemMap(): addr: %p", addr )); /* write to memory map to release server */ *addr = 1; rc = PR_MemUnmap( addr, fmSize ); PR_ASSERT( rc == PR_SUCCESS ); PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemUnap(): success" )); rc = PR_CloseFileMap( fm ); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemUnap() failed, OSError: %d", PR_GetOSError() )); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_CloseFileMap(): success" )); return; } /* end ClientOne() */ /* ** ClientTwo() -- */ static void ClientTwo( void ) { failed_already = 1; } /* end ClientTwo() */ /* ** ServerOne() -- */ static void ServerOne( void ) { PRFileMap *fm; PRStatus rc; PRIntn i; char *addr; char fmString[256]; char envBuf[256]; char *child_argv[8]; PRProcess *proc; PRInt32 exit_status; PR_LOG(lm, msgLevel, ("ServerOne() starting")); fm = PR_OpenAnonFileMap( dirName, fmSize, fmProt ); if ( NULL == fm ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_OpenAnonFileMap() failed")); return; } PR_LOG(lm, msgLevel, ("ServerOne(): FileMap: %p", fm )); rc = PR_ExportFileMapAsString( fm, sizeof(fmString), fmString ); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_ExportFileMap() failed")); return; } /* ** put the string into the environment */ PR_snprintf( envBuf, sizeof(envBuf), "%s=%s", fmEnvName, fmString); putenv( envBuf ); addr = PR_MemMap( fm, LL_ZERO, fmSize ); if ( NULL == addr ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_MemMap() failed")); return; } /* set initial value for client */ for (i = 0; i < (PRIntn)fmSize ; i++ ) { *(addr+i) = 0x00; } PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemMap(): addr: %p", addr )); /* ** set arguments for child process */ child_argv[0] = "anonfm"; child_argv[1] = "-C"; child_argv[2] = "1"; child_argv[3] = NULL; proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); PR_ASSERT( proc ); PR_LOG(lm, msgLevel, ("ServerOne(): PR_CreateProcess(): proc: %x", proc )); /* ** ClientOne() will set the memory to 1 */ PR_LOG(lm, msgLevel, ("ServerOne(): waiting on Client, *addr: %x", *addr )); while( *addr == 0x00 ) { if ( debug ) { fprintf(stderr, "."); } PR_Sleep(PR_MillisecondsToInterval(300)); } if ( debug ) { fprintf(stderr, "\n"); } PR_LOG(lm, msgLevel, ("ServerOne(): Client responded" )); rc = PR_WaitProcess( proc, &exit_status ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_MemUnmap( addr, fmSize); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_MemUnmap() failed")); return; } PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemUnmap(): success" )); rc = PR_CloseFileMap(fm); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_CloseFileMap() failed")); return; } PR_LOG(lm, msgLevel, ("ServerOne(): PR_CloseFileMap() success" )); return; } /* end ServerOne() */ /* ** ServerTwo() -- */ static void ServerTwo( void ) { PR_LOG(lm, msgLevel, ("ServerTwo(): Not implemented yet" )); } /* end ServerTwo() */ int main(int argc, char **argv) { { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hdC:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) { continue; } switch (opt->option) { case 'C': /* Client style */ client = atol(opt->value); break; case 's': /* file size */ fmSize = atol( opt->value ) * 1024; break; case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_DEBUG; break; case 'h': /* help message */ Help(); break; default: strcpy(dirName, opt->value); break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ if ( client == 1 ) { ClientOne(); } else if ( client == 2 ) { ClientTwo(); } else { ServerOne(); if ( failed_already ) { goto Finished; } ServerTwo(); } Finished: if ( debug ) { printf("%s\n", (failed_already)? "FAIL" : "PASS"); } return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */ /* end anonfm.c */