OpenCores
URL https://opencores.org/ocsvn/plasma/plasma/trunk

Subversion Repositories plasma

[/] [plasma/] [trunk/] [kernel/] [filesys.c] - Blame information for rev 219

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 219 rhoads
/*--------------------------------------------------------------------
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
#ifndef WIN32
24
#include "rtos.h"
25
#else
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
typedef unsigned int   uint32;
30
typedef unsigned short uint16;
31
typedef unsigned char  uint8;
32
#endif
33
 
34
#define BLOCK_SIZE      512
35
#define FILE_NAME_SIZE   40
36
#define FULL_NAME_SIZE  128
37
#define BLOCK_MALLOC    0x0
38
#define BLOCK_EOF       0xffffffff
39
 
40
typedef enum {
41
   FILE_MEDIA_RAM,
42
   FILE_MEDIA_FLASH,
43
   FILE_MEDIA_DISK
44
} OS_MediaType_e;
45
 
46
typedef struct OS_FileEntry_s {
47
   char name[FILE_NAME_SIZE];
48
   uint32 blockIndex;       //first block of file
49
   uint32 modifiedTime;
50
   uint32 length;
51
   uint8 isDirectory;
52
   uint8 attributes;
53
   uint8 valid;
54
   uint8 mediaType;
55
   uint16 blockSize;        //Normally BLOCK_SIZE
56
} OS_FileEntry_t;
57
 
58
typedef struct OS_Block_s {
59
   uint32 next;
60
   uint8 data[4];
61
} OS_Block_t;
62
 
63
struct OS_FILE_s {
64
   OS_FileEntry_t fileEntry;  //written to directory upon OS_fclose()
65
   uint8 fileModified;
66
   uint8 blockModified;
67
   uint32 blockIndex;         //index of block
68
   uint32 blockOffset;        //byte offset into block
69
   uint32 fileOffset;         //byte offset into file
70
   char fullname[FULL_NAME_SIZE]; //includes full path
71
   OS_Block_t *block;
72
   OS_Block_t *blockLocal;    //local copy for flash or disk file system
73
};
74
 
75
static OS_FileEntry_t rootFileEntry;
76
 
77
// Public prototypes
78
#ifndef _FILESYS_
79
typedef struct OS_FILE_s OS_FILE;
80
#endif
81
OS_FILE *OS_fopen(char *name, char *mode);
82
void OS_fclose(OS_FILE *file);
83
int OS_fread(void *buffer, int size, int count, OS_FILE *file);
84
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file);
85
int OS_fseek(OS_FILE *file, int offset, int mode);
86
int OS_fmkdir(char *name);
87
int OS_fdir(OS_FILE *dir, char name[64]);
88
void OS_fdelete(char *name);
89
 
90
 
91
/***************** Media Functions Start ***********************/
92
static uint32 MediaBlockMalloc(OS_FILE *file)
93
{
94
   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
95
      return (uint32)malloc(file->fileEntry.blockSize);
96
   else
97
      return (uint32)malloc(file->fileEntry.blockSize);  //TODO
98
}
99
 
100
 
101
static void MediaBlockFree(OS_FILE *file, uint32 blockIndex)
102
{
103
   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
104
      free((void*)blockIndex);
105
   else
106
      free((void*)blockIndex);  //TODO
107
}
108
 
109
 
110
static void MediaBlockRead(OS_FILE *file, uint32 blockIndex)
111
{
112
   if(file->fileEntry.mediaType == FILE_MEDIA_RAM)
113
      file->block = (OS_Block_t*)blockIndex;
114
   else
115
   {
116
      if(file->blockLocal == NULL)
117
         file->blockLocal = (OS_Block_t*)malloc(file->fileEntry.blockSize);
118
      file->block = file->blockLocal;
119
      memcpy(file->block, (void*)blockIndex, file->fileEntry.blockSize); //TODO
120
   }
121
}
122
 
123
 
124
static void MediaBlockWrite(OS_FILE *file)
125
{
126
   if(file->fileEntry.mediaType != FILE_MEDIA_RAM)
127
      memcpy((void*)file->blockIndex, file->block, file->fileEntry.blockSize); //TODO
128
}
129
 
130
/***************** Media Functions End *************************/
131
 
