Compare commits

...

8 Commits

Author SHA1 Message Date
Simon Glass
7cd988f165 fat: Split get_contents() into helper functions
Break down the large get_contents() function into smaller, focused
helper functions to improve readability and maintainability:

- seek_clust(): Navigate to the cluster at a given position
- read_partial(): Handle partial cluster reads with offset
- find_consecutive(): Find and read consecutive clusters

This refactoring eliminates the goto statement and makes the code flow
clearer while maintaining the same functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:28:59 -07:00
Simon Glass
c7195de38f fat: Make flush_dirty_fat_buffer() static inline when read-only
Move the read-only stub of flush_dirty_fat_buffer() from fat.c to
fat_internal.h as a static inline function. This eliminates the need
for a separate stub implementation and makes the code cleaner.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:22:32 -07:00
Simon Glass
35eb3ad7c8 fat: Move and rename find_directory_entry()
Move find_directory_entry() to the top of the file to eliminate the
need for a forward declaration. Rename it to find_dir_entry() for
brevity.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:20:56 -07:00
Simon Glass
1c624170db fat: Move global/static variables to top of files
Move global and static variable declarations to the top of their files
after struct definitions for better organization and visibility. Add
comments to document their purpose.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:18:27 -07:00
Simon Glass
650dbda9cb fat: Move struct fat_dir to top of file
Move struct definitions to the top of the file for better organization
and visibility. Add kernel-doc style documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:16:19 -07:00
Simon Glass
4e783237a6 fat: Move struct fat_dir to top of file
Move struct definitions to the top of the file for better organization
and visibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:15:20 -07:00
Simon Glass
ad6be5dfa6 fat: Use '\0' for null terminator assignments
Use '\0' instead of 0 when assigning null terminators to make the intent
clearer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:13:53 -07:00
Simon Glass
6f08359f92 fat: Use simpler form for zero comparisons
Replace == 0 with ! and remove != 0 where appropriate to make the code
more idiomatic and improve readability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 20:11:22 -07:00
3 changed files with 246 additions and 150 deletions

View File

