|
|
|
@ -1,6 +1,10 @@ |
|
|
|
|
#pragma once |
|
|
|
|
|
|
|
|
|
/** Abstract block device interface */ |
|
|
|
|
/**
|
|
|
|
|
* Abstract block device interface |
|
|
|
|
* |
|
|
|
|
* Populate this with pointers to your I/O functions. |
|
|
|
|
*/ |
|
|
|
|
typedef struct |
|
|
|
|
{ |
|
|
|
|
// Sequential read
|
|
|
|
@ -20,7 +24,10 @@ typedef struct |
|
|
|
|
|
|
|
|
|
// -------------------------------
|
|
|
|
|
|
|
|
|
|
/** file types (values don't matter) */ |
|
|
|
|
/**
|
|
|
|
|
* File types (values can be used for debug printing). |
|
|
|
|
* Accessible using file->type |
|
|
|
|
*/ |
|
|
|
|
typedef enum |
|
|
|
|
{ |
|
|
|
|
FT_NONE = '-', |
|
|
|
@ -29,102 +36,73 @@ typedef enum |
|
|
|
|
FT_PARENT = 'P', |
|
|
|
|
FT_LABEL = 'L', |
|
|
|
|
FT_LFN = '~', |
|
|
|
|
FT_INVALID = 'i', // not recognized weird file
|
|
|
|
|
FT_INVALID = '?', // not recognized weird file
|
|
|
|
|
FT_SELF = '.', |
|
|
|
|
FT_FILE = 'F' |
|
|
|
|
} FAT16_FT; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// File Attributes (bit flags)
|
|
|
|
|
#define FA_READONLY 0x01 // read only file
|
|
|
|
|
#define FA_HIDDEN 0x02 // hidden file
|
|
|
|
|
#define FA_SYSTEM 0x04 // system file
|
|
|
|
|
#define FA_LABEL 0x08 // volume label entry, found only in root directory.
|
|
|
|
|
#define FA_DIR 0x10 // subdirectory
|
|
|
|
|
#define FA_ARCHIVE 0x20 // archive flag
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Boot Sector structure - INTERNAL! */ |
|
|
|
|
typedef struct __attribute__((packed)) |
|
|
|
|
{ |
|
|
|
|
// Include definitions of fully internal structs
|
|
|
|
|
#include "fat16_internal.h" |
|
|
|
|
|
|
|
|
|
// Fields loaded directly from disk:
|
|
|
|
|
|
|
|
|
|
// 13 bytes skipped
|
|
|
|
|
uint8_t sectors_per_cluster; |
|
|
|
|
uint16_t reserved_sectors; |
|
|
|
|
uint8_t num_fats; |
|
|
|
|
uint16_t root_entries; |
|
|
|
|
// 3 bytes skipped
|
|
|
|
|
uint16_t fat_size_sectors; |
|
|
|
|
// 8 bytes skipped
|
|
|
|
|
uint32_t total_sectors; // if "short size sectors" is used, it's copied here too
|
|
|
|
|
// 7 bytes skipped
|
|
|
|
|
char volume_label[11]; // space padded, no terminator
|
|
|
|
|
|
|
|
|
|
// Added fields:
|
|
|
|
|
|
|
|
|
|
uint32_t bytes_per_cluster; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
Fat16BootSector; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** FAT filesystem handle - private fields! */ |
|
|
|
|
/**
|
|
|
|
|
* File handle struct. |
|
|
|
|
* |
|
|
|
|
* File handle contains cursor, file name, type, size etc. |
|
|
|
|
* Everything (files, dirs) is accessed using this. |
|
|
|
|
*/ |
|
|
|
|
typedef struct __attribute__((packed)) |
|
|
|
|
{ |
|
|
|
|
// Backing block device
|
|
|
|
|
const BLOCKDEV* dev; |
|
|
|
|
|
|
|
|
|
// Root directory sector start
|
|
|
|
|
uint32_t rd_addr; |
|
|
|
|
|
|
|
|
|
// Start of first cluster (number "2")
|
|
|
|
|
uint32_t data_addr; |
|
|
|
|
|
|
|
|
|
// Start of fat table
|
|
|
|
|
uint32_t fat_addr; |
|
|
|
|
/**
|
|
|
|
|
* Raw file name. Starting 0x05 was converted to 0xE5. |
|
|
|
|
* To get PRINTABLE file name, use fat16_dispname() |
|
|
|
|
*/ |
|
|
|
|
uint8_t name[11]; |
|
|
|
|
|
|
|
|
|
// Boot sector data struct
|
|
|
|
|
Fat16BootSector bs; |
|
|
|
|
} |
|
|
|
|
FAT16; |
|
|
|
|
/**
|
|
|
|
|
* File attributes - bit field composed of FA_* flags |
|
|
|
|
* (internal) |
|
|
|
|
*/ |
|
|
|
|
uint8_t attribs; |
|
|
|
|
|
|
|
|
|
// 14 bytes skipped (10 reserved, date, time)
|
|
|
|
|
|
|
|
|
|
/** File handle struct */ |
|
|
|
|
typedef struct __attribute__((packed)) |
|
|
|
|
{ |
|
|
|
|
// Fields loaded directly from disk:
|
|
|
|
|
|
|
|
|
|
uint8_t name[11]; // Starting 0x05 converted to 0xE5, other "magic chars" left intact
|
|
|
|
|
uint8_t attribs; // composed of FA_* constants
|
|
|
|
|
// 14 bytes skipped
|
|
|
|
|
/** First cluster of the file. (internal) */ |
|
|
|
|
uint16_t clu_start; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* File size in bytes. |
|
|
|
|
* This is the current allocated and readable file size. |
|
|
|
|
*/ |
|
|
|
|
uint32_t size; |
|
|
|
|
|
|
|
|
|
// Added fields:
|
|
|
|
|
|
|
|
|
|
// --- the following fields are added when reading ---
|
|
|
|
|
|
|
|
|
|
/** File type. */ |
|
|
|
|
FAT16_FT type; |
|
|
|
|
|
|
|
|
|
// --- Private fields ---
|
|
|
|
|
|
|
|
|
|
// Cursor
|
|
|
|
|
// --- INTERNAL FIELDS ---
|
|
|
|
|
|
|
|
|
|
// Cursor variables. (internal)
|
|
|
|
|
uint32_t cur_abs; // absolute position in device
|
|
|
|
|
uint32_t cur_rel; // relative position in file
|
|
|
|
|
uint16_t cur_clu; // cluster where the cursor is
|
|
|
|
|
uint16_t cur_ofs; // offset within the active cluster
|
|
|
|
|
|
|
|
|
|
// File position in the directory
|
|
|
|
|
// File position in the directory. (internal)
|
|
|
|
|
uint16_t clu; // first cluster of directory
|
|
|
|
|
uint16_t num; // fiel entry number
|
|
|
|
|
uint16_t num; // file entry number
|
|
|
|
|
|
|
|
|
|
// pointer to FAT
|
|
|
|
|
// Pointer to the FAT16 handle. (internal)
|
|
|
|
|
const FAT16* fat; |
|
|
|
|
} |
|
|
|
|
FAT16_FILE; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Initialize a filesystem */ |
|
|
|
|
/** Initialize the file system - store into "fat" */ |
|
|
|
|
void fat16_init(const BLOCKDEV* dev, FAT16* fat); |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -132,14 +110,13 @@ void fat16_init(const BLOCKDEV* dev, FAT16* fat); |
|
|
|
|
* Open the first file of the root directory. |
|
|
|
|
* The file may be invalid (eg. a volume label, deleted etc), |
|
|
|
|
* or blank (type FT_NONE) if the filesystem is empty. |
|
|
|
|
* |
|
|
|
|
* Either way, the prev and next functions will work as expected. |
|
|
|
|
*/ |
|
|
|
|
void fat16_root(const FAT16* fat, FAT16_FILE* file); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Resolve the disk label. |
|
|
|
|
* That can be in the Boot Sector, or in the first root directory entry. |
|
|
|
|
*/ |
|
|
|
|
char* fat16_disk_label(const FAT16* fat, char* label_out); |
|
|
|
|
|
|
|
|
@ -185,29 +162,29 @@ bool fat16_mkdir(FAT16_FILE* file, const char* name); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write new file size (also to the disk). |
|
|
|
|
* Allocates / frees needed clusters, does not erase them. |
|
|
|
|
* Set new file size. |
|
|
|
|
* Allocates / frees needed clusters, does NOT erase them. |
|
|
|
|
* |
|
|
|
|
* Useful mainly for shrinking. |
|
|
|
|
*/ |
|
|
|
|
void fat16_resize(FAT16_FILE* file, uint32_t size); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete a file entry and free clusters. |
|
|
|
|
* Does NOT work on folders. |
|
|
|
|
* Delete a *FILE* and free it's clusters. |
|
|
|
|
*/ |
|
|
|
|
bool fat16_rmfile(FAT16_FILE* file); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete an empty directory. |
|
|
|
|
* Calling with non-subfolder entry or non-empty directory will cause error. |
|
|
|
|
* Delete an empty *DIRECTORY* and free it's clusters. |
|
|
|
|
*/ |
|
|
|
|
bool fat16_rmdir(FAT16_FILE* file); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete a file or directory, regardless of type. |
|
|
|
|
* Directories are deleted recursively. |
|
|
|
|
* Delete a file or directory, even FT_LFN and FT_INVALID. |
|
|
|
|
* Directories are deleted recursively (!) |
|
|
|
|
*/ |
|
|
|
|
bool fat16_delete(FAT16_FILE* file); |
|
|
|
|
|
|
|
|
@ -226,17 +203,19 @@ bool fat16_next(FAT16_FILE* file); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Open a subdirectory denoted by the file. |
|
|
|
|
* Provided handle changes to first entry of the directory. |
|
|
|
|
* Provided handle changes to the first entry of the directory. |
|
|
|
|
*/ |
|
|
|
|
bool fat16_opendir(FAT16_FILE* file); |
|
|
|
|
bool fat16_opendir(FAT16_FILE* 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); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Rewind to first file in directory */ |
|
|
|
|
/** Jump to first file in this directory */ |
|
|
|
|
void fat16_first(FAT16_FILE* file); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|