Root/plasma/kernel/filesys.c

1/*--------------------------------------------------------------------
2 * TITLE: Plasma File System
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 4/26/07
5 * FILENAME: filesys.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Plasma File System. Supports RAM, flash, and disk file systems.
11 * Possible call tree:
12 * OS_fclose()
13 * FileFindRecursive() //find the existing file
14 * FileOpen() //open root file system
15 * FileFind() //find the next level of directory
16 * OS_fread() //read the directory file
17 * BlockRead() //read blocks of directory
18 * MediaBlockRead() //low level read
19 * FileOpen() //open next directory
20 * OS_fwrite() //write file entry into directory
21 * BlockRead() //flush changes to directory
22 *--------------------------------------------------------------------*/
23#ifdef WIN32
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#define _LIBC
28#endif
29#include "rtos.h"
30
31#define FLASH_SIZE 1024*1024*16
32#define FLASH_SECTOR_SIZE 1024*128
33#define FLASH_BLOCK_SIZE 512
34#define FLASH_LN2_SIZE 9 //2^FLASH_LN2_SIZE == FLASH_BLOCK_SIZE
35#define FLASH_OFFSET FLASH_SECTOR_SIZE //offset to start of flash file system
36
37#define BLOCK_SIZE 512
38#define FILE_NAME_SIZE 40
39#define FULL_NAME_SIZE 128
40#define BLOCK_MALLOC 0x0
41#define BLOCK_EOF 0xffffffff
42
43typedef enum {
44   FILE_MEDIA_RAM,
45   FILE_MEDIA_FLASH,
46   FILE_MEDIA_DISK
47} OS_MediaType_e;
48
49typedef struct OS_FileEntry_s {
50   char name[FILE_NAME_SIZE];
51   uint32 blockIndex; //first block of file
52   uint32 modifiedTime;
53   uint32 length;
54   uint8 isDirectory;
55   uint8 attributes;
56   uint8 valid;
57   uint8 mediaType;
58   uint16 blockSize; //Normally BLOCK_SIZE
59} OS_FileEntry_t;
60
61typedef struct OS_Block_s {
62   uint32 next;
63   uint8 data[4];
64} OS_Block_t;
65
66struct OS_FILE_s {
67   OS_FileEntry_t fileEntry; //written to directory upon OS_fclose()
68   uint8 fileModified;
69   uint8 blockModified;
70   uint32 blockIndex; //index of block
71   uint32 blockOffset; //byte offset into block
72   uint32 fileOffset; //byte offset into file
73   char fullname[FULL_NAME_SIZE]; //includes full path
74   OS_Block_t *block;
75   OS_Block_t *blockLocal; //local copy for flash or disk file system
76};
77
78static OS_FileEntry_t rootFileEntry;
79static OS_Mutex_t *mutexFilesys;
80
81// Public prototypes
82#ifndef _FILESYS_
83typedef struct OS_FILE_s OS_FILE;
84#endif
85OS_FILE *OS_fopen(char *name, char *mode);
86void OS_fclose(OS_FILE *file);
87int OS_fread(void *buffer, int size, int count, OS_FILE *file);
88int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
89int OS_fseek(OS_FILE *file, int offset, int mode);
90int OS_fmkdir(char *name);
91int OS_fdir(OS_FILE *dir, char name[64]);
92void OS_fdelete(char *name);
93
94
95/***************** Media Functions Start ***********************/
96#ifdef INCLUDE_FLASH
97#define FLASH_BLOCKS FLASH_SIZE/FLASH_BLOCK_SIZE
98#define FLASH_START (FLASH_OFFSET+FLASH_BLOCKS/8*2)/FLASH_BLOCK_SIZE
99static unsigned char FlashBlockEmpty[FLASH_BLOCKS/8];
100static unsigned char FlashBlockUsed[FLASH_BLOCKS/8];
101static int FlashBlock;
102
103//Free unused flash blocks
104static int MediaBlockCleanup(void)
105{
106   int i, sector, block, count=0;
107   unsigned char *buf;
108
109   printf("FlashCleanup\n");
110   buf = (unsigned char*)malloc(FLASH_SECTOR_SIZE);
111   if(buf == NULL)
112      return 0;
113   for(sector = FLASH_OFFSET / FLASH_SECTOR_SIZE; sector < FLASH_SIZE / FLASH_SECTOR_SIZE; ++sector)
114   {
115      FlashRead((uint16*)buf, FLASH_SECTOR_SIZE*sector, FLASH_SECTOR_SIZE);
116      if(sector == FLASH_OFFSET / FLASH_SECTOR_SIZE)
117      {
118         for(i = 0; i < FLASH_BLOCKS/8; ++i)
119            FlashBlockEmpty[i] |= ~FlashBlockUsed[i];
120         memcpy(buf, FlashBlockEmpty, sizeof(FlashBlockEmpty));
121         memset(FlashBlockUsed, 0xff, sizeof(FlashBlockUsed));
122         memset(buf+sizeof(FlashBlockEmpty), 0xff, sizeof(FlashBlockUsed));
123      }
124      //Erase empty blocks
125      for(block = 0; block < FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE; ++block)
126      {
127         i = sector * FLASH_SECTOR_SIZE / FLASH_BLOCK_SIZE + block;
128         if(i < FLASH_BLOCKS/8 && (FlashBlockEmpty[i >> 3] & (1 << (i & 7))))
129         {
130            memset(buf + FLASH_BLOCK_SIZE*block, 0xff, FLASH_BLOCK_SIZE);
131            ++count;
132         }
133      }
134      FlashErase(FLASH_SECTOR_SIZE * sector);
135      FlashWrite((uint16*)buf, FLASH_SECTOR_SIZE * sector, FLASH_SECTOR_SIZE);
136   }
137   free(buf);
138   return count;
139}
140
141
142int MediaBlockInit(void)
143{
144   FlashRead((uint16*)FlashBlockEmpty, FLASH_OFFSET, sizeof(FlashBlockEmpty));
145   FlashRead((uint16*)FlashBlockUsed, FLASH_OFFSET+sizeof(FlashBlockEmpty),
146             sizeof(FlashBlockUsed));
147   FlashBlock = FLASH_START;
148   return FlashBlockEmpty[FlashBlock >> 3] & (1 << (FlashBlock & 7));
149}
150#endif
151
152
153static uint32 MediaBlockMalloc(OS_FILE *file)
154{
155   int i, j;
156   (void)i; (void)j;
157
158   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
159      return (uint32)malloc(file->fileEntry.blockSize);
160#ifdef INCLUDE_FLASH
161   //Find empty flash block
162   for(i = FlashBlock; i < FLASH_BLOCKS; ++i)
163   {
164      if(FlashBlockEmpty[i >> 3] & (1 << (i & 7)))
165      {
166         FlashBlock = i + 1;
167         FlashBlockEmpty[i >> 3] &= ~(1 << (i & 7));
168         j = i >> 3;
169         j &= ~1;
170         FlashWrite((uint16*)(FlashBlockEmpty + j), FLASH_OFFSET + j, 2);
171         return i;
172      }
173   }
174
175   i = MediaBlockCleanup();
176   if(i == 0)
177      return 0;
178   FlashBlock = FLASH_START;
179   return MediaBlockMalloc(file);
180#else
181   return 0;
182#endif
183}
184
185
186static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
187{
188   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
189      free((void*)blockIndex);
190#ifdef INCLUDE_FLASH
191   else
192   {
193      int i=blockIndex, j;
194      FlashBlockUsed[i >> 3] &= ~(1 << (i & 7));
195      j = i >> 3;
196      j &= ~1;
197      FlashWrite((uint16*)(FlashBlockUsed + j), FLASH_OFFSET + sizeof(FlashBlockEmpty) + j, 2);
198   }
199#endif
200}
201
202
203static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
204{
205   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
206      file->block = (OS_Block_t*)blockIndex;
207#ifdef INCLUDE_FLASH
208   else
209   {
210      if(file->blockLocal == NULL)
211         file->blockLocal = (OS_Block_t*)malloc(FLASH_BLOCK_SIZE);
212      file->block = file->blockLocal;
213      FlashRead((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
214   }
215#endif
216}
217
218
219static void MediaBlockWrite(OS_FILE *file, uint32 blockIndex)
220{
221   (void)file;
222   (void)blockIndex;
223#ifdef INCLUDE_FLASH
224   if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
225      FlashWrite((uint16*)file->block, blockIndex << FLASH_LN2_SIZE, FLASH_BLOCK_SIZE);
226#endif
227}
228
229/***************** Media Functions End *************************/
230
231// Get the next block and write the old block if it was modified
232static void BlockRead(OS_FILE *file, uint32 blockIndex)
233{
234   uint32 blockIndexSave = blockIndex;
235
236   OS_MutexPend(mutexFilesys);
237   if(blockIndex == BLOCK_MALLOC)
238   {
239      // Get a new block
240      blockIndex = MediaBlockMalloc(file);
241      if(blockIndex == 0)
242         blockIndex = BLOCK_EOF;
243      if(file->block)
244      {
245         // Set next pointer in previous block
246         file->block->next = blockIndex;
247         file->blockModified = 1;
248      }
249   }
250   if(file->block && file->blockModified)
251   {
252      // Write block back to flash or disk
253      MediaBlockWrite(file, file->blockIndex);
254      file->blockModified = 0;
255   }
256   if(blockIndex == BLOCK_EOF)
257   {
258      OS_MutexPost(mutexFilesys);
259      return;
260   }
261   file->blockIndex = blockIndex;
262   file->blockOffset = 0;
263   MediaBlockRead(file, blockIndex);
264   if(blockIndexSave == BLOCK_MALLOC)
265   {
266      memset(file->block, 0xff, file->fileEntry.blockSize);
267      file->blockModified = 1;
268   }
269   OS_MutexPost(mutexFilesys);
270}
271
272
273int OS_fread(void *buffer, int size, int count, OS_FILE *file)
274{
275   int items, bytes;
276   uint8 *buf = (uint8*)buffer;
277
278   for(items = 0; items < count; ++items)
279   {
280      for(bytes = 0; bytes < size; ++bytes)
281      {
282         if(file->fileOffset >= file->fileEntry.length &&
283            file->fileEntry.isDirectory == 0)
284            return items;
285         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
286         {
287            if(file->block->next == BLOCK_EOF)
288               return items;
289            BlockRead(file, file->block->next);
290         }
291         *buf++ = file->block->data[file->blockOffset++];
292         ++file->fileOffset;
293      }
294   }
295   return items;
296}
297
298
299int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
300{
301   int items, bytes;
302   uint8 *buf = (uint8*)buffer;
303
304   OS_MutexPend(mutexFilesys);
305   file->blockModified = 1;
306   for(items = 0; items < count; ++items)
307   {
308      for(bytes = 0; bytes < size; ++bytes)
309      {
310         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
311         {
312            if(file->block->next == BLOCK_EOF)
313               file->block->next = BLOCK_MALLOC;
314            BlockRead(file, file->block->next);
315            if(file->blockIndex == BLOCK_EOF)
316            {
317               count = 0;
318               --items;
319               break;
320            }
321            file->blockModified = 1;
322         }
323         file->block->data[file->blockOffset++] = *buf++;
324         ++file->fileOffset;
325      }
326   }
327   file->blockModified = 1;
328   file->fileModified = 1;
329   if(file->fileOffset > file->fileEntry.length)
330      file->fileEntry.length = file->fileOffset;
331   OS_MutexPost(mutexFilesys);
332   return items;
333}
334
335
336int OS_fseek(OS_FILE *file, int offset, int mode)
337{
338   if(mode == 1) //SEEK_CUR
339      offset += file->fileOffset;
340   else if(mode == 2) //SEEK_END
341      offset += file->fileEntry.length;
342   file->fileOffset = offset;
343   BlockRead(file, file->fileEntry.blockIndex);
344   while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32))
345   {
346      BlockRead(file, file->block->next);
347      offset -= file->fileEntry.blockSize - (int)sizeof(uint32);
348   }
349   file->blockOffset = offset;
350   return 0;
351}
352
353
354static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry)
355{
356   memset(file, 0, sizeof(OS_FILE));
357   if(fileEntry == NULL)
358   {
359      // Open root file
360      memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t));
361   }
362   else if(fileEntry->valid == 1)
363   {
364      // Open existing file
365      memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t));
366   }
367   else
368   {
369      // Initialize new file
370      file->fileModified = 1;
371      file->blockModified = 1;
372      memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t));
373      file->fileEntry.isDirectory = 0;
374      file->fileEntry.length = 0;
375      strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1);
376      file->fileEntry.blockIndex = 0;
377      file->fileEntry.valid = 1;
378      file->fileEntry.blockSize = fileEntry->blockSize;
379      file->fileEntry.mediaType = fileEntry->mediaType;
380   }
381   BlockRead(file, file->fileEntry.blockIndex); //Get first block
382   file->fileEntry.blockIndex = file->blockIndex;
383   file->fileOffset = 0;
384   if(file->blockIndex == BLOCK_EOF)
385      return -1;
386   return 0;
387}
388
389
390static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry)
391{
392   int count, rc = -1;
393   uint32 blockIndex, blockOffset;
394   uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0;
395
396   // Loop through files in directory
397   for(;;)
398   {
399      blockIndex = directory->blockIndex;
400      blockOffset = directory->blockOffset;
401      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory);
402      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
403         break;
404      if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0)
405      {
406         rc = 0; //Found the file in the directory
407         break;
408      }
409      if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF)
410      {
411         blockIndexEmpty = blockIndex;
412         blockOffsetEmpty = blockOffset;
413      }
414   }
415   if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH ||
416      blockIndexEmpty == BLOCK_EOF)
417   {
418      // Backup to start of fileEntry or last entry in directory
419      if(directory->blockIndex != blockIndex)
420         BlockRead(directory, blockIndex);
421      directory->blockOffset = blockOffset;
422   }
423   else
424   {
425      // Backup to empty slot
426      if(directory->blockIndex != blockIndexEmpty)
427         BlockRead(directory, blockIndexEmpty);
428      directory->blockOffset = blockOffsetEmpty;
429   }
430   return rc;
431}
432
433
434static int FileFindRecursive(OS_FILE *directory, char *name,
435                             OS_FileEntry_t *fileEntry, char *filename)
436{
437   int rc, length;
438
439   rc = FileOpen(directory, NULL, NULL); //Open root directory
440   for(;;)
441   {
442      if(name[0] == '/')
443         ++name;
444      for(length = 0; length < FILE_NAME_SIZE; ++length)
445      {
446         if(name[length] == 0 || name[length] == '/')
447            break;
448         filename[length] = name[length];
449      }
450      filename[length] = 0;
451      rc = FileFind(directory, filename, fileEntry); //Find file
452      if(rc)
453      {
454         // File not found
455         fileEntry->mediaType = directory->fileEntry.mediaType;
456         fileEntry->blockSize = directory->fileEntry.blockSize;
457         fileEntry->valid = 0;
458         if(strstr(name, "/") == NULL)
459            return rc;
460         else
461            return -2; //can't find parent directory
462      }
463      name += length;
464      if(name[0])
465         rc = FileOpen(directory, filename, fileEntry); //Open subdir
466      else
467         break;
468   }
469   return rc;
470}
471
472
473OS_FILE *OS_fopen(char *name, char *mode)
474{
475   OS_FILE *file;
476   OS_FileEntry_t fileEntry;
477   OS_FILE dir;
478   char filename[FILE_NAME_SIZE]; //Name without directories
479   int rc;
480
481   if(rootFileEntry.blockIndex == 0)
482   {
483      // Mount file system
484      mutexFilesys = OS_MutexCreate("filesys");
485      memset(&dir, 0, sizeof(OS_FILE));
486      dir.fileEntry.blockSize = BLOCK_SIZE;
487      //dir.fileEntry.mediaType = FILE_MEDIA_FLASH; //Test flash
488      BlockRead(&dir, BLOCK_MALLOC);
489      strcpy(rootFileEntry.name, "/");
490      rootFileEntry.mediaType = dir.fileEntry.mediaType;
491      rootFileEntry.blockIndex = dir.blockIndex;
492      rootFileEntry.blockSize = dir.fileEntry.blockSize;
493      rootFileEntry.isDirectory = 1;
494      BlockRead(&dir, BLOCK_EOF); //Flush data
495#ifdef INCLUDE_FLASH
496      file = OS_fopen("flash", "w+");
497      if(file == NULL)
498         return NULL;
499      file->fileEntry.isDirectory = 1;
500      file->fileEntry.mediaType = FILE_MEDIA_FLASH;
501      file->fileEntry.blockSize = FLASH_BLOCK_SIZE;
502      file->blockLocal = file->block;
503      file->block = NULL;
504      rc = MediaBlockInit();
505      if(rc == 1)
506         BlockRead(file, BLOCK_MALLOC);
507      else
508         BlockRead(file, FLASH_START);
509      file->fileEntry.blockIndex = file->blockIndex;
510      OS_fclose(file);
511#endif
512   }
513
514   file = (OS_FILE*)malloc(sizeof(OS_FILE));
515   if(file == NULL)
516      return NULL;
517   OS_MutexPend(mutexFilesys);
518   if(name[0] == 0 || strcmp(name, "/") == 0)
519   {
520      FileOpen(file, NULL, NULL);
521      OS_MutexPost(mutexFilesys);
522      return file;
523   }
524   if(mode[0] == 'w')
525   {
526      //Don't over write a directory
527      fileEntry.isDirectory = 0;
528      rc = FileFindRecursive(&dir, name, &fileEntry, filename);
529      if(dir.blockLocal)
530         free(dir.blockLocal);
531      if(rc == 0)
532      {
533         if(fileEntry.isDirectory)
534         {
535            free(file);
536            return NULL;
537         }
538         OS_fdelete(name);
539      }
540   }
541   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
542   if(dir.blockLocal)
543      free(dir.blockLocal);
544   if(rc == -2 || (rc && mode[0] == 'r'))
545   {
546      free(file);
547      OS_MutexPost(mutexFilesys);
548      return NULL;
549   }
550   if(rc)
551      fileEntry.valid = 0;
552   rc = FileOpen(file, filename, &fileEntry); //Open file
553   file->fullname[0] = 0;
554   strncat(file->fullname, name, FULL_NAME_SIZE);
555   OS_MutexPost(mutexFilesys);
556   if(mode[0] == 'a')
557      OS_fseek(file, 0, 2); //goto end of file
558   return file;
559}
560
561
562void OS_fclose(OS_FILE *file)
563{
564   OS_FileEntry_t fileEntry;
565   OS_FILE dir;
566   char filename[FILE_NAME_SIZE];
567   int rc;
568
569   if(file->fileModified)
570   {
571      // Write file->fileEntry into parent directory
572      OS_MutexPend(mutexFilesys);
573      BlockRead(file, BLOCK_EOF);
574      rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
575      if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
576      {
577         // Invalidate old entry and add new entry at the end
578         fileEntry.valid = 0;
579         OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
580         FileFind(&dir, "endoffile", &fileEntry);
581      }
582      OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
583      BlockRead(&dir, BLOCK_EOF); //flush data
584      if(dir.blockLocal)
585         free(dir.blockLocal);
586      OS_MutexPost(mutexFilesys);
587   }
588   if(file->blockLocal)
589      free(file->blockLocal);
590   free(file);
591}
592
593
594int OS_fmkdir(char *name)
595{
596   OS_FILE *file;
597   file = OS_fopen(name, "w+");
598   if(file == NULL)
599      return -1;
600   file->fileEntry.isDirectory = 1;
601   OS_fclose(file);
602   return 0;
603}
604
605
606void OS_fdelete(char *name)
607{
608   OS_FILE dir, file;
609   OS_FileEntry_t fileEntry;
610   int rc;
611   uint32 blockIndex;
612   char filename[FILE_NAME_SIZE]; //Name without directories
613
614   OS_MutexPend(mutexFilesys);
615   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
616   if(rc == 0)
617   {
618      FileOpen(&file, NULL, &fileEntry);
619      for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
620      {
621         BlockRead(&file, file.block->next);
622         MediaBlockFree(&file, blockIndex);
623      }
624      MediaBlockFree(&file, blockIndex);
625      fileEntry.valid = 0;
626      OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
627      BlockRead(&dir, BLOCK_EOF);
628      if(file.blockLocal)
629         free(file.blockLocal);
630   }
631   if(dir.blockLocal)
632      free(dir.blockLocal);
633   OS_MutexPost(mutexFilesys);
634}
635
636
637int OS_flength(char *entry)
638{
639   OS_FileEntry_t *entry2=(OS_FileEntry_t*)entry;
640   return entry2->length;
641}
642
643
644int OS_fdir(OS_FILE *dir, char name[64])
645{
646   OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name;
647   int count;
648   for(;;)
649   {
650      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir);
651      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
652         return -1;
653      if(fileEntry->valid == 1)
654         break;
655   }
656   return 0;
657}
658
659/*************************************************/
660#define TEST_FILES
661#ifdef TEST_FILES
662int DirRecursive(char *name)
663{
664   OS_FileEntry_t fileEntry;
665   OS_FILE *dir;
666   char fullname[FULL_NAME_SIZE];
667   int rc;
668
669   dir = OS_fopen(name, "r");
670   for(;;)
671   {
672      rc = OS_fdir(dir, (char*)&fileEntry);
673      if(rc)
674         break;
675      printf("%s %d\n", fileEntry.name, fileEntry.length);
676      if(fileEntry.isDirectory)
677      {
678         if(strcmp(name, "/") == 0)
679            sprintf(fullname, "/%s", fileEntry.name);
680         else
681            sprintf(fullname, "%s/%s", name, fileEntry.name);
682         DirRecursive(fullname);
683      }
684   }
685   OS_fclose(dir);
686   return 0;
687}
688
689int OS_ftest(void)
690{
691   OS_FILE *file;
692   char *buf;
693   int count;
694   int i, j;
695
696   buf = (char*)malloc(5000);
697   memset(buf, 0, 5000);
698   for(count = 0; count < 4000; ++count)
699      buf[count] = (char)('A' + (count % 26));
700   OS_fmkdir("dir");
701   OS_fmkdir("/dir/subdir");
702   file = OS_fopen("/dir/subdir/test.txt", "w");
703   count = OS_fwrite(buf, 1, 4000, file);
704   OS_fclose(file);
705   memset(buf, 0, 5000);
706   file = OS_fopen("/dir/subdir/test.txt", "r");
707   count = OS_fread(buf, 1, 5000, file);
708   OS_fclose(file);
709   printf("(%s)\n", buf);
710
711   DirRecursive("/");
712
713   for(i = 0; i < 5; ++i)
714   {
715      sprintf(buf, "/dir%d", i);
716      OS_fmkdir(buf);
717      for(j = 0; j < 5; ++j)
718      {
719         sprintf(buf, "/dir%d/file%d%d", i, i, j);
720         file = OS_fopen(buf, "w");
721         sprintf(buf, "i=%d j=%d", i, j);
722         OS_fwrite(buf, 1, 8, file);
723         OS_fclose(file);
724      }
725   }
726
727   OS_fdelete("/dir1/file12");
728   DirRecursive("/");
729   file = OS_fopen("/baddir/myfile.txt", "w");
730   if(file)
731      printf("ERROR!\n");
732
733   for(i = 0; i < 5; ++i)
734   {
735      for(j = 0; j < 5; ++j)
736      {
737         sprintf(buf, "/dir%d/file%d%d", i, i, j);
738         file = OS_fopen(buf, "r");
739         if(file)
740         {
741            count = OS_fread(buf, 1, 500, file);
742            printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf);
743            OS_fclose(file);
744         }
745      }
746   }
747
748   OS_fdelete("/dir/subdir/test.txt");
749   OS_fdelete("/dir/subdir");
750   OS_fdelete("/dir");
751   for(i = 0; i < 5; ++i)
752   {
753      for(j = 0; j < 5; ++j)
754      {
755         sprintf(buf, "/dir%d/file%d%d", i, i, j);
756         OS_fdelete(buf);
757      }
758      sprintf(buf, "/dir%d", i);
759      OS_fdelete(buf);
760   }
761
762   DirRecursive("/");
763
764   free(buf);
765   return 0;
766}
767#endif //TEST_FILES
768

Archive Download this file

Branches:
master



interactive