diff options
author | Heinrich Schuchardt | 2020-11-25 16:33:55 +0100 |
---|---|---|
committer | Heinrich Schuchardt | 2020-12-10 09:14:59 +0100 |
commit | 3a331aee561f4551e2e131114c416a70e91ae05f (patch) | |
tree | ea238c0b23ded673f4ec0a2cbd82da2a120eec17 | |
parent | 57b745e2387a7dafd2d29004351cdd3ffffcc5b9 (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.c | 41 |
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) { |