Workaround for garbage in the root directory.

This commit is contained in:
relan
2016-05-26 16:15:54 +03:00
parent a6a2d06fda
commit a2a3834b6e
3 changed files with 28 additions and 11 deletions
+2 -2
View File
@@ -369,7 +369,7 @@ static bool erase_raw(struct exfat* ef, size_t size, off_t offset)
return true;
}
static int erase_range(struct exfat* ef, struct exfat_node* node,
int exfat_erase_range(struct exfat* ef, struct exfat_node* node,
uint64_t begin, uint64_t end)
{
uint64_t cluster_boundary;
@@ -427,7 +427,7 @@ int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size,
if (erase)
{
rc = erase_range(ef, node, node->size, size);
rc = exfat_erase_range(ef, node, node->size, size);
if (rc != 0)
return rc;
}
+2
View File
@@ -170,6 +170,8 @@ cluster_t exfat_advance_cluster(const struct exfat* ef,
struct exfat_node* node, uint32_t count);
int exfat_flush_nodes(struct exfat* ef);
int exfat_flush(struct exfat* ef);
int exfat_erase_range(struct exfat* ef, struct exfat_node* node,
uint64_t begin, uint64_t end);
int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size,
bool erase);
uint32_t exfat_count_free_clusters(const struct exfat* ef);
+24 -9
View File
@@ -251,7 +251,7 @@ static void decompress_upcase(uint16_t* output, const le16_t* source,
* Reads one entry in directory at position pointed by iterator and fills
* node structure.
*/
static int readdir(struct exfat* ef, const struct exfat_node* parent,
static int readdir(struct exfat* ef, struct exfat_node* parent,
struct exfat_node** node, struct iterator* it)
{
int rc = -EIO;
@@ -275,14 +275,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
for (;;)
{
if (it->offset >= parent->size)
{
if (continuations != 0)
{
exfat_error("expected %hhu continuations", continuations);
goto error;
}
return -ENOENT; /* that's OK, means end of directory */
}
goto success;
entry = get_entry_ptr(ef, it);
switch (entry->type)
@@ -490,6 +483,20 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent,
goto error;
break;
case 0:
/* exFAT does not have end-of-directory entries. However, we can
safely assume that there are no valid entries in a directory
after a zero entry. The problem here is that some buggy cameras
have garbage after it in the root directory. As a workaround,
we zero out root directory space after the first zero entry. */
if (!ef->ro && parent == ef->root)
{
rc = exfat_erase_range(ef, parent, it->offset, parent->size);
if (rc != 0)
goto error;
}
goto success;
default:
if (!(entry->type & EXFAT_ENTRY_VALID))
break; /* deleted entry, ignore it */
@@ -518,6 +525,14 @@ error:
free(*node);
*node = NULL;
return rc;
success:
if (continuations != 0)
{
exfat_error("expected %hhu continuations", continuations);
goto error;
}
return -ENOENT; /* that's OK, means end of directory */
}
int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)