Merge tag 'u-boot-atmel-fixes-2021.01-b' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / fs / fat / fat_write.c
index 320a8a7..7afc838 100644 (file)
@@ -9,9 +9,11 @@
 #include <command.h>
 #include <config.h>
 #include <fat.h>
+#include <log.h>
 #include <malloc.h>
 #include <asm/byteorder.h>
 #include <part.h>
+#include <asm/cache.h>
 #include <linux/ctype.h>
 #include <div64.h>
 #include <linux/math64.h>
@@ -48,8 +50,11 @@ static int disk_write(__u32 block, __u32 nr_blocks, void *buf)
        return ret;
 }
 
-/*
- * Set short name in directory entry
+/**
+ * set_name() - set short name in directory entry
+ *
+ * @dirent:    directory entry
+ * @filename:  long file name
  */
 static void set_name(dir_entry *dirent, const char *filename)
 {
@@ -64,7 +69,8 @@ static void set_name(dir_entry *dirent, const char *filename)
        if (len == 0)
                return;
 
-       strcpy(s_name, filename);
+       strncpy(s_name, filename, VFAT_MAXLEN_BYTES - 1);
+       s_name[VFAT_MAXLEN_BYTES - 1] = '\0';
        uppercase(s_name, len);
 
        period = strchr(s_name, '.');
@@ -85,6 +91,11 @@ static void set_name(dir_entry *dirent, const char *filename)
                memcpy(dirent->name, s_name, period_location);
        } else {
                memcpy(dirent->name, s_name, 6);
+               /*
+                * TODO: Translating two long names with the same first six
+                *       characters to the same short name is utterly wrong.
+                *       Short names must be unique.
+                */
                dirent->name[6] = '~';
                dirent->name[7] = '1';
        }
@@ -249,9 +260,8 @@ fill_dir_slot(fat_itr *itr, const char *l_name)
                        flush_dir(itr);
 
                /* allocate a cluster for more entries */
-               if (!fat_itr_next(itr))
-                       if (!itr->dent &&
-                           (!itr->is_root || itr->fsdata->fatsize == 32) &&
+               if (!fat_itr_next(itr) && !itr->dent)
+                       if ((itr->is_root && itr->fsdata->fatsize != 32) ||
                            new_dir_table(itr))
                                return -1;
        }
@@ -489,8 +499,6 @@ flush_dir(fat_itr *itr)
                           nsects * mydata->sect_size);
 }
 
-static __u8 tmpbuf_cluster[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
-
 /*
  * Read and modify data on existing and consecutive cluster blocks
  */
@@ -498,6 +506,7 @@ static int
 get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
                loff_t size, loff_t *gotsize)
 {
+       static u8 *tmpbuf_cluster;
        unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
        __u32 startsect;
        loff_t wsize;
@@ -507,6 +516,12 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
        if (!size)
                return 0;
 
+       if (!tmpbuf_cluster) {
+               tmpbuf_cluster = memalign(ARCH_DMA_MINALIGN, MAX_CLUSTSIZE);
+               if (!tmpbuf_cluster)
+                       return -1;
+       }
+
        assert(pos < bytesperclust);
        startsect = clust_to_sect(mydata, clustnum);
 
@@ -795,6 +810,8 @@ set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer,
 
                        newclust = get_fatent(mydata, endclust);
 
+                       if (newclust != endclust + 1)
+                               break;
                        if (IS_LAST_CLUST(newclust, mydata->fatsize))
                                break;
                        if (CHECK_CLUST(newclust, mydata->fatsize)) {
@@ -812,7 +829,9 @@ set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer,
                        offset = 0;
                else
                        offset = pos - cur_pos;
-               wsize = min(cur_pos + actsize, filesize) - pos;
+               wsize = min_t(unsigned long long, actsize, filesize - cur_pos);
+               wsize -= offset;
+
                if (get_set_cluster(mydata, curclust, offset,
                                    buffer, wsize, &actsize)) {
                        printf("Error get-and-setting cluster\n");
@@ -825,8 +844,6 @@ set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer,
                if (filesize <= cur_pos)
                        break;
 
-               /* CHECK: newclust = get_fatent(mydata, endclust); */
-
                if (IS_LAST_CLUST(newclust, mydata->fatsize))
                        /* no more clusters */
                        break;
@@ -1174,7 +1191,8 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
                }
 
                /* Set short name entry */
-               fill_dentry(itr->fsdata, itr->dent, filename, 0, size, 0x20);
+               fill_dentry(itr->fsdata, itr->dent, filename, 0, size,
+                           ATTR_ARCH);
 
                retdent = itr->dent;
        }