Browse Source

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>
Heinrich Schuchardt 3 years ago
parent
commit
3d20d212cf
1 changed files with 76 additions and 12 deletions
  1. 76 12
      fs/fat/fat_write.c

+ 76 - 12
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);