132
// Get the next block and write the old block if it was modified
133
static void BlockRead(OS_FILE *file, uint32 blockIndex)
134
{
135
   uint32 blockIndexSave = blockIndex;
136
   if(blockIndex == BLOCK_MALLOC)
137
   {
138
      // Get a new block
139
      blockIndex = MediaBlockMalloc(file);
140
      if(blockIndex == 0)
141
         blockIndex = BLOCK_EOF;
142
      if(file->block)
143
      {
144
         // Set next pointer in previous block
145
         file->block->next = blockIndex;
146
         file->blockModified = 1;
147
      }
148
   }
149
   if(file->block && file->blockModified)
150
   {
151
      // Write block back to flash or disk
152
      MediaBlockWrite(file);
153
      file->blockModified = 0;
154
   }
155
   if(blockIndex == BLOCK_EOF)
156
      return;
157
   file->blockIndex = blockIndex;
158
   file->blockOffset = 0;
159
   MediaBlockRead(file, blockIndex);
160
   if(blockIndexSave == BLOCK_MALLOC)
161
   {
162
      memset(file->block, 0xff, file->fileEntry.blockSize);
163
      file->blockModified = 1;
164
   }
165
}
166
 
167
 
168
int OS_fread(void *buffer, int size, int count, OS_FILE *file)
169
{
170
   int items, bytes;
171
   uint8 *buf = (uint8*)buffer;
172
 
173
   for(items = 0; items < count; ++items)
174
   {
175
      for(bytes = 0; bytes < size; ++bytes)
176
      {
177
         if(file->fileOffset >= file->fileEntry.length &&
178
            file->fileEntry.isDirectory == 0)
179
            return items;
180
         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
181
         {
182
            if(file->block->next == BLOCK_EOF)
183
               return items;
184
            BlockRead(file, file->block->next);
185
         }
186
         *buf++ = file->block->data[file->blockOffset++];
187
         ++file->fileOffset;
188
      }
189
   }
190
   return items;
191
}
192
 
193
 
194
int OS_fwrite(void *buffer, int size, int count, OS_FILE *file)
195
{
196
   int items, bytes;
197
   uint8 *buf = (uint8*)buffer;
198
 
199
   file->blockModified = 1;
200
   for(items = 0; items < count; ++items)
201
   {
202
      for(bytes = 0; bytes < size; ++bytes)
203
      {
204
         if(file->blockOffset >= file->fileEntry.blockSize - sizeof(uint32))
205
         {
206
            if(file->block->next == BLOCK_EOF)
207
               file->block->next = BLOCK_MALLOC;
208
            BlockRead(file, file->block->next);
209
            if(file->blockIndex == BLOCK_EOF)
210
            {
211
               count = 0;
212
               --items;
213
               break;
214
            }
215
            file->blockModified = 1;
216
         }
217
         file->block->data[file->blockOffset++] = *buf++;
218
         ++file->fileOffset;
219
      }
220
   }
221
   file->blockModified = 1;
222
   file->fileModified = 1;
223
   if(file->fileOffset > file->fileEntry.length)
224
      file->fileEntry.length = file->fileOffset;
225
   return items;
226
}
227
 
228
 
229
int OS_fseek(OS_FILE *file, int offset, int mode)
230
{
231
   if(mode == 1)      //SEEK_CUR
232
      offset += file->fileOffset;
233
   else if(mode == 2) //SEEK_END
234
      offset += file->fileEntry.length;
235
   file->fileOffset = offset;
236
   BlockRead(file, file->fileEntry.blockIndex);
237
   while(offset > (int)file->fileEntry.blockSize - (int)sizeof(uint32))
238
   {
239
      BlockRead(file, file->block->next);
240
      offset -= file->fileEntry.blockSize - (int)sizeof(uint32);
241
   }
242
   file->blockOffset = offset;
243
   return 0;
244
}
245
 
246
 
