forked from len0rd/rockbox
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
This commit is contained in:
parent
7aabb1ab66
commit
eee2c01697
2 changed files with 246 additions and 147 deletions
|
|
@ -100,7 +100,6 @@
|
||||||
#define FATDIR_FILESIZE 28
|
#define FATDIR_FILESIZE 28
|
||||||
|
|
||||||
#define FATLONG_ORDER 0
|
#define FATLONG_ORDER 0
|
||||||
#define FATLONG_ATTR 11
|
|
||||||
#define FATLONG_TYPE 12
|
#define FATLONG_TYPE 12
|
||||||
#define FATLONG_CHKSUM 13
|
#define FATLONG_CHKSUM 13
|
||||||
|
|
||||||
|
|
@ -648,9 +647,9 @@ static int write_long_name(struct fat_file* file,
|
||||||
unsigned char* entry;
|
unsigned char* entry;
|
||||||
unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR;
|
unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR;
|
||||||
unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR;
|
unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR;
|
||||||
unsigned int i, j=0, nameidx;
|
unsigned int i, j=0;
|
||||||
unsigned char chksum = 0;
|
unsigned char chksum = 0;
|
||||||
unsigned int namelen = strlen(name);
|
int nameidx=0, namelen = strlen(name);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
LDEBUGF("write_long_name(file:%x, first:%d, num:%d, name:%s)\n",
|
LDEBUGF("write_long_name(file:%x, first:%d, num:%d, name:%s)\n",
|
||||||
|
|
@ -669,6 +668,7 @@ static int write_long_name(struct fat_file* file,
|
||||||
chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];
|
chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];
|
||||||
|
|
||||||
/* calc position of last name segment */
|
/* calc position of last name segment */
|
||||||
|
if ( namelen > NAME_BYTES_PER_ENTRY )
|
||||||
for (nameidx=0;
|
for (nameidx=0;
|
||||||
nameidx < (namelen - NAME_BYTES_PER_ENTRY);
|
nameidx < (namelen - NAME_BYTES_PER_ENTRY);
|
||||||
nameidx += NAME_BYTES_PER_ENTRY);
|
nameidx += NAME_BYTES_PER_ENTRY);
|
||||||
|
|
@ -685,10 +685,15 @@ static int write_long_name(struct fat_file* file,
|
||||||
if (rc<1)
|
if (rc<1)
|
||||||
return -4;
|
return -4;
|
||||||
|
|
||||||
/* grab next sector */
|
/* read next sector */
|
||||||
rc = fat_readwrite(file, 1, buf, false);
|
rc = fat_readwrite(file, 1, buf, false);
|
||||||
if (rc<1)
|
if (rc<0) {
|
||||||
|
LDEBUGF("Failed writing new sector: %d\n",rc);
|
||||||
return -5;
|
return -5;
|
||||||
|
}
|
||||||
|
if (rc==0)
|
||||||
|
/* end of dir */
|
||||||
|
memset(buf, 0, sizeof buf);
|
||||||
|
|
||||||
sector++;
|
sector++;
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
@ -707,13 +712,34 @@ static int write_long_name(struct fat_file* file,
|
||||||
if ( i+1 < numentries ) {
|
if ( i+1 < numentries ) {
|
||||||
/* longname entry */
|
/* longname entry */
|
||||||
int k, l = nameidx;
|
int k, l = nameidx;
|
||||||
|
|
||||||
entry[FATLONG_ORDER] = numentries-i-1;
|
entry[FATLONG_ORDER] = numentries-i-1;
|
||||||
if (i==0)
|
if (i==0) {
|
||||||
|
/* mark this as last long entry */
|
||||||
entry[FATLONG_ORDER] |= 0x40;
|
entry[FATLONG_ORDER] |= 0x40;
|
||||||
for (k=0; k<5 && name[l]; k++) entry[k*2 + 1] = name[l++];
|
|
||||||
for (k=0; k<6 && name[l]; k++) entry[k*2 + 14] = name[l++];
|
/* pad name with 0xffff */
|
||||||
for (k=0; k<2 && name[l]; k++) entry[k*2 + 28] = name[l++];
|
for (k=1; k<12; k++) entry[k] = 0xff;
|
||||||
entry[FATLONG_ATTR] = FAT_ATTR_LONG_NAME;
|
for (k=14; k<26; k++) entry[k] = 0xff;
|
||||||
|
for (k=28; k<32; k++) entry[k] = 0xff;
|
||||||
|
};
|
||||||
|
/* set name */
|
||||||
|
for (k=0; k<5 && l <= namelen; k++) {
|
||||||
|
entry[k*2 + 1] = name[l++];
|
||||||
|
entry[k*2 + 2] = 0;
|
||||||
|
}
|
||||||
|
for (k=0; k<6 && l <= namelen; k++) {
|
||||||
|
entry[k*2 + 14] = name[l++];
|
||||||
|
entry[k*2 + 15] = 0;
|
||||||
|
}
|
||||||
|
for (k=0; k<2 && l <= namelen; k++) {
|
||||||
|
entry[k*2 + 28] = name[l++];
|
||||||
|
entry[k*2 + 29] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry[FATDIR_ATTR] = FAT_ATTR_LONG_NAME;
|
||||||
|
entry[FATDIR_FSTCLUSLO] = 0;
|
||||||
|
entry[FATLONG_TYPE] = 0;
|
||||||
entry[FATLONG_CHKSUM] = chksum;
|
entry[FATLONG_CHKSUM] = chksum;
|
||||||
LDEBUGF("Longname entry %d: %.13s\n", idx, name+nameidx);
|
LDEBUGF("Longname entry %d: %.13s\n", idx, name+nameidx);
|
||||||
}
|
}
|
||||||
|
|
@ -726,7 +752,6 @@ static int write_long_name(struct fat_file* file,
|
||||||
}
|
}
|
||||||
idx++;
|
idx++;
|
||||||
nameidx -= NAME_BYTES_PER_ENTRY;
|
nameidx -= NAME_BYTES_PER_ENTRY;
|
||||||
//dbg_dump_buffer(buf, SECTOR_SIZE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update last sector */
|
/* update last sector */
|
||||||
|
|
@ -751,8 +776,10 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
unsigned int sector;
|
unsigned int sector;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
|
bool last = false;
|
||||||
int entries_needed, entries_found = 0;
|
int entries_needed, entries_found = 0;
|
||||||
int namelen = strlen(name);
|
int namelen = strlen(name);
|
||||||
|
int firstentry;
|
||||||
|
|
||||||
LDEBUGF( "add_dir_entry(%s,%x)\n",
|
LDEBUGF( "add_dir_entry(%s,%x)\n",
|
||||||
name, file->firstcluster);
|
name, file->firstcluster);
|
||||||
|
|
@ -767,6 +794,9 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
if (namelen % NAME_BYTES_PER_ENTRY)
|
if (namelen % NAME_BYTES_PER_ENTRY)
|
||||||
entries_needed++;
|
entries_needed++;
|
||||||
|
|
||||||
|
restart:
|
||||||
|
firstentry = 0;
|
||||||
|
|
||||||
err=fat_seek(&dir->file, 0);
|
err=fat_seek(&dir->file, 0);
|
||||||
if (err<0)
|
if (err<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -803,7 +833,7 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* look for free slots */
|
/* look for free slots */
|
||||||
for (i=0; i < DIR_ENTRIES_PER_SECTOR; i++)
|
for (i=0; i < DIR_ENTRIES_PER_SECTOR && !done; i++)
|
||||||
{
|
{
|
||||||
unsigned char firstbyte = buf[i * DIR_ENTRY_SIZE];
|
unsigned char firstbyte = buf[i * DIR_ENTRY_SIZE];
|
||||||
switch (firstbyte) {
|
switch (firstbyte) {
|
||||||
|
|
@ -811,6 +841,8 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
entries_found = entries_needed;
|
entries_found = entries_needed;
|
||||||
LDEBUGF("Found last entry %d\n",
|
LDEBUGF("Found last entry %d\n",
|
||||||
sector * DIR_ENTRIES_PER_SECTOR + i);
|
sector * DIR_ENTRIES_PER_SECTOR + i);
|
||||||
|
last = true;
|
||||||
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xe5: /* free entry */
|
case 0xe5: /* free entry */
|
||||||
|
|
@ -822,20 +854,34 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
|
|
||||||
default:
|
default:
|
||||||
entries_found = 0;
|
entries_found = 0;
|
||||||
|
|
||||||
|
/* check that our intended shortname doesn't already exist */
|
||||||
|
if (!strncmp(shortname, buf + i * DIR_ENTRY_SIZE, 12)) {
|
||||||
|
/* filename exists already. make a new one */
|
||||||
|
snprintf(shortname+8, 4, "%03X", (unsigned)rand() & 0xfff);
|
||||||
|
LDEBUGF("Duplicate shortname, changing to %s\n",
|
||||||
|
shortname);
|
||||||
|
|
||||||
|
/* name has changed, we need to restart search */
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entries_found == entries_needed)
|
if (!firstentry && (entries_found == entries_needed)) {
|
||||||
{
|
firstentry = sector * DIR_ENTRIES_PER_SECTOR + i;
|
||||||
int firstentry = sector * DIR_ENTRIES_PER_SECTOR + i;
|
|
||||||
|
|
||||||
/* if we're not extending the dir, we must go back to first
|
/* if we're not extending the dir,
|
||||||
free entry */
|
we must go back to first free entry */
|
||||||
if (firstbyte)
|
if (!last)
|
||||||
firstentry -= (entries_needed - 1);
|
firstentry -= (entries_needed - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sector = firstentry / DIR_ENTRIES_PER_SECTOR;
|
||||||
LDEBUGF("Adding longname to entry %d in sector %d\n",
|
LDEBUGF("Adding longname to entry %d in sector %d\n",
|
||||||
i, sector);
|
firstentry, sector);
|
||||||
|
|
||||||
err = write_long_name(&dir->file, firstentry,
|
err = write_long_name(&dir->file, firstentry,
|
||||||
entries_needed, name, shortname);
|
entries_needed, name, shortname);
|
||||||
|
|
@ -843,18 +889,45 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
return -5;
|
return -5;
|
||||||
|
|
||||||
/* remember where the shortname dir entry is located */
|
/* remember where the shortname dir entry is located */
|
||||||
file->dirsector = dir->file.lastsector;
|
file->direntry = firstentry + entries_needed - 1;
|
||||||
file->direntry =
|
file->direntries = entries_needed;
|
||||||
(i + entries_needed - 1) % DIR_ENTRIES_PER_SECTOR;
|
file->dircluster = dir->file.firstcluster;
|
||||||
|
LDEBUGF("Added new dir entry %d, using %d slots.\n",
|
||||||
|
file->direntry, file->direntries);
|
||||||
|
|
||||||
/* advance the last_empty_entry marker? */
|
/* advance the end-of-dir marker? */
|
||||||
if (firstbyte == 0)
|
if (last)
|
||||||
{
|
{
|
||||||
i++;
|
unsigned int lastentry = firstentry + entries_needed;
|
||||||
if (i < DIR_ENTRIES_PER_SECTOR)
|
|
||||||
|
LDEBUGF("Updating end-of-dir entry %d\n",lastentry);
|
||||||
|
|
||||||
|
if (lastentry % DIR_ENTRIES_PER_SECTOR)
|
||||||
{
|
{
|
||||||
/* next entry is now last */
|
int idx = (lastentry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE;
|
||||||
buf[i*DIR_ENTRY_SIZE] = 0;
|
|
||||||
|
err=fat_seek(&dir->file, lastentry / DIR_ENTRIES_PER_SECTOR);
|
||||||
|
if (err<0)
|
||||||
|
return -6;
|
||||||
|
|
||||||
|
err = fat_readwrite(&dir->file, 1, buf, false);
|
||||||
|
if (err<1)
|
||||||
|
return -7;
|
||||||
|
|
||||||
|
/* clear last entry */
|
||||||
|
buf[idx] = 0;
|
||||||
|
|
||||||
|
err=fat_seek(&dir->file, lastentry / DIR_ENTRIES_PER_SECTOR);
|
||||||
|
if (err<0)
|
||||||
|
return -8;
|
||||||
|
|
||||||
|
/* we must clear entire last cluster */
|
||||||
|
do {
|
||||||
|
err = fat_readwrite(&dir->file, 1, buf, true);
|
||||||
|
if (err<1)
|
||||||
|
return -9;
|
||||||
|
memset(buf, 0, sizeof buf);
|
||||||
|
} while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -863,14 +936,8 @@ static int add_dir_entry(struct fat_dir* dir,
|
||||||
do {
|
do {
|
||||||
err = fat_readwrite(&dir->file, 1, buf, true);
|
err = fat_readwrite(&dir->file, 1, buf, true);
|
||||||
if (err<1)
|
if (err<1)
|
||||||
return -6;
|
return -10;
|
||||||
} while (dir->file.sectornum <
|
} while (dir->file.sectornum < (int)fat_bpb.bpb_secperclus);
|
||||||
(int)fat_bpb.bpb_secperclus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -916,89 +983,54 @@ unsigned char char2dos(unsigned char c)
|
||||||
|
|
||||||
static int create_dos_name(unsigned char *name, unsigned char *newname)
|
static int create_dos_name(unsigned char *name, unsigned char *newname)
|
||||||
{
|
{
|
||||||
unsigned char n[12];
|
int i,j;
|
||||||
unsigned char c;
|
|
||||||
int i;
|
|
||||||
char *ext;
|
|
||||||
|
|
||||||
strncpy(n, name, sizeof n);
|
|
||||||
|
|
||||||
ext = strchr(n, '.');
|
|
||||||
if(ext)
|
|
||||||
{
|
|
||||||
*ext++ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The file name is either empty, or there was only an extension.
|
|
||||||
In either case it is illegal. */
|
|
||||||
if(n[0] == 0)
|
|
||||||
{
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Name part */
|
/* Name part */
|
||||||
for(i = 0;n[i] && (i < 8);i++)
|
for (i=0, j=0; name[i] && (j < 8); i++)
|
||||||
{
|
{
|
||||||
c = char2dos(n[i]);
|
unsigned char c = char2dos(name[i]);
|
||||||
if(c)
|
if (c)
|
||||||
{
|
newname[j++] = toupper(c);
|
||||||
newname[i] = toupper(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(i < 8)
|
|
||||||
{
|
|
||||||
newname[i++] = ' ';
|
|
||||||
}
|
}
|
||||||
|
while (j < 8)
|
||||||
|
newname[j++] = ' ';
|
||||||
|
|
||||||
/* Extension part */
|
/* Extension part */
|
||||||
for (i = 0;ext && ext[i] && (i < 3);i++)
|
snprintf(newname+8, 4, "%03X", (unsigned)rand() & 0xfff);
|
||||||
{
|
|
||||||
c = char2dos(ext[i]);
|
|
||||||
if (c)
|
|
||||||
{
|
|
||||||
newname[8+i] = toupper(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(i < 3)
|
|
||||||
{
|
|
||||||
newname[8+i++] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
newname[11] = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int update_file_size( struct fat_file* file, int size )
|
static int update_file_size( struct fat_file* file, int size )
|
||||||
{
|
{
|
||||||
unsigned char buf[SECTOR_SIZE];
|
unsigned char buf[SECTOR_SIZE];
|
||||||
int sector = file->dirsector + fat_bpb.startsector;
|
int sector = file->direntry / DIR_ENTRIES_PER_SECTOR;
|
||||||
unsigned char* entry = buf + file->direntry * DIR_ENTRY_SIZE;
|
unsigned char* entry =
|
||||||
|
buf + DIR_ENTRY_SIZE * (file->direntry % DIR_ENTRIES_PER_SECTOR);
|
||||||
unsigned int* sizeptr;
|
unsigned int* sizeptr;
|
||||||
unsigned short* clusptr;
|
unsigned short* clusptr;
|
||||||
|
struct fat_file dir;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
LDEBUGF("update_file_size(cluster:%x entry:%d sector:%x size:%d)\n",
|
LDEBUGF("update_file_size(cluster:%x entry:%d size:%d)\n",
|
||||||
file->firstcluster, file->direntry, file->dirsector, size);
|
file->firstcluster, file->direntry, size);
|
||||||
|
|
||||||
if ( file->direntry >= DIR_ENTRIES_PER_SECTOR )
|
/* create a temporary file handle for the dir holding this file */
|
||||||
panicf("update_file_size(): Illegal entry %d!\n",file->direntry);
|
err = fat_open(file->dircluster, &dir, NULL);
|
||||||
|
if (err<0)
|
||||||
if ( file->direntry < 0 )
|
|
||||||
panicf("update_file_size(): Illegal entry %d!\n",file->direntry);
|
|
||||||
|
|
||||||
err = ata_read_sectors(sector, 1, buf);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
DEBUGF( "update_file_size() - Couldn't read dir sector %d"
|
|
||||||
" (error code %d)\n", sector, err);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ( size == -1 ) {
|
err = fat_seek( &dir, sector );
|
||||||
/* mark entry deleted */
|
if (err<0)
|
||||||
entry[0] = 0xe5;
|
return -2;
|
||||||
}
|
|
||||||
else {
|
err = fat_readwrite(&dir, 1, buf, false);
|
||||||
|
if (err<1)
|
||||||
|
return -3;
|
||||||
|
|
||||||
|
if (!entry[0] || entry[0] == 0xe5)
|
||||||
|
panicf("Updating size on empty dir entry %d\n", file->direntry);
|
||||||
|
|
||||||
clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
|
clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
|
||||||
*clusptr = SWAB16(file->firstcluster >> 16);
|
*clusptr = SWAB16(file->firstcluster >> 16);
|
||||||
|
|
||||||
|
|
@ -1007,15 +1039,14 @@ static int update_file_size( struct fat_file* file, int size )
|
||||||
|
|
||||||
sizeptr = (int*)(entry + FATDIR_FILESIZE);
|
sizeptr = (int*)(entry + FATDIR_FILESIZE);
|
||||||
*sizeptr = SWAB32(size);
|
*sizeptr = SWAB32(size);
|
||||||
}
|
|
||||||
|
|
||||||
err = ata_write_sectors(sector, 1, buf);
|
err = fat_seek( &dir, sector );
|
||||||
if (err)
|
if (err<0)
|
||||||
{
|
return -4;
|
||||||
DEBUGF( "update_file_size() - Couldn't write dir sector %d"
|
|
||||||
" (error code %d)\n", sector, err);
|
err = fat_readwrite(&dir, 1, buf, true);
|
||||||
return -2;
|
if (err<1)
|
||||||
}
|
return -5;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1057,8 +1088,9 @@ int fat_open(unsigned int startcluster,
|
||||||
|
|
||||||
/* remember where the file's dir entry is located */
|
/* remember where the file's dir entry is located */
|
||||||
if ( dir ) {
|
if ( dir ) {
|
||||||
file->dirsector = dir->sector;
|
|
||||||
file->direntry = dir->entry - 1;
|
file->direntry = dir->entry - 1;
|
||||||
|
file->direntries = dir->entrycount;
|
||||||
|
file->dircluster = dir->file.firstcluster;
|
||||||
}
|
}
|
||||||
LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry);
|
LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1113,7 +1145,7 @@ int fat_closewrite(struct fat_file *file, int size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->dirsector)
|
if (file->dircluster)
|
||||||
if (update_file_size(file, size) < 0)
|
if (update_file_size(file, size) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
@ -1152,9 +1184,69 @@ int fat_remove(struct fat_file* file)
|
||||||
update_fat_entry(last,0);
|
update_fat_entry(last,0);
|
||||||
last = next;
|
last = next;
|
||||||
}
|
}
|
||||||
update_file_size(file, -1);
|
|
||||||
file->dirsector = 0;
|
/* free all dir entries */
|
||||||
|
if ( file->dircluster ) {
|
||||||
|
unsigned char buf[SECTOR_SIZE];
|
||||||
|
struct fat_file dir;
|
||||||
|
unsigned int entry = file->direntry - file->direntries + 1;
|
||||||
|
unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR;
|
||||||
|
unsigned int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* create a temporary file handle for the dir holding this file */
|
||||||
|
err = fat_open(file->dircluster, &dir, NULL);
|
||||||
|
if (err<0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
err = fat_seek( &dir, sector );
|
||||||
|
if (err<0)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
err = fat_readwrite(&dir, 1, buf, false);
|
||||||
|
if (err<1)
|
||||||
|
return -3;
|
||||||
|
|
||||||
|
for (i=0; i < file->direntries; i++) {
|
||||||
|
LDEBUGF("Clearing dir entry %d (%d/%d)\n",
|
||||||
|
entry, i+1, file->direntries);
|
||||||
|
buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5;
|
||||||
|
entry++;
|
||||||
|
|
||||||
|
if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) {
|
||||||
|
/* flush this sector */
|
||||||
|
err = fat_seek(&dir, sector);
|
||||||
|
if (err<0)
|
||||||
|
return -4;
|
||||||
|
|
||||||
|
err = fat_readwrite(&dir, 1, buf, true);
|
||||||
|
if (err<1)
|
||||||
|
return -5;
|
||||||
|
|
||||||
|
if ( i+1 < file->direntries ) {
|
||||||
|
/* read next sector */
|
||||||
|
err = fat_readwrite(&dir, 1, buf, false);
|
||||||
|
if (err<1)
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
sector++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( entry % DIR_ENTRIES_PER_SECTOR ) {
|
||||||
|
/* flush this sector */
|
||||||
|
err = fat_seek(&dir, sector);
|
||||||
|
if (err<0)
|
||||||
|
return -7;
|
||||||
|
|
||||||
|
err = fat_readwrite(&dir, 1, buf, true);
|
||||||
|
if (err<1)
|
||||||
|
return -8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
file->firstcluster = 0;
|
file->firstcluster = 0;
|
||||||
|
file->dircluster = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1384,9 +1476,11 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
int sectoridx=0;
|
int sectoridx=0;
|
||||||
static unsigned char cached_buf[SECTOR_SIZE];
|
static unsigned char cached_buf[SECTOR_SIZE];
|
||||||
|
|
||||||
|
dir->entrycount = 0;
|
||||||
|
|
||||||
while(!done)
|
while(!done)
|
||||||
{
|
{
|
||||||
if ( dir->entry >= DIR_ENTRIES_PER_SECTOR || !dir->sector )
|
if ( !(dir->entry % DIR_ENTRIES_PER_SECTOR) || !dir->sector )
|
||||||
{
|
{
|
||||||
err = fat_readwrite(&dir->file, 1, cached_buf, false);
|
err = fat_readwrite(&dir->file, 1, cached_buf, false);
|
||||||
if (err==0) {
|
if (err==0) {
|
||||||
|
|
@ -1400,7 +1494,6 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dir->sector = dir->file.lastsector;
|
dir->sector = dir->file.lastsector;
|
||||||
dir->entry = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = dir->entry % DIR_ENTRIES_PER_SECTOR;
|
for (i = dir->entry % DIR_ENTRIES_PER_SECTOR;
|
||||||
|
|
@ -1414,15 +1507,19 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
|
||||||
if (firstbyte == 0xe5) {
|
if (firstbyte == 0xe5) {
|
||||||
/* free entry */
|
/* free entry */
|
||||||
sectoridx = 0;
|
sectoridx = 0;
|
||||||
|
dir->entrycount = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstbyte == 0) {
|
if (firstbyte == 0) {
|
||||||
/* last entry */
|
/* last entry */
|
||||||
entry->name[0] = 0;
|
entry->name[0] = 0;
|
||||||
|
dir->entrycount = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dir->entrycount++;
|
||||||
|
|
||||||
/* longname entry? */
|
/* longname entry? */
|
||||||
if ( ( cached_buf[entrypos + FATDIR_ATTR] &
|
if ( ( cached_buf[entrypos + FATDIR_ATTR] &
|
||||||
FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) {
|
FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) {
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,16 @@ struct fat_file
|
||||||
int lastcluster; /* cluster of last access */
|
int lastcluster; /* cluster of last access */
|
||||||
int lastsector; /* sector of last access */
|
int lastsector; /* sector of last access */
|
||||||
int sectornum; /* sector number in this cluster */
|
int sectornum; /* sector number in this cluster */
|
||||||
int dirsector; /* sector where the dir entry is located */
|
unsigned int direntry; /* short dir entry index from start of dir */
|
||||||
int direntry; /* dir entry index in sector */
|
unsigned int direntries; /* number of dir entries used by this file */
|
||||||
|
unsigned int dircluster; /* first cluster of dir */
|
||||||
bool eof;
|
bool eof;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fat_dir
|
struct fat_dir
|
||||||
{
|
{
|
||||||
unsigned int entry;
|
unsigned int entry;
|
||||||
|
unsigned int entrycount;
|
||||||
int sector;
|
int sector;
|
||||||
struct fat_file file;
|
struct fat_file file;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue