summaryrefslogtreecommitdiff
path: root/fs/fat
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2020-11-19 07:31:18 +0100
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2020-12-10 09:15:00 +0100
commit3d20d212cf410102ce67b62774c831bd73617424 (patch)
treebe1c6d0c02cc8d9e0b40467c7c704cf88f70b909 /fs/fat
parent89735b44c4cee895b416f005468370d2943fa8d8 (diff)
downloadu-boot-3d20d212cf410102ce67b62774c831bd73617424.tar.gz
u-boot-3d20d212cf410102ce67b62774c831bd73617424.tar.bz2
u-boot-3d20d212cf410102ce67b62774c831bd73617424.zip
fs: fat: deletion of long file names
Long file names are stored in multiple directory entries. When deleting a file we must delete all of them. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/fat_write.c88
1 files changed, 76 insertions, 12 deletions
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index c403d7d5c6..20a54a2418 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -1445,27 +1445,91 @@ exit:
return count;
}
-static int delete_dentry(fat_itr *itr)
+/**
+ * delete_single_dentry() - delete a single directory entry
+ *
+ * @itr: directory iterator
+ * Return: 0 for success
+ */
+static int delete_single_dentry(fat_itr *itr)
+{
+ struct dir_entry *dent = itr->dent;
+
+ memset(dent, 0, sizeof(*dent));
+ dent->name[0] = DELETED_FLAG;
+
+ if (!itr->remaining) {
+ if (flush_dir(itr)) {
+ printf("error: writing directory entry\n");
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+/**
+ * delete_long_name() - delete long name directory entries
+ *
+ * @itr: directory iterator
+ * Return: 0 for success
+ */
+static int delete_long_name(fat_itr *itr)
+{
+ struct dir_entry *dent = itr->dent;
+ int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK;
+
+ while (seqn--) {
+ int ret;
+
+ ret = delete_single_dentry(itr);
+ if (ret)
+ return ret;
+ dent = next_dent(itr);
+ if (!dent)
+ return -EIO;
+ }
+ return 0;
+}
+
+/**
+ * delete_dentry_long() - remove directory entry
+ *
+ * @itr: directory iterator
+ * Return: 0 for success
+ */
+static int delete_dentry_long(fat_itr *itr)
{
fsdata *mydata = itr->fsdata;
- dir_entry *dentptr = itr->dent;
+ dir_entry *dent = itr->dent;
/* free cluster blocks */
- clear_fatent(mydata, START(dentptr));
+ clear_fatent(mydata, START(dent));
if (flush_dirty_fat_buffer(mydata) < 0) {
printf("Error: flush fat buffer\n");
return -EIO;
}
+ /* Position to first directory entry for long name */
+ if (itr->clust != itr->dent_clust) {
+ int ret;
- /*
- * update a directory entry
- * TODO:
- * - long file name support
- * - find and mark the "new" first invalid entry as name[0]=0x00
- */
- memset(dentptr, 0, sizeof(*dentptr));
- dentptr->name[0] = DELETED_FLAG;
+ ret = fat_move_to_cluster(itr, itr->dent_clust);
+ if (ret)
+ return ret;
+ }
+ itr->dent = itr->dent_start;
+ itr->remaining = itr->dent_rem;
+ dent = itr->dent_start;
+ /* Delete long name */
+ if ((dent->attr & ATTR_VFAT) == ATTR_VFAT &&
+ (dent->name[0] & LAST_LONG_ENTRY_MASK)) {
+ int ret;
+ ret = delete_long_name(itr);
+ if (ret)
+ return ret;
+ }
+ /* Delete short name */
+ delete_single_dentry(itr);
if (flush_dir(itr)) {
printf("error: writing directory entry\n");
return -EIO;
@@ -1535,7 +1599,7 @@ int fat_unlink(const char *filename)
}
}
- ret = delete_dentry(itr);
+ ret = delete_dentry_long(itr);
exit:
free(fsdata.fatbuf);