summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-01-03 07:59:49 +0000
committerJens Arnold <amiconn@rockbox.org>2005-01-03 07:59:49 +0000
commit316ae187aa6fbd6ddced713b46fba847d3e652e1 (patch)
tree797390856dc722f0ee0c0122d97b1b75a8d43374
parent98ccef267f033fa444a0ca269ec3037a3f7115d7 (diff)
downloadrockbox-316ae187aa6fbd6ddced713b46fba847d3e652e1.tar.gz
rockbox-316ae187aa6fbd6ddced713b46fba847d3e652e1.zip
Correct handling of FAT16 root directory when it does not start on a pseudo cluster boundary. Fixed some places where the cluster number can become negative. Significant code cleanup.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5527 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/fat.c124
-rw-r--r--firmware/export/fat.h8
2 files changed, 46 insertions, 86 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index b4b256c142..81e12fd0b4 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -217,7 +217,8 @@ struct bpb
int bpb_rootentcnt; /* Number of dir entries in the root */
/* internals for FAT16 support */
bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */
- unsigned int rootdirsectors; /* fixed # of sectors occupied by root dir */
+ unsigned int rootdiroffset; /* sector offset of root dir relative to start
+ * of first pseudo cluster */
#endif /* #ifdef HAVE_FAT16SUPPORT */
#ifdef HAVE_MULTIVOLUME
int drive; /* on which physical device is this located */
@@ -229,7 +230,6 @@ static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb));
-static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster);
static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int secnum);
static int create_dos_name(const unsigned char *name, unsigned char *newname);
static unsigned int find_free_cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int start);
@@ -251,50 +251,28 @@ struct fat_cache_entry
static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
-static int sec2cluster(IF_MV2(struct bpb* fat_bpb,) unsigned int sec)
-{
-#ifndef HAVE_MULTIVOLUME
- struct bpb* fat_bpb = &fat_bpbs[0];
-#endif
- if ( sec < fat_bpb->firstdatasector )
- {
- DEBUGF( "sec2cluster() - Bad sector number (%d)\n", sec);
- return -1;
- }
-
- return ((sec - fat_bpb->firstdatasector) / fat_bpb->bpb_secperclus) + 2;
-}
-
static int cluster2sec(IF_MV2(struct bpb* fat_bpb,) int cluster)
{
#ifndef HAVE_MULTIVOLUME
struct bpb* fat_bpb = &fat_bpbs[0];
#endif
+#ifdef HAVE_FAT16SUPPORT
+ /* negative clusters (FAT16 root dir) don't get the 2 offset */
+ int zerocluster = cluster < 0 ? 0 : 2;
+#else
+ const int zerocluster = 2;
+#endif
int max_cluster = fat_bpb->totalsectors -
fat_bpb->firstdatasector / fat_bpb->bpb_secperclus + 1;
- if(cluster > max_cluster)
+ if (cluster > max_cluster)
{
- DEBUGF( "cluster2sec() - Bad cluster number (%d)\n",
- cluster);
+ DEBUGF( "cluster2sec() - Bad cluster number (%d)\n", cluster);
return -1;
}
- return first_sector_of_cluster(IF_MV2(fat_bpb,) cluster);
-}
-
-static int first_sector_of_cluster(IF_MV2(struct bpb* fat_bpb,) int cluster)
-{
-#ifndef HAVE_MULTIVOLUME
- struct bpb* fat_bpb = &fat_bpbs[0];
-#endif
-#ifdef HAVE_FAT16SUPPORT
- /* negative clusters (FAT16 root dir) don't get the 2 offset */
- int zerocluster = cluster < 0 ? 0 : 2;
-#else
- const int zerocluster = 2;
-#endif
- return (cluster - zerocluster) * fat_bpb->bpb_secperclus + fat_bpb->firstdatasector;
+ return (cluster - zerocluster) * fat_bpb->bpb_secperclus
+ + fat_bpb->firstdatasector;
}
int fat_startsector(IF_MV_NONVOID(int volume))
@@ -349,6 +327,9 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
unsigned char buf[SECTOR_SIZE];
int rc;
int datasec;
+#ifdef HAVE_FAT16SUPPORT
+ int rootdirsectors;
+#endif
/* Read the sector */
rc = ata_read_sectors(IF_MV2(drive,) startsector,1,buf);
@@ -359,7 +340,7 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
}
memset(fat_bpb, 0, sizeof(struct bpb));
- fat_bpb->startsector = startsector;
+ fat_bpb->startsector = startsector;
#ifdef HAVE_MULTIVOLUME
fat_bpb->drive = drive;
#endif
@@ -388,13 +369,13 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
#ifdef HAVE_FAT16SUPPORT
fat_bpb->bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT);
- fat_bpb->rootdirsectors = ((fat_bpb->bpb_rootentcnt * 32)
+ rootdirsectors = ((fat_bpb->bpb_rootentcnt * 32)
+ (fat_bpb->bpb_bytspersec - 1)) / fat_bpb->bpb_bytspersec;
#endif /* #ifdef HAVE_FAT16SUPPORT */
fat_bpb->firstdatasector = fat_bpb->bpb_rsvdseccnt
#ifdef HAVE_FAT16SUPPORT
- + fat_bpb->rootdirsectors
+ + rootdirsectors
#endif
+ fat_bpb->bpb_numfats * fat_bpb->fatsize;
@@ -431,11 +412,13 @@ int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) int startsector)
int dirclusters;
fat_bpb->rootdirsector = fat_bpb->bpb_rsvdseccnt
+ fat_bpb->bpb_numfats * fat_bpb->bpb_fatsz16;
- dirclusters = ((fat_bpb->rootdirsectors + fat_bpb->bpb_secperclus - 1)
- / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */
+ dirclusters = ((rootdirsectors + fat_bpb->bpb_secperclus - 1)
+ / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */
/* I assign negative pseudo cluster numbers for the root directory,
their range is counted upward until -1. */
fat_bpb->bpb_rootclus = 0 - dirclusters; /* backwards, before the data */
+ fat_bpb->rootdiroffset = dirclusters * fat_bpb->bpb_secperclus
+ - rootdirsectors;
}
else
#endif /* #ifdef HAVE_FAT16SUPPORT */
@@ -610,7 +593,7 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
sectorbuf);
if(rc < 0)
{
- panicf("cache_fat_sector() - Could not write sector %d"
+ panicf("flush_fat_sector() - Could not write sector %d"
" (error %d)\n",
secnum, rc);
}
@@ -630,7 +613,7 @@ static void flush_fat_sector(struct fat_cache_entry *fce,
secnum, 1, sectorbuf);
if(rc < 0)
{
- panicf("cache_fat_sector() - Could not write sector %d"
+ panicf("flush_fat_sector() - Could not write sector %d"
" (error %d)\n",
secnum, rc);
}
@@ -667,7 +650,7 @@ static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,) int fatsector)
/* Load the sector if it is not cached */
if(!fce->inuse)
{
- rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
+ rc = ata_read_sectors(IF_MV2(fat_bpb->drive,)
secnum + fat_bpb->startsector,1,
sectorbuf);
if(rc < 0)
@@ -780,7 +763,7 @@ static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned int entry, uns
sec = cache_fat_sector(IF_MV2(fat_bpb,) sector);
if (!sec)
{
- DEBUGF( "update_entry() - Could not cache sector %d\n", sector);
+ DEBUGF( "update_fat_entry() - Could not cache sector %d\n", sector);
return -1;
}
fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true;
@@ -816,7 +799,7 @@ static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned int entry, uns
sec = cache_fat_sector(IF_MV2(fat_bpb,) sector);
if (!sec)
{
- DEBUGF( "update_entry() - Could not cache sector %d\n", sector);
+ DEBUGF( "update_fat_entry() - Could not cache sector %d\n", sector);
return -1;
}
fat_cache[(sector + fat_bpb->bpb_rsvdseccnt) & FAT_CACHE_MASK].dirty = true;
@@ -1541,8 +1524,8 @@ static int parse_direntry(struct fat_direntry *de, const unsigned char *buf)
return 1;
}
-int fat_open(IF_MV2(int volume,)
- unsigned int startcluster,
+int fat_open(IF_MV2(int volume,)
+ int startcluster,
struct fat_file *file,
const struct fat_dir* dir)
{
@@ -1572,33 +1555,6 @@ int fat_open(IF_MV2(int volume,)
return 0;
}
-#ifdef HAVE_FAT16SUPPORT
-/* special function to open the FAT16 root dir,
- which may not be on cluster boundary */
-static int fat_open_root(IF_MV2(int volume,)
- struct fat_file *file)
-{
- int dirclusters;
-#ifdef HAVE_MULTIVOLUME
- struct bpb* fat_bpb = &fat_bpbs[volume];
- file->volume = volume;
-#else
- struct bpb* fat_bpb = &fat_bpbs[0];
-#endif
- file->firstcluster = fat_bpb->bpb_rootclus;
- file->lastcluster = fat_bpb->bpb_rootclus;
- file->lastsector = 0;
- file->clusternum = 0;
- dirclusters = 0 - fat_bpb->bpb_rootclus; /* bpb_rootclus is the negative */
- file->sectornum = (dirclusters * fat_bpb->bpb_secperclus)
- - fat_bpb->rootdirsectors; /* cluster sectors minus real sectors */
- file->eof = false;
-
- LDEBUGF("fat_open_root(), sector %d\n", cluster2sec(fat_bpb->bpb_rootclus));
- return 0;
-}
-#endif /* #ifdef HAVE_FAT16SUPPORT */
-
int fat_create_file(const char* name,
struct fat_file* file,
struct fat_dir* dir)
@@ -2054,6 +2010,13 @@ int fat_readwrite( struct fat_file *file, int sectorcount,
/* look up first sector of file */
sector = cluster2sec(IF_MV2(fat_bpb,) file->firstcluster);
numsec=1;
+#ifdef HAVE_FAT16SUPPORT
+ if (file->firstcluster < 0)
+ { /* FAT16 root dir */
+ sector += fat_bpb->rootdiroffset;
+ numsec += fat_bpb->rootdiroffset;
+ }
+#endif
}
}
@@ -2108,6 +2071,11 @@ int fat_seek(struct fat_file *file, unsigned int seeksector )
int cluster = file->firstcluster;
int i;
+#ifdef HAVE_FAT16SUPPORT
+ if (cluster < 0) /* FAT16 root dir */
+ seeksector += fat_bpb->rootdiroffset;
+#endif
+
file->eof = false;
if (seeksector) {
/* we need to find the sector BEFORE the requested, since
@@ -2168,15 +2136,7 @@ int fat_opendir(IF_MV2(int volume,)
dir->sector = 0;
if (startcluster == 0)
- {
-#ifdef HAVE_FAT16SUPPORT
- if (fat_bpb->is_fat16)
- { /* FAT16 has the root dir outside of the data area */
- return fat_open_root(IF_MV2(volume,) &dir->file);
- }
-#endif
- startcluster = sec2cluster(IF_MV2(fat_bpb,) fat_bpb->rootdirsector);
- }
+ startcluster = fat_bpb->bpb_rootclus;
rc = fat_open(IF_MV2(volume,) startcluster, &dir->file, parent_dir);
if(rc)
diff --git a/firmware/export/fat.h b/firmware/export/fat.h
index 7150d2b09f..2f1c7be0a8 100644
--- a/firmware/export/fat.h
+++ b/firmware/export/fat.h
@@ -57,10 +57,10 @@ struct fat_file
int sectornum; /* sector number in this cluster */
unsigned int direntry; /* short dir entry index from start of dir */
unsigned int direntries; /* number of dir entries used by this file */
- unsigned int dircluster; /* first cluster of dir */
+ int dircluster; /* first cluster of dir */
bool eof;
#ifdef HAVE_MULTIVOLUME
- int volume; /* file resides on which volume */
+ int volume; /* file resides on which volume */
#endif
};
@@ -83,7 +83,7 @@ extern int fat_create_dir(const char* name,
struct fat_dir* dir);
extern int fat_startsector(IF_MV_NONVOID(int volume)); // public for config sector
extern int fat_open(IF_MV2(int volume,)
- unsigned int cluster,
+ int cluster,
struct fat_file* ent,
const struct fat_dir* dir);
extern int fat_create_file(const char* name,
@@ -96,7 +96,7 @@ extern int fat_seek(struct fat_file *ent, unsigned int sector );
extern int fat_remove(struct fat_file *ent);
extern int fat_truncate(const struct fat_file *ent);
extern int fat_rename(struct fat_file* file,
- struct fat_dir* dir,
+ struct fat_dir* dir,
const unsigned char* newname,
int size, int attr);