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