fs: fat: export fat_next_cluster()

Rename function next_cluster() to fat_next_cluster() and export it.

When creating a new directory entries we should reuse deleted entries.
This requires re-scanning the directory.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Heinrich Schuchardt 2020-11-22 09:19:52 +01:00
parent c5924118c0
commit d236e825a2
2 changed files with 80 additions and 33 deletions

View File

@ -621,7 +621,7 @@ static int get_fs_info(fsdata *mydata)
/*
* The root directory is not cluster-aligned and may be on a
* "negative" cluster, this will be handled specially in
* next_cluster().
* fat_next_cluster().
*/
mydata->root_cluster = 0;
}
@ -647,44 +647,76 @@ static int get_fs_info(fsdata *mydata)
return 0;
}
/*
* Directory iterator, to simplify filesystem traversal
/**
* struct fat_itr - directory iterator, to simplify filesystem traversal
*
* Implements an iterator pattern to traverse directory tables,
* transparently handling directory tables split across multiple
* clusters, and the difference between FAT12/FAT16 root directory
* (contiguous) and subdirectories + FAT32 root (chained).
*
* Rough usage:
* Rough usage
*
* for (fat_itr_root(&itr, fsdata); fat_itr_next(&itr); ) {
* // to traverse down to a subdirectory pointed to by
* // current iterator position:
* fat_itr_child(&itr, &itr);
* }
* .. code-block:: c
*
* For more complete example, see fat_itr_resolve()
* for (fat_itr_root(&itr, fsdata); fat_itr_next(&itr); ) {
* // to traverse down to a subdirectory pointed to by
* // current iterator position:
* fat_itr_child(&itr, &itr);
* }
*
* For a more complete example, see fat_itr_resolve().
*/
typedef struct {
fsdata *fsdata; /* filesystem parameters */
unsigned start_clust; /* first cluster */
unsigned clust; /* current cluster */
unsigned next_clust; /* next cluster if remaining == 0 */
int last_cluster; /* set once we've read last cluster */
int is_root; /* is iterator at root directory */
int remaining; /* remaining dent's in current cluster */
/* current iterator position values: */
dir_entry *dent; /* current directory entry */
char l_name[VFAT_MAXLEN_BYTES]; /* long (vfat) name */
char s_name[14]; /* short 8.3 name */
char *name; /* l_name if there is one, else s_name */
/* storage for current cluster in memory: */
u8 block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
} fat_itr;
struct fat_itr {
/**
* @fsdata: filesystem parameters
*/
fsdata *fsdata;
/**
* @start_clust: first cluster
*/
unsigned int start_clust;
/**
* @clust: current cluster
*/
unsigned int clust;
/**
* @next_clust: next cluster if remaining == 0
*/
unsigned int next_clust;
/**
* @last_cluster: set if last cluster of directory reached
*/
int last_cluster;
/**
* @is_root: is iterator at root directory
*/
int is_root;
/**
* @remaining: remaining directory entries in current cluster
*/
int remaining;
/**
* @dent: current directory entry
*/
dir_entry *dent;
/**
* @l_name: long name of current directory entry
*/
char l_name[VFAT_MAXLEN_BYTES];
/**
* @s_name: short 8.3 name of current directory entry
*/
char s_name[14];
/**
* @name: l_name if there is one, else s_name
*/
char *name;
/**
* @block: buffer for current cluster
*/
u8 block[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
};
static int fat_itr_isdir(fat_itr *itr);
@ -753,7 +785,17 @@ static void fat_itr_child(fat_itr *itr, fat_itr *parent)
itr->last_cluster = 0;
}
static void *next_cluster(fat_itr *itr, unsigned *nbytes)
/**
* fat_next_cluster() - load next FAT cluster
*
* The function is used when iterating through directories. It loads the
* next cluster with directory entries
*
* @itr: directory iterator
* @nbytes: number of bytes read, 0 on error
* Return: first directory entry, NULL on error
*/
void *fat_next_cluster(fat_itr *itr, unsigned int *nbytes)
{
fsdata *mydata = itr->fsdata; /* for silly macros */
int ret;
@ -825,7 +867,7 @@ static dir_entry *next_dent(fat_itr *itr)
{
if (itr->remaining == 0) {
unsigned nbytes;
struct dir_entry *dent = next_cluster(itr, &nbytes);
struct dir_entry *dent = fat_next_cluster(itr, &nbytes);
/* have we reached the last cluster? */
if (!dent) {

View File

@ -9,8 +9,9 @@
#ifndef _FAT_H_
#define _FAT_H_
#include <asm/byteorder.h>
#include <fs.h>
#include <asm/byteorder.h>
#include <asm/cache.h>
struct disk_partition;
@ -179,6 +180,9 @@ typedef struct {
int fats; /* Number of FATs */
} fsdata;
struct fat_itr;
typedef struct fat_itr fat_itr;
static inline u32 clust_to_sect(fsdata *fsdata, u32 clust)
{
return fsdata->data_begin + clust * fsdata->clust_size;
@ -208,4 +212,5 @@ void fat_closedir(struct fs_dir_stream *dirs);
int fat_unlink(const char *filename);
int fat_mkdir(const char *dirname);
void fat_close(void);
void *fat_next_cluster(fat_itr *itr, unsigned int *nbytes);
#endif /* _FAT_H_ */