Choco OS  V.0.16.9.0
Join to the chocolate world
oc_ramfs.c
Go to the documentation of this file.
1 
27 #include <oc_ramfs.h>
28 #include <oc_list.h>
29 #include <oc_stdlib.h>
30 #include <oc_object.h>
31 #include <oc_ifnot.h>
32 #include <string.h>
33 #include <oc_intman.h>
34 #include <oc_array.h>
35 #include <oc_math.h>
36 #include <oc_ktime.h>
37 #include <oc_errors.h>
38 
44 #define _________________________________________MACROS_SECTION_____________________________________________________________________________
45 
46 #define IsFileCorrect(File) (oC_CheckObjectControl((File),oC_ObjectId_RamFsFile,(File)->ObjectControl))
47 #define IsDirCorrect(Dir) (oC_CheckObjectControl((Dir),oC_ObjectId_RamFsDir,(Dir)->ObjectControl))
48 #define IsFileReadOnly(file) ((file)->Attributes & oC_FileSystem_FileAttributes_ReadOnly )
49 #define IsFileLocked(File) ((file)->Lock)
50 
51 #undef _________________________________________MACROS_SECTION_____________________________________________________________________________
52 
53 
59 #define _________________________________________TYPES_SECTION______________________________________________________________________________
60 
61 struct File_t
62 {
63  oC_ObjectControl_t ObjectControl;
64  char * Path;
65  uint8_t * Data;
66  uint32_t Size;
67  uint32_t Offset;
68  oC_FileSystem_FileType_t FileType;
69  oC_FileSystem_FileAttributes_t Attributes;
70  bool Lock;
71  oC_Timestamp_t Timestamp;
72 };
73 
74 struct Dir_t
75 {
76  oC_ObjectControl_t ObjectControl;
77  char * Path;
78  oC_File_t LastFile;
79 };
80 
81 struct Context_t
82 {
83  oC_ObjectControl_t ObjectControl;
84  oC_List(oC_File_t) Files;
85 };
86 
87 #undef _________________________________________TYPES_SECTION______________________________________________________________________________
88 
94 #define _________________________________________PROTOTYPES_SECTION_________________________________________________________________________
95 
96 static bool IsContextCorrect(oC_RamFs_Context_t Context );
97 static const char * GetLastEntryNameFromPath( const char * Path );
98 static char * GetParentDirOfPath( const char * Path , char * outDir , oC_UInt_t Size );
99 static bool CheckIfParentDirectoryExists( oC_RamFs_Context_t Context , const char * Path );
100 static bool CheckIfPathExists( oC_RamFs_Context_t Context , const char * Path );
101 static oC_File_t GetFile( oC_RamFs_Context_t Context , const char * Path );
102 static oC_File_t CreateFile( oC_RamFs_Context_t Context , const char * Path , oC_FileSystem_FileType_t FileType , oC_FileSystem_FileAttributes_t Attributes );
103 static bool DeleteFile( oC_RamFs_Context_t Context , const char * Path );
104 static bool LockFile( oC_File_t File );
105 static void UnlockFile( oC_File_t File );
106 
107 #undef _________________________________________PROTOTYPES_SECTION_________________________________________________________________________
108 
109 
115 #define _________________________________________VARIABLES_SECTION__________________________________________________________________________
116 
117 //==========================================================================================================================================
118 //==========================================================================================================================================
119 const oC_FileSystem_Registration_t RamFs = {
120  .Name = "RamFs" ,
121  .init = oC_RamFs_init ,
122  .deinit = oC_RamFs_deinit ,
123  .fopen = oC_RamFs_fopen ,
124  .fclose = oC_RamFs_fclose ,
125  .fread = oC_RamFs_fread ,
126  .fwrite = oC_RamFs_fwrite ,
127  .lseek = oC_RamFs_lseek ,
128  .ioctl = oC_RamFs_ioctl ,
129  .sync = oC_RamFs_sync ,
130  .Getc = oC_RamFs_getc ,
131  .Putc = oC_RamFs_putc ,
132  .tell = NULL ,
133  .eof = oC_RamFs_eof ,
134  .size = oC_RamFs_size ,
135 
136  .opendir = oC_RamFs_opendir ,
137  .closedir = oC_RamFs_closedir ,
138  .readdir = oC_RamFs_readdir ,
139 
140  .stat = oC_RamFs_stat ,
141  .unlink = oC_RamFs_unlink ,
142  .rename = oC_RamFs_rename ,
143  .chmod = oC_RamFs_chmod ,
144  .utime = oC_RamFs_utime ,
145  .mkdir = oC_RamFs_mkdir ,
146  .DirExists= oC_RamFs_DirExists ,
147 };
148 
149 //==========================================================================================================================================
150 //==========================================================================================================================================
151 const oC_Allocator_t Allocator = {
152  .Name = "RamFs"
153 };
154 
155 #undef _________________________________________VARIABLES_SECTION__________________________________________________________________________
156 
157 
163 #define _________________________________________INTERFACE_FUNCTIONS_SECTION________________________________________________________________
164 
165 //==========================================================================================================================================
166 //==========================================================================================================================================
167 oC_ErrorCode_t oC_RamFs_init( oC_RamFs_Context_t * outContext )
168 {
169  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
170 
171  if(
172  oC_AssignErrorCodeIfFalse(&errorCode , isram(outContext) , oC_ErrorCode_OutputAddressNotInRAM)
173  )
174  {
175  oC_RamFs_Context_t context = kmalloc(sizeof(struct Context_t) , &Allocator , AllocationFlags_CanWait1Second );
176 
177  if(isram(context))
178  {
179  context->ObjectControl = oC_CountObjectControl(context,oC_ObjectId_RamFsContext);
180  context->Files = oC_List_New(&Allocator,AllocationFlags_CanWait1Second);
181 
182  if(oC_List_IsCorrect(context->Files))
183  {
184  *outContext = context;
185  errorCode = oC_ErrorCode_None;
186  }
187  else
188  {
189  errorCode = oC_ErrorCode_ListNotCorrect;
190 
191  ifnot(kfree(context,AllocationFlags_CanWaitForever))
192  {
193  oC_SaveError("RamFs - init: Cannot release context memory" , oC_ErrorCode_ReleaseError);
194  }
195  }
196  }
197  else
198  {
199  errorCode = oC_ErrorCode_AllocationError;
200  }
201  }
202 
203  return errorCode;
204 }
205 
206 //==========================================================================================================================================
207 //==========================================================================================================================================
208 oC_ErrorCode_t oC_RamFs_deinit( oC_RamFs_Context_t Context )
209 {
210  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
211 
212  if(
213  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect )
214  )
215  {
216  Context->ObjectControl = 0;
217  errorCode = oC_ErrorCode_None;
218 
219  oC_List_Foreach(Context->Files,file)
220  {
221  UnlockFile(file);
222 
223  ifnot(DeleteFile(Context,file->Path))
224  {
225  oC_SaveError("RamFs:deinit, cannot delete file" , oC_ErrorCode_ReleaseError);
226  }
227  }
228 
229  oC_AssignErrorCodeIfFalse(&errorCode , oC_List_Delete(Context->Files,AllocationFlags_CanWaitForever) , oC_ErrorCode_ReleaseError );
230  oC_AssignErrorCodeIfFalse(&errorCode , kfree(Context,AllocationFlags_CanWaitForever) , oC_ErrorCode_ReleaseError );
231  }
232 
233  return errorCode;
234 }
235 
236 //==========================================================================================================================================
237 //==========================================================================================================================================
238 oC_ErrorCode_t oC_RamFs_fopen( oC_RamFs_Context_t Context , oC_File_t * outFile , const char * Path , oC_FileSystem_ModeFlags_t Mode , oC_FileSystem_FileAttributes_t Attributes )
239 {
240  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
241 
242  if(
243  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
244  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress ) &&
245  oC_AssignErrorCodeIfFalse(&errorCode , isram(outFile) , oC_ErrorCode_OutputAddressNotInRAM)
246  )
247  {
248  oC_File_t file = GetFile(Context,Path);
249 
250  if(
251  oC_AssignErrorCodeIfFalse(&errorCode , (file == NULL) && (Mode & oC_FileSystem_ModeFlags__FailIfNotExists), oC_ErrorCode_NoSuchFile ) &&
252  oC_AssignErrorCodeIfFalse(&errorCode , ((file != NULL) && (Mode & oC_FileSystem_ModeFlags__FailIfExists)) , oC_ErrorCode_FileAlreadyExists ) &&
253  oC_AssignErrorCodeIfFalse(&errorCode , !IsFileCorrect(file) || !IsFileLocked(file) , oC_ErrorCode_FileIsBusy )
254  )
255  {
256  if(file != NULL)
257  {
258  if(!IsFileCorrect(file) && !(Mode & oC_FileSystem_ModeFlags__Create))
259  {
260  errorCode = oC_ErrorCode_ExistingFileNotCorrect;
261  }
262  else if((Mode & oC_FileSystem_ModeFlags_Write) && IsFileReadOnly(file))
263  {
264  errorCode = oC_ErrorCode_FileIsReadOnly;
265  }
266  else if(Mode & oC_FileSystem_ModeFlags__Open)
267  {
268  *outFile = file;
269  errorCode= oC_ErrorCode_None;
270  }
271  else if(Mode & oC_FileSystem_ModeFlags__Create)
272  {
273  if(IsFileReadOnly(file))
274  {
275  errorCode = oC_ErrorCode_FileIsReadOnly;
276  }
277  else
278  {
279  if(DeleteFile(Context,Path))
280  {
281  file = CreateFile(Context,Path,oC_FileSystem_FileType_File,Attributes);
282 
283  if(file)
284  {
285  *outFile = file;
286  errorCode = oC_ErrorCode_None;
287  }
288  else
289  {
290  errorCode = oC_ErrorCode_CannotCreateFile;
291  }
292  }
293  else
294  {
295  errorCode = oC_ErrorCode_CannotDeleteFile;
296  }
297  }
298  }
299  }
300  else
301  {
302  if(Mode & oC_FileSystem_ModeFlags__Create)
303  {
304  if(CheckIfParentDirectoryExists(Context,Path))
305  {
306  file = CreateFile(Context,Path,oC_FileSystem_FileType_File,Attributes);
307 
308  if(file)
309  {
310  *outFile = file;
311  errorCode = oC_ErrorCode_None;
312  }
313  else
314  {
315  errorCode = oC_ErrorCode_CannotCreateFile;
316  }
317  }
318  else
319  {
320  errorCode = oC_ErrorCode_DirectoryNotExists;
321  }
322  }
323  else
324  {
325  errorCode = oC_ErrorCode_ModeNotCorrect;
326  }
327  }
328  }
329  }
330 
331  return errorCode;
332 }
333 
334 //==========================================================================================================================================
335 //==========================================================================================================================================
336 oC_ErrorCode_t oC_RamFs_fclose( oC_RamFs_Context_t Context , oC_File_t File )
337 {
338  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
339 
340  if(
341  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
342  oC_AssignErrorCodeIfFalse(&errorCode , IsFileCorrect(Context) , oC_ErrorCode_FileNotCorrect )
343  )
344  {
345  UnlockFile(File);
346  errorCode = oC_ErrorCode_None;
347  }
348 
349  return errorCode;
350 }
351 
352 //==========================================================================================================================================
353 //==========================================================================================================================================
354 oC_ErrorCode_t oC_RamFs_fread( oC_RamFs_Context_t Context , oC_File_t File , void * outBuffer , uint32_t * Size )
355 {
356  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
357 
358  if(
359  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
360  oC_AssignErrorCodeIfFalse(&errorCode , IsFileCorrect(File) , oC_ErrorCode_FileNotCorrect ) &&
361  oC_AssignErrorCodeIfFalse(&errorCode , isram(outBuffer), oC_ErrorCode_OutputAddressNotInRAM) &&
362  oC_AssignErrorCodeIfFalse(&errorCode , isram(Size), oC_ErrorCode_OutputAddressNotInRAM) &&
363  oC_AssignErrorCodeIfFalse(&errorCode , *Size > 0, oC_ErrorCode_SizeNotCorrect) &&
364  oC_AssignErrorCodeIfFalse(&errorCode , isarrayinram(outBuffer,*Size), oC_ErrorCode_ArraySizeTooBig) &&
365  oC_AssignErrorCodeIfFalse(&errorCode , LockFile(File), oC_ErrorCode_FileIsBusy)
366  )
367  {
368  uint8_t * buffer = outBuffer;
369  uint32_t byteIndex = 0;
370 
371 
372  for(byteIndex = 0 ; isram(&File->Data[File->Offset]) && byteIndex < *Size && File->Offset < File->Size ; byteIndex++ )
373  {
374  buffer[byteIndex] = File->Data[File->Offset++];
375  }
376 
377  if(byteIndex < *Size)
378  {
379  errorCode = oC_ErrorCode_NoAllBytesRead;
380  }
381  else
382  {
383  errorCode = oC_ErrorCode_None;
384  }
385 
386  UnlockFile(File);
387  }
388 
389  return errorCode;
390 }
391 
392 //==========================================================================================================================================
393 //==========================================================================================================================================
394 oC_ErrorCode_t oC_RamFs_fwrite( oC_RamFs_Context_t Context , oC_File_t File , const void * Buffer , uint32_t * Size )
395 {
396  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
397 
398  if(
399  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
400  oC_AssignErrorCodeIfFalse(&errorCode , IsFileCorrect(File) , oC_ErrorCode_FileNotCorrect ) &&
401  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Buffer), oC_ErrorCode_WrongAddress) &&
402  oC_AssignErrorCodeIfFalse(&errorCode , isram(Size), oC_ErrorCode_OutputAddressNotInRAM) &&
403  oC_AssignErrorCodeIfFalse(&errorCode , *Size > 0, oC_ErrorCode_SizeNotCorrect) &&
404  oC_AssignErrorCodeIfFalse(&errorCode , isarraycorrect(Buffer,*Size), oC_ErrorCode_ArraySizeTooBig) &&
405  oC_AssignErrorCodeIfFalse(&errorCode , LockFile(File), oC_ErrorCode_FileIsBusy)
406  )
407  {
408  uint32_t newSize = oC_MAX(*Size + File->Offset , File->Size);
409  uint8_t * newBuffer = kmalloc(newSize ,&Allocator,AllocationFlags_CanWait1Second);
410  const uint8_t * buffer = Buffer;
411  const uint8_t * bufferEnd = &buffer[*Size];
412 
413  if(oC_AssignErrorCodeIfFalse(&errorCode , isram(newBuffer) , oC_ErrorCode_AllocationError))
414  {
415  for(uint32_t newBufferIndex = 0; newBufferIndex < newSize ; newBufferIndex++)
416  {
417  if(newBufferIndex < File->Offset || buffer >= bufferEnd)
418  {
419  newBuffer[newBufferIndex] = File->Data[newBufferIndex];
420  }
421  else
422  {
423  newBuffer[newBufferIndex] = *buffer;
424  buffer++;
425  }
426  }
427 
428  if(oC_AssignErrorCodeIfFalse(&errorCode , File->Data == NULL || kfree(File->Data,AllocationFlags_CanWaitForever) , oC_ErrorCode_ReleaseError))
429  {
430  File->Size = newSize;
431  File->Data = newBuffer;
432  File->Offset += *Size;
433  File->Timestamp = oC_KTime_GetTimestamp();
434 
435  errorCode = oC_ErrorCode_None;
436  }
437  else
438  {
439  ifnot(kfree(newBuffer,AllocationFlags_CanWaitForever))
440  {
441  oC_SaveError("RamFs: fwrite - relasing temp buffer error" , oC_ErrorCode_ReleaseError);
442  }
443  }
444 
445  }
446 
447  UnlockFile(File);
448  }
449 
450  return errorCode;
451 }
452 
453 //==========================================================================================================================================
454 //==========================================================================================================================================
455 oC_ErrorCode_t oC_RamFs_lseek( oC_RamFs_Context_t Context , oC_File_t File , uint32_t Offset )
456 {
457  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
458 
459  if(
460  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
461  oC_AssignErrorCodeIfFalse(&errorCode , IsFileCorrect(File) , oC_ErrorCode_FileNotCorrect ) &&
462  oC_AssignErrorCodeIfFalse(&errorCode , Offset < File->Size , oC_ErrorCode_OffsetTooBig )
463  )
464  {
465  File->Offset = Offset;
466  }
467 
468  return errorCode;
469 }
470 
471 //==========================================================================================================================================
472 //==========================================================================================================================================
473 oC_ErrorCode_t oC_RamFs_ioctl( oC_RamFs_Context_t Context , oC_File_t File , oC_Ioctl_Command_t Command , void * Pointer)
474 {
475  return oC_ErrorCode_NotHandledByFileSystem;
476 }
477 
478 //==========================================================================================================================================
479 //==========================================================================================================================================
480 oC_ErrorCode_t oC_RamFs_sync( oC_RamFs_Context_t Context , oC_File_t File )
481 {
482  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
483 
484  if(
485  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
486  oC_AssignErrorCodeIfFalse(&errorCode , IsFileCorrect(File) , oC_ErrorCode_FileNotCorrect )
487  )
488  {
489  errorCode = oC_ErrorCode_None;
490  }
491 
492  return errorCode;
493 }
494 
495 //==========================================================================================================================================
496 //==========================================================================================================================================
497 oC_ErrorCode_t oC_RamFs_getc( oC_RamFs_Context_t Context , char * outCharacter , oC_File_t File )
498 {
499  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
500 
501  if(
502  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
503  oC_AssignErrorCodeIfFalse(&errorCode , IsFileCorrect(File) , oC_ErrorCode_FileNotCorrect ) &&
504  oC_AssignErrorCodeIfFalse(&errorCode , isram(outCharacter) , oC_ErrorCode_OutputAddressNotInRAM) &&
505  oC_AssignErrorCodeIfFalse(&errorCode , File->Data != NULL , oC_ErrorCode_FileIsEmpty) &&
506  oC_AssignErrorCodeIfFalse(&errorCode , File->Offset < File->Size , oC_ErrorCode_EndOfFile) &&
507  oC_AssignErrorCodeIfFalse(&errorCode , LockFile(File) , oC_ErrorCode_FileIsBusy)
508  )
509  {
510  *outCharacter = File->Data[File->Offset++];
511  errorCode = oC_ErrorCode_None;
512 
513  UnlockFile(File);
514  }
515 
516  return errorCode;
517 }
518 
519 //==========================================================================================================================================
520 //==========================================================================================================================================
521 oC_ErrorCode_t oC_RamFs_putc( oC_RamFs_Context_t Context , char Character , oC_File_t File )
522 {
523  uint32_t size = 1;
524  return oC_RamFs_fwrite(Context,File,&Character,&size);
525 }
526 
527 //==========================================================================================================================================
528 //==========================================================================================================================================
529 bool oC_RamFs_eof( oC_RamFs_Context_t Context , oC_File_t File )
530 {
531  bool eof = true;
532 
533  if(IsContextCorrect(Context) && IsFileCorrect(File))
534  {
535  eof = File->Offset >= File->Size;
536  }
537 
538  return eof;
539 }
540 
541 //==========================================================================================================================================
542 //==========================================================================================================================================
543 uint32_t oC_RamFs_size( oC_RamFs_Context_t Context , oC_File_t File )
544 {
545  uint32_t size = 0;
546 
547  if(IsContextCorrect(Context) && IsFileCorrect(File))
548  {
549  size = File->Size;
550  }
551 
552  return size;
553 }
554 
555 //==========================================================================================================================================
556 //==========================================================================================================================================
557 oC_ErrorCode_t oC_RamFs_opendir( oC_RamFs_Context_t Context , oC_Dir_t * outDir , const char * Path )
558 {
559  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
560 
561  if(
562  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect) &&
563  oC_AssignErrorCodeIfFalse(&errorCode , isram(outDir) , oC_ErrorCode_OutputAddressNotInRAM) &&
564  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress) &&
565  oC_AssignErrorCodeIfFalse(&errorCode , CheckIfPathExists(Context,Path) , oC_ErrorCode_PathNotCorrect)
566  )
567  {
568  oC_Dir_t dir = smartalloc(sizeof(struct Dir_t),AllocationFlags_CanWaitForever);
569 
570  if(dir)
571  {
572  dir->ObjectControl = oC_CountObjectControl(dir,oC_ObjectId_RamFsDir);
573  dir->Path = smartalloc(strlen(Path)+1,AllocationFlags_CanWait1Second | AllocationFlags_ZeroFill);
574 
575  if(dir->Path != NULL)
576  {
577  strcpy(dir->Path,Path);
578  dir->LastFile = NULL;
579  *outDir = dir;
580  errorCode = oC_ErrorCode_None;
581  }
582  else
583  {
584  if(smartfree(dir,sizeof(struct Dir_t),AllocationFlags_CanWaitForever)==false)
585  {
586  oC_SaveError("RamFs-opendir: Cannot release memory previously allocated for DIR: " , oC_ErrorCode_ReleaseError);
587  }
588  errorCode = oC_ErrorCode_AllocationError;
589  }
590 
591  }
592  else
593  {
594  errorCode = oC_ErrorCode_AllocationError;
595  }
596  }
597 
598  return errorCode;
599 }
600 
601 //==========================================================================================================================================
602 //==========================================================================================================================================
603 oC_ErrorCode_t oC_RamFs_closedir( oC_RamFs_Context_t Context , oC_Dir_t Dir )
604 {
605  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
606 
607  if(
608  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect) &&
609  oC_AssignErrorCodeIfFalse(&errorCode , IsDirCorrect(Dir) , oC_ErrorCode_ObjectNotCorrect)
610  )
611  {
612  errorCode = oC_ErrorCode_None;
613 
614  ifnot(smartfree(Dir->Path,strlen(Dir->Path)+1,AllocationFlags_CanWaitForever))
615  {
616  errorCode = oC_ErrorCode_ReleaseError;
617  }
618 
619  ifnot(smartfree(Dir,sizeof(struct Dir_t),AllocationFlags_CanWaitForever))
620  {
621  errorCode = oC_ErrorCode_ReleaseError;
622  }
623  }
624 
625  return errorCode;
626 }
627 
628 //==========================================================================================================================================
629 //==========================================================================================================================================
630 oC_ErrorCode_t oC_RamFs_readdir( oC_RamFs_Context_t Context , oC_Dir_t Dir , oC_FileInfo_t * outFileInfo )
631 {
632  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
633 
634  if(
635  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect) &&
636  oC_AssignErrorCodeIfFalse(&errorCode , IsDirCorrect(Dir) , oC_ErrorCode_ObjectNotCorrect) &&
637  oC_AssignErrorCodeIfFalse(&errorCode , isram(outFileInfo) , oC_ErrorCode_OutputAddressNotInRAM)
638  )
639  {
640  bool lastFileFound = Dir->LastFile == NULL;
641  bool nextFileFound = false;
642  oC_UInt_t pathLength = strlen(Dir->Path);
643  char * tempDir = smartalloc(pathLength+1,AllocationFlags_ZeroFill);
644 
645 
646  oC_List_Foreach(Context->Files,file)
647  {
648  char * path = GetParentDirOfPath(file->Path,tempDir,pathLength+1);
649  if(path != NULL)
650  {
651  if(strcmp(path,Dir->Path) == 0)
652  {
653  if(lastFileFound)
654  {
655  Dir->LastFile = file;
656  nextFileFound = true;
657  break;
658  }
659  else
660  {
661  lastFileFound = file == Dir->LastFile;
662  }
663  }
664  }
665  }
666 
667  if(nextFileFound)
668  {
669  outFileInfo->FileType = Dir->LastFile->FileType;
670  outFileInfo->Size = Dir->LastFile->Size;
671  outFileInfo->Timestamp= Dir->LastFile->Timestamp;
672  outFileInfo->Name = GetLastEntryNameFromPath(Dir->LastFile->Path);
673 
674  errorCode = oC_ErrorCode_None;
675  }
676  else
677  {
678  errorCode = oC_ErrorCode_NoSuchFile;
679  }
680 
681  ifnot(smartfree(tempDir,pathLength+1,AllocationFlags_CanWaitForever))
682  {
683  oC_SaveError("RamFs-readdir: cannot release temp buffer",oC_ErrorCode_ReleaseError);
684  }
685  }
686 
687  return errorCode;
688 }
689 
690 //==========================================================================================================================================
691 //==========================================================================================================================================
692 oC_ErrorCode_t oC_RamFs_stat( oC_RamFs_Context_t Context , const char * Path , oC_FileInfo_t * outFileInfo)
693 {
694  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
695 
696  if(
697  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect) &&
698  oC_AssignErrorCodeIfFalse(&errorCode , isram(outFileInfo) , oC_ErrorCode_OutputAddressNotInRAM) &&
699  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress) &&
700  oC_AssignErrorCodeIfFalse(&errorCode , CheckIfPathExists(Context,Path) , oC_ErrorCode_PathNotCorrect)
701  )
702  {
703  oC_File_t file = GetFile(Context,Path);
704 
705  if(file != NULL)
706  {
707  outFileInfo->FileType = file->FileType;
708  outFileInfo->Name = GetLastEntryNameFromPath(file->Path);
709  outFileInfo->Size = file->Size;
710  outFileInfo->Timestamp= file->Timestamp;
711  errorCode = oC_ErrorCode_None;
712  }
713  else
714  {
715  errorCode = oC_ErrorCode_NoSuchFile;
716  }
717  }
718 
719  return errorCode;
720 }
721 
722 //==========================================================================================================================================
723 //==========================================================================================================================================
724 oC_ErrorCode_t oC_RamFs_unlink( oC_RamFs_Context_t Context , const char * Path)
725 {
726  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
727 
728  if(
729  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect) &&
730  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress) &&
731  oC_AssignErrorCodeIfFalse(&errorCode , CheckIfPathExists(Context,Path) , oC_ErrorCode_PathNotCorrect)
732  )
733  {
734  oC_File_t file = GetFile(Context,Path);
735 
736  if(file)
737  {
738  if(DeleteFile(Context,Path))
739  {
740  errorCode = oC_ErrorCode_None;
741 
742  if(file->FileType == oC_FileSystem_FileType_Directory)
743  {
744  oC_UInt_t pathLength = strlen(Path);
745  oC_List_Foreach(Context->Files,file)
746  {
747  if(strncmp(Path,file->Path,pathLength)==0)
748  {
749  ifnot(DeleteFile(Context,file->Path))
750  {
751  oC_SaveError("RamFs-unlink: Cannot delete one of subfiles",oC_ErrorCode_ReleaseError);
752  }
753  }
754  }
755  }
756  }
757  else
758  {
759  errorCode = oC_ErrorCode_CannotDeleteFile;
760  }
761  }
762  else
763  {
764  errorCode = oC_ErrorCode_NoSuchFile;
765  }
766  }
767 
768  return errorCode;
769 }
770 
771 //==========================================================================================================================================
772 //==========================================================================================================================================
773 oC_ErrorCode_t oC_RamFs_rename( oC_RamFs_Context_t Context , const char * OldName , const char * NewName)
774 {
775  return oC_ErrorCode_NotImplemented;
776 }
777 
778 //==========================================================================================================================================
779 //==========================================================================================================================================
780 oC_ErrorCode_t oC_RamFs_chmod( oC_RamFs_Context_t Context , const char * Path, oC_FileSystem_FileAttributes_t Attributes , oC_FileSystem_FileAttributes_t Mask)
781 {
782  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
783 
784  if(
785  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
786  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress ) &&
787  oC_AssignErrorCodeIfFalse(&errorCode , CheckIfPathExists(Context,Path) , oC_ErrorCode_PathNotCorrect)
788  )
789  {
790  oC_File_t file = GetFile(Context,Path);
791 
792  if(file)
793  {
794  file->Attributes &= ~Mask;
795  file->Attributes |= Attributes;
796 
797  errorCode = oC_ErrorCode_None;
798  }
799  else
800  {
801  errorCode = oC_ErrorCode_NoSuchFile;
802  }
803  }
804 
805  return errorCode;
806 }
807 
808 //==========================================================================================================================================
809 //==========================================================================================================================================
810 oC_ErrorCode_t oC_RamFs_utime( oC_RamFs_Context_t Context , const char * Path , oC_Timestamp_t Timestamp )
811 {
812  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
813 
814  if(
815  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
816  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress ) &&
817  oC_AssignErrorCodeIfFalse(&errorCode , CheckIfPathExists(Context,Path) , oC_ErrorCode_PathNotCorrect)
818  )
819  {
820  oC_File_t file = GetFile(Context,Path);
821 
822  if(file)
823  {
824  file->Timestamp = Timestamp;
825  errorCode = oC_ErrorCode_None;
826  }
827  else
828  {
829  errorCode = oC_ErrorCode_NoSuchFile;
830  }
831  }
832 
833  return errorCode;
834 }
835 
836 //==========================================================================================================================================
837 //==========================================================================================================================================
838 oC_ErrorCode_t oC_RamFs_mkdir( oC_RamFs_Context_t Context , const char * Path)
839 {
840  oC_ErrorCode_t errorCode = oC_ErrorCode_ImplementError;
841 
842  if(
843  oC_AssignErrorCodeIfFalse(&errorCode , IsContextCorrect(Context) , oC_ErrorCode_ContextNotCorrect ) &&
844  oC_AssignErrorCodeIfFalse(&errorCode , isaddresscorrect(Path) , oC_ErrorCode_WrongAddress ) &&
845  oC_AssignErrorCodeIfFalse(&errorCode , !CheckIfPathExists(Context,Path) , oC_ErrorCode_PathAlreadyUsed) &&
846  oC_AssignErrorCodeIfFalse(&errorCode , CheckIfParentDirectoryExists(Context,Path) , oC_ErrorCode_PathNotCorrect)
847  )
848  {
849  if(CreateFile(Context,Path,oC_FileSystem_FileType_Directory,0)!=NULL)
850  {
851  errorCode = oC_ErrorCode_None;
852  }
853  else
854  {
855  errorCode = oC_ErrorCode_CannotCreateFile;
856  }
857  }
858 
859  return errorCode;
860 }
861 
862 //==========================================================================================================================================
863 //==========================================================================================================================================
864 bool oC_RamFs_DirExists( oC_RamFs_Context_t Context , const char * Path)
865 {
866  return IsContextCorrect(Context) && CheckIfPathExists(Context,Path);
867 }
868 
869 #undef _________________________________________INTERFACE_FUNCTIONS_SECTION________________________________________________________________
870 
876 #define _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
877 
878 //==========================================================================================================================================
879 //==========================================================================================================================================
880 static bool IsContextCorrect(oC_RamFs_Context_t Context )
881 {
882  return isram(Context) && oC_CheckObjectControl(Context,oC_ObjectId_RamFsContext,Context->ObjectControl);
883 }
884 
885 //==========================================================================================================================================
886 //==========================================================================================================================================
887 static const char * GetLastEntryNameFromPath( const char * Path )
888 {
889  oC_UInt_t pathLength = strlen(Path);
890  const char * entryName = (pathLength > 1)? &Path[pathLength-2] :&Path[pathLength-1];
891 
892  while(entryName >= Path)
893  {
894  if(*entryName == '/')
895  {
896  entryName++;
897  break;
898  }
899 
900  entryName--;
901  }
902 
903  return entryName;
904 }
905 
906 //==========================================================================================================================================
907 //==========================================================================================================================================
908 static char * GetParentDirOfPath( const char * Path , char * outDir , oC_UInt_t Size )
909 {
910  char * dir = outDir;
911  const char * entryName = GetLastEntryNameFromPath(Path);
912  oC_UInt_t dirLength = strlen(Path)-strlen(entryName);
913 
914  if(dirLength <= (Size-1))
915  {
916  strncpy(dir,Path,dirLength);
917  dir[dirLength] = 0;
918  }
919  else
920  {
921  dir = NULL;
922  }
923 
924  return dir;
925 }
926 
927 //==========================================================================================================================================
928 //==========================================================================================================================================
929 static bool CheckIfParentDirectoryExists( oC_RamFs_Context_t Context , const char * Path )
930 {
931  bool exists = false;
932  const char * lastEntry = GetLastEntryNameFromPath(Path);
933  oC_UInt_t parentPathLength = strlen(Path) - strlen(lastEntry);
934 
935  exists = strncmp("/" , Path , parentPathLength) == 0;
936 
937  oC_List_Foreach(Context->Files,file)
938  {
939  if(
940  file->FileType == oC_FileSystem_FileType_Directory &&
941  strncmp(file->Path , Path , parentPathLength) == 0
942  )
943  {
944  exists = true;
945  break;
946  }
947  }
948 
949 
950  return exists;
951 }
952 
953 //==========================================================================================================================================
954 //==========================================================================================================================================
955 static bool CheckIfPathExists( oC_RamFs_Context_t Context , const char * Path )
956 {
957  bool exists = strcmp(Path,"/") == 0;
958 
959  oC_List_Foreach(Context->Files,file)
960  {
961  if(strcmp(file->Path,Path)==0)
962  {
963  exists = true;
964  break;
965  }
966  }
967 
968  return exists;
969 }
970 
971 //==========================================================================================================================================
972 //==========================================================================================================================================
973 static oC_File_t GetFile( oC_RamFs_Context_t Context , const char * Path )
974 {
975  oC_File_t fileToReturn = NULL;
976 
977  oC_List_Foreach(Context->Files,file)
978  {
979  if(strcmp(file->Path,Path)==0)
980  {
981  fileToReturn = file;
982  break;
983  }
984  }
985 
986  return fileToReturn;
987 }
988 
989 //==========================================================================================================================================
990 //==========================================================================================================================================
991 static oC_File_t CreateFile( oC_RamFs_Context_t Context , const char * Path , oC_FileSystem_FileType_t FileType , oC_FileSystem_FileAttributes_t Attributes )
992 {
993  oC_File_t file = kmalloc(sizeof(struct File_t),&Allocator,AllocationFlags_CanWait1Second);
994 
995  if(file)
996  {
997  file->Path = kmalloc(strlen(Path)+1,&Allocator,AllocationFlags_CanWait1Second | AllocationFlags_ZeroFill);
998 
999  if(file->Path)
1000  {
1001  strcpy(file->Path,Path);
1002  file->Attributes = Attributes;
1003  file->FileType = FileType;
1004  file->Lock = false;
1005  file->Size = 0;
1006  file->Offset = 0;
1007  file->Data = NULL;
1008  file->ObjectControl = oC_CountObjectControl(file,oC_ObjectId_RamFsFile);
1009  file->Timestamp = oC_KTime_GetTimestamp();
1010 
1011  bool pushed = oC_List_PushBack(Context->Files,file,&Allocator);
1012 
1013  ifnot(pushed)
1014  {
1015  file->ObjectControl = 0;
1016 
1017  ifnot(kfree(file->Path,AllocationFlags_CanWaitForever))
1018  {
1019  oC_SaveError("RamFs: Create file error: " , oC_ErrorCode_ReleaseError);
1020  }
1021  ifnot(kfree(file,AllocationFlags_CanWaitForever))
1022  {
1023  oC_SaveError("RamFs: Create file error: " , oC_ErrorCode_ReleaseError);
1024  }
1025  file = NULL;
1026  }
1027  }
1028  else
1029  {
1030  ifnot(kfree(file,AllocationFlags_CanWaitForever))
1031  {
1032  oC_SaveError("RamFs: Create file error: " , oC_ErrorCode_ReleaseError);
1033  }
1034  file = NULL;
1035  }
1036  }
1037 
1038  return file;
1039 }
1040 
1041 //==========================================================================================================================================
1042 //==========================================================================================================================================
1043 static bool DeleteFile( oC_RamFs_Context_t Context , const char * Path )
1044 {
1045  bool deleted = false;
1046  oC_File_t file = GetFile(Context,Path);
1047 
1048  if(file && LockFile(file))
1049  {
1050  bool removedFromList = oC_List_RemoveAll(Context->Files,file);
1051 
1052  ifnot(removedFromList)
1053  {
1054  oC_SaveError("RamFs:DeleteFile" , oC_ErrorCode_CannotRemoveObjectFromList);
1055  }
1056  else
1057  {
1058  file->ObjectControl = 0;
1059 
1060  deleted = true;
1061 
1062  ifnot(file->Data == NULL || kfree(file->Data,AllocationFlags_CanWaitForever))
1063  {
1064  oC_SaveError("RamFs: DeleteFile, cannot delete data buffer" , oC_ErrorCode_ReleaseError);
1065  deleted = false;
1066  }
1067 
1068  ifnot(kfree(file->Path,AllocationFlags_CanWaitForever))
1069  {
1070  oC_SaveError("RamFs: DeleteFile, cannot delete path buffer" , oC_ErrorCode_ReleaseError);
1071  deleted = false;
1072  }
1073 
1074  ifnot(kfree(file,AllocationFlags_CanWaitForever))
1075  {
1076  oC_SaveError("RamFs: DeleteFile, cannot release file memory" , oC_ErrorCode_ReleaseError);
1077  deleted = false;
1078  }
1079 
1080  }
1081  }
1082 
1083  return deleted;
1084 }
1085 
1086 //==========================================================================================================================================
1087 //==========================================================================================================================================
1088 static bool LockFile( oC_File_t File )
1089 {
1090  bool locked = false;
1091  oC_IntMan_EnterCriticalSection();
1092  if(File->Lock==false)
1093  {
1094  File->Lock = true;
1095  locked = true;
1096  }
1097  oC_IntMan_ExitCriticalSection();
1098 
1099  return locked;
1100 }
1101 
1102 //==========================================================================================================================================
1103 //==========================================================================================================================================
1104 static void UnlockFile( oC_File_t File )
1105 {
1106  oC_IntMan_EnterCriticalSection();
1107  File->Lock = false;
1108  oC_IntMan_ExitCriticalSection();
1109 }
1110 
1111 
1112 #undef _________________________________________LOCAL_FUNCTIONS_SECTION____________________________________________________________________
Basic math operations.
const char * Name
Definition: oc_stdlib.h:161
identifier for allocations
Definition: oc_stdlib.h:159
With ifnot definition.
The file with helper macros for managing objects.
uint32_t oC_ObjectControl_t
stores object control value
Definition: oc_object.h:141
The file with list library.
oC_FileSystem_ModeFlags_t
Definition: oc_fs.h:54
The file with interface for interrupt manager.
static oC_ObjectControl_t oC_CountObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId)
counts object control for object
Definition: oc_object.h:168
static bool oC_CheckObjectControl(void *ObjectPointer, oC_ObjectId_t ObjectId, oC_ObjectControl_t ObjectControl)
checks if object control is correct
Definition: oc_object.h:203
specifies write access to the file
Definition: oc_fs.h:57
oC_ObjectControl_t ObjectControl
Definition: oc_eth.c:100
stores ETH context
Definition: oc_eth.c:97
Static array definitions.
The file with source for the RAM file system.
Definition: oc_devfs.c:60
The file with interface of kernel time module.
#define NULL
pointer to a zero
Definition: oc_null.h:37