Skip to content

Commit

Permalink
fs: fat: check and normalize file name
Browse files Browse the repository at this point in the history
FAT file system's long file name support is a bit complicated and has some
restrictions on its naming. We should be careful about it especially for
write as it may easily end up with wrong file system.

normalize_longname() check for the rules and normalize a file name
if necessary. Please note, however, that this function is yet to be
extended to fully comply with the standard.

Signed-off-by: AKASHI Takahiro <[email protected]>
Signed-off-by: Alexander Graf <[email protected]>
  • Loading branch information
AKASHI Takahiro authored and agraf committed Sep 23, 2018
1 parent 881042e commit 25bb9da
Showing 1 changed file with 44 additions and 8 deletions.
52 changes: 44 additions & 8 deletions fs/fat/fat_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,44 @@ static dir_entry *find_directory_entry(fsdata *mydata, int startsect,
return NULL;
}

static int normalize_longname(char *l_filename, const char *filename)
{
const char *p, legal[] = "!#$%&\'()-.@^`_{}~";
char c;
int name_len;

/* Check that the filename is valid */
for (p = filename; p < filename + strlen(filename); p++) {
c = *p;

if (('0' <= c) && (c <= '9'))
continue;
if (('A' <= c) && (c <= 'Z'))
continue;
if (('a' <= c) && (c <= 'z'))
continue;
if (strchr(legal, c))
continue;
/* extended code */
if ((0x80 <= c) && (c <= 0xff))
continue;

return -1;
}

/* Normalize it */
name_len = strlen(filename);
if (name_len >= VFAT_MAXLEN_BYTES)
/* should return an error? */
name_len = VFAT_MAXLEN_BYTES - 1;

memcpy(l_filename, filename, name_len);
l_filename[name_len] = 0; /* terminate the string */
downcase(l_filename, INT_MAX);

return 0;
}

static int do_fat_write(const char *filename, void *buffer, loff_t size,
loff_t *actwrite)
{
Expand All @@ -910,7 +948,7 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
fsdata datablock;
fsdata *mydata = &datablock;
int cursect;
int ret = -1, name_len;
int ret = -1;
char l_filename[VFAT_MAXLEN_BYTES];

*actwrite = size;
Expand Down Expand Up @@ -971,13 +1009,11 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
}
dentptr = (dir_entry *) do_fat_read_at_block;

name_len = strlen(filename);
if (name_len >= VFAT_MAXLEN_BYTES)
name_len = VFAT_MAXLEN_BYTES - 1;

memcpy(l_filename, filename, name_len);
l_filename[name_len] = 0; /* terminate the string */
downcase(l_filename, INT_MAX);
if (normalize_longname(l_filename, filename)) {
printf("FAT: illegal filename (%s)\n", filename);
ret = -EINVAL;
goto exit;
}

startsect = mydata->rootdir_sect;
retdent = find_directory_entry(mydata, startsect,
Expand Down

0 comments on commit 25bb9da

Please sign in to comment.