From 7fc8b5898f855ef2669358d517f29fdb875305a3 Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Tue, 9 Dec 2014 19:08:57 +0100
Subject: [PATCH] fat: read: fix read issue
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
---
fs/fat/fat.c | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 561921fa2d..fed893f5d8 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -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) {
--
2.34.1