diff mbox series

[09/18] fs: fat: generate unique short names

Message ID 20201129020216.4865-10-xypron.glpk@gmx.de
State Accepted, archived
Commit 3a331aee561f4551e2e131114c416a70e91ae05f
Delegated to: Tom Rini
Headers show
Series fs: fat: fix long name support | expand

Commit Message

Heinrich Schuchardt Nov. 29, 2020, 2:02 a.m. UTC
File names must be unique within their directory. So before assigning a
short name we must check that it is unique.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
 fs/fat/fat_write.c | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

--
2.29.2
diff mbox series

Patch

diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 716b6a6627..59cffef34e 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -20,6 +20,8 @@ 
 #include <linux/math64.h>
 #include "fat.c"

+static dir_entry *find_directory_entry(fat_itr *itr, char *filename);
+
 /* Characters that may only be used in long file names */
 static const char LONG_ONLY_CHARS[] = "+,;=[]";

@@ -63,6 +65,27 @@  static int str2fat(char *dest, char *src, int length)
 	return i;
 }

+/**
+ * fat_move_to_cluster() - position to first directory entry in cluster
+ *
+ * @itr:	directory iterator
+ * @cluster	cluster
+ * Return:	0 for success, -EIO on error
+ */
+static int fat_move_to_cluster(fat_itr *itr, unsigned int cluster)
+{
+	unsigned int nbytes;
+
+	/* position to the start of the directory */
+	itr->next_clust = cluster;
+	itr->last_cluster = 0;
+	if (!fat_next_cluster(itr, &nbytes))
+		return -EIO;
+	itr->dent = (dir_entry *)itr->block;
+	itr->remaining = nbytes / sizeof(dir_entry) - 1;
+	return 0;
+}
+
 /**
  * set_name() - set short name in directory entry
  *
@@ -71,11 +94,12 @@  static int str2fat(char *dest, char *src, int length)
  *
  * If a long name is needed, a short name is constructed.
  *
+ * @itr:	directory iterator
  * @filename:	long file name
  * @shortname:	buffer of 11 bytes to receive chosen short name and extension
  * Return:	number of directory entries needed, negative on error
  */
-static int set_name(const char *filename, char *shortname)
+static int set_name(fat_itr *itr, const char *filename, char *shortname)
 {
 	char *period;
 	char *pos;
@@ -144,9 +168,16 @@  static int set_name(const char *filename, char *shortname)
 		else
 			sprintf(buf, "%.*s", suffix_start + suffix_len,
 				dirent.name);
-		debug("short name: %s\n", buf);
-		/* TODO: Check that the short name does not exist yet. */
+		debug("generated short name: %s\n", buf);
+
+		/* Check that the short name does not exist yet. */
+		ret = fat_move_to_cluster(itr, itr->start_clust);
+		if (ret)
+			return ret;
+		if (find_directory_entry(itr, buf))
+			continue;

+		debug("chosen short name: %s\n", buf);
 		/* Each long name directory entry takes 13 characters. */
 		ret = (strlen(filename) + 25) / 13;
 		goto out;
@@ -1261,7 +1292,7 @@  int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
 		}

 		/* Check if long name is needed */
-		ret = set_name(filename, shortname);
+		ret = set_name(itr, filename, shortname);
 		if (ret < 0)
 			goto exit;
 		if (ret > 1) {
@@ -1523,7 +1554,7 @@  int fat_mkdir(const char *new_dirname)
 		}

 		/* Check if long name is needed */
-		ret = set_name(dirname, shortname);
+		ret = set_name(itr, dirname, shortname);
 		if (ret < 0)
 			goto exit;
 		if (ret > 1) {