Added great improvements from avr-lib, including huge name changes.

master
Ondřej Hruška 9 years ago
parent adae8b8cdf
commit 50b933231c
  1. 66
      blockdev.h
  2. 225
      fat16.c
  3. 117
      fat16.h
  4. 1
      fat16_internal.h
  5. 14
      main.c

@ -0,0 +1,66 @@
#pragma once
//
// Block device interface, somewhat akin to stream.h
// Used for filesystem implementations.
//
#include <stdint.h>
/** Abstract block device interface
*
* Populate an instance of this with pointers to your I/O functions.
*/
typedef struct
{
/** Sequential read at cursor
* @param dest destination memory structure
* @param len number of bytes to load and store in {dest}
*/
void (*load)(void* dest, const uint16_t len);
/** Sequential write at cursor
* @param src source memory structure
* @param len number of bytes to write
*/
void (*store)(const void* src, const uint16_t len);
/** Write one byte at cursor
* @param b byte to write
*/
void (*write)(const uint8_t b);
/** Read one byte at cursor
* @return the read byte
*/
uint8_t (*read)(void);
/** Absolute seek - set cursor
* @param addr new cursor address
*/
void (*seek)(const uint32_t addr);
/** Relative seek - move cursor
* @param offset cursor address change
*/
void (*rseek)(const int16_t offset);
/** Flush the data buffer if it's dirty.
*
* Should be called after each sequence of writes,
* to avoid data loss.
*
* Tmplementations that do not need this should provide
* a no-op function.
*/
void (*flush)(void);
} BLOCKDEV;

@ -24,7 +24,7 @@ uint16_t next_clu(const FAT16* fat, uint16_t cluster);
uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr);
/** Read a file entry from directory (dir starting cluster, entry number) */
void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num);
void open_file(const FAT16* fat, FFILE* 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);
@ -42,7 +42,7 @@ bool free_cluster_chain(const FAT16* fat, uint16_t clu);
* Check if there is already a file of given RAW name
* Raw name - name as found on disk, not "display name".
*/
bool dir_find_file_raw(FAT16_FILE* dir, const char* fname);
bool dir_find_file_raw(FFILE* dir, const char* fname);
/** Write a value into FAT */
void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value);
@ -103,7 +103,10 @@ uint32_t find_bs(const BLOCKDEV* dev)
// Verify that the boot sector has a valid signature mark
dev->seek(tmp + 510);
dev->load(&tmp2, 2);
if (tmp2 != 0xAA55) continue; // continue to next entry
if (tmp2 != 0xAA55)
{
continue; // continue to next entry
}
// return absolute MBR address
return tmp;
@ -273,10 +276,10 @@ bool free_cluster_chain(const FAT16* fat, uint16_t clu)
* Check if there is already a file of given RAW name
* Raw name - name as found on disk, not "display name".
*/
bool dir_find_file_raw(FAT16_FILE* dir, const char* fname)
bool dir_find_file_raw(FFILE* dir, const char* fname)
{
// rewind
fat16_first(dir);
ff_first(dir);
do
{
@ -296,7 +299,7 @@ bool dir_find_file_raw(FAT16_FILE* dir, const char* fname)
return true; // file is already open.
}
}
while (fat16_next(dir));
while (ff_next(dir));
return false;
}
@ -308,7 +311,7 @@ bool dir_find_file_raw(FAT16_FILE* dir, const char* fname)
* dir_cluster ... directory start cluster
* num ... entry number in the directory
*/
void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num)
void open_file(const FAT16* fat, FFILE* file, const uint16_t dir_cluster, const uint16_t num)
{
// Resolve starting address
uint32_t addr;
@ -394,7 +397,7 @@ void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, c
}
// Init cursors
fat16_seek(file, 0);
ff_seek(file, 0);
}
@ -403,7 +406,7 @@ void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, c
* Write information into a file header.
* "file" is an open handle.
*/
void write_file_header(FAT16_FILE* file, const char* fname_raw, const uint8_t attribs, const uint16_t clu_start)
void write_file_header(FFILE* file, const char* fname_raw, const uint8_t attribs, const uint16_t clu_start)
{
const BLOCKDEV* dev = file->fat->dev;
@ -439,9 +442,12 @@ void write_file_header(FAT16_FILE* file, const char* fname_raw, const uint8_t at
// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
/** Initialize a FAT16 handle */
void fat16_init(const BLOCKDEV* dev, FAT16* fat)
bool ff_init(const BLOCKDEV* dev, FAT16* fat)
{
const uint32_t bs_a = find_bs(dev);
if (bs_a == 0) return false;
fat->dev = dev;
read_bs(dev, &(fat->bs), bs_a);
fat->fat_addr = bs_a + (fat->bs.reserved_sectors * 512);
@ -449,6 +455,8 @@ void fat16_init(const BLOCKDEV* dev, FAT16* fat)
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);
return true;
}
@ -456,7 +464,7 @@ void fat16_init(const BLOCKDEV* dev, FAT16* fat)
* Move file cursor to a position relative to file start
* Allows seek past end of file, will allocate new cluster if needed.
*/
bool fat16_seek(FAT16_FILE* file, uint32_t addr)
bool ff_seek(FFILE* file, uint32_t addr)
{
const FAT16* fat = file->fat;
@ -504,7 +512,7 @@ bool fat16_seek(FAT16_FILE* file, uint32_t addr)
* Check if file is a regular file or directory entry.
* Those files can be shown to user.
*/
bool fat16_is_regular(const FAT16_FILE* file)
bool ff_is_regular(const FFILE* file)
{
switch (file->type)
{
@ -522,13 +530,19 @@ bool fat16_is_regular(const FAT16_FILE* file)
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
bool fat16_read(FAT16_FILE* file, void* target, uint32_t len)
uint16_t ff_read(FFILE* file, void* target, uint16_t len)
{
if (file->cur_abs == 0xFFFF)
return false; // file at the end already
return 0; // file at the end already
if (file->cur_rel + len > file->size)
return false; // Attempt to read more than what is available
{
if (file->cur_rel > file->size) return 0;
len = file->size - file->cur_rel;
//return false; // Attempt to read more than what is available
}
const uint16_t len_orig = len;
const FAT16* fat = file->fat;
const BLOCKDEV* dev = fat->dev;
@ -562,18 +576,27 @@ bool fat16_read(FAT16_FILE* file, void* target, uint32_t len)
len -= chunk;
}
return true;
return len_orig;
}
bool ff_write_str(FFILE* file, const char* source)
{
uint16_t len = 0;
for (; source[len] != 0; len++);
return ff_write(file, source, len);
}
bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
bool ff_write(FFILE* file, const void* source, uint32_t len)
{
const FAT16* fat = file->fat;
const BLOCKDEV* dev = fat->dev;
if (file->cur_abs == 0xFFFF)
return false; // file at the end already
return false; // file past it's end (rare)
// Attempt to write past end of file
if (file->cur_rel + len >= file->size)
@ -582,14 +605,14 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
// Seek to the last position
// -> fseek will allocate clusters
if (!fat16_seek(file, pos_start + len))
if (!ff_seek(file, pos_start + len))
return false; // error in seek
// Write starts beyond EOF - creating a zero-filled "hole"
if (file->cur_rel > file->size)
if (pos_start > file->size + 1)
{
// Seek to the end of valid data
fat16_seek(file, file->size);
ff_seek(file, file->size);
// fill space between EOF and start-of-write with zeros
uint32_t fill = pos_start - file->size;
@ -617,31 +640,44 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
}
}
// Save new size
fat16_resize(file, pos_start + len);
// Store new size
file->size = pos_start + len;
// Seek back to where it was before
fat16_seek(file, pos_start);
ff_seek(file, pos_start);
} // (end zerofill)
// write the data
while (len > 0)
{
// How much can be stored in this cluster
const uint16_t chunk = MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len);
// store the chunk
dev->seek(file->cur_abs);
dev->store(source, chunk);
uint16_t chunk;
// advance cursors
file->cur_abs += chunk;
file->cur_rel += chunk;
file->cur_ofs += chunk;
if (len == 1)
{
dev->write(*((uint8_t*)source));
file->cur_abs++;
file->cur_rel++;
file->cur_ofs++;
chunk = 1;
// Pointer arith!
source += chunk; // advance the source pointer
}
else
{
// How much can be stored in this cluster
chunk = MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len);
dev->store(source, chunk);
// advance cursors
file->cur_abs += chunk;
file->cur_rel += chunk;
file->cur_ofs += chunk;
// Pointer arith!
source += chunk; // advance the source pointer
}
// detect cluster overflow
if (file->cur_ofs >= fat->bs.bytes_per_cluster)
@ -662,7 +698,7 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
/** Open next file in the directory */
bool fat16_next(FAT16_FILE* file)
bool ff_next(FFILE* file)
{
const FAT16* fat = file->fat;
const BLOCKDEV* dev = fat->dev;
@ -686,7 +722,7 @@ bool fat16_next(FAT16_FILE* file)
/** Open previous file in the directory */
bool fat16_prev(FAT16_FILE* file)
bool ff_prev(FFILE* file)
{
if (file->num == 0)
return false; // first file already
@ -698,14 +734,14 @@ bool fat16_prev(FAT16_FILE* file)
/** Rewind to first file in directory */
void fat16_first(FAT16_FILE* file)
void ff_first(FFILE* file)
{
open_file(file->fat, file, file->clu, 0);
}
/** Open a directory denoted by the file. */
bool fat16_opendir(FAT16_FILE* dir)
bool ff_opendir(FFILE* dir)
{
// Don't open non-dirs and "." directory.
if (!(dir->attribs & FA_DIR) || dir->type == FT_SELF)
@ -716,7 +752,7 @@ bool fat16_opendir(FAT16_FILE* dir)
}
void fat16_root(const FAT16* fat, FAT16_FILE* file)
void ff_root(const FAT16* fat, FFILE* file)
{
open_file(fat, file, 0, 0);
}
@ -727,16 +763,16 @@ void fat16_root(const FAT16* fat, FAT16_FILE* file)
* 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(FAT16_FILE* dir, const char* name)
bool ff_open(FFILE* dir, const char* name)
{
char fname[11];
fat16_rawname(name, fname);
ff_rawname(name, fname);
return dir_find_file_raw(dir, fname);
}
/** Go through a directory, and "open" first FT_NONE or FT_DELETED file entry. */
bool find_empty_file_slot(FAT16_FILE* file)
bool find_empty_file_slot(FFILE* file)
{
const uint16_t clu = file->clu;
const FAT16* fat = file->fat;
@ -781,15 +817,15 @@ bool find_empty_file_slot(FAT16_FILE* file)
bool fat16_mkfile(FAT16_FILE* file, const char* name)
bool ff_newfile(FFILE* file, const char* name)
{
// Convert filename to zero padded raw string
char fname[11];
fat16_rawname(name, fname);
ff_rawname(name, fname);
// Abort if file already exists
bool exists = dir_find_file_raw(file, fname);
fat16_first(file); // rewind dir
ff_first(file); // rewind dir
if (exists)
return false; // file already exists in the dir.
@ -809,15 +845,15 @@ bool fat16_mkfile(FAT16_FILE* file, const char* name)
* Create a sub-directory of given name.
* Directory is allocated and populated with entries "." and ".."
*/
bool fat16_mkdir(FAT16_FILE* file, const char* name)
bool ff_mkdir(FFILE* file, const char* name)
{
// Convert filename to zero padded raw string
char fname[11];
fat16_rawname(name, fname);
ff_rawname(name, fname);
// Abort if file already exists
bool exists = dir_find_file_raw(file, fname);
fat16_first(file); // rewind dir
ff_first(file); // rewind dir
if (exists)
return false; // file already exusts in the dir.
@ -840,20 +876,20 @@ bool fat16_mkdir(FAT16_FILE* file, const char* name)
write_file_header(file, ".. ", FA_DIR, parent_clu);
// rewind.
fat16_first(file);
ff_first(file);
return true;
}
char* fat16_disk_label(const FAT16* fat, char* label_out)
char* ff_disk_label(const FAT16* fat, char* label_out)
{
FAT16_FILE first;
fat16_root(fat, &first);
FFILE first;
ff_root(fat, &first);
if (first.type == FT_LABEL)
{
return fat16_dispname(&first, label_out);
return ff_dispname(&first, label_out);
}
// find where spaces end
@ -876,7 +912,7 @@ char* fat16_disk_label(const FAT16* fat, char* label_out)
}
char* fat16_dispname(const FAT16_FILE* file, char* disp_out)
char* ff_dispname(const FFILE* file, char* disp_out)
{
// Cannot get name for special files
if (file->type == FT_NONE || // not-yet-used directory location
@ -926,7 +962,7 @@ char* fat16_dispname(const FAT16_FILE* file, char* disp_out)
}
char* fat16_rawname(const char* disp_in, char* raw_out)
char* ff_rawname(const char* disp_in, char* raw_out)
{
uint8_t name_c = 0, wr_c = 0;
bool filling = false;
@ -1000,21 +1036,41 @@ char* fat16_rawname(const char* disp_in, char* raw_out)
}
/** Write new file size (also to the disk). Does not allocate clusters. */
void fat16_resize(FAT16_FILE* file, uint32_t size)
FSAVEPOS ff_savepos(const FFILE* file)
{
FSAVEPOS fsp;
fsp.clu = file->clu;
fsp.num = file->num;
fsp.cur_rel = file->cur_rel;
return fsp;
}
void ff_reopen(FFILE* file, const FSAVEPOS* pos)
{
open_file(file->fat, file, pos->clu, pos->num);
ff_seek(file, pos->cur_rel);
}
void ff_flush_file(FFILE* file)
{
const FAT16* fat = file->fat;
const BLOCKDEV* dev = file->fat->dev;
// Store open page
dev->flush();
// Store file size
// Find address for storing the size
const uint32_t addr = clu_offs(fat, file->clu, file->num * 32 + 28);
file->size = size;
dev->seek(addr);
dev->store(&size, 4);
dev->store(&(file->size), 4);
// Seek to the end of the file, to make sure clusters are allocated
fat16_seek(file, size - 1);
ff_seek(file, file->size - 1);
const uint16_t next = next_clu(fat, file->cur_clu);
if (next != 0xFFFF)
@ -1026,8 +1082,10 @@ void fat16_resize(FAT16_FILE* file, uint32_t size)
}
}
/** Low level no-check file delete and free */
void delete_file_do(FAT16_FILE* file)
void delete_file_do(FFILE* file)
{
const FAT16* fat = file->fat;
@ -1049,7 +1107,7 @@ void delete_file_do(FAT16_FILE* file)
/** Delete a simple file */
bool fat16_rmfile(FAT16_FILE* file)
bool ff_rmfile(FFILE* file)
{
switch (file->type)
{
@ -1068,19 +1126,15 @@ bool fat16_rmfile(FAT16_FILE* file)
/** Delete an empty directory */
bool fat16_rmdir(FAT16_FILE* file)
bool ff_rmdir(FFILE* file)
{
if (file->type != FT_SUBDIR)
return false; // not a subdirectory entry
const FAT16* fat = file->fat;
const uint16_t clu1 = file->clu;
const uint16_t num1 = file->num;
const FSAVEPOS orig = ff_savepos(file);
// Open the subdir
if (!fat16_opendir(file))
if (!ff_opendir(file))
return false; // could not open
// Look for valid files and subdirs in the directory
@ -1097,16 +1151,16 @@ bool fat16_rmdir(FAT16_FILE* file)
{
// Valid child file was found, aborting.
// reopen original file
open_file(fat, file, clu1, num1);
ff_reopen(file, &orig);
return false;
}
if (cnt < 2) cnt++;
}
while (fat16_next(file));
while (ff_next(file));
// reopen original file
open_file(fat, file, clu1, num1);
ff_reopen(file, &orig);
// and delete as ordinary file
delete_file_do(file);
@ -1115,7 +1169,7 @@ bool fat16_rmdir(FAT16_FILE* file)
}
bool fat16_delete(FAT16_FILE* file)
bool ff_delete(FFILE* file)
{
switch (file->type)
{
@ -1126,8 +1180,7 @@ bool fat16_delete(FAT16_FILE* file)
case FT_SUBDIR:; // semicolon needed to allow declaration after "case"
// store original file location
const uint16_t clu1 = file->clu;
const uint16_t num1 = file->num;
const FSAVEPOS orig = ff_savepos(file);
// open the directory (skip "." and "..")
open_file(file->fat, file, file->clu_start, 2);
@ -1135,34 +1188,32 @@ bool fat16_delete(FAT16_FILE* file)
// delete all children
do
{
if (!fat16_delete(file))
if (!ff_delete(file))
{
// failure
// reopen original file
open_file(file->fat, file, clu1, num1);
ff_reopen(file, &orig);
return false;
}
}
while (fat16_next(file));
while (ff_next(file));
// go up and delete the dir
open_file(file->fat, file, clu1, num1);
return fat16_rmdir(file);
ff_reopen(file, &orig);
return ff_rmdir(file);
default:
// try to delete as a regular file
return fat16_rmfile(file);
return ff_rmfile(file);
}
}
bool fat16_parent(FAT16_FILE* file)
bool ff_parent(FFILE* file)
{
const uint16_t clu1 = file->clu;
const uint16_t num1 = file->num;
// open second entry of the directory
open_file(file->fat, file, file->clu, 1);
const FSAVEPOS orig = ff_savepos(file);
// if it's a valid PARENT link, follow it.
if (file->type == FT_PARENT)
@ -1174,7 +1225,7 @@ bool fat16_parent(FAT16_FILE* file)
{
// in root already?
// reopen original file
open_file(file->fat, file, clu1, num1);
ff_reopen(file, &orig);
return false;
}
}

@ -1,28 +1,16 @@
#pragma once
//
// Simple FAT16 library.
//
// To use it, implement BLOCKDEV functions
// and attach them to it's instance.
//
#include <stdint.h>
#include <stdbool.h>
/**
* Abstract block device interface
*
* Populate this with pointers to your I/O functions.
*/
typedef struct
{
// Sequential read
void (*load)(void* dest, const uint16_t len);
// Sequential write
void (*store)(const void* src, const uint16_t len);
// Sequential byte write
void (*write)(const uint8_t b);
// Sequential byte read
uint8_t (*read)(void);
// Absolute seek
void (*seek)(const uint32_t);
// Relative seek
void (*rseek)(const int16_t);
} BLOCKDEV;
#include "blockdev.h"
// -------------------------------
@ -45,6 +33,15 @@ typedef enum
} FAT16_FT;
/** "File address" for saving and restoring file */
typedef struct
{
uint16_t clu;
uint16_t num;
uint32_t cur_rel;
} FSAVEPOS;
// Include definitions of fully internal structs
#include "fat16_internal.h"
@ -102,11 +99,31 @@ typedef struct __attribute__((packed))
// Pointer to the FAT16 handle. (internal)
const FAT16* fat;
}
FAT16_FILE;
FFILE;
/** Initialize the file system - store into "fat" */
void fat16_init(const BLOCKDEV* dev, FAT16* fat);
/**
* Store modified file metadata and flush it to disk.
*/
void ff_flush_file(FFILE* file);
/**
* Save a file "position" into a struct, for later restoration.
* Cursor is also saved.
*/
FSAVEPOS ff_savepos(const FFILE* file);
/**
* Restore a file from a saved position.
*/
void ff_reopen(FFILE* file, const FSAVEPOS* pos);
/**
* Initialize the file system - store into "fat"
*/
bool ff_init(const BLOCKDEV* dev, FAT16* fat);
/**
@ -114,14 +131,17 @@ void fat16_init(const BLOCKDEV* dev, FAT16* fat);
* The file may be invalid (eg. a volume label, deleted etc),
* or blank (type FT_NONE) if the filesystem is empty.
*/
void fat16_root(const FAT16* fat, FAT16_FILE* file);
void ff_root(const FAT16* fat, FFILE* file);
/**
* Resolve the disk label.
* That can be in the Boot Sector, or in the first root directory entry.
*
* @param fat the FAT handle
* @param label_out string to store the label in. Should have at least 12 bytes.
*/
char* fat16_disk_label(const FAT16* fat, char* label_out);
char* ff_disk_label(const FAT16* fat, char* label_out);
// ----------- FILE I/O -------------
@ -131,21 +151,26 @@ char* fat16_disk_label(const FAT16* fat, char* label_out);
* Move file cursor to a position relative to file start
* Returns false on I/O error (bad file, out of range...)
*/
bool fat16_seek(FAT16_FILE* file, uint32_t addr);
bool ff_seek(FFILE* file, uint32_t addr);
/**
* Read bytes from file into memory
* Returns false on I/O error (bad file, out of range...)
* Returns number of bytes read, 0 on error.
*/
bool fat16_read(FAT16_FILE* file, void* target, uint32_t len);
uint16_t ff_read(FFILE* file, void* target, uint16_t len);
/**
* Write into file at a "seek" position.
* "seek" cursor must be within (0..filesize)
*/
bool fat16_write(FAT16_FILE* file, void* source, uint32_t len);
bool ff_write(FFILE* file, const void* source, uint32_t len);
/**
* Store a 0-terminated string at cursor.
*/
bool ff_write_str(FFILE* file, const char* source);
/**
@ -154,14 +179,14 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len);
* file ... open directory; new file is opened into this handle.
* name ... name of the new file, including extension
*/
bool fat16_mkfile(FAT16_FILE* file, const char* name);
bool ff_newfile(FFILE* file, const char* name);
/**
* Create a sub-directory of given name.
* Directory is allocated and populated with entries "." and ".."
*/
bool fat16_mkdir(FAT16_FILE* file, const char* name);
bool ff_mkdir(FFILE* file, const char* name);
/**
@ -170,26 +195,26 @@ bool fat16_mkdir(FAT16_FILE* file, const char* name);
*
* Useful mainly for shrinking.
*/
void fat16_resize(FAT16_FILE* file, uint32_t size);
void set_file_size(FFILE* file, uint32_t size);
/**
* Delete a *FILE* and free it's clusters.
*/
bool fat16_rmfile(FAT16_FILE* file);
bool ff_rmfile(FFILE* file);
/**
* Delete an empty *DIRECTORY* and free it's clusters.
*/
bool fat16_rmdir(FAT16_FILE* file);
bool ff_rmdir(FFILE* file);
/**
* Delete a file or directory, even FT_LFN and FT_INVALID.
* Directories are deleted recursively (!)
*/
bool fat16_delete(FAT16_FILE* file);
bool ff_delete(FFILE* file);
@ -197,55 +222,55 @@ bool fat16_delete(FAT16_FILE* file);
/** Go to previous file in the directory (false = no prev file) */
bool fat16_prev(FAT16_FILE* file);
bool ff_prev(FFILE* file);
/** Go to next file in directory (false = no next file) */
bool fat16_next(FAT16_FILE* file);
bool ff_next(FFILE* file);
/**
* Open a subdirectory denoted by the file.
* Provided handle changes to the first entry of the directory.
*/
bool fat16_opendir(FAT16_FILE* dir);
bool ff_opendir(FFILE* dir);
/**
* Open a parent directory. Fails in root.
* Provided handle changes to the first entry of the parent directory.
*/
bool fat16_parent(FAT16_FILE* file);
bool ff_parent(FFILE* file);
/** Jump to first file in this directory */
void fat16_first(FAT16_FILE* file);
void ff_first(FFILE* file);
/**
* Find a file with given "display name" in this directory.
* Find a file with given "display name" in this directory, and open it.
* If file is found, "dir" will contain it's handle.
* If file is NOT found, the handle points to the last entry of the directory.
*/
bool fat16_find(FAT16_FILE* dir, const char* name);
bool ff_open(FFILE* dir, const char* name);
// -------- FILE INSPECTION -----------
/** Check if file is a valid entry, or long-name/label/deleted */
bool fat16_is_regular(const FAT16_FILE* file);
bool ff_is_regular(const FFILE* file);
/**
* Resolve a file name, trim spaces and add null terminator.
* Returns the passed char*, or NULL on error.
*/
char* fat16_dispname(const FAT16_FILE* file, char* disp_out);
char* ff_dispname(const FFILE* file, char* disp_out);
/**
* Convert filename to zero-padded fixed length one
* Returns the passed char*.
*/
char* fat16_rawname(const char* disp_in, char* raw_out);
char* ff_rawname(const char* disp_in, char* raw_out);

@ -9,7 +9,6 @@
/** Boot Sector structure */
typedef struct __attribute__((packed))
{
// Fields loaded directly from disk:
// 13 bytes skipped

@ -81,26 +81,26 @@ int main()
// Initialize the FS
FAT16 fat;
fat16_init(&test, &fat);
ff_init(&test, &fat);
FAT16_FILE file;
fat16_root(&fat, &file);
FFILE file;
ff_root(&fat, &file);
char str[12];
printf("Disk label: %s\n", fat16_disk_label(&fat, str));
printf("Disk label: %s\n", ff_disk_label(&fat, str));
do
{
if (!fat16_is_regular(&file))
if (!ff_is_regular(&file))
continue;
printf("File name: %s, %c, %d B, @ 0x%x\n",
fat16_dispname(&file, str),
ff_dispname(&file, str),
file.type, file.size, file.clu_start);
}
while (fat16_next(&file));
while (ff_next(&file));
// fat16_root(&fat, &file);

Loading…
Cancel
Save