aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt2020-11-25 16:33:55 +0100
committerHeinrich Schuchardt2020-12-10 09:14:59 +0100
commit3a331aee561f4551e2e131114c416a70e91ae05f (patch)
treeea238c0b23ded673f4ec0a2cbd82da2a120eec17
parent57b745e2387a7dafd2d29004351cdd3ffffcc5b9 (diff)
fs: fat: generate unique short names
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>
-rw-r--r--fs/fat/fat_write.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 716b6a6627d..59cffef34e6 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[] = "+,;=[]";
@@ -64,6 +66,27 @@ static int str2fat(char *dest, char *src, int length)
}
/**
+ * 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
*
* The function determines if the @filename is a valid short name.
@@ -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) {