aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt2020-11-22 09:19:52 +0100
committerHeinrich Schuchardt2020-12-10 09:14:58 +0100
commitd236e825a214a5684598fa7a7b919af332c43390 (patch)
treeb4068142ae945949d73ba0bbdecaf9ea18214300
parentc5924118c03dc8db30d633de98afe6ad6eb7f277 (diff)
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>
-rw-r--r--fs/fat/fat.c106
-rw-r--r--include/fat.h7
2 files changed, 80 insertions, 33 deletions
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index fb6ba894664..674236d68a6 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -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) {
diff --git a/include/fat.h b/include/fat.h
index 02742f92a5c..3c29a4484d4 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -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_ */