Fix problem where duplicate object headers were not always being selected correctly...
[yaffs2.git] / direct / nor_stress.c
1 #include "nor_stress.h"
2
3
4 #include "yaffsfs.h"
5
6 #include <stdio.h>
7
8
9
10 static unsigned powerUps;
11 static unsigned cycleStarts;
12 static unsigned cycleEnds;
13
14
15 char fullPathName[100];
16 char fullPowerUpName[100];
17 char fullStartName[100];
18 char fullEndName[100];
19 char fullMainName[100];
20 char fullTempMainName[100];
21 char fullTempCounterName[100];
22
23
24 void MakeName(char *fullName,const char *prefix, const char *name)
25 {
26   strcpy(fullName,prefix);
27   strcat(fullName,"/");
28   strcat(fullName,name);
29 }
30
31
32 void MakeFullNames(const char *prefix)
33 {
34   MakeName(fullPathName,prefix,"");
35   MakeName(fullPowerUpName,prefix,"powerUps");
36   MakeName(fullStartName,prefix,"starts");
37   MakeName(fullEndName,prefix,"ends");
38   MakeName(fullMainName,prefix,"main");
39   MakeName(fullTempCounterName,prefix,"tmp-counter");
40   MakeName(fullTempMainName,prefix,"tmp-main");
41 }
42
43 static void FatalError(void)
44 {
45   printf("Integrity error\n");
46   while(1){}
47 }
48
49 static void UpdateCounter(const char *name, unsigned *val,  int initialise)
50 {
51   int inh=-1;
52   int outh=-1;
53   unsigned x[2];
54   int nread = 0;
55   int nwritten = 0;
56   
57   x[0] = x[1] = 0;
58   
59   if(initialise){
60     x[0] = 0; 
61     x[1] = 1;
62   } else {
63     inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE);
64     if(inh >= 0){
65       nread = yaffs_read(inh,x,sizeof(x));
66       yaffs_close(inh);
67     }
68
69     if(nread != sizeof(x) ||
70        x[0] + 1 != x[1]){
71       printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n",
72               name, inh, x[0], x[1],yaffsfs_GetLastError());
73       FatalError();
74               
75     }
76     x[0]++;
77     x[1]++;
78   }
79   
80   outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
81   if(outh >= 0){
82     nwritten = yaffs_write(outh,x,sizeof(x));
83     yaffs_close(outh);
84     yaffs_rename(fullTempCounterName,name);
85   }
86   
87   if(nwritten != sizeof(x)){
88       printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n",
89               name, inh, x[0], x[1]);
90       FatalError();
91   }
92   
93   *val = x[0];
94   
95   printf("##\n"
96          "## Set counter %s to %u\n"
97          "##\n", name,x[0]);
98 }
99
100
101 static void dump_directory_tree_worker(const char *dname,int recursive)
102 {
103         yaffs_DIR *d;
104         yaffs_dirent *de;
105         struct yaffs_stat s;
106         char str[1000];
107                         
108         d = yaffs_opendir(dname);
109         
110         if(!d)
111         {
112                 printf("opendir failed\n");
113         }
114         else
115         {
116                 while((de = yaffs_readdir(d)) != NULL)
117                 {
118                         strcpy(str,dname);
119                         strcat(str,"/");
120                         strcat(str,de->d_name);
121                         
122                         yaffs_lstat(str,&s);
123                         
124                         printf("%s inode %d obj %x length %d mode %X ",str,s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode);
125                         switch(s.st_mode & S_IFMT)
126                         {
127                                 case S_IFREG: printf("data file"); break;
128                                 case S_IFDIR: printf("directory"); break;
129                                 case S_IFLNK: printf("symlink -->");
130                                                           if(yaffs_readlink(str,str,100) < 0)
131                                                                 printf("no alias");
132                                                           else
133                                                                 printf("\"%s\"",str);    
134                                                           break;
135                                 default: printf("unknown"); break;
136                         }
137                         
138                         printf("\n");
139
140                         if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
141                                 dump_directory_tree_worker(str,1);
142                                 
143                         if(s.st_ino > 10000)
144                           FatalError();
145                                                         
146                 }
147                 
148                 yaffs_closedir(d);
149         }
150
151 }
152
153 static void dump_directory_tree(const char *dname)
154 {
155         dump_directory_tree_worker(dname,1);
156         printf("\n");
157         printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname));
158 }
159
160
161
162
163 #define XX_SIZE 500
164
165 static unsigned xx[XX_SIZE];
166
167 static int yWriteFile(const char *fname, unsigned sz32)
168 {
169         int h;
170         int r;
171         int i;
172         unsigned checksum = 0;
173         
174         printf("Writing file %s\n",fname);
175
176         h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
177
178         if(h < 0){
179                 printf("could not open file %s\n",fname);
180                 return h;
181         }
182
183         xx[0] = sz32;
184         checksum ^= xx[0];
185
186         if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
187                 goto WRITE_ERROR;
188         }
189                 
190         while(sz32> 0){
191                 for(i = 0; i < XX_SIZE; i++){
192                   xx[i] = sz32 + i;
193                   checksum ^= xx[i];
194                 }
195
196                 if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){
197                         goto WRITE_ERROR;
198                 }
199                 sz32--;
200         }
201
202         xx[0] = checksum;
203
204         if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
205                 goto WRITE_ERROR;
206         }
207         
208         
209         yaffs_close(h);
210         return 0;
211
212 WRITE_ERROR:
213         printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END));
214         yaffs_close(h);
215         return -1;
216         
217 }
218
219 static int yVerifyFile(const char *fName)
220 {
221         unsigned checksum = 0;
222         unsigned totalSize;
223         unsigned sz32;
224         unsigned recordedSize = 0;
225         int r;
226         int h;
227         int i;
228         int retval = 0;
229
230
231         printf("Verifying file %s\n",fName);
232                 
233         h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE);
234
235         if(h < 0){
236                 printf("could not open file %s\n",fName);
237                 return -1;
238         }
239
240         totalSize = yaffs_lseek(h,0,SEEK_END);
241         yaffs_lseek(h,0,SEEK_SET);
242
243         r = yaffs_read(h,&sz32,sizeof(sz32));
244
245         if(r != sizeof(sz32)){
246                 printf("reading size failed ... returned %d\n",r);
247                 yaffs_close(h);
248                 return -1;
249         }
250         
251         recordedSize = sz32 * sizeof(xx) + 8;
252
253         printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize);
254         if(totalSize != recordedSize){
255                 printf("!!!!!!!!!!!!!!!!!!!!!!!!file size is wrong, should be %d, is %d\n", recordedSize,totalSize);
256                 yaffs_close(h);
257                 return -1;
258         }
259
260         checksum ^= sz32;
261
262
263         while(sz32 > 0){
264                 r = yaffs_read(h,xx,sizeof(xx));
265                 if(r != sizeof(xx)){
266                         printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
267                         yaffs_close(h);
268                         return -1;
269                 }
270                 for(i = 0; i < XX_SIZE; i++)
271                   checksum ^= xx[i];
272                 sz32--;
273         }
274         r = yaffs_read(h,xx,sizeof(xx[0]));
275         if(r != sizeof(xx[0])){
276                 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
277                 yaffs_close(h);
278                 return -1;
279         }
280         
281         checksum ^= xx[0];
282
283         if(checksum != 0){
284                 printf("!!!!!!!!!!!!!!!!!!!!! checksum failed\n");
285                 retval = -1;
286         } else
287                 printf("verified ok\n");
288         yaffs_close(h);
289
290         return retval;
291 }
292
293 static unsigned long next = 1;
294 int myrand(void) {
295   next = next * 1103515245 + 12345;
296   return((unsigned)(next/65536) % 32768);
297 }
298
299 static void DoUpdateMainFile(void)
300 {
301         int result;
302         int sz32;
303         sz32 = (myrand() % 1000)   + 20;
304         
305         result = yWriteFile(fullTempMainName,sz32);
306         if(result)
307             FatalError();
308         yaffs_rename(fullTempMainName,fullMainName);
309 }
310
311 static void DoVerifyMainFile(void)
312 {
313         int result;
314         result = yVerifyFile(fullMainName);
315         if(result)
316             FatalError();
317
318 }
319
320
321 void NorStressTestInitialise(const char *prefix)
322 {
323   MakeFullNames(prefix);
324   
325   yaffs_StartUp();
326   yaffs_mount(fullPathName);
327   UpdateCounter(fullPowerUpName,&powerUps,1);
328   UpdateCounter(fullStartName,&cycleStarts,1);
329   UpdateCounter(fullEndName,&cycleEnds,1);
330   UpdateCounter(fullPowerUpName,&powerUps,1);
331   DoUpdateMainFile();
332   DoVerifyMainFile();
333   yaffs_unmount(fullPathName);
334 }
335
336
337 void NorStressTestRun(const char *prefix)
338 {
339   MakeFullNames(prefix);
340
341   yaffs_StartUp();
342   yaffs_mount(fullPathName);
343   
344   dump_directory_tree(fullPathName);
345   
346   UpdateCounter(fullPowerUpName,&powerUps,0);
347   
348   while(1){
349     UpdateCounter(fullStartName, &cycleStarts,0);
350     DoVerifyMainFile();
351     DoUpdateMainFile();
352     dump_directory_tree(fullPathName);
353   
354     UpdateCounter(fullEndName,&cycleEnds,0);
355   }
356 }