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