Rev 378 | Rev 380 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 378 | Rev 379 | ||
---|---|---|---|
Line 52... | Line 52... | ||
52 | // + *) The territory aspect only refers to the place where the Software is used, not its programmed range. |
52 | // + *) The territory aspect only refers to the place where the Software is used, not its programmed range. |
53 | // + #### END OF LICENSING TERMS #### |
53 | // + #### END OF LICENSING TERMS #### |
54 | // + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de. |
54 | // + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de. |
55 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
55 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
56 | #include <stdio.h> |
56 | #include <stdio.h> |
- | 57 | #include <string.h> |
|
57 | #include "91x_lib.h" |
58 | #include "91x_lib.h" |
58 | #include "timer1.h" |
59 | #include "timer1.h" |
59 | #include "fat16.h" |
60 | #include "fat16.h" |
60 | #include "sdc.h" |
61 | #include "sdc.h" |
61 | #include "uart1.h" |
62 | #include "uart1.h" |
62 | #include "logging.h" |
- | |
63 | #include "led.h" |
63 | #include "main.h" |
- | 64 | ||
64 | //________________________________________________________________________________________________________________________________________ |
65 | //________________________________________________________________________________________________________________________________________ |
65 | // Module name: fat16.c |
66 | // Module name: fat16.c |
66 | // Compiler used: avr-gcc 3.4.5 |
67 | // Compiler used: avr-gcc 3.4.5 |
67 | // Last Modifikation: 20.03.2010 |
68 | // Last Modifikation: 20.03.2010 |
68 | // Version: 2.10 |
69 | // Version: 2.10 |
Line 104... | Line 105... | ||
104 | Root Directory Entry Start + # of Reserved + (# of Sectors Per FAT * 2) |
105 | Root Directory Entry Start + # of Reserved + (# of Sectors Per FAT * 2) |
105 | Data Area (Starts with Cluster #2) Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector) |
106 | Data Area (Starts with Cluster #2) Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector) |
106 | */ |
107 | */ |
Line -... | Line 108... | ||
- | 108 | ||
107 | 109 | ||
108 | 110 | ||
Line 109... | Line 111... | ||
109 | /* |
111 | /* |
110 | ________________________________________________________________________________________________________________________________________ |
112 | ________________________________________________________________________________________________________________________________________ |
Line 124... | Line 126... | ||
124 | u16 EndCylSec; // End of Partition - Cylinder/Sector |
126 | u16 EndCylSec; // End of Partition - Cylinder/Sector |
125 | u32 NoSectorsBeforePartition; // Number of Sectors between the MBR and the First Sector in the Partition |
127 | u32 NoSectorsBeforePartition; // Number of Sectors between the MBR and the First Sector in the Partition |
126 | u32 NoSectorsPartition ; // Number of Sectors in the Partition |
128 | u32 NoSectorsPartition ; // Number of Sectors in the Partition |
127 | } __attribute__((packed)) PartitionEntry_t; |
129 | } __attribute__((packed)) PartitionEntry_t; |
Line -... | Line 130... | ||
- | 130 | ||
- | 131 | ||
128 | 132 | ||
129 | /* |
133 | /* |
Line 130... | Line 134... | ||
130 | Coding of Cylinder/Sector words |
134 | Coding of Cylinder/Sector words |
131 | 135 | ||
Line 307... | Line 311... | ||
307 | u16 SectorsPerFat; // how many sectors does a fat16 contain? |
311 | u16 SectorsPerFat; // how many sectors does a fat16 contain? |
308 | u32 FirstFatSector; // sector of the start of the fat |
312 | u32 FirstFatSector; // sector of the start of the fat |
309 | u32 FirstRootDirSector; // sector of the rootdirectory |
313 | u32 FirstRootDirSector; // sector of the rootdirectory |
310 | u32 FirstDataSector; // sector of the first cluster containing data (cluster2). |
314 | u32 FirstDataSector; // sector of the first cluster containing data (cluster2). |
311 | u32 LastDataSector; // the last data sector of the partition |
315 | u32 LastDataSector; // the last data sector of the partition |
312 | u8 VolumeLabel[12]; // the volume label |
316 | u8 VolumeLabel[12]; // the volume label |
- | 317 | u32 CurrentWorkingDirectory;// A pointer to the directory we are actual using |
|
- | 318 | s8 PathToCwd[256]; // a string containing the complete path to the current working directory |
|
313 | } Partition_t; |
319 | } __attribute__((packed)) Partition_t; |
Line 314... | Line 320... | ||
314 | 320 | ||
Line 315... | Line 321... | ||
315 | Partition_t Partition; // Structure holds partition information |
321 | Partition_t Partition; // Structure holds partition information |
Line -... | Line 322... | ||
- | 322 | ||
- | 323 | File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
|
316 | 324 | ||
317 | File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
325 | |
318 | 326 | ||
319 | 327 | ||
320 | /****************************************************************************************************************************************/ |
328 | /****************************************************************************************************************************************/ |
Line 442... | Line 450... | ||
442 | } |
450 | } |
Line 443... | Line 451... | ||
443 | 451 | ||
444 | // clear dirname with spaces |
452 | // clear dirname with spaces |
445 | dirname[11] = 0; // terminate dirname |
453 | dirname[11] = 0; // terminate dirname |
- | 454 | for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' '; |
|
- | 455 | ||
- | 456 | // handle the special dirnames "." and ".." seperately |
|
- | 457 | readpointer = 0; |
|
- | 458 | if(filepath[0] == '/') readpointer++; |
|
- | 459 | // if we are trying to enter directories "." or ".." |
|
- | 460 | if(filepath[readpointer] == '.') |
|
- | 461 | { |
|
- | 462 | // directory '.' |
|
- | 463 | if(filepath[readpointer+1] == 0) |
|
- | 464 | { |
|
- | 465 | dirname[0] = '.'; |
|
- | 466 | return((s8*)&filepath[readpointer]); |
|
- | 467 | } |
|
- | 468 | // directory '..' |
|
- | 469 | if((filepath[readpointer+1] == '.') && (filepath[readpointer+2] == 0)) |
|
- | 470 | { |
|
- | 471 | dirname[0] = '.'; |
|
- | 472 | dirname[1] = '.'; |
|
- | 473 | return((s8*)&filepath[readpointer]); |
|
- | 474 | } |
|
- | 475 | } |
|
446 | for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' '; |
476 | |
447 | writepointer = 0; |
477 | writepointer = 0; |
448 | // start seperating the dirname from the filepath. |
478 | // start seperating the dirname from the filepath. |
449 | readpointer = 0; |
479 | readpointer = 0; |
450 | if(filepath[0] == '/') readpointer = 1; // ignore first '/' |
480 | if(filepath[0] == '/') readpointer = 1; // ignore first '/' |
Line 547... | Line 577... | ||
547 | } |
577 | } |
548 | returnvalue = SDC_Deinit(); // uninitialize interface to sd-card |
578 | returnvalue = SDC_Deinit(); // uninitialize interface to sd-card |
549 | Partition.IsValid = 0; // mark data in partition structure as invalid |
579 | Partition.IsValid = 0; // mark data in partition structure as invalid |
550 | Partition.VolumeLabel[0]='\0'; |
580 | Partition.VolumeLabel[0]='\0'; |
551 | UART1_PutString("ok"); |
581 | UART1_PutString("ok"); |
552 | SD_LoggingError = 100; |
582 | SD_WatchDog = 0; |
553 | return(returnvalue); |
583 | return(returnvalue); |
554 | } |
584 | } |
Line 555... | Line 585... | ||
555 | 585 | ||
556 | /****************************************************************************************************************************************/ |
586 | /****************************************************************************************************************************************/ |
Line 570... | Line 600... | ||
570 | File_t *file; |
600 | File_t *file; |
571 | u8 result = 0; |
601 | u8 result = 0; |
Line 572... | Line 602... | ||
572 | 602 | ||
573 | UART1_PutString("\r\n FAT16 init..."); |
603 | UART1_PutString("\r\n FAT16 init..."); |
574 | Partition.IsValid = 0; |
- | |
575 | 604 | Partition.IsValid = 0; |
|
576 | // declare the filepointers as unused. |
605 | // declare the filepointers as unused. |
577 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
606 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
578 | { |
607 | { |
579 | UnlockFilePointer(&FilePointer[cnt]); |
608 | UnlockFilePointer(&FilePointer[cnt]); |
Line 653... | Line 682... | ||
653 | UART1_PutString("VBR: Partition ist not FAT16 type."); |
682 | UART1_PutString("VBR: Partition ist not FAT16 type."); |
654 | result = 6; |
683 | result = 6; |
655 | goto end; |
684 | goto end; |
656 | } |
685 | } |
657 | Partition.IsValid = 1; // mark data in partition structure as valid |
686 | Partition.IsValid = 1; // mark data in partition structure as valid |
- | 687 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
|
- | 688 | strcpy(Partition.PathToCwd,"/"); |
|
658 | result = 0; |
689 | result = 0; |
659 | end: |
690 | end: |
660 | if(result != 0) Fat16_Deinit(); |
691 | if(result != 0) Fat16_Deinit(); |
661 | else UART1_PutString("ok"); |
692 | else UART1_PutString("ok"); |
662 | return(result); |
693 | return(result); |
Line 684... | Line 715... | ||
684 | { |
715 | { |
685 | file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
716 | file->SectorInCache = file->FirstSectorOfCurrCluster + i; |
686 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
717 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
687 | { |
718 | { |
688 | Fat16_Deinit(); |
719 | Fat16_Deinit(); |
689 | retvalue = 0; |
- | |
690 | return(retvalue); |
720 | return(0); |
691 | } |
721 | } |
692 | } |
722 | } |
693 | return(retvalue); |
723 | return(retvalue); |
694 | } |
724 | } |
Line 724... | Line 754... | ||
724 | { |
754 | { |
725 | file->SectorInCache = sector; // update sector stored in buffer |
755 | file->SectorInCache = sector; // update sector stored in buffer |
726 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
756 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
727 | { |
757 | { |
728 | Fat16_Deinit(); |
758 | Fat16_Deinit(); |
729 | return (cluster); |
759 | return (CLUSTER_UNDEFINED); |
730 | } |
760 | } |
731 | } |
761 | } |
732 | // read the next cluster from cache |
762 | // read the next cluster from cache |
733 | fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
763 | fat = (Fat16Entry_t *)(&(file->Cache[byte])); |
734 | cluster = fat->NextCluster; |
764 | cluster = fat->NextCluster; |
Line 746... | Line 776... | ||
746 | } |
776 | } |
747 | return(cluster); |
777 | return(cluster); |
748 | } |
778 | } |
Line -... | Line 779... | ||
- | 779 | ||
749 | 780 | ||
750 | 781 | ||
751 | /****************************************************************************************************************************************/ |
782 | /****************************************************************************************************************************************/ |
752 | /* Function: FindNextFreeCluster(File_t *); */ |
783 | /* Function: FindNextFreeCluster(File_t *); */ |
753 | /* */ |
784 | /* */ |
Line 772... | Line 803... | ||
772 | curr_sector = Partition.FirstFatSector + fat_sector; // calculate sector to read |
803 | curr_sector = Partition.FirstFatSector + fat_sector; // calculate sector to read |
773 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
804 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
774 | if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector of fat from sd-card. |
805 | if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector of fat from sd-card. |
775 | { |
806 | { |
776 | Fat16_Deinit(); |
807 | Fat16_Deinit(); |
777 | return(free_cluster); |
808 | return(CLUSTER_UNDEFINED); |
778 | } |
809 | } |
Line 779... | Line 810... | ||
779 | 810 | ||
Line 780... | Line 811... | ||
780 | fat = (Fat16Entry_t *)file->Cache; // set fat pointer to file cache |
811 | fat = (Fat16Entry_t *)file->Cache; // set fat pointer to file cache |
Line 785... | Line 816... | ||
785 | { |
816 | { |
786 | fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX; // mark this fat-entry as used |
817 | fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX; // mark this fat-entry as used |
787 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // and save the sector at the sd-card. |
818 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // and save the sector at the sd-card. |
788 | { |
819 | { |
789 | Fat16_Deinit(); |
820 | Fat16_Deinit(); |
790 | return(free_cluster); |
821 | return(CLUSTER_UNDEFINED); |
791 | } |
822 | } |
792 | free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry); |
823 | free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry); |
793 | fat_entry = FAT16_ENTRIES_PER_SECTOR; // terminate the search for a free cluster in this sector. |
824 | fat_entry = FAT16_ENTRIES_PER_SECTOR; // terminate the search for a free cluster in this sector. |
794 | } |
825 | } |
795 | } |
826 | } |
Line 1036... | Line 1067... | ||
1036 | if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist); |
1067 | if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist); |
Line 1037... | Line 1068... | ||
1037 | 1068 | ||
1038 | // dir entries can be searched only in filesclusters that have |
1069 | // dir entries can be searched only in filesclusters that have |
1039 | // a corresponding dir entry with adir-flag set in its attribute |
1070 | // a corresponding dir entry with adir-flag set in its attribute |
1040 | // or direct within the root directory area |
- | |
1041 | 1071 | // or direct within the root directory area |
|
1042 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1072 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1043 | // no current directory exist therefore assume searching in the root |
1073 | // no current directory exist therefore assume searching in the root |
1044 | if(file->DirectorySector == SECTOR_UNDEFINED) |
1074 | if(file->DirectorySector == SECTOR_UNDEFINED) |
1045 | { |
1075 | { |
Line 1063... | Line 1093... | ||
1063 | // check if the directory entry of current file is existent and has the dir-flag set |
1093 | // check if the directory entry of current file is existent and has the dir-flag set |
1064 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1094 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1065 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1095 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1066 | { |
1096 | { |
1067 | Fat16_Deinit(); |
1097 | Fat16_Deinit(); |
1068 | return(direntry_exist); |
1098 | return(0); |
1069 | } |
1099 | } |
1070 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1100 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1071 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1101 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1072 | { |
1102 | { |
1073 | case SLOT_EMPTY: |
1103 | case SLOT_EMPTY: |
Line 1091... | Line 1121... | ||
1091 | file->SectorOfCurrCluster = 0; |
1121 | file->SectorOfCurrCluster = 0; |
1092 | file->ByteOfCurrSector = 0; |
1122 | file->ByteOfCurrSector = 0; |
Line 1093... | Line 1123... | ||
1093 | 1123 | ||
1094 | do // loop over all data clusters of the current directory entry |
1124 | do // loop over all data clusters of the current directory entry |
1095 | { |
1125 | { |
1096 | dir_sector = 0; // reset sector counter within a new cluster |
1126 | dir_sector = 0; |
1097 | do // loop over all sectors of a cluster or all sectors of the root directory |
1127 | do // loop over all sectors of a cluster or all sectors of the root directory |
1098 | { |
1128 | { |
1099 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1129 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1100 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1130 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1101 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector |
1131 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector |
1102 | { |
1132 | { |
1103 | Fat16_Deinit(); |
1133 | Fat16_Deinit(); |
1104 | return(direntry_exist); |
1134 | return(0); |
1105 | } |
1135 | } |
1106 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1136 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1107 | // search all directory entries within that sector |
1137 | // search all directory entries within that sector |
1108 | for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
1138 | for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
Line 1196... | Line 1226... | ||
1196 | // check if the directory entry of current file is existent and has the dir-flag set |
1226 | // check if the directory entry of current file is existent and has the dir-flag set |
1197 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1227 | file->SectorInCache = file->DirectorySector; // update the sector number of file cache. |
1198 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1228 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1199 | { |
1229 | { |
1200 | Fat16_Deinit(); |
1230 | Fat16_Deinit(); |
1201 | return(retvalue); |
1231 | return(0); |
1202 | } |
1232 | } |
1203 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1233 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1204 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1234 | switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1205 | { |
1235 | { |
1206 | case SLOT_EMPTY: |
1236 | case SLOT_EMPTY: |
Line 1238... | Line 1268... | ||
1238 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1268 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1239 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1269 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1240 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1270 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1241 | { |
1271 | { |
1242 | Fat16_Deinit(); |
1272 | Fat16_Deinit(); |
1243 | return(retvalue); |
1273 | return(0); |
1244 | } |
1274 | } |
Line 1245... | Line 1275... | ||
1245 | 1275 | ||
1246 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1276 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1247 | // search all directory entries of a sector |
1277 | // search all directory entries of a sector |
Line 1264... | Line 1294... | ||
1264 | dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry. |
1294 | dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry. |
1265 | dir[dir_entry].Size = 0; // the new createted file has no content yet. |
1295 | dir[dir_entry].Size = 0; // the new createted file has no content yet. |
1266 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
1296 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
1267 | { |
1297 | { |
1268 | Fat16_Deinit(); |
1298 | Fat16_Deinit(); |
1269 | return(retvalue); |
1299 | return(0); |
1270 | } |
1300 | } |
1271 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
1301 | file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
1272 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
1302 | file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
1273 | file->SectorOfCurrCluster = 0; // reset sector of cureen cluster |
1303 | file->SectorOfCurrCluster = 0; // reset sector of cureen cluster |
1274 | file->ByteOfCurrSector = 0; // reset the byte location within the current sector |
1304 | file->ByteOfCurrSector = 0; // reset the byte location within the current sector |
Line 1282... | Line 1312... | ||
1282 | ClearCurrCluster(file); // fill cluster with zeros |
1312 | ClearCurrCluster(file); // fill cluster with zeros |
1283 | file->SectorInCache = file->FirstSectorOfFirstCluster; |
1313 | file->SectorInCache = file->FirstSectorOfFirstCluster; |
1284 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1314 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
1285 | { |
1315 | { |
1286 | Fat16_Deinit(); |
1316 | Fat16_Deinit(); |
1287 | return(retvalue); |
1317 | return(0); |
1288 | } |
1318 | } |
1289 | dir = (DirEntry_t *)file->Cache; |
1319 | dir = (DirEntry_t *)file->Cache; |
1290 | // create direntry "." to current dir |
1320 | // create direntry "." to current dir |
1291 | dir[0].Name[0] = 0x2E; |
1321 | dir[0].Name[0] = 0x2E; |
1292 | for(i = 1; i < 11; i++) dir[0].Name[i] = ' '; |
1322 | for(i = 1; i < 11; i++) dir[0].Name[i] = ' '; |
Line 1301... | Line 1331... | ||
1301 | dir[1].StartCluster = dircluster; |
1331 | dir[1].StartCluster = dircluster; |
1302 | dir[1].Size = 0; |
1332 | dir[1].Size = 0; |
1303 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
1333 | if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
1304 | { |
1334 | { |
1305 | Fat16_Deinit(); |
1335 | Fat16_Deinit(); |
1306 | return(retvalue); |
1336 | return(0); |
1307 | } |
1337 | } |
1308 | } |
1338 | } |
1309 | retvalue = 1; |
1339 | retvalue = 1; |
1310 | dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop |
1340 | dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop |
1311 | } |
1341 | } |
Line 1349... | Line 1379... | ||
1349 | 1379 | ||
1350 | // trace along the filepath |
1380 | // trace along the filepath |
1351 | path = (s8*)filename; // start a the beginning of the filename string |
1381 | path = (s8*)filename; // start a the beginning of the filename string |
1352 | file->DirectorySector = 0; // start at RootDirectory with file search |
1382 | file->DirectorySector = 0; // start at RootDirectory with file search |
- | 1383 | file->DirectoryIndex = 0; |
|
- | 1384 | /* if a path begins with a '/' at index 0 the search starts at the rootdirectory otherwise we will start relative to the cwd */ |
|
- | 1385 | if(path[0] != '/') |
|
- | 1386 | { |
|
- | 1387 | /* is the current working directory the rootdirectory? */ |
|
- | 1388 | if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0; |
|
- | 1389 | /* otherwise we are working in an subdirectory */ |
|
- | 1390 | else file->DirectorySector = Partition.CurrentWorkingDirectory; |
|
1353 | file->DirectoryIndex = 0; |
1391 | } |
1354 | // as long as the file was not found and the remaining path is not empty |
1392 | // as long as the file was not found and the remaining path is not empty |
1355 | while((*path != 0) && !file_exist) |
1393 | while((*path != 0) && !file_exist) |
1356 | { // separate dirname and subpath from filepath string |
1394 | { // separate dirname and subpath from filepath string |
1357 | subpath = SeperateDirName(path, dirname); |
1395 | subpath = SeperateDirName(path, dirname); |
Line 1459... | Line 1497... | ||
1459 | /* Returnvalue: The filepointer to the file or 0 if faild. */ |
1497 | /* Returnvalue: The filepointer to the file or 0 if faild. */ |
1460 | /********************************************************************************************************************************************/ |
1498 | /********************************************************************************************************************************************/ |
1461 | File_t * fopen_(s8 * const filename, const s8 mode) |
1499 | File_t * fopen_(s8 * const filename, const s8 mode) |
1462 | { |
1500 | { |
1463 | File_t *file = 0; |
1501 | File_t *file = 0; |
- | 1502 | s8 *cptr; |
|
Line 1464... | Line 1503... | ||
1464 | 1503 | ||
Line 1465... | Line 1504... | ||
1465 | if((!Partition.IsValid) || (filename == 0)) return(file); |
1504 | if((!Partition.IsValid) || (filename == 0)) return(file); |
1466 | 1505 | ||
Line 1481... | Line 1520... | ||
1481 | file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
1520 | file->SectorInCache = SECTOR_UNDEFINED; // the last sector read, wich is still in the sectorbuffer. |
1482 | file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
1521 | file->DirectorySector = SECTOR_UNDEFINED; // the sectorposition where the directoryentry has been made. |
1483 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
1522 | file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
1484 | file->Attribute = 0; // the attribute of the file opened. |
1523 | file->Attribute = 0; // the attribute of the file opened. |
Line -... | Line 1524... | ||
- | 1524 | ||
- | 1525 | // bring the path into the correct syntax |
|
- | 1526 | cptr = filename; |
|
- | 1527 | // search the whole string |
|
- | 1528 | while(*cptr != 0) |
|
- | 1529 | { |
|
- | 1530 | // replace all '\' by '/' |
|
- | 1531 | if(*cptr == '\\') *cptr = '/'; |
|
- | 1532 | cptr++; |
|
1485 | 1533 | } |
|
1486 | // check if a real file (no directory) to the given filename exist |
1534 | // check if a real file (no directory) to the given filename exist |
1487 | if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file)) |
1535 | if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file)) |
1488 | { // file exist |
1536 | { // file exist |
1489 | switch(mode) // check mode |
1537 | switch(mode) // check mode |
Line 1558... | Line 1606... | ||
1558 | // try to create the file |
1606 | // try to create the file |
1559 | if(!FileCreate(filename, ATTR_ARCHIVE, file)) |
1607 | if(!FileCreate(filename, ATTR_ARCHIVE, file)) |
1560 | { // if it could not be created |
1608 | { // if it could not be created |
1561 | fclose_(file); |
1609 | fclose_(file); |
1562 | file = NULL; |
1610 | file = NULL; |
1563 | } |
1611 | } |
1564 | break; |
1612 | break; |
1565 | case 'r': // else opened for 'r' |
1613 | case 'r': // else opened for 'r' |
1566 | default: // if unsupported mode |
1614 | default: // if unsupported mode |
1567 | fclose_(file); |
1615 | fclose_(file); |
1568 | file = NULL; |
1616 | file = NULL; |
Line 1661... | Line 1709... | ||
1661 | s16 c = EOF; |
1709 | s16 c = EOF; |
1662 | u32 curr_sector; |
1710 | u32 curr_sector; |
Line 1663... | Line 1711... | ||
1663 | 1711 | ||
1664 | if( (!Partition.IsValid) || (file == NULL)) return(c); |
1712 | if( (!Partition.IsValid) || (file == NULL)) return(c); |
1665 | // if the end of the file is not reached, get the next character. |
1713 | // if the end of the file is not reached, get the next character. |
1666 | if((0 < file->Size) && ((file->Position+1) < file->Size) ) |
1714 | if((0 < file->Size) && ((file->Position) < file->Size) ) |
1667 | { |
1715 | { |
1668 | curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read. |
1716 | curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read. |
Line 1669... | Line 1717... | ||
1669 | curr_sector += file->SectorOfCurrCluster; |
1717 | curr_sector += file->SectorOfCurrCluster; |
1670 | 1718 | ||
1671 | if(file->SectorInCache != curr_sector) |
1719 | if(file->SectorInCache != curr_sector) |
1672 | { |
1720 | { |
1673 | file->SectorInCache = curr_sector; |
1721 | file->SectorInCache = curr_sector; |
1674 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache)) |
1722 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache)) |
1675 | { |
1723 | { |
1676 | Fat16_Deinit(); |
1724 | Fat16_Deinit(); |
1677 | return(c); |
1725 | return(EOF); |
1678 | } |
1726 | } |
1679 | } |
1727 | } |
1680 | c = (s16) file->Cache[file->ByteOfCurrSector]; |
1728 | c = (s16) file->Cache[file->ByteOfCurrSector]; |
Line 1738... | Line 1786... | ||
1738 | { |
1786 | { |
1739 | Fat16_Deinit(); |
1787 | Fat16_Deinit(); |
1740 | return(EOF); |
1788 | return(EOF); |
1741 | } |
1789 | } |
1742 | } |
1790 | } |
1743 | - | ||
1744 | 1791 | ||
- | 1792 | file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once |
|
1745 | 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. |
1793 | 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. |
1746 | file->Position++; // the actual positon within the file. |
1794 | file->Position++; // the actual positon within the file. |
1747 | file->ByteOfCurrSector++; // goto next byte in sector |
1795 | file->ByteOfCurrSector++; // goto next byte in sector |
1748 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
1796 | if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet |
1749 | { // save the sector to the sd-card |
1797 | { // save the sector to the sd-card |
Line 2003... | Line 2051... | ||
2003 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
2051 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
2004 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
2052 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
2005 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector |
2053 | if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector |
2006 | { |
2054 | { |
2007 | Fat16_Deinit(); |
2055 | Fat16_Deinit(); |
2008 | return(pVolumeLabel); |
2056 | return(NULL); |
2009 | } |
2057 | } |
2010 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
2058 | dir = (DirEntry_t *)file->Cache; // set pointer to directory |
2011 | // search all directory entries within that sector |
2059 | // search all directory entries within that sector |
2012 | for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
2060 | for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++) |
2013 | { // check for existing dir entry |
2061 | { // check for existing dir entry |
Line 2040... | Line 2088... | ||
2040 | }while((dir_sector < max_dir_sector) && (!pVolumeLabel)); |
2088 | }while((dir_sector < max_dir_sector) && (!pVolumeLabel)); |
Line 2041... | Line 2089... | ||
2041 | 2089 | ||
2042 | UnlockFilePointer(file); |
2090 | UnlockFilePointer(file); |
2043 | return(pVolumeLabel); |
2091 | return(pVolumeLabel); |
- | 2092 | } |
|
- | 2093 | ||
- | 2094 | ||
- | 2095 | ||
- | 2096 | #define ATTR_NONE 0x00 // normal file |
|
- | 2097 | #define ATTR_READONLY 0x01 // file is readonly |
|
- | 2098 | #define ATTR_HIDDEN 0x02 // file is hidden |
|
- | 2099 | #define ATTR_SYSTEM 0x04 // file is a system file |
|
- | 2100 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
|
- | 2101 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
|
- | 2102 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
|
- | 2103 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
|
- | 2104 | ||
- | 2105 | ||
- | 2106 | /********************************************************************************************************************************************/ |
|
- | 2107 | /* Function: u8 FindItem(Find_t); */ |
|
- | 2108 | /* */ |
|
- | 2109 | /* Description: This function looks for the item specified by global structure FindElement in the actual directory */ |
|
- | 2110 | /* */ |
|
- | 2111 | /* */ |
|
- | 2112 | /* Returnvalue: TRUE if an matching element was found */ |
|
- | 2113 | /********************************************************************************************************************************************/ |
|
- | 2114 | ||
- | 2115 | u8 FindItem(Find_t *findelement) |
|
- | 2116 | { |
|
- | 2117 | u16 index = 0; |
|
- | 2118 | u16 max_dir_sector = 0; |
|
- | 2119 | u16 end_of_directory_not_reached = 1; // the directory has been read completely without a result. |
|
- | 2120 | u8 i = 0; |
|
- | 2121 | u8 readpointer = 0; |
|
- | 2122 | u8 writepointer = 0; |
|
- | 2123 | u8 retvalue = 0; |
|
- | 2124 | DirEntry_t *DirectoryEntry; |
|
- | 2125 | File_t file; |
|
- | 2126 | ||
- | 2127 | file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster; |
|
- | 2128 | file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster; |
|
- | 2129 | index = findelement->fp.DirectoryIndex; |
|
- | 2130 | ||
- | 2131 | // within the root directory area we can read sectors sequentially until the end of this area |
|
- | 2132 | if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector)) |
|
- | 2133 | { |
|
- | 2134 | max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
|
- | 2135 | } |
|
- | 2136 | // within the data clusters we can read sectors sequentially only within the cluster |
|
- | 2137 | else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector)) |
|
- | 2138 | { |
|
- | 2139 | max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
|
- | 2140 | } |
|
- | 2141 | ||
- | 2142 | do |
|
- | 2143 | { // search the next 16 rootentries in this sector of the roordirectory. |
|
- | 2144 | if(SD_SUCCESS != SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache)); // Read the Rootdirectory. |
|
- | 2145 | { |
|
- | 2146 | Fat16_Deinit(); |
|
- | 2147 | return(0); |
|
- | 2148 | } |
|
- | 2149 | ||
- | 2150 | DirectoryEntry = (DirEntry_t *)file.Cache; |
|
- | 2151 | ||
- | 2152 | while((!retvalue)&&(index<16)) |
|
- | 2153 | { |
|
- | 2154 | i=0; |
|
- | 2155 | if((u8) DirectoryEntry[index].Name[0] != 0xe5) // ignore deleted items. |
|
- | 2156 | { |
|
- | 2157 | while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?')) |
|
- | 2158 | { |
|
- | 2159 | i++; |
|
- | 2160 | } |
|
- | 2161 | } |
|
- | 2162 | if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11)) |
|
- | 2163 | { |
|
- | 2164 | for(readpointer=0;readpointer<=10;readpointer++) |
|
- | 2165 | { |
|
- | 2166 | if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8)) |
|
- | 2167 | { |
|
- | 2168 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
|
- | 2169 | writepointer++; |
|
- | 2170 | } |
|
- | 2171 | else |
|
- | 2172 | { |
|
- | 2173 | if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE) |
|
- | 2174 | { |
|
- | 2175 | if(readpointer < 8) readpointer=8; |
|
- | 2176 | if(DirectoryEntry[index].Name[readpointer] != ' ') |
|
- | 2177 | { |
|
- | 2178 | findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8. |
|
- | 2179 | writepointer++; |
|
- | 2180 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
|
- | 2181 | writepointer++; |
|
- | 2182 | } |
|
- | 2183 | else break; |
|
- | 2184 | } |
|
- | 2185 | else break; |
|
- | 2186 | } |
|
- | 2187 | /* terminate the namestring with 0 for debugpurposes*/ |
|
- | 2188 | findelement->name[12] = 0; |
|
- | 2189 | } |
|
- | 2190 | findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster; |
|
- | 2191 | findelement->fp.DirectoryIndex = index; |
|
- | 2192 | findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster; |
|
- | 2193 | findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster); |
|
- | 2194 | findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster; |
|
- | 2195 | findelement->fp.Size = DirectoryEntry[index].Size; |
|
- | 2196 | findelement->fp.Attribute = DirectoryEntry[index].Attribute; |
|
- | 2197 | retvalue = 1; |
|
- | 2198 | } |
|
- | 2199 | /* search the next sector */ |
|
- | 2200 | index++; |
|
- | 2201 | } |
|
- | 2202 | /* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */ |
|
- | 2203 | if(!retvalue) // file not found in this sector so take next sector. |
|
- | 2204 | { |
|
- | 2205 | /* in the next sector we start looking for the specified entry beginning at index 0 */ |
|
- | 2206 | index = 0; |
|
- | 2207 | /* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */ |
|
- | 2208 | if(file.SectorOfCurrCluster < max_dir_sector-1) file.SectorOfCurrCluster++; else end_of_directory_not_reached = 0; |
|
- | 2209 | /* if we are looking for an directoryentry outside the rootdirectory and have reached the end of the cluster we have to get the next one */ |
|
- | 2210 | if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) |
|
- | 2211 | { |
|
- | 2212 | end_of_directory_not_reached = GetNextCluster(&file); |
|
- | 2213 | } |
|
- | 2214 | } |
|
- | 2215 | } |
|
- | 2216 | while((end_of_directory_not_reached) && (!retvalue) ); |
|
- | 2217 | ||
- | 2218 | return(retvalue); |
|
- | 2219 | } |
|
- | 2220 | ||
- | 2221 | ||
- | 2222 | ||
- | 2223 | ||
- | 2224 | /********************************************************************************************************************************************/ |
|
- | 2225 | /* Function: findnext_(Find_t *); */ |
|
- | 2226 | /* */ |
|
- | 2227 | /* Description: This function looks for the next item in the specified directory with a matching filename and fileattributes specified */ |
|
- | 2228 | /* by function findfirst() */ |
|
- | 2229 | /* */ |
|
- | 2230 | /* Returnvalue: */ |
|
- | 2231 | /********************************************************************************************************************************************/ |
|
- | 2232 | u8 findnext_(Find_t * findelement) |
|
- | 2233 | { |
|
- | 2234 | u8 itemfound = 0; |
|
- | 2235 | u8 index = 0; |
|
- | 2236 | ||
- | 2237 | findelement->fp.DirectoryIndex++; |
|
- | 2238 | ||
- | 2239 | /* before we start searching an element we clear the complete namestring within the structure FindElement */ |
|
- | 2240 | for(index=0;index<11;index++) findelement->name[index] = 0; |
|
- | 2241 | ||
- | 2242 | if(FindItem(findelement)) |
|
- | 2243 | { |
|
- | 2244 | itemfound = 1; |
|
- | 2245 | } |
|
- | 2246 | ||
- | 2247 | return(itemfound); |
|
- | 2248 | } |
|
- | 2249 | ||
- | 2250 | ||
- | 2251 | ||
- | 2252 | /********************************************************************************************************************************************/ |
|
- | 2253 | /* Function: findfirst_(s8* filename, u8 attribmask, Find_t *); */ |
|
- | 2254 | /* */ |
|
- | 2255 | /* Description: This function looks for the first item in the specified directory with a matching filename and fileattributes */ |
|
- | 2256 | /* The filename of the element found is transformed from 8.3 to a string */ |
|
- | 2257 | /* */ |
|
- | 2258 | /* */ |
|
- | 2259 | /* Returnvalue: (1) if Element was found. (0) if no valid element was found */ |
|
- | 2260 | /********************************************************************************************************************************************/ |
|
- | 2261 | u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement) |
|
- | 2262 | { |
|
- | 2263 | u8 itemfound = 0; |
|
- | 2264 | u8 index = 0; |
|
- | 2265 | ||
- | 2266 | /* initialize the FindElement structure */ |
|
- | 2267 | findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file. |
|
- | 2268 | findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment. |
|
- | 2269 | findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster. |
|
- | 2270 | findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector. |
|
- | 2271 | findelement->fp.Size = 0; // The size of the opend file in bytes. |
|
- | 2272 | findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize |
|
- | 2273 | findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
|
- | 2274 | findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector. |
|
- | 2275 | findelement->attribfilter = 0; |
|
- | 2276 | findelement->attribmask = attribmask; |
|
- | 2277 | findelement->searchstring[0]=0; |
|
- | 2278 | ||
- | 2279 | /* seperate the name of the element to be found from the filepath and bring it to the 8.3*/ |
|
- | 2280 | SeperateDirName(name, findelement->searchstring); |
|
- | 2281 | /* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */ |
|
- | 2282 | for(index=0;index<8;index++) |
|
- | 2283 | { |
|
- | 2284 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
|
- | 2285 | if(findelement->searchstring[index] == '*') |
|
- | 2286 | { |
|
- | 2287 | /* */ |
|
- | 2288 | while(++index <8) findelement->searchstring[index] = '*'; |
|
- | 2289 | } |
|
- | 2290 | } |
|
- | 2291 | for(index=8;index<11;index++) |
|
- | 2292 | { |
|
- | 2293 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
|
- | 2294 | if(findelement->searchstring[index] == '*') |
|
- | 2295 | { |
|
- | 2296 | /* */ |
|
- | 2297 | while(++index <11) findelement->searchstring[index] = '*'; |
|
- | 2298 | } |
|
- | 2299 | } |
|
- | 2300 | ||
- | 2301 | /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */ |
|
- | 2302 | findelement->fp.DirectoryIndex--; |
|
- | 2303 | /* now lets search for the item within the direcory */ |
|
- | 2304 | itemfound = findnext_(findelement); |
|
- | 2305 | ||
- | 2306 | return(itemfound); |
|
- | 2307 | } |
|
- | 2308 | ||
- | 2309 | ||
- | 2310 | /********************************************************************************************************************************************/ |
|
- | 2311 | /* Function: u8 GetDirCount(s8* filepath); */ |
|
- | 2312 | /* */ |
|
- | 2313 | /* Description: This function counts the number of subdirectories the dirpath contains */ |
|
- | 2314 | /* */ |
|
- | 2315 | /* */ |
|
- | 2316 | /* Returnvalue: then number of subdirectories within the specified path */ |
|
- | 2317 | /********************************************************************************************************************************************/ |
|
- | 2318 | u8 GetDirCount(u8 *dirpath) |
|
- | 2319 | { |
|
- | 2320 | u8 i=0; |
|
- | 2321 | u8 cnt=0; |
|
- | 2322 | ||
- | 2323 | while(dirpath[i] != 0 ) |
|
- | 2324 | { |
|
- | 2325 | if(dirpath[i]=='/') |
|
- | 2326 | { |
|
- | 2327 | if(dirpath[i+1]!=0) cnt++; // ignore last'/' |
|
- | 2328 | } |
|
- | 2329 | i++; |
|
- | 2330 | } |
|
- | 2331 | i=0; |
|
- | 2332 | return(cnt); |
|
- | 2333 | } |
|
- | 2334 | ||
- | 2335 | ||
- | 2336 | /********************************************************************************************************************************************/ |
|
- | 2337 | /* Funtion: char *GetSubDirectory (char *dirpath, char *directory) */ |
|
- | 2338 | /* */ |
|
- | 2339 | /* Description: this function returns a pointer to the beginning of the next subdirectory or NULL */ |
|
- | 2340 | /* */ |
|
- | 2341 | /* */ |
|
- | 2342 | /* returnvalue: number of subdirectories in the filepath */ |
|
- | 2343 | /********************************************************************************************************************************************/ |
|
- | 2344 | u8 * GetSubDirectory(u8 *dirpath, u8 *directory) |
|
- | 2345 | { |
|
- | 2346 | u8 *cptr = dirpath; |
|
- | 2347 | u8 *dptr = directory; |
|
- | 2348 | u8 *retvalue = NULL; |
|
- | 2349 | ||
- | 2350 | /* if the first character of the path is an '/' we go to the next character */ |
|
- | 2351 | if(*cptr == '/') cptr++; |
|
- | 2352 | /* search end of path or subdirectory*/ |
|
- | 2353 | while((*cptr != 0) && (*cptr != '/')) |
|
- | 2354 | { |
|
- | 2355 | *dptr = *cptr; |
|
- | 2356 | dptr++; |
|
- | 2357 | cptr++; |
|
- | 2358 | } |
|
- | 2359 | if(*cptr!=0) retvalue = ++cptr; |
|
- | 2360 | *dptr = 0; |
|
- | 2361 | ||
- | 2362 | return(retvalue); |
|
- | 2363 | } |
|
- | 2364 | ||
- | 2365 | /********************************************************************************************************************************************/ |
|
- | 2366 | /* Function: s8 *GetPath(void); */ |
|
- | 2367 | /* */ |
|
- | 2368 | /* Description: This function function returns a pointer to the absolute path of the active partition */ |
|
- | 2369 | /* */ |
|
- | 2370 | /* */ |
|
- | 2371 | /* Returnvalue: */ |
|
- | 2372 | /********************************************************************************************************************************************/ |
|
- | 2373 | ||
- | 2374 | s8 *GetPath(void) |
|
- | 2375 | { |
|
- | 2376 | return(Partition.PathToCwd); |
|
- | 2377 | } |
|
- | 2378 | ||
- | 2379 | /********************************************************************************************************************************************/ |
|
- | 2380 | /* Function: void SetPathToRoot(void); */ |
|
- | 2381 | /* */ |
|
- | 2382 | /* Description: This function sets the path to the rootdirectory */ |
|
- | 2383 | /* */ |
|
- | 2384 | /* */ |
|
- | 2385 | /* Returnvalue: */ |
|
- | 2386 | /********************************************************************************************************************************************/ |
|
- | 2387 | ||
- | 2388 | void SetPathToRoot(void) |
|
- | 2389 | { |
|
- | 2390 | /* lets point to the rootdirectory */ |
|
- | 2391 | strcpy(Partition.PathToCwd, "/"); |
|
- | 2392 | } |
|
- | 2393 | ||
- | 2394 | /********************************************************************************************************************************************/ |
|
- | 2395 | /* Function: void AppendDirToPath(s8* directory); */ |
|
- | 2396 | /* */ |
|
- | 2397 | /* Description: This function function appends the name of an directory to the Path to the CWD */ |
|
- | 2398 | /* */ |
|
- | 2399 | /* */ |
|
- | 2400 | /* Returnvalue: */ |
|
- | 2401 | /********************************************************************************************************************************************/ |
|
- | 2402 | ||
- | 2403 | void AppendDirToPath(s8* directory) |
|
- | 2404 | { |
|
- | 2405 | /* append the name of the directory to the path */ |
|
- | 2406 | strcat(Partition.PathToCwd, directory); |
|
- | 2407 | /* append a '/' after the directoryname */ |
|
- | 2408 | strcat(Partition.PathToCwd, "/"); |
|
- | 2409 | } |
|
- | 2410 | ||
- | 2411 | /********************************************************************************************************************************************/ |
|
- | 2412 | /* Function: RemoveLastDirFromPath(void); */ |
|
- | 2413 | /* */ |
|
- | 2414 | /* Description: This function removes the last directory from the path to the cwd */ |
|
- | 2415 | /* */ |
|
- | 2416 | /* */ |
|
- | 2417 | /* Returnvalue: */ |
|
- | 2418 | /********************************************************************************************************************************************/ |
|
- | 2419 | ||
- | 2420 | void RemoveLastDirFromPath(void) |
|
- | 2421 | { |
|
- | 2422 | /* a pointer to the beginning of the absolute path to the cwd */ |
|
- | 2423 | s8 * cptr = Partition.PathToCwd; |
|
- | 2424 | /* lets find the end of the path to the cwd */ |
|
- | 2425 | while(*cptr != 0 ) cptr++; |
|
- | 2426 | /* if the path is terminated with an '/' */ |
|
- | 2427 | if((*(cptr-1)) == '/') *(cptr-1)=0; |
|
- | 2428 | /* now lets find the beginning of the last directorientry */ |
|
- | 2429 | while((*cptr != '/' ) && cptr > Partition.PathToCwd) cptr--; |
|
- | 2430 | /* is there one subdirectory left within the path? */ |
|
- | 2431 | if(cptr > Partition.PathToCwd) |
|
- | 2432 | { |
|
- | 2433 | /* we delete the direntry by terminating the path with 0 */ |
|
- | 2434 | *cptr = 0; |
|
- | 2435 | } |
|
- | 2436 | /* there is no subdirectory left within the path. Therefore we create the root instead. */ |
|
- | 2437 | else |
|
- | 2438 | { |
|
- | 2439 | *cptr = '/'; |
|
- | 2440 | *(cptr+1) = 0; |
|
- | 2441 | } |
|
- | 2442 | } |
|
- | 2443 | ||
- | 2444 | /********************************************************************************************************************************************/ |
|
- | 2445 | /* Function: chdir_(s8* filepath); */ |
|
- | 2446 | /* */ |
|
- | 2447 | /* Description: This function changed the current working directory to the directory specified by the filepath */ |
|
- | 2448 | /* by function findfirst() */ |
|
- | 2449 | /* */ |
|
- | 2450 | /* Returnvalue: */ |
|
- | 2451 | /********************************************************************************************************************************************/ |
|
- | 2452 | /* |
|
- | 2453 | #define ATTR_NONE 0x00 // normal file |
|
- | 2454 | #define ATTR_READONLY 0x01 // file is readonly |
|
- | 2455 | #define ATTR_HIDDEN 0x02 // file is hidden |
|
- | 2456 | #define ATTR_SYSTEM 0x04 // file is a system file |
|
- | 2457 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
|
- | 2458 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
|
- | 2459 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
|
- | 2460 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
|
- | 2461 | */ |
|
- | 2462 | ||
- | 2463 | u8 chdir_(s8 *path) |
|
- | 2464 | { |
|
- | 2465 | u8 retvalue = 0; // the value returned by this function |
|
- | 2466 | u32 ultemp = 0; // temp. variable |
|
- | 2467 | u8 *directory = path; // pointer to a directoryname within the path |
|
- | 2468 | u8 dircount = 0; // the number of subdirectoryentries within the path |
|
- | 2469 | u8 cache[64]; // a buffer containing the name of the subdirectory we are actually looking for |
|
- | 2470 | Find_t fe; // The findelement needed for function findfirst to find the subdirectoryentry |
|
- | 2471 | s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully |
|
- | 2472 | u32 cwdt = 0; |
|
- | 2473 | s8 *cptr; |
|
- | 2474 | ||
- | 2475 | /* bring the path into the correct syntax */ |
|
- | 2476 | cptr = path; |
|
- | 2477 | /* search the whole string */ |
|
- | 2478 | while(*cptr != 0 ) |
|
- | 2479 | { |
|
- | 2480 | if(*cptr == '\\') *cptr = '/'; |
|
- | 2481 | cptr++; |
|
- | 2482 | } |
|
- | 2483 | /* lets remember the actual path */ |
|
- | 2484 | strcpy(tp, Partition.PathToCwd); |
|
- | 2485 | cwdt = Partition.CurrentWorkingDirectory; |
|
- | 2486 | /* how many subdirectories are there within the path? */ |
|
- | 2487 | dircount = GetDirCount(path); |
|
- | 2488 | /* if the path is absolute we begin at the rootdirectory */ |
|
- | 2489 | if(path[0] == '/') |
|
- | 2490 | { |
|
- | 2491 | strcpy(Partition.PathToCwd, "/"); |
|
- | 2492 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
|
- | 2493 | /* if there is no other pathinformation we only switch to the rootdirectory. So theres nothing left todo.*/ |
|
- | 2494 | if(!dircount) return(1); |
|
- | 2495 | } |
|
- | 2496 | /* now we parse through all the subdirectories within the path */ |
|
- | 2497 | do |
|
- | 2498 | { |
|
- | 2499 | /* until all the subdirectories within the path have been processed */ |
|
- | 2500 | if(dircount) dircount--; |
|
- | 2501 | /* this is the name of the next subdirectory we are looking for */ |
|
- | 2502 | directory = GetSubDirectory(directory, cache); |
|
- | 2503 | /* search for the next subdirectory within the path */ |
|
- | 2504 | if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe)) |
|
- | 2505 | { |
|
- | 2506 | /* we try to change into the directory "..". Now we have to delete the last direntry from the path */ |
|
- | 2507 | if(strcmp(cache,"..") == 0) RemoveLastDirFromPath(); |
|
- | 2508 | /* we try to change into the actual directory so there's nothing todo */ |
|
- | 2509 | else if(cache[0] == '.') return(1); |
|
- | 2510 | /* otherwise we append the name of the directory we are changing in to the path */ |
|
- | 2511 | else AppendDirToPath(cache); |
|
- | 2512 | /* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */ |
|
- | 2513 | ultemp = (u32) fe.fp.FirstSectorOfFirstCluster; |
|
- | 2514 | /* the first 2 entries are reserved for '.' and '..' */ |
|
- | 2515 | ultemp -= 2; |
|
- | 2516 | /* now we have to transform the position within the fat into the corrosponding sectoraddress relative to the beginning of the datasection of the active partition*/ |
|
- | 2517 | ultemp *= Partition.SectorsPerCluster; |
|
- | 2518 | /* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */ |
|
- | 2519 | ultemp += Partition.FirstDataSector; |
|
- | 2520 | /* the cwd now points to the specified directory */ |
|
- | 2521 | Partition.CurrentWorkingDirectory = ultemp; |
|
- | 2522 | /* we found the folder specified by the foldername */ |
|
- | 2523 | retvalue = 1; |
|
- | 2524 | } |
|
- | 2525 | } |
|
- | 2526 | /* do this until all subdirectories have been found or a subdirectory is missing */ |
|
- | 2527 | while(dircount && retvalue ); |
|
- | 2528 | ||
- | 2529 | /* if we could not change to the specified directory we restore the actual path */ |
|
- | 2530 | if(!retvalue) |
|
- | 2531 | { |
|
- | 2532 | Partition.CurrentWorkingDirectory = cwdt; |
|
- | 2533 | strcpy(Partition.PathToCwd, tp); |
|
- | 2534 | } |
|
- | 2535 | return(retvalue); |