@@ -27,6 +27,25 @@
#include <linux/log2.h>
#include "fat_internal.h"
/**
* struct fat_dir - directory stream for FAT filesystem
* @parent: generic directory stream
* @dirent: directory entry information
* @fsdata: filesystem data
* @itr: FAT iterator for traversing directory entries
*/
struct fat_dir {
struct fs_dir_stream parent;
struct fs_dirent dirent;
struct fsdata fsdata;
struct fat_itr itr;
};
/* Current block device */
struct blk_desc *cur_dev;
/* Current partition information */
struct disk_partition cur_part_info;
/*
* Convert a string to lowercase. Converts at most 'len' characters,
* 'len' may be larger than the length of 'str' if 'str' is NULL
@@ -40,9 +59,6 @@ void downcase(char *str, size_t len)
}
}
struct blk_desc *cur_dev;
struct disk_partition cur_part_info;
int disk_read(u32 block, u32 nr_blocks, void *buf)
{
ulong ret;
@@ -96,7 +112,7 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no)
/* Read the partition table, if present */
if (part_get_info(dev_desc, part_no, &info)) {
if (part_no != 0) {
if (part_no) {
log_err("Partition %d invalid on device %d\n", part_no,
dev_desc->devnum);
return -1;
@@ -105,8 +121,8 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no)
info.start = 0;
info.size = dev_desc->lba;
info.blksz = dev_desc->blksz;
info.name[0] = 0;
info.type[0] = 0;
info.name[0] = '\0';
info.type[0] = '\0';
info.bootable = 0;
disk_partition_clr_uuid(&info);
}
@@ -144,15 +160,6 @@ static void get_name(struct dir_entry *dirent, char *s_name)
*s_name = DELETED_FLAG;
}
#if !CONFIG_IS_ENABLED(FAT_WRITE)
/* Stub for read only operation */
int flush_dirty_fat_buffer(struct fsdata *mydata)
{
(void)(mydata);
return 0;
}
#endif
/*
* Get the entry at index 'entry' in a FAT (12/16/32) table.
* On failure 0x00 is returned.
@@ -300,6 +307,124 @@ get_cluster(struct fsdata *mydata, u32 clustnum, u8 *buffer, unsigned long size)
return 0;
}
/**
* seek_clust() - seek to the cluster containing the specified position
*
* Navigate through the FAT chain to find the cluster that contains the given
* file position.
*
* @mydata: file system description
* @curclust: starting cluster
* @pos: position to seek to
* @bytesperclust: bytes per cluster
* Return: cluster number at position, or 0 on error
*/
static u32 seek_clust(struct fsdata *mydata, u32 curclust, loff_t pos,
unsigned int bytesperclust)
{
loff_t actsize = bytesperclust;
/* go to cluster at pos */
while (actsize <= pos) {
curclust = get_fatent(mydata, curclust);
if (CHECK_CLUST(curclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
printf("Invalid FAT entry\n");
return 0;
}
actsize += bytesperclust;
}
return curclust;
}
/**
* read_partial() - read partial data from a cluster
*
* Read data from a cluster starting at a non-zero offset. This is used when
* the read position is not cluster-aligned. A temporary buffer is used to
* read the full cluster, then the requested portion is copied out.
*
* @mydata: file system description
* @curclust: cluster to read from
* @pos: offset within cluster
* @buffer: buffer to read into
* @filesize: remaining file size
* @bytesperclust: bytes per cluster
* @gotsize: pointer to accumulate bytes read
* Return: 0 on success, -1 on error
*/
static int read_partial(struct fsdata *mydata, u32 curclust, loff_t pos,
u8 **buffer, loff_t filesize,
unsigned int bytesperclust, loff_t *gotsize)
{
u8 *tmp_buffer;
loff_t actsize;
actsize = min(filesize, (loff_t)bytesperclust);
tmp_buffer = malloc_cache_aligned(actsize);
if (!tmp_buffer) {
debug("Error: allocating buffer\n");
return -1;
}
if (get_cluster(mydata, curclust, tmp_buffer, actsize)) {
printf("Error reading cluster\n");
free(tmp_buffer);
return -1;
}
actsize -= pos;
memcpy(*buffer, tmp_buffer + pos, actsize);
free(tmp_buffer);
*gotsize += actsize;
*buffer += actsize;
return 0;
}
/**
* find_consecutive() - find consecutive clusters
*
* Search the FAT chain to find a run of consecutive clusters starting from
* the given cluster. This allows reading multiple clusters in a single
* operation for better performance.
*
* @mydata: file system description
* @curclust: starting cluster
* @endclust: pointer to ending cluster
* @buffer: buffer to read into
* @filesize: remaining file size
* @bytesperclust: bytes per cluster
* @actsize: pointer to actual size read
* Return: 0 if all remaining data is consecutive, 1 if not consecutive
*/
static int find_consecutive(struct fsdata *mydata, u32 curclust,
u32 *endclust, u8 *buffer, loff_t filesize,
unsigned int bytesperclust, loff_t *actsize)
{
u32 newclust;
*actsize = bytesperclust;
*endclust = curclust;
/* search for consecutive clusters */
while (*actsize < filesize) {
newclust = get_fatent(mydata, *endclust);
if ((newclust - 1) != *endclust)
return 1; /* not consecutive */
if (CHECK_CLUST(newclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", newclust);
printf("Invalid FAT entry\n");
return -1;
}
*endclust = newclust;
*actsize += bytesperclust;
}
return 0; /* all remaining data is consecutive */
}
/**
* get_contents() - read from file
*
@@ -321,8 +446,10 @@ static int get_contents(struct fsdata *mydata, struct dir_entry *dentptr, loff_t
loff_t filesize = FAT2CPU32(dentptr->size);
unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
u32 curclust = START(dentptr);
u32 endclust, newclust;
u32 endclust;
loff_t actsize;
loff_t offset_in_clust;
int ret;
*gotsize = 0;
debug("Filesize: %llu bytes\n", filesize);
@@ -337,48 +464,26 @@ static int get_contents(struct fsdata *mydata, struct dir_entry *dentptr, loff_t
debug("%llu bytes\n", filesize);
actsize = bytesperclust;
/* Seek to the cluster containing pos */
curclust = seek_clust(mydata, curclust, pos, bytesperclust);
if (!curclust)
return -1;
/* go to cluster at pos */
while (actsize <= pos) {
curclust = get_fatent(mydata, curclust);
if (CHECK_CLUST(curclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
printf("Invalid FAT entry\n");
return -1;
}
actsize += bytesperclust;
}
/* Calculate offset within the cluster and adjust pos/filesize */
offset_in_clust = pos % bytesperclust;
filesize -= pos - offset_in_clust;
/* actsize > pos */
actsize -= bytesperclust;
filesize -= actsize;
pos -= actsize;
/* Handle partial cluster read at the beginning */
if (offset_in_clust) {
ret = read_partial(mydata, curclust, offset_in_clust,
&buffer, filesize, bytesperclust,
gotsize);
if (ret)
return ret;
/* align to beginning of next cluster if any */
if (pos) {
u8 *tmp_buffer;
actsize = min(filesize, (loff_t)bytesperclust);
tmp_buffer = malloc_cache_aligned(actsize);
if (!tmp_buffer) {
debug("Error: allocating buffer\n");
return -1;
}
if (get_cluster(mydata, curclust, tmp_buffer, actsize) != 0) {
printf("Error reading cluster\n");
free(tmp_buffer);
return -1;
}
filesize -= actsize;
actsize -= pos;
memcpy(buffer, tmp_buffer + pos, actsize);
free(tmp_buffer);
*gotsize += actsize;
filesize -= min(filesize, (loff_t)(bytesperclust - offset_in_clust));
if (!filesize)
return 0;
buffer += actsize;
curclust = get_fatent(mydata, curclust);
if (CHECK_CLUST(curclust, mydata->fatsize)) {
@@ -388,50 +493,40 @@ static int get_contents(struct fsdata *mydata, struct dir_entry *dentptr, loff_t
}
}
actsize = bytesperclust;
endclust = curclust;
/* Read remaining data in full/partial clusters */
while (filesize > 0) {
ret = find_consecutive(mydata, curclust, &endclust,
buffer, filesize, bytesperclust,
&actsize);
if (ret < 0)
return -1;
do {
/* search for consecutive clusters */
while (actsize < filesize) {
newclust = get_fatent(mydata, endclust);
if ((newclust - 1) != endclust)
goto getit;
if (CHECK_CLUST(newclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", newclust);
printf("Invalid FAT entry\n");
return -1;
}
endclust = newclust;
actsize += bytesperclust;
}
/* Read all consecutive clusters or remaining bytes */
if (!ret)
actsize = filesize;
/* get remaining bytes */
actsize = filesize;
if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
if (get_cluster(mydata, curclust, buffer, (int)actsize)) {
printf("Error reading cluster\n");
return -1;
}
*gotsize += actsize;
return 0;
getit:
if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
printf("Error reading cluster\n");
return -1;
}
*gotsize += (int)actsize;
filesize -= actsize;
buffer += actsize;
if (!filesize || !ret)
return 0;
/* Move to next cluster */
curclust = get_fatent(mydata, endclust);
if (CHECK_CLUST(curclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
printf("Invalid FAT entry\n");
return -1;
}
actsize = bytesperclust;
endclust = curclust;
} while (1);
}
return 0;
}
/*
@@ -445,19 +540,19 @@ static int slot2str(struct dir_slot *slotptr, char *l_name, int *idx)
for (j = 0; j <= 8; j += 2) {
l_name[*idx] = slotptr->name0_4[j];
if (l_name[*idx] == 0x00)
if (!l_name[*idx])
return 1;
(*idx)++;
}
for (j = 0; j <= 10; j += 2) {
l_name[*idx] = slotptr->name5_10[j];
if (l_name[*idx] == 0x00)
if (!l_name[*idx])
return 1;
(*idx)++;
}
for (j = 0; j <= 2; j += 2) {
l_name[*idx] = slotptr->name11_12[j];
if (l_name[*idx] == 0x00)
if (!l_name[*idx])
return 1;
(*idx)++;
}
@@ -643,7 +738,7 @@ static int get_fs_info(struct fsdata *mydata)
mydata->sect_size, cur_part_info.blksz);
return -1;
}
if (mydata->clust_size == 0) {
if (!mydata->clust_size) {
log_err("FAT cluster size not set\n");
return -1;
}
@@ -816,7 +911,7 @@ void *fat_next_cluster(struct fat_itr *itr, unsigned int *nbytes)
struct dir_entry *next_dent(struct fat_itr *itr)
{
if (itr->remaining == 0) {
if (!itr->remaining) {
unsigned nbytes;
struct dir_entry *dent = fat_next_cluster(itr, &nbytes);
@@ -835,7 +930,7 @@ struct dir_entry *next_dent(struct fat_itr *itr)
}
/* have we reached the last valid entry? */
if (itr->dent->nameext.name[0] == 0)
if (!itr->dent->nameext.name[0])
return NULL;
return itr->dent;
@@ -967,7 +1062,7 @@ int fat_itr_resolve(struct fat_itr *itr, const char *path, uint type)
path++;
/* are we at the end? */
if (strlen(path) == 0) {
if (!strlen(path)) {
if (!(type & TYPE_DIR))
return -ENOENT;
return 0;
@@ -990,7 +1085,7 @@ int fat_itr_resolve(struct fat_itr *itr, const char *path, uint type)
itr->remaining = 0;
itr->last_cluster = 0;
if (next[0] == 0) {
if (!next[0]) {
if (type & TYPE_DIR)
return 0;
else
@@ -1084,7 +1179,7 @@ int fat_exists(const char *filename)
free(fsdata.fatbuf);
out:
free(itr);
return ret == 0;
return !ret;
}
/**
@@ -1190,13 +1285,6 @@ int file_fat_read(const char *filename, void *buffer, int maxsize)
return actread;
}
struct fat_dir {
struct fs_dir_stream parent;
struct fs_dirent dirent;
struct fsdata fsdata;
struct fat_itr itr;
};
int fat_opendir(const char *filename, struct fs_dir_stream **dirsp)
{
struct fat_dir *dir;

View File

@@ -111,7 +111,14 @@ int disk_read(u32 block, u32 nr_blocks, void *buf);
* @mydata: filesystem data
* Return: 0 on success, -1 on error
*/
#if CONFIG_IS_ENABLED(FAT_WRITE)
int flush_dirty_fat_buffer(struct fsdata *mydata);
#else
static inline int flush_dirty_fat_buffer(struct fsdata *mydata)
{
return 0;
}
#endif
/* Internal function declarations */

View File

@@ -23,7 +23,6 @@
#include <linux/math64.h>
#include "fat_internal.h"
static struct dir_entry *find_directory_entry(struct fat_itr *itr, char *filename);
static int new_dir_table(struct fat_itr *itr);
/* Characters that may only be used in long file names */
@@ -32,6 +31,40 @@ static const char LONG_ONLY_CHARS[] = "+,;=[]";
/* Combined size of the name and ext fields in the directory entry */
#define SHORT_NAME_SIZE 11
/* Total number of sectors in the partition */
static int total_sector;
/**
* find_dir_entry() - find a directory entry by filename
*
* @itr: directory iterator
* @filename: name of file to find
* Return: directory entry or NULL
*/
static struct dir_entry *find_dir_entry(struct fat_itr *itr, char *filename)
{
int match = 0;
while (fat_itr_next(itr)) {
/* check both long and short name: */
if (!strcasecmp(filename, itr->name))
match = 1;
else if (itr->name != itr->s_name &&
!strcasecmp(filename, itr->s_name))
match = 1;
if (!match)
continue;
if (itr->dent->nameext.name[0] == '\0')
return NULL;
else
return itr->dent;
}
return NULL;
}
/**
* str2fat() - convert string to valid FAT name characters
*
@@ -177,7 +210,7 @@ static int set_name(struct fat_itr *itr, const char *filename, char *shortname)
ret = fat_move_to_cluster(itr, itr->start_clust);
if (ret)
return ret;
if (find_directory_entry(itr, buf))
if (find_dir_entry(itr, buf))
continue;
goto out_ret;
@@ -192,7 +225,6 @@ out:
return ret;
}
static int total_sector;
static int disk_write(u32 block, u32 nr_blocks, void *buf)
{
ulong ret;
@@ -207,7 +239,7 @@ static int disk_write(u32 block, u32 nr_blocks, void *buf)
}
ret = blk_dwrite(cur_dev, cur_part_info.start + block, nr_blocks, buf);
if (nr_blocks && ret == 0)
if (nr_blocks && !ret)
return -1;
return ret;
@@ -322,7 +354,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
int j, end_idx = 0;
for (j = 0; j <= 8; j += 2) {
if (name[*idx] == 0x00) {
if (!name[*idx]) {
slotptr->name0_4[j] = 0;
slotptr->name0_4[j + 1] = 0;
end_idx++;
@@ -333,7 +365,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
end_idx++;
}
for (j = 0; j <= 10; j += 2) {
if (name[*idx] == 0x00) {
if (!name[*idx]) {
slotptr->name5_10[j] = 0;
slotptr->name5_10[j + 1] = 0;
end_idx++;
@@ -344,7 +376,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
end_idx++;
}
for (j = 0; j <= 2; j += 2) {
if (name[*idx] == 0x00) {
if (!name[*idx]) {
slotptr->name11_12[j] = 0;
slotptr->name11_12[j + 1] = 0;
end_idx++;
@@ -355,7 +387,7 @@ static int str2slot(struct dir_slot *slotptr, const char *name, int *idx)
end_idx++;
}
if (name[*idx] == 0x00)
if (!name[*idx])
return 1;
return 0;
@@ -411,7 +443,7 @@ fill_dir_slot(struct fat_itr *itr, const char *l_name, const char *shortname)
slotptr->attr = ATTR_VFAT;
slotptr->alias_checksum = checksum;
slotptr++;
} while (ret == 0);
} while (!ret);
slotptr--;
slotptr->id |= LAST_LONG_ENTRY_MASK;
@@ -552,7 +584,7 @@ static u32 determine_fatent(struct fsdata *mydata, u32 entry)
while (1) {
next_fat = get_fatent(mydata, next_entry);
if (next_fat == 0) {
if (!next_fat) {
/* found free entry, link to entry */
set_fatent_value(mydata, entry, next_entry);
break;
@@ -809,7 +841,7 @@ static int find_empty_cluster(struct fsdata *mydata)
while (1) {
fat_val = get_fatent(mydata, entry);
if (fat_val == 0)
if (!fat_val)
break;
entry++;
}
@@ -869,7 +901,7 @@ static int clear_fatent(struct fsdata *mydata, u32 entry)
while (!CHECK_CLUST(entry, mydata->fatsize)) {
fat_val = get_fatent(mydata, entry);
if (fat_val != 0)
if (fat_val)
set_fatent_value(mydata, entry, 0);
else
break;
@@ -912,7 +944,7 @@ static int check_overflow(struct fsdata *mydata, u32 clustnum, loff_t size)
sect_num = div_u64_rem(size, mydata->sect_size, &offset);
if (offset != 0)
if (offset)
sect_num++;
if (startsect + sect_num > total_sector)
@@ -1115,7 +1147,7 @@ set_clusters:
/* set remaining bytes */
actsize = filesize;
if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
if (set_cluster(mydata, curclust, buffer, (u32)actsize)) {
debug("error: writing cluster\n");
return -1;
}
@@ -1132,7 +1164,7 @@ set_clusters:
return 0;
getit:
if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
if (set_cluster(mydata, curclust, buffer, (u32)actsize)) {
debug("error: writing cluster\n");
return -1;
}
@@ -1335,37 +1367,6 @@ static int create_link(struct fat_itr *itr, char *basename, u32 clust, u32 size,
return ret;
}
/**
* find_directory_entry() - find a directory entry by filename
*
* @itr: directory iterator
* @filename: name of file to find
* Return: directory entry or NULL
*/
static struct dir_entry *find_directory_entry(struct fat_itr *itr, char *filename)
{
int match = 0;
while (fat_itr_next(itr)) {
/* check both long and short name: */
if (!strcasecmp(filename, itr->name))
match = 1;
else if (itr->name != itr->s_name &&
!strcasecmp(filename, itr->s_name))
match = 1;
if (!match)
continue;
if (itr->dent->nameext.name[0] == '\0')
return NULL;
else
return itr->dent;
}
return NULL;
}
static int split_filename(char *filename, char **dirname, char **basename)
{
char *p, *last_slash, *last_slash_cont;
@@ -1517,7 +1518,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
goto exit;
}
retdent = find_directory_entry(itr, l_filename);
retdent = find_dir_entry(itr, l_filename);
if (retdent) {
if (fat_itr_isdir(itr)) {
@@ -1757,7 +1758,7 @@ int fat_unlink(const char *filename)
goto exit;
}
if (!find_directory_entry(itr, basename)) {
if (!find_dir_entry(itr, basename)) {
log_err("%s: doesn't exist (%d)\n", basename, -ENOENT);
ret = -ENOENT;
goto exit;
@@ -1834,7 +1835,7 @@ int fat_mkdir(const char *dirname)
goto exit;
}
retdent = find_directory_entry(itr, l_dirname);
retdent = find_dir_entry(itr, l_dirname);
if (retdent) {
printf("%s: already exists\n", l_dirname);
@@ -2040,7 +2041,7 @@ int fat_rename(const char *old_path, const char *new_path)
goto exit;
}
if (!find_directory_entry(old_itr, old_basename)) {
if (!find_dir_entry(old_itr, old_basename)) {
log_debug("%s doesn't exist (%d)\n", old_basename, -ENOENT);
ret = -ENOENT;
goto exit;
@@ -2063,7 +2064,7 @@ int fat_rename(const char *old_path, const char *new_path)
goto exit;
}
found_existing = find_directory_entry(new_itr, l_new_basename);
found_existing = find_dir_entry(new_itr, l_new_basename);
if (found_existing) {
/* store cluster of new_path since it may need to be deleted */
@@ -2147,7 +2148,7 @@ int fat_rename(const char *old_path, const char *new_path)
struct dir_entry *dent;
fat_itr_child(new_itr, new_itr);
dent = find_directory_entry(new_itr, "..");
dent = find_dir_entry(new_itr, "..");
if (!dent) {
log_debug("FAT filesystem corrupt!\n");
log_debug("dir %s has no parent direntry\n",