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