Refactoring + cleanup, support for creating new files, function to find a file in dir.

master
Ondřej Hruška 10 years ago
parent 0bdc15e1d4
commit 2781148a25
  1. 582
      fat16.c
  2. 53
      fat16.h
  3. 63
      main.c

@ -6,122 +6,47 @@
#include "fat16.h"
char* fat16_volume_label(const FAT16* fat, char* str)
{
FAT16_FILE first;
fat16_open_root(fat, &first);
if (first.type == FT_LABEL) {
return fat16_display_name(&first, str);
}
// find where spaces end
uint8_t j = 10;
for (; j >= 0; j--)
{
if (fat->bs.volume_label[j] != ' ') break;
}
// copy all until spaces
uint8_t i;
for (i = 0; i <= j; i++)
{
str[i] = fat->bs.volume_label[i];
}
str[i] = 0; // ender
return str;
}
/**
* Resolve a file name, trim spaces and add null terminator.
* Returns the passed char*, or NULL on error.
*/
char* fat16_display_name(const FAT16_FILE* file, char* str)
{
// Cannot get name for special files
if (file->type == FT_NONE || // not-yet-used directory location
file->type == FT_DELETED || // deleted file entry
file->attribs == 0x0F) // long name special entry (system, hidden)
return NULL;
// find first non-space
uint8_t j = 7;
for (; j >= 0; j--)
{
if (file->name[j] != ' ') break;
}
// j ... last no-space char
uint8_t i;
for (i = 0; i <= j; i++)
{
str[i] = file->name[i];
}
// directory entry, no extension
if (file->type == FT_SUBDIR || file->type == FT_SELF || file->type == FT_PARENT)
{
str[i] = 0; // end of string
return str;
}
// add a dot
if (file->type != FT_LABEL) // volume label has no dot!
str[i++] = '.';
// Add extension chars
for (j = 0; j < 3; j++, i++)
{
const char c = file->ext[j];
if (c == ' ') break;
str[i] = c;
}
str[i] = 0; // end of string
return str;
}
// ============== INTERNAL PROTOTYPES ==================
/** Read boot sector from given address */
void _fat16_read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t addr);
/**
* Find absolute address of first BootSector.
* Returns 0 on failure.
*/
uint32_t _fat16_find_bs(const BLOCKDEV* dev);
void read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t addr);
/** Find absolute address of first BootSector. Returns 0 on failure. */
uint32_t find_bs(const BLOCKDEV* dev);
/** Get cluster's starting address */
uint32_t _fat16_clu_start(const FAT16* fat, const uint16_t cluster);
uint32_t clu_start(const FAT16* fat, const uint16_t cluster);
/** Find following cluster using FAT for jumps */
uint16_t _fat16_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 */
uint32_t _fat16_clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr);
uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr);
/** 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 fat16_fopen(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 */
bool append_cluster(const FAT16* fat, const uint16_t clu);
/** Allocate a new cluster, clean it, and mark with 0xFFFF in FAT */
uint16_t alloc_cluster(const FAT16* fat);
/** Zero out entire cluster. */
void wipe_cluster(const FAT16* fat, const uint16_t clu);
/**
* Find absolute address of first boot sector.
* Returns 0 on failure.
* Check if there is already a file of given RAW name
* Raw name - name as found on disk, not "display name".
*/
uint32_t _fat16_find_bs(const BLOCKDEV* dev)
bool dir_contains_file_raw(FAT16_FILE* dir, char* fname);
// =========== INTERNAL FUNCTION IMPLEMENTATIONS =========
/** Find absolute address of first boot sector. Returns 0 on failure. */
uint32_t find_bs(const BLOCKDEV* dev)
{
// Reference structure:
//
@ -141,19 +66,21 @@ uint32_t _fat16_find_bs(const BLOCKDEV* dev)
for (uint8_t i = 0; i < 4; i++, addr += 16)
{
// Read partition type
dev->aread(&tmp, 1, addr);
dev->seek(addr);
tmp = dev->read();
// Check if type is valid
if (tmp == 4 || tmp == 6 || tmp == 14)
{
// read MBR address
dev->rseek(3);// skip 3 bytes
dev->read(&tmp, 4);
dev->load(&tmp, 4);
tmp = tmp << 9; // multiply address by 512 (sector size)
// Verify that the boot sector has a valid signature mark
dev->aread(&tmp2, 2, tmp + 510);
dev->seek(tmp + 510);
dev->load(&tmp2, 2);
if (tmp2 != 0xAA55) continue; // continue to next entry
// return absolute MBR address
@ -165,25 +92,26 @@ uint32_t _fat16_find_bs(const BLOCKDEV* dev)
}
void _fat16_read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t addr)
/** Read the boot sector */
void read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t addr)
{
dev->seek(addr + 13); // skip 13
dev->read(&(info->sectors_per_cluster), 6); // spc, rs, nf, re
dev->load(&(info->sectors_per_cluster), 6); // spc, rs, nf, re
info->total_sectors = 0;
dev->read(&(info->total_sectors), 2); // short sectors
dev->load(&(info->total_sectors), 2); // short sectors
dev->rseek(1); // md
dev->read(&(info->fat_size_sectors), 2);
dev->load(&(info->fat_size_sectors), 2);
dev->rseek(8); // spt, noh, hs
// read or skip long sectors field
if (info->total_sectors == 0)
{
dev->read(&(info->total_sectors), 4);
dev->load(&(info->total_sectors), 4);
} else
{
dev->rseek(4); // tsl
@ -191,50 +119,141 @@ void _fat16_read_bs(const BLOCKDEV* dev, Fat16BootSector* info, const uint32_t a
dev->rseek(7); // dn, ch, bs, vi
dev->read(&(info->volume_label), 11);
}
/** Initialize a FAT16 handle */
void fat16_init(const BLOCKDEV* dev, FAT16* fat)
{
const uint32_t bs_a = _fat16_find_bs(dev);
fat->dev = dev;
_fat16_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);
dev->load(&(info->volume_label), 11);
}
/** Get cluster starting address */
uint32_t _fat16_clu_start(const FAT16* fat, const uint16_t cluster)
uint32_t clu_start(const FAT16* fat, const uint16_t cluster)
{
if (cluster < 2) return fat->rd_addr;
return fat->data_addr + (cluster - 2) * fat->bs.bytes_per_cluster;
}
uint16_t _fat16_next_clu(const FAT16* fat, uint16_t cluster)
uint16_t next_clu(const FAT16* fat, uint16_t cluster)
{
fat->dev->aread(&cluster, 2, fat->fat_addr + (cluster * 2));
return cluster;
fat->dev->seek(fat->fat_addr + (cluster * 2));
return fat->dev->read16();
}
/** Find file-relative address in fat table */
uint32_t _fat16_clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr)
uint32_t clu_add(const FAT16* fat, uint16_t cluster, uint32_t addr)
{
while (addr >= fat->bs.bytes_per_cluster)
{
cluster = _fat16_next_clu(fat, cluster);
cluster = next_clu(fat, cluster);
if (cluster == 0xFFFF) return 0xFFFF; // fail
addr -= fat->bs.bytes_per_cluster;
}
return _fat16_clu_start(fat, cluster) + addr;
return clu_start(fat, cluster) + addr;
}
/**
* Zero out entire cluster
* This is important only for directory clusters, so we can
* zero only every first byte of each file entry, to indicate
* that it is unused (FT_NONE).
*/
void wipe_cluster(const FAT16* fat, const uint16_t clu)
{
uint32_t addr = clu_start(fat, clu);
const BLOCKDEV* dev = fat->dev;
dev->seek(addr);
for (uint32_t b = 0; b < fat->bs.bytes_per_cluster; b += 32)
{
dev->write(0);
dev->rseek(32);
}
}
/** Allocate a new cluster, clean it, and mark with 0xFFFF in FAT */
uint16_t alloc_cluster(const FAT16* fat)
{
// find new unclaimed cluster that can be added to the chain.
uint16_t i, b;
for (i = 2; i < fat->bs.fat_size_sectors * 256; i++)
{
// read value from FAT
fat->dev->seek(fat->fat_addr + (i * 2));
b = fat->dev->read16();
if (b == 0)
{
// Write FFFF to "i", to mark end of file
b = 0xFFFF;
fat->dev->seek(fat->fat_addr + (i * 2));
fat->dev->write16(b);
// Wipe the cluster
wipe_cluster(fat, i);
return i;
}
}
return 0xFFFF;//error code
}
/** Allocate and chain new cluster to a chain starting at given cluster */
bool append_cluster(const FAT16* fat, const uint16_t clu)
{
uint16_t clu2 = alloc_cluster(fat);
if (clu2 == 0xFFFF) return false;
// Write "i" to "clu"
fat->dev->seek(fat->fat_addr + (clu * 2));
fat->dev->write16(clu2);
return true;
}
/**
* Check if there is already a file of given RAW name
* Raw name - name as found on disk, not "display name".
*/
bool dir_contains_file_raw(FAT16_FILE* dir, char* fname)
{
do {
bool diff = false;
for (uint8_t i = 0; i < 11; i++)
{
if (dir->name[i] != fname[i])
{
diff = true;
break;
}
}
if (!diff) return true;
} while (fat16_next(dir));
return false;
}
// =============== 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);
}
@ -253,11 +272,11 @@ bool fat16_fseek(FAT16_FILE* file, uint32_t addr)
while (addr >= file->fat->bs.bytes_per_cluster)
{
file->cur_clu = _fat16_next_clu(file->fat, file->cur_clu);
file->cur_clu = next_clu(file->fat, file->cur_clu);
addr -= file->fat->bs.bytes_per_cluster;
}
file->cur_abs = _fat16_clu_start(file->fat, file->cur_clu) + addr;
file->cur_abs = clu_start(file->fat, file->cur_clu) + addr;
file->cur_ofs = addr;
return true;
@ -270,21 +289,22 @@ bool fat16_fseek(FAT16_FILE* file, uint32_t addr)
* dir_cluster ... directory start cluster
* 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 fat16_fopen(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num)
{
// Resolve starting address
uint32_t addr;
if (dir_cluster == 0)
{
addr = _fat16_clu_start(fat, dir_cluster) + num * 32; // root directory, max 512 entries.
addr = clu_start(fat, dir_cluster) + num * 32; // root directory, max 512 entries.
} else
{
addr = _fat16_clu_add(fat, dir_cluster, num * 32); // cluster + N (wrapping to next cluster if needed)
addr = clu_add(fat, dir_cluster, num * 32); // cluster + N (wrapping to next cluster if needed)
}
fat->dev->aread(file, 12, addr);
fat->dev->seek(addr);
fat->dev->load(file, 12); // name, ext, attribs
fat->dev->rseek(14); // skip 14 bytes
fat->dev->read(((void*)file) + 12, 6); // read remaining bytes
fat->dev->load(((void*)file) + 12, 6); // read remaining bytes
file->clu = dir_cluster;
file->num = num;
@ -364,7 +384,6 @@ bool fat16_is_file_valid(const FAT16_FILE* file)
}
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len)
@ -375,11 +394,15 @@ bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len)
if (file->cur_rel + len > file->size)
return false; // attempt to read outside file size
const FAT16* fat = file->fat;
const BLOCKDEV* dev = fat->dev;
while (len > 0 && file->cur_rel < file->size)
{
uint16_t chunk = MIN(file->size - file->cur_rel, MIN(file->fat->bs.bytes_per_cluster - file->cur_ofs, len));
uint16_t chunk = MIN(file->size - file->cur_rel, MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len));
file->fat->dev->aread(target, chunk, file->cur_abs);
dev->seek(file->cur_abs);
dev->load(target, chunk);
file->cur_abs += chunk;
file->cur_rel += chunk;
@ -387,10 +410,10 @@ bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len)
target += chunk;
if (file->cur_ofs >= file->fat->bs.bytes_per_cluster)
if (file->cur_ofs >= fat->bs.bytes_per_cluster)
{
file->cur_clu = _fat16_next_clu(file->fat, file->cur_clu);
file->cur_abs = _fat16_clu_start(file->fat, file->cur_clu);
file->cur_clu = next_clu(fat, file->cur_clu);
file->cur_abs = clu_start(fat, file->cur_clu);
file->cur_ofs = 0;
}
@ -404,25 +427,26 @@ bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len)
/** Open next file in the directory */
bool fat16_next(FAT16_FILE* file)
{
if (file->clu == 0 && file->num >= file->fat->bs.root_entries)
const FAT16* fat = file->fat;
const BLOCKDEV* dev = fat->dev;
if (file->clu == 0 && file->num >= fat->bs.root_entries)
return false; // attempt to read outside root directory.
uint32_t addr = _fat16_clu_add(file->fat, file->clu, (file->num + 1) * 32);
uint32_t addr = clu_add(fat, file->clu, (file->num + 1) * 32);
if (addr == 0xFFFF)
return false; // next file is out of the directory cluster
// read first byte of the file entry; if zero, can't read (file is NONE)
// FIXME this may be a problem when creating a new file...
// FIXME this may be a problem when creating a new file...?
uint8_t x;
file->fat->dev->aread(&x, 1, addr);
dev->seek(addr);
x = dev->read();
if (x == 0)
return false;
_fat16_fopen(file->fat, file, file->clu, file->num+1);
/* // Skip bad files
if (!fat16_is_file_valid(file))
fat16_next(file);*/
fat16_fopen(fat, file, file->clu, file->num+1);
return true;
}
@ -434,7 +458,7 @@ bool fat16_prev(FAT16_FILE* file)
if (file->num == 0)
return false; // first file already
_fat16_fopen(file->fat, file, file->clu, file->num-1);
fat16_fopen(file->fat, file, file->clu, file->num-1);
/* // Skip bad files
if (!fat16_is_file_valid(file))
@ -444,6 +468,13 @@ bool fat16_prev(FAT16_FILE* file)
}
/** Rewind to first file in directory */
void fat16_first(FAT16_FILE* file)
{
fat16_fopen(file->fat, file, file->clu, 0);
}
/** Open a directory */
bool fat16_opendir(FAT16_FILE* file)
{
@ -451,12 +482,257 @@ bool fat16_opendir(FAT16_FILE* file)
if (!(file->attribs & FA_DIR) || file->type == FT_SELF)
return false;
_fat16_fopen(file->fat, file, file->clu_start, 0);
fat16_fopen(file->fat, file, file->clu_start, 0);
return true;
}
void fat16_open_root(const FAT16* fat, FAT16_FILE* file)
{
_fat16_fopen(fat, file, 0, 0);
fat16_fopen(fat, file, 0, 0);
}
/**
* Find a file with given "display name" in this directory.
* If file is found, "dir" will contain it's handle.
* Either way, "dir" gets modified and you may need to rewind it afterwards.
*/
bool fat16_find_file(FAT16_FILE* dir, const char* name)
{
char fname[11];
fat16_undisplay_name(name, fname);
return dir_contains_file_raw(dir, fname);
}
bool fat16_newfile(FAT16_FILE* dir, FAT16_FILE* file, const char* name)
{
// Convert filename to zero padded raw string
char fname[11];
fat16_undisplay_name(name, fname);
// Abort if file already exists
bool exists = dir_contains_file_raw(dir, fname);
fat16_first(dir); // rewind dir
if (exists) return false;
// Find free directory entry that can be used
uint16_t clu = dir->clu;
const FAT16* fat = dir->fat;
uint16_t num = 0;
for (; num < 0xFFFF; num++)
{
// root directory has fewer entries, error if trying
// to add one more.
if (dir->clu == 0 && num >= fat->bs.root_entries)
return false;
// Resolve addres of next file entry
uint32_t addr;
do {
addr = clu_add(fat, dir->clu, num * 32);
if (addr == 0xFFFF)
{
// end of chain of allocated clusters for the directory
// append new cluster, return false on failure
if (!append_cluster(fat, dir->clu)) return false;
}
// if new cluster was just added, repeat.
} while (addr == 0xFFFF);
// Open the file entry
fat16_fopen(fat, file, clu, num);
// Check if can be overwritten
if (file->type == FT_DELETED || file->type == FT_NONE)
{
const uint16_t newclu = alloc_cluster(fat);
const uint32_t entrystart = clu_add(fat, clu, num * 32);
// store the file name
fat->dev->seek(entrystart);
// filename, without dor, zero-padded.
fat->dev->store(fname, 11);
fat->dev->write(0); // attributes
fat->dev->rseek(14);
fat->dev->write16(newclu); // starting cluster
// file size (uint32_t)
fat->dev->write16(0);
fat->dev->write16(0);
// reopen file, load the information just written
fat16_fopen(fat, file, clu, num);
return true;
}
}
return false;
}
char* fat16_volume_label(const FAT16* fat, char* str)
{
FAT16_FILE first;
fat16_open_root(fat, &first);
if (first.type == FT_LABEL) {
return fat16_display_name(&first, str);
}
// find where spaces end
uint8_t j = 10;
for (; j >= 0; j--)
{
if (fat->bs.volume_label[j] != ' ') break;
}
// copy all until spaces
uint8_t i;
for (i = 0; i <= j; i++)
{
str[i] = fat->bs.volume_label[i];
}
str[i] = 0; // ender
return str;
}
char* fat16_display_name(const FAT16_FILE* file, char* str)
{
// Cannot get name for special files
if (file->type == FT_NONE || // not-yet-used directory location
file->type == FT_DELETED || // deleted file entry
file->attribs == 0x0F) // long name special entry (system, hidden)
return NULL;
// find first non-space
uint8_t j = 7;
for (; j >= 0; j--)
{
if (file->name[j] != ' ') break;
}
// j ... last no-space char
uint8_t i;
for (i = 0; i <= j; i++)
{
str[i] = file->name[i];
}
// directory entry, no extension
if (file->type == FT_SUBDIR || file->type == FT_SELF || file->type == FT_PARENT)
{
str[i] = 0; // end of string
return str;
}
// add a dot
if (file->type != FT_LABEL) // volume label has no dot!
str[i++] = '.';
// Add extension chars
for (j = 8; j < 11; j++, i++)
{
const char c = file->name[j];
if (c == ' ') break;
str[i] = c;
}
str[i] = 0; // end of string
return str;
}
char* fat16_undisplay_name(const char* name, char* fixed)
{
uint8_t name_c = 0, wr_c = 0;
bool filling = false;
bool at_ext = false;
for (; wr_c < 11; wr_c++)
{
// start filling with spaces if end of filename reached
char c = name[name_c];
// handle special rule for 0xE5
if (name_c == 0 && c == 0xE5) {
c = 0x05;
}
if (c == '.' || c == 0)
{
if (!filling)
{
filling = true;
if (c == '.')
{
name_c++; // skip the dot
c = name[name_c];
at_ext = true;
}
}
}
// if at the start of ext
if (wr_c == 8)
{
if (!at_ext)
{
// try to advance past dot (if any)
while(true)
{
c = name[name_c++];
if (c == 0) break;
if (c == '.') {
// read char PAST the dot
c = name[name_c];
at_ext = true;
break;
}
}
}
// if c has valid char for extension
if (c != 0 && c != '.')
{
// start copying again.
filling = false;
}
}
if (!filling)
{
// copy char of filename
fixed[wr_c] = name[name_c++];
}
else
{
// add a filler space
fixed[wr_c] = ' ';
}
}
return fixed;
}

@ -3,13 +3,17 @@
/** Abstract block device interface */
typedef struct {
// Sequential read
void (*read)(void* dest, const uint16_t len);
// Read at address
void (*aread)(void* dest, const uint16_t len, const uint32_t addr);
void (*load)(void* dest, const uint16_t len);
// Sequential write
void (*write)(const void* src, const uint16_t len);
// Write at address
void (*awrite)(const void* src, const uint16_t len, const uint32_t addr);
void (*store)(const void* src, const uint16_t len);
// Sequential byte write
void (*write)(const uint8_t b);
// Sequential 2-byte write
void (*write16)(const uint16_t b);
// Sequential byte read
uint8_t (*read)(void);
// Sequential 2-byte read
uint16_t (*read16)(void);
// Absolute seek
void (*seek)(const uint32_t);
// Relative seek
@ -89,10 +93,9 @@ typedef struct __attribute__((packed)) {
// Fields loaded directly from disk:
uint8_t name[8]; // Starting 0x05 converted to 0xE5, other "magic chars" left intact
uint8_t ext[3];
uint8_t name[11]; // Starting 0x05 converted to 0xE5, other "magic chars" left intact
uint8_t attribs; // composed of FA_* constants
// 12 bytes skipped
// 14 bytes skipped
uint16_t clu_start;
uint32_t size;
@ -152,6 +155,16 @@ bool fat16_fseek(FAT16_FILE* file, uint32_t addr);
bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len);
/**
* Create a new file in given folder
*
* directory ... parent folder's first entry
* file ... where to store info about newly opened file
* name ... name of the new file, including extension
*/
bool fat16_newfile(FAT16_FILE* directory, FAT16_FILE* file, const char* name);
// --------- NAVIGATION ------------
@ -159,14 +172,21 @@ bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len);
/** Go to previous file in the directory (false = no prev file) */
bool fat16_prev(FAT16_FILE* file);
/** Go to next file in directory (false = no next file) */
bool fat16_next(FAT16_FILE* file);
/** Open a directory (file is a directory entry) */
bool fat16_opendir(FAT16_FILE* file);
/** Rewind to first file in directory */
void fat16_first(FAT16_FILE* file);
/**
* Find a file with given "display name" in this directory.
* If file is found, "dir" will contain it's handle.
* Either way, "dir" gets modified and you may need to rewind it afterwards.
*/
bool fat16_find_file(FAT16_FILE* dir, const char* name);
// -------- FILE INSPECTION -----------
@ -175,12 +195,15 @@ bool fat16_opendir(FAT16_FILE* file);
bool fat16_is_file_valid(const FAT16_FILE* file);
/** Get opened file's type */
FAT16_FT fat16_get_type(const FAT16_FILE* file);
/**
* Resolve a file name, trim spaces and add null terminator.
* Returns the passed char*, or NULL on error.
*/
char* fat16_display_name(const FAT16_FILE* file, char* str);
/**
* Convert filename to zero-padded fixed length one
* Returns the passed char*.
*/
char* fat16_undisplay_name(const char* name, char* fixed);

@ -7,7 +7,7 @@
// ------------- test bed ----------------
// ------------- test ----------------
BLOCKDEV test;
FILE* testf;
@ -22,42 +22,62 @@ void test_rseek(const uint16_t pos)
fseek(testf, pos, SEEK_CUR);
}
void test_read(void* dest, const uint16_t len)
void test_load(void* dest, const uint16_t len)
{
for (int a = 0; a < len; a++) {
fread(dest+a, 1, 1, testf);
}
fread(dest, len, 1, testf);
// for (int a = 0; a < len; a++) {
// fread(dest+a, 1, 1, testf);
// }
}
void test_aread(void* dest, const uint16_t len, const uint32_t addr)
void test_store(const void* source, const uint16_t len)
{
test_seek(addr);
test_read(dest, len);
fwrite(source, len, 1, testf);
// for (int a = 0; a < len; a++) {
// fwrite(source+a, 1, 1, testf);
// }
}
void test_write(const uint8_t b)
{
fwrite(&b, 1, 1, testf);
}
void test_write16(const uint16_t b)
{
fwrite(&b, 2, 1, testf);
}
void test_write(const void* source, const uint16_t len)
uint8_t test_read()
{
for (int a = 0; a < len; a++) {
fwrite(source+a, 1, 1, testf);
}
uint8_t a;
fread(&a, 1, 1, testf);
return a;
}
void test_awrite(const void* source, const uint16_t len, const uint32_t addr)
uint16_t test_read16()
{
test_seek(addr);
test_write(source, len);
uint16_t a;
fread(&a, 2, 1, testf);
return a;
}
void test_open()
{
test.read = &test_read;
test.aread = &test_aread;
test.write = &test_write;
test.awrite = &test_awrite;
test.read16 = &test_read16;
test.write16 = &test_write16;
test.load = &test_load;
test.store = &test_store;
test.seek = &test_seek;
test.rseek = &test_rseek;
testf = fopen("imgs/dump_sd.img", "rb+");
testf = fopen("imgs/hamlet.img", "rb+");
}
void test_close()
@ -97,6 +117,13 @@ int main(int argc, char const *argv[])
} while (fat16_next(&file));
//FAT16_FILE file2;
fat16_open_root(&fat, &file);
//fat16_newfile(&file, &file2, "nuclear.war");
printf("Exists? %d\n", fat16_find_file(&file, "HAMLET.TXT"));
printf("Size: %d\n", file.size);
test_close();
return 0;

Loading…
Cancel
Save