forked from len0rd/rockbox
Dircache: Fix 2 nasty bugs introduced with the reworks starting with r30032.
The first is an off-by-one that leads to miscalculation of the dircache size. The format string size was used but dircache size was incremented by the snprintf() result which is smaller. The other forgot to update the location of the "." and ".." strings upon compaction, so that new folders got assigned orphaned pointers for those directory entires. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30224 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
564b696500
commit
32b54164d8
1 changed files with 13 additions and 8 deletions
|
@ -336,9 +336,12 @@ static int dircache_scan_and_build(IF_MV2(int volume,) struct dircache_entry *ce
|
|||
#ifdef HAVE_MULTIVOLUME
|
||||
if (volume > 0)
|
||||
{
|
||||
ce->d_name = (d_names_start -= sizeof(VOL_NAMES));
|
||||
size_t len = snprintf(ce->d_name, VOL_ENUM_POS + 3, VOL_NAMES, volume)+1;
|
||||
dircache_size += len;
|
||||
/* broken for 100+ volumes because the format string is too small
|
||||
* and we use that for size calculation */
|
||||
const size_t max_len = VOL_ENUM_POS + 3;
|
||||
ce->d_name = (d_names_start -= max_len);
|
||||
snprintf(ce->d_name, max_len, VOL_NAMES, volume);
|
||||
dircache_size += max_len;
|
||||
ce->info.attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
|
||||
ce->info.size = 0;
|
||||
append_position = dircache_gen_next(ce);
|
||||
|
@ -844,8 +847,7 @@ int dircache_build(int last_size)
|
|||
allocated_size = last_size + DIRCACHE_RESERVE;
|
||||
dircache_root = buffer_alloc(allocated_size);
|
||||
ALIGN_BUFFER(dircache_root, allocated_size, sizeof(struct dircache_entry));
|
||||
d_names_start =
|
||||
d_names_end = ((char*)dircache_root)+allocated_size-1;
|
||||
d_names_start = d_names_end = ((char*)dircache_root)+allocated_size-1;
|
||||
dircache_size = 0;
|
||||
thread_enabled = true;
|
||||
generate_dot_d_names();
|
||||
|
@ -873,12 +875,13 @@ int dircache_build(int last_size)
|
|||
|
||||
/* now compact the dircache buffer */
|
||||
char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE);
|
||||
ptrdiff_t offset = d_names_start - dst, size_to_move;
|
||||
ptrdiff_t offset = d_names_start - dst;
|
||||
if (offset <= 0) /* something went wrong */
|
||||
return -1;
|
||||
|
||||
/* memmove d_names down, there's a possibility of overlap */
|
||||
size_to_move = dircache_size - entry_count*sizeof(struct dircache_entry);
|
||||
/* memmove d_names down, there's a possibility of overlap
|
||||
* equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */
|
||||
ptrdiff_t size_to_move = d_names_end - d_names_start;
|
||||
memmove(dst, d_names_start, size_to_move);
|
||||
|
||||
/* fix up pointers to the d_names */
|
||||
|
@ -887,6 +890,8 @@ int dircache_build(int last_size)
|
|||
|
||||
d_names_start -= offset;
|
||||
d_names_end -= offset;
|
||||
dot -= offset;
|
||||
dotdot -= offset;
|
||||
|
||||
/* equivalent to dircache_size + DIRCACHE_RESERVE */
|
||||
allocated_size = (d_names_end - (char*)dircache_root);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue