From: relan Date: Mon, 21 Oct 2013 07:11:48 +0000 (+0000) Subject: Handle I/O error in exfat_next_cluster(). X-Git-Tag: android-x86-6.0-r1~71 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=bbf2fe89699d9a280aa3ab7be5c893ce55d84e66;p=android-x86%2Fexternal-exfat.git Handle I/O error in exfat_next_cluster(). --- diff --git a/libexfat/cluster.c b/libexfat/cluster.c index 5cabdbb..e3cb251 100644 --- a/libexfat/cluster.c +++ b/libexfat/cluster.c @@ -83,9 +83,9 @@ cluster_t exfat_next_cluster(const struct exfat* ef, return cluster + 1; fat_offset = s2o(ef, le32_to_cpu(ef->sb->fat_sector_start)) + cluster * sizeof(cluster_t); - /* FIXME handle I/O error */ if (exfat_pread(ef->dev, &next, sizeof(next), fat_offset) < 0) - exfat_bug("failed to read the next cluster after %#x", cluster); + return EXFAT_CLUSTER_BAD; /* the caller should handle this and print + appropriate error message */ return le32_to_cpu(next); } diff --git a/libexfat/mount.c b/libexfat/mount.c index d10fc98..1202b4d 100644 --- a/libexfat/mount.c +++ b/libexfat/mount.c @@ -39,6 +39,12 @@ static uint64_t rootdir_size(const struct exfat* ef) to indicate this */ rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster); } + if (rootdir_cluster != EXFAT_CLUSTER_END) + { + exfat_error("bad cluster %#x while reading root directory", + rootdir_cluster); + return 0; + } return clusters * CLUSTER_SIZE(*ef->sb); } @@ -260,6 +266,14 @@ int exfat_mount(struct exfat* ef, const char* spec, const char* options) ef->root->fptr_cluster = ef->root->start_cluster; ef->root->name[0] = cpu_to_le16('\0'); ef->root->size = rootdir_size(ef); + if (ef->root->size == 0) + { + free(ef->root); + free(ef->zero_cluster); + exfat_close(ef->dev); + free(ef->sb); + return -EIO; + } /* exFAT does not have time attributes for the root directory */ ef->root->mtime = 0; ef->root->atime = 0; diff --git a/libexfat/node.c b/libexfat/node.c index fea371b..3d27ad5 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -544,13 +544,21 @@ void exfat_reset_cache(struct exfat* ef) reset_cache(ef, ef->root); } -static void next_entry(struct exfat* ef, const struct exfat_node* parent, +static bool next_entry(struct exfat* ef, const struct exfat_node* parent, cluster_t* cluster, off_t* offset) { *offset += sizeof(struct exfat_entry); if (*offset % CLUSTER_SIZE(*ef->sb) == 0) - /* next cluster cannot be invalid */ + { *cluster = exfat_next_cluster(ef, parent, *cluster); + if (CLUSTER_INVALID(*cluster)) + { + exfat_error("invalid cluster %#x while getting next entry", + *cluster); + return false; + } + } + return true; } int exfat_flush_node(struct exfat* ef, struct exfat_node* node) @@ -573,7 +581,8 @@ int exfat_flush_node(struct exfat* ef, struct exfat_node* node) cluster = node->entry_cluster; offset = node->entry_offset; meta1_offset = co2o(ef, cluster, offset); - next_entry(ef, node->parent, &cluster, &offset); + if (!next_entry(ef, node->parent, &cluster, &offset)) + return -EIO; meta2_offset = co2o(ef, cluster, offset); if (exfat_pread(ef->dev, &meta1, sizeof(meta1), meta1_offset) < 0) @@ -633,7 +642,8 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node) return false; } - next_entry(ef, node->parent, &cluster, &offset); + if (!next_entry(ef, node->parent, &cluster, &offset)) + return false; entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID; if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0) { @@ -643,7 +653,8 @@ static bool erase_entry(struct exfat* ef, struct exfat_node* node) while (name_entries--) { - next_entry(ef, node->parent, &cluster, &offset); + if (!next_entry(ef, node->parent, &cluster, &offset)) + return false; entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID; if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0) @@ -838,7 +849,8 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir, exfat_error("failed to write meta1 entry"); return -EIO; } - next_entry(ef, dir, &cluster, &offset); + if (!next_entry(ef, dir, &cluster, &offset)) + return -EIO; if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, cluster, offset)) < 0) { @@ -851,7 +863,8 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir, memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX, MIN(EXFAT_ENAME_MAX, EXFAT_NAME_MAX - i * EXFAT_ENAME_MAX) * sizeof(le16_t)); - next_entry(ef, dir, &cluster, &offset); + if (!next_entry(ef, dir, &cluster, &offset)) + return -EIO; if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry), co2o(ef, cluster, offset)) < 0) { @@ -945,7 +958,8 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, exfat_error("failed to read meta1 entry on rename"); return -EIO; } - next_entry(ef, node->parent, &old_cluster, &old_offset); + if (!next_entry(ef, node->parent, &old_cluster, &old_offset)) + return -EIO; if (exfat_pread(ef->dev, &meta2, sizeof(meta2), co2o(ef, old_cluster, old_offset)) < 0) { @@ -969,7 +983,8 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, exfat_error("failed to write meta1 entry on rename"); return -EIO; } - next_entry(ef, dir, &new_cluster, &new_offset); + if (!next_entry(ef, dir, &new_cluster, &new_offset)) + return -EIO; if (exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, new_cluster, new_offset)) < 0) { @@ -982,7 +997,8 @@ static int rename_entry(struct exfat* ef, struct exfat_node* dir, struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0}; memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX, EXFAT_ENAME_MAX * sizeof(le16_t)); - next_entry(ef, dir, &new_cluster, &new_offset); + if (!next_entry(ef, dir, &new_cluster, &new_offset)) + return -EIO; if (exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry), co2o(ef, new_cluster, new_offset)) < 0) {