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>
This commit is contained in:
Heinrich Schuchardt 2020-11-25 16:33:55 +01:00
parent 57b745e238
commit 3a331aee56

View file

@ -20,6 +20,8 @@
#include <linux/math64.h> #include <linux/math64.h>
#include "fat.c" #include "fat.c"
static dir_entry *find_directory_entry(fat_itr *itr, char *filename);
/* Characters that may only be used in long file names */ /* Characters that may only be used in long file names */
static const char LONG_ONLY_CHARS[] = "+,;=[]"; static const char LONG_ONLY_CHARS[] = "+,;=[]";
@ -63,6 +65,27 @@ static int str2fat(char *dest, char *src, int length)
return i; 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 * 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. * If a long name is needed, a short name is constructed.
* *
* @itr: directory iterator
* @filename: long file name * @filename: long file name
* @shortname: buffer of 11 bytes to receive chosen short name and extension * @shortname: buffer of 11 bytes to receive chosen short name and extension
* Return: number of directory entries needed, negative on error * 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 *period;
char *pos; char *pos;
@ -144,9 +168,16 @@ static int set_name(const char *filename, char *shortname)
else else
sprintf(buf, "%.*s", suffix_start + suffix_len, sprintf(buf, "%.*s", suffix_start + suffix_len,
dirent.name); dirent.name);
debug("short name: %s\n", buf); debug("generated short name: %s\n", buf);
/* TODO: Check that the short name does not exist yet. */
/* 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. */ /* Each long name directory entry takes 13 characters. */
ret = (strlen(filename) + 25) / 13; ret = (strlen(filename) + 25) / 13;
goto out; 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 */ /* Check if long name is needed */
ret = set_name(filename, shortname); ret = set_name(itr, filename, shortname);
if (ret < 0) if (ret < 0)
goto exit; goto exit;
if (ret > 1) { if (ret > 1) {
@ -1523,7 +1554,7 @@ int fat_mkdir(const char *new_dirname)
} }
/* Check if long name is needed */ /* Check if long name is needed */
ret = set_name(dirname, shortname); ret = set_name(itr, dirname, shortname);
if (ret < 0) if (ret < 0)
goto exit; goto exit;
if (ret > 1) { if (ret > 1) {