tor-browser

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

anonfm.c (7199B)


      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 ** File: anonfm.c
      8 ** Description: Test anonymous file map
      9 **
     10 ** Synopsis: anonfm [options] [dirName]
     11 **
     12 ** Options:
     13 ** -d   enable debug mode
     14 ** -h   display a help message
     15 ** -s <n>  size of the anonymous memory map, in KBytes. default: 100KBytes.
     16 ** -C 1 Operate this process as ClientOne()
     17 ** -C 2 Operate this process as ClientTwo()
     18 **
     19 ** anonfn.c contains two tests, corresponding to the two protocols for
     20 ** passing an anonymous file map to a child process.
     21 **
     22 ** ServerOne()/ClientOne() tests the passing of "raw" file map; it uses
     23 ** PR_CreateProcess() [for portability of the test case] to create the
     24 ** child process, but does not use the PRProcessAttr structure for
     25 ** passing the file map data.
     26 **
     27 ** ServerTwo()/ClientTwo() tests the passing of the file map using the
     28 ** PRProcessAttr structure.
     29 **
     30 */
     31 #include <plgetopt.h>
     32 #include <nspr.h>
     33 #include <private/primpl.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <string.h>
     37 
     38 /*
     39 ** Test harness infrastructure
     40 */
     41 PRLogModuleInfo* lm;
     42 PRLogModuleLevel msgLevel = PR_LOG_NONE;
     43 PRUint32 failed_already = 0;
     44 
     45 PRIntn debug = 0;
     46 PRIntn client = 0;       /* invoke client, style */
     47 char dirName[512] = "."; /* directory name to contain anon mapped file */
     48 PRSize fmSize = (100 * 1024);
     49 PRUint32 fmMode = 0600;
     50 PRFileMapProtect fmProt = PR_PROT_READWRITE;
     51 const char* fmEnvName = "nsprFileMapEnvVariable";
     52 
     53 /*
     54 ** Emit help text for this test
     55 */
     56 static void Help(void) {
     57  printf("anonfm [options] [dirName]\n");
     58  printf("-d -- enable debug mode\n");
     59  printf(
     60      "dirName is alternate directory name. Default: . (current directory)\n");
     61  exit(1);
     62 } /* end Help() */
     63 
     64 /*
     65 ** ClientOne() --
     66 */
     67 static void ClientOne(void) {
     68  PRFileMap* fm;
     69  char* fmString;
     70  char* addr;
     71  PRStatus rc;
     72 
     73  PR_LOG(lm, msgLevel, ("ClientOne() starting"));
     74 
     75  fmString = PR_GetEnv(fmEnvName);
     76  if (NULL == fmString) {
     77    failed_already = 1;
     78    PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv() failed"));
     79    return;
     80  }
     81  PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv(): found: %s", fmString));
     82 
     83  fm = PR_ImportFileMapFromString(fmString);
     84  if (NULL == fm) {
     85    failed_already = 1;
     86    PR_LOG(lm, msgLevel, ("ClientOne(): PR_ImportFileMapFromString() failed"));
     87    return;
     88  }
     89  PR_LOG(lm, msgLevel,
     90         ("ClientOne(): PR_ImportFileMapFromString(): fm: %p", fm));
     91 
     92  addr = PR_MemMap(fm, LL_ZERO, fmSize);
     93  if (NULL == addr) {
     94    failed_already = 1;
     95    PR_LOG(lm, msgLevel,
     96           ("ClientOne(): PR_MemMap() failed, OSError: %d", PR_GetOSError()));
     97    return;
     98  }
     99  PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemMap(): addr: %p", addr));
    100 
    101  /* write to memory map to release server */
    102  *addr = 1;
    103 
    104  rc = PR_MemUnmap(addr, fmSize);
    105  PR_ASSERT(rc == PR_SUCCESS);
    106  PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemUnap(): success"));
    107 
    108  rc = PR_CloseFileMap(fm);
    109  if (PR_FAILURE == rc) {
    110    failed_already = 1;
    111    PR_LOG(lm, msgLevel,
    112           ("ClientOne(): PR_MemUnap() failed, OSError: %d", PR_GetOSError()));
    113    return;
    114  }
    115  PR_LOG(lm, msgLevel, ("ClientOne(): PR_CloseFileMap(): success"));
    116 
    117  return;
    118 } /* end ClientOne() */
    119 
    120 /*
    121 ** ClientTwo() --
    122 */
    123 static void ClientTwo(void) { failed_already = 1; } /* end ClientTwo() */
    124 
    125 /*
    126 ** ServerOne() --
    127 */
    128 static void ServerOne(void) {
    129  PRFileMap* fm;
    130  PRStatus rc;
    131  PRIntn i;
    132  char* addr;
    133  char fmString[256];
    134  char envBuf[256];
    135  char* child_argv[8];
    136  PRProcess* proc;
    137  PRInt32 exit_status;
    138 
    139  PR_LOG(lm, msgLevel, ("ServerOne() starting"));
    140 
    141  fm = PR_OpenAnonFileMap(dirName, fmSize, fmProt);
    142  if (NULL == fm) {
    143    failed_already = 1;
    144    PR_LOG(lm, msgLevel, ("PR_OpenAnonFileMap() failed"));
    145    return;
    146  }
    147  PR_LOG(lm, msgLevel, ("ServerOne(): FileMap: %p", fm));
    148 
    149  rc = PR_ExportFileMapAsString(fm, sizeof(fmString), fmString);
    150  if (PR_FAILURE == rc) {
    151    failed_already = 1;
    152    PR_LOG(lm, msgLevel, ("PR_ExportFileMap() failed"));
    153    return;
    154  }
    155 
    156  /*
    157  ** put the string into the environment
    158  */
    159  PR_snprintf(envBuf, sizeof(envBuf), "%s=%s", fmEnvName, fmString);
    160  putenv(envBuf);
    161 
    162  addr = PR_MemMap(fm, LL_ZERO, fmSize);
    163  if (NULL == addr) {
    164    failed_already = 1;
    165    PR_LOG(lm, msgLevel, ("PR_MemMap() failed"));
    166    return;
    167  }
    168 
    169  /* set initial value for client */
    170  for (i = 0; i < (PRIntn)fmSize; i++) {
    171    *(addr + i) = 0x00;
    172  }
    173 
    174  PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemMap(): addr: %p", addr));
    175 
    176  /*
    177  ** set arguments for child process
    178  */
    179  child_argv[0] = "anonfm";
    180  child_argv[1] = "-C";
    181  child_argv[2] = "1";
    182  child_argv[3] = NULL;
    183 
    184  proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
    185  PR_ASSERT(proc);
    186  PR_LOG(lm, msgLevel, ("ServerOne(): PR_CreateProcess(): proc: %x", proc));
    187 
    188  /*
    189  ** ClientOne() will set the memory to 1
    190  */
    191  PR_LOG(lm, msgLevel, ("ServerOne(): waiting on Client, *addr: %x", *addr));
    192  while (*addr == 0x00) {
    193    if (debug) {
    194      fprintf(stderr, ".");
    195    }
    196    PR_Sleep(PR_MillisecondsToInterval(300));
    197  }
    198  if (debug) {
    199    fprintf(stderr, "\n");
    200  }
    201  PR_LOG(lm, msgLevel, ("ServerOne(): Client responded"));
    202 
    203  rc = PR_WaitProcess(proc, &exit_status);
    204  PR_ASSERT(PR_FAILURE != rc);
    205 
    206  rc = PR_MemUnmap(addr, fmSize);
    207  if (PR_FAILURE == rc) {
    208    failed_already = 1;
    209    PR_LOG(lm, msgLevel, ("PR_MemUnmap() failed"));
    210    return;
    211  }
    212  PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemUnmap(): success"));
    213 
    214  rc = PR_CloseFileMap(fm);
    215  if (PR_FAILURE == rc) {
    216    failed_already = 1;
    217    PR_LOG(lm, msgLevel, ("PR_CloseFileMap() failed"));
    218    return;
    219  }
    220  PR_LOG(lm, msgLevel, ("ServerOne(): PR_CloseFileMap() success"));
    221 
    222  return;
    223 } /* end ServerOne() */
    224 
    225 /*
    226 ** ServerTwo() --
    227 */
    228 static void ServerTwo(void) {
    229  PR_LOG(lm, msgLevel, ("ServerTwo(): Not implemented yet"));
    230 } /* end ServerTwo() */
    231 
    232 int main(int argc, char** argv) {
    233  {
    234    /*
    235    ** Get command line options
    236    */
    237    PLOptStatus os;
    238    PLOptState* opt = PL_CreateOptState(argc, argv, "hdC:");
    239 
    240    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    241      if (PL_OPT_BAD == os) {
    242        continue;
    243      }
    244      switch (opt->option) {
    245        case 'C': /* Client style */
    246          client = atol(opt->value);
    247          break;
    248        case 's': /* file size */
    249          fmSize = atol(opt->value) * 1024;
    250          break;
    251        case 'd': /* debug */
    252          debug = 1;
    253          msgLevel = PR_LOG_DEBUG;
    254          break;
    255        case 'h': /* help message */
    256          Help();
    257          break;
    258        default:
    259          strcpy(dirName, opt->value);
    260          break;
    261      }
    262    }
    263    PL_DestroyOptState(opt);
    264  }
    265 
    266  lm = PR_NewLogModule("Test"); /* Initialize logging */
    267 
    268  if (client == 1) {
    269    ClientOne();
    270  } else if (client == 2) {
    271    ClientTwo();
    272  } else {
    273    ServerOne();
    274    if (failed_already) {
    275      goto Finished;
    276    }
    277    ServerTwo();
    278  }
    279 
    280 Finished:
    281  if (debug) {
    282    printf("%s\n", (failed_already) ? "FAIL" : "PASS");
    283  }
    284  return ((failed_already == PR_TRUE) ? 1 : 0);
    285 } /* main() */
    286 /* end anonfm.c */