diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-11-18 11:58:43 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-11-18 11:58:43 +0000 |
commit | eee2c01697f90e3be4d7c1b0c57f6921c78e85b9 (patch) | |
tree | 071d638ff388222972a70f55997412cc23dcef29 /firmware/drivers | |
parent | 7aabb1ab66b3126b987200528b62f4a3fb98d205 (diff) | |
download | rockbox-eee2c01697f90e3be4d7c1b0c57f6921c78e85b9.tar.gz rockbox-eee2c01697f90e3be4d7c1b0c57f6921c78e85b9.zip |
Added longname handling to fat_remove().
Added proper 0xffff padding of last longname entry.
add_dir_entry() now makes sure shortname is unique.
Changed update_file_size() to use dir-as-file handling.
Simplified create_dos_name() since we never use shortnames.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2853 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/fat.c | 373 | ||||
-rw-r--r-- | firmware/drivers/fat.h | 6 |
2 files changed, 239 insertions, 140 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 534d48bf76..a3ed62e4bc 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -100,7 +100,6 @@ | |||
100 | #define FATDIR_FILESIZE 28 | 100 | #define FATDIR_FILESIZE 28 |
101 | 101 | ||
102 | #define FATLONG_ORDER 0 | 102 | #define FATLONG_ORDER 0 |
103 | #define FATLONG_ATTR 11 | ||
104 | #define FATLONG_TYPE 12 | 103 | #define FATLONG_TYPE 12 |
105 | #define FATLONG_CHKSUM 13 | 104 | #define FATLONG_CHKSUM 13 |
106 | 105 | ||
@@ -648,9 +647,9 @@ static int write_long_name(struct fat_file* file, | |||
648 | unsigned char* entry; | 647 | unsigned char* entry; |
649 | unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR; | 648 | unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR; |
650 | unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR; | 649 | unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR; |
651 | unsigned int i, j=0, nameidx; | 650 | unsigned int i, j=0; |
652 | unsigned char chksum = 0; | 651 | unsigned char chksum = 0; |
653 | unsigned int namelen = strlen(name); | 652 | int nameidx=0, namelen = strlen(name); |
654 | int rc; | 653 | int rc; |
655 | 654 | ||
656 | LDEBUGF("write_long_name(file:%x, first:%d, num:%d, name:%s)\n", | 655 | LDEBUGF("write_long_name(file:%x, first:%d, num:%d, name:%s)\n", |
@@ -669,9 +668,10 @@ static int write_long_name(struct fat_file* file, | |||
669 | chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; | 668 | chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++]; |
670 | 669 | ||
671 | /* calc position of last name segment */ | 670 | /* calc position of last name segment */ |
672 | for (nameidx=0; | 671 | if ( namelen > NAME_BYTES_PER_ENTRY ) |
673 | nameidx < (namelen - NAME_BYTES_PER_ENTRY); | 672 | for (nameidx=0; |
674 | nameidx += NAME_BYTES_PER_ENTRY); | 673 | nameidx < (namelen - NAME_BYTES_PER_ENTRY); |
674 | nameidx += NAME_BYTES_PER_ENTRY); | ||
675 | 675 | ||
676 | for (i=0; i < numentries; i++) { | 676 | for (i=0; i < numentries; i++) { |
677 | /* new sector? */ | 677 | /* new sector? */ |
@@ -685,10 +685,15 @@ static int write_long_name(struct fat_file* file, | |||
685 | if (rc<1) | 685 | if (rc<1) |
686 | return -4; | 686 | return -4; |
687 | 687 | ||
688 | /* grab next sector */ | 688 | /* read next sector */ |
689 | rc = fat_readwrite(file, 1, buf, false); | 689 | rc = fat_readwrite(file, 1, buf, false); |
690 | if (rc<1) | 690 | if (rc<0) { |
691 | LDEBUGF("Failed writing new sector: %d\n",rc); | ||
691 | return -5; | 692 | return -5; |
693 | } | ||
694 | if (rc==0) | ||
695 | /* end of dir */ | ||
696 | memset(buf, 0, sizeof buf); | ||
692 | 697 | ||
693 | sector++; | 698 | sector++; |
694 | idx = 0; | 699 | idx = 0; |
@@ -707,13 +712,34 @@ static int write_long_name(struct fat_file* file, | |||
707 | if ( i+1 < numentries ) { | 712 | if ( i+1 < numentries ) { |
708 | /* longname entry */ | 713 | /* longname entry */ |
709 | int k, l = nameidx; | 714 | int k, l = nameidx; |
715 | |||
710 | entry[FATLONG_ORDER] = numentries-i-1; | 716 | entry[FATLONG_ORDER] = numentries-i-1; |
711 | if (i==0) | 717 | if (i==0) { |
718 | /* mark this as last long entry */ | ||
712 | entry[FATLONG_ORDER] |= 0x40; | 719 | entry[FATLONG_ORDER] |= 0x40; |
713 | for (k=0; k<5 && name[l]; k++) entry[k*2 + 1] = name[l++]; | 720 | |
714 | for (k=0; k<6 && name[l]; k++) entry[k*2 + 14] = name[l++]; | 721 | /* pad name with 0xffff */ |
715 | for (k=0; k<2 && name[l]; k++) entry[k*2 + 28] = name[l++]; | 722 | for (k=1; k<12; k++) entry[k] = 0xff; |
716 | entry[FATLONG_ATTR] = FAT_ATTR_LONG_NAME; | 723 | for (k=14; k<26; k++) entry[k] = 0xff; |
724 | for (k=28; k<32; k++) entry[k] = 0xff; | ||
725 | }; | ||
726 | /* set name */ | ||
727 | for (k=0; k<5 && l <= namelen; k++) { | ||
728 | entry[k*2 + 1] = name[l++]; | ||
729 | entry[k*2 + 2] = 0; | ||
730 | } | ||
731 | for (k=0; k<6 && l <= namelen; k++) { | ||
732 | entry[k*2 + 14] = name[l++]; | ||
733 | entry[k*2 + 15] = 0; | ||
734 | } | ||
735 | for (k=0; k<2 && l <= namelen; k++) { | ||
736 | entry[k*2 + 28] = name[l++]; | ||
737 | entry[k*2 + 29] = 0; | ||
738 | } | ||
739 | |||
740 | entry[FATDIR_ATTR] = FAT_ATTR_LONG_NAME; | ||
741 | entry[FATDIR_FSTCLUSLO] = 0; | ||
742 | entry[FATLONG_TYPE] = 0; | ||
717 | entry[FATLONG_CHKSUM] = chksum; | 743 | entry[FATLONG_CHKSUM] = chksum; |
718 | LDEBUGF("Longname entry %d: %.13s\n", idx, name+nameidx); | 744 | LDEBUGF("Longname entry %d: %.13s\n", idx, name+nameidx); |
719 | } | 745 | } |
@@ -726,14 +752,13 @@ static int write_long_name(struct fat_file* file, | |||
726 | } | 752 | } |
727 | idx++; | 753 | idx++; |
728 | nameidx -= NAME_BYTES_PER_ENTRY; | 754 | nameidx -= NAME_BYTES_PER_ENTRY; |
729 | //dbg_dump_buffer(buf, SECTOR_SIZE, 0); | ||
730 | } | 755 | } |
731 | 756 | ||
732 | /* update last sector */ | 757 | /* update last sector */ |
733 | rc = fat_seek(file, sector); | 758 | rc = fat_seek(file, sector); |
734 | if (rc<0) | 759 | if (rc<0) |
735 | return -5; | 760 | return -5; |
736 | 761 | ||
737 | rc = fat_readwrite(file, 1, buf, true); | 762 | rc = fat_readwrite(file, 1, buf, true); |
738 | if (rc<1) | 763 | if (rc<1) |
739 | return -6; | 764 | return -6; |
@@ -751,8 +776,10 @@ static int add_dir_entry(struct fat_dir* dir, | |||
751 | unsigned int sector; | 776 | unsigned int sector; |
752 | bool done = false; | 777 | bool done = false; |
753 | bool eof = false; | 778 | bool eof = false; |
779 | bool last = false; | ||
754 | int entries_needed, entries_found = 0; | 780 | int entries_needed, entries_found = 0; |
755 | int namelen = strlen(name); | 781 | int namelen = strlen(name); |
782 | int firstentry; | ||
756 | 783 | ||
757 | LDEBUGF( "add_dir_entry(%s,%x)\n", | 784 | LDEBUGF( "add_dir_entry(%s,%x)\n", |
758 | name, file->firstcluster); | 785 | name, file->firstcluster); |
@@ -767,6 +794,9 @@ static int add_dir_entry(struct fat_dir* dir, | |||
767 | if (namelen % NAME_BYTES_PER_ENTRY) | 794 | if (namelen % NAME_BYTES_PER_ENTRY) |
768 | entries_needed++; | 795 | entries_needed++; |
769 | 796 | ||
797 | restart: | ||
798 | firstentry = 0; | ||
799 | |||
770 | err=fat_seek(&dir->file, 0); | 800 | err=fat_seek(&dir->file, 0); |
771 | if (err<0) | 801 | if (err<0) |
772 | return -1; | 802 | return -1; |
@@ -803,7 +833,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
803 | } | 833 | } |
804 | 834 | ||
805 | /* look for free slots */ | 835 | /* look for free slots */ |
806 | for (i=0; i < DIR_ENTRIES_PER_SECTOR; i++) | 836 | for (i=0; i < DIR_ENTRIES_PER_SECTOR && !done; i++) |
807 | { | 837 | { |
808 | unsigned char firstbyte = buf[i * DIR_ENTRY_SIZE]; | 838 | unsigned char firstbyte = buf[i * DIR_ENTRY_SIZE]; |
809 | switch (firstbyte) { | 839 | switch (firstbyte) { |
@@ -811,6 +841,8 @@ static int add_dir_entry(struct fat_dir* dir, | |||
811 | entries_found = entries_needed; | 841 | entries_found = entries_needed; |
812 | LDEBUGF("Found last entry %d\n", | 842 | LDEBUGF("Found last entry %d\n", |
813 | sector * DIR_ENTRIES_PER_SECTOR + i); | 843 | sector * DIR_ENTRIES_PER_SECTOR + i); |
844 | last = true; | ||
845 | done = true; | ||
814 | break; | 846 | break; |
815 | 847 | ||
816 | case 0xe5: /* free entry */ | 848 | case 0xe5: /* free entry */ |
@@ -822,55 +854,90 @@ static int add_dir_entry(struct fat_dir* dir, | |||
822 | 854 | ||
823 | default: | 855 | default: |
824 | entries_found = 0; | 856 | entries_found = 0; |
857 | |||
858 | /* check that our intended shortname doesn't already exist */ | ||
859 | if (!strncmp(shortname, buf + i * DIR_ENTRY_SIZE, 12)) { | ||
860 | /* filename exists already. make a new one */ | ||
861 | snprintf(shortname+8, 4, "%03X", (unsigned)rand() & 0xfff); | ||
862 | LDEBUGF("Duplicate shortname, changing to %s\n", | ||
863 | shortname); | ||
864 | |||
865 | /* name has changed, we need to restart search */ | ||
866 | goto restart; | ||
867 | } | ||
825 | break; | 868 | break; |
826 | } | 869 | } |
827 | 870 | ||
828 | if (entries_found == entries_needed) | 871 | if (!firstentry && (entries_found == entries_needed)) { |
829 | { | 872 | firstentry = sector * DIR_ENTRIES_PER_SECTOR + i; |
830 | int firstentry = sector * DIR_ENTRIES_PER_SECTOR + i; | ||
831 | 873 | ||
832 | /* if we're not extending the dir, we must go back to first | 874 | /* if we're not extending the dir, |
833 | free entry */ | 875 | we must go back to first free entry */ |
834 | if (firstbyte) | 876 | if (!last) |
835 | firstentry -= (entries_needed - 1); | 877 | firstentry -= (entries_needed - 1); |
878 | } | ||
879 | } | ||
880 | } | ||
836 | 881 | ||
837 | LDEBUGF("Adding longname to entry %d in sector %d\n", | 882 | sector = firstentry / DIR_ENTRIES_PER_SECTOR; |
838 | i, sector); | 883 | LDEBUGF("Adding longname to entry %d in sector %d\n", |
884 | firstentry, sector); | ||
839 | 885 | ||
840 | err = write_long_name(&dir->file, firstentry, | 886 | err = write_long_name(&dir->file, firstentry, |
841 | entries_needed, name, shortname); | 887 | entries_needed, name, shortname); |
842 | if (err < 0) | 888 | if (err < 0) |
843 | return -5; | 889 | return -5; |
844 | 890 | ||
845 | /* remember where the shortname dir entry is located */ | 891 | /* remember where the shortname dir entry is located */ |
846 | file->dirsector = dir->file.lastsector; | 892 | file->direntry = firstentry + entries_needed - 1; |
847 | file->direntry = | 893 | file->direntries = entries_needed; |
848 | (i + entries_needed - 1) % DIR_ENTRIES_PER_SECTOR; | 894 | file->dircluster = dir->file.firstcluster; |
895 | LDEBUGF("Added new dir entry %d, using %d slots.\n", | ||
896 | file->direntry, file->direntries); | ||
849 | 897 | ||
850 | /* advance the last_empty_entry marker? */ | 898 | /* advance the end-of-dir marker? */ |
851 | if (firstbyte == 0) | 899 | if (last) |
852 | { | 900 | { |
853 | i++; | 901 | unsigned int lastentry = firstentry + entries_needed; |
854 | if (i < DIR_ENTRIES_PER_SECTOR) | 902 | |
855 | { | 903 | LDEBUGF("Updating end-of-dir entry %d\n",lastentry); |
856 | /* next entry is now last */ | 904 | |
857 | buf[i*DIR_ENTRY_SIZE] = 0; | 905 | if (lastentry % DIR_ENTRIES_PER_SECTOR) |
858 | } | 906 | { |
859 | else | 907 | int idx = (lastentry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE; |
860 | { | 908 | |
861 | /* add a new sector/cluster for last entry */ | 909 | err=fat_seek(&dir->file, lastentry / DIR_ENTRIES_PER_SECTOR); |
862 | memset(buf, 0, sizeof buf); | 910 | if (err<0) |
863 | do { | 911 | return -6; |
864 | err = fat_readwrite(&dir->file, 1, buf, true); | 912 | |
865 | if (err<1) | 913 | err = fat_readwrite(&dir->file, 1, buf, false); |
866 | return -6; | 914 | if (err<1) |
867 | } while (dir->file.sectornum < | 915 | return -7; |
868 | (int)fat_bpb.bpb_secperclus); | 916 | |
869 | } | 917 | /* clear last entry */ |
870 | } | 918 | buf[idx] = 0; |
871 | done = true; | 919 | |
872 | break; | 920 | err=fat_seek(&dir->file, lastentry / DIR_ENTRIES_PER_SECTOR); |
873 | } | 921 | if (err<0) |
922 | return -8; | ||
923 | |||
924 | /* we must clear entire last cluster */ | ||
925 | do { | ||
926 | err = fat_readwrite(&dir->file, 1, buf, true); | ||
927 | if (err<1) | ||
928 | return -9; | ||
929 | memset(buf, 0, sizeof buf); | ||
930 | } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); | ||
931 | } | ||
932 | else | ||
933 | { | ||
934 | /* add a new sector/cluster for last entry */ | ||
935 | memset(buf, 0, sizeof buf); | ||
936 | do { | ||
937 | err = fat_readwrite(&dir->file, 1, buf, true); | ||
938 | if (err<1) | ||
939 | return -10; | ||
940 | } while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus); | ||
874 | } | 941 | } |
875 | } | 942 | } |
876 | 943 | ||
@@ -916,106 +983,70 @@ unsigned char char2dos(unsigned char c) | |||
916 | 983 | ||
917 | static int create_dos_name(unsigned char *name, unsigned char *newname) | 984 | static int create_dos_name(unsigned char *name, unsigned char *newname) |
918 | { | 985 | { |
919 | unsigned char n[12]; | 986 | int i,j; |
920 | unsigned char c; | ||
921 | int i; | ||
922 | char *ext; | ||
923 | 987 | ||
924 | strncpy(n, name, sizeof n); | ||
925 | |||
926 | ext = strchr(n, '.'); | ||
927 | if(ext) | ||
928 | { | ||
929 | *ext++ = 0; | ||
930 | } | ||
931 | |||
932 | /* The file name is either empty, or there was only an extension. | ||
933 | In either case it is illegal. */ | ||
934 | if(n[0] == 0) | ||
935 | { | ||
936 | return -2; | ||
937 | } | ||
938 | |||
939 | /* Name part */ | 988 | /* Name part */ |
940 | for(i = 0;n[i] && (i < 8);i++) | 989 | for (i=0, j=0; name[i] && (j < 8); i++) |
941 | { | ||
942 | c = char2dos(n[i]); | ||
943 | if(c) | ||
944 | { | ||
945 | newname[i] = toupper(c); | ||
946 | } | ||
947 | } | ||
948 | while(i < 8) | ||
949 | { | 990 | { |
950 | newname[i++] = ' '; | 991 | unsigned char c = char2dos(name[i]); |
992 | if (c) | ||
993 | newname[j++] = toupper(c); | ||
951 | } | 994 | } |
995 | while (j < 8) | ||
996 | newname[j++] = ' '; | ||
952 | 997 | ||
953 | /* Extension part */ | 998 | /* Extension part */ |
954 | for (i = 0;ext && ext[i] && (i < 3);i++) | 999 | snprintf(newname+8, 4, "%03X", (unsigned)rand() & 0xfff); |
955 | { | ||
956 | c = char2dos(ext[i]); | ||
957 | if (c) | ||
958 | { | ||
959 | newname[8+i] = toupper(c); | ||
960 | } | ||
961 | } | ||
962 | while(i < 3) | ||
963 | { | ||
964 | newname[8+i++] = ' '; | ||
965 | } | ||
966 | 1000 | ||
967 | newname[11] = 0; | ||
968 | return 0; | 1001 | return 0; |
969 | } | 1002 | } |
970 | 1003 | ||
971 | static int update_file_size( struct fat_file* file, int size ) | 1004 | static int update_file_size( struct fat_file* file, int size ) |
972 | { | 1005 | { |
973 | unsigned char buf[SECTOR_SIZE]; | 1006 | unsigned char buf[SECTOR_SIZE]; |
974 | int sector = file->dirsector + fat_bpb.startsector; | 1007 | int sector = file->direntry / DIR_ENTRIES_PER_SECTOR; |
975 | unsigned char* entry = buf + file->direntry * DIR_ENTRY_SIZE; | 1008 | unsigned char* entry = |
1009 | buf + DIR_ENTRY_SIZE * (file->direntry % DIR_ENTRIES_PER_SECTOR); | ||
976 | unsigned int* sizeptr; | 1010 | unsigned int* sizeptr; |
977 | unsigned short* clusptr; | 1011 | unsigned short* clusptr; |
1012 | struct fat_file dir; | ||
978 | int err; | 1013 | int err; |
979 | 1014 | ||
980 | LDEBUGF("update_file_size(cluster:%x entry:%d sector:%x size:%d)\n", | 1015 | LDEBUGF("update_file_size(cluster:%x entry:%d size:%d)\n", |
981 | file->firstcluster, file->direntry, file->dirsector, size); | 1016 | file->firstcluster, file->direntry, size); |
982 | 1017 | ||
983 | if ( file->direntry >= DIR_ENTRIES_PER_SECTOR ) | 1018 | /* create a temporary file handle for the dir holding this file */ |
984 | panicf("update_file_size(): Illegal entry %d!\n",file->direntry); | 1019 | err = fat_open(file->dircluster, &dir, NULL); |
1020 | if (err<0) | ||
1021 | return -1; | ||
985 | 1022 | ||
986 | if ( file->direntry < 0 ) | 1023 | err = fat_seek( &dir, sector ); |
987 | panicf("update_file_size(): Illegal entry %d!\n",file->direntry); | 1024 | if (err<0) |
1025 | return -2; | ||
988 | 1026 | ||
989 | err = ata_read_sectors(sector, 1, buf); | 1027 | err = fat_readwrite(&dir, 1, buf, false); |
990 | if (err) | 1028 | if (err<1) |
991 | { | 1029 | return -3; |
992 | DEBUGF( "update_file_size() - Couldn't read dir sector %d" | ||
993 | " (error code %d)\n", sector, err); | ||
994 | return -1; | ||
995 | } | ||
996 | 1030 | ||
997 | if ( size == -1 ) { | 1031 | if (!entry[0] || entry[0] == 0xe5) |
998 | /* mark entry deleted */ | 1032 | panicf("Updating size on empty dir entry %d\n", file->direntry); |
999 | entry[0] = 0xe5; | ||
1000 | } | ||
1001 | else { | ||
1002 | clusptr = (short*)(entry + FATDIR_FSTCLUSHI); | ||
1003 | *clusptr = SWAB16(file->firstcluster >> 16); | ||
1004 | 1033 | ||
1005 | clusptr = (short*)(entry + FATDIR_FSTCLUSLO); | 1034 | clusptr = (short*)(entry + FATDIR_FSTCLUSHI); |
1006 | *clusptr = SWAB16(file->firstcluster & 0xffff); | 1035 | *clusptr = SWAB16(file->firstcluster >> 16); |
1036 | |||
1037 | clusptr = (short*)(entry + FATDIR_FSTCLUSLO); | ||
1038 | *clusptr = SWAB16(file->firstcluster & 0xffff); | ||
1007 | 1039 | ||
1008 | sizeptr = (int*)(entry + FATDIR_FILESIZE); | 1040 | sizeptr = (int*)(entry + FATDIR_FILESIZE); |
1009 | *sizeptr = SWAB32(size); | 1041 | *sizeptr = SWAB32(size); |
1010 | } | ||
1011 | 1042 | ||
1012 | err = ata_write_sectors(sector, 1, buf); | 1043 | err = fat_seek( &dir, sector ); |
1013 | if (err) | 1044 | if (err<0) |
1014 | { | 1045 | return -4; |
1015 | DEBUGF( "update_file_size() - Couldn't write dir sector %d" | 1046 | |
1016 | " (error code %d)\n", sector, err); | 1047 | err = fat_readwrite(&dir, 1, buf, true); |
1017 | return -2; | 1048 | if (err<1) |
1018 | } | 1049 | return -5; |
1019 | 1050 | ||
1020 | return 0; | 1051 | return 0; |
1021 | } | 1052 | } |
@@ -1057,8 +1088,9 @@ int fat_open(unsigned int startcluster, | |||
1057 | 1088 | ||
1058 | /* remember where the file's dir entry is located */ | 1089 | /* remember where the file's dir entry is located */ |
1059 | if ( dir ) { | 1090 | if ( dir ) { |
1060 | file->dirsector = dir->sector; | ||
1061 | file->direntry = dir->entry - 1; | 1091 | file->direntry = dir->entry - 1; |
1092 | file->direntries = dir->entrycount; | ||
1093 | file->dircluster = dir->file.firstcluster; | ||
1062 | } | 1094 | } |
1063 | LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry); | 1095 | LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry); |
1064 | return 0; | 1096 | return 0; |
@@ -1113,7 +1145,7 @@ int fat_closewrite(struct fat_file *file, int size) | |||
1113 | } | 1145 | } |
1114 | } | 1146 | } |
1115 | 1147 | ||
1116 | if (file->dirsector) | 1148 | if (file->dircluster) |
1117 | if (update_file_size(file, size) < 0) | 1149 | if (update_file_size(file, size) < 0) |
1118 | return -1; | 1150 | return -1; |
1119 | 1151 | ||
@@ -1152,9 +1184,69 @@ int fat_remove(struct fat_file* file) | |||
1152 | update_fat_entry(last,0); | 1184 | update_fat_entry(last,0); |
1153 | last = next; | 1185 | last = next; |
1154 | } | 1186 | } |
1155 | update_file_size(file, -1); | 1187 | |
1156 | file->dirsector = 0; | 1188 | /* free all dir entries */ |
1189 | if ( file->dircluster ) { | ||
1190 | unsigned char buf[SECTOR_SIZE]; | ||
1191 | struct fat_file dir; | ||
1192 | unsigned int entry = file->direntry - file->direntries + 1; | ||
1193 | unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; | ||
1194 | unsigned int i; | ||
1195 | int err; | ||
1196 | |||
1197 | /* create a temporary file handle for the dir holding this file */ | ||
1198 | err = fat_open(file->dircluster, &dir, NULL); | ||
1199 | if (err<0) | ||
1200 | return -1; | ||
1201 | |||
1202 | err = fat_seek( &dir, sector ); | ||
1203 | if (err<0) | ||
1204 | return -2; | ||
1205 | |||
1206 | err = fat_readwrite(&dir, 1, buf, false); | ||
1207 | if (err<1) | ||
1208 | return -3; | ||
1209 | |||
1210 | for (i=0; i < file->direntries; i++) { | ||
1211 | LDEBUGF("Clearing dir entry %d (%d/%d)\n", | ||
1212 | entry, i+1, file->direntries); | ||
1213 | buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5; | ||
1214 | entry++; | ||
1215 | |||
1216 | if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) { | ||
1217 | /* flush this sector */ | ||
1218 | err = fat_seek(&dir, sector); | ||
1219 | if (err<0) | ||
1220 | return -4; | ||
1221 | |||
1222 | err = fat_readwrite(&dir, 1, buf, true); | ||
1223 | if (err<1) | ||
1224 | return -5; | ||
1225 | |||
1226 | if ( i+1 < file->direntries ) { | ||
1227 | /* read next sector */ | ||
1228 | err = fat_readwrite(&dir, 1, buf, false); | ||
1229 | if (err<1) | ||
1230 | return -6; | ||
1231 | } | ||
1232 | sector++; | ||
1233 | } | ||
1234 | } | ||
1235 | |||
1236 | if ( entry % DIR_ENTRIES_PER_SECTOR ) { | ||
1237 | /* flush this sector */ | ||
1238 | err = fat_seek(&dir, sector); | ||
1239 | if (err<0) | ||
1240 | return -7; | ||
1241 | |||
1242 | err = fat_readwrite(&dir, 1, buf, true); | ||
1243 | if (err<1) | ||
1244 | return -8; | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1157 | file->firstcluster = 0; | 1248 | file->firstcluster = 0; |
1249 | file->dircluster = 0; | ||
1158 | 1250 | ||
1159 | return 0; | 1251 | return 0; |
1160 | } | 1252 | } |
@@ -1384,9 +1476,11 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1384 | int sectoridx=0; | 1476 | int sectoridx=0; |
1385 | static unsigned char cached_buf[SECTOR_SIZE]; | 1477 | static unsigned char cached_buf[SECTOR_SIZE]; |
1386 | 1478 | ||
1479 | dir->entrycount = 0; | ||
1480 | |||
1387 | while(!done) | 1481 | while(!done) |
1388 | { | 1482 | { |
1389 | if ( dir->entry >= DIR_ENTRIES_PER_SECTOR || !dir->sector ) | 1483 | if ( !(dir->entry % DIR_ENTRIES_PER_SECTOR) || !dir->sector ) |
1390 | { | 1484 | { |
1391 | err = fat_readwrite(&dir->file, 1, cached_buf, false); | 1485 | err = fat_readwrite(&dir->file, 1, cached_buf, false); |
1392 | if (err==0) { | 1486 | if (err==0) { |
@@ -1400,7 +1494,6 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1400 | return -1; | 1494 | return -1; |
1401 | } | 1495 | } |
1402 | dir->sector = dir->file.lastsector; | 1496 | dir->sector = dir->file.lastsector; |
1403 | dir->entry = 0; | ||
1404 | } | 1497 | } |
1405 | 1498 | ||
1406 | for (i = dir->entry % DIR_ENTRIES_PER_SECTOR; | 1499 | for (i = dir->entry % DIR_ENTRIES_PER_SECTOR; |
@@ -1414,15 +1507,19 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1414 | if (firstbyte == 0xe5) { | 1507 | if (firstbyte == 0xe5) { |
1415 | /* free entry */ | 1508 | /* free entry */ |
1416 | sectoridx = 0; | 1509 | sectoridx = 0; |
1510 | dir->entrycount = 0; | ||
1417 | continue; | 1511 | continue; |
1418 | } | 1512 | } |
1419 | 1513 | ||
1420 | if (firstbyte == 0) { | 1514 | if (firstbyte == 0) { |
1421 | /* last entry */ | 1515 | /* last entry */ |
1422 | entry->name[0] = 0; | 1516 | entry->name[0] = 0; |
1517 | dir->entrycount = 0; | ||
1423 | return 0; | 1518 | return 0; |
1424 | } | 1519 | } |
1425 | 1520 | ||
1521 | dir->entrycount++; | ||
1522 | |||
1426 | /* longname entry? */ | 1523 | /* longname entry? */ |
1427 | if ( ( cached_buf[entrypos + FATDIR_ATTR] & | 1524 | if ( ( cached_buf[entrypos + FATDIR_ATTR] & |
1428 | FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { | 1525 | FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { |
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index f05acf3c8f..a5abfd5214 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h | |||
@@ -52,14 +52,16 @@ struct fat_file | |||
52 | int lastcluster; /* cluster of last access */ | 52 | int lastcluster; /* cluster of last access */ |
53 | int lastsector; /* sector of last access */ | 53 | int lastsector; /* sector of last access */ |
54 | int sectornum; /* sector number in this cluster */ | 54 | int sectornum; /* sector number in this cluster */ |
55 | int dirsector; /* sector where the dir entry is located */ | 55 | unsigned int direntry; /* short dir entry index from start of dir */ |
56 | int direntry; /* dir entry index in sector */ | 56 | unsigned int direntries; /* number of dir entries used by this file */ |
57 | unsigned int dircluster; /* first cluster of dir */ | ||
57 | bool eof; | 58 | bool eof; |
58 | }; | 59 | }; |
59 | 60 | ||
60 | struct fat_dir | 61 | struct fat_dir |
61 | { | 62 | { |
62 | unsigned int entry; | 63 | unsigned int entry; |
64 | unsigned int entrycount; | ||
63 | int sector; | 65 | int sector; |
64 | struct fat_file file; | 66 | struct fat_file file; |
65 | }; | 67 | }; |