247
static int FileOpen(OS_FILE *file, char *name, OS_FileEntry_t *fileEntry)
248
{
249
   memset(file, 0, sizeof(OS_FILE));
250
   if(fileEntry == NULL)
251
   {
252
      // Open root file
253
      memcpy(&file->fileEntry, &rootFileEntry, sizeof(OS_FileEntry_t));
254
   }
255
   else if(fileEntry->valid == 1)
256
   {
257
      // Open existing file
258
      memcpy(&file->fileEntry, fileEntry, sizeof(OS_FileEntry_t));
259
   }
260
   else
261
   {
262
      // Initialize new file
263
      file->fileModified = 1;
264
      file->blockModified = 1;
265
      memset(&file->fileEntry, 0, sizeof(OS_FileEntry_t));
266
      file->fileEntry.isDirectory = 0;
267
      file->fileEntry.length = 0;
268
      strncpy(file->fileEntry.name, name, FILE_NAME_SIZE-1);
269
      file->fileEntry.blockIndex = 0;
270
      file->fileEntry.valid = 1;
271
      file->fileEntry.blockSize = fileEntry->blockSize;
272
      file->fileEntry.mediaType = fileEntry->mediaType;
273
   }
274
   BlockRead(file, file->fileEntry.blockIndex);    //Get first block
275
   file->fileEntry.blockIndex = file->blockIndex;
276
   file->fileOffset = 0;
277
   if(file->blockIndex == BLOCK_EOF)
278
      return -1;
279
   return 0;
280
}
281
 
282
 
283
static int FileFind(OS_FILE *directory, char *name, OS_FileEntry_t *fileEntry)
284
{
285
   int count, rc = -1;
286
   uint32 blockIndex, blockOffset;
287
   uint32 blockIndexEmpty=BLOCK_EOF, blockOffsetEmpty=0;
288
 
289
   // Loop through files in directory
290
   for(;;)
291
   {
292
      blockIndex = directory->blockIndex;
293
      blockOffset = directory->blockOffset;
294
      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, directory);
295
      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
296
         break;
297
      if(fileEntry->valid == 1 && strcmp(fileEntry->name, name) == 0)
298
      {
299
         rc = 0;  //Found the file in the directory
300
         break;
301
      }
302
      if(fileEntry->valid != 1 && blockIndexEmpty == BLOCK_EOF)
303
      {
304
         blockIndexEmpty = blockIndex;
305
         blockOffsetEmpty = blockOffset;
306
      }
307
   }
308
   if(rc == 0 || directory->fileEntry.mediaType == FILE_MEDIA_FLASH ||
309
      blockIndexEmpty == BLOCK_EOF)
310
   {
311
      // Backup to start of fileEntry or last entry in directory
312
      if(directory->blockIndex != blockIndex)
313
         BlockRead(directory, blockIndex);
314
      directory->blockOffset = blockOffset;
315
   }
316
   else
317
   {
318
      // Backup to empty slot
319
      if(directory->blockIndex != blockIndexEmpty)
320
         BlockRead(directory, blockIndexEmpty);
321
      directory->blockOffset = blockOffsetEmpty;
322
   }
323
   return rc;
324
}
325
 
326
 
327
static int FileFindRecursive(OS_FILE *directory, char *name,
328
                             OS_FileEntry_t *fileEntry, char *filename)
329
{
330
   int rc, length;
331
 
332
   rc = FileOpen(directory, NULL, NULL);            //Open root directory
333
   for(;;)
334
   {
335
      if(name[0] == '/')
336
         ++name;
337
      for(length = 0; length < FILE_NAME_SIZE; ++length)
338
      {
339
         if(name[length] == 0 || name[length] == '/')
340
            break;
341
         filename[length] = name[length];
342
      }
343
      filename[length] = 0;
344
      rc = FileFind(directory, filename, fileEntry);  //Find file
345
      if(rc)
346
      {
347
         // File not found
348
         fileEntry->mediaType = directory->fileEntry.mediaType;
349
         fileEntry->blockSize = directory->fileEntry.blockSize;
350
         if(strstr(name, "/") == NULL)
351
            return rc;
352
         else
353
            return -2;  //can't find parent directory
354
      }
355
      name += length;
356
      if(name[0])
357
         rc = FileOpen(directory, filename, fileEntry);  //Open subdir
358
      else
359
         break;
360
   }
361
   return rc;
362
}
363
 
364
 
365
OS_FILE *OS_fopen(char *name, char *mode)
366
{
367
   OS_FILE *file;
368
   OS_FileEntry_t fileEntry;
369
   OS_FILE dir;
370
   char filename[FILE_NAME_SIZE];  //Name without directories
371
   int rc;
372
 
373
   if(rootFileEntry.blockIndex == 0)
374
   {
375
      // Mount file system
376
      memset(&dir, 0, sizeof(OS_FILE));
377
      dir.fileEntry.blockSize = BLOCK_SIZE;
378
      //dir.fileEntry.mediaType = FILE_MEDIA_FLASH;  //Test flash
379
      BlockRead(&dir, BLOCK_MALLOC);
380
      strcpy(rootFileEntry.name, "/");
381
      rootFileEntry.mediaType = dir.fileEntry.mediaType;
382
      rootFileEntry.blockIndex = dir.blockIndex;
383
      rootFileEntry.blockSize = dir.fileEntry.blockSize;
384
      rootFileEntry.isDirectory = 1;
385
      BlockRead(&dir, BLOCK_EOF);    //Flush data
386
   }
387
 
388
   file = (OS_FILE*)malloc(sizeof(OS_FILE));
389
   if(file == NULL)
390
      return NULL;
391
   if(strcmp(name, "/") == 0)
392
   {
393
      FileOpen(file, NULL, NULL);
394
      return file;
395
   }
396
   if(strcmp(mode, "w") == 0)
397
      OS_fdelete(name);
398
   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
399
   if(dir.blockLocal)
400
      free(dir.blockLocal);
401
   if(rc == -2 || (rc && mode[0] == 'r'))
402
   {
403
      free(file);
404
      return NULL;
405
   }
406
   rc = FileOpen(file, filename, &fileEntry);  //Open file
407
   file->fullname[0] = 0;
408
   strncat(file->fullname, name, FULL_NAME_SIZE);
409
   return file;
410
}
411
 
412
 
413
void OS_fclose(OS_FILE *file)
414
{
415
   OS_FileEntry_t fileEntry;
416
   OS_FILE dir;
417
   char filename[FILE_NAME_SIZE];
418
   int rc;
419
 
420
   if(file->fileModified)
421
   {
422
      // Write file->fileEntry into parent directory
423
      BlockRead(file, BLOCK_EOF);
424
      rc = FileFindRecursive(&dir, file->fullname, &fileEntry, filename);
425
      if(file->fileEntry.mediaType == FILE_MEDIA_FLASH && rc == 0)
426
      {
427
         // Invalidate old entry and add new entry at the end
428
         fileEntry.valid = 0;
429
         OS_fwrite(&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
430
         FileFind(&dir, "endoffile", &fileEntry);
431
      }
432
      OS_fwrite(&file->fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
433
      BlockRead(&dir, BLOCK_EOF);  //flush data
434
      if(dir.blockLocal)
435
         free(dir.blockLocal);
436
   }
437
   if(file->blockLocal)
438
      free(file->blockLocal);
439
   free(file);
440
}
441
 
442
 
443
int OS_fmkdir(char *name)
444
{
445
   OS_FILE *file;
446
   file = OS_fopen(name, "w+");
447
   if(file == NULL)
448
      return -1;
449
   file->fileEntry.isDirectory = 1;
450
   OS_fclose(file);
451
   return 0;
452
}
453
 
454
 
455
void OS_fdelete(char *name)
456
{
457
   OS_FILE dir, file;
458
   OS_FileEntry_t fileEntry;
459
   int rc;
460
   uint32 blockIndex;
461
   char filename[FILE_NAME_SIZE];  //Name without directories
462
 
463
   rc = FileFindRecursive(&dir, name, &fileEntry, filename);
464
   if(rc == 0)
465
   {
466
      FileOpen(&file, NULL, &fileEntry);
467
      for(blockIndex = file.blockIndex; file.block->next != BLOCK_EOF; blockIndex = file.blockIndex)
468
      {
469
         BlockRead(&file, file.block->next);
470
         MediaBlockFree(&file, blockIndex);
471
      }
472
      MediaBlockFree(&file, blockIndex);
473
      fileEntry.valid = 0;
474
      OS_fwrite((char*)&fileEntry, sizeof(OS_FileEntry_t), 1, &dir);
475
      BlockRead(&dir, BLOCK_EOF);
476
      if(file.blockLocal)
477
         free(file.blockLocal);
478
   }
479
   if(dir.blockLocal)
480
      free(dir.blockLocal);
481
}
482
 
483
 
484
int OS_fdir(OS_FILE *dir, char name[64])
485
{
486
   OS_FileEntry_t *fileEntry = (OS_FileEntry_t*)name;
487
   int count;
488
   for(;;)
489
   {
490
      count = OS_fread(fileEntry, sizeof(OS_FileEntry_t), 1, dir);
491
      if(count == 0 || fileEntry->blockIndex == BLOCK_EOF)
492
         return -1;
493
      if(fileEntry->valid == 1)
494
         break;
495
   }
496
   return 0;
497
}
498
 
499
/*************************************************/
500
#define TEST_FILES
501
#ifdef TEST_FILES
502
int DirRecursive(char *name)
503
{
504
   OS_FileEntry_t fileEntry;
505
   OS_FILE *dir;
506
   char fullname[FULL_NAME_SIZE];
507
   int rc;
508
 
509
   dir = OS_fopen(name, "r");
510
   for(;;)
511
   {
512
      rc = OS_fdir(dir, (char*)&fileEntry);
513
      if(rc)
514
         break;
515
      printf("%s %d\n", fileEntry.name, fileEntry.length);
516
      if(fileEntry.isDirectory)
517
      {
518
         if(strcmp(name, "/") == 0)
519
            sprintf(fullname, "/%s", fileEntry.name);
520
         else
521
            sprintf(fullname, "%s/%s", name, fileEntry.name);
522
         DirRecursive(fullname);
523
      }
524
   }
525
   OS_fclose(dir);
526
   return 0;
527
}
528
 
529
int OS_ftest(void)
530
{
531
   OS_FILE *file;
532
   char *buf;
533
   int count;
534
   int i, j;
535
 
536
   buf = (char*)malloc(5000);
537
   memset(buf, 0, 5000);
538
   for(count = 0; count < 4000; ++count)
539
      buf[count] = (char)('A' + (count % 26));
540
   OS_fmkdir("dir");
541
   OS_fmkdir("/dir/subdir");
542
   file = OS_fopen("/dir/subdir/test.txt", "w");
543
   count = OS_fwrite(buf, 1, 4000, file);
544
   OS_fclose(file);
545
   memset(buf, 0, 5000);
546
   file = OS_fopen("/dir/subdir/test.txt", "r");
547
   count = OS_fread(buf, 1, 5000, file);
548
   OS_fclose(file);
549
   printf("(%s)\n", buf);
550
 
551
   DirRecursive("/");
552
 
553
   for(i = 0; i < 5; ++i)
554
   {
555
      sprintf(buf, "/dir%d", i);
556
      OS_fmkdir(buf);
557
      for(j = 0; j < 5; ++j)
558
      {
559
         sprintf(buf, "/dir%d/file%d%d", i, i, j);
560
         file = OS_fopen(buf, "w");
561
         sprintf(buf, "i=%d j=%d", i, j);
562
         OS_fwrite(buf, 1, 8, file);
563
         OS_fclose(file);
564
      }
565
   }
566
 
567
   OS_fdelete("/dir1/file12");
568
   DirRecursive("/");
569
   file = OS_fopen("/baddir/myfile.txt", "w");
570
   if(file)
571
      printf("ERROR!\n");
572
 
573
   for(i = 0; i < 5; ++i)
574
   {
575
      for(j = 0; j < 5; ++j)
576
      {
577
         sprintf(buf, "/dir%d/file%d%d", i, i, j);
578
         file = OS_fopen(buf, "r");
579
         if(file)
580
         {
581
            count = OS_fread(buf, 1, 500, file);
582
            printf("i=%d j=%d count=%d (%s)\n", i, j, count, buf);
583
            OS_fclose(file);
584
         }
585
      }
586
   }
587
 
588
   OS_fdelete("/dir/subdir/test.txt");
589
   OS_fdelete("/dir/subdir");
590
   OS_fdelete("/dir");
591
   for(i = 0; i < 5; ++i)
592
   {
593
      for(j = 0; j < 5; ++j)
594
      {
595
         sprintf(buf, "/dir%d/file%d%d", i, i, j);
596
         OS_fdelete(buf);
597
      }
598
      sprintf(buf, "/dir%d", i);
599
      OS_fdelete(buf);
600
   }
601
 
602
   DirRecursive("/");
603
 
604
   free(buf);
605
   return 0;
606
}
607
#endif  //TEST_FILES

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.