fat: update
authorMinkyu Kang <mk7.kang@samsung.com>
Fri, 3 Dec 2010 02:36:00 +0000 (11:36 +0900)
committerMinkyu Kang <mk7.kang@samsung.com>
Fri, 3 Dec 2010 02:36:00 +0000 (11:36 +0900)
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
fs/fat/fat.c
include/fat.h

index c22f657..4368668 100644 (file)
@@ -631,15 +631,23 @@ __u8 get_vfatname_block[MAX_CLUSTSIZE];
 
 static int
 get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
-             dir_entry **retdent, char *l_name)
+             dir_entry *retdent, char *l_name)
 {
        dir_entry *realdent;
-       dir_slot *slotptr = (dir_slot *)(*retdent);
-       __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+       dir_slot *slotptr = (dir_slot *)retdent;
+       __u8 *buflimit = cluster + ((curclust == 0) ?
+                                       LINEAR_PREFETCH_SIZE :
+                                       (mydata->clust_size * SECTOR_SIZE)
+                                  );
        __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
        int idx = 0;
 
-       while ((__u8 *)slotptr < nextclust) {
+       if (counter > VFAT_MAXSEQ) {
+               debug("Error: VFAT name is too long\n");
+               return -1;
+       }
+
+       while ((__u8 *)slotptr < buflimit) {
                if (counter == 0)
                        break;
                if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
@@ -648,10 +656,11 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
                counter--;
        }
 
-       if ((__u8 *)slotptr >= nextclust) {
+       if ((__u8 *)slotptr >= buflimit) {
                dir_slot *slotptr2;
 
-               slotptr--;
+               if (curclust == 0)
+                       return -1;
                curclust = get_fatent(mydata, curclust);
                if (CHECK_CLUST(curclust, mydata->fatsize)) {
                        debug("curclust: 0x%x\n", curclust);
@@ -666,14 +675,19 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
                }
 
                slotptr2 = (dir_slot *)get_vfatname_block;
-               while (slotptr2->id > 0x01)
+               while (counter > 0) {
+                       if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
+                           & 0xff) != counter)
+                               return -1;
                        slotptr2++;
+                       counter--;
+               }
 
                /* Save the real directory entry */
-               realdent = (dir_entry *)slotptr2 + 1;
-               while ((__u8 *)slotptr2 >= get_vfatname_block) {
-                       slot2str(slotptr2, l_name, &idx);
+               realdent = (dir_entry *)slotptr2;
+               while ((__u8 *)slotptr2 > get_vfatname_block) {
                        slotptr2--;
+                       slot2str(slotptr2, l_name, &idx);
                }
        } else {
                /* Save the real directory entry */
@@ -694,7 +708,7 @@ get_vfatname (fsdata *mydata, int curclust, __u8 *cluster,
        downcase(l_name);
 
        /* Return the real directory entry */
-       *retdent = realdent;
+       memcpy(retdent, realdent, sizeof(dir_entry));
 
        return 0;
 }
@@ -774,7 +788,7 @@ static dir_entry *get_dentfromdir (fsdata *mydata, int startsect,
                                   int dols)
 {
        __u16 prevcksum = 0xffff;
-       __u32 curclust = startsect;
+       __u32 curclust = START(retdent);
        int files = 0, dirs = 0;
 
        debug("get_dentfromdir: %s\n", filename);
@@ -784,16 +798,16 @@ static dir_entry *get_dentfromdir (fsdata *mydata, int startsect,
 
                int i;
 
-               if (disk_read(curclust, mydata->clust_size,
-                           get_dentfromdir_block) < 0) {
-                       printf("Error: reading directory block\n");
+               if (get_cluster(mydata, curclust, get_dentfromdir_block,
+                               mydata->clust_size * SECTOR_SIZE) != 0) {
+                       debug("Error: reading directory block\n");
                        return NULL;
                }
 
                dentptr = (dir_entry *)get_dentfromdir_block;
 
                for (i = 0; i < DIRENTSPERCLUST; i++) {
-                       char s_name[14], l_name[256];
+                       char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
                        l_name[0] = '\0';
                        if (dentptr->name[0] == DELETED_FLAG) {
@@ -807,7 +821,7 @@ static dir_entry *get_dentfromdir (fsdata *mydata, int startsect,
                                        prevcksum = ((dir_slot *)dentptr)->alias_checksum;
                                        get_vfatname(mydata, curclust,
                                                     get_dentfromdir_block,
-                                                    &dentptr, l_name);
+                                                    dentptr, l_name);
                                        if (dols) {
                                                int isdir;
                                                char dirc;
@@ -913,7 +927,7 @@ static dir_entry *get_dentfromdir (fsdata *mydata, int startsect,
                              FAT2CPU32(dentptr->size),
                              (dentptr->attr & ATTR_DIR) ? "(DIR)" : "");
 
-                       return dentptr;
+                       return retdent;
                }
 
                curclust = get_fatent(mydata, curclust);
@@ -1093,7 +1107,11 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
                debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%d\n",
                        cursect, mydata->clust_size, DIRENTSPERBLOCK);
 
-               if (disk_read(cursect, mydata->clust_size, do_fat_read_block) < 0) {
+               if (disk_read(cursect,
+                               (mydata->fatsize == 32) ?
+                               (mydata->clust_size) :
+                               LINEAR_PREFETCH_SIZE / SECTOR_SIZE,
+                               do_fat_read_block) < 0) {
                        debug("Error: reading rootdir block\n");
                        return -1;
                }
@@ -1101,9 +1119,13 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
                dentptr = (dir_entry *) do_fat_read_block;
 
                for (i = 0; i < DIRENTSPERBLOCK; i++) {
-                       char s_name[14], l_name[256];
+                       char s_name[14], l_name[VFAT_MAXLEN_BYTES];
 
                        l_name[0] = '\0';
+                       if (dentptr->name[0] == DELETED_FLAG) {
+                               dentptr++;
+                               continue;
+                       }
                        if ((dentptr->attr & ATTR_VOLUME)) {
 #ifdef CONFIG_SUPPORT_VFAT
                                if ((dentptr->attr & ATTR_VFAT) &&
@@ -1111,9 +1133,12 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
                                        prevcksum =
                                                ((dir_slot *)dentptr)->alias_checksum;
 
-                                       get_vfatname(mydata, 0,
+                                       get_vfatname(mydata,
+                                                    (mydata->fatsize == 32) ?
+                                                    root_cluster :
+                                                    0,
                                                     do_fat_read_block,
-                                                    &dentptr, l_name);
+                                                    dentptr, l_name);
 
                                        if (dols == LS_ROOT) {
                                                char dirc;
index 772cf35..b7839ac 100644 (file)
 #include <asm/byteorder.h>
 
 #define CONFIG_SUPPORT_VFAT
+/* Maximum Long File Name length supported here is 128 UTF-16 code units */
+#define VFAT_MAXLEN_BYTES      256 /* Maximum LFN buffer in bytes */
+#define VFAT_MAXSEQ            9   /* Up to 9 of 13 2-byte UTF-16 entries */
+#define LINEAR_PREFETCH_SIZE   (SECTOR_SIZE*2) /* Prefetch buffer size */
 
 #define SECTOR_SIZE FS_BLOCK_SIZE