Added more documentation for file system
This commit is contained in:
parent
8df9742b25
commit
3c68904970
149
lib/fs/fat32.c
149
lib/fs/fat32.c
@ -8,7 +8,7 @@
|
||||
#include <time.h>
|
||||
|
||||
// NOTE rueegges: uncomment to enable fat32 performance measurements
|
||||
#define FAT32_PERFORMANCE
|
||||
// #define FAT32_PERFORMANCE
|
||||
#ifdef FAT32_PERFORMANCE
|
||||
#include <aos/performance.h>
|
||||
static struct performance_context fat32_perf_context;
|
||||
@ -60,11 +60,20 @@ static uint8_t fat32_get_active_fat(struct fat32 *fat32) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t fat32_lock_id_from_directory_entry_ref(struct fat32_directory_entry_ref directory_entry_ref) {
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param directory_entry_ref reference to the directory entry that we want to get an id for
|
||||
* @return uint64_t unique identifier for the directory entry referenced
|
||||
*/
|
||||
static uint64_t fat32_id_from_directory_entry_ref(struct fat32_directory_entry_ref directory_entry_ref) {
|
||||
// there can never be this many directory entries in a sector
|
||||
return ((uint64_t)directory_entry_ref.sector_number << 32) | directory_entry_ref.index_in_sector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief given a cluster number calculate information about where in the FAT this entry is located
|
||||
*/
|
||||
static void fat32_fat_entry_parameters(struct fat32 *fat32, uint32_t cluster_number, uint32_t *fat_sector_num, uint32_t *fat_sector_offset) {
|
||||
uint8_t fat_index = fat32_get_active_fat(fat32);
|
||||
uint32_t fat_offset = cluster_number * 4;
|
||||
@ -72,6 +81,9 @@ static void fat32_fat_entry_parameters(struct fat32 *fat32, uint32_t cluster_num
|
||||
*fat_sector_offset = fat_offset % fat32->bytes_per_sector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set all bytes of all sectors of a cluster to zero
|
||||
*/
|
||||
static errval_t fat32_zero_cluster(struct fat32 *fat32, uint32_t cluster_number) {
|
||||
errval_t err;
|
||||
|
||||
@ -93,6 +105,9 @@ static errval_t fat32_zero_cluster(struct fat32 *fat32, uint32_t cluster_number)
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write to en entry given by the cluster number in the FAT
|
||||
*/
|
||||
static errval_t fat32_fat_write_entry(struct fat32 *fat32, uint32_t cluster_number, uint32_t entry) {
|
||||
errval_t err;
|
||||
|
||||
@ -114,6 +129,10 @@ static errval_t fat32_fat_write_entry(struct fat32 *fat32, uint32_t cluster_numb
|
||||
}
|
||||
|
||||
static errval_t fat32_next_cluster_in_chain(struct fat32 *fat32, uint32_t cluster_number, uint32_t *return_next_cluster_number);
|
||||
/**
|
||||
* @brief find a free cluster number and store the end of chain mark so it is not seen as free anymore
|
||||
* @param return_cluster_number the free cluster if it was found
|
||||
*/
|
||||
static errval_t fat32_alloc_cluster(struct fat32 *fat32, uint32_t *return_cluster_number) {
|
||||
errval_t err;
|
||||
|
||||
@ -151,6 +170,9 @@ static errval_t fat32_alloc_cluster(struct fat32 *fat32, uint32_t *return_cluste
|
||||
}
|
||||
|
||||
__attribute__((__used__))
|
||||
/**
|
||||
* @brief free a cluster by writing zero to its entry in the FAT
|
||||
*/
|
||||
static errval_t fat32_free_cluster(struct fat32 *fat32, uint32_t cluster_number) {
|
||||
errval_t err;
|
||||
|
||||
@ -171,6 +193,9 @@ static errval_t fat32_free_cluster(struct fat32 *fat32, uint32_t cluster_number)
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief add the given cluster to the end of the given chain tail
|
||||
*/
|
||||
static errval_t fat32_extend_cluster_chain(struct fat32 *fat32, uint32_t current_tail_cluster_number, uint32_t new_tail_cluster_number) {
|
||||
errval_t err;
|
||||
|
||||
@ -193,6 +218,9 @@ static errval_t fat32_extend_cluster_chain(struct fat32 *fat32, uint32_t current
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the next cluster in the chain by reading the value for the current cluster in the FAT
|
||||
*/
|
||||
static errval_t fat32_next_cluster_in_chain(struct fat32 *fat32, uint32_t cluster_number, uint32_t *return_next_cluster_number) {
|
||||
errval_t err;
|
||||
|
||||
@ -214,6 +242,9 @@ static errval_t fat32_next_cluster_in_chain(struct fat32 *fat32, uint32_t cluste
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief try to get the next cluster in the chain. If there is none then extend the chain.
|
||||
*/
|
||||
static errval_t fat32_next_cluster_in_chain_or_extend(struct fat32 *fat32, uint32_t cluster_number, uint32_t *return_next_cluster_number) {
|
||||
errval_t err;
|
||||
|
||||
@ -243,6 +274,11 @@ static errval_t fat32_next_cluster_in_chain_or_extend(struct fat32 *fat32, uint3
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free all clusters in the chain starting at the first_cluster
|
||||
|
||||
* @param first_cluster first cluster in the chain to be freed
|
||||
*/
|
||||
static errval_t fat32_free_cluster_chain(struct fat32 *fat32, uint32_t first_cluster) {
|
||||
errval_t err;
|
||||
|
||||
@ -285,6 +321,12 @@ static bool fat32_name_is_dotdot(const char *short_name, const char *short_name_
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief turn the weird short_name and short_name_ext fields of a directory entry into a beautiful name
|
||||
*
|
||||
* @param directory_entry entry for which we want the nice name
|
||||
* @return char* memory allocated using malloc containing the nice name or NULL if malloc failed
|
||||
*/
|
||||
static char* fat32_directory_entry_get_nice_name(struct fat32_directory_entry *directory_entry){
|
||||
// get length of short_name by searching for first space
|
||||
// NOTE rueegges: short_name is not allowed to contain spaces
|
||||
@ -303,6 +345,7 @@ static char* fat32_directory_entry_get_nice_name(struct fat32_directory_entry *d
|
||||
|
||||
// allocate output name and copy data
|
||||
char *name = malloc(name_len);
|
||||
if (name == NULL) return NULL;
|
||||
memcpy(name, directory_entry->short_name, short_name_len);
|
||||
if (short_name_ext_len > 0) {
|
||||
name[short_name_len] = '.';
|
||||
@ -324,7 +367,15 @@ static char* fat32_directory_entry_get_nice_name(struct fat32_directory_entry *d
|
||||
return name;
|
||||
}
|
||||
|
||||
// returns true -> if anything was left of the path, false -> nothing was left or for example only '/'
|
||||
/**
|
||||
* @brief Get the next element of a path. elements are separated with one or more FS_PATH_SEP. Checks for validity of path elements
|
||||
*
|
||||
* @param path_cursor where to start looking for the next element
|
||||
* @param path_end first byte that should not be looked at anymore
|
||||
* @param return_path_cursor where in the path we ended up after extracting the next element
|
||||
* @param return_short_name location to save the short name extracted
|
||||
* @param return_short_name_ext location to save the short name extension extracted
|
||||
*/
|
||||
static errval_t fat32_extract_next_path_element(
|
||||
const char *path_cursor,
|
||||
const char *path_end,
|
||||
@ -422,6 +473,7 @@ static errval_t fat32_extract_next_path_element(
|
||||
}
|
||||
}
|
||||
|
||||
// return the position we ended up in
|
||||
if (return_path_cursor != NULL) {
|
||||
*return_path_cursor = path_cursor;
|
||||
}
|
||||
@ -429,6 +481,9 @@ static errval_t fat32_extract_next_path_element(
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the directory entry identified by the given reference from disk
|
||||
*/
|
||||
static errval_t fat32_read_directory_entry(
|
||||
struct fat32 *fat32,
|
||||
struct fat32_directory_entry_ref directory_entry_ref,
|
||||
@ -441,6 +496,9 @@ static errval_t fat32_read_directory_entry(
|
||||
directory_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the directory entry identified by the given reference to disk
|
||||
*/
|
||||
static errval_t fat32_write_directory_entry(
|
||||
struct fat32 *fat32,
|
||||
struct fat32_directory_entry_ref directory_entry_ref,
|
||||
@ -455,6 +513,9 @@ static errval_t fat32_write_directory_entry(
|
||||
directory_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief try to find a free directory entry in the given directory. If there is no free entry left then we extend the cluster chain
|
||||
*/
|
||||
static errval_t fat32_allocate_directory_entry(
|
||||
struct fat32 *fat32,
|
||||
struct fat32_directory_entry *search_directory,
|
||||
@ -500,6 +561,9 @@ static errval_t fat32_allocate_directory_entry(
|
||||
USER_PANIC("This code should be unreachable");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief try to free a directory entry by writing 0xE5 to the first byte of the shortname. if there are open handles for the given directory entry then we fail.
|
||||
*/
|
||||
static errval_t fat32_free_directory_entry(struct fat32 *fat32, struct fat32_directory_entry_ref directory_entry_ref) {
|
||||
errval_t err;
|
||||
|
||||
@ -509,7 +573,7 @@ static errval_t fat32_free_directory_entry(struct fat32 *fat32, struct fat32_dir
|
||||
|
||||
// if the directory entry is still opened by someone we cannot delete it yet
|
||||
size_t handler_count;
|
||||
err = fat32->count_handles_fn(fat32_lock_id_from_directory_entry_ref(directory_entry_ref), &handler_count);
|
||||
err = fat32->count_handles_fn(fat32_id_from_directory_entry_ref(directory_entry_ref), &handler_count);
|
||||
if(err_is_fail(err)) return err;
|
||||
if(handler_count > 0) return FAT_ERR_OPENED;
|
||||
|
||||
@ -526,6 +590,9 @@ static errval_t fat32_free_directory_entry(struct fat32 *fat32, struct fat32_dir
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief look for a directory entry with the given name inside the given directory
|
||||
*/
|
||||
static errval_t fat32_search_in_directory(
|
||||
struct fat32 *fat32,
|
||||
struct fat32_directory_entry *search_directory,
|
||||
@ -596,7 +663,9 @@ static errval_t fat32_search_in_directory(
|
||||
return FS_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief check if a directory is empty. Does not ignore hidden entries
|
||||
*/
|
||||
static errval_t fat32_check_directory_empty(
|
||||
struct fat32 *fat32,
|
||||
struct fat32_directory_entry *search_directory
|
||||
@ -647,6 +716,9 @@ static errval_t fat32_check_directory_empty(
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check if the path starts with the mount string and if so calculate the position in the path right after the mount
|
||||
*/
|
||||
static errval_t fat32_skip_mount_point(struct fat32 *fat32, const char *path, const char **result_path) {
|
||||
// remove the mount point from the path. This is a very simple approach
|
||||
// if the path is shorter than the mount point then we have nothing to show
|
||||
@ -664,6 +736,11 @@ static errval_t fat32_skip_mount_point(struct fat32 *fat32, const char *path, co
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to resolve the given path to a directory entry reference.
|
||||
* Allows resolving a path up to a specific point.
|
||||
* This way we don't have to copy the path string to get the parent directory during mkdir and fcreate.
|
||||
*/
|
||||
static errval_t fat32_resolve_path_partial(
|
||||
struct fat32 *fat32,
|
||||
const char *path,
|
||||
@ -728,14 +805,7 @@ static errval_t fat32_resolve_path_partial(
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param fat32
|
||||
* @param path
|
||||
* @param return_directory_entry directory entry that was found
|
||||
* @param return_parent_sector_number zero if we are in the root directory
|
||||
* @param return_parent_directory_number undefined if the result is the root directory
|
||||
* @return errval_t
|
||||
* @brief try to resolve the given path to a directory entry reference
|
||||
*/
|
||||
static errval_t fat32_resolve_path(
|
||||
struct fat32 *fat32,
|
||||
@ -746,6 +816,9 @@ static errval_t fat32_resolve_path(
|
||||
}
|
||||
|
||||
__attribute__((__used__))
|
||||
/**
|
||||
* @brief get the point in the string where the last element of the path starts
|
||||
*/
|
||||
static errval_t fat32_find_basename(const char *path, const char **basename) {
|
||||
assert(path != NULL);
|
||||
assert(basename != NULL);
|
||||
@ -763,15 +836,15 @@ static errval_t fat32_find_basename(const char *path, const char **basename) {
|
||||
// pass over the basename
|
||||
while (path_end >= path && *path_end != FS_PATH_SEP) --path_end;
|
||||
|
||||
// pass over preceding separators
|
||||
// while (path_end >= path && *path_end == FS_PATH_SEP) --path_end;
|
||||
|
||||
// plus one because we don't want the preceding slash in the basename
|
||||
*basename = path_end + 1;
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief create a new handle and register it with the block driver
|
||||
*/
|
||||
static errval_t fat32_create_handle(struct fat32 *fat32, struct fat32_handle **handle, bool is_dir, uint32_t first_cluster, struct fat32_directory_entry_ref directory_entry_ref) {
|
||||
assert(first_cluster > 1);
|
||||
|
||||
@ -786,16 +859,19 @@ static errval_t fat32_create_handle(struct fat32 *fat32, struct fat32_handle **h
|
||||
(*handle)->byte_offset = 0;
|
||||
(*handle)->directory_entry_ref = directory_entry_ref;
|
||||
|
||||
err = fat32->register_handle_fn(fat32_lock_id_from_directory_entry_ref(directory_entry_ref));
|
||||
err = fat32->register_handle_fn(fat32_id_from_directory_entry_ref(directory_entry_ref));
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief free the given handle and unregister it with the block driver
|
||||
*/
|
||||
static errval_t fat32_free_handle(struct fat32 *fat32, struct fat32_handle *handle) {
|
||||
errval_t err;
|
||||
|
||||
err = fat32->unregister_handle_fn(fat32_lock_id_from_directory_entry_ref(handle->directory_entry_ref));
|
||||
err = fat32->unregister_handle_fn(fat32_id_from_directory_entry_ref(handle->directory_entry_ref));
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
free(handle);
|
||||
@ -840,6 +916,9 @@ static void fat32_verify(struct bpb *bpb){
|
||||
}
|
||||
|
||||
__attribute__((__unused__))
|
||||
/**
|
||||
* @brief print some information about the file system useful for early debugging
|
||||
*/
|
||||
static void fat32_print(struct bpb *bpb){
|
||||
struct bpb_fat32 *fat32 = &bpb->bpb_fat.bpb_fat32;
|
||||
|
||||
@ -876,7 +955,11 @@ static void fat32_print(struct bpb *bpb){
|
||||
}
|
||||
}
|
||||
|
||||
// authors are very strict that it MUST be done exactly this way so here we go
|
||||
//
|
||||
/**
|
||||
* @brief Check if the file system is FAT32.
|
||||
* The authors of the FAT32 specification are very strict that it MUST be done exactly this way so here we go.
|
||||
*/
|
||||
static bool is_fat32(struct bpb *bpb) {
|
||||
debug_printf("[is_fat32] check fat type\n");
|
||||
uint32_t root_dir_sectors = ((bpb->root_entry_count * 32) + (bpb->bytes_per_sector - 1)) / bpb->bytes_per_sector;
|
||||
@ -975,7 +1058,6 @@ errval_t fat32_init(
|
||||
|
||||
static errval_t _fat32_mkdir(struct fat32 *fat32, const char *path) {
|
||||
// debug_printf("[fat32_mkdir]\n");
|
||||
// resolve path to directory cluster
|
||||
errval_t err;
|
||||
|
||||
// split the path into the part that should exist and the part to create
|
||||
@ -1063,6 +1145,7 @@ static errval_t _fat32_mkdir(struct fat32 *fat32, const char *path) {
|
||||
.write_time = write_time,
|
||||
};
|
||||
|
||||
// store the dot and dotdot entries to disk
|
||||
struct fat32_directory_entry_ref ref = {
|
||||
.sector_number = fat32_first_sector_of_cluster(fat32, free_cluster_number),
|
||||
};
|
||||
@ -1086,6 +1169,7 @@ static errval_t _fat32_mkdir(struct fat32 *fat32, const char *path) {
|
||||
err = fat32_extract_next_path_element(basename, basename + strlen(basename), NULL, directory_entry.short_name, directory_entry.short_name_ext);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// store the new directory entry to disk
|
||||
err = fat32_write_directory_entry(fat32, free_path_resolve_result.directory_entry_ref, &directory_entry);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
@ -1118,6 +1202,7 @@ static errval_t _fat32_opendir(struct fat32 *fat32, const char *path, struct fat
|
||||
err = fat32_resolve_path(fat32, path, &path_resolve_result);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// check that it is a directory and not a file
|
||||
if (!(path_resolve_result.directory_entry.attributes & FAT32_ATTR_DIRECTORY)) {
|
||||
return FS_ERR_NOTDIR;
|
||||
}
|
||||
@ -1163,7 +1248,7 @@ static errval_t _fat32_stat(struct fat32 *fat32, struct fat32_handle *handle, st
|
||||
|
||||
if (handle->is_dir) {
|
||||
fileinfo->type = FS_DIRECTORY;
|
||||
// TODO rueegges: somehow get directory sizes?
|
||||
// NOTE rueegges: This should probably be changed to sum over all files in subtree or similar
|
||||
fileinfo->size = 0;
|
||||
} else {
|
||||
struct fat32_directory_entry directory_entry;
|
||||
@ -1191,6 +1276,7 @@ static errval_t _fat32_readdir(struct fat32 *fat32, struct fat32_handle *dir_han
|
||||
|
||||
*name = NULL;
|
||||
|
||||
// search for the next file in the directory starting at the current byte offset
|
||||
while (!fat32_is_end_of_cluster_chain(dir_handle->current_cluster)) {
|
||||
uint32_t first_sector_of_cluster = fat32_first_sector_of_cluster(fat32, dir_handle->current_cluster);
|
||||
for (uint32_t sector_offset = (dir_handle->byte_offset / fat32->bytes_per_sector) % fat32->sectors_per_cluster; sector_offset < fat32->sectors_per_cluster; ++sector_offset) {
|
||||
@ -1212,6 +1298,7 @@ static errval_t _fat32_readdir(struct fat32 *fat32, struct fat32_handle *dir_han
|
||||
|
||||
// found the next directory
|
||||
*name = fat32_directory_entry_get_nice_name(&directory_entries[directory_index]);
|
||||
if(*name == NULL) return LIB_ERR_MALLOC_FAIL;
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
}
|
||||
@ -1234,10 +1321,12 @@ static errval_t _fat32_rmdir(struct fat32 *fat32, const char *path) {
|
||||
err = fat32_resolve_path(fat32, path, &path_resolve_result);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// this function can only be used to delete directories
|
||||
if (!(path_resolve_result.directory_entry.attributes & FAT32_ATTR_DIRECTORY)) {
|
||||
return FS_ERR_NOTDIR;
|
||||
}
|
||||
|
||||
// we refuse to delete non-empty directories
|
||||
err = fat32_check_directory_empty(fat32, &path_resolve_result.directory_entry);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
@ -1266,6 +1355,7 @@ static errval_t _fat32_rm(struct fat32 *fat32, const char *path) {
|
||||
err = fat32_resolve_path(fat32, path, &path_resolve_result);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// only files can be deleted this way
|
||||
if (path_resolve_result.directory_entry.attributes & FAT32_ATTR_DIRECTORY) {
|
||||
return FS_ERR_NOTFILE;
|
||||
}
|
||||
@ -1333,6 +1423,9 @@ static errval_t _fat32_fcreate(struct fat32 *fat32, const char *path, struct fat
|
||||
if (err_is_ok(err)) return FS_ERR_EXISTS;
|
||||
if (err_no(err) != FS_ERR_NOTFOUND) return err;
|
||||
|
||||
// make sure the path is a valid file path (i.e. does not end with a slash) (emulating behaviour seen on linux)
|
||||
if (path[strlen(path) - 1] == FS_PATH_SEP) return FS_ERR_NOTFILE;
|
||||
|
||||
// iterate throught the parent directory to find a free entry
|
||||
struct fat32_path_resolve_result free_path_resolve_result;
|
||||
err = fat32_allocate_directory_entry(
|
||||
@ -1452,6 +1545,7 @@ static errval_t _fat32_fread(struct fat32 *fat32, struct fat32_handle *file_hand
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
// calculate how much we can read until the end of the file
|
||||
size_t bytes_till_eof = directory_entry.file_size - file_handle->byte_offset;
|
||||
// debug_printf("[fat32_fread] bytes_till_eof: %lu\n", bytes_till_eof);
|
||||
size_t bytes_to_read = MIN(bytes, bytes_till_eof);
|
||||
@ -1472,6 +1566,8 @@ static errval_t _fat32_fread(struct fat32 *fat32, struct fat32_handle *file_hand
|
||||
assert(!fat32_is_end_of_cluster_chain(file_handle->current_cluster));
|
||||
}
|
||||
|
||||
// read until we have reached the desired amount of bytes
|
||||
// where we read is determined by the current byte offset of the file handle
|
||||
*bytes_read = 0;
|
||||
while (*bytes_read < bytes_to_read) {
|
||||
// make sure we never try to look at the reserved clusters during traversal
|
||||
@ -1501,8 +1597,11 @@ static errval_t _fat32_fread(struct fat32 *fat32, struct fat32_handle *file_hand
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
}
|
||||
// continue in the next cluster
|
||||
err = fat32_next_cluster_in_chain(fat32, file_handle->current_cluster, &file_handle->current_cluster);
|
||||
if (err_is_fail(err)) return err;
|
||||
// we have checked in advance that this exists by checking the file size
|
||||
assert(!fat32_is_end_of_cluster_chain(file_handle->current_cluster));
|
||||
}
|
||||
|
||||
// debug_printf("[fat32_fread] file now at offset %lu\n", file_handle->byte_offset);
|
||||
@ -1545,6 +1644,7 @@ static errval_t _fat32_fwrite(struct fat32 *fat32, struct fat32_handle *file_han
|
||||
// when we are past the end of the file then the cluster_number is invalid
|
||||
file_handle->current_cluster = file_handle->first_cluster;
|
||||
for (size_t i = 0; i + 1 < cluster_min_count; ++i) {
|
||||
// add a cluster to the chain if necessary
|
||||
err = fat32_next_cluster_in_chain_or_extend(fat32, file_handle->current_cluster, &file_handle->current_cluster);
|
||||
if (err_is_fail(err)) return err;
|
||||
}
|
||||
@ -1583,6 +1683,7 @@ static errval_t _fat32_fwrite(struct fat32 *fat32, struct fat32_handle *file_han
|
||||
if (err_is_fail(err)) break;
|
||||
if (*bytes_written == bytes) break;
|
||||
|
||||
// if we reached the end of the file just extend it
|
||||
err = fat32_next_cluster_in_chain_or_extend(fat32, file_handle->current_cluster, &file_handle->current_cluster);
|
||||
if (err_is_fail(err)) break;
|
||||
}
|
||||
@ -1602,6 +1703,7 @@ static errval_t _fat32_fwrite(struct fat32 *fat32, struct fat32_handle *file_han
|
||||
// set the archive flag
|
||||
directory_entry.attributes |= FAT32_ATTR_ARCHIVE;
|
||||
|
||||
// update the directory information on disk
|
||||
errval_t dir_update_err = fat32_write_directory_entry(
|
||||
fat32,
|
||||
file_handle->directory_entry_ref,
|
||||
@ -1630,6 +1732,7 @@ errval_t fat32_fclose(struct fat32 *fat32, struct fat32_handle *file_handle) {
|
||||
|
||||
errval_t fat32_tell(struct fat32 *fat32, struct fat32_handle *file_handle, size_t *pos) {
|
||||
// debug_printf("[fat32_tell]\n");
|
||||
// get the current position if it is a file and return 0 otherwise
|
||||
*pos = file_handle->is_dir ? 0 : file_handle->byte_offset;
|
||||
// debug_printf("[fat32_tell] @%lu\n", file_handle->byte_offset);
|
||||
return SYS_ERR_OK;
|
||||
@ -1646,7 +1749,9 @@ static errval_t _fat32_seek(struct fat32 *fat32, struct fat32_handle *file_handl
|
||||
case FS_SEEK_SET:
|
||||
assert(offset >= 0);
|
||||
if (file_handle->is_dir) {
|
||||
absolute_offset = offset * sizeof(struct fat32_directory_entry);
|
||||
// allow restarting directory reading from the beginning
|
||||
assert(offset == 0);
|
||||
absolute_offset = 0;
|
||||
} else {
|
||||
absolute_offset = offset;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user