54,14 → 54,12 |
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de. |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
#include <stdio.h> |
#include <string.h> |
#include "91x_lib.h" |
#include "timer1.h" |
#include "fat16.h" |
#include "sdc.h" |
#include "uart1.h" |
#include "main.h" |
|
#include "logging.h" |
//________________________________________________________________________________________________________________________________________ |
// Module name: fat16.c |
// Compiler used: avr-gcc 3.4.5 |
107,7 → 105,6 |
*/ |
|
|
|
/* |
________________________________________________________________________________________________________________________________________ |
|
128,8 → 125,6 |
u32 NoSectorsPartition ; // Number of Sectors in the Partition |
} __attribute__((packed)) PartitionEntry_t; |
|
|
|
/* |
Coding of Cylinder/Sector words |
|
313,18 → 308,14 |
u32 FirstRootDirSector; // sector of the rootdirectory |
u32 FirstDataSector; // sector of the first cluster containing data (cluster2). |
u32 LastDataSector; // the last data sector of the partition |
u8 VolumeLabel[12]; // the volume label |
u32 CurrentWorkingDirectory;// A pointer to the directory we are actual using |
s8 PathToCwd[256]; // a string containing the complete path to the current working directory |
} __attribute__((packed)) Partition_t; |
u8 VolumeLabel[12]; // the volume label |
} Partition_t; |
|
Partition_t Partition; // Structure holds partition information |
Partition_t Partition; // Structure holds partition information |
|
File_t FilePointer[FILE_MAX_OPEN]; // Allocate Memmoryspace for each filepointer used. |
|
|
|
|
/****************************************************************************************************************************************/ |
/* Function: FileDate(DateTime_t *); */ |
/* */ |
440,7 → 431,7 |
subpath = NULL; |
readpointer = 0; |
if(filepath[0] == '/') readpointer = 1; // ignore first '/' |
while(subpath == NULL && (SD_WatchDog)) // search the filepath until a subpath was found. |
while(subpath == NULL) // search the filepath until a subpath was found. |
{ |
if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/'))) // if '/' found or end of filepath reached |
{ |
452,33 → 443,11 |
// clear dirname with spaces |
dirname[11] = 0; // terminate dirname |
for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' '; |
|
// handle the special dirnames "." and ".." seperately |
readpointer = 0; |
if(filepath[0] == '/') readpointer++; |
// if we are trying to enter directories "." or ".." |
if(filepath[readpointer] == '.') |
{ |
// directory '.' |
if(filepath[readpointer+1] == 0) |
{ |
dirname[0] = '.'; |
return((s8*)&filepath[readpointer]); |
} |
// directory '..' |
if((filepath[readpointer+1] == '.') && (filepath[readpointer+2] == 0)) |
{ |
dirname[0] = '.'; |
dirname[1] = '.'; |
return((s8*)&filepath[readpointer]); |
} |
} |
|
writepointer = 0; |
// start seperating the dirname from the filepath. |
readpointer = 0; |
if(filepath[0] == '/') readpointer = 1; // ignore first '/' |
while( &filepath[readpointer] < subpath && (SD_WatchDog)) |
while( &filepath[readpointer] < subpath) |
{ |
if(writepointer >= 11) return(NULL); // dirname to long |
if(filepath[readpointer] == '.') // seperating dirname and extension. |
579,6 → 548,7 |
Partition.IsValid = 0; // mark data in partition structure as invalid |
Partition.VolumeLabel[0]='\0'; |
UART1_PutString("ok"); |
SD_LoggingError = 100; |
return(returnvalue); |
} |
|
601,6 → 571,7 |
|
UART1_PutString("\r\n FAT16 init..."); |
Partition.IsValid = 0; |
|
// declare the filepointers as unused. |
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++) |
{ |
683,8 → 654,6 |
goto end; |
} |
Partition.IsValid = 1; // mark data in partition structure as valid |
Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
strcpy(Partition.PathToCwd,"/"); |
result = 0; |
end: |
if(result != 0) Fat16_Deinit(); |
716,7 → 685,8 |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) |
{ |
Fat16_Deinit(); |
return(0); |
retvalue = 0; |
return(retvalue); |
} |
} |
return(retvalue); |
755,7 → 725,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card |
{ |
Fat16_Deinit(); |
return (CLUSTER_UNDEFINED); |
return (cluster); |
} |
} |
// read the next cluster from cache |
777,7 → 747,6 |
} |
|
|
|
/****************************************************************************************************************************************/ |
/* Function: FindNextFreeCluster(File_t *); */ |
/* */ |
804,7 → 773,7 |
if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector of fat from sd-card. |
{ |
Fat16_Deinit(); |
return(CLUSTER_UNDEFINED); |
return(free_cluster); |
} |
|
fat = (Fat16Entry_t *)file->Cache; // set fat pointer to file cache |
817,7 → 786,7 |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // and save the sector at the sd-card. |
{ |
Fat16_Deinit(); |
return(CLUSTER_UNDEFINED); |
return(free_cluster); |
} |
free_cluster = (u16)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (u32)fat_entry); |
fat_entry = FAT16_ENTRIES_PER_SECTOR; // terminate the search for a free cluster in this sector. |
825,7 → 794,7 |
} |
fat_sector++; // continue the search in next fat sector |
// repeat until the end of the fat is reached and no free cluster has been found so far |
}while((fat_sector < Partition.SectorsPerFat) && (!free_cluster) && (SD_WatchDog)); |
}while((fat_sector < Partition.SectorsPerFat) && (!free_cluster)); |
return(free_cluster); |
} |
|
867,7 → 836,7 |
file->ByteOfCurrSector = 0; |
file->Position = 0; |
if(file->FirstSectorOfCurrCluster == SECTOR_UNDEFINED) return(retvalue); |
while(file->Position < fposition && (SD_WatchDog)) // repeat until the current position is less than target |
while(file->Position < fposition) // repeat until the current position is less than target |
{ |
file->Position++; // increment file position |
file->ByteOfCurrSector++; // next byte in current sector |
957,7 → 926,7 |
} |
} |
} |
while(repeat && (SD_WatchDog)); |
while(repeat); |
|
return 1; |
} |
1068,6 → 1037,7 |
// dir entries can be searched only in filesclusters that have |
// a corresponding dir entry with adir-flag set in its attribute |
// or direct within the root directory area |
|
file->FirstSectorOfFirstCluster = SECTOR_UNDEFINED; |
// no current directory exist therefore assume searching in the root |
if(file->DirectorySector == SECTOR_UNDEFINED) |
1094,7 → 1064,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(0); |
return(direntry_exist); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1122,7 → 1092,7 |
|
do // loop over all data clusters of the current directory entry |
{ |
dir_sector = 0; |
dir_sector = 0; // reset sector counter within a new cluster |
do // loop over all sectors of a cluster or all sectors of the root directory |
{ |
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number |
1130,7 → 1100,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector |
{ |
Fat16_Deinit(); |
return(0); |
return(direntry_exist); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
// search all directory entries within that sector |
1164,7 → 1134,7 |
} |
dir_sector++; // search next sector |
// stop if we reached the end of the cluster or the end of the root dir |
}while((dir_sector < max_dir_sector) && (!direntry_exist) && (SD_WatchDog)); |
}while((dir_sector < max_dir_sector) && (!direntry_exist)); |
|
// if we are seaching in the data area and the file not found in this cluster so take next cluster. |
if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)) |
1171,7 → 1141,7 |
{ |
end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster |
} |
}while((end_of_directory_not_reached) && (!direntry_exist) && (SD_WatchDog)); // repeat until a next cluster exist an no |
}while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no |
return(direntry_exist); |
} |
|
1227,7 → 1197,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(0); |
return(retvalue); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist |
1269,7 → 1239,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(0); |
return(retvalue); |
} |
|
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
1295,7 → 1265,7 |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card |
{ |
Fat16_Deinit(); |
return(0); |
return(retvalue); |
} |
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster. |
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster. |
1313,7 → 1283,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(0); |
return(retvalue); |
} |
dir = (DirEntry_t *)file->Cache; |
// create direntry "." to current dir |
1332,7 → 1302,7 |
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector. |
{ |
Fat16_Deinit(); |
return(0); |
return(retvalue); |
} |
} |
retvalue = 1; |
1341,7 → 1311,7 |
} |
dir_sector++; // search next sector |
// stop if we reached the end of the cluster or the end of the root dir |
}while((dir_sector < max_dir_sector) && (!retvalue) && (SD_WatchDog)); |
}while((dir_sector < max_dir_sector) && (!retvalue)); |
|
// if we are seaching in the data area and the file not found in this cluster so take next cluster. |
if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)) |
1348,7 → 1318,7 |
{ |
end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster |
} |
}while((end_of_directory_not_reached) && (!retvalue) && (SD_WatchDog)); |
}while((end_of_directory_not_reached) && (!retvalue)); |
// Perhaps we are at the end of the last cluster of a directory file and have no free direntry found. |
// Then we would need to add a cluster to that file and create the new direntry there. |
// This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are |
1380,16 → 1350,8 |
path = (s8*)filename; // start a the beginning of the filename string |
file->DirectorySector = 0; // start at RootDirectory with file search |
file->DirectoryIndex = 0; |
/* if a path begins with a '/' at index 0 the search starts at the rootdirectory otherwise we will start relative to the cwd */ |
if(path[0] != '/') |
{ |
/* is the current working directory the rootdirectory? */ |
if(Partition.CurrentWorkingDirectory == Partition.FirstRootDirSector) file->DirectorySector = 0; |
/* otherwise we are working in an subdirectory */ |
else file->DirectorySector = Partition.CurrentWorkingDirectory; |
} |
// as long as the file was not found and the remaining path is not empty |
while((*path != 0) && !file_exist && (SD_WatchDog)) |
while((*path != 0) && !file_exist) |
{ // separate dirname and subpath from filepath string |
subpath = SeperateDirName(path, dirname); |
if(subpath != NULL) |
1451,7 → 1413,7 |
file->DirectorySector = 0; // start at RootDirectory with file search |
file->DirectoryIndex = 0; |
// as long as the file was not created and the remaining file path is not empty |
while((*path != 0) && !file_created && (SD_WatchDog)) |
while((*path != 0) && !file_created) |
{ // separate dirname and subpath from filepath string |
subpath = SeperateDirName(path, dirname); |
if(subpath != NULL) |
1498,7 → 1460,6 |
File_t * fopen_(s8 * const filename, const s8 mode) |
{ |
File_t *file = 0; |
s8 *cptr; |
|
if((!Partition.IsValid) || (filename == 0)) return(file); |
|
1521,15 → 1482,6 |
file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector. |
file->Attribute = 0; // the attribute of the file opened. |
|
// bring the path into the correct syntax |
cptr = filename; |
// search the whole string |
while(*cptr != 0 && (SD_WatchDog)) |
{ |
// replace all '\' by '/' |
if(*cptr == '\\') *cptr = '/'; |
cptr++; |
} |
// check if a real file (no directory) to the given filename exist |
if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file)) |
{ // file exist |
1607,7 → 1559,7 |
{ // if it could not be created |
fclose_(file); |
file = NULL; |
} |
} |
break; |
case 'r': // else opened for 'r' |
default: // if unsupported mode |
1710,7 → 1662,7 |
|
if( (!Partition.IsValid) || (file == NULL)) return(c); |
// if the end of the file is not reached, get the next character. |
if((0 < file->Size) && ((file->Position) < file->Size) ) |
if((0 < file->Size) && ((file->Position+1) < file->Size) ) |
{ |
curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read. |
curr_sector += file->SectorOfCurrCluster; |
1721,7 → 1673,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache)) |
{ |
Fat16_Deinit(); |
return(EOF); |
return(c); |
} |
} |
c = (s16) file->Cache[file->ByteOfCurrSector]; |
1848,10 → 1800,10 |
|
pbuff = (u8 *) buffer; // cast the void pointer to an u8 * |
|
while((object_cnt < count) && success && (SD_WatchDog)) |
while((object_cnt < count) && success) |
{ |
object_size = size; |
while((size > 0) && success && (SD_WatchDog)) |
while((size > 0) && success) |
{ |
c = fgetc_(file); |
if(c != EOF) |
1891,10 → 1843,10 |
if(file->Mode == 'r') return (0); // opened read only |
pbuff = (u8 *) buffer; // cast the void pointer to an u8 * |
|
while((object_cnt < count) && success && (SD_WatchDog)) |
while((object_cnt < count) && success) |
{ |
object_size = size; |
while((size > 0) && success && (SD_WatchDog)) |
while((size > 0) && success) |
{ |
c = fputc_(*pbuff, file); // write a byte from the buffer to the opened file. |
if(c != EOF) |
1928,7 → 1880,7 |
|
if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(EOF); |
if(file->Mode == 'r') return(EOF); |
while((string[i] != 0)&& (c != EOF) && (SD_WatchDog)) |
while((string[i] != 0)&& (c != EOF)) |
{ |
c = fputc_(string[i], file); |
i++; |
1951,7 → 1903,7 |
if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length < 1)) return (0); |
bytecount = length; |
pbuff = string; // set write pointer to start of string |
while(bytecount > 1 && (SD_WatchDog)) // read the length-1 characters from the file to the string. |
while(bytecount > 1) // read the length-1 characters from the file to the string. |
{ |
c = fgetc_(file); // read a character from the opened file. |
switch(c) |
2052,7 → 2004,7 |
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector |
{ |
Fat16_Deinit(); |
return(NULL); |
return(pVolumeLabel); |
} |
dir = (DirEntry_t *)file->Cache; // set pointer to directory |
// search all directory entries within that sector |
2084,452 → 2036,8 |
} |
dir_sector++; // search next sector |
// stop if we reached the end of the cluster or the end of the root dir |
}while((dir_sector < max_dir_sector) && (!pVolumeLabel) && (SD_WatchDog)); |
}while((dir_sector < max_dir_sector) && (!pVolumeLabel)); |
|
UnlockFilePointer(file); |
return(pVolumeLabel); |
} |
|
|
|
#define ATTR_NONE 0x00 // normal file |
#define ATTR_READONLY 0x01 // file is readonly |
#define ATTR_HIDDEN 0x02 // file is hidden |
#define ATTR_SYSTEM 0x04 // file is a system file |
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
#define ATTR_ARCHIVE 0x20 // file is new or modified |
|
|
/********************************************************************************************************************************************/ |
/* Function: u8 FindItem(Find_t); */ |
/* */ |
/* Description: This function looks for the item specified by global structure FindElement in the actual directory */ |
/* */ |
/* */ |
/* Returnvalue: TRUE if an matching element was found */ |
/********************************************************************************************************************************************/ |
|
u8 FindItem(Find_t *findelement) |
{ |
u16 index = 0; |
u16 max_dir_sector = 0; |
u16 end_of_directory_not_reached = 1; // the directory has been read completely without a result. |
u8 i = 0; |
u8 readpointer = 0; |
u8 writepointer = 0; |
u8 retvalue = 0; |
DirEntry_t *DirectoryEntry; |
File_t file; |
|
file.FirstSectorOfCurrCluster = findelement->fp.FirstSectorOfCurrCluster; |
file.SectorOfCurrCluster = findelement->fp.SectorOfCurrCluster; |
index = findelement->fp.DirectoryIndex; |
|
// within the root directory area we can read sectors sequentially until the end of this area |
if((Partition.FirstRootDirSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster < Partition.FirstDataSector)) |
{ |
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR; |
} |
// within the data clusters we can read sectors sequentially only within the cluster |
else if((Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) && (file.FirstSectorOfCurrCluster <= Partition.LastDataSector)) |
{ |
max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster |
} |
|
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
if(SD_SUCCESS != SDC_GetSector(((u32) file.FirstSectorOfCurrCluster + (u32)file.SectorOfCurrCluster), file.Cache)); // Read the Rootdirectory. |
{ |
Fat16_Deinit(); |
return(0); |
} |
|
DirectoryEntry = (DirEntry_t *)file.Cache; |
|
while((!retvalue)&&(index<16) && (SD_WatchDog)) |
{ |
i=0; |
if((u8) DirectoryEntry[index].Name[0] != 0xe5) // ignore deleted items. |
{ |
while((i<=10)&&((DirectoryEntry[index].Name[i] == findelement->searchstring[i]) || (findelement->searchstring[i]=='*') || findelement->searchstring[i]=='?')) |
{ |
i++; |
} |
} |
if((DirectoryEntry[index].Attribute <= 0x30) && (DirectoryEntry[index].Attribute & findelement->attribmask) && (i==11)) |
{ |
for(readpointer=0;readpointer<=10;readpointer++) |
{ |
if((DirectoryEntry[index].Name[readpointer] != ' ') && (readpointer!=8)) |
{ |
findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
writepointer++; |
} |
else |
{ |
if(DirectoryEntry[index].Attribute == ATTR_ARCHIVE) |
{ |
if(readpointer < 8) readpointer=8; |
if(DirectoryEntry[index].Name[readpointer] != ' ') |
{ |
findelement->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8. |
writepointer++; |
findelement->name[writepointer] = DirectoryEntry[index].Name[readpointer]; // copy the name of the item found to the find_structure. |
writepointer++; |
} |
else break; |
} |
else break; |
} |
/* terminate the namestring with 0 for debugpurposes*/ |
findelement->name[12] = 0; |
} |
findelement->fp.FirstSectorOfFirstCluster = (u32) DirectoryEntry[index].StartCluster; |
findelement->fp.DirectoryIndex = index; |
findelement->fp.FirstSectorOfCurrCluster = file.FirstSectorOfCurrCluster; |
findelement->fp.DirectorySector = (file.FirstSectorOfCurrCluster + file.SectorOfCurrCluster); |
findelement->fp.SectorOfCurrCluster = file.SectorOfCurrCluster; |
findelement->fp.Size = DirectoryEntry[index].Size; |
findelement->fp.Attribute = DirectoryEntry[index].Attribute; |
retvalue = 1; |
} |
/* search the next sector */ |
index++; |
} |
/* this sector has been searched but we havn't found what we are looking for. Therefore we have to find the next sector */ |
if(!retvalue) // file not found in this sector so take next sector. |
{ |
/* in the next sector we start looking for the specified entry beginning at index 0 */ |
index = 0; |
/* there are still sectors to be read within the cluster or within the linear addresspace of the rootdirectory */ |
if(file.SectorOfCurrCluster < max_dir_sector-1) file.SectorOfCurrCluster++; else end_of_directory_not_reached = 0; |
/* 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 */ |
if(Partition.FirstDataSector <= file.FirstSectorOfCurrCluster) |
{ |
end_of_directory_not_reached = GetNextCluster(&file); |
} |
} |
} |
while((end_of_directory_not_reached) && (!retvalue) && (SD_WatchDog)); |
|
return(retvalue); |
} |
|
|
|
|
/********************************************************************************************************************************************/ |
/* Function: findnext_(Find_t *); */ |
/* */ |
/* Description: This function looks for the next item in the specified directory with a matching filename and fileattributes specified */ |
/* by function findfirst() */ |
/* */ |
/* Returnvalue: */ |
/********************************************************************************************************************************************/ |
u8 findnext_(Find_t * findelement) |
{ |
u8 itemfound = 0; |
u8 index = 0; |
|
findelement->fp.DirectoryIndex++; |
|
/* before we start searching an element we clear the complete namestring within the structure FindElement */ |
for(index=0;index<11;index++) findelement->name[index] = 0; |
|
if(FindItem(findelement)) |
{ |
itemfound = 1; |
} |
|
return(itemfound); |
} |
|
|
|
/********************************************************************************************************************************************/ |
/* Function: findfirst_(s8* filename, u8 attribmask, Find_t *); */ |
/* */ |
/* Description: This function looks for the first item in the specified directory with a matching filename and fileattributes */ |
/* The filename of the element found is transformed from 8.3 to a string */ |
/* */ |
/* */ |
/* Returnvalue: (1) if Element was found. (0) if no valid element was found */ |
/********************************************************************************************************************************************/ |
u8 findfirst_(const s8* name, u8 attribmask, Find_t *findelement) |
{ |
u8 itemfound = 0; |
u8 index = 0; |
|
/* initialize the FindElement structure */ |
findelement->fp.FirstSectorOfFirstCluster = 0; // First sector of the first cluster of the file. |
findelement->fp.FirstSectorOfCurrCluster = Partition.CurrentWorkingDirectory; // First sector of the cluster which is edited at the moment. |
findelement->fp.SectorOfCurrCluster = 0; // The sector within the current cluster. |
findelement->fp.ByteOfCurrSector = 0; // The byte location within the current sector. |
findelement->fp.Size = 0; // The size of the opend file in bytes. |
findelement->fp.Position = 0; // Pointer to a character within the file 0 < fileposition < filesize |
findelement->fp.DirectorySector = 0; // the sectorposition where the directoryentry has been made. |
findelement->fp.DirectoryIndex = 0; // The index to the directoryentry within the specified sector. |
findelement->attribfilter = 0; |
findelement->attribmask = attribmask; |
findelement->searchstring[0]=0; |
|
/* seperate the name of the element to be found from the filepath and bring it to the 8.3*/ |
SeperateDirName(name, findelement->searchstring); |
/* after the name of the element is in 8.3 we process the wildcards (*). After an * all following character are wildcards to */ |
for(index=0;index<8;index++) |
{ |
/* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
if(findelement->searchstring[index] == '*') |
{ |
/* */ |
while(++index <8) findelement->searchstring[index] = '*'; |
} |
} |
for(index=8;index<11;index++) |
{ |
/* if we find an wildcard within the name of the searchstring all remaining character after the wildcard shall be wildcards also */ |
if(findelement->searchstring[index] == '*') |
{ |
/* */ |
while(++index <11) findelement->searchstring[index] = '*'; |
} |
} |
|
/* the value of ...DirectoryIndex will be incremented in findnext_() thererfore it has to be decremented in findfirst_() */ |
findelement->fp.DirectoryIndex--; |
/* now lets search for the item within the direcory */ |
itemfound = findnext_(findelement); |
|
return(itemfound); |
} |
|
|
/********************************************************************************************************************************************/ |
/* Function: u8 GetDirCount(s8* filepath); */ |
/* */ |
/* Description: This function counts the number of subdirectories the dirpath contains */ |
/* */ |
/* */ |
/* Returnvalue: then number of subdirectories within the specified path */ |
/********************************************************************************************************************************************/ |
u8 GetDirCount(u8 *dirpath) |
{ |
u8 i=0; |
u8 cnt=0; |
|
while(dirpath[i] != 0 && (SD_WatchDog)) |
{ |
if(dirpath[i]=='/') |
{ |
if(dirpath[i+1]!=0) cnt++; // ignore last'/' |
} |
i++; |
} |
i=0; |
return(cnt); |
} |
|
|
/********************************************************************************************************************************************/ |
/* Funtion: char *GetSubDirectory (char *dirpath, char *directory) */ |
/* */ |
/* Description: this function returns a pointer to the beginning of the next subdirectory or NULL */ |
/* */ |
/* */ |
/* returnvalue: number of subdirectories in the filepath */ |
/********************************************************************************************************************************************/ |
u8 * GetSubDirectory(u8 *dirpath, u8 *directory) |
{ |
u8 *cptr = dirpath; |
u8 *dptr = directory; |
u8 *retvalue = NULL; |
|
/* if the first character of the path is an '/' we go to the next character */ |
if(*cptr == '/') cptr++; |
/* search end of path or subdirectory*/ |
while((*cptr != 0) && (*cptr != '/') && (SD_WatchDog)) |
{ |
*dptr = *cptr; |
dptr++; |
cptr++; |
} |
if(*cptr!=0) retvalue = ++cptr; |
*dptr = 0; |
|
return(retvalue); |
} |
|
/********************************************************************************************************************************************/ |
/* Function: s8 *GetPath(void); */ |
/* */ |
/* Description: This function function returns a pointer to the absolute path of the active partition */ |
/* */ |
/* */ |
/* Returnvalue: */ |
/********************************************************************************************************************************************/ |
|
s8 *GetPath(void) |
{ |
return(Partition.PathToCwd); |
} |
|
/********************************************************************************************************************************************/ |
/* Function: void SetPathToRoot(void); */ |
/* */ |
/* Description: This function sets the path to the rootdirectory */ |
/* */ |
/* */ |
/* Returnvalue: */ |
/********************************************************************************************************************************************/ |
|
void SetPathToRoot(void) |
{ |
/* lets point to the rootdirectory */ |
strcpy(Partition.PathToCwd, "/"); |
} |
|
/********************************************************************************************************************************************/ |
/* Function: void AppendDirToPath(s8* directory); */ |
/* */ |
/* Description: This function function appends the name of an directory to the Path to the CWD */ |
/* */ |
/* */ |
/* Returnvalue: */ |
/********************************************************************************************************************************************/ |
|
void AppendDirToPath(s8* directory) |
{ |
/* append the name of the directory to the path */ |
strcat(Partition.PathToCwd, directory); |
/* append a '/' after the directoryname */ |
strcat(Partition.PathToCwd, "/"); |
} |
|
/********************************************************************************************************************************************/ |
/* Function: RemoveLastDirFromPath(void); */ |
/* */ |
/* Description: This function removes the last directory from the path to the cwd */ |
/* */ |
/* */ |
/* Returnvalue: */ |
/********************************************************************************************************************************************/ |
|
void RemoveLastDirFromPath(void) |
{ |
/* a pointer to the beginning of the absolute path to the cwd */ |
s8 * cptr = Partition.PathToCwd; |
/* lets find the end of the path to the cwd */ |
while(*cptr != 0 && (SD_WatchDog)) cptr++; |
/* if the path is terminated with an '/' */ |
if((*(cptr-1)) == '/') *(cptr-1)=0; |
/* now lets find the beginning of the last directorientry */ |
while((*cptr != '/' && (SD_WatchDog)) && cptr > Partition.PathToCwd) cptr--; |
/* is there one subdirectory left within the path? */ |
if(cptr > Partition.PathToCwd) |
{ |
/* we delete the direntry by terminating the path with 0 */ |
*cptr = 0; |
} |
/* there is no subdirectory left within the path. Therefore we create the root instead. */ |
else |
{ |
*cptr = '/'; |
*(cptr+1) = 0; |
} |
} |
|
/********************************************************************************************************************************************/ |
/* Function: chdir_(s8* filepath); */ |
/* */ |
/* Description: This function changed the current working directory to the directory specified by the filepath */ |
/* by function findfirst() */ |
/* */ |
/* Returnvalue: */ |
/********************************************************************************************************************************************/ |
/* |
#define ATTR_NONE 0x00 // normal file |
#define ATTR_READONLY 0x01 // file is readonly |
#define ATTR_HIDDEN 0x02 // file is hidden |
#define ATTR_SYSTEM 0x04 // file is a system file |
#define ATTR_VOLUMELABEL 0x08 // entry is a volume label |
#define ATTR_LONG_FILENAME 0x0F // this is a long filename entry |
#define ATTR_SUBDIRECTORY 0x10 // entry is a directory name |
#define ATTR_ARCHIVE 0x20 // file is new or modified |
*/ |
|
u8 chdir_(s8 *path) |
{ |
u8 retvalue = 0; // the value returned by this function |
u32 ultemp = 0; // temp. variable |
u8 *directory = path; // pointer to a directoryname within the path |
u8 dircount = 0; // the number of subdirectoryentries within the path |
u8 cache[64]; // a buffer containing the name of the subdirectory we are actually looking for |
Find_t fe; // The findelement needed for function findfirst to find the subdirectoryentry |
s8 tp[256]; // temporarily we remember the actual path until the operation has finished successfully |
u32 cwdt = 0; |
s8 *cptr; |
|
/* bring the path into the correct syntax */ |
cptr = path; |
/* search the whole string */ |
while(*cptr != 0 && (SD_WatchDog)) |
{ |
if(*cptr == '\\') *cptr = '/'; |
cptr++; |
} |
/* lets remember the actual path */ |
strcpy(tp, Partition.PathToCwd); |
cwdt = Partition.CurrentWorkingDirectory; |
/* how many subdirectories are there within the path? */ |
dircount = GetDirCount(path); |
/* if the path is absolute we begin at the rootdirectory */ |
if(path[0] == '/') |
{ |
strcpy(Partition.PathToCwd, "/"); |
Partition.CurrentWorkingDirectory = Partition.FirstRootDirSector; |
/* if there is no other pathinformation we only switch to the rootdirectory. So theres nothing left todo.*/ |
if(!dircount) return(1); |
} |
/* now we parse through all the subdirectories within the path */ |
do |
{ |
/* until all the subdirectories within the path have been processed */ |
if(dircount) dircount--; |
/* this is the name of the next subdirectory we are looking for */ |
directory = GetSubDirectory(directory, cache); |
/* search for the next subdirectory within the path */ |
if(findfirst_(cache, ATTR_SUBDIRECTORY, &fe)) |
{ |
/* we try to change into the directory "..". Now we have to delete the last direntry from the path */ |
if(strcmp(cache,"..") == 0) RemoveLastDirFromPath(); |
/* we try to change into the actual directory so there's nothing todo */ |
else if(cache[0] == '.') return(1); |
/* otherwise we append the name of the directory we are changing in to the path */ |
else AppendDirToPath(cache); |
/* The startcluster within an directoryentry specifies the position within the fat where the file or directory starts */ |
ultemp = (u32) fe.fp.FirstSectorOfFirstCluster; |
/* the first 2 entries are reserved for '.' and '..' */ |
ultemp -= 2; |
/* 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*/ |
ultemp *= Partition.SectorsPerCluster; |
/* at least we make the sectoraddress absolute by adding the relative address to the beginning of the datasection of the active partition */ |
ultemp += Partition.FirstDataSector; |
/* the cwd now points to the specified directory */ |
Partition.CurrentWorkingDirectory = ultemp; |
/* we found the folder specified by the foldername */ |
retvalue = 1; |
} |
} |
/* do this until all subdirectories have been found or a subdirectory is missing */ |
while(dircount && retvalue && (SD_WatchDog)); |
|
/* if we could not change to the specified directory we restore the actual path */ |
if(!retvalue) |
{ |
Partition.CurrentWorkingDirectory = cwdt; |
strcpy(Partition.PathToCwd, tp); |
} |
return(retvalue); |
} |