tor-browser

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

testfile.c (23420B)


      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 #include "nspr.h"
      7 #include "prpriv.h"
      8 
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 #ifdef WIN32
     13 #  include <windows.h>
     14 #  include <process.h>
     15 #endif
     16 #if defined(_PR_PTHREADS)
     17 #  include <pthread.h>
     18 #endif
     19 
     20 #if defined(XP_UNIX)
     21 #  include <unistd.h>
     22 #endif
     23 
     24 static int _debug_on = 0;
     25 
     26 #ifdef WINCE
     27 #  define setbuf(x, y)
     28 #endif
     29 
     30 #ifdef XP_WIN
     31 #  define mode_t int
     32 #endif
     33 
     34 #define DPRINTF(arg) \
     35  if (_debug_on) printf arg
     36 
     37 PRLock* lock;
     38 PRMonitor* mon;
     39 PRInt32 count;
     40 int thread_count;
     41 
     42 #define BUF_DATA_SIZE 256 * 1024
     43 
     44 #define NUM_RDWR_THREADS 10
     45 #define NUM_DIRTEST_THREADS 4
     46 #define CHUNK_SIZE 512
     47 
     48 typedef struct buffer {
     49  char data[BUF_DATA_SIZE];
     50 } buffer;
     51 
     52 typedef struct File_Rdwr_Param {
     53  char* pathname;
     54  char* buf;
     55  int offset;
     56  int len;
     57 } File_Rdwr_Param;
     58 
     59 #ifdef XP_PC
     60 char* TEST_DIR = "C:\\temp\\prdir";
     61 char* FILE_NAME = "pr_testfile";
     62 char* HIDDEN_FILE_NAME = "hidden_pr_testfile";
     63 #else
     64 char* TEST_DIR = "./tmp-testfile_dir";
     65 char* FILE_NAME = "pr_testfile";
     66 char* HIDDEN_FILE_NAME = ".hidden_pr_testfile";
     67 #endif
     68 buffer *in_buf, *out_buf;
     69 char pathname[256], renamename[256];
     70 #ifdef WINCE
     71 WCHAR wPathname[256];
     72 #endif
     73 #define TMPDIR_LEN 64
     74 char testdir[TMPDIR_LEN];
     75 static PRInt32 PR_CALLBACK DirTest(void* argunused);
     76 PRInt32 dirtest_failed = 0;
     77 
     78 #if defined(_PR_PTHREADS)
     79 typedef void* (*nativeStartType)(void*);
     80 #elif defined(WIN32)
     81 typedef unsigned(__stdcall* nativeStartType)(void*);
     82 #else
     83 typedef void (*nativeStartType)(void*);
     84 #endif
     85 
     86 #if defined(_PR_PTHREADS)
     87 static void* PR_CALLBACK DirTestWrapper(void* argunused) {
     88  (void)DirTest(argunused);
     89  return NULL;
     90 }
     91 #elif defined(WIN32)
     92 static unsigned __stdcall DirTestWrapper(void* argunused) {
     93  (void)DirTest(argunused);
     94  return 0;
     95 }
     96 #else
     97 static void PR_CALLBACK DirTestWrapper(void* argunused) {
     98  (void)DirTest(argunused);
     99 }
    100 #endif
    101 
    102 static void PR_CALLBACK DirTestVoid(void* argunused) {
    103  (void)DirTest(argunused);
    104 }
    105 
    106 PRThread* create_new_thread(PRThreadType type, nativeStartType nativeStart,
    107                            void (*prStart)(void*), void* arg,
    108                            PRThreadPriority priority, PRThreadScope scope,
    109                            PRThreadState state, PRUint32 stackSize,
    110                            PRInt32 index) {
    111  PRInt32 native_thread = 0;
    112 
    113  PR_ASSERT(state == PR_UNJOINABLE_THREAD);
    114 
    115 #if defined(_PR_PTHREADS) || defined(WIN32)
    116 
    117  switch (index % 4) {
    118    case 0:
    119      scope = (PR_LOCAL_THREAD);
    120      break;
    121    case 1:
    122      scope = (PR_GLOBAL_THREAD);
    123      break;
    124    case 2:
    125      scope = (PR_GLOBAL_BOUND_THREAD);
    126      break;
    127    case 3:
    128      native_thread = 1;
    129      break;
    130    default:
    131      PR_NOT_REACHED("Invalid scope");
    132      break;
    133  }
    134  if (native_thread) {
    135 #  if defined(_PR_PTHREADS)
    136    pthread_t tid;
    137    if (!pthread_create(&tid, NULL, nativeStart, arg)) {
    138      return ((PRThread*)tid);
    139    } else {
    140      return (NULL);
    141    }
    142 #  else
    143    HANDLE thandle;
    144    unsigned tid;
    145 
    146    thandle = (HANDLE)_beginthreadex(NULL, stackSize, nativeStart, arg,
    147                                     STACK_SIZE_PARAM_IS_A_RESERVATION, &tid);
    148    return ((PRThread*)thandle);
    149 #  endif
    150  } else {
    151    return (
    152        PR_CreateThread(type, prStart, arg, priority, scope, state, stackSize));
    153  }
    154 #else
    155  return (
    156      PR_CreateThread(type, prStart, arg, priority, scope, state, stackSize));
    157 #endif
    158 }
    159 
    160 static void PR_CALLBACK File_Write(void* arg) {
    161  PRFileDesc* fd_file;
    162  File_Rdwr_Param* fp = (File_Rdwr_Param*)arg;
    163  char *name, *buf;
    164  int offset, len;
    165 
    166  setbuf(stdout, NULL);
    167  name = fp->pathname;
    168  buf = fp->buf;
    169  offset = fp->offset;
    170  len = fp->len;
    171 
    172  fd_file = PR_Open(name, PR_RDWR | PR_CREATE_FILE, 0777);
    173  if (fd_file == NULL) {
    174    printf("testfile failed to create/open file %s\n", name);
    175    return;
    176  }
    177  if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) {
    178    printf("testfile failed to seek in file %s\n", name);
    179    return;
    180  }
    181  if ((PR_Write(fd_file, buf, len)) < 0) {
    182    printf("testfile failed to write to file %s\n", name);
    183    return;
    184  }
    185  DPRINTF(("Write out_buf[0] = 0x%x\n", (*((int*)buf))));
    186  PR_Close(fd_file);
    187  PR_DELETE(fp);
    188 
    189  PR_EnterMonitor(mon);
    190  --thread_count;
    191  PR_Notify(mon);
    192  PR_ExitMonitor(mon);
    193 }
    194 
    195 #if defined(_PR_PTHREADS)
    196 static void* PR_CALLBACK File_Write_Wrapper(void* argunused) {
    197  (void)File_Write(argunused);
    198  return NULL;
    199 }
    200 #elif defined(WIN32)
    201 static unsigned __stdcall File_Write_Wrapper(void* argunused) {
    202  (void)File_Write(argunused);
    203  return 0;
    204 }
    205 #else
    206 static void PR_CALLBACK File_Write_Wrapper(void* argunused) {
    207  (void)File_Write(argunused);
    208 }
    209 #endif
    210 
    211 static void PR_CALLBACK File_Read(void* arg) {
    212  PRFileDesc* fd_file;
    213  File_Rdwr_Param* fp = (File_Rdwr_Param*)arg;
    214  char *name, *buf;
    215  int offset, len;
    216 
    217  setbuf(stdout, NULL);
    218  name = fp->pathname;
    219  buf = fp->buf;
    220  offset = fp->offset;
    221  len = fp->len;
    222 
    223  fd_file = PR_Open(name, PR_RDONLY, 0);
    224  if (fd_file == NULL) {
    225    printf("testfile failed to open file %s\n", name);
    226    return;
    227  }
    228  if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) {
    229    printf("testfile failed to seek in file %s\n", name);
    230    return;
    231  }
    232  if ((PR_Read(fd_file, buf, len)) < 0) {
    233    printf("testfile failed to read to file %s\n", name);
    234    return;
    235  }
    236  DPRINTF(("Read in_buf[0] = 0x%x\n", (*((int*)buf))));
    237  PR_Close(fd_file);
    238  PR_DELETE(fp);
    239 
    240  PR_EnterMonitor(mon);
    241  --thread_count;
    242  PR_Notify(mon);
    243  PR_ExitMonitor(mon);
    244 }
    245 
    246 #if defined(_PR_PTHREADS)
    247 static void* PR_CALLBACK File_Read_Wrapper(void* argunused) {
    248  (void)File_Read(argunused);
    249  return NULL;
    250 }
    251 #elif defined(WIN32)
    252 static unsigned __stdcall File_Read_Wrapper(void* argunused) {
    253  (void)File_Read(argunused);
    254  return 0;
    255 }
    256 #else
    257 static void PR_CALLBACK File_Read_Wrapper(void* argunused) {
    258  (void)File_Read(argunused);
    259 }
    260 #endif
    261 
    262 static PRInt32 Misc_File_Tests(char* pathname) {
    263  PRFileDesc* fd_file;
    264  int len, rv = 0;
    265  PRFileInfo file_info, file_info1;
    266  char tmpname[1024];
    267 
    268  setbuf(stdout, NULL);
    269  /*
    270   * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
    271   */
    272 
    273  fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
    274 
    275  if (fd_file == NULL) {
    276    printf("testfile failed to create/open file %s\n", pathname);
    277    return -1;
    278  }
    279  if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
    280    printf("testfile PR_GetFileInfo failed on file %s\n", pathname);
    281    rv = -1;
    282    goto cleanup;
    283  }
    284  if (PR_Access(pathname, PR_ACCESS_EXISTS) != 0) {
    285    printf("testfile PR_Access failed on file %s\n", pathname);
    286    rv = -1;
    287    goto cleanup;
    288  }
    289  if (PR_Access(pathname, PR_ACCESS_WRITE_OK) != 0) {
    290    printf("testfile PR_Access failed on file %s\n", pathname);
    291    rv = -1;
    292    goto cleanup;
    293  }
    294  if (PR_Access(pathname, PR_ACCESS_READ_OK) != 0) {
    295    printf("testfile PR_Access failed on file %s\n", pathname);
    296    rv = -1;
    297    goto cleanup;
    298  }
    299 
    300  if (PR_GetFileInfo(pathname, &file_info) < 0) {
    301    printf("testfile PR_GetFileInfo failed on file %s\n", pathname);
    302    rv = -1;
    303    goto cleanup;
    304  }
    305  if (file_info.type != PR_FILE_FILE) {
    306    printf(
    307        "testfile: Error - PR_GetFileInfo returned incorrect type for file "
    308        "%s\n",
    309        pathname);
    310    rv = -1;
    311    goto cleanup;
    312  }
    313  if (file_info.size != 0) {
    314    printf(
    315        "testfile PR_GetFileInfo returned incorrect size (%d should be 0) for "
    316        "file %s\n",
    317        file_info.size, pathname);
    318    rv = -1;
    319    goto cleanup;
    320  }
    321  file_info1 = file_info;
    322 
    323  len = PR_Available(fd_file);
    324  if (len < 0) {
    325    printf("testfile PR_Available failed on file %s\n", pathname);
    326    rv = -1;
    327    goto cleanup;
    328  } else if (len != 0) {
    329    printf("testfile PR_Available failed: expected/returned = %d/%d bytes\n", 0,
    330           len);
    331    rv = -1;
    332    goto cleanup;
    333  }
    334  if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
    335    printf("testfile PR_GetFileInfo failed on file %s\n", pathname);
    336    goto cleanup;
    337  }
    338  if (LL_NE(file_info.creationTime, file_info1.creationTime)) {
    339    printf(
    340        "testfile PR_GetFileInfo returned incorrect status-change time: %s\n",
    341        pathname);
    342    printf("ft = %lld, ft1 = %lld\n", (long long)file_info.creationTime,
    343           (long long)file_info1.creationTime);
    344    rv = -1;
    345    goto cleanup;
    346  }
    347  len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
    348  if (len < 0) {
    349    printf("testfile failed to write to file %s\n", pathname);
    350    rv = -1;
    351    goto cleanup;
    352  }
    353  if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) {
    354    printf("testfile PR_GetFileInfo failed on file %s\n", pathname);
    355    goto cleanup;
    356  }
    357  if (file_info.size != CHUNK_SIZE) {
    358    printf(
    359        "testfile PR_GetFileInfo returned incorrect size (%d should be %d) for "
    360        "file %s\n",
    361        file_info.size, CHUNK_SIZE, pathname);
    362    rv = -1;
    363    goto cleanup;
    364  }
    365  if (LL_CMP(file_info.modifyTime, <, file_info1.modifyTime)) {
    366    printf("testfile PR_GetFileInfo returned incorrect modify time: %s\n",
    367           pathname);
    368    printf("ft = %lld, ft1 = %lld\n", (long long)file_info.modifyTime,
    369           (long long)file_info1.modifyTime);
    370    rv = -1;
    371    goto cleanup;
    372  }
    373 
    374  len = PR_Available(fd_file);
    375  if (len < 0) {
    376    printf("testfile PR_Available failed on file %s\n", pathname);
    377    rv = -1;
    378    goto cleanup;
    379  } else if (len != 0) {
    380    printf("testfile PR_Available failed: expected/returned = %d/%d bytes\n", 0,
    381           len);
    382    rv = -1;
    383    goto cleanup;
    384  }
    385 
    386  PR_Seek(fd_file, 0, PR_SEEK_SET);
    387  len = PR_Available(fd_file);
    388  if (len < 0) {
    389    printf("testfile PR_Available failed on file %s\n", pathname);
    390    rv = -1;
    391    goto cleanup;
    392  } else if (len != CHUNK_SIZE) {
    393    printf("testfile PR_Available failed: expected/returned = %d/%d bytes\n",
    394           CHUNK_SIZE, len);
    395    rv = -1;
    396    goto cleanup;
    397  }
    398  PR_Close(fd_file);
    399 
    400  strcpy(tmpname, pathname);
    401  strcat(tmpname, ".RENAMED");
    402  if (PR_FAILURE == PR_Rename(pathname, tmpname)) {
    403    printf("testfile failed to rename file %s\n", pathname);
    404    rv = -1;
    405    goto cleanup;
    406  }
    407 
    408  fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
    409  len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE);
    410  PR_Close(fd_file);
    411  if (PR_SUCCESS == PR_Rename(pathname, tmpname)) {
    412    printf("testfile renamed to existing file %s\n", pathname);
    413  }
    414 
    415  if ((PR_Delete(tmpname)) < 0) {
    416    printf("testfile failed to unlink file %s\n", tmpname);
    417    rv = -1;
    418  }
    419 
    420 cleanup:
    421  if ((PR_Delete(pathname)) < 0) {
    422    printf("testfile failed to unlink file %s\n", pathname);
    423    rv = -1;
    424  }
    425  return rv;
    426 }
    427 
    428 static PRInt32 PR_CALLBACK FileTest(void) {
    429  PRDir* fd_dir;
    430  int i, offset, len, rv = 0;
    431  PRThreadScope scope = PR_GLOBAL_THREAD;
    432  File_Rdwr_Param* fparamp;
    433 
    434  /*
    435   * Create Test dir
    436   */
    437  if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
    438    printf("testfile failed to create dir %s\n", TEST_DIR);
    439    return -1;
    440  }
    441  fd_dir = PR_OpenDir(TEST_DIR);
    442  if (fd_dir == NULL) {
    443    printf("testfile failed to open dir %s\n", TEST_DIR);
    444    rv = -1;
    445    goto cleanup;
    446  }
    447 
    448  PR_CloseDir(fd_dir);
    449 
    450  strcat(pathname, TEST_DIR);
    451  strcat(pathname, "/");
    452  strcat(pathname, FILE_NAME);
    453 
    454  in_buf = PR_NEW(buffer);
    455  if (in_buf == NULL) {
    456    printf("testfile failed to alloc buffer struct\n");
    457    rv = -1;
    458    goto cleanup;
    459  }
    460  out_buf = PR_NEW(buffer);
    461  if (out_buf == NULL) {
    462    printf("testfile failed to alloc buffer struct\n");
    463    rv = -1;
    464    goto cleanup;
    465  }
    466 
    467  /*
    468   * Start a bunch of writer threads
    469   */
    470  offset = 0;
    471  len = CHUNK_SIZE;
    472  PR_EnterMonitor(mon);
    473  for (i = 0; i < NUM_RDWR_THREADS; i++) {
    474    fparamp = PR_NEW(File_Rdwr_Param);
    475    if (fparamp == NULL) {
    476      printf("testfile failed to alloc File_Rdwr_Param struct\n");
    477      rv = -1;
    478      goto cleanup;
    479    }
    480    fparamp->pathname = pathname;
    481    fparamp->buf = out_buf->data + offset;
    482    fparamp->offset = offset;
    483    fparamp->len = len;
    484    memset(fparamp->buf, i, len);
    485 
    486    (void)create_new_thread(PR_USER_THREAD, File_Write_Wrapper, File_Write,
    487                            (void*)fparamp, PR_PRIORITY_NORMAL, scope,
    488                            PR_UNJOINABLE_THREAD, 0, i);
    489    offset += len;
    490  }
    491  thread_count = i;
    492  /* Wait for writer threads to exit */
    493  while (thread_count) {
    494    PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
    495  }
    496  PR_ExitMonitor(mon);
    497 
    498  /*
    499   * Start a bunch of reader threads
    500   */
    501  offset = 0;
    502  len = CHUNK_SIZE;
    503  PR_EnterMonitor(mon);
    504  for (i = 0; i < NUM_RDWR_THREADS; i++) {
    505    fparamp = PR_NEW(File_Rdwr_Param);
    506    if (fparamp == NULL) {
    507      printf("testfile failed to alloc File_Rdwr_Param struct\n");
    508      rv = -1;
    509      goto cleanup;
    510    }
    511    fparamp->pathname = pathname;
    512    fparamp->buf = in_buf->data + offset;
    513    fparamp->offset = offset;
    514    fparamp->len = len;
    515 
    516    (void)create_new_thread(PR_USER_THREAD, File_Read_Wrapper, File_Read,
    517                            (void*)fparamp, PR_PRIORITY_NORMAL, scope,
    518                            PR_UNJOINABLE_THREAD, 0, i);
    519    offset += len;
    520    if ((offset + len) > BUF_DATA_SIZE) {
    521      break;
    522    }
    523  }
    524  thread_count = i;
    525 
    526  /* Wait for reader threads to exit */
    527  while (thread_count) {
    528    PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
    529  }
    530  PR_ExitMonitor(mon);
    531 
    532  if (memcmp(in_buf->data, out_buf->data, offset) != 0) {
    533    printf("File Test failed: file data corrupted\n");
    534    rv = -1;
    535    goto cleanup;
    536  }
    537 
    538  if ((PR_Delete(pathname)) < 0) {
    539    printf("testfile failed to unlink file %s\n", pathname);
    540    rv = -1;
    541    goto cleanup;
    542  }
    543 
    544  /*
    545   * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access
    546   */
    547  if (Misc_File_Tests(pathname) < 0) {
    548    rv = -1;
    549  }
    550 
    551 cleanup:
    552  if ((PR_RmDir(TEST_DIR)) < 0) {
    553    printf("testfile failed to rmdir %s\n", TEST_DIR);
    554    rv = -1;
    555  }
    556  return rv;
    557 }
    558 
    559 struct dirtest_arg {
    560  PRMonitor* mon;
    561  PRInt32 done;
    562 };
    563 
    564 static PRInt32 RunDirTest(void) {
    565  int i;
    566  PRThread* t;
    567  PRMonitor* mon;
    568  struct dirtest_arg thrarg;
    569 
    570  mon = PR_NewMonitor();
    571  if (!mon) {
    572    printf("RunDirTest: Error - failed to create monitor\n");
    573    dirtest_failed = 1;
    574    return -1;
    575  }
    576  thrarg.mon = mon;
    577 
    578  for (i = 0; i < NUM_DIRTEST_THREADS; i++) {
    579    thrarg.done = 0;
    580    t = create_new_thread(PR_USER_THREAD, DirTestWrapper, DirTestVoid, &thrarg,
    581                          PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
    582                          PR_UNJOINABLE_THREAD, 0, i);
    583    if (!t) {
    584      printf("RunDirTest: Error - failed to create thread\n");
    585      dirtest_failed = 1;
    586      return -1;
    587    }
    588    PR_EnterMonitor(mon);
    589    while (!thrarg.done) {
    590      PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
    591    }
    592    PR_ExitMonitor(mon);
    593  }
    594  PR_DestroyMonitor(mon);
    595  return 0;
    596 }
    597 
    598 static PRInt32 PR_CALLBACK DirTest(void* arg) {
    599  struct dirtest_arg* tinfo = (struct dirtest_arg*)arg;
    600  PRFileDesc* fd_file;
    601  PRDir* fd_dir;
    602  int i;
    603  int path_len;
    604  PRDirEntry* dirEntry;
    605  PRFileInfo info;
    606  PRInt32 num_files = 0;
    607 #if defined(XP_PC) && defined(WIN32)
    608  HANDLE hfile;
    609 #endif
    610 
    611 #define FILES_IN_DIR 20
    612 
    613  /*
    614   * Create Test dir
    615   */
    616  DPRINTF(("Creating test dir %s\n", TEST_DIR));
    617  if ((PR_MkDir(TEST_DIR, 0777)) < 0) {
    618    printf("testfile failed to create dir %s [%d, %d]\n", TEST_DIR,
    619           PR_GetError(), PR_GetOSError());
    620    return -1;
    621  }
    622  fd_dir = PR_OpenDir(TEST_DIR);
    623  if (fd_dir == NULL) {
    624    printf("testfile failed to open dirctory %s [%d, %d]\n", TEST_DIR,
    625           PR_GetError(), PR_GetOSError());
    626    return -1;
    627  }
    628 
    629  strcpy(pathname, TEST_DIR);
    630  strcat(pathname, "/");
    631  strcat(pathname, FILE_NAME);
    632  path_len = strlen(pathname);
    633 
    634  for (i = 0; i < FILES_IN_DIR; i++) {
    635    sprintf(pathname + path_len, "%d%s", i, "");
    636 
    637    DPRINTF(("Creating test file %s\n", pathname));
    638 
    639    fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
    640 
    641    if (fd_file == NULL) {
    642      printf("testfile failed to create/open file %s [%d, %d]\n", pathname,
    643             PR_GetError(), PR_GetOSError());
    644      return -1;
    645    }
    646    PR_Close(fd_file);
    647  }
    648 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32))
    649  /*
    650   * Create a hidden file - a platform-dependent operation
    651   */
    652  strcpy(pathname, TEST_DIR);
    653  strcat(pathname, "/");
    654  strcat(pathname, HIDDEN_FILE_NAME);
    655 #  if defined(XP_UNIX)
    656  DPRINTF(("Creating hidden test file %s\n", pathname));
    657  fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777);
    658 
    659  if (fd_file == NULL) {
    660    printf("testfile failed to create/open hidden file %s [%d, %d]\n", pathname,
    661           PR_GetError(), PR_GetOSError());
    662    return -1;
    663  }
    664 
    665  PR_Close(fd_file);
    666 
    667 #  elif defined(WINCE)
    668  DPRINTF(("Creating hidden test file %s\n", pathname));
    669  MultiByteToWideChar(CP_ACP, 0, pathname, -1, wPathname, 256);
    670  hfile =
    671      CreateFile(wPathname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
    672                 NULL, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, NULL);
    673  if (hfile == INVALID_HANDLE_VALUE) {
    674    printf("testfile failed to create/open hidden file %s [0, %d]\n", pathname,
    675           GetLastError());
    676    return -1;
    677  }
    678  CloseHandle(hfile);
    679 
    680 #  elif defined(XP_PC) && defined(WIN32)
    681  DPRINTF(("Creating hidden test file %s\n", pathname));
    682  hfile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
    683                     NULL, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, NULL);
    684  if (hfile == INVALID_HANDLE_VALUE) {
    685    printf("testfile failed to create/open hidden file %s [0, %d]\n", pathname,
    686           GetLastError());
    687    return -1;
    688  }
    689  CloseHandle(hfile);
    690 
    691 #  endif /* XP_UNIX */
    692 
    693 #endif /* XP_UNIX || (XP_PC && WIN32) */
    694 
    695  if (PR_FAILURE == PR_CloseDir(fd_dir)) {
    696    printf("testfile failed to close dirctory %s [%d, %d]\n", TEST_DIR,
    697           PR_GetError(), PR_GetOSError());
    698    return -1;
    699  }
    700  fd_dir = PR_OpenDir(TEST_DIR);
    701  if (fd_dir == NULL) {
    702    printf("testfile failed to reopen dirctory %s [%d, %d]\n", TEST_DIR,
    703           PR_GetError(), PR_GetOSError());
    704    return -1;
    705  }
    706 
    707  /*
    708   * List all files, including hidden files
    709   */
    710  DPRINTF(("Listing all files in directory %s\n", TEST_DIR));
    711 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32))
    712  num_files = FILES_IN_DIR + 1;
    713 #else
    714  num_files = FILES_IN_DIR;
    715 #endif
    716  while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_BOTH)) != NULL) {
    717    num_files--;
    718    strcpy(pathname, TEST_DIR);
    719    strcat(pathname, "/");
    720    strcat(pathname, dirEntry->name);
    721    DPRINTF(("\t%s\n", dirEntry->name));
    722 
    723    if ((PR_GetFileInfo(pathname, &info)) < 0) {
    724      printf("testfile failed to GetFileInfo file %s [%d, %d]\n", pathname,
    725             PR_GetError(), PR_GetOSError());
    726      return -1;
    727    }
    728 
    729    if (info.type != PR_FILE_FILE) {
    730      printf("testfile incorrect fileinfo for file %s [%d, %d]\n", pathname,
    731             PR_GetError(), PR_GetOSError());
    732      return -1;
    733    }
    734  }
    735  if (num_files != 0) {
    736    printf("testfile failed to find all files in directory %s [%d, %d]\n",
    737           TEST_DIR, PR_GetError(), PR_GetOSError());
    738    return -1;
    739  }
    740 
    741  PR_CloseDir(fd_dir);
    742 
    743 #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32))
    744 
    745  /*
    746   * List all files, except hidden files
    747   */
    748 
    749  fd_dir = PR_OpenDir(TEST_DIR);
    750  if (fd_dir == NULL) {
    751    printf("testfile failed to reopen dirctory %s [%d, %d]\n", TEST_DIR,
    752           PR_GetError(), PR_GetOSError());
    753    return -1;
    754  }
    755 
    756  DPRINTF(("Listing non-hidden files in directory %s\n", TEST_DIR));
    757  while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_HIDDEN)) != NULL) {
    758    DPRINTF(("\t%s\n", dirEntry->name));
    759    if (!strcmp(HIDDEN_FILE_NAME, dirEntry->name)) {
    760      printf("testfile found hidden file %s\n", pathname);
    761      return -1;
    762    }
    763  }
    764  /*
    765   * Delete hidden file
    766   */
    767  strcpy(pathname, TEST_DIR);
    768  strcat(pathname, "/");
    769  strcat(pathname, HIDDEN_FILE_NAME);
    770  if (PR_FAILURE == PR_Delete(pathname)) {
    771    printf("testfile failed to delete hidden file %s [%d, %d]\n", pathname,
    772           PR_GetError(), PR_GetOSError());
    773    return -1;
    774  }
    775 
    776  PR_CloseDir(fd_dir);
    777 #endif /* XP_UNIX || (XP_PC && WIN32) */
    778 
    779  strcpy(renamename, TEST_DIR);
    780  strcat(renamename, ".RENAMED");
    781  if (PR_FAILURE == PR_Rename(TEST_DIR, renamename)) {
    782    printf("testfile failed to rename directory %s [%d, %d]\n", TEST_DIR,
    783           PR_GetError(), PR_GetOSError());
    784    return -1;
    785  }
    786 
    787  if (PR_FAILURE == PR_MkDir(TEST_DIR, 0777)) {
    788    printf("testfile failed to recreate dir %s [%d, %d]\n", TEST_DIR,
    789           PR_GetError(), PR_GetOSError());
    790    return -1;
    791  }
    792  if (PR_SUCCESS == PR_Rename(renamename, TEST_DIR)) {
    793    printf("testfile renamed directory to existing name %s\n", renamename);
    794    return -1;
    795  }
    796 
    797  if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
    798    printf("testfile failed to rmdir %s [%d, %d]\n", TEST_DIR, PR_GetError(),
    799           PR_GetOSError());
    800    return -1;
    801  }
    802 
    803  if (PR_FAILURE == PR_Rename(renamename, TEST_DIR)) {
    804    printf("testfile failed to rename directory %s [%d, %d]\n", renamename,
    805           PR_GetError(), PR_GetOSError());
    806    return -1;
    807  }
    808  fd_dir = PR_OpenDir(TEST_DIR);
    809  if (fd_dir == NULL) {
    810    printf("testfile failed to reopen directory %s [%d, %d]\n", TEST_DIR,
    811           PR_GetError(), PR_GetOSError());
    812    return -1;
    813  }
    814 
    815  strcpy(pathname, TEST_DIR);
    816  strcat(pathname, "/");
    817  strcat(pathname, FILE_NAME);
    818  path_len = strlen(pathname);
    819 
    820  for (i = 0; i < FILES_IN_DIR; i++) {
    821    sprintf(pathname + path_len, "%d%s", i, "");
    822 
    823    if (PR_FAILURE == PR_Delete(pathname)) {
    824      printf("testfile failed to delete file %s [%d, %d]\n", pathname,
    825             PR_GetError(), PR_GetOSError());
    826      return -1;
    827    }
    828  }
    829 
    830  PR_CloseDir(fd_dir);
    831 
    832  if (PR_FAILURE == PR_RmDir(TEST_DIR)) {
    833    printf("testfile failed to rmdir %s [%d, %d]\n", TEST_DIR, PR_GetError(),
    834           PR_GetOSError());
    835    return -1;
    836  }
    837  PR_EnterMonitor(tinfo->mon);
    838  tinfo->done = 1;
    839  PR_Notify(tinfo->mon);
    840  PR_ExitMonitor(tinfo->mon);
    841 
    842  return 0;
    843 }
    844 /************************************************************************/
    845 
    846 /*
    847 * Test file and directory NSPR APIs
    848 */
    849 
    850 int main(int argc, char** argv) {
    851 #ifdef WIN32
    852  PRUint32 len;
    853 #endif
    854 #if defined(XP_UNIX)
    855  int opt;
    856  extern char* optarg;
    857  extern int optind;
    858 #endif
    859 #if defined(XP_UNIX)
    860  while ((opt = getopt(argc, argv, "d")) != EOF) {
    861    switch (opt) {
    862      case 'd':
    863        _debug_on = 1;
    864        break;
    865      default:
    866        break;
    867    }
    868  }
    869 #endif
    870  PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    871 
    872  mon = PR_NewMonitor();
    873  if (mon == NULL) {
    874    printf("testfile: PR_NewMonitor failed\n");
    875    exit(2);
    876  }
    877 #ifdef WIN32
    878 
    879 #  ifdef WINCE
    880  {
    881    WCHAR tdir[TMPDIR_LEN];
    882    len = GetTempPath(TMPDIR_LEN, tdir);
    883    if ((len > 0) && (len < (TMPDIR_LEN - 6))) {
    884      /*
    885       * enough space for prdir
    886       */
    887      WideCharToMultiByte(CP_ACP, 0, tdir, -1, testdir, TMPDIR_LEN, 0, 0);
    888    }
    889  }
    890 #  else
    891  len = GetTempPath(TMPDIR_LEN, testdir);
    892 #  endif /* WINCE */
    893 
    894  if ((len > 0) && (len < (TMPDIR_LEN - 6))) {
    895    /*
    896     * enough space for prdir
    897     */
    898    strcpy((testdir + len), "prdir");
    899    TEST_DIR = testdir;
    900    printf("TEST_DIR = %s\n", TEST_DIR);
    901  }
    902 #endif /* WIN32 */
    903 
    904  if (FileTest() < 0) {
    905    printf("File Test failed\n");
    906    exit(2);
    907  }
    908  printf("File Test passed\n");
    909  if ((RunDirTest() < 0) || dirtest_failed) {
    910    printf("Dir Test failed\n");
    911    exit(2);
    912  }
    913  printf("Dir Test passed\n");
    914 
    915  PR_DestroyMonitor(mon);
    916  PR_Cleanup();
    917  return 0;
    918 }