]> git.ipfire.org Git - thirdparty/u-boot.git/blobdiff - fs/fat/fat_write.c
fs: fat: correct file name normalization
[thirdparty/u-boot.git] / fs / fat / fat_write.c
index fc211e74bc69ef71c5c262778b70eb094f8c4da0..2a74199236d8398575beb8dd833bbca3ba4c84fd 100644 (file)
@@ -387,16 +387,22 @@ static __u32 determine_fatent(fsdata *mydata, __u32 entry)
        return next_entry;
 }
 
-/*
- * Write at most 'size' bytes from 'buffer' into the specified cluster.
- * Return 0 on success, -1 otherwise.
+/**
+ * set_cluster() - write data to cluster
+ *
+ * Write 'size' bytes from 'buffer' into the specified cluster.
+ *
+ * @mydata:    data to be written
+ * @clustnum:  cluster to be written to
+ * @buffer:    data to be written
+ * @size:      bytes to be written (but not more than the size of a cluster)
+ * Return:     0 on success, -1 otherwise
  */
 static int
-set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer,
-            unsigned long size)
+set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size)
 {
-       __u32 idx = 0;
-       __u32 startsect;
+       u32 idx = 0;
+       u32 startsect;
        int ret;
 
        if (clustnum > 0)
@@ -438,7 +444,8 @@ set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer,
 
        if (size) {
                ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
-
+               /* Do not leak content of stack */
+               memset(tmpbuf, 0, mydata->sect_size);
                memcpy(tmpbuf, buffer, size);
                ret = disk_write(startsect, 1, tmpbuf);
                if (ret != 1) {
@@ -689,11 +696,11 @@ static int
 set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer,
             loff_t maxsize, loff_t *gotsize)
 {
-       loff_t filesize;
        unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
        __u32 curclust = START(dentptr);
        __u32 endclust = 0, newclust = 0;
-       loff_t cur_pos, offset, actsize, wsize;
+       u64 cur_pos, filesize;
+       loff_t offset, actsize, wsize;
 
        *gotsize = 0;
        filesize = pos + maxsize;
@@ -821,7 +828,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer,
 
        curclust = endclust;
        filesize -= cur_pos;
-       assert(!(cur_pos % bytesperclust));
+       assert(!do_div(cur_pos, bytesperclust));
 
 set_clusters:
        /* allocate and write */
@@ -872,7 +879,7 @@ set_clusters:
 
                /* set remaining bytes */
                actsize = filesize;
-               if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
+               if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
                        debug("error: writing cluster\n");
                        return -1;
                }
@@ -889,7 +896,7 @@ set_clusters:
 
                return 0;
 getit:
-               if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
+               if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
                        debug("error: writing cluster\n");
                        return -1;
                }
@@ -1002,40 +1009,32 @@ again:
        return 0;
 }
 
+/**
+ * normalize_longname() - check long file name and convert to lower case
+ *
+ * We assume here that the FAT file system is using an 8bit code page.
+ * Linux typically uses CP437, EDK2 assumes CP1250.
+ *
+ * @l_filename:        preallocated buffer receiving the normalized name
+ * @filename:  filename to normalize
+ * Return:     0 on success, -1 on failure
+ */
 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;
+       const char *p, illegal[] = "<>:\"/\\|?*";
 
+       if (strlen(filename) >= VFAT_MAXLEN_BYTES)
                return -1;
-       }
 
-       /* Normalize it */
-       name_len = strlen(filename);
-       if (name_len >= VFAT_MAXLEN_BYTES)
-               /* should return an error? */
-               name_len = VFAT_MAXLEN_BYTES - 1;
+       for (p = filename; *p; ++p) {
+               if ((unsigned char)*p < 0x20)
+                       return -1;
+               if (strchr(illegal, *p))
+                       return -1;
+       }
 
-       memcpy(l_filename, filename, name_len);
-       l_filename[name_len] = 0; /* terminate the string */
-       downcase(l_filename, INT_MAX);
+       strcpy(l_filename, filename);
+       downcase(l_filename, VFAT_MAXLEN_BYTES);
 
        return 0;
 }
@@ -1259,6 +1258,11 @@ int fat_unlink(const char *filename)
        char *filename_copy, *dirname, *basename;
 
        filename_copy = strdup(filename);
+       if (!filename_copy) {
+               printf("Error: allocating memory\n");
+               ret = -ENOMEM;
+               goto exit;
+       }
        split_filename(filename_copy, &dirname, &basename);
 
        if (!strcmp(dirname, "/") && !strcmp(basename, "")) {
@@ -1270,7 +1274,8 @@ int fat_unlink(const char *filename)
        itr = malloc_cache_aligned(sizeof(fat_itr));
        if (!itr) {
                printf("Error: allocating memory\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto exit;
        }
 
        ret = fat_itr_root(itr, &fsdata);