Widen page count field in blockinfo to allow lots of pages per block
[yaffs/.git] / direct / dtest.c
1 /*
2 * Test code for the "direct" interface. 
3 */
4
5
6 #include <stdio.h>
7 #include <string.h>
8
9 #include "yaffsfs.h"
10
11 char xx[600];
12
13 void copy_in_a_file(char *yaffsName,char *inName)
14 {
15         int inh,outh;
16         unsigned char buffer[100];
17         int ni,no;
18         inh = open(inName,O_RDONLY);
19         outh = yaffs_open(yaffsName, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
20         
21         while((ni = read(inh,buffer,100)) > 0)
22         {
23                 no = yaffs_write(outh,buffer,ni);
24                 if(ni != no)
25                 {
26                         printf("problem writing yaffs file\n");
27                 }
28                 
29         }
30         
31         yaffs_close(outh);
32         close(inh);
33 }
34
35 void make_a_file(char *yaffsName,char bval,int sizeOfFile)
36 {
37         int outh;
38         int i;
39         unsigned char buffer[100];
40
41         outh = yaffs_open(yaffsName, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
42         
43         memset(buffer,bval,100);
44         
45         do{
46                 i = sizeOfFile;
47                 if(i > 100) i = 100;
48                 sizeOfFile -= i;
49                 
50                 yaffs_write(outh,buffer,i);
51                 
52         } while (sizeOfFile > 0);
53         
54                 
55         yaffs_close(outh);
56
57 }
58
59
60
61
62 void fill_disk(char *path,int nfiles)
63 {
64         int h;
65         int n;
66         int result;
67         int f;
68         
69         char str[50];
70         
71         for(n = 0; n < nfiles; n++)
72         {
73                 sprintf(str,"%s/%d",path,n);
74                 
75                 h = yaffs_open(str, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
76                 
77                 printf("writing file %s handle %d ",str, h);
78                 
79                 while ((result = yaffs_write(h,xx,600)) == 600)
80                 {
81                         f = yaffs_freespace("/boot");
82                 }
83                 result = yaffs_close(h);
84                 printf(" close %d\n",result);
85         }
86 }
87
88 void fill_disk_and_delete(char *path, int nfiles, int ncycles)
89 {
90         int i,j;
91         char str[50];
92         int result;
93         
94         for(i = 0; i < ncycles; i++)
95         {
96                 printf("@@@@@@@@@@@@@@ cycle %d\n",i);
97                 fill_disk(path,nfiles);
98                 
99                 for(j = 0; j < nfiles; j++)
100                 {
101                         sprintf(str,"%s/%d",path,j);
102                         result = yaffs_unlink(str);
103                         printf("unlinking file %s, result %d\n",str,result);
104                 }
105         }
106 }
107
108
109 void fill_files(char *path,int flags, int maxIterations,int siz)
110 {
111         int i;
112         int j;
113         char str[50];
114         int h;
115         
116         i = 0;
117         
118         do{
119                 sprintf(str,"%s/%d",path,i);
120                 h = yaffs_open(str, O_CREAT | O_TRUNC | O_RDWR,S_IREAD | S_IWRITE);
121                 yaffs_close(h);
122
123                 if(h >= 0)
124                 {
125                         for(j = 0; j < siz; j++)
126                         {
127                                 yaffs_write(h,str,1);
128                         }
129                 }
130                 
131                 if( flags & 1)
132                 {
133                         yaffs_unlink(str);
134                 }
135                 i++;
136         } while(h >= 0 && i < maxIterations);
137         
138         if(flags & 2)
139         {
140                 i = 0;
141                 do{
142                         sprintf(str,"%s/%d",path,i);
143                         printf("unlink %s\n",str);
144                         i++;
145                 } while(yaffs_unlink(str) >= 0);
146         }
147 }
148
149 void leave_unlinked_file(char *path,int maxIterations,int siz)
150 {
151         int i;
152         char str[50];
153         int h;
154         
155         i = 0;
156         
157         do{
158                 sprintf(str,"%s/%d",path,i);
159                 printf("create %s\n",str);
160                 h = yaffs_open(str, O_CREAT | O_TRUNC | O_RDWR,S_IREAD | S_IWRITE);
161                 if(h >= 0)
162                 {
163                         yaffs_unlink(str);
164                 }
165                 i++;
166         } while(h < 0 && i < maxIterations);
167         
168         if(h >= 0)
169         {
170                 for(i = 0; i < siz; i++)
171                 {
172                         yaffs_write(h,str,1);
173                 }
174         }
175         
176         printf("Leaving file %s open\n",str);
177
178 }
179
180 void dumpDirFollow(const char *dname)
181 {
182         yaffs_DIR *d;
183         yaffs_dirent *de;
184         struct yaffs_stat s;
185         char str[100];
186                         
187         d = yaffs_opendir(dname);
188         
189         if(!d)
190         {
191                 printf("opendir failed\n");
192         }
193         else
194         {
195                 while((de = yaffs_readdir(d)) != NULL)
196                 {
197                         sprintf(str,"%s/%s",dname,de->d_name);
198                         
199                         yaffs_stat(str,&s);
200                         
201                         printf("%s length %d mode %X ",de->d_name,s.st_size,s.st_mode);
202                         switch(s.st_mode & S_IFMT)
203                         {
204                                 case S_IFREG: printf("data file"); break;
205                                 case S_IFDIR: printf("directory"); break;
206                                 case S_IFLNK: printf("symlink -->");
207                                                           if(yaffs_readlink(str,str,100) < 0)
208                                                                 printf("no alias");
209                                                           else
210                                                                 printf("\"%s\"",str);    
211                                                           break;
212                                 default: printf("unknown"); break;
213                         }
214                         
215                         printf("\n");           
216                 }
217                 
218                 yaffs_closedir(d);
219         }
220         printf("\n");
221         
222         printf("Free space in %s is %d\n\n",dname,yaffs_freespace(dname));
223
224 }
225 void dumpDir(const char *dname)
226 {
227         yaffs_DIR *d;
228         yaffs_dirent *de;
229         struct yaffs_stat s;
230         char str[100];
231                         
232         d = yaffs_opendir(dname);
233         
234         if(!d)
235         {
236                 printf("opendir failed\n");
237         }
238         else
239         {
240                 while((de = yaffs_readdir(d)) != NULL)
241                 {
242                         sprintf(str,"%s/%s",dname,de->d_name);
243                         
244                         yaffs_lstat(str,&s);
245                         
246                         printf("%s length %d mode %X ",de->d_name,s.st_size,s.st_mode);
247                         switch(s.st_mode & S_IFMT)
248                         {
249                                 case S_IFREG: printf("data file"); break;
250                                 case S_IFDIR: printf("directory"); break;
251                                 case S_IFLNK: printf("symlink -->");
252                                                           if(yaffs_readlink(str,str,100) < 0)
253                                                                 printf("no alias");
254                                                           else
255                                                                 printf("\"%s\"",str);    
256                                                           break;
257                                 default: printf("unknown"); break;
258                         }
259                         
260                         printf("\n");           
261                 }
262                 
263                 yaffs_closedir(d);
264         }
265         printf("\n");
266         
267         printf("Free space in %s is %d\n\n",dname,yaffs_freespace(dname));
268
269 }
270
271
272 static void PermissionsCheck(const char *path, mode_t tmode, int tflags,int expectedResult)
273 {
274         int fd;
275         
276         if(yaffs_chmod(path,tmode)< 0) printf("chmod failed\n");
277         
278         fd = yaffs_open(path,tflags,0);
279         
280         if((fd >= 0) != (expectedResult > 0))
281         {
282                 printf("Permissions check %x %x %d failed\n",tmode,tflags,expectedResult);
283         }
284         else
285         {
286                 printf("Permissions check %x %x %d OK\n",tmode,tflags,expectedResult);
287         }
288         
289         
290         yaffs_close(fd);
291         
292         
293 }
294
295 int long_test(int argc, char *argv[])
296 {
297
298         int f;
299         int r;
300         char buffer[20];
301         
302         char str[100];
303         
304         int h;
305         mode_t temp_mode;
306         struct yaffs_stat ystat;
307         
308         yaffs_StartUp();
309         
310         yaffs_mount("/boot");
311         yaffs_mount("/data");
312         yaffs_mount("/flash");
313         yaffs_mount("/ram");
314         
315         printf("\nDirectory look-up of /boot\n");
316         dumpDir("/boot");
317         printf("\nDirectory look-up of /data\n");
318         dumpDir("/data");
319         printf("\nDirectory look-up of /flash\n");
320         dumpDir("/flash");
321
322         //leave_unlinked_file("/flash",20000,0);
323         //leave_unlinked_file("/data",20000,0);
324         
325         leave_unlinked_file("/ram",20,0);
326         
327
328         f = yaffs_open("/boot/b1", O_RDONLY,0);
329         
330         printf("open /boot/b1 readonly, f=%d\n",f);
331         
332         f = yaffs_open("/boot/b1", O_CREAT,S_IREAD | S_IWRITE);
333         
334         printf("open /boot/b1 O_CREAT, f=%d\n",f);
335         
336         
337         r = yaffs_write(f,"hello",1);
338         printf("write %d attempted to write to a read-only file\n",r);
339         
340         r = yaffs_close(f);
341         
342         printf("close %d\n",r);
343
344         f = yaffs_open("/boot/b1", O_RDWR,0);
345         
346         printf("open /boot/b1 O_RDWR,f=%d\n",f);
347         
348         
349         r = yaffs_write(f,"hello",2);
350         printf("write %d attempted to write to a writeable file\n",r);
351         r = yaffs_write(f,"world",3);
352         printf("write %d attempted to write to a writeable file\n",r);
353         
354         r= yaffs_lseek(f,0,SEEK_END);
355         printf("seek end %d\n",r);
356         memset(buffer,0,20);
357         r = yaffs_read(f,buffer,10);
358         printf("read %d \"%s\"\n",r,buffer);
359         r= yaffs_lseek(f,0,SEEK_SET);
360         printf("seek set %d\n",r);
361         memset(buffer,0,20);
362         r = yaffs_read(f,buffer,10);
363         printf("read %d \"%s\"\n",r,buffer);
364         memset(buffer,0,20);
365         r = yaffs_read(f,buffer,10);
366         printf("read %d \"%s\"\n",r,buffer);
367
368         // Check values reading at end.
369         // A read past end of file should return 0 for 0 bytes read.
370                 
371         r= yaffs_lseek(f,0,SEEK_END);
372         r = yaffs_read(f,buffer,10);
373         printf("read at end returned  %d\n",r); 
374         r= yaffs_lseek(f,500,SEEK_END);
375         r = yaffs_read(f,buffer,10);
376         printf("read past end returned  %d\n",r);       
377         
378         r = yaffs_close(f);
379         
380         printf("close %d\n",r);
381         
382         copy_in_a_file("/boot/yyfile","xxx");
383         
384         // Create a file with a long name
385         
386         copy_in_a_file("/boot/file with a long name","xxx");
387         
388         
389         printf("\nDirectory look-up of /boot\n");
390         dumpDir("/boot");
391
392         // Check stat
393         r = yaffs_stat("/boot/file with a long name",&ystat);
394         
395         // Check rename
396         
397         r = yaffs_rename("/boot/file with a long name","/boot/r1");
398         
399         printf("\nDirectory look-up of /boot\n");
400         dumpDir("/boot");
401         
402         // Check unlink
403         r = yaffs_unlink("/boot/r1");
404         
405         printf("\nDirectory look-up of /boot\n");
406         dumpDir("/boot");
407
408         // Check mkdir
409         
410         r = yaffs_mkdir("/boot/directory1",0);
411         
412         printf("\nDirectory look-up of /boot\n");
413         dumpDir("/boot");
414         printf("\nDirectory look-up of /boot/directory1\n");
415         dumpDir("/boot/directory1");
416
417         // add a file to the directory                  
418         copy_in_a_file("/boot/directory1/file with a long name","xxx");
419         
420         printf("\nDirectory look-up of /boot\n");
421         dumpDir("/boot");
422         printf("\nDirectory look-up of /boot/directory1\n");
423         dumpDir("/boot/directory1");
424         
425         //  Attempt to delete directory (should fail)
426         
427         r = yaffs_rmdir("/boot/directory1");
428         
429         printf("\nDirectory look-up of /boot\n");
430         dumpDir("/boot");
431         printf("\nDirectory look-up of /boot/directory1\n");
432         dumpDir("/boot/directory1");
433         
434         // Delete file first, then rmdir should work
435         r = yaffs_unlink("/boot/directory1/file with a long name");
436         r = yaffs_rmdir("/boot/directory1");
437         
438         
439         printf("\nDirectory look-up of /boot\n");
440         dumpDir("/boot");
441         printf("\nDirectory look-up of /boot/directory1\n");
442         dumpDir("/boot/directory1");
443
444 #if 0
445         fill_disk_and_delete("/boot",20,20);
446                         
447         printf("\nDirectory look-up of /boot\n");
448         dumpDir("/boot");
449 #endif
450
451         yaffs_symlink("yyfile","/boot/slink");
452         
453         yaffs_readlink("/boot/slink",str,100);
454         printf("symlink alias is %s\n",str);
455         
456         
457         
458         
459         printf("\nDirectory look-up of /boot\n");
460         dumpDir("/boot");
461         printf("\nDirectory look-up of /boot (using stat instead of lstat)\n");
462         dumpDirFollow("/boot");
463         printf("\nDirectory look-up of /boot/directory1\n");
464         dumpDir("/boot/directory1");
465
466         h = yaffs_open("/boot/slink",O_RDWR,0);
467         
468         printf("file length is %d\n",yaffs_lseek(h,0,SEEK_END));
469         
470         yaffs_close(h);
471         
472         yaffs_unlink("/boot/slink");
473
474         
475         printf("\nDirectory look-up of /boot\n");
476         dumpDir("/boot");
477         
478         // Check chmod
479         
480         yaffs_stat("/boot/yyfile",&ystat);
481         temp_mode = ystat.st_mode;
482         
483         yaffs_chmod("/boot/yyfile",0x55555);
484         printf("\nDirectory look-up of /boot\n");
485         dumpDir("/boot");
486         
487         yaffs_chmod("/boot/yyfile",temp_mode);
488         printf("\nDirectory look-up of /boot\n");
489         dumpDir("/boot");
490         
491         // Permission checks...
492         PermissionsCheck("/boot/yyfile",0, O_WRONLY,0);
493         PermissionsCheck("/boot/yyfile",0, O_RDONLY,0);
494         PermissionsCheck("/boot/yyfile",0, O_RDWR,0);
495
496         PermissionsCheck("/boot/yyfile",S_IREAD, O_WRONLY,0);
497         PermissionsCheck("/boot/yyfile",S_IREAD, O_RDONLY,1);
498         PermissionsCheck("/boot/yyfile",S_IREAD, O_RDWR,0);
499
500         PermissionsCheck("/boot/yyfile",S_IWRITE, O_WRONLY,1);
501         PermissionsCheck("/boot/yyfile",S_IWRITE, O_RDONLY,0);
502         PermissionsCheck("/boot/yyfile",S_IWRITE, O_RDWR,0);
503         
504         PermissionsCheck("/boot/yyfile",S_IREAD | S_IWRITE, O_WRONLY,1);
505         PermissionsCheck("/boot/yyfile",S_IREAD | S_IWRITE, O_RDONLY,1);
506         PermissionsCheck("/boot/yyfile",S_IREAD | S_IWRITE, O_RDWR,1);
507
508         yaffs_chmod("/boot/yyfile",temp_mode);
509         
510         //create a zero-length file and unlink it (test for scan bug)
511         
512         h = yaffs_open("/boot/zlf",O_CREAT | O_TRUNC | O_RDWR,0);
513         yaffs_close(h);
514         
515         yaffs_unlink("/boot/zlf");
516         
517         
518         yaffs_DumpDevStruct("/boot");
519         
520         fill_disk_and_delete("/boot",20,20);
521         
522         yaffs_DumpDevStruct("/boot");
523         
524         fill_files("/boot",1,10000,0);
525         fill_files("/boot",1,10000,5000);
526         fill_files("/boot",2,10000,0);
527         fill_files("/boot",2,10000,5000);
528         
529         leave_unlinked_file("/data",20000,0);
530         leave_unlinked_file("/data",20000,5000);
531         leave_unlinked_file("/data",20000,5000);
532         leave_unlinked_file("/data",20000,5000);
533         leave_unlinked_file("/data",20000,5000);
534         leave_unlinked_file("/data",20000,5000);
535         
536         yaffs_DumpDevStruct("/boot");
537         yaffs_DumpDevStruct("/data");
538         
539                 
540                 
541         return 0;
542
543 }
544
545
546
547 int directory_rename_test(void)
548 {
549         int r;
550         yaffs_StartUp();
551         
552         yaffs_mount("/ram");
553         yaffs_mkdir("/ram/a",0);
554         yaffs_mkdir("/ram/a/b",0);
555         yaffs_mkdir("/ram/c",0);
556         
557         printf("\nDirectory look-up of /ram\n");
558         dumpDir("/ram");
559         dumpDir("/ram/a");
560         dumpDir("/ram/a/b");
561
562         printf("Do rename (should fail)\n");
563                 
564         r = yaffs_rename("/ram/a","/ram/a/b/d");
565         printf("\nDirectory look-up of /ram\n");
566         dumpDir("/ram");
567         dumpDir("/ram/a");
568         dumpDir("/ram/a/b");
569
570         printf("Do rename (should not fail)\n");
571                 
572         r = yaffs_rename("/ram/c","/ram/a/b/d");
573         printf("\nDirectory look-up of /ram\n");
574         dumpDir("/ram");
575         dumpDir("/ram/a");
576         dumpDir("/ram/a/b");
577         
578         
579         return 1;
580         
581 }
582
583 int cache_read_test(void)
584 {
585         int a,b,c;
586         int i;
587         int sizeOfFiles = 500000;
588         char buffer[100];
589         
590         yaffs_StartUp();
591         
592         yaffs_mount("/boot");
593         
594         make_a_file("/boot/a",'a',sizeOfFiles);
595         make_a_file("/boot/b",'b',sizeOfFiles);
596
597         a = yaffs_open("/boot/a",O_RDONLY,0);
598         b = yaffs_open("/boot/b",O_RDONLY,0);
599         c = yaffs_open("/boot/c", O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
600
601         do{
602                 i = sizeOfFiles;
603                 if (i > 100) i = 100;
604                 sizeOfFiles  -= i;
605                 yaffs_read(a,buffer,i);
606                 yaffs_read(b,buffer,i);
607                 yaffs_write(c,buffer,i);
608         } while(sizeOfFiles > 0);
609         
610         
611         
612         return 1;
613         
614 }
615
616 int cache_bypass_bug_test(void)
617 {
618         // This test reporoduces a bug whereby YAFFS caching is buypassed
619         // resulting in erroneous reads after writes.
620         int a;
621         int i;
622         char buffer1[1000];
623         char buffer2[1000];
624         
625         memset(buffer1,0,sizeof(buffer1));
626         memset(buffer2,0,sizeof(buffer2));
627                 
628         yaffs_StartUp();
629         
630         yaffs_mount("/boot");
631         
632         // Create a file of 2000 bytes.
633         make_a_file("/boot/a",'X',2000);
634
635         a = yaffs_open("/boot/a",O_RDWR, S_IREAD | S_IWRITE);
636         
637         // Write a short sequence to the file.
638         // This will go into the cache.
639         yaffs_lseek(a,0,SEEK_SET);
640         yaffs_write(a,"abcdefghijklmnopqrstuvwxyz",20); 
641
642         // Read a short sequence from the file.
643         // This will come from the cache.
644         yaffs_lseek(a,0,SEEK_SET);
645         yaffs_read(a,buffer1,30); 
646
647         // Read a page size sequence from the file.
648         yaffs_lseek(a,0,SEEK_SET);
649         yaffs_read(a,buffer2,512); 
650         
651         printf("buffer 1 %s\n",buffer1);
652         printf("buffer 2 %s\n",buffer2);
653         
654         if(strncmp(buffer1,buffer2,20))
655         {
656                 printf("Cache bypass bug detected!!!!!\n");
657         }
658         
659         
660         return 1;
661 }
662
663
664 int free_space_check(void)
665 {
666         int f;
667         
668                 yaffs_StartUp();
669                 yaffs_mount("/boot");
670             fill_disk("/boot/",2);
671             f = yaffs_freespace("/boot");
672             
673             printf("%d free when disk full\n",f);           
674             return 1;
675 }
676
677
678 int main(int argc, char *argv[])
679 {
680         //return long_test(argc,argv);
681         
682         //return cache_read_test();
683         
684         //return cache_bypass_bug_test();
685         
686         return free_space_check();
687         
688 }