#include <stdio.h>
#include <avr/io.h>
#include "fat16.h"
#include "sdc.h"
#include "printf_P.h"
//________________________________________________________________________________________________________________________________________
// Module name: fat16.c
// Compiler used: avr-gcc 3.4.5
// Last Modifikation: 28.03.2008
// Version: 1.25
// Authors: Stephan Busker
// Description: Source files for FAT16 implementation with read and write-access using AVR-Mikrocontrollers
// Copyright (C) 2007 Stephan Busker
//........................................................................................................................................
// Functions: extern u8 FAT16_Init(void);
// u8 fopen_(s8 *fname,s8 mode, File *file);
// void fclose_(File *file);
// u32 fread_(void *buffer, u32 size, u32 count, File *file);
// u32 fwrite_(void *buffer, u32 size, u32 count, File *file);
// s16 fseek_(File *file, s32 offset, s16 origin);
// s8 fgets_(s8 *string, s16 count, File *file);
// u8 fputchar_(File *file,s8 c);
// u8 fputs_(File *file,s8 *string);
// s8 * fgets(s8 *, s16, File);
// u8 fexist_(u8*, File *file);
// u8 mkdir__(s8 *name);
// u8 chdir__(s8 *name);
// u8 findfirst_(s8 *fname, Find *item, u8 attribute);
// u8 findnext_(Find *item);
// u8 fdelete_(s8 *fname)
// u8 rmdir_(s8 *dname)
//........................................................................................................................................
// ext. functions: extern u8 SDC_GetSector (u32,u8 *);
// extern u8 SDC_PutSector (u32,u8 *);
//........................................................................................................................................
//
// URL: www.Mikro-Control.de
// mailto: stephan.busker@mikro-control.de
//________________________________________________________________________________________________________________________________________
u8 text
[80];
//________________________________________________________________________________________________________________________________________
//
// Global variables needed for read- or write-acces to the FAT16- filesystem.
//
//________________________________________________________________________________________________________________________________________
u8 SectorsPerCluster
= 0; // how many sectors does a cluster contain?
u8 FatCopies
= 0; // Numbers of copies of the FAT
u16 PossibleRootEntries
= 0; // Possible number of entries in the root directory.
u16 SectorsPerFat
= 0; // how many sectors does a fat16 contain?
u32 ReservedSectors
= 0; // Sectors reserved by the filesystem.
u32 FirstPartitionSector
= 0; // Distance in sectors between the first partition and the master bootrecord.
u32 FileAllocationTable
= 0; // pointer to the first FAT
u32 RootDirectory
= 0; // Pointer to the rootdirectory of the first partition.
u32 FirstDataCluster
= 0; // Pointer to the first cluster containing data (cluster0).
u32 CWD
= 0; // Pointer startcluster to the current working directory
struct DirEntry
*DirectoryEntry
; // Pointer to an entry of the directory.
struct FatEntry
*Fat
; // Pointer to an entry of the fat (next clusterposition).
File FilePointer
[__MAX_FILES_USED
]; // Allocate Memmoryspace for each filepointer used.
//________________________________________________________________________________________________________________________________________
// Funtion: InitFat16(void);
//
// Description: This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdirectory
// and stores the information in global variables.
//
// Returnvalue: The function returns "0" if the filesystem could not be initialized because no partition was found on the disc.
//________________________________________________________________________________________________________________________________________
u8 FAT16_Init
(void)
{
u8 retvalue
= 0;
u8 cnt
= 0;
struct VBR_Entry
*VBR
; // Pointer to the VolumeBootRecord.
struct MBR_Entry
*MBR
; // Pointer to the masterbootrecord.
File
*file
;
for(cnt
=0;cnt
<__MAX_FILES_USED
;cnt
++)
{
FilePointer
[cnt
].
state = _UNUSED
; // declare the filepointers as unused.
}
file
= &FilePointer
[0];
while((SDC_Init
() != 0) && (cnt
++<200)); // initialise the sdcard.
if(cnt
<200) //sdcard initialised succesfully
{
SDC_GetSector
((u32
)_MBR_SECTOR
,file
->buffer
); // Read the MasterBootRecord from mmc.
MBR
= (struct MBR_Entry
*) file
->buffer
;
FirstPartitionSector
= MBR
->PartitionEntry1.
NoSectorsBeforePartition;
if((MBR
->PartitionEntry1.
Type == _FAT16_32_MB_BIOS_Extension
) ||
(MBR
->PartitionEntry1.
Type == _FAT16_ST_32_MB
) ||
(MBR
->PartitionEntry1.
Type == _FAT16_LT_32_MB
))
{
SDC_GetSector
(FirstPartitionSector
,file
->buffer
); // Read the volume bootrecord from mmc.
VBR
= (struct VBR_Entry
*) file
->buffer
; // Enter the VBR using the structure VBR_Entry.
SectorsPerCluster
= VBR
->SectorsPerCluster
; // Number of sectors per cluster. Depends on the memorysize of the sd-card.
FatCopies
= VBR
->NoFATCopies
; // Number of fatcopies.
PossibleRootEntries
= VBR
->MaxRootEntries
; // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
SectorsPerFat
= VBR
->SectorsPerFAT
; // The number of sectors per FAT.
ReservedSectors
= VBR
->ReservedSectors
; // calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster.
FileAllocationTable
= (u32
)(FirstPartitionSector
+ (u32
)ReservedSectors
); // Calculate the position of the FileAllocationTable.
RootDirectory
= (u32
)((u32
)FileAllocationTable
+ (u32
)((u32
)SectorsPerFat
*(u32
)FatCopies
)); // Calculate the position of the Rootdirectory.
FirstDataCluster
= (u32
)((u32
)RootDirectory
+ ((u32
)(PossibleRootEntries
>>4))); // Calculate the position of the first datacluster.
CWD
= RootDirectory
; // The actual directory is the rootdirectory.
retvalue
= 1;
}
}
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: File * fopen_(u8*, u8 *);
//
// Description: This function looks for the file in the directory specified by the variable "CWD" of the drive. If the file is found the number of the
// corrosponding datacluster is returned to main. Only modes 'r' (reading) and 'a' append are implemented yet.
//
// Return: 0 = faild to open speicified file
// 1 = file opened
//________________________________________________________________________________________________________________________________________
File
* fopen_
(s8
*fname
, s8 mode
)
{
File
*file
;
file
= ReserveFilePointer
(); // reserve a filepointer.
if(file
!= NULL
) // A free filepointer was found.
{
file
->mode
= mode
; // mode of fileoperation (read,write)
if(SeekFileInDirectory
(fname
, file
)) // if file was found
{
if(mode
== 'a') // open existing file for writing (append data at the end of the file)
{
fseek_
(file
, 0, SEEK_END
); // fseek points to the end of the file
}
else if(mode
== 'r')
{
return(file
);
}
else
{
fclose_
(file
);
file
= NULL
;
}
}
else
{
if((mode
== 'a') || (mode
== 'w')) // specified file doesn't exist so create new file for writing data.
{
if(CreateFileInDirectory
(fname
,file
)) // Could an entry for the new file in the rootdirectory be created?
{
return(file
);
}
else
{
fclose_
(file
);
file
= NULL
;
}
}
}
}
return(file
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: fflush_(File *file);
//
// Description: This function writes the data already in the buffer but not yet written to the file.
//
//________________________________________________________________________________________________________________________________________
s16 fflush_
(File
*file
)
{
u16
time=0;
u16 date
=0;
if(file
&& ((file
->mode
=='a') || (file
->mode
=='w')))
{
if(file
->byte_index
> 0) // has data been added to the file?
{
SDC_PutSector
((u32
)(file
->cluster_pointer
+ file
->sector_index
),file
->buffer
);// save the data still in the buffer
}
SDC_GetSector
((u32
)file
->directory_sector
,file
->buffer
); // read the directoryentry for this file.
DirectoryEntry
= (struct DirEntry
*)file
->buffer
;
DirectoryEntry
[file
->directory_index
].
size = (u32
) file
->filesize
;
DirectoryEntry
[file
->directory_index
].
time = (u16
) time;
DirectoryEntry
[file
->directory_index
].
date = (u16
) date
;
SDC_PutSector
((u32
)file
->directory_sector
,file
->buffer
);
}
return(0);
}
//________________________________________________________________________________________________________________________________________
// Funtion: fclose_(File *file);
//
// Description: This function closes the open file by writing the remaining data from the buffer to the device and entering the filesize
// in the directory entry.
//________________________________________________________________________________________________________________________________________
void fclose_
(File
*file
)
{
if(file
!= NULL
)
{
fflush_
(file
); // save buffered data to the disk
}
FreeFilePointer
(file
); // and free the filepointer.
}
//________________________________________________________________________________________________________________________________________
// Funtion: u32 fread_(void *buffer, s32 size, s32 count, File *file);
//
// Description: This function reads count objects of the specified size from the actual position of the file to the specified buffer.
//
// Returnvalue: The function returns the number of objects (not bytes) read from the file.
//
//________________________________________________________________________________________________________________________________________
u32 fread_
(void *buffer
, u32 size
, u32 count
, File
*file
)
{
u32 object_cnt
= 0; // count the number of objects read from the file.
u32 object_size
= 0; // count the number of bytes read from the actual object.
u8
*buff_pnt
= 0; // a pointer to the actual bufferposition.
u8 success
= 1; // no error occured during read operation to the file.
buff_pnt
= (u8
*) buffer
; // cast the void pointer to an u8 *
while((object_cnt
< count
) && success
)
{
object_size
= size
;
while((size
> 0) && success
)
{
*buff_pnt
= (u8
) fgetchar_
(file
); // read a byte from the buffer to the opened file.
buff_pnt
++;
size
--;
}
if(success
) object_cnt
++;
}
return(object_cnt
); // return the number of objects succesfully read from the file
}
//________________________________________________________________________________________________________________________________________
// Funtion: u32 fwrite_(void *buffer, s32 size, s32 count, File *file);
//
// Description: This function writes count objects of the specified size from the buffer to the actual positon within the file.
//
// Returnvalue: The function returns the number of objects (not bytes) written to the file.
//
//________________________________________________________________________________________________________________________________________
u32 fwrite_
(void *buffer
, u32 size
, u32 count
, File
*file
)
{
u32 object_cnt
= 0; // count the number of objects written to the file.
u32 object_size
= 0; // count the number of bytes written from the actual object.
u8
*buff_pnt
= 0; // a pointer to the actual bufferposition.
u8 success
= 1; // no error occured during write operation to the file.
buff_pnt
= (u8
*) buffer
; // cast the void pointer to an u8 *
while((object_cnt
< count
) && success
)
{
object_size
= size
;
while((size
> 0) && success
)
{
success
= fputchar_
(file
, *buff_pnt
); // write a byte from the buffer to the opened file.
buff_pnt
++;
size
--;
}
if(success
) object_cnt
++;
}
return(object_cnt
); // return the number of objects succesfully written to the file
} // (!!!!! objects and not bytes !!!!)
//________________________________________________________________________________________________________________________________________
// Funtion: s16 fseek_(File *, s32, s16)
//
// Description: This function sets the pointer of the stream relative to the position
// specified by origin (SEEK_SET, SEEK_CUR, SEEK_END).
//
//________________________________________________________________________________________________________________________________________
s16 fseek_
(File
*file
, s32 offset
, s16 origin
)
{
s32 fposition
= 0;
s16 retvalue
= 1;
u32 temp
= 0;
//......................................................
if(origin
== SEEK_SET
) // Fileposition relative to the beginning of the file.
{
fposition
= 0;
}
//......................................................
else if(origin
== SEEK_END
) // Fileposition relative to the end of the file.
{
fposition
= (s32
) file
->filesize
;
}
//......................................................
else if(origin
== SEEK_CUR
) // Fileposition relative to the current position of the file.
{
fposition
= file
->fileposition
;
}
fposition
+= offset
;
if((fposition
>= 0) && (fposition
<= (s32
)file
->filesize
)) // is the pointer still within the file?
{
retvalue
= 0;
file
->sector_index
= 0;
file
->byte_index
= 0;
file
->fileposition
= 0;
file
->cluster_pointer
= file
->start_cluster
;
while(file
->fileposition
< fposition
)
{
file
->fileposition
++;
if(file
->byte_index
< 511)
{
file
->byte_index
++;
}
else
{
file
->byte_index
=0; // reading at the beginning of new sector.
file
->sector_index
++; // continue reading in next sector
if(file
->sector_index
>= SectorsPerCluster
) // When end of cluster is reached, the next datacluster has to be searched in the FAT.
{
if(file
->fileposition
< fposition
)
{
file
->sector_index
= 0; // start reading new cluster at first sector of the cluster.
GetNextCluster
(file
); // Sets the clusterpointer of the file to the next datacluster.
}
}
}
}
if(file
->byte_index
)
{
temp
= (u32
)((u32
)file
->cluster_pointer
+ (u32
)file
->sector_index
);
SDC_GetSector
((u32
)temp
,file
->buffer
); // FileBuffer will be written at once at the end of the cluster and has to be updated.
}
}
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: fgetchar_(File *file);
//
// Description: This function reads and returns one character from the specified file.
//
// Returnvalue: The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.
//________________________________________________________________________________________________________________________________________
s16 fgetchar_
(File
*file
)
{
s16 c
= EOF
;
u32 temp1
;
if(file
->filesize
> 0) // wen the end of the file is not reached, get the next character.
{
temp1
= (u32
)file
->cluster_pointer
; // calculate the adress of the next character to be read.
temp1
+= (u32
)file
->sector_index
;
if(file
->sector_in_buffer
!= temp1
) // Has the content of the buffer been modified and has to be updated?
{
SDC_GetSector
((u32
)temp1
,file
->buffer
); // Read the calculated cluster.
file
->sector_in_buffer
= (u32
)temp1
;
}
c
= (s16
) file
->buffer
[file
->byte_index
];
file
->filesize
--; // decrement the number of characters available.
if(file
->byte_index
< 511) // continue reading from this sector until the end of the sector is reached.
{
file
->byte_index
++;
}
else // has the end of an sector been reached->
{
file
->byte_index
=0; // continue reading at the beginning -
file
->sector_index
++; // of new sector.
if(file
->sector_index
>= SectorsPerCluster
) // When the end of an cluster is reached, the next datacluster has to be searched in the FAT.
{
file
->sector_index
= 0; // start reading new cluster at first sector of the cluster.
GetNextCluster
(file
); // Sets the clusterpointer of the file to the next datacluster.
}
}
}
return(c
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: fputchar_(File *file, s8 *);
//
// Description: This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.
//
// Returnvalue: The function returns a value of 0 if the data could not be written.
//________________________________________________________________________________________________________________________________________
u8 fputchar_
(File
*file
,s8 c
)
{
u32 ul_temp
= 0;
u8 retvalue
= 1;
if(file
->sector_index
>= SectorsPerCluster
) // if end of the cluster is reached, find next free cluster
{
file
->sector_index
= 0;
if(!AppendCluster
(file
)) retvalue
= 0; // append a new and free cluster at the end of the file.
}
file
->buffer
[file
->byte_index
] = c
; // write databyte into the buffer. The byte will be written to the device at once
if(file
->filesize
== file
->fileposition
) file
->filesize
++; // a character has been written to the file so the size is inkremented but only when the character has been added at the end of the file.
file
->fileposition
++; // the actual positon within the file.
// if the buffer contains the complete sectordata.
if(file
->byte_index
< 511) // if the end of this sector is not reached yet
{
file
->byte_index
++; // the next byte will be written to the next byteposition in this sector.
}
else // otherwise the data in the sectorbuffer will be written to the device and the next sector will be selected.
{
ul_temp
= (u32
)file
->cluster_pointer
;
ul_temp
+= (u32
)file
->sector_index
;
SDC_PutSector
((u32
)ul_temp
,file
->buffer
);
file
->byte_index
=0; // and the next byte will be written at the beginning of this new sector.
file
->sector_index
++;
if(file
->sector_index
>= SectorsPerCluster
) // if end of the cluster is reached, find next free cluster
{
file
->sector_index
= 0;
if(!AppendCluster
(file
)) retvalue
= 0; // append a new and free cluster at the end of the file.
}
}
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: fputs_(File *file, s8 *string);
//
// Description: This function writes a string to the specified file.
//
//________________________________________________________________________________________________________________________________________
u8 fputs_
(File
*file
,s8
* string
)
{
u8 i
=0;
while(string
[i
] != 0)
{
fputchar_
(file
,string
[i
]);
i
++;
}
return(0);
}
//________________________________________________________________________________________________________________________________________
// Funtion: s8 * fgets_(s8 *string, s16 count, File *file)
//
// Description: This function reads a string from the file to the specifies string.
//
// Returnvalue: A pointer to the string written from the file.
//________________________________________________________________________________________________________________________________________
s8
* fgets_
(s8
*string
, s16 count
, File
*file
)
{
s16 buff_pnt
= 0;
s16 buff_tmp
= 0;
u8 state
= 0; // Variable used for a statemachine to recognize the end of a line.
while(count
> 1) // read the count-1 characters from the file to the string.
{
buff_tmp
= fgetchar_
(file
); // read a character from the opened file.
switch(state
)
{
case 0:
if(buff_tmp
== 0x0D) state
++;
break;
case 1:
if(buff_tmp
== 0x0A)
{
count
= 1;
}
state
= 0;
break;
}
if(buff_tmp
== EOF
) {buff_tmp
= 0; count
= 1;} // is the end of the file reached, terminate the string with zero.
string
[buff_pnt
] = (s8
) buff_tmp
;
count
--;
buff_pnt
++;
}
string
[buff_pnt
] = 0;
return(string
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 fexist_(u8*, File *file);
//
// Description: This function searches the specified file and returns 0 if the file was not found.
//
//
// Return: 0 = file does not exist
// 1 = file exists
//________________________________________________________________________________________________________________________________________
u8 fexist_
(s8
*fname
)
{
File
*file
;
file
= ReserveFilePointer
();
if(file
!= NULL
)
{
if((file
= fopen_
(fname
,'r'))!= NULL
)
{
fclose_
(file
);
return(1);
}
else
{
return(0);
}
}
else
{
return(0);
}
}
//________________________________________________________________________________________________________________________________________
// Funtion: GetNextCluster(File *file);
//
// Description: This function finds the next datacluster of the file specified with File *file.
//
// Returnvalue: The function returns "0" if the last cluster has already been reached.
//________________________________________________________________________________________________________________________________________
u16 GetNextCluster
(File
*file
)
{
u32 fat_pointer
= 0;
u32 fat_sector_offset
= 0;
u32 ul_tmp
= 0;
u8 retvalue
= 0; // no new cluster found yet.
if((file
->cluster_pointer
>= RootDirectory
) && (file
->cluster_pointer
< (RootDirectory
+ 31)))
{ // Is the next cluster searched within the rootdirectory and available?
file
->cluster_pointer
++; // the rootdirectory is a linear adress space of 32 clusters.
retvalue
= 1; // and the next cluster has been found.
}
else if(file
->cluster_pointer
> (RootDirectory
+ 31)) // The specified cluster is within the FAT.
{
fat_sector_offset
= ((file
->cluster_pointer
) - (FirstDataCluster
)); // Calculate index of actual cluster within the FAT.
fat_sector_offset
/= SectorsPerCluster
; // calculate the index of the actual sector within the FAT.
fat_sector_offset
+= 2; // In Fat16 clusterpositions have an offset of two.
fat_pointer
= (fat_sector_offset
%0x100); // Calculate the sector within the cluster.
fat_sector_offset
= (fat_sector_offset
>>8); // and the position within the sector.
SDC_GetSector
((u32
)(FileAllocationTable
+ fat_sector_offset
),file
->buffer
);
file
->sector_in_buffer
= (FileAllocationTable
+ fat_sector_offset
); // Mark that new sector has been read.
ul_tmp
= (u32
)file
->buffer
[((fat_pointer
<< 1)+1)]; // Read next sector information from calculated clusterposition.
ul_tmp
= (ul_tmp
<< 8);
ul_tmp
|= (u32
)file
->buffer
[(fat_pointer
<< 1)];
ul_tmp
-=2; // next datacluster is clusterposition in fat - 2.
ul_tmp
*= SectorsPerCluster
; // calculate sectorposition of new cluster
ul_tmp
+= FirstDataCluster
; // in relation to first datacluster of the disk.
if(ul_tmp
< 0xfff7) // has a new cluster been read or was the end of the fat reached?
{
file
->cluster_pointer
= (u32
) ul_tmp
; // continue reading the file at the beginning of new datacluster.
retvalue
= 1; // a new cluster was found.
}
}
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 FindNextFreeCluster(void)
//
// Description: This function looks in the FAT to find the next free datacluster
//
// Returnvalue: The function returns the adress of the next free cluster found within the fAT.
//________________________________________________________________________________________________________________________________________
u16 FindNextFreeCluster
(File
*file
)
{
u32 fat_pointer
= 0; // Pointer to the first sector of the FAT.
u32 ul_tmp
= 0; // temporary variable used to calculate a sectornumber.
u16 fat_sector_offset
= 0; // index to a sector within the FAT.
u16 fat_entry
= 0; // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
u16 free_cluster
= 0; // a pointer to the first sector of the next free cluster.
fat_pointer
= (u32
) FileAllocationTable
; // start searching for empty cluster at the beginning of the fat.
// if the end of the fat is not reached yet and no free cluster has been found
while((fat_sector_offset
< SectorsPerFat
) && (!free_cluster
))
{
ul_tmp
= (u32
) ((u32
)fat_pointer
+ (u32
)fat_sector_offset
);
SDC_GetSector
((u32
)ul_tmp
,file
->buffer
); // read next sector of FAT.
file
->sector_in_buffer
= ul_tmp
; // remember the number of the sector in FileBuffer.
Fat
= (struct FatEntry
*)file
->buffer
;
for(fat_entry
=0;fat_entry
<256;fat_entry
++) // look for an free cluster at all entries in this sector of the fat.
{
if(Fat
[fat_entry
].
next_cluster == 0x0000) // empty cluster found!!
{
Fat
[fat_entry
].
next_cluster = 0xffff; // mark this fat-entry as used and save it to the device.
SDC_PutSector
((u32
)file
->sector_in_buffer
,file
->buffer
);
free_cluster
= fat_entry
; // the relative position of the free cluster found in this sector of the FAT.
free_cluster
+= (fat_sector_offset
<< 8); // calculate the absolute position of the free cluster in the FAT;
fat_entry
= 256; // terminate the search for a free cluster in this sector.
}
}
fat_sector_offset
++;
}
return(free_cluster
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 AppendCluster(File *file);
//
// Description: This function finds the next free datacluster on the disk and appends it to the specified file.
//
// Returnvalue: This funktion returns 1 if a cluster was appended to the specified file.
//________________________________________________________________________________________________________________________________________
u8 AppendCluster
(File
*file
)
{
u16 free_cluster
= 0;
u32 fat_pointer
= 0;
u8 retvalue
= 0;
free_cluster
= FindNextFreeCluster
(file
); // the next free cluster found on the disk.
if(free_cluster
) retvalue
= 1; // A free cluster was found and can be added to the end of the file.
fat_pointer
= FileAllocationTable
; // Set Pointer to the beginnig of the FAT.
fat_pointer
+= (u32
)((u32
)GetFatClusterOffset
(file
) >> 8); // find the sector in the FAT with 256 entries per sector.
SDC_GetSector
(fat_pointer
,file
->buffer
);
Fat
= (struct FatEntry
*)file
->buffer
;
Fat
[GetFatSectorIndex
(file
)].
next_cluster = free_cluster
; // append the free cluster to the end of the file in the FAT.
SDC_PutSector
((u32
)fat_pointer
,file
->buffer
); // save the modified sector to the FAT.
fat_pointer
= (u32
)free_cluster
;
fat_pointer
-= 2;
fat_pointer
*= SectorsPerCluster
;
fat_pointer
+= FirstDataCluster
;
file
->cluster_pointer
= fat_pointer
; // continue wrtiting to the file in the new and free datacluster.
return(retvalue
); // return 1 when a new cluster was appended to the file
}
//________________________________________________________________________________________________________________________________________
// Funtion: void DeleteClusterChain(u16 startcluster);
//
// Description: This function frees all the clusters used for file from the fat.
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
void DeleteClusterChain
(u16 startcluster
)
{
u16 fat_index
= 0;
u16 fat_sector_offset
= 0;
u32 sector_in_buffer
= 0;
u32 ul_temp
= 0;
u8 buffer
[512];
fat_index
= (startcluster
% 0x100); // Calculate the sector within the cluster.
fat_sector_offset
= (startcluster
>> 8); // and the position within the sector.
ul_temp
= (u32
)(FileAllocationTable
+ fat_sector_offset
);
do
{
if(sector_in_buffer
!= ul_temp
)
{
sector_in_buffer
= ul_temp
;
SDC_GetSector
(ul_temp
,buffer
);
}
Fat
= (struct FatEntry
*)buffer
;
startcluster
= Fat
[fat_index
].
next_cluster;
Fat
[fat_index
].
next_cluster = 0x0000; // free the cluster within the fat.
fat_index
= (startcluster
% 0x100); // Calculate the sector within the cluster.
fat_sector_offset
= (startcluster
>> 8); // and the position within the sector.
ul_temp
= (u32
)(FileAllocationTable
+ fat_sector_offset
);
if((sector_in_buffer
!= ul_temp
) || (startcluster
== 0xffff))
{
SDC_PutSector
(sector_in_buffer
,buffer
);
}
}
while(startcluster
!= 0xffff); // last cluster has been deleted.
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 GetFatClusterIndex(File *file);
//
// Description: This function returns the clusterindex of the cluster specified by file->cluster_pointer of the specified file.
//
//________________________________________________________________________________________________________________________________________
u16 GetFatClusterOffset
(File
*file
)
{
u32 fat_sector_offset
= 0;
fat_sector_offset
= ((file
->cluster_pointer
) - (FirstDataCluster
)); // Calculate index of actual cluster in FAT.
fat_sector_offset
/= SectorsPerCluster
;
fat_sector_offset
+= 2; // In Fat16 clusterpositions have an offset of two.
return((u16
)fat_sector_offset
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 GetFatSectorIndex(File *file);
//
// Description: This function returns the sectorindex of the cluster specified by file->cluster_pointer of the specified file.
//
//________________________________________________________________________________________________________________________________________
u16 GetFatSectorIndex
(File
*file
)
{
u16 fat_pointer
= 0;
fat_pointer
= GetFatClusterOffset
(file
);
fat_pointer
= fat_pointer
% 0x100; // Calculate the clusterposition in the fat
return(fat_pointer
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 CreateFileInDirectory(u8 *, File *)
//
// Description: This function looks for the next free position in the directory and creates an entry. The type of an directoryentry is
// specified by the attribute.
// bit0: unused
// bit1: archive
// bit2: read_only
// bit3: system
// bit4: directory
// bit5: volume
//________________________________________________________________________________________________________________________________________
u8 CreateFileInDirectory
(s8
*fname
, File
*file
)
{
u16 rootentry
= 0; // index to an entry in the rootdirectory.
u16 cnt_enries_searched
= 0; // count the number of rootentries which have been searched already.
u8 i
= 0;
u16 sector_offset
= 0; // index to the sector of the Rootentry which is searched momentarily
u8 retvalue
= 0;
u32 cluster_temp
= 0;
u16 cluster
= 0;
s8 name
[11] = " ";
SeperateFileName
(fname
,name
);
cluster_temp
= (u32
)FindNextFreeCluster
(file
); // the next free cluster on the disk.
if(cluster_temp
) // if a free cluster is available:
{
cluster
= (u16
)cluster_temp
; // remember the index of the free datacluster found for the directory entry.
cluster_temp
-=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
cluster_temp
*= SectorsPerCluster
; // Calculate relative sectorindex of first datacluster.
file
->start_cluster
= (FirstDataCluster
+ cluster_temp
); // Calculate absolute sectorposition of first datacluster.
file
->cluster_pointer
= file
->start_cluster
; // start reading the file with the first sector of the first datacluster.
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
rootentry
=0;
SDC_GetSector
((u32
)(CWD
+ sector_offset
),file
->buffer
); // Read the Rootdirectory.
DirectoryEntry
= (struct DirEntry
*)file
->buffer
;
while((rootentry
<16) && (!retvalue
))
{
if((DirectoryEntry
[rootentry
].
attribute == 0) || (DirectoryEntry
[rootentry
].
attribute == 0xE5)) // empty directory entry found
{
for(i
=0;i
<11;i
++) DirectoryEntry
[rootentry
].
name[i
] = name
[i
]; // Kopie the filename and the file extension to the directoryentry.
DirectoryEntry
[rootentry
].
attribute = _FILE
; // Set the fileattribute to archive to reserve the directoryentry.
DirectoryEntry
[rootentry
].
startcluster = cluster
; // copy the location of the first datacluster to the directoryentry.
DirectoryEntry
[rootentry
].
size = 0; // the new createted file has no content yet.
file
->directory_sector
= (u32
) (CWD
+ sector_offset
);
file
->directory_index
= (u8
) rootentry
;
retvalue
= 1;
SDC_PutSector
((u32
)(CWD
+ sector_offset
),file
->buffer
);
}
rootentry
++;
cnt_enries_searched
++;
}
if(!retvalue
) // file not found in this sector so take next sector.
{
rootentry
= 0;
sector_offset
++;
}
}
while((cnt_enries_searched
< PossibleRootEntries
) && (!retvalue
));
}
return(retvalue
); // return 1 if file has been created otherwise return 0.
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 SeekFileInDirectory(s8 *fname, File *)
//
// Description: this function searches all possible entries withint the actual directory for the specified object.
//
// Returnvalue: This function returns 1 if the directoryentry specified was found.
//________________________________________________________________________________________________________________________________________
u8 SeekFileInDirectory
(s8
*fname
, File
*file
)
{
u16 rootentry
=0;
u16 end_of_directory_not_reached
= 0; // the directory has been read completely without a result.
u8 i
=0;
u8 retvalue
= 0;
u32 cluster_temp
= 0;
s8 name
[11] = " ";
SeperateFileName
(fname
,name
);
file
->cluster_pointer
= CWD
; // start looking for the file in the actual directory.
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
rootentry
=0;
SDC_GetSector
((u32
) file
->cluster_pointer
,file
->buffer
); // Read the Rootdirectory.
DirectoryEntry
= (struct DirEntry
*)file
->buffer
;
while((!retvalue
)&&(rootentry
<16))
{
i
=0;
if(DirectoryEntry
[rootentry
].
name[0] != 0xe5) // ignore deleted items.
{
while((i
<=10)&&(DirectoryEntry
[rootentry
].
name[i
] == name
[i
]))
{
i
++;
}
}
if((i
==11) && (DirectoryEntry
[rootentry
].
attribute & _FILE
)) // entry found!! -> reading startcluster of entry from offset 26.
{
cluster_temp
= (u32
)DirectoryEntry
[rootentry
].
startcluster;
cluster_temp
-=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
cluster_temp
*= (u32
)SectorsPerCluster
; // Calculate positon of first cluster.
file
->start_cluster
= (FirstDataCluster
+ cluster_temp
);
file
->directory_sector
= (u32
) file
->cluster_pointer
;
file
->cluster_pointer
= file
->start_cluster
; // start reading the file with the first cluster.
file
->filesize
= (u32
) DirectoryEntry
[rootentry
].
size;
file
->directory_index
= (u8
) rootentry
;
retvalue
= 1;
}
rootentry
++;
}
if(!retvalue
) // file not found in this sector so take next sector.
{
end_of_directory_not_reached
= GetNextCluster
(file
);
}
}
while((end_of_directory_not_reached
) && (!retvalue
));
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: void SeperateFileName(u8*);
//
// Description: This function seperates the filename and the fileattribute and brings them into the needed format ('test.txt' -> 'TEST TXT');
//
//________________________________________________________________________________________________________________________________________
void SeperateFileName
(s8
*fname
, s8
*name
)
{
u8 readpointer
= 0;
u8 writepointer
= 0;
u8 attribute
= 1;
u8 i
= 0;
while((writepointer
<=10) && (fname
[readpointer
]!=0)) // the rootdirectoryentry is 8bytes for filename and 3bytes for fileattribute.
{ // the filename in the rootdirectory is in the format "TEST TXT" without the dot.
if(fname
[readpointer
]=='.') // seperating filename and attribute.
{
if(attribute
) // is the filename "." or ".." ?
{
name
[writepointer
] = fname
[readpointer
];
readpointer
++;
writepointer
++;
}
else
{
if(fname
[(readpointer
-1)] != '*')
{
for(i
=writepointer
;i
<8;i
++)
{
name
[i
] = ' ';
}
}
readpointer
++;
writepointer
= 8;
}
}
else if(fname
[readpointer
] == '*') // wildcard found within the filename + extension.
{
if(writepointer
< 8) // in extension.
{
readpointer
++;
writepointer
= 8;
}
else // in filename.
{
writepointer
= 11; // jump to the end of the string to terminate this function.
}
attribute
= 0;
}
else
{
if((fname
[readpointer
]>96) && (fname
[readpointer
]<123))
{
name
[writepointer
]=(fname
[readpointer
] - 32); // all characters must be upper case.
}
else
{
name
[writepointer
]=fname
[readpointer
];
}
readpointer
++;
writepointer
++;
attribute
= 0;
}
}
}
//________________________________________________________________________________________________________________________________________
// Funtion: File * ReserveFilePointer_(void);
//
// Description: This function looks for a free filepointer and reserves it.
//
//
// Return: NULL = faild to reserve a filepointer
// otherwise filepointer
//________________________________________________________________________________________________________________________________________
File
* ReserveFilePointer
(void)
{
File
*file
;
file
= NULL
;
u8 temp
;
for(temp
= 0;temp
<__MAX_FILES_USED
;temp
++)
{
if(FilePointer
[temp
].
state == _UNUSED
) // free filepointer found?
{
file
= &FilePointer
[temp
];
FilePointer
[temp
].
state = _USED
; // mark as used.
FilePointer
[temp
].
mode = 0; // type of access (read/write) not defined yet.
FilePointer
[temp
].
start_cluster = 0; // Sectorpointer to the first sector of the first datacluster of the file.
FilePointer
[temp
].
cluster_pointer = 0; // Pointer to the cluster which is edited at the moment.
FilePointer
[temp
].
sector_index = 0; // The sector which is edited at the moment (cluster_pointer + sector_index).
FilePointer
[temp
].
byte_index = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
FilePointer
[temp
].
filesize = 0; // the size of the opend file in bytes.
FilePointer
[temp
].
fileposition = 0; // pointer to a character within the file 0 < fileposition < filesize
FilePointer
[temp
].
sector_in_buffer = 0; // the last sector read, wich is still in the sectorbuffer.
FilePointer
[temp
].
directory_sector = 0; // the sectorposition where the directoryentry has been made.
FilePointer
[temp
].
directory_index = 0; // the index to the directoryentry within the specified sector.
FilePointer
[temp
].
attribute = 0; // the attribute of the file opened.
break;
}
}
return(file
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: void FreeFilePointer_(File *);
//
// Description: This function free's the filepointer by marking it as unused.
//
//
// Return: none
//
//________________________________________________________________________________________________________________________________________
void FreeFilePointer
(File
*file
)
{
u8 cnt
= 0;
for(cnt
=0;cnt
<__MAX_FILES_USED
;cnt
++) // Is the filepointeradress vaild?
{
if(&FilePointer
[cnt
] == file
) // filepointer found therefore it must be valid
{
FilePointer
[cnt
].
state = _UNUSED
; // and can be marked as unused.
}
}
}
//________________________________________________________________________________________________________________________________________
// Funtion: void DelteDirectoryEntry(Find *)
//
// Description: This function deletes the directoryentry of the specified item.
//
//
// returnvalue: 1 if the directory could be created.
//________________________________________________________________________________________________________________________________________
void DeleteDirectoryEntry
(Find
*item
)
{
u8 buffer
[512];
SDC_GetSector
((u32
) item
->cluster_pointer
,buffer
); // Read the Rootdirectory.
DirectoryEntry
= (struct DirEntry
*)buffer
;
DirectoryEntry
[(item
->directory_index
)-1].
attribute = 0; // free the directoryentry.
DirectoryEntry
[(item
->directory_index
)-1].
name[0] = 0xE5; // free the directoryentry.
SDC_PutSector
((u32
) item
->cluster_pointer
,buffer
); // Read the Rootdirectory.
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 CreateSubDirectory(u8 *)
//
// Description: This function creates an directory within the directory specified by CWD
//
//
// returnvalue: 1 if the directory could be created.
//________________________________________________________________________________________________________________________________________
u8 CreateSubDirectory
(s8
*fname
)
{
u16 index
= 0; // index to an entry in the rootdirectory.
u16 cnt_entries_searched
= 0; // count the number of rootentries which have been searched already.
u16 i
= 0;
u16 sector_offset
= 0; // index to the sector of the entry which is searched momentarily
u8 retvalue
= 0;
u32 cluster_temp
= 0;
u16 cluster
= 0;
File file
;
u8 name
[11] = {" "};
SeperateFileName
(fname
,name
);
cluster_temp
= (u32
)FindNextFreeCluster
(&file
); // the next free cluster on the disk.
if(cluster_temp
) // if a free cluster is available:
{
cluster
= (u16
)cluster_temp
; // remember the index of the free datacluster found for the directory entry.
cluster_temp
-=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
cluster_temp
*= SectorsPerCluster
; // Calculate relative sectorindex of first datacluster.
file.
start_cluster = (FirstDataCluster
+ cluster_temp
); // Calculate absolute sectorposition of first datacluster.
file.
cluster_pointer = file.
start_cluster; // start reading the file with the first sector of the first datacluster.
// -Initialise new cluster to zero--------------------------------------------------------
for(i
=0;i
<512;i
++)
{
file.
buffer[i
] = 0; // initialise buffer to zero
}
for(sector_offset
=0;sector_offset
<SectorsPerCluster
;sector_offset
++) // initialise all sectors of new cluster with buffer.
{
SDC_PutSector
((u32
)(file.
start_cluster + sector_offset
),file.
buffer); // save the initialised sector to the card.
}
// -Create directoryentry "." -------------------------------------------------------------
DirectoryEntry
= (struct DirEntry
*)file.
buffer;
DirectoryEntry
[0].
name[0] = '.';
DirectoryEntry
[0].
attribute = _DIRECTORY
;
DirectoryEntry
[0].
startcluster = cluster
;
// -Create directoryentry "." -------------------------------------------------------------
DirectoryEntry
[1].
name[0] = '.';
DirectoryEntry
[1].
name[1] = '.';
DirectoryEntry
[1].
attribute = _DIRECTORY
;
if(CWD
== RootDirectory
)
{
DirectoryEntry
[1].
startcluster = 0;
}
else
{
cluster_temp
= (CWD
- FirstDataCluster
);
cluster_temp
/= SectorsPerCluster
;
cluster_temp
-= 2;
DirectoryEntry
[1].
startcluster = (u16
) cluster_temp
;
}
SDC_PutSector
((u32
) file.
start_cluster,file.
buffer); // save the initialised sector to the card.
// -create directoryentry within the cwd --------------------------------------------------
sector_offset
= 0;
cnt_entries_searched
= 0;
do
{ // search the next 16 rootentries in this sector of the roordirectory.
index
=0;
SDC_GetSector
((u32
)(CWD
+ sector_offset
),file.
buffer); // Read the actual directory.
DirectoryEntry
= (struct DirEntry
*)file.
buffer;
while((index
<16) && (!retvalue
))
{
if((DirectoryEntry
[index
].
attribute == 0) || (DirectoryEntry
[index
].
attribute == 0xE5)) // empty directory entry found
{
for(i
=0;i
<11;i
++) DirectoryEntry
[index
].
name[i
] = name
[i
]; // Kopie the filename and the file extension to the directoryentry.
DirectoryEntry
[index
].
attribute = _DIRECTORY
; // Set the fileattribute to archive to reserve the directoryentry.
DirectoryEntry
[index
].
startcluster = cluster
; // copy the location of the first datacluster to the directoryentry.
DirectoryEntry
[index
].
size = 0; // the new createted file has no content yet.
file.
directory_sector = (u32
) (CWD
+ sector_offset
);
file.
directory_index = (u8
) index
;
retvalue
= 1;
SDC_PutSector
((u32
)(CWD
+ sector_offset
),file.
buffer);
}
index
++;
cnt_entries_searched
++;
}
if(!retvalue
) // file not found in this sector so take next sector.
{
index
= 0;
sector_offset
++;
}
}
while((cnt_entries_searched
< PossibleRootEntries
) && (!retvalue
));
}
return(retvalue
); // return 1 if file has been created otherwise return 0.
}
//________________________________________________________________________________________________________________________________________
// Funtion: u16 SeekSubDirectory(s8 *fname)
//
// Description: looks for the specified directory within the CWD.
//
// Returnvalue: If the specified directory was found the startcluster is returned. otherwise 0.
//________________________________________________________________________________________________________________________________________
u16 SeekSubDirectory
(s8
*fname
)
{
u16 index
= 0;
u16 end_of_directory_not_reached
= 0; // the directory has been read completely without a result.
u8 i
= 0;
u16 cluster_temp
= 0;
s8 name
[11] = " ";
File file
;
SeperateFileName
(fname
,name
);
file.
cluster_pointer = CWD
; // start looking for the file in the actual directory.
file.
start_cluster = CWD
; // start looking for the file in the actual directory.
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
index
=0;
SDC_GetSector
((u32
) file.
cluster_pointer,file.
buffer); // Read the Rootdirectory.
DirectoryEntry
= (struct DirEntry
*)file.
buffer;
while((!cluster_temp
)&&(index
<16))
{
i
=0;
if(DirectoryEntry
[index
].
name[0] != 0xe5) // ignore deleted items.
{
while((i
<=10)&&(DirectoryEntry
[index
].
name[i
] == name
[i
]))
{
i
++;
}
}
if((i
==11) && (DirectoryEntry
[index
].
attribute & _DIRECTORY
)) // entry found!! -> reading startcluster of entry from offset 26.
{
cluster_temp
= (u16
)DirectoryEntry
[index
].
startcluster;
}
index
++;
}
if(!cluster_temp
) // file not found in this sector so take next sector.
{
end_of_directory_not_reached
= GetNextCluster
(&file
);
}
}
while((end_of_directory_not_reached
) && (!cluster_temp
));
return(cluster_temp
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 mkdir_(u8 *)
//
// Description: This function checks if the directory to be created already exists. If not the directory will be created.
//
//
// returnvalue: 1 if the directory could be created.
//________________________________________________________________________________________________________________________________________
u8 mkdir_
(s8
*fname
)
{
u8 retvalue
= 0;
retvalue
= SeekSubDirectory
(fname
); // check wether the specified directory already exists.
if(!retvalue
)
{
CreateSubDirectory
(fname
); // if directory doesn't exist, create it.
retvalue
= 1;
}
else
{
retvalue
= 0;
}
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 chdir_(u8 *)
//
// Description: This function changes the CWD to the directory specified.
//
//
// returnvalue: 1 if the directory could be changed.
//________________________________________________________________________________________________________________________________________
u8 chdir_
(s8
*fname
)
{
u8 retvalue
= 0;
u8 name
[11] = {" "};
u32 ultemp
= 0;
SeperateFileName
(fname
,name
);
ultemp
= (u32
)SeekSubDirectory
(name
);
if(ultemp
>= 2)
{
ultemp
-=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
ultemp
*= SectorsPerCluster
; // Calculate relative sectorindex of first datacluster.
ultemp
+= FirstDataCluster
;
CWD
= ultemp
;
retvalue
= 1;
}
else
{
CWD
= RootDirectory
;
retvalue
= 1;
}
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 FindItem(s8 *fname, Find *)
//
// Description: finds an item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
//
// Returnvalue: If an item was found this function returns '1' else '0'.
//________________________________________________________________________________________________________________________________________
u8 FindItem
(Find
*item
)
{
u16 index
= 0;
u16 end_of_directory_not_reached
= 0; // the directory has been read completely without a result.
u8 i
= 0;
u8 readpointer
= 0;
u8 writepointer
= 0;
u8 retvalue
= 0;
File file
;
file.
cluster_pointer = item
->cluster_pointer
;
file.
start_cluster = item
->cluster_pointer
;
index
= item
->directory_index
;
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
SDC_GetSector
((u32
) file.
cluster_pointer,file.
buffer); // Read the Rootdirectory.
DirectoryEntry
= (struct DirEntry
*)file.
buffer;
while((!retvalue
)&&(index
<16))
{
i
=0;
if(DirectoryEntry
[index
].
name[0] != 0xe5) // ignore deleted items.
{
while((i
<=10)&&((DirectoryEntry
[index
].
name[i
] == item
->searchstring
[i
]) || (item
->searchstring
[i
]=='*') || item
->searchstring
[i
]=='?'))
{
i
++;
}
}
if((i
==11) && (DirectoryEntry
[index
].
attribute & item
->attribute
))
{
for(readpointer
=0;readpointer
<=10;readpointer
++)
{
if(DirectoryEntry
[index
].
name[readpointer
] != ' ')
{
item
->name
[writepointer
] = DirectoryEntry
[index
].
name[readpointer
]; // copy the name of the item found to the find_structure.
writepointer
++;
}
else if((readpointer
==7) && (DirectoryEntry
[index
].
attribute == _FILE
)) // if the item found is a file
{
if(DirectoryEntry
[index
].
name[readpointer
] != ' ')
{
item
->name
[writepointer
] = DirectoryEntry
[index
].
name[readpointer
]; // copy the name of the item found to the find_structure.
writepointer
++;
}
item
->name
[writepointer
] = '.'; // then seperate the name and the extension by a '.' at index 8.
writepointer
++;
}
}
item
->startcluster
= (u16
)DirectoryEntry
[index
].
startcluster;
item
->directory_index
= ++index
;
item
->cluster_pointer
= file.
cluster_pointer;
retvalue
= 1;
}
index
++;
}
if(!retvalue
) // file not found in this sector so take next sector.
{
end_of_directory_not_reached
= GetNextCluster
(&file
);
}
index
= 0;
}
while((end_of_directory_not_reached
) && (!retvalue
));
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 findfirst(s8 *fname, Find *)
//
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
//
// Returnvalue: If an item was found this function returns '1' else '0'.
//________________________________________________________________________________________________________________________________________
u8 findfirst_
(s8
*fname
, Find
*item
, u8 attribute
)
{
u8 retvalue
= 0;
u8 i
= 0;
for(i
=0;i
<=11;i
++)
{
item
->searchstring
[i
] = '*'; // initialise the searchstring with wildcards.
item
->name
[i
] = 0;
}
SeperateFileName
(fname
,item
->searchstring
);
item
->cluster_pointer
= CWD
; // findfirst_ starts at the beginning of the cwd.
item
->directory_index
= 0;
item
->attribute
= attribute
;
retvalue
= FindItem
(item
);
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 findnext(Find *)
//
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
//
// Returnvalue: If an item was found this function returns '1' else '0'.
//________________________________________________________________________________________________________________________________________
u8 findnext_
(Find
*item
)
{
u8 retvalue
= 0;
u8 i
= 0;
for(i
=0;i
<=11;i
++)
{
item
->name
[i
] = 0;
}
retvalue
= FindItem
(item
);
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 fdelete(s8 *fname)
//
// Description: Deletes the file specified by fname.
//
// Returnvalue:
//________________________________________________________________________________________________________________________________________
u8 fdelete_
(s8
*fname
)
{
u8 retvalue
= 0;
Find item
;
printf("\n\rDeleting file");
retvalue
= findfirst_
(fname
,&item
, _FILE
); // look for the item to be deleted.
if(retvalue
); // item found?
{
printf("\n\r");
printf("%s", item.
name);
DeleteClusterChain
(item.
startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry
(&item
); // free the directoryentry.
do
{
printf("\n\r");
printf("%s", item.
name);
retvalue
= findnext_
(&item
);
if(retvalue
)
{
DeleteClusterChain
(item.
startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry
(&item
); // free the directoryentry.
}
}
while(retvalue
);
}
printf("\n\rDone");
return(retvalue
);
}
//________________________________________________________________________________________________________________________________________
// Funtion: u8 rmdir(s8 *fname)
//
// Description: Deletes the directory specified by dname.
//
// Returnvalue:
//________________________________________________________________________________________________________________________________________
u8 rmdir_
(s8
*dname
)
{
u8 retvalue
= 0;
Find item
;
printf("\n\rDeleting folder");
retvalue
= findfirst_
(dname
,&item
, _DIRECTORY
); // look for the item to be deleted.
if(retvalue
); // item found?
{
printf("\n\r");
printf("%s", item.
name);
DeleteClusterChain
(item.
startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry
(&item
); // free the directoryentry.
do
{
printf("\n\r");
printf("%s", item.
name);
retvalue
= findnext_
(&item
);
if(retvalue
)
{
DeleteClusterChain
(item.
startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry
(&item
); // free the directoryentry.
}
}
while(retvalue
);
}
printf("\n\rDone");
return(retvalue
);
}