some formatting

master
Ondřej Hruška 10 years ago
parent dfa70f8d32
commit 9096222ff2
  1. 167
      fat16.c

@ -22,10 +22,10 @@ uint32_t clu_addr(const FAT16* fat, const uint16_t cluster);
uint16_t next_clu(const FAT16* fat, uint16_t cluster); uint16_t next_clu(const FAT16* fat, uint16_t cluster);
/** Find relative address in a file, using FAT for cluster lookup */ /** Find relative address in a file, using FAT for cluster lookup */
uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr); uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr);
/** Read a file entry from directory (dir starting cluster, entry number) */ /** Read a file entry from directory (dir starting cluster, entry number) */
void fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num); void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num);
/** Allocate and chain new cluster to a chain starting at given cluster */ /** Allocate and chain new cluster to a chain starting at given cluster */
bool append_cluster(const FAT16* fat, const uint16_t clu); bool append_cluster(const FAT16* fat, const uint16_t clu);
@ -161,7 +161,7 @@ uint16_t next_clu(const FAT16* fat, uint16_t cluster)
/** Find file-relative address in fat table */ /** Find file-relative address in fat table */
uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr) uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr)
{ {
while (addr >= fat->bs.bytes_per_cluster) while (addr >= fat->bs.bytes_per_cluster)
{ {
@ -277,76 +277,13 @@ bool dir_contains_file_raw(FAT16_FILE* dir, char* fname)
} }
// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
/** Initialize a FAT16 handle */
void fat16_init(const BLOCKDEV* dev, FAT16* fat)
{
const uint32_t bs_a = find_bs(dev);
fat->dev = dev;
read_bs(dev, &(fat->bs), bs_a);
fat->fat_addr = bs_a + (fat->bs.reserved_sectors * 512);
fat->rd_addr = bs_a + (fat->bs.reserved_sectors + fat->bs.fat_size_sectors * fat->bs.num_fats) * 512;
fat->data_addr = fat->rd_addr + (fat->bs.root_entries * 32); // entry is 32B long
fat->bs.bytes_per_cluster = (fat->bs.sectors_per_cluster * 512);
}
/**
* Move file cursor to a position relative to file start
* Allows seek past end of file, will allocate new cluster if needed.
*/
bool fat16_fseek(FAT16_FILE* file, uint32_t addr)
{
// Store as rel
file->cur_rel = addr;
// Rewind and resolve abs, clu, ofs
file->cur_clu = file->clu_start;
while (addr >= file->fat->bs.bytes_per_cluster)
{
uint32_t next;
// Go to next cluster, allocate if needed
do {
next = next_clu(file->fat, file->cur_clu);
if (next == 0xFFFF)
{
// reached end of allocated space
// add one more cluster
if (!append_cluster(file->fat, file->cur_clu))
{
return false;
}
printf("Allocating new cluster due to seek past EOF\n");
}
} while(next == 0xFFFF);
file->cur_clu = next;
addr -= file->fat->bs.bytes_per_cluster;
}
file->cur_abs = clu_addr(file->fat, file->cur_clu) + addr;
file->cur_ofs = addr;
// Physically seek to that location
file->fat->dev->seek(file->cur_abs);
return true;
}
/** /**
* Read a file entry * Read a file entry
* *
* dir_cluster ... directory start cluster * dir_cluster ... directory start cluster
* num ... entry number in the directory * num ... entry number in the directory
*/ */
void fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num) void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num)
{ {
// Resolve starting address // Resolve starting address
uint32_t addr; uint32_t addr;
@ -355,7 +292,7 @@ void fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster,
addr = clu_addr(fat, dir_cluster) + num * 32; // root directory, max 512 entries. addr = clu_addr(fat, dir_cluster) + num * 32; // root directory, max 512 entries.
} else } else
{ {
addr = clu_add(fat, dir_cluster, num * 32); // cluster + N (wrapping to next cluster if needed) addr = clu_offs(fat, dir_cluster, num * 32); // cluster + N (wrapping to next cluster if needed)
} }
fat->dev->seek(addr); fat->dev->seek(addr);
@ -405,12 +342,12 @@ void fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster,
if (file->attribs & FA_DIR && file->type == FT_FILE) if (file->attribs & FA_DIR && file->type == FT_FILE)
{ {
file->type = FT_SUBDIR; file->type = FT_SUBDIR;
} else }
if (file->attribs == FA_LABEL) else if (file->attribs == FA_LABEL)
{ {
file->type = FT_LABEL; // volume label special file file->type = FT_LABEL; // volume label special file
} else }
if (file->attribs == 0x0F) else if (file->attribs == 0x0F)
{ {
file->type = FT_LFN; // long name special file, can be safely ignored file->type = FT_LFN; // long name special file, can be safely ignored
} }
@ -423,6 +360,68 @@ void fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster,
} }
// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
/** Initialize a FAT16 handle */
void fat16_init(const BLOCKDEV* dev, FAT16* fat)
{
const uint32_t bs_a = find_bs(dev);
fat->dev = dev;
read_bs(dev, &(fat->bs), bs_a);
fat->fat_addr = bs_a + (fat->bs.reserved_sectors * 512);
fat->rd_addr = bs_a + (fat->bs.reserved_sectors + fat->bs.fat_size_sectors * fat->bs.num_fats) * 512;
fat->data_addr = fat->rd_addr + (fat->bs.root_entries * 32); // entry is 32B long
fat->bs.bytes_per_cluster = (fat->bs.sectors_per_cluster * 512);
}
/**
* Move file cursor to a position relative to file start
* Allows seek past end of file, will allocate new cluster if needed.
*/
bool fat16_fseek(FAT16_FILE* file, uint32_t addr)
{
// Store as rel
file->cur_rel = addr;
// Rewind and resolve abs, clu, ofs
file->cur_clu = file->clu_start;
while (addr >= file->fat->bs.bytes_per_cluster)
{
uint32_t next;
// Go to next cluster, allocate if needed
do {
next = next_clu(file->fat, file->cur_clu);
if (next == 0xFFFF)
{
// reached end of allocated space
// add one more cluster
if (!append_cluster(file->fat, file->cur_clu))
{
return false;
}
printf("Allocating new cluster due to seek past EOF\n");
}
} while(next == 0xFFFF);
file->cur_clu = next;
addr -= file->fat->bs.bytes_per_cluster;
}
file->cur_abs = clu_addr(file->fat, file->cur_clu) + addr;
file->cur_ofs = addr;
// Physically seek to that location
file->fat->dev->seek(file->cur_abs);
return true;
}
/** /**
* Check if file is a valid entry (to be shown) * Check if file is a valid entry (to be shown)
*/ */
@ -598,7 +597,7 @@ bool fat16_next(FAT16_FILE* file)
if (file->clu == 0 && file->num >= fat->bs.root_entries) if (file->clu == 0 && file->num >= fat->bs.root_entries)
return false; // attempt to read outside root directory. return false; // attempt to read outside root directory.
uint32_t addr = clu_add(fat, file->clu, (file->num + 1) * 32); uint32_t addr = clu_offs(fat, file->clu, (file->num + 1) * 32);
if (addr == 0xFFFF) if (addr == 0xFFFF)
return false; // next file is out of the directory cluster return false; // next file is out of the directory cluster
@ -611,7 +610,7 @@ bool fat16_next(FAT16_FILE* file)
if (x == 0) if (x == 0)
return false; return false;
fat16_fopen(fat, file, file->clu, file->num+1); open_file(fat, file, file->clu, file->num+1);
return true; return true;
} }
@ -623,7 +622,7 @@ bool fat16_prev(FAT16_FILE* file)
if (file->num == 0) if (file->num == 0)
return false; // first file already return false; // first file already
fat16_fopen(file->fat, file, file->clu, file->num-1); open_file(file->fat, file, file->clu, file->num-1);
/* // Skip bad files /* // Skip bad files
if (!fat16_is_file_valid(file)) if (!fat16_is_file_valid(file))
@ -636,7 +635,7 @@ bool fat16_prev(FAT16_FILE* file)
/** Rewind to first file in directory */ /** Rewind to first file in directory */
void fat16_first(FAT16_FILE* file) void fat16_first(FAT16_FILE* file)
{ {
fat16_fopen(file->fat, file, file->clu, 0); open_file(file->fat, file, file->clu, 0);
} }
@ -647,14 +646,14 @@ bool fat16_opendir(FAT16_FILE* file)
if (!(file->attribs & FA_DIR) || file->type == FT_SELF) if (!(file->attribs & FA_DIR) || file->type == FT_SELF)
return false; return false;
fat16_fopen(file->fat, file, file->clu_start, 0); open_file(file->fat, file, file->clu_start, 0);
return true; return true;
} }
void fat16_open_root(const FAT16* fat, FAT16_FILE* file) void fat16_open_root(const FAT16* fat, FAT16_FILE* file)
{ {
fat16_fopen(fat, file, 0, 0); open_file(fat, file, 0, 0);
} }
@ -698,7 +697,7 @@ bool fat16_newfile(FAT16_FILE* dir, FAT16_FILE* file, const char* name)
// Resolve addres of next file entry // Resolve addres of next file entry
uint32_t addr; uint32_t addr;
do { do {
addr = clu_add(fat, dir->clu, num * 32); addr = clu_offs(fat, dir->clu, num * 32);
if (addr == 0xFFFF) if (addr == 0xFFFF)
{ {
@ -712,14 +711,14 @@ bool fat16_newfile(FAT16_FILE* dir, FAT16_FILE* file, const char* name)
// Open the file entry // Open the file entry
fat16_fopen(fat, file, clu, num); open_file(fat, file, clu, num);
// Check if can be overwritten // Check if can be overwritten
if (file->type == FT_DELETED || file->type == FT_NONE) if (file->type == FT_DELETED || file->type == FT_NONE)
{ {
const uint16_t newclu = alloc_cluster(fat); const uint16_t newclu = alloc_cluster(fat);
const uint32_t entrystart = clu_add(fat, clu, num * 32); const uint32_t entrystart = clu_offs(fat, clu, num * 32);
// store the file name // store the file name
fat->dev->seek(entrystart); fat->dev->seek(entrystart);
@ -742,7 +741,7 @@ bool fat16_newfile(FAT16_FILE* dir, FAT16_FILE* file, const char* name)
fat->dev->write16(0); fat->dev->write16(0);
// reopen file, load the information just written // reopen file, load the information just written
fat16_fopen(fat, file, clu, num); open_file(fat, file, clu, num);
return true; return true;
} }
} }
@ -908,7 +907,7 @@ void fat16_set_file_size(FAT16_FILE* file, uint32_t size)
const BLOCKDEV* dev = file->fat->dev; const BLOCKDEV* dev = file->fat->dev;
// Find address for storing the size // Find address for storing the size
const uint32_t addr = clu_add(fat, file->clu, file->num * 32 + 28); const uint32_t addr = clu_offs(fat, file->clu, file->num * 32 + 28);
file->size = size; file->size = size;
dev->seek(addr); dev->seek(addr);
@ -935,7 +934,7 @@ void fat16_delete_file(FAT16_FILE* file)
const FAT16* fat = file->fat; const FAT16* fat = file->fat;
// seek to file record // seek to file record
fat->dev->seek(clu_add(fat, file->clu, file->num * 32)); fat->dev->seek(clu_offs(fat, file->clu, file->num * 32));
// mark as deleted // mark as deleted
fat->dev->write(0xE5); // "deleted" mark fat->dev->write(0xE5); // "deleted" mark

Loading…
Cancel
Save