fat: read: fix read issue 84/31784/2
authorPrzemyslaw Marczak <p.marczak@samsung.com>
Tue, 9 Dec 2014 18:08:57 +0000 (19:08 +0100)
committerChanho Park <chanho61.park@samsung.com>
Wed, 10 Dec 2014 09:00:38 +0000 (01:00 -0800)
The present fat implementation ignores FAT16 long name directory entries
stored as the each block last entry. This causes that some files can't
be accessed by read in case if it's dir entries are stored in two blocks.
Now this is fixed by store the last used block in the buffer,
before read the next one.

Note that this is a temporary fix, since this breaks FAT32 read,
and will be fixed ASAP.

Change-Id: Ie2c2ccd07091d5fd09011c52d6f7c7dbdabd1dab
Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com>
fs/fat/fat.c

index 561921f..fed893f 100644 (file)
@@ -825,7 +825,8 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
        int firsttime;
        __u32 root_cluster = 0;
        int rootdir_size = 0;
-       int j;
+       int j, k;
+       __u8 *dir_ptr;
 
        if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
                debug("Error: reading boot sector\n");
@@ -911,24 +912,29 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
        }
 
        j = 0;
+       k = 0;
        while (1) {
                int i;
+               debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
+                       cursect, mydata->clust_size, DIRENTSPERBLOCK);
 
-               if (j == 0) {
-                       debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
-                               cursect, mydata->clust_size, DIRENTSPERBLOCK);
-
-                       if (disk_read(cursect,
-                                       (mydata->fatsize == 32) ?
-                                       (mydata->clust_size) :
-                                       PREFETCH_BLOCKS,
-                                       do_fat_read_at_block) < 0) {
-                               debug("Error: reading rootdir block\n");
-                               goto exit;
-                       }
+               if (!k) {
+                       dir_ptr = do_fat_read_at_block;
+                       k++;
+               } else {
+                       dir_ptr = (do_fat_read_at_block + mydata->sect_size);
+                       memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
+               }
 
-                       dentptr = (dir_entry *) do_fat_read_at_block;
+               if (disk_read(cursect,
+                       (mydata->fatsize == 32) ?
+                               (mydata->clust_size) :
+                               PREFETCH_BLOCKS,
+                               dir_ptr) < 0) {
+                       debug("Error: reading rootdir block\n");
+                       goto exit;
                }
+               dentptr = (dir_entry *) dir_ptr;
 
                for (i = 0; i < DIRENTSPERBLOCK; i++) {
                        char s_name[14], l_name[VFAT_MAXLEN_BYTES];
@@ -952,7 +958,7 @@ do_fat_read_at(const char *filename, unsigned long pos, void *buffer,
 
                                        get_vfatname(mydata,
                                                     root_cluster,
-                                                    do_fat_read_at_block,
+                                                    dir_ptr,
                                                     dentptr, l_name);
 
                                        if (dols == LS_ROOT) {