Rev 210 | Rev 218 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 210 | Rev 211 | ||
---|---|---|---|
Line 59... | Line 59... | ||
59 | #include "timer1.h" |
59 | #include "timer1.h" |
60 | #include "fat16.h" |
60 | #include "fat16.h" |
61 | #include "sdc.h" |
61 | #include "sdc.h" |
62 | #include "uart1.h" |
62 | #include "uart1.h" |
Line 63... | Line -... | ||
63 | - | ||
64 | 63 | ||
65 | //________________________________________________________________________________________________________________________________________ |
64 | //________________________________________________________________________________________________________________________________________ |
66 | // Module name: fat16.c |
65 | // Module name: fat16.c |
67 | // Compiler used: avr-gcc 3.4.5 |
66 | // Compiler used: avr-gcc 3.4.5 |
68 | // Last Modifikation: 16.06.2008 |
67 | // Last Modifikation: 20.03.2010 |
69 | // Version: 2.00 |
68 | // Version: 2.10 |
70 | // Authors: Stephan Busker & Gregor Stobrawa |
69 | // Authors: Stephan Busker & Gregor Stobrawa |
71 | // Description: Source files for FAT16 implementation with read and write-access |
70 | // Description: Source files for FAT16 implementation with read and write-access |
72 | // Copyright (C) 2008 Stephan Busker & Gregor Stobrawa |
71 | // Copyright (C) 2008 Stephan Busker & Gregor Stobrawa |
73 | //........................................................................................................................................ |
72 | //........................................................................................................................................ |
74 | // Functions: extern s16 Fat16_Init(void); |
73 | // Functions: extern s16 Fat16_Init(void); |
- | 74 | // extern s16 Fat16_Deinit(void); |
|
75 | // extern s16 Fat16_Deinit(void); |
75 | // extern s8* FAT16_GetVolumeLabel(void); |
76 | // extern File_t * fopen_(const u8 *filename, const s8 mode); |
76 | // extern File_t * fopen_(const u8 *filename, const s8 mode); |
- | 77 | // extern s16 fclose_(File_t *File); |
|
77 | // extern s16 fclose_(File_t *File); |
78 | // extern u8 fexist_(s8 * const filename); |
78 | // extern s16 fflush_(File_t *File); |
79 | // extern s16 fflush_(File_t *File); |
79 | // extern s16 fseek_(File_t *File, s32 offset, s16 origin); |
80 | // extern s16 fseek_(File_t *File, s32 offset, s16 origin); |
80 | // extern s16 fgetc_(File_t *File); |
81 | // extern s16 fgetc_(File_t *File); |
81 | // extern s16 fputc_(u8 c, File_t *File); |
82 | // extern s16 fputc_(u8 c, File_t *File); |
82 | // extern u32 fread_(void *buffer, u32 size, u32 count, File_t *File); |
83 | // extern u32 fread_(void *buffer, u32 size, u32 count, File_t *File); |
83 | // extern u32 fwrite_(void *buffer, u32 size, u32 count, File_t *File); |
84 | // extern u32 fwrite_(void *buffer, u32 size, u32 count, File_t *File); |
84 | // extern s16 fputs_(const u8 *string, File_t *File); |
85 | // extern s16 fputs_(const u8 *string, File_t *File); |
- | 86 | // extern u8 * fgets_(u8 *string, s16 length, File_t *File); |
|
85 | // extern u8 * fgets_(u8 *string, s16 length, File_t *File); |
87 | // extern u8 feof_(File_t * const file); |
86 | //........................................................................................................................................ |
88 | //........................................................................................................................................ |
87 | // ext. functions: extern SD_Result_t SDC_Init(void;) |
89 | // ext. functions: extern SD_Result_t SDC_Init(void;) |
88 | // extern SD_Result_t SDC_Deinit(void); |
90 | // extern SD_Result_t SDC_Deinit(void); |
89 | // extern SD_Result_t SDC_GetSector (u32,u8 *); |
91 | // extern SD_Result_t SDC_GetSector (u32,u8 *); |
Line 228... | Line 230... | ||
228 | typedef struct |
230 | typedef struct |
229 | { |
231 | { |
230 | s8 Name[8]; // 8 bytes name, padded with spaces. |
232 | s8 Name[8]; // 8 bytes name, padded with spaces. |
231 | u8 Extension[3]; // 3 bytes extension, padded with spaces. |
233 | u8 Extension[3]; // 3 bytes extension, padded with spaces. |
232 | u8 Attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume) |
234 | u8 Attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume) |
- | 235 | u8 Res1; // should be zero |
|
233 | u8 Reserved[10]; // reserved bytes within the directory entry. |
236 | u8 CreationTime10ms; // subsecond resolution of creation time |
- | 237 | u16 CreationTime; // Time of creation h:m:s |
|
- | 238 | u16 CreationDate; // Date of creation Y.M.D |
|
- | 239 | u16 LastAccessDate; // The date where the file was last accessed |
|
- | 240 | u8 Res2[2]; // should be zero |
|
- | 241 | u16 ModTime; // date of last write access |
|
234 | u32 DateTime; // date and time of last write access to the file or directory. |
242 | u16 ModDate; // date of last write access to the file or directory. |
235 | u16 StartCluster; // first cluster of the file or directory. |
243 | u16 StartCluster; // first cluster of the file or directory. |
236 | u32 Size; // size of the file or directory in bytes. |
244 | u32 Size; // size of the file or directory in bytes. |
237 | } __attribute__((packed)) DirEntry_t; |
245 | } __attribute__((packed)) DirEntry_t; |
Line 238... | Line 246... | ||
238 | 246 | ||
Line 282... | Line 290... | ||
282 | #define DIRENTRY_SIZE 32 //bytes |
290 | #define DIRENTRY_SIZE 32 //bytes |
283 | #define DIRENTRIES_PER_SECTOR BYTES_PER_SECTOR/DIRENTRY_SIZE |
291 | #define DIRENTRIES_PER_SECTOR BYTES_PER_SECTOR/DIRENTRY_SIZE |
284 | #define FAT16_BYTES 2 |
292 | #define FAT16_BYTES 2 |
285 | #define FAT16_ENTRIES_PER_SECTOR BYTES_PER_SECTOR/FAT16_BYTES |
293 | #define FAT16_ENTRIES_PER_SECTOR BYTES_PER_SECTOR/FAT16_BYTES |
Line -... | Line 294... | ||
- | 294 | ||
- | 295 | #define SECTOR_UNDEFINED 0x00000000L |
|
- | 296 | #define CLUSTER_UNDEFINED 0x0000 |
|
286 | 297 | ||
287 | #define FSTATE_UNUSED 0 |
298 | #define FSTATE_UNUSED 0 |
Line 288... | Line 299... | ||
288 | #define FSTATE_USED 1 |
299 | #define FSTATE_USED 1 |
289 | 300 | ||
Line 305... | Line 316... | ||
305 | 316 | ||
Line 306... | Line 317... | ||
306 | File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
317 | File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
307 | 318 | ||
308 | 319 | ||
309 | /****************************************************************************************************************************************/ |
320 | /****************************************************************************************************************************************/ |
310 | /* Function: FileDateTime(DateTime_t *); */ |
321 | /* Function: FileDate(DateTime_t *); */ |
311 | /* */ |
322 | /* */ |
312 | /* Description: This function calculates the DOS date time from a pointer to a time structure. */ |
323 | /* Description: This function calculates the DOS date from a pointer to a time structure. */ |
313 | /* */ |
- | |
314 | /* Returnvalue: Returns the DOS date time. */ |
324 | /* */ |
315 | /****************************************************************************************************************************************/ |
325 | /* Returnvalue: Returns the DOS date. */ |
316 | 326 | /****************************************************************************************************************************************/ |
|
- | 327 | u16 FileDate(DateTime_t * pTimeStruct) |
|
317 | u32 FileDateTime(DateTime_t * pTimeStruct) |
328 | { |
Line 318... | Line 329... | ||
318 | { |
329 | u16 date = 0; |
319 | u32 datetime = 0; |
330 | if(pTimeStruct == NULL) return date; |
320 | if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime; |
331 | if(!(pTimeStruct->Valid)) return date; |
321 | - | ||
322 | datetime |= (0x0000007FL & (u32)(pTimeStruct->Year - 1980))<<25; // set year |
- | |
323 | datetime |= (0x0000000FL & (u32)(pTimeStruct->Month))<<21; // set month |
- | |
324 | datetime |= (0x0000001FL & (u32)(pTimeStruct->Day))<<16; |
332 | |
325 | datetime |= (0x0000001FL & (u32)(pTimeStruct->Hour))<<11; |
333 | date |= (0x007F & (u16)(pTimeStruct->Year - 1980))<<9; // set year |
Line -... | Line 334... | ||
- | 334 | date |= (0x000F & (u16)(pTimeStruct->Month))<<5; // set month |
|
- | 335 | date |= (0x001F & (u16)(pTimeStruct->Day)); |
|
- | 336 | return date; |
|
- | 337 | } |
|
- | 338 | ||
- | 339 | /****************************************************************************************************************************************/ |
|
- | 340 | /* Function: FileTime(DateTime_t *); */ |
|
- | 341 | /* */ |
|
- | 342 | /* Description: This function calculates the DOS time from a pointer to a time structure. */ |
|
- | 343 | /* */ |
|
- | 344 | /* Returnvalue: Returns the DOS time. */ |
|
- | 345 | /****************************************************************************************************************************************/ |
|
- | 346 | ||
- | 347 | u16 FileTime(DateTime_t * pTimeStruct) |
|
- | 348 | { |
|
- | 349 | u16 time = 0; |
|
- | 350 | if(pTimeStruct == NULL) return time; |
|
- | 351 | if(!(pTimeStruct->Valid)) return time; |
|
- | 352 | ||
Line 326... | Line 353... | ||
326 | datetime |= (0x0000003FL & (u32)(pTimeStruct->Min))<<5; |
353 | time |= (0x001F & (u16)(pTimeStruct->Hour))<<11; |
327 | datetime |= (0x0000001FL & (u32)(pTimeStruct->Sec/2)); |
354 | time |= (0x003F & (u16)(pTimeStruct->Min))<<5; |
328 | return datetime; |
355 | time |= (0x001F & (u16)(pTimeStruct->Sec/2)); |
329 | } |
356 | return time; |
Line 366... | Line 393... | ||
366 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
393 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
367 | { |
394 | { |
368 | if(&FilePointer[cnt] == file) // filepointer to be freed found? |
395 | if(&FilePointer[cnt] == file) // filepointer to be freed found? |
369 | { |
396 | { |
370 | file->State = FSTATE_UNUSED; |
397 | file->State = FSTATE_UNUSED; |
371 | file->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
398 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; // Sectorpointer to the first sector of the first datacluster of the file. |
372 | file->FirstSectorOfCurrCluster = 0; |
- | |
373 | file->SectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment. |
399 | file->FirstSectorOfCurrCluster = SECTOR_UNDEFINED; // Pointer to the cluster which is edited at the moment. |
374 | file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
400 | file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
375 | file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
401 | file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
376 | file->Mode = 0; // mode of fileoperation (read,write) |
402 | file->Mode = 0; // mode of fileoperation (read,write) |
377 | file->Size = 0; // the size of the opend file in bytes. |
403 | file->Size = 0; // the size of the opend file in bytes. |
378 | file->Position = 0; // pointer to a character within the file 0 < fileposition < filesize |
404 | file->Position = 0; // pointer to a character within the file 0 < fileposition < filesize |
379 | file->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer. |
405 | file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
380 | file->DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
406 | file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
381 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
407 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
382 | file->Attribute = 0; // the attribute of the file opened. |
408 | file->Attribute = 0; // the attribute of the file opened. |
383 | file = NULL; |
409 | file = NULL; |
384 | return(1); |
410 | return(1); |
385 | } |
411 | } |
Line 460... | Line 486... | ||
460 | /* */ |
486 | /* */ |
461 | /* Returnvalue: The sector number with the data area of the given cluster */ |
487 | /* Returnvalue: The sector number with the data area of the given cluster */ |
462 | /****************************************************************************************************************************************/ |
488 | /****************************************************************************************************************************************/ |
463 | u32 Fat16ClusterToSector(u16 cluster) |
489 | u32 Fat16ClusterToSector(u16 cluster) |
464 | { |
490 | { |
465 | if(!Partition.IsValid) return 0; |
491 | if(!Partition.IsValid) return SECTOR_UNDEFINED; |
466 | if (cluster < 2) cluster = 2; // the 0. and 1. cluster in the fat are used for the media descriptor |
492 | if (cluster < 2) |
- | 493 | { |
|
- | 494 | return SECTOR_UNDEFINED; |
|
- | 495 | } |
|
- | 496 | else |
|
- | 497 | { |
|
467 | return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector is represented by the 2nd cluster |
498 | return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector is represented by the 2nd cluster |
- | 499 | } |
|
468 | } |
500 | } |
Line 469... | Line 501... | ||
469 | 501 | ||
470 | /****************************************************************************************************************************************/ |
502 | /****************************************************************************************************************************************/ |
471 | /* Function: SectorToFat16Cluster( u32 sector); */ |
503 | /* Function: SectorToFat16Cluster( u32 sector); */ |
Line 475... | Line 507... | ||
475 | /* */ |
507 | /* */ |
476 | /* Returnvalue: The cluster number representing the data area of the sector. */ |
508 | /* Returnvalue: The cluster number representing the data area of the sector. */ |
477 | /****************************************************************************************************************************************/ |
509 | /****************************************************************************************************************************************/ |
478 | u16 SectorToFat16Cluster(u32 sector) |
510 | u16 SectorToFat16Cluster(u32 sector) |
479 | { |
511 | { |
480 | if(!Partition.IsValid) return 0; |
512 | if(!Partition.IsValid) return CLUSTER_UNDEFINED; |
- | 513 | if((sector == SECTOR_UNDEFINED) || (sector < Partition.FirstDataSector)) return CLUSTER_UNDEFINED; |
|
481 | return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2); |
514 | else return ((u16)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2); |
482 | } |
515 | } |
Line 483... | Line 516... | ||
483 | 516 | ||
484 | 517 | ||
Line 512... | Line 545... | ||
512 | { |
545 | { |
513 | if(FilePointer[cnt].State == FSTATE_USED) |
546 | if(FilePointer[cnt].State == FSTATE_USED) |
514 | { |
547 | { |
515 | returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers |
548 | returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers |
516 | } |
549 | } |
- | 550 | else UnlockFilePointer(&FilePointer[cnt]); |
|
Line 517... | Line 551... | ||
517 | 551 | ||
518 | } |
552 | } |
519 | SDC_Deinit(); // uninitialize interface to sd-card |
553 | SDC_Deinit(); // uninitialize interface to sd-card |
520 | Partition.IsValid = 0; // mark data in partition structure as invalid |
554 | Partition.IsValid = 0; // mark data in partition structure as invalid |
Line 544... | Line 578... | ||
544 | Partition.IsValid = 0; |
578 | Partition.IsValid = 0; |
Line 545... | Line 579... | ||
545 | 579 | ||
546 | // declare the filepointers as unused. |
580 | // declare the filepointers as unused. |
547 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
581 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
548 | { |
582 | { |
549 | FilePointer[cnt].State = FSTATE_UNUSED; |
583 | UnlockFilePointer(&FilePointer[cnt]); |
550 | } |
584 | } |
551 | // set current file pinter to first position in list |
585 | // set current file pinter to first position in list |
Line 552... | Line 586... | ||
552 | file = &FilePointer[0]; |
586 | file = &FilePointer[0]; |
553 | 587 | ||
554 | // try to initialise the sd-card. |
588 | // try to initialize the sd-card. |
555 | if(SD_SUCCESS != SDC_Init()) |
589 | if(SD_SUCCESS != SDC_Init()) |
556 | { |
590 | { |
557 | UART1_PutString("SD-Card could not be initialized."); |
591 | UART1_PutString("SD-Card could not be initialized."); |
Line 647... | Line 681... | ||
647 | u32 i; |
681 | u32 i; |
Line 648... | Line 682... | ||
648 | 682 | ||
Line 649... | Line 683... | ||
649 | if((!Partition.IsValid) || (file == NULL)) return(0); |
683 | if((!Partition.IsValid) || (file == NULL)) return(0); |
- | 684 | ||
650 | 685 | for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache |
|
651 | for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache |
686 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return (0); // nothing to do |
652 | for(i = 0; i < Partition.SectorsPerCluster; i++) |
687 | for(i = 0; i < Partition.SectorsPerCluster; i++) |
653 | { |
688 | { |
654 | file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
689 | file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
Line 668... | Line 703... | ||
668 | /* */ |
703 | /* */ |
669 | /* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached. */ |
704 | /* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached. */ |
670 | /*****************************************************************************************************************************************/ |
705 | /*****************************************************************************************************************************************/ |
671 | u16 GetNextCluster(File_t * file) |
706 | u16 GetNextCluster(File_t * file) |
672 | { |
707 | { |
673 | u16 cluster = 0; |
708 | u16 cluster = CLUSTER_UNDEFINED; |
674 | u32 fat_byte_offset, sector, byte; |
709 | u32 fat_byte_offset, sector, byte; |
675 | Fat16Entry_t * fat; |
710 | Fat16Entry_t * fat; |
Line 676... | Line 711... | ||
676 | 711 | ||
- | 712 | if((!Partition.IsValid) || (file == NULL)) return(cluster); |
|
677 | if((!Partition.IsValid) || (file == NULL)) return(cluster); |
713 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(cluster); |
678 | // if sector is within the data area |
714 | // if sector is within the data area |
679 | if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector)) |
715 | if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector)) |
680 | { |
716 | { |
681 | // determine current file cluster |
717 | // determine current file cluster |
Line 697... | Line 733... | ||
697 | } |
733 | } |
698 | } |
734 | } |
699 | // read the next cluster from cache |
735 | // read the next cluster from cache |
700 | fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
736 | fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
701 | cluster = fat->NextCluster; |
737 | cluster = fat->NextCluster; |
702 | // if last cluster fat entry |
738 | // if no next cluster exist |
703 | if(FAT16_CLUSTER_LAST_MIN <= cluster) |
739 | if(FAT16_CLUSTER_LAST_MIN <= cluster) |
704 | { |
740 | { |
705 | cluster = 0; |
741 | cluster = CLUSTER_UNDEFINED; // next cluster is undefined |
706 | } |
742 | } |
707 | else |
743 | else |
708 | { |
744 | { |
709 | file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster); |
745 | file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster); |
710 | file->SectorOfCurrCluster = 0; |
746 | file->SectorOfCurrCluster = 0; |
Line 725... | Line 761... | ||
725 | u16 FindNextFreeCluster(File_t *file) |
761 | u16 FindNextFreeCluster(File_t *file) |
726 | { |
762 | { |
727 | u32 fat_sector; // current sector within the fat relative to the first sector of the fat. |
763 | u32 fat_sector; // current sector within the fat relative to the first sector of the fat. |
728 | u32 curr_sector; // current sector |
764 | u32 curr_sector; // current sector |
729 | u16 fat_entry; // index to an fatentry within the actual sector (256 fatentries are possible within one sector). |
765 | u16 fat_entry; // index to an fatentry within the actual sector (256 fatentries are possible within one sector). |
730 | u16 free_cluster = 0; // next free cluster number. |
766 | u16 free_cluster = CLUSTER_UNDEFINED; // next free cluster number. |
731 | Fat16Entry_t * fat; |
767 | Fat16Entry_t * fat; |
Line 732... | Line 768... | ||
732 | 768 | ||
Line 733... | Line 769... | ||
733 | if((!Partition.IsValid) || (file == NULL)) return(0); |
769 | if((!Partition.IsValid) || (file == NULL)) return(0); |
Line 770... | Line 806... | ||
770 | /****************************************************************************************************************************************************/ |
806 | /****************************************************************************************************************************************************/ |
771 | /* Function: s16 fseek_(File_t *, s32 *, u8) */ |
807 | /* Function: s16 fseek_(File_t *, s32 *, u8) */ |
772 | /* */ |
808 | /* */ |
773 | /* Description: This function sets the pointer of the stream relative to the position */ |
809 | /* Description: This function sets the pointer of the stream relative to the position */ |
774 | /* specified by origin (SEEK_SET, SEEK_CUR, SEEK_END) */ |
810 | /* specified by origin (SEEK_SET, SEEK_CUR, SEEK_END) */ |
775 | /* Returnvalue: Is 1 if seek was successful */ |
811 | /* Returnvalue: Is 0 if seek was successful */ |
776 | /****************************************************************************************************************************************************/ |
812 | /****************************************************************************************************************************************************/ |
777 | s16 fseek_(File_t *file, s32 offset, s16 origin) |
813 | s16 fseek_(File_t *file, s32 offset, s16 origin) |
778 | { |
814 | { |
779 | s32 fposition = 0; |
815 | s32 fposition = 0; |
780 | s16 retvalue = 1; |
816 | s16 retvalue = 1; |
Line 781... | Line 817... | ||
781 | 817 | ||
782 | if((!Partition.IsValid) || (file == NULL)) return(0); |
818 | if((!Partition.IsValid) || (file == NULL)) return(retvalue); |
783 | switch(origin) |
819 | switch(origin) |
784 | { |
820 | { |
785 | case SEEK_SET: // Fileposition relative to the beginning of the file. |
821 | case SEEK_SET: // Fileposition relative to the beginning of the file. |
786 | fposition = 0; |
822 | fposition = 0; |
Line 801... | Line 837... | ||
801 | // reset file position to start of the file |
837 | // reset file position to start of the file |
802 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
838 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
803 | file->SectorOfCurrCluster = 0; |
839 | file->SectorOfCurrCluster = 0; |
804 | file->ByteOfCurrSector = 0; |
840 | file->ByteOfCurrSector = 0; |
805 | file->Position = 0; |
841 | file->Position = 0; |
806 | - | ||
- | 842 | if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue); |
|
807 | while(file->Position < fposition) // repeat until the current position is less than target |
843 | while(file->Position < fposition) // repeat until the current position is less than target |
808 | { |
844 | { |
809 | file->Position++; // increment file position |
845 | file->Position++; // increment file position |
810 | file->ByteOfCurrSector++; // next byte in current sector |
846 | file->ByteOfCurrSector++; // next byte in current sector |
811 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) |
847 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) |
Line 818... | Line 854... | ||
818 | { |
854 | { |
819 | file->SectorOfCurrCluster = 0; |
855 | file->SectorOfCurrCluster = 0; |
820 | } |
856 | } |
821 | else // the last cluster was allready reached |
857 | else // the last cluster was allready reached |
822 | { |
858 | { |
823 | file->SectorOfCurrCluster--; // jump back to the ast sector in the last cluster |
859 | file->SectorOfCurrCluster--; // jump back to the last sector in the last cluster |
824 | file->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end |
860 | file->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end |
825 | } |
861 | } |
826 | } |
862 | } |
827 | } |
863 | } |
828 | } |
864 | } |
Line 845... | Line 881... | ||
845 | Fat16Entry_t * fat; |
881 | Fat16Entry_t * fat; |
846 | u8 buffer[BYTES_PER_SECTOR]; |
882 | u8 buffer[BYTES_PER_SECTOR]; |
847 | u32 sector_in_buffer = 0; |
883 | u32 sector_in_buffer = 0; |
848 | u8 repeat = 0; |
884 | u8 repeat = 0; |
Line 849... | Line 885... | ||
849 | 885 | ||
- | 886 | if(!Partition.IsValid) return(0); |
|
850 | if(!Partition.IsValid) return 0; |
887 | if(StartCluster == CLUSTER_UNDEFINED) return(0); |
851 | cluster = StartCluster; // init chain trace |
888 | cluster = StartCluster; // init chain trace |
852 | // if start cluster is equal to the last cluster we are done |
889 | // if start cluster is no real cluster |
Line 853... | Line 890... | ||
853 | if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1; |
890 | if(FAT16_CLUSTER_LAST_MIN <= cluster) return 1; |
854 | 891 | ||
855 | // calculate byte offset in the fat for corresponding entry |
892 | // calculate byte offset in the fat for corresponding entry |
856 | fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
893 | fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
Line 867... | Line 904... | ||
867 | if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0; // read sector from sd-card |
904 | if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0; // read sector from sd-card |
868 | } |
905 | } |
869 | // read the next cluster from cache |
906 | // read the next cluster from cache |
870 | fat = (Fat16Entry_t *)(&(buffer[byte])); |
907 | fat = (Fat16Entry_t *)(&(buffer[byte])); |
871 | cluster = fat->NextCluster; |
908 | cluster = fat->NextCluster; |
- | 909 | fat->NextCluster = FAT16_CLUSTER_FREE; // mark current cluster as free |
|
- | 910 | ||
872 | if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1; |
911 | if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) |
- | 912 | { |
|
- | 913 | repeat = 1; |
|
- | 914 | // calculate sector byte and byte offset in the fat for the next cluster |
|
- | 915 | fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
|
- | 916 | // calculate the sector that contains the current cluster within the fat |
|
- | 917 | sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
|
- | 918 | // calculate byte offset of the current cluster within that fat sector |
|
- | 919 | byte = fat_byte_offset % BYTES_PER_SECTOR; |
|
- | 920 | } |
|
873 | else repeat = 0; |
921 | else repeat = 0; |
Line 874... | Line -... | ||
874 | - | ||
875 | fat->NextCluster = FAT16_CLUSTER_FREE; // mark current cluster as free |
- | |
876 | // calculate byte offset in the fat for corresponding entry |
- | |
877 | fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster |
- | |
878 | // calculate the sector that contains the current cluster within the fat |
- | |
879 | sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
- | |
880 | // calculate byte offset of the current cluster within that fat sector |
- | |
881 | byte = fat_byte_offset % BYTES_PER_SECTOR; |
922 | |
882 | // if new sector is not the sector in buffer or the last cluster in the chain was traced |
923 | // if new sector is not the sector in buffer or the last cluster in the chain was traced |
883 | if((sector != sector_in_buffer) || !repeat) |
924 | if((sector != sector_in_buffer) || !repeat) |
884 | { // write sector in buffer |
925 | { // write sector in buffer |
885 | if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) |
926 | if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) |
886 | { |
927 | { |
887 | Fat16_Deinit(); |
928 | Fat16_Deinit(); |
888 | return 0; |
929 | return(0); |
889 | } |
930 | } |
890 | } |
931 | } |
891 | } |
932 | } |
Line 898... | Line 939... | ||
898 | /****************************************************************************************************************************************/ |
939 | /****************************************************************************************************************************************/ |
899 | /* Function: u16 AppendCluster(File *file); */ |
940 | /* Function: u16 AppendCluster(File *file); */ |
900 | /* */ |
941 | /* */ |
901 | /* Description: This function looks in the fat to find the next free cluster and appends it to the file. */ |
942 | /* Description: This function looks in the fat to find the next free cluster and appends it to the file. */ |
902 | /* */ |
943 | /* */ |
903 | /* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended. */ |
944 | /* Returnvalue: The function returns the appened cluster number or CLUSTER_UNDEFINED of no cluster was appended. */ |
904 | /****************************************************************************************************************************************/ |
945 | /****************************************************************************************************************************************/ |
905 | u16 AppendCluster(File_t *file) |
946 | u16 AppendCluster(File_t *file) |
906 | { |
947 | { |
907 | u16 last_cluster, new_cluster = 0; |
948 | u16 last_cluster, new_cluster = CLUSTER_UNDEFINED; |
908 | u32 fat_byte_offset, sector, byte; |
949 | u32 fat_byte_offset, sector, byte; |
909 | Fat16Entry_t * fat; |
950 | Fat16Entry_t * fat; |
Line 910... | Line 951... | ||
910 | 951 | ||
Line 911... | Line 952... | ||
911 | if((!Partition.IsValid) || (file == NULL)) return(new_cluster); |
952 | if((!Partition.IsValid) || (file == NULL)) return(new_cluster); |
912 | 953 | ||
913 | new_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk. |
954 | new_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk. |
914 | if(new_cluster) |
955 | if(new_cluster != CLUSTER_UNDEFINED) |
915 | { // A free cluster was found and can be added to the end of the file. |
956 | { // A free cluster was found and can be added to the end of the file. |
916 | fseek_(file, 0, SEEK_END); // jump to the end of the file |
- | |
917 | last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster); // determine current file cluster |
- | |
918 | fat_byte_offset = ((u32)last_cluster)<<1; |
- | |
919 | sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
- | |
920 | byte = fat_byte_offset % BYTES_PER_SECTOR; |
957 | fseek_(file, 0, SEEK_END); // jump to the end of the file |
921 | 958 | last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster); // determine current file cluster |
|
- | 959 | if(last_cluster != CLUSTER_UNDEFINED) |
|
- | 960 | { |
|
- | 961 | // update FAT entry of last cluster |
|
- | 962 | fat_byte_offset = ((u32)last_cluster)<<1; |
|
- | 963 | sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR); |
|
- | 964 | byte = fat_byte_offset % BYTES_PER_SECTOR; |
|
- | 965 | // read the sector containing the last cluster of the file |
|
922 | if(file->SectorInCache != sector) |
966 | if(file->SectorInCache != sector) |
923 | { |
967 | { |
- | 968 | file->SectorInCache = sector; // update sector stored in buffer |
|
- | 969 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
|
- | 970 | { |
|
- | 971 | Fat16_Deinit(); |
|
- | 972 | return(0); |
|
- | 973 | } |
|
- | 974 | } |
|
- | 975 | fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
|
924 | file->SectorInCache = sector; // update sector stored in buffer |
976 | fat->NextCluster = new_cluster; // append the free cluster to the end of the file in the FAT. |
925 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
977 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // save the modified sector to the FAT. |
926 | { |
978 | { |
927 | Fat16_Deinit(); |
979 | Fat16_Deinit(); |
928 | return(0); |
980 | return(0); |
929 | } |
981 | } |
- | 982 | } |
|
- | 983 | else // last cluster of the file is undefined |
|
- | 984 | { // then the new cluster must be the first one of the file |
|
930 | } |
985 | // and its cluster number must be set in the direntry |
931 | fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
986 | DirEntry_t * dir; |
932 | fat->NextCluster = new_cluster; // append the free cluster to the end of the file in the FAT. |
987 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
933 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // save the modified sector to the FAT. |
988 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
- | 989 | { |
|
- | 990 | Fat16_Deinit(); |
|
- | 991 | return(CLUSTER_UNDEFINED); |
|
- | 992 | } |
|
- | 993 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
|
- | 994 | dir[file->DirectoryIndex].Res1 = 0; |
|
- | 995 | dir[file->DirectoryIndex].Res2[0] = 0; |
|
- | 996 | dir[file->DirectoryIndex].Res2[1] = 0; |
|
- | 997 | dir[file->DirectoryIndex].StartCluster = new_cluster; // update startcluster |
|
- | 998 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime);// set time |
|
- | 999 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime);// and date of modification |
|
- | 1000 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
|
- | 1001 | dir[file->DirectoryIndex].Size = 0; |
|
- | 1002 | // write sector containing the direntry |
|
934 | { |
1003 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
- | 1004 | { |
|
- | 1005 | Fat16_Deinit(); |
|
- | 1006 | return(CLUSTER_UNDEFINED); |
|
- | 1007 | } |
|
- | 1008 | // update file info |
|
- | 1009 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(new_cluster); |
|
935 | Fat16_Deinit(); |
1010 | file->Size = 0; |
- | 1011 | file->Position = 0; |
|
936 | return(0); |
1012 | } |
937 | } |
1013 | // update file pointes |
938 | file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster); |
1014 | file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster); |
939 | file->SectorOfCurrCluster = 0; |
1015 | file->SectorOfCurrCluster = 0; |
940 | file->ByteOfCurrSector = 0; |
1016 | file->ByteOfCurrSector = 0; |
Line 964... | Line 1040... | ||
964 | 1040 | ||
965 | // dir entries can be searched only in filesclusters that have |
1041 | // dir entries can be searched only in filesclusters that have |
966 | // a corresponding dir entry with adir-flag set in its attribute |
1042 | // a corresponding dir entry with adir-flag set in its attribute |
Line 967... | Line 1043... | ||
967 | // or direct within the root directory area |
1043 | // or direct within the root directory area |
968 | 1044 | ||
969 | file->FirstSectorOfFirstCluster = 0; |
1045 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
970 | // no current directory exist therefore assume searching in the root |
1046 | // no current directory exist therefore assume searching in the root |
971 | if(file->DirectorySector == 0) |
1047 | if(file->DirectorySector == SECTOR_UNDEFINED) |
972 | { |
1048 | { |
973 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
1049 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
974 | file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
1050 | file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector; |
Line 983... | Line 1059... | ||
983 | { |
1059 | { |
984 | max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
1060 | max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
985 | } |
1061 | } |
986 | else return (direntry_exist); // bad sector range for directory sector of the file |
1062 | else return (direntry_exist); // bad sector range for directory sector of the file |
987 | // if search area is not defined yet |
1063 | // if search area is not defined yet |
988 | if(file->FirstSectorOfFirstCluster == 0) |
1064 | if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
989 | { |
1065 | { |
990 | // check if the directory entry of current file is existent and has the dir-flag set |
1066 | // check if the directory entry of current file is existent and has the dir-flag set |
991 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1067 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
992 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1068 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
993 | { |
1069 | { |
994 | Fat16_Deinit(); |
1070 | Fat16_Deinit(); |
995 | return(direntry_exist); |
1071 | return(direntry_exist); |
996 | } |
1072 | } |
997 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1073 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
998 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1074 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
999 | { |
1075 | { |
1000 | case SLOT_EMPTY: |
1076 | case SLOT_EMPTY: |
1001 | case SLOT_DELETED: |
1077 | case SLOT_DELETED: |
1002 | // the directrory pointer of this file points to a deleted or not existen directory |
1078 | // the directrory pointer of this file points to a deleted or not existen directory |
1003 | // therefore no file or subdirectory can be created |
1079 | // therefore no file or subdirectory can be created |
Line 1096... | Line 1172... | ||
1096 | // It is not checked here that the dir entry that should be created is already existent! |
1172 | // It is not checked here that the dir entry that should be created is already existent! |
Line 1097... | Line 1173... | ||
1097 | 1173 | ||
1098 | // Dir entries can be created only in file-clusters that have |
1174 | // Dir entries can be created only in file-clusters that have |
Line 1099... | Line 1175... | ||
1099 | // the dir-flag set in its attribute or within the root directory |
1175 | // the dir-flag set in its attribute or within the root directory |
1100 | 1176 | ||
1101 | file->FirstSectorOfFirstCluster = 0; |
1177 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1102 | // no current directory exist therefore assume creating in the root |
1178 | // no current directory exist therefore assume creating in the root |
1103 | if(file->DirectorySector == 0) |
1179 | if(file->DirectorySector == SECTOR_UNDEFINED) |
1104 | { |
1180 | { |
1105 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
1181 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
1106 | dircluster = 0; |
1182 | dircluster = 0; |
Line 1116... | Line 1192... | ||
1116 | { |
1192 | { |
1117 | max_dir_sector = Partition.SectorsPerCluster; |
1193 | max_dir_sector = Partition.SectorsPerCluster; |
1118 | } |
1194 | } |
1119 | else return (retvalue); // bad sector range for directory sector of the file |
1195 | else return (retvalue); // bad sector range for directory sector of the file |
1120 | // if search area is not defined yet |
1196 | // if search area is not defined yet |
1121 | if(file->FirstSectorOfFirstCluster == 0) |
1197 | if(file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED) |
1122 | { |
1198 | { |
1123 | // check if the directory entry of current file is existent and has the dir-flag set |
1199 | // check if the directory entry of current file is existent and has the dir-flag set |
1124 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1200 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1125 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1201 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1126 | { |
1202 | { |
Line 1143... | Line 1219... | ||
1143 | } |
1219 | } |
1144 | dircluster = dir[file->DirectoryIndex].StartCluster; |
1220 | dircluster = dir[file->DirectoryIndex].StartCluster; |
1145 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster); |
1221 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster); |
1146 | } |
1222 | } |
Line 1147... | Line 1223... | ||
1147 | 1223 | ||
1148 | subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used. |
1224 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
- | 1225 | file->SectorOfCurrCluster = 0; |
|
1149 | if(subdircluster) |
1226 | do // loop over all clusters of current directory |
1150 | { |
- | |
1151 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
- | |
1152 | file->SectorOfCurrCluster = 0; |
- | |
1153 | do // loop over all clusters of current directory |
- | |
1154 | { |
1227 | { |
1155 | dir_sector = 0; // reset sector counter within a new cluster |
1228 | dir_sector = 0; // reset sector counter within a new cluster |
1156 | do // loop over all sectors of a cluster or all sectors of the root directory |
1229 | do // loop over all sectors of a cluster or all sectors of the root directory |
1157 | { |
1230 | { |
1158 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1231 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1159 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1232 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1160 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1233 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1161 | { |
1234 | { |
1162 | Fat16_Deinit(); |
1235 | Fat16_Deinit(); |
1163 | return(retvalue); |
1236 | return(retvalue); |
- | 1237 | } |
|
1164 | } |
1238 | |
1165 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1239 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1166 | // search all directory entries of a sector |
1240 | // search all directory entries of a sector |
1167 | for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
1241 | for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
1168 | { // check if current direntry is available |
1242 | { // check if current direntry is available |
1169 | if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED)) |
1243 | if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED)) |
1170 | { // a free direntry was found |
1244 | { // a free direntry was found |
- | 1245 | for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i]; // Set dir name |
|
- | 1246 | dir[dir_entry].Attribute = attrib; |
|
- | 1247 | dir[dir_entry].Res1 = 0; |
|
- | 1248 | dir[dir_entry].CreationTime10ms = (u8)(SystemTime.mSec/10); |
|
- | 1249 | dir[dir_entry].CreationTime = FileTime(&SystemTime); |
|
- | 1250 | dir[dir_entry].CreationDate = FileDate(&SystemTime); |
|
- | 1251 | dir[dir_entry].LastAccessDate = dir[dir_entry].CreationDate; |
|
- | 1252 | dir[dir_entry].Res2[0] = 0; |
|
- | 1253 | dir[dir_entry].Res2[1] = 0; |
|
- | 1254 | dir[dir_entry].ModTime = dir[dir_entry].CreationTime; |
|
- | 1255 | dir[dir_entry].ModDate = dir[dir_entry].CreationDate; |
|
- | 1256 | // if the new direntry is a subdirectory |
|
- | 1257 | if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) |
|
- | 1258 | { // get a free clutser for its content |
|
- | 1259 | subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used. |
|
- | 1260 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
|
- | 1261 | } |
|
- | 1262 | else // normal file |
|
- | 1263 | { // has no data cluster after creation |
|
- | 1264 | subdircluster = CLUSTER_UNDEFINED; |
|
- | 1265 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
|
1171 | for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i]; // Set dir name |
1266 | } |
1172 | dir[dir_entry].Attribute = attrib; // Set the attribute of the new directoryentry. |
1267 | // Set the attribute of the new directoryentry. |
1173 | dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry. |
1268 | dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry. |
- | 1269 | dir[dir_entry].Size = 0; // the new createted file has no content yet. |
|
- | 1270 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
|
- | 1271 | { |
|
- | 1272 | Fat16_Deinit(); |
|
- | 1273 | return(retvalue); |
|
- | 1274 | } |
|
- | 1275 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
|
1174 | dir[dir_entry].DateTime = FileDateTime(&SystemTime); // set date/time |
1276 | file->SectorOfCurrCluster = 0; // reset sector of cureen cluster |
- | 1277 | file->ByteOfCurrSector = 0; // reset the byte location within the current sector |
|
- | 1278 | file->Attribute = attrib; // set file attribute to dir attribute |
|
- | 1279 | file->Size = 0; // new file has no size |
|
- | 1280 | file->DirectorySector = curr_sector; |
|
- | 1281 | file->DirectoryIndex = dir_entry; |
|
- | 1282 | // prepare subdirectory data cluster |
|
- | 1283 | if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) // if a new directory was created then initilize the data area |
|
- | 1284 | { |
|
- | 1285 | ClearCurrCluster(file); // fill cluster with zeros |
|
1175 | dir[dir_entry].Size = 0; // the new createted file has no content yet. |
1286 | file->SectorInCache = file->FirstSectorOfFirstCluster; |
1176 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
1287 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1177 | { |
1288 | { |
1178 | Fat16_Deinit(); |
1289 | Fat16_Deinit(); |
1179 | return(retvalue); |
1290 | return(retvalue); |
- | 1291 | } |
|
1180 | } |
1292 | dir = (DirEntry_t *)file->Cache; |
- | 1293 | // create direntry "." to current dir |
|
1181 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
1294 | dir[0].Name[0] = 0x2E; |
- | 1295 | for(i = 1; i < 11; i++) dir[0].Name[i] = ' '; |
|
1182 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
1296 | dir[0].Attribute = ATTR_SUBDIRECTORY; |
- | 1297 | dir[0].StartCluster = subdircluster; |
|
1183 | file->SectorOfCurrCluster = 0; // reset sector of cureen cluster |
1298 | dir[0].Size = 0; |
- | 1299 | // create direntry ".." to the upper dir |
|
- | 1300 | dir[1].Name[0] = 0x2E; |
|
1184 | file->ByteOfCurrSector = 0; // reset the byte location within the current sector |
1301 | dir[1].Name[1] = 0x2E; |
1185 | file->Attribute = attrib; // set file attribute to dir attribute |
1302 | for(i = 2; i < 11; i++) dir[1].Name[i] = ' '; |
1186 | file->Size = 0; // new file has no size |
1303 | dir[1].Attribute = ATTR_SUBDIRECTORY; |
1187 | file->DirectorySector = curr_sector; |
1304 | dir[1].StartCluster = dircluster; |
1188 | file->DirectoryIndex = dir_entry; |
1305 | dir[1].Size = 0; |
1189 | if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) // if a new directory was created then initilize the data area |
1306 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
1190 | { |
- | |
1191 | ClearCurrCluster(file); // fill cluster with zeros |
- | |
1192 | file->SectorInCache = file->FirstSectorOfFirstCluster; |
- | |
1193 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
- | |
1194 | { |
1307 | { |
1195 | Fat16_Deinit(); |
- | |
1196 | return(retvalue); |
- | |
1197 | } |
- | |
1198 | dir = (DirEntry_t *)file->Cache; |
- | |
1199 | // create direntry "." to current dir |
- | |
1200 | dir[0].Name[0] = 0x2E; |
- | |
1201 | for(i = 1; i < 11; i++) dir[0].Name[i] = ' '; |
- | |
1202 | dir[0].Attribute = ATTR_SUBDIRECTORY; |
- | |
1203 | dir[0].StartCluster = subdircluster; |
- | |
1204 | dir[0].DateTime = 0; |
- | |
1205 | dir[0].Size = 0; |
- | |
1206 | // create direntry ".." to the upper dir |
- | |
1207 | dir[1].Name[0] = 0x2E; |
- | |
1208 | dir[1].Name[1] = 0x2E; |
- | |
1209 | for(i = 2; i < 11; i++) dir[1].Name[i] = ' '; |
- | |
1210 | dir[1].Attribute = ATTR_SUBDIRECTORY; |
- | |
1211 | dir[1].StartCluster = dircluster; |
- | |
1212 | dir[1].DateTime = 0; |
- | |
1213 | dir[1].Size = 0; |
- | |
1214 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
- | |
1215 | { |
- | |
1216 | Fat16_Deinit(); |
1308 | Fat16_Deinit(); |
1217 | return(retvalue); |
1309 | return(retvalue); |
1218 | } |
1310 | } |
1219 | } |
1311 | } |
1220 | retvalue = 1; |
1312 | retvalue = 1; |
1221 | dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop |
- | |
1222 | } |
1313 | dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop |
- | 1314 | } |
|
1223 | } |
1315 | } |
1224 | dir_sector++; // search next sector |
1316 | dir_sector++; // search next sector |
1225 | // stop if we reached the end of the cluster or the end of the root dir |
1317 | // stop if we reached the end of the cluster or the end of the root dir |
1226 | }while((dir_sector < max_dir_sector) && (!retvalue)); |
1318 | }while((dir_sector < max_dir_sector) && (!retvalue)); |
1227 | 1319 | ||
1228 | // if we are seaching in the data area and the file not found in this cluster so take next cluster. |
1320 | // if we are seaching in the data area and the file not found in this cluster so take next cluster. |
1229 | if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)) |
1321 | if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)) |
1230 | { |
1322 | { |
1231 | end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster |
1323 | end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster |
1232 | } |
1324 | } |
1233 | }while((end_of_directory_not_reached) && (!retvalue)); |
1325 | }while((end_of_directory_not_reached) && (!retvalue)); |
1234 | // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found. |
1326 | // Perhaps we are at the end of the last cluster of a directory file and have no free direntry found. |
1235 | // Then we would need to add a cluster to that file and create the new direntry there. |
1327 | // Then we would need to add a cluster to that file and create the new direntry there. |
1236 | // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are |
1328 | // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are |
1237 | // within a subdirectory of root. |
1329 | // within a subdirectory of root. |
1238 | } |
1330 | |
1239 | return(retvalue); // return 1 if file has been created otherwise return 0. |
1331 | return(retvalue); // return 1 if file has been created otherwise return 0. |
Line 1240... | Line 1332... | ||
1240 | } |
1332 | } |
1241 | 1333 | ||
Line 1380... | Line 1472... | ||
1380 | // if no unused file pointer was found return 0 |
1472 | // if no unused file pointer was found return 0 |
1381 | if(file == NULL) return(file); |
1473 | if(file == NULL) return(file); |
Line 1382... | Line 1474... | ||
1382 | 1474 | ||
1383 | // now we have found a free filepointer and claimed it |
1475 | // now we have found a free filepointer and claimed it |
1384 | // so let initiate its property values |
1476 | // so let initiate its property values |
1385 | file->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
1477 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; // Sectorpointer to the first sector of the first datacluster of the file. |
1386 | file->FirstSectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment. |
1478 | file->FirstSectorOfCurrCluster = SECTOR_UNDEFINED; // Pointer to the cluster which is edited at the moment. |
1387 | file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
1479 | file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
1388 | file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
1480 | file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
1389 | file->Mode = mode; // mode of fileoperation (read,write) |
1481 | file->Mode = mode; // mode of fileoperation (read,write) |
1390 | file->Size = 0; // the size of the opened file in bytes. |
1482 | file->Size = 0; // the size of the opened file in bytes. |
1391 | file->Position = 0; // pointer to a byte within the file 0 < fileposition < filesize |
1483 | file->Position = 0; // pointer to a byte within the file 0 < fileposition < filesize |
1392 | file->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer. |
1484 | file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
1393 | file->DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
1485 | file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
1394 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
1486 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
Line 1395... | Line 1487... | ||
1395 | file->Attribute = 0; // the attribute of the file opened. |
1487 | file->Attribute = 0; // the attribute of the file opened. |
1396 | 1488 | ||
Line 1415... | Line 1507... | ||
1415 | { // file is marked as readonly --> do not open this file |
1507 | { // file is marked as readonly --> do not open this file |
1416 | fclose_(file); |
1508 | fclose_(file); |
1417 | file = NULL; |
1509 | file = NULL; |
1418 | } |
1510 | } |
1419 | else |
1511 | else |
1420 | { // file is not marked as read only --> goto start of file |
1512 | { // file is not marked as read only |
- | 1513 | DirEntry_t * dir; |
|
1421 | // free all clusters of that file |
1514 | // free all clusters of that file |
1422 | DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster)); |
1515 | DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster)); |
- | 1516 | // update directory entry of that file |
|
- | 1517 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
|
- | 1518 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
|
- | 1519 | { |
|
- | 1520 | Fat16_Deinit(); |
|
- | 1521 | return(NULL); |
|
- | 1522 | } |
|
1423 | // mark an empy cluster as the last one and store the corresponding sector |
1523 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
- | 1524 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime); // set modification time |
|
- | 1525 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime); // set modification date |
|
- | 1526 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
|
- | 1527 | dir[file->DirectoryIndex].StartCluster = CLUSTER_UNDEFINED; // update startcluster |
|
- | 1528 | dir[file->DirectoryIndex].Size = 0; |
|
- | 1529 | // write sector containing the direntry |
|
- | 1530 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
|
- | 1531 | { |
|
- | 1532 | Fat16_Deinit(); |
|
- | 1533 | return(NULL); |
|
- | 1534 | } |
|
1424 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file)); |
1535 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1425 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
1536 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; |
1426 | file->SectorOfCurrCluster = 0; |
1537 | file->SectorOfCurrCluster = 0; |
1427 | file->ByteOfCurrSector = 0; |
1538 | file->ByteOfCurrSector = 0; |
1428 | file->Size = 0; |
1539 | file->Size = 0; |
1429 | file->Position = 0; |
1540 | file->Position = 0; |
Line 1499... | Line 1610... | ||
1499 | Fat16_Deinit(); |
1610 | Fat16_Deinit(); |
1500 | return(EOF); |
1611 | return(EOF); |
1501 | } |
1612 | } |
Line 1502... | Line 1613... | ||
1502 | 1613 | ||
- | 1614 | dir = (DirEntry_t *)file->Cache; |
|
- | 1615 | // update dile size and modification time & date |
|
- | 1616 | dir[file->DirectoryIndex].ModTime = FileTime(&SystemTime); |
|
- | 1617 | dir[file->DirectoryIndex].ModDate = FileDate(&SystemTime); |
|
1503 | dir = (DirEntry_t *)file->Cache; |
1618 | dir[file->DirectoryIndex].LastAccessDate = dir[file->DirectoryIndex].ModDate; |
1504 | dir[file->DirectoryIndex].Size = file->Size; // update file size |
- | |
1505 | dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime); // update date time |
1619 | dir[file->DirectoryIndex].Size = file->Size; // update file size |
1506 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to sd-card |
1620 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to sd-card |
1507 | { |
1621 | { |
1508 | Fat16_Deinit(); |
1622 | Fat16_Deinit(); |
1509 | return(EOF); |
1623 | return(EOF); |
1510 | } |
1624 | } |
1511 | break; |
1625 | break; |
1512 | case 'r': |
1626 | case 'r': |
- | 1627 | default: |
|
1513 | default: |
1628 | // do nothing! |
1514 | return(EOF); |
1629 | return(EOF); |
Line 1515... | Line 1630... | ||
1515 | break; |
1630 | break; |
1516 | 1631 | ||
Line 1601... | Line 1716... | ||
1601 | s16 fputc_(const s8 c, File_t *file) |
1716 | s16 fputc_(const s8 c, File_t *file) |
1602 | { |
1717 | { |
1603 | u32 curr_sector = 0; |
1718 | u32 curr_sector = 0; |
Line 1604... | Line 1719... | ||
1604 | 1719 | ||
1605 | if((!Partition.IsValid) || (file == NULL)) return(EOF); |
- | |
1606 | - | ||
1607 | // If file position equals to file size, then the end of file has reached. |
- | |
1608 | // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR |
- | |
1609 | // and a new cluster should be appended. |
- | |
1610 | if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) |
- | |
1611 | { |
- | |
1612 | if(!AppendCluster(file)) return(EOF); |
- | |
1613 | } |
- | |
1614 | - | ||
1615 | curr_sector = file->FirstSectorOfCurrCluster; |
1720 | if((!Partition.IsValid) || (file == NULL)) return(EOF); |
1616 | curr_sector += file->SectorOfCurrCluster; |
- | |
1617 | if(file->SectorInCache != curr_sector) |
1721 | switch(file->Mode) |
1618 | { |
- | |
1619 | file->SectorInCache = curr_sector; |
- | |
1620 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) |
- | |
1621 | { |
1722 | { |
1622 | Fat16_Deinit(); |
1723 | case 'w': |
1623 | return(EOF); |
- | |
1624 | } |
- | |
1625 | } |
- | |
1626 | 1724 | case 'a': |
|
1627 | file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
- | |
1628 | if(file->Size == file->Position) file->Size++; // a character has been written to the file so the size is incremented only when the character has been added at the end of the file. |
1725 | // If file position equals to file size, then the end of file has been reached. |
1629 | file->Position++; // the actual positon within the file. |
1726 | // In this case it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR |
1630 | file->ByteOfCurrSector++; // goto next byte in sector |
1727 | // and a new cluster should be appended. |
1631 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
1728 | // If the first sector of first cluster is unvalid, then the file claims no data clusters |
1632 | { // save the sector to the sd-card |
1729 | // and size should be zero, therefore append a new Cluster too. |
1633 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
1730 | if(((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR)) || (file->FirstSectorOfFirstCluster == SECTOR_UNDEFINED)) |
1634 | { |
- | |
1635 | Fat16_Deinit(); |
1731 | { |
1636 | return(EOF); |
1732 | if(CLUSTER_UNDEFINED == AppendCluster(file)) return(EOF); |
- | 1733 | } |
|
1637 | } |
1734 | |
1638 | file->ByteOfCurrSector = 0; // reset byte location |
1735 | curr_sector = file->FirstSectorOfCurrCluster; |
1639 | file->SectorOfCurrCluster++; // next sector |
1736 | curr_sector += file->SectorOfCurrCluster; |
1640 | if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT. |
1737 | if(file->SectorInCache != curr_sector) |
1641 | { |
- | |
1642 | if(!GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster. |
1738 | { |
1643 | { // if current cluster was the last cluster of the file |
1739 | file->SectorInCache = curr_sector; |
1644 | if(!AppendCluster(file)) // append a new and free cluster at the end of the file. |
1740 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) |
1645 | { |
1741 | { |
1646 | file->SectorOfCurrCluster--; // jump back to last sector of last cluster |
- | |
1647 | file->ByteOfCurrSector = BYTES_PER_SECTOR; // set byte location to 1 byte over sector len |
1742 | Fat16_Deinit(); |
1648 | return(EOF); |
1743 | return(EOF); |
1649 | } |
1744 | } |
- | 1745 | } |
|
- | 1746 | ||
- | 1747 | file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
|
- | 1748 | if(file->Size == file->Position) file->Size++; // a character has been written to the file so the size is incremented only when the character has been added at the end of the file. |
|
- | 1749 | file->Position++; // the actual positon within the file. |
|
- | 1750 | file->ByteOfCurrSector++; // goto next byte in sector |
|
- | 1751 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
|
- | 1752 | { // save the sector to the sd-card |
|
- | 1753 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
|
- | 1754 | { |
|
- | 1755 | Fat16_Deinit(); |
|
- | 1756 | return(EOF); |
|
- | 1757 | } |
|
- | 1758 | file->ByteOfCurrSector = 0; // reset byte location |
|
- | 1759 | file->SectorOfCurrCluster++; // next sector |
|
- | 1760 | if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT. |
|
- | 1761 | { |
|
- | 1762 | if(!GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster. |
|
- | 1763 | { // if current cluster was the last cluster of the file |
|
- | 1764 | if(!AppendCluster(file)) // append a new and free cluster at the end of the file. |
|
- | 1765 | { |
|
- | 1766 | file->SectorOfCurrCluster--; // jump back to last sector of last cluster |
|
- | 1767 | file->ByteOfCurrSector = BYTES_PER_SECTOR; // set byte location to 1 byte over sector len |
|
- | 1768 | return(EOF); |
|
- | 1769 | } |
|
1650 | } |
1770 | } |
1651 | else // next cluster |
1771 | else // next cluster |
1652 | { |
1772 | { |
- | 1773 | file->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster. |
|
- | 1774 | } |
|
1653 | file->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster. |
1775 | } |
1654 | } |
1776 | } |
- | 1777 | break; |
|
- | 1778 | case 'r': |
|
- | 1779 | default: |
|
1655 | } |
1780 | return(EOF); |
- | 1781 | break; |
|
1656 | } |
1782 | } // EOF switch(file->Mode) |
1657 | return(0); |
1783 | return(0); |
Line 1658... | Line 1784... | ||
1658 | } |
1784 | } |
Line 1716... | Line 1842... | ||
1716 | u8 *pbuff = 0; // a pointer to the actual bufferposition. |
1842 | u8 *pbuff = 0; // a pointer to the actual bufferposition. |
1717 | u8 success = 1; // no error occured during write operation to the file. |
1843 | u8 success = 1; // no error occured during write operation to the file. |
1718 | s16 c; |
1844 | s16 c; |
Line 1719... | Line 1845... | ||
1719 | 1845 | ||
1720 | if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0); |
- | |
- | 1846 | if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0); |
|
1721 | 1847 | if(file->Mode == 'r') return (0); // opened read only |
|
Line 1722... | Line 1848... | ||
1722 | pbuff = (u8 *) buffer; // cast the void pointer to an u8 * |
1848 | pbuff = (u8 *) buffer; // cast the void pointer to an u8 * |
1723 | 1849 | ||
1724 | while((object_cnt < count) && success) |
1850 | while((object_cnt < count) && success) |
Line 1754... | Line 1880... | ||
1754 | s16 fputs_(s8 * const string, File_t * const file) |
1880 | s16 fputs_(s8 * const string, File_t * const file) |
1755 | { |
1881 | { |
1756 | u8 i=0; |
1882 | u8 i=0; |
1757 | s16 c = 0; |
1883 | s16 c = 0; |
Line 1758... | Line 1884... | ||
1758 | 1884 | ||
1759 | if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0); |
- | |
- | 1885 | if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF); |
|
1760 | 1886 | if(file->Mode == 'r') return(EOF); |
|
1761 | while((string[i] != 0)&& (c != EOF)) |
1887 | while((string[i] != 0)&& (c != EOF)) |
1762 | { |
1888 | { |
1763 | c = fputc_(string[i], file); |
1889 | c = fputc_(string[i], file); |
1764 | i++; |
1890 | i++; |