Rev 324 | Rev 353 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 324 | Rev 349 | ||
---|---|---|---|
Line 53... | Line 53... | ||
53 | // + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
53 | // + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
54 | // + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
54 | // + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
55 | // + POSSIBILITY OF SUCH DAMAGE. |
55 | // + POSSIBILITY OF SUCH DAMAGE. |
56 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
56 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
57 | #include <stdio.h> |
57 | #include <stdio.h> |
- | 58 | #include <string.h> |
|
58 | #include "91x_lib.h" |
59 | #include "91x_lib.h" |
59 | #include "timer1.h" |
60 | #include "timer1.h" |
60 | #include "fat16.h" |
61 | #include "fat16.h" |
61 | #include "sdc.h" |
62 | #include "sdc.h" |
62 | #include "uart1.h" |
63 | #include "uart1.h" |
Line -... | Line 64... | ||
- | 64 | ||
63 | 65 | void Test(void); |
|
64 | //________________________________________________________________________________________________________________________________________ |
66 | //________________________________________________________________________________________________________________________________________ |
65 | // Module name: fat16.c |
67 | // Module name: fat16.c |
66 | // Compiler used: avr-gcc 3.4.5 |
68 | // Compiler used: avr-gcc 3.4.5 |
67 | // Last Modifikation: 20.03.2010 |
69 | // Last Modifikation: 20.03.2010 |
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 316... | Line 322... | ||
316 | 322 | ||
Line 569... | Line 575... | ||
569 | File_t *file; |
575 | File_t *file; |
570 | u8 result = 0; |
576 | u8 result = 0; |
Line 571... | Line 577... | ||
571 | 577 | ||
572 | UART1_PutString("\r\n FAT16 init..."); |
578 | UART1_PutString("\r\n FAT16 init..."); |
573 | Partition.IsValid = 0; |
- | |
574 | 579 | Partition.IsValid = 0; |
|
575 | // declare the filepointers as unused. |
580 | // declare the filepointers as unused. |
576 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
581 | for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
577 | { |
582 | { |
578 | UnlockFilePointer(&FilePointer[cnt]); |
583 | UnlockFilePointer(&FilePointer[cnt]); |
Line 652... | Line 657... | ||
652 | UART1_PutString("VBR: Partition ist not FAT16 type."); |
657 | UART1_PutString("VBR: Partition ist not FAT16 type."); |
653 | result = 6; |
658 | result = 6; |
654 | goto end; |
659 | goto end; |
655 | } |
660 | } |
656 | Partition.IsValid = 1; // mark data in partition structure as valid |
661 | Partition.IsValid = 1; // mark data in partition structure as valid |
- | 662 | Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
|
- | 663 | strcpy(Partition.PathToCwd,"/"); |
|
657 | result = 0; |
664 | result = 0; |
- | 665 | ||
- | 666 | // Test(); |
|
658 | end: |
667 | end: |
659 | if(result != 0) Fat16_Deinit(); |
668 | if(result != 0) Fat16_Deinit(); |
660 | else UART1_PutString("ok"); |
669 | else UART1_PutString("ok"); |
661 | return(result); |
670 | return(result); |
662 | } |
671 | } |
Line 1035... | Line 1044... | ||
1035 | if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist); |
1044 | if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist); |
Line 1036... | Line 1045... | ||
1036 | 1045 | ||
1037 | // dir entries can be searched only in filesclusters that have |
1046 | // dir entries can be searched only in filesclusters that have |
1038 | // a corresponding dir entry with adir-flag set in its attribute |
1047 | // a corresponding dir entry with adir-flag set in its attribute |
1039 | // or direct within the root directory area |
- | |
1040 | 1048 | // or direct within the root directory area |
|
1041 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1049 | file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
1042 | // no current directory exist therefore assume searching in the root |
1050 | // no current directory exist therefore assume searching in the root |
1043 | if(file->DirectorySector == SECTOR_UNDEFINED) |
1051 | if(file->DirectorySector == SECTOR_UNDEFINED) |
1044 | { |
1052 | { |
Line 1090... | Line 1098... | ||
1090 | file->SectorOfCurrCluster = 0; |
1098 | file->SectorOfCurrCluster = 0; |
1091 | file->ByteOfCurrSector = 0; |
1099 | file->ByteOfCurrSector = 0; |
Line 1092... | Line 1100... | ||
1092 | 1100 | ||
1093 | do // loop over all data clusters of the current directory entry |
1101 | do // loop over all data clusters of the current directory entry |
1094 | { |
1102 | { |
1095 | dir_sector = 0; // reset sector counter within a new cluster |
1103 | dir_sector = 0; |
1096 | do // loop over all sectors of a cluster or all sectors of the root directory |
1104 | do // loop over all sectors of a cluster or all sectors of the root directory |
1097 | { |
1105 | { |
1098 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1106 | curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1099 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
1107 | file->SectorInCache = curr_sector; // upate the sector number of file cache. |
Line 1348... | Line 1356... | ||
1348 | 1356 | ||
1349 | // trace along the filepath |
1357 | // trace along the filepath |
1350 | path = (s8*)filename; // start a the beginning of the filename string |
1358 | path = (s8*)filename; // start a the beginning of the filename string |
1351 | file->DirectorySector = 0; // start at RootDirectory with file search |
1359 | file->DirectorySector = 0; // start at RootDirectory with file search |
- | 1360 | file->DirectoryIndex = 0; |
|
- | 1361 | /* if a path begins with a '/' at index 0 the search starts at the rootdirectory otherwise we will start relative to the cwd */ |
|
- | 1362 | if(path[0] != '/') |
|
- | 1363 | { |
|
- | 1364 | /* is the current working directory the rootdirectory? */ |
|
- | 1365 | if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0; |
|
- | 1366 | /* otherwise we are working in an subdirectory */ |
|
- | 1367 | else file->DirectorySector = Partition.CurrentWorkingDirectory; |
|
1352 | file->DirectoryIndex = 0; |
1368 | } |
1353 | // as long as the file was not found and the remaining path is not empty |
1369 | // as long as the file was not found and the remaining path is not empty |
1354 | while((*path != 0) && !file_exist) |
1370 | while((*path != 0) && !file_exist) |
1355 | { // separate dirname and subpath from filepath string |
1371 | { // separate dirname and subpath from filepath string |
1356 | subpath = SeperateDirName(path, dirname); |
1372 | subpath = SeperateDirName(path, dirname); |
Line 1557... | Line 1573... | ||
1557 | // try to create the file |
1573 | // try to create the file |
1558 | if(!FileCreate(filename, ATTR_ARCHIVE, file)) |
1574 | if(!FileCreate(filename, ATTR_ARCHIVE, file)) |
1559 | { // if it could not be created |
1575 | { // if it could not be created |
1560 | fclose_(file); |
1576 | fclose_(file); |
1561 | file = NULL; |
1577 | file = NULL; |
1562 | } |
1578 | } |
1563 | break; |
1579 | break; |
1564 | case 'r': // else opened for 'r' |
1580 | case 'r': // else opened for 'r' |
1565 | default: // if unsupported mode |
1581 | default: // if unsupported mode |
1566 | fclose_(file); |
1582 | fclose_(file); |
1567 | file = NULL; |
1583 | file = NULL; |
Line 1660... | Line 1676... | ||
1660 | s16 c = EOF; |
1676 | s16 c = EOF; |
1661 | u32 curr_sector; |
1677 | u32 curr_sector; |
Line 1662... | Line 1678... | ||
1662 | 1678 | ||
1663 | if( (!Partition.IsValid) || (file == NULL)) return(c); |
1679 | if( (!Partition.IsValid) || (file == NULL)) return(c); |
1664 | // if the end of the file is not reached, get the next character. |
1680 | // if the end of the file is not reached, get the next character. |
1665 | if((0 < file->Size) && ((file->Position+1) < file->Size) ) |
1681 | if((0 < file->Size) && ((file->Position) < file->Size) ) |
1666 | { |
1682 | { |
1667 | curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read. |
1683 | curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read. |
Line 1668... | Line 1684... | ||
1668 | curr_sector += file->SectorOfCurrCluster; |
1684 | curr_sector += file->SectorOfCurrCluster; |
Line 2039... | Line 2055... | ||
2039 | }while((dir_sector < max_dir_sector) && (!pVolumeLabel)); |
2055 | }while((dir_sector < max_dir_sector) && (!pVolumeLabel)); |
Line 2040... | Line 2056... | ||
2040 | 2056 | ||
2041 | UnlockFilePointer(file); |
2057 | UnlockFilePointer(file); |
2042 | return(pVolumeLabel); |
2058 | return(pVolumeLabel); |
- | 2059 | } |
|
- | 2060 | ||
- | 2061 | ||
- | 2062 | ||
- | 2063 | #define ATTR_NONE 0x00 // normal file |
|
- | 2064 | #define ATTR_READONLY 0x01 // file is readonly |
|
- | 2065 | #define ATTR_HIDDEN 0x02 // file is hidden |
|
- | 2066 | #define ATTR_SYSTEM 0x04 // file is a system file |
|
- | 2067 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
|
- | 2068 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
|
- | 2069 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
|
- | 2070 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
|
- | 2071 | ||
- | 2072 | ||
- | 2073 | /********************************************************************************************************************************************/ |
|
- | 2074 | /* Function: u8 FindItem(Find_t); */ |
|
- | 2075 | /* */ |
|
- | 2076 | /* Description: This function looks for the item specified by global structure FindElement in the actual directory */ |
|
- | 2077 | /* */ |
|
- | 2078 | /* */ |
|
- | 2079 | /* Returnvalue: TRUE if an matching element was found */ |
|
- | 2080 | /********************************************************************************************************************************************/ |
|
- | 2081 | ||
- | 2082 | u8 FindItem(Find_t *findelement) |
|
- | 2083 | { |
|
- | 2084 | u16 index = 0; |
|
- | 2085 | u16 end_of_directory_not_reached = 1; // the directory has been read completely without a result. |
|
- | 2086 | u8 i = 0; |
|
- | 2087 | u8 readpointer = 0; |
|
- | 2088 | u8 writepointer = 0; |
|
- | 2089 | u8 retvalue = 0; |
|
- | 2090 | DirEntry_t *DirectoryEntry; |
|
- | 2091 | File_t file; |
|
- | 2092 | ||
- | 2093 | file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster; |
|
- | 2094 | file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster; |
|
- | 2095 | index = findelement->fp.DirectoryIndex; |
|
- | 2096 | ||
- | 2097 | ||
- | 2098 | do |
|
- | 2099 | { // search the next 16 rootentries in this sector of the roordirectory. |
|
- | 2100 | SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache); // Read the Rootdirectory. |
|
- | 2101 | DirectoryEntry = (DirEntry_t *)file.Cache; |
|
- | 2102 | ||
- | 2103 | while((!retvalue)&&(index<16)) |
|
- | 2104 | { |
|
- | 2105 | i=0; |
|
- | 2106 | if((u8) DirectoryEntry[index].Name[0] != 0xe5) // ignore deleted items. |
|
- | 2107 | { |
|
- | 2108 | while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?')) |
|
- | 2109 | { |
|
- | 2110 | i++; |
|
- | 2111 | } |
|
- | 2112 | } |
|
- | 2113 | if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11)) |
|
- | 2114 | { |
|
- | 2115 | for(readpointer=0;readpointer<=10;readpointer++) |
|
- | 2116 | { |
|
- | 2117 | if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8)) |
|
- | 2118 | { |
|
- | 2119 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
|
- | 2120 | writepointer++; |
|
- | 2121 | } |
|
- | 2122 | else |
|
- | 2123 | { |
|
- | 2124 | if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE) |
|
- | 2125 | { |
|
- | 2126 | if(readpointer < 8) readpointer=8; |
|
- | 2127 | if(DirectoryEntry[index].Name[readpointer] != ' ') |
|
- | 2128 | { |
|
- | 2129 | findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8. |
|
- | 2130 | writepointer++; |
|
- | 2131 | findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
|
- | 2132 | writepointer++; |
|
- | 2133 | } |
|
- | 2134 | else break; |
|
- | 2135 | } |
|
- | 2136 | else break; |
|
- | 2137 | } |
|
- | 2138 | /* terminate the namestring with 0 for debugpurposes*/ |
|
- | 2139 | findelement->name[12] = 0; |
|
- | 2140 | } |
|
- | 2141 | findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster; |
|
- | 2142 | findelement->fp.DirectoryIndex = index; |
|
- | 2143 | findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster; |
|
- | 2144 | findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster); |
|
- | 2145 | findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster; |
|
- | 2146 | findelement->fp.Size = DirectoryEntry[index].Size; |
|
- | 2147 | findelement->fp.Attribute = DirectoryEntry[index].Attribute; |
|
- | 2148 | retvalue = 1; |
|
- | 2149 | } |
|
- | 2150 | index++; |
|
- | 2151 | } |
|
- | 2152 | if(!retvalue) // file not found in this sector so take next sector. |
|
- | 2153 | { |
|
- | 2154 | file.SectorOfCurrCluster++; |
|
- | 2155 | if(file.SectorOfCurrCluster >= Partition.SectorsPerCluster) |
|
- | 2156 | { |
|
- | 2157 | file.SectorOfCurrCluster=0; |
|
- | 2158 | end_of_directory_not_reached = GetNextCluster(&file); |
|
- | 2159 | } |
|
- | 2160 | } |
|
- | 2161 | index = 0; |
|
- | 2162 | } |
|
- | 2163 | while((end_of_directory_not_reached) && (!retvalue)); |
|
- | 2164 | ||
- | 2165 | return(retvalue); |
|
- | 2166 | } |
|
- | 2167 | ||
- | 2168 | ||
- | 2169 | /********************************************************************************************************************************************/ |
|
- | 2170 | /* Function: findnext_(Find_t *); */ |
|
- | 2171 | /* */ |
|
- | 2172 | /* Description: This function looks for the next item in the specified directory with a matching filename and fileattributes specified */ |
|
- | 2173 | /* by function findfirst() */ |
|
- | 2174 | /* */ |
|
- | 2175 | /* Returnvalue: */ |
|
- | 2176 | /********************************************************************************************************************************************/ |
|
- | 2177 | u8 findnext_(Find_t * findelement) |
|
- | 2178 | { |
|
- | 2179 | u8 itemfound = 0; |
|
- | 2180 | u8 index = 0; |
|
- | 2181 | ||
- | 2182 | findelement->fp.DirectoryIndex++; |
|
- | 2183 | ||
- | 2184 | /* before we start searching an element we clear the complete namestring within the structure FindElement */ |
|
- | 2185 | for(index=0;index<11;index++) findelement->name[index] = 0; |
|
- | 2186 | ||
- | 2187 | if(FindItem(findelement)) |
|
- | 2188 | { |
|
- | 2189 | itemfound = 1; |
|
- | 2190 | } |
|
- | 2191 | ||
- | 2192 | return(itemfound); |
|
- | 2193 | } |
|
- | 2194 | ||
- | 2195 | ||
- | 2196 | ||
- | 2197 | /********************************************************************************************************************************************/ |
|
- | 2198 | /* Function: findfirst_(s8* filename, u8 attribfilter, u8 attribmask, Find_t *); */ |
|
- | 2199 | /* */ |
|
- | 2200 | /* Description: This function looks for the first item in the specified directory with a matching filename and fileattributes */ |
|
- | 2201 | /* The filename of the element found is transformed from 8.3 to a string */ |
|
- | 2202 | /* */ |
|
- | 2203 | /* */ |
|
- | 2204 | /* Returnvalue: (1) if Element was found. (0) if no valid element was found */ |
|
- | 2205 | /********************************************************************************************************************************************/ |
|
- | 2206 | u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement) |
|
- | 2207 | { |
|
- | 2208 | u8 itemfound = 0; |
|
- | 2209 | u8 index = 0; |
|
- | 2210 | ||
- | 2211 | /* initialize the FindElement structure */ |
|
- | 2212 | findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file. |
|
- | 2213 | findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment. |
|
- | 2214 | findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster. |
|
- | 2215 | findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector. |
|
- | 2216 | findelement->fp.Size = 0; // The size of the opend file in bytes. |
|
- | 2217 | findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize |
|
- | 2218 | findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
|
- | 2219 | findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector. |
|
- | 2220 | findelement->attribfilter = 0; |
|
- | 2221 | findelement->attribmask = attribmask; |
|
- | 2222 | findelement->searchstring[0]=0; |
|
- | 2223 | ||
- | 2224 | /* seperate the name of the element to be found from the filepath and bring it to the 8.3*/ |
|
- | 2225 | SeperateDirName(name, findelement->searchstring); |
|
- | 2226 | /* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */ |
|
- | 2227 | for(index=0;index<8;index++) |
|
- | 2228 | { |
|
- | 2229 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
|
- | 2230 | if(findelement->searchstring[index] == '*') |
|
- | 2231 | { |
|
- | 2232 | /* */ |
|
- | 2233 | while(++index <8) findelement->searchstring[index] = '*'; |
|
- | 2234 | } |
|
- | 2235 | } |
|
- | 2236 | for(index=8;index<11;index++) |
|
- | 2237 | { |
|
- | 2238 | /* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
|
- | 2239 | if(findelement->searchstring[index] == '*') |
|
- | 2240 | { |
|
- | 2241 | /* */ |
|
- | 2242 | while(++index <11) findelement->searchstring[index] = '*'; |
|
- | 2243 | } |
|
- | 2244 | } |
|
- | 2245 | ||
- | 2246 | /* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */ |
|
- | 2247 | findelement->fp.DirectoryIndex--; |
|
- | 2248 | /* now lets search for the item within the direcory */ |
|
- | 2249 | itemfound = findnext_(findelement); |
|
- | 2250 | ||
- | 2251 | return(itemfound); |
|
- | 2252 | } |
|
- | 2253 | ||
- | 2254 | ||
- | 2255 | /********************************************************************************************************************************************/ |
|
- | 2256 | /* Function: u8 GetDirCount(s8* filepath); */ |
|
- | 2257 | /* */ |
|
- | 2258 | /* Description: This function counts the number of subdirectories the dirpath contains */ |
|
- | 2259 | /* */ |
|
- | 2260 | /* */ |
|
- | 2261 | /* Returnvalue: then number of subdirectories within the specified path */ |
|
- | 2262 | /********************************************************************************************************************************************/ |
|
- | 2263 | u8 GetDirCount(u8 *dirpath) |
|
- | 2264 | { |
|
- | 2265 | u8 i=0; |
|
- | 2266 | u8 cnt=0; |
|
- | 2267 | ||
- | 2268 | while(dirpath[i] != 0) |
|
- | 2269 | { |
|
- | 2270 | if(dirpath[i]=='/') |
|
- | 2271 | { |
|
- | 2272 | if(dirpath[i+1]!=0) cnt++; // ignore last'/' |
|
- | 2273 | } |
|
- | 2274 | i++; |
|
- | 2275 | } |
|
- | 2276 | i=0; |
|
- | 2277 | return(cnt); |
|
- | 2278 | } |
|
- | 2279 | ||
- | 2280 | ||
- | 2281 | /********************************************************************************************************************************************/ |
|
- | 2282 | /* Funtion: char *GetSubDirectory (char *dirpath, char *directory) */ |
|
- | 2283 | /* */ |
|
- | 2284 | /* Description: this function returns a pointer to the beginning of the next subdirectory or NULL */ |
|
- | 2285 | /* */ |
|
- | 2286 | /* */ |
|
- | 2287 | /* returnvalue: number of subdirectories in the filepath */ |
|
- | 2288 | /********************************************************************************************************************************************/ |
|
- | 2289 | u8 * GetSubDirectory(u8 *dirpath, u8 *directory) |
|
- | 2290 | { |
|
- | 2291 | u8 *cptr = dirpath; |
|
- | 2292 | u8 *dptr = directory; |
|
- | 2293 | u8 *retvalue = NULL; |
|
- | 2294 | ||
- | 2295 | /* if the first character of the path is an '/' we go to the next character */ |
|
- | 2296 | if(*cptr == '/') cptr++; |
|
- | 2297 | /* search end of path or subdirectory*/ |
|
- | 2298 | while((*cptr != 0) && (*cptr != '/')) |
|
- | 2299 | { |
|
- | 2300 | *dptr = *cptr; |
|
- | 2301 | dptr++; |
|
- | 2302 | cptr++; |
|
- | 2303 | } |
|
- | 2304 | if(*cptr!=0) retvalue = ++cptr; |
|
- | 2305 | *dptr = 0; |
|
- | 2306 | ||
- | 2307 | return(retvalue); |
|
- | 2308 | } |
|
- | 2309 | ||
- | 2310 | /********************************************************************************************************************************************/ |
|
- | 2311 | /* Function: s8 *GetPath(void); */ |
|
- | 2312 | /* */ |
|
- | 2313 | /* Description: This function function returns a pointer to the absolute path of the active partition */ |
|
- | 2314 | /* */ |
|
- | 2315 | /* */ |
|
- | 2316 | /* Returnvalue: */ |
|
- | 2317 | /********************************************************************************************************************************************/ |
|
- | 2318 | ||
- | 2319 | s8 *GetPath(void) |
|
- | 2320 | { |
|
- | 2321 | return(Partition.PathToCwd); |
|
- | 2322 | } |
|
- | 2323 | ||
- | 2324 | /********************************************************************************************************************************************/ |
|
- | 2325 | /* Function: void SetPathToRoot(void); */ |
|
- | 2326 | /* */ |
|
- | 2327 | /* Description: This function sets the path to the rootdirectory */ |
|
- | 2328 | /* */ |
|
- | 2329 | /* */ |
|
- | 2330 | /* Returnvalue: */ |
|
- | 2331 | /********************************************************************************************************************************************/ |
|
- | 2332 | ||
- | 2333 | void SetPathToRoot(void) |
|
- | 2334 | { |
|
- | 2335 | /* lets point to the rootdirectory */ |
|
- | 2336 | strcpy(Partition.PathToCwd, "/"); |
|
- | 2337 | } |
|
- | 2338 | ||
- | 2339 | /********************************************************************************************************************************************/ |
|
- | 2340 | /* Function: void AppendDirToPath(s8* directory); */ |
|
- | 2341 | /* */ |
|
- | 2342 | /* Description: This function function appends the name of an directory to the Path to the CWD */ |
|
- | 2343 | /* */ |
|
- | 2344 | /* */ |
|
- | 2345 | /* Returnvalue: */ |
|
- | 2346 | /********************************************************************************************************************************************/ |
|
- | 2347 | ||
- | 2348 | void AppendDirToPath(s8* directory) |
|
- | 2349 | { |
|
- | 2350 | /* append the name of the directory to the path */ |
|
- | 2351 | strcat(Partition.PathToCwd, directory); |
|
- | 2352 | /* append a '/' after the directoryname */ |
|
- | 2353 | strcat(Partition.PathToCwd, "/"); |
|
- | 2354 | } |
|
- | 2355 | ||
- | 2356 | /********************************************************************************************************************************************/ |
|
- | 2357 | /* Function: RemoveLastDirFromPath(void); */ |
|
- | 2358 | /* */ |
|
- | 2359 | /* Description: This function removes the last directory from the path to the cwd */ |
|
- | 2360 | /* */ |
|
- | 2361 | /* */ |
|
- | 2362 | /* Returnvalue: */ |
|
- | 2363 | /********************************************************************************************************************************************/ |
|
- | 2364 | ||
- | 2365 | void RemoveLastDirFromPath(void) |
|
- | 2366 | { |
|
- | 2367 | /* a pointer to the beginning of the absolute path to the cwd */ |
|
- | 2368 | s8 * cptr = Partition.PathToCwd; |
|
- | 2369 | /* lets find the end of the path to the cwd */ |
|
- | 2370 | while(*cptr++ != 0); |
|
- | 2371 | /* now lets find the beginning of the last directorientry */ |
|
- | 2372 | while(*cptr-- != '/'); |
|
- | 2373 | /* we delete the direntry by terminating the path with 0 */ |
|
- | 2374 | *++cptr = 0; |
|
- | 2375 | } |
|
- | 2376 | ||
- | 2377 | /********************************************************************************************************************************************/ |
|
- | 2378 | /* Function: chdir_(s8* filepath); */ |
|
- | 2379 | /* */ |
|
- | 2380 | /* Description: This function changed the current working directory to the directory specified by the filepath */ |
|
- | 2381 | /* by function findfirst() */ |
|
- | 2382 | /* */ |
|
- | 2383 | /* Returnvalue: */ |
|
- | 2384 | /********************************************************************************************************************************************/ |
|
- | 2385 | /* |
|
- | 2386 | #define ATTR_NONE 0x00 // normal file |
|
- | 2387 | #define ATTR_READONLY 0x01 // file is readonly |
|
- | 2388 | #define ATTR_HIDDEN 0x02 // file is hidden |
|
- | 2389 | #define ATTR_SYSTEM 0x04 // file is a system file |
|
- | 2390 | #define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
|
- | 2391 | #define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
|
- | 2392 | #define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
|
- | 2393 | #define ATTR_ARCHIVE 0x20 // file is new or modified |
|
- | 2394 | */ |
|
- | 2395 | ||
- | 2396 | u8 chdir_(s8 *path) |
|
- | 2397 | { |
|
- | 2398 | u8 retvalue = 0; // the value returned by this function |
|
- | 2399 | u32 ultemp = 0; // temp. variable |
|
- | 2400 | u8 *directory = path; // pointer to a directoryname within the path |
|
- | 2401 | u8 dircount = 0; // the number of subdirectoryentries within the path |
|
- | 2402 | u8 cache[64]; // a buffer containing the name of the subdirectory we are actually looking for |
|
- | 2403 | Find_t fe; // The findelement needed for function findfirst to find the subdirectoryentry |
|
- | 2404 | s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully |
|
- | 2405 | u32 cwdt = 0; |
|
- | 2406 | ||
- | 2407 | /* lets remember the actual path */ |
|
- | 2408 | strcpy(tp, Partition.PathToCwd); |
|
- | 2409 | cwdt = Partition.CurrentWorkingDirectory; |
|
- | 2410 | /* if the path is absolute we begin at the rootdirectory */ |
|
- | 2411 | strcpy(Partition.PathToCwd, "/"); |
|
- | 2412 | /* how many subdirectories are there within the path? */ |
|
- | 2413 | dircount = GetDirCount(path); |
|
- | 2414 | /* now we parse through all the subdirectories within the path */ |
|
- | 2415 | do |
|
- | 2416 | { |
|
- | 2417 | /* until all the subdirectories within the path have been processed */ |
|
- | 2418 | if(dircount) dircount--; |
|
- | 2419 | /* this is the name of the next subdirectory we are looking for */ |
|
- | 2420 | directory = GetSubDirectory(directory, cache); |
|
- | 2421 | /* search for the next subdirectory within the path */ |
|
- | 2422 | if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe)) |
|
- | 2423 | { |
|
- | 2424 | /* we try to change into the directory "..". Now we have to delete the last direntry from the path */ |
|
- | 2425 | if(strcmp(cache,"..") == 0) RemoveLastDirFromPath(); |
|
- | 2426 | /* we try to change into the actual directory so there's nothing todo */ |
|
- | 2427 | else if(cache[0] == '.') return(1); |
|
- | 2428 | /* otherwise we append the name of the directory we are changing in to the path */ |
|
- | 2429 | else AppendDirToPath(cache); |
|
- | 2430 | /* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */ |
|
- | 2431 | ultemp = (u32) fe.fp.FirstSectorOfFirstCluster; |
|
- | 2432 | /* the first 2 entries are reserved for '.' and '..' */ |
|
- | 2433 | ultemp -= 2; |
|
- | 2434 | /* 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*/ |
|
- | 2435 | ultemp *= Partition.SectorsPerCluster; |
|
- | 2436 | /* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */ |
|
- | 2437 | ultemp += Partition.FirstDataSector; |
|
- | 2438 | /* the cwd now points to the specified directory */ |
|
- | 2439 | Partition.CurrentWorkingDirectory = ultemp; |
|
- | 2440 | /* we found the folder specified by the foldername */ |
|
- | 2441 | retvalue = 1; |
|
- | 2442 | } |
|
- | 2443 | } |
|
- | 2444 | /* do this until all subdirectories have been found or a subdirectory is missing */ |
|
- | 2445 | while(dircount && retvalue); |
|
- | 2446 | ||
- | 2447 | /* if we could not change to the specified directory we restore the actual path */ |
|
- | 2448 | if(!retvalue) |
|
- | 2449 | { |
|
- | 2450 | Partition.CurrentWorkingDirectory = cwdt; |
|
- | 2451 | strcpy(Partition.PathToCwd, tp); |
|
- | 2452 | } |
|
- | 2453 | return(retvalue); |
|
- | 2454 | } |
|
- | 2455 | ||
- | 2456 | /********************************************************************************************************************************************/ |
|
- | 2457 | /* Function: void Test(void); */ |
|
- | 2458 | /* */ |
|
- | 2459 | /* Description: Diese Funktion demonstriert die Möglichkeiten der Funktionen findfirst_() findnext_() und changedir_() */ |
|
- | 2460 | /* */ |
|
- | 2461 | /* */ |
|
- | 2462 | /* Returnvalue: */ |
|
- | 2463 | /********************************************************************************************************************************************/ |
|
- | 2464 | ||
- | 2465 | void Test(void) |
|
- | 2466 | { |
|
- | 2467 | File_t *fp = NULL; |
|
- | 2468 | Find_t fe; |
|
- | 2469 | u32 cwd = 0; |
|
- | 2470 | ||
- | 2471 | ||
- | 2472 | cwd = Partition.CurrentWorkingDirectory; |
|
- | 2473 | sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text); |
|
- | 2474 | /* Als Erstes suchen wir uns das erste Unterverzeichnis (ATTR_SUBDIRECTORY) auf der Speicherkarte */ |
|
- | 2475 | if(findfirst_("*.*", ATTR_SUBDIRECTORY, &fe)) |
|
- | 2476 | { |
|
- | 2477 | /* Danach wechseln wir in in dieses Unterverzeichnis auf der speicherkarte */ |
|
- | 2478 | if(chdir_(fe.name)) |
|
- | 2479 | { |
|
- | 2480 | sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text); |
|
- | 2481 | /* Dann finden wir die erste Datei (ATTR_ARCIVE) in diesem Unterverzeichnis */ |
|
- | 2482 | if(findfirst_("*.*", ATTR_ARCHIVE, &fe)) |
|
- | 2483 | { |
|
- | 2484 | /* Der Name der gefundenen Datei wird ausgegeben */ |
|
- | 2485 | UART1_PutString("\r\n"); |
|
- | 2486 | UART1_PutString(fe.name); |
|
- | 2487 | /* nun wir die erste gefundene Datei im Unterverzeichnis lesend geöffnet */ |
|
- | 2488 | fp = fopen_(fe.name, 'r'); |
|
- | 2489 | if(fp != NULL){ |
|
- | 2490 | /* und die erste Zeile aus dem Inhalt ausgegeben */ |
|
- | 2491 | fgets_(text,60,fp); |
|
- | 2492 | UART1_PutString("\r\n"); |
|
- | 2493 | UART1_PutString(text); |
|
- | 2494 | fclose_(fp); |
|
- | 2495 | } |
|
- | 2496 | else { |
|
- | 2497 | UART1_PutString("\r\nfile not found"); |
|
- | 2498 | } |
|
- | 2499 | ||
- | 2500 | /* anschließend suchen wir alle weiteren Dateien im aktuellen Unterverzeichnis */ |
|
- | 2501 | while(findnext_(&fe)) |
|
- | 2502 | { |
|
- | 2503 | /* und geben ebenfalls deren Namen */ |
|
- | 2504 | UART1_PutString("\r\n"); |
|
- | 2505 | UART1_PutString(fe.name); |
|
- | 2506 | /* sowie nach dem Öffnen ihren Inhalt aus */ |
|
- | 2507 | fp = fopen_(fe.name, 'r'); |
|
- | 2508 | if(fp != NULL) |
|
- | 2509 | { |
|
- | 2510 | fgets_(text,60,fp); |
|
- | 2511 | UART1_PutString("\r\n"); |
|
- | 2512 | UART1_PutString(text); |
|
- | 2513 | fclose_(fp); |
|
- | 2514 | } |
|
- | 2515 | } |
|
- | 2516 | } |
|
- | 2517 | } |
|
- | 2518 | } |
|
- | 2519 | Partition.CurrentWorkingDirectory = cwd; |
|
- | 2520 | sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text); |
|
- | 2521 | if(chdir_("/ordner1/ordner12/ordner13")) |
|
- | 2522 | { |
|
- | 2523 | sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text); |
|
- | 2524 | fp = fopen_("Datei13.txt", 'r'); |
|
- | 2525 | if(fp != NULL){ |
|
- | 2526 | /* und die erste Zeile aus dem Inhalt ausgegeben */ |
|
- | 2527 | fgets_(text,60,fp); |
|
- | 2528 | UART1_PutString("\r\n"); |
|
- | 2529 | UART1_PutString(text); |
|
- | 2530 | fclose_(fp); |
|
- | 2531 | } |
|
- | 2532 | else { |
|
- | 2533 | UART1_PutString("\r\nfile not found"); |
|
- | 2534 | } |
|
- | 2535 | } |
|
- | 2536 | else |
|
- | 2537 | UART1_PutString("\r\ndirectory not found"); |
|
- | 2538 | /* jetzt sind wir wieder im Rootverzeichnis */ |
|
- | 2539 | Partition.CurrentWorkingDirectory = cwd; |
|
- | 2540 | sprintf(text,"\r\n Path: %s\r\n",Partition.PathToCwd); UART1_PutString(text); |
|
- | 2541 | } |