From: AKASHI Takahiro <takahiro.aka...@linaro.org>

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 <takahiro.aka...@linaro.org>
---
 fs/fat/fat_write.c | 52 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index 3b77557b3ede..6c715a70f447 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -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)
 {
@@ -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;
@@ -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,
-- 
2.18.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to