diff options
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 3eab47e8b3..dc933be599 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -123,9 +123,14 @@ static unsigned int getcurrdostime(unsigned short *dosdate, | |||
123 | static int create_dos_name(unsigned char *name, unsigned char *newname); | 123 | static int create_dos_name(unsigned char *name, unsigned char *newname); |
124 | #endif | 124 | #endif |
125 | 125 | ||
126 | /* fat cache */ | ||
126 | static unsigned char *fat_cache[256]; | 127 | static unsigned char *fat_cache[256]; |
127 | static int fat_cache_dirty[256]; | 128 | static int fat_cache_dirty[256]; |
128 | 129 | ||
130 | /* sectors cache for longname use */ | ||
131 | static unsigned char lastsector[SECTOR_SIZE]; | ||
132 | static unsigned char lastsector2[SECTOR_SIZE]; | ||
133 | |||
129 | #ifdef TEST_FAT | 134 | #ifdef TEST_FAT |
130 | 135 | ||
131 | #include "debug.h" | 136 | #include "debug.h" |
@@ -788,13 +793,6 @@ int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name) | |||
788 | 793 | ||
789 | static int parse_direntry(struct fat_direntry *de, unsigned char *buf) | 794 | static int parse_direntry(struct fat_direntry *de, unsigned char *buf) |
790 | { | 795 | { |
791 | /* is this a long filename entry? */ | ||
792 | if ( ( buf[FATDIR_ATTR] & FAT_ATTR_LONG_NAME_MASK ) == | ||
793 | FAT_ATTR_LONG_NAME ) | ||
794 | { | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | memset(de, 0, sizeof(struct fat_direntry)); | 796 | memset(de, 0, sizeof(struct fat_direntry)); |
799 | de->attr = buf[FATDIR_ATTR]; | 797 | de->attr = buf[FATDIR_ATTR]; |
800 | de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; | 798 | de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; |
@@ -930,26 +928,84 @@ int fat_getnext(struct bpb *bpb, | |||
930 | int i; | 928 | int i; |
931 | int err; | 929 | int err; |
932 | unsigned char firstbyte; | 930 | unsigned char firstbyte; |
931 | int longarray[20]; | ||
932 | int longs=0; | ||
933 | int sectoridx=0; | ||
933 | 934 | ||
934 | while(!done) | 935 | while(!done) |
935 | { | 936 | { |
936 | /* Look for a free slot */ | ||
937 | for(i = ent->entry;i < SECTOR_SIZE/32;i++) | 937 | for(i = ent->entry;i < SECTOR_SIZE/32;i++) |
938 | { | 938 | { |
939 | firstbyte = ent->cached_buf[i*32]; | 939 | firstbyte = ent->cached_buf[i*32]; |
940 | |||
940 | if(firstbyte == 0xe5) | 941 | if(firstbyte == 0xe5) |
942 | /* free entry */ | ||
941 | continue; | 943 | continue; |
942 | 944 | ||
943 | if(firstbyte == 0) | 945 | if(firstbyte == 0) |
944 | /* no more entries */ | 946 | /* last entry */ |
945 | return -1; | 947 | return -1; |
946 | 948 | ||
947 | if ( parse_direntry(entry, &ent->cached_buf[i*32]) ) { | 949 | /* longname entry? */ |
948 | done = 1; | 950 | if ( ( ent->cached_buf[i*32 + FATDIR_ATTR] & |
949 | break; | 951 | FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { |
952 | longarray[longs++] = i*32 + sectoridx; | ||
953 | } | ||
954 | else { | ||
955 | if ( parse_direntry(entry, &ent->cached_buf[i*32]) ) { | ||
956 | |||
957 | /* replace shortname with longname? */ | ||
958 | if ( longs ) { | ||
959 | int j,k,l=0; | ||
960 | |||
961 | /* iterate backwards through the dir entries */ | ||
962 | for (j=longs-1; j>=0; j--) { | ||
963 | unsigned char* ptr = ent->cached_buf; | ||
964 | int index = longarray[j]; | ||
965 | |||
966 | /* current or cached sector? */ | ||
967 | if ( sectoridx >= SECTOR_SIZE ) { | ||
968 | if ( sectoridx >= SECTOR_SIZE*2 ) { | ||
969 | if ( index >= SECTOR_SIZE ) { | ||
970 | if ( index >= SECTOR_SIZE*2 ) | ||
971 | ptr = ent->cached_buf; | ||
972 | else | ||
973 | ptr = lastsector; | ||
974 | } | ||
975 | else | ||
976 | ptr = lastsector2; | ||
977 | } | ||
978 | else { | ||
979 | if ( index < SECTOR_SIZE ) | ||
980 | ptr = lastsector; | ||
981 | } | ||
982 | |||
983 | index &= SECTOR_SIZE-1; | ||
984 | } | ||
985 | |||
986 | /* piece together the name subcomponents */ | ||
987 | for (k=0; k<5; k++) | ||
988 | entry->name[l++] = ptr[index + k*2 + 1]; | ||
989 | for (k=0; k<6; k++) | ||
990 | entry->name[l++] = ptr[index + k*2 + 14]; | ||
991 | for (k=0; k<2; k++) | ||
992 | entry->name[l++] = ptr[index + k*2 + 28]; | ||
993 | } | ||
994 | entry->name[l]=0; | ||
995 | } | ||
996 | done = 1; | ||
997 | break; | ||
998 | } | ||
950 | } | 999 | } |
951 | } | 1000 | } |
952 | 1001 | ||
1002 | /* save this sector, for longname use */ | ||
1003 | if ( sectoridx ) | ||
1004 | memcpy( lastsector2, ent->cached_buf, SECTOR_SIZE ); | ||
1005 | else | ||
1006 | memcpy( lastsector, ent->cached_buf, SECTOR_SIZE ); | ||
1007 | sectoridx += SECTOR_SIZE; | ||
1008 | |||
953 | /* Next sector? */ | 1009 | /* Next sector? */ |
954 | if(i < SECTOR_SIZE/32) | 1010 | if(i < SECTOR_SIZE/32) |
955 | { | 1011 | { |