diff --git a/fat16.c b/fat16.c index f5f8d1b..4b4b793 100644 --- a/fat16.c +++ b/fat16.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; } + + + + + + + diff --git a/fat16.h b/fat16.h index 10affd3..bce4ee4 100644 --- a/fat16.h +++ b/fat16.h @@ -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); + diff --git a/main.c b/main.c index b86c591..6f6a412 100644 --- a/main.c +++ b/main.c @@ -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;