📄 fat.c
字号:
/* check if current file is a directory */
if ((fat_cache.info.attributes & ATTR_DIRECTORY) == ATTR_DIRECTORY)
{
/* computes the sector address (RELATIVE) */
/* check also if we go to the root dir or not */
if (fat_cache.info.start_cluster != 0)
{
dir_is_root = FALSE; /* not the root dir */
fat_get_clusters(&dir_clusters); /* get directory allocation table */
/* initialize fat pointers */
fat_current_dir_fragment = 1;
fat_current_dir_cluster = 0;
fat_current_sector_cluster = 0;
fat_current_byte_counter = 0;
/* computes sector number from allocation table */
fat_current_sector = (((Uint32)(dir_clusters.cluster[0])) *
fat_cluster_size) + (fat_ptr_data - fat_ptr_rdir);
}
else
{
return fat_get_root_directory(id); /* goto root directory */
}
/* set the ABSOLUTE sector address */
fat_current_sector += fat_ptr_rdir;
fat_get_directory_chain(id);
fat_file_ptr = 1;
/* now we are at the beginning of directory */
if (fat_dseek((Int16)(fat_directory_chain[fat_file_ptr] * 32)) == OK)
{
/* update parent info in ".." entry*/
fat_fetch_directory_info(&fat_cache.parent);
/* point next file */
return fat_goto_next();
}
else
{
return KO;
}
}
}
/*F**************************************************************************
* NAME: fat_goto_parentdir
*----------------------------------------------------------------------------
* PARAMS:
* id: file extension to select
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* Go to the parent directory
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit fat_goto_parentdir (Byte id)
{
/* goto the parent directory */
fat_cache.info = fat_cache.parent;
/* issue the equivalent to a cd .. DOS command */
return (fat_goto_subdir(id));
}
/*F**************************************************************************
* NAME: fat_fopen
*----------------------------------------------------------------------------
* PARAMS:
* mode: READ: open file for read
* WRITE: open file for write
*
* return:
* - OK: file opened
* - KO: file not opened: - file is empty
* - file is too much fragmented
*----------------------------------------------------------------------------
* PURPOSE:
* Open the file in read or write mode
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit fat_fopen (bit mode)
{
if (fat_cache.info.size == 0)
{
return KO; /* file empty */
}
else
{
/* fat file byte counter */
fat_file_byte_counter = 0;
/* reset the allocation list variable */
fat_chain_index = 0;
fat_chain_cluster = 0;
if (fat_get_clusters(&clusters) != OK)
{
return KO; /* file too much fragmented */
}
/* seek to the beginning of the file */
if (mode == READ)
{
fat_open_mode = READ;
return Hard_read_open(fat_ptr_data + ((Uint32)(clusters.cluster[0])
* fat_cluster_size));
}
else
{
fat_open_mode = WRITE;
return Hard_write_open(fat_ptr_data + ((Uint32)(clusters.cluster[0])
* fat_cluster_size));
}
}
}
/*F**************************************************************************
* NAME: fat_fclose
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* Close opened file
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void fat_fclose (void)
{
if (fat_open_mode == READ)
{
Hard_read_close(); /* close reading */
}
else
{
Hard_write_close(); /* close writing */
}
}
/*F**************************************************************************
* NAME: fat_get_clusters
*----------------------------------------------------------------------------
* PARAMS:
* chain: allocation list address
*
* return:
* - OK: allocation done
* - KO: allocation not done: file too much fragmented
*----------------------------------------------------------------------------
* PURPOSE:
* Prepare a list of all the file clusters built as two tables:
* cluster[n] contains the staring cluster number of a fragment
* number[n] contains the number of contiguous clusters in fragment
* This way implies that file is not be too much fragmented
* The number of possible fragment is defined by the constant
* MAX_FILE_FRAGMENT_NUMBER in fat.h header file
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
bit fat_get_clusters (fat_cluster_chain *chain)
{
idata Uint16 new_cluster;
idata Uint16 old_cluster;
idata Byte index; /* index in chain */
idata Uint16 i;
idata Uint16 fat12_cluster;
bdata bit fat12_parity;
/* build the first entry of the allocation list */
chain->number[0] = 1;
chain->cluster[0] = fat_cache.info.start_cluster - 2; /* 2 = 1st cluster */
old_cluster = fat_cache.info.start_cluster;
index = 0;
/* calculate the first offset in fat and read the corresponding sector */
if (fat_is_fat16)
Hard_read_open(fat_ptr_fats + (old_cluster / (SECTOR_SIZE / 2)));
else
Hard_read_open(fat_ptr_fats);
if (fat_is_fat16) /* FAT16 management */
{ /* compute offset in sector */
for (i = (old_cluster % (SECTOR_SIZE / 2)); i != 0; i--)
{
Hard_read_byte(); /* dummy FAT read */
Hard_read_byte();
}
/* read first entry */
((Byte *)&new_cluster)[1]= Hard_read_byte();
((Byte *)&new_cluster)[0]= Hard_read_byte();
while (new_cluster != LAST_CLUSTER) /* loop until last cluster found */
{
if ((new_cluster == (old_cluster + 1)) && (chain->number[index] != 255))
{ /* contiguous cluster */
chain->number[index]++;
}
else
{ /* compute fragmentation */
index++;
chain->number[index] = 1;
chain->cluster[index] = new_cluster - 2; /* 2 = 1st cluster */
for (i = new_cluster - old_cluster - 1; i != 0; i--)
{
Hard_read_byte(); /* dummy FAT read */
Hard_read_byte();
}
}
old_cluster = new_cluster;
if (index == MAX_FILE_FRAGMENT_NUMBER - 2)
{
return KO; /* file too much fragmented */
}
else
{
/* read new entry */
((Byte *)&new_cluster)[1]= Hard_read_byte();
((Byte *)&new_cluster)[0]= Hard_read_byte();
}
}
}
else /* FAT12 management */
{ /* compute offset in sector */
fat12_parity = 0;
i = (old_cluster + 1);
do
{
if (fat12_parity == 0)
{
((Byte *)&fat12_cluster)[1]= Hard_read_byte();
((Byte *)&fat12_cluster)[0]= Hard_read_byte();
new_cluster = (fat12_cluster & 0x00FF);
new_cluster += (fat12_cluster & 0x0F00);
fat12_parity = 1;
}
else
{
((Byte *)&fat12_cluster)[1]= Hard_read_byte();
new_cluster = (fat12_cluster & 0xF000) >> 12;
new_cluster += (fat12_cluster & 0x00FF) << 4;
fat12_parity = 0;
}
i--;
}
while (i != 0);
while ( (new_cluster != 0xFFF) && (new_cluster != 0xFF8))
/* loop until last cluster found */
{
if ((new_cluster == (old_cluster + 1)) && (chain->number[index] != 255))
{ /* contiguous cluster */
chain->number[index]++;
}
else
{ /* compute fragmentation */
index++;
chain->number[index] = 1;
chain->cluster[index] = new_cluster - 2; /* 2 = 1st cluster */
for (i = new_cluster - old_cluster - 1; i != 0; i--)
{ /* dummy FAT read */
if (fat12_parity == 0)
{
((Byte *)&fat12_cluster)[1]= Hard_read_byte();
((Byte *)&fat12_cluster)[0]= Hard_read_byte();
fat12_parity = 1;
}
else
{
((Byte *)&fat12_cluster)[1]= Hard_read_byte();
fat12_parity = 0;
}
}
}
old_cluster = new_cluster;
if (index == MAX_FILE_FRAGMENT_NUMBER - 2)
{
return KO; /* file too much fragmented */
}
else
{
/* read new entry */
if (fat12_parity == 0)
{
((Byte *)&fat12_cluster)[1]= Hard_read_byte();
((Byte *)&fat12_cluster)[0]= Hard_read_byte();
new_cluster = (fat12_cluster & 0x00FF);
new_cluster += (fat12_cluster & 0x0F00);
fat12_parity = 1;
}
else
{
((Byte *)&fat12_cluster)[1]= Hard_read_byte();
new_cluster = (fat12_cluster & 0xF000) >> 12;
new_cluster += (fat12_cluster & 0x00FF) << 4;
fat12_parity = 0;
}
}
}
}
/* mark the last chain element with number= 0 */
chain->number[index + 1] = 0; /* end of chain marker */
Hard_read_close(); /* close physical read */
return OK;
}
/*F**************************************************************************
* NAME: fat_fgetc
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
* byte read
*----------------------------------------------------------------------------
* PURPOSE:
* Read one byte from file
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
* As this function is called very often it must be short and optimized
* in execution time
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte fat_fgetc (void)
{
/* check if we are at the end of a cluster */
if ((((Byte*)&fat_file_byte_counter)[3] == 0x00) &&
((((Byte*)&fat_file_byte_counter)[2] & fat_cluster_mask) == 0x00))
{
/* extract if necessary the next cluster from the allocation list */
if (clusters.number[fat_chain_index] == fat_chain_cluster)
{ /* new fragment */
fat_chain_index++;
fat_chain_cluster = 1;
Hard_read_open(fat_ptr_data + ((Uint32)(clusters.cluster[fat_chain_index]) * fat_cluster_size));
}
else
{ /* no new fragment */
fat_chain_cluster++; /* one more cluster read */
}
}
fat_file_byte_counter++; /* one more byte read */
return Hard_read_byte();
}
/*F**************************************************************************
* NAME: fat_fputc
*----------------------------------------------------------------------------
* PARAMS:
* d: data byte to write
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* Write one byte to file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -