OSDN Git Service

Handle I/O error in exfat_next_cluster().
authorrelan <relan@users.noreply.github.com>
Mon, 21 Oct 2013 07:11:48 +0000 (07:11 +0000)
committerrelan <relan@users.noreply.github.com>
Mon, 24 Aug 2015 05:26:16 +0000 (08:26 +0300)
libexfat/cluster.c
libexfat/mount.c
libexfat/node.c

index 5cabdbb..e3cb251 100644 (file)
@@ -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);
 }
 
index d10fc98..1202b4d 100644 (file)
@@ -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;
index fea371b..3d27ad5 100644 (file)
@@ -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)
                {