node.c (09.10.09)
exFAT file system implementation library.
- Copyright (C) 2009, 2010 Andrew Nayenko
+ Copyright (C) 2010-2012 Andrew Nayenko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
exfat_error("out of memory");
return -ENOMEM;
}
- exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
- exfat_c2o(ef, it->cluster), ef->fd);
+ exfat_pread(ef->dev, it->chunk, CLUSTER_SIZE(*ef->sb),
+ exfat_c2o(ef, it->cluster));
return 0;
}
it->cluster = exfat_next_cluster(ef, parent, it->cluster);
if (CLUSTER_INVALID(it->cluster))
{
- exfat_error("invalid cluster while reading directory");
+ exfat_error("invalid cluster 0x%x while reading directory",
+ it->cluster);
return 1;
}
- exfat_read_raw(it->chunk, CLUSTER_SIZE(*ef->sb),
- exfat_c2o(ef, it->cluster), ef->fd);
+ exfat_pread(ef->dev, it->chunk, CLUSTER_SIZE(*ef->sb),
+ exfat_c2o(ef, it->cluster));
}
return 0;
}
le16_t* namep = NULL;
uint16_t reference_checksum = 0;
uint16_t actual_checksum = 0;
+ uint64_t real_size = 0;
*node = NULL;
}
init_node_meta2(*node, meta2);
actual_checksum = exfat_add_checksum(entry, actual_checksum);
- /* There are two fields that contain file size. Maybe they plan
- to add compression support in the future and one of those
- fields is visible (uncompressed) size and the other is real
- (compressed) size. Anyway, currently it looks like exFAT does
- not support compression and both fields must be equal. */
- if (le64_to_cpu(meta2->real_size) != (*node)->size)
- {
- exfat_error("real size does not equal to size "
- "(%"PRIu64" != %"PRIu64")",
- le64_to_cpu(meta2->real_size), (*node)->size);
- goto error;
- }
+ real_size = le64_to_cpu(meta2->real_size);
/* empty files must be marked as non-contiguous */
if ((*node)->size == 0 && (meta2->flags & EXFAT_FLAG_CONTIGUOUS))
{
if (((*node)->flags & EXFAT_ATTRIB_DIR) &&
(*node)->size % CLUSTER_SIZE(*ef->sb) != 0)
{
- char buffer[EXFAT_NAME_MAX + 1];
-
- exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
- exfat_error("directory `%s' has invalid size %"PRIu64" bytes",
- buffer, (*node)->size);
+ exfat_error("directory has invalid size %"PRIu64" bytes",
+ (*node)->size);
goto error;
}
--continuations;
namep += EXFAT_ENAME_MAX;
if (--continuations == 0)
{
+ /*
+ There are two fields that contain file size. Maybe they
+ plan to add compression support in the future and one of
+ those fields is visible (uncompressed) size and the other
+ is real (compressed) size. Anyway, currently it looks like
+ exFAT does not support compression and both fields must be
+ equal.
+
+ There is an exception though: pagefile.sys (its real_size
+ is always 0).
+ */
+ if (real_size != (*node)->size)
+ {
+ char buffer[EXFAT_NAME_MAX + 1];
+
+ exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
+ exfat_error("`%s' real size does not equal to size "
+ "(%"PRIu64" != %"PRIu64")", buffer,
+ real_size, (*node)->size);
+ goto error;
+ }
if (actual_checksum != reference_checksum)
{
- exfat_error("invalid checksum (0x%hx != 0x%hx)",
- actual_checksum, reference_checksum);
+ char buffer[EXFAT_NAME_MAX + 1];
+
+ exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
+ exfat_error("`%s' has invalid checksum (0x%hx != 0x%hx)",
+ buffer, actual_checksum, reference_checksum);
goto error;
}
if (fetch_next_entry(ef, parent, it) != 0)
upcase = (const struct exfat_entry_upcase*) entry;
if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster)))
{
- exfat_error("invalid cluster in upcase table");
+ exfat_error("invalid cluster 0x%x in upcase table",
+ le32_to_cpu(upcase->start_cluster));
goto error;
}
if (le64_to_cpu(upcase->size) == 0 ||
}
ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t);
- exfat_read_raw(ef->upcase, le64_to_cpu(upcase->size),
- exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)), ef->fd);
+ exfat_pread(ef->dev, ef->upcase, le64_to_cpu(upcase->size),
+ exfat_c2o(ef, le32_to_cpu(upcase->start_cluster)));
break;
case EXFAT_ENTRY_BITMAP:
bitmap = (const struct exfat_entry_bitmap*) entry;
- if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster)))
+ ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
+ if (CLUSTER_INVALID(ef->cmap.start_cluster))
{
- exfat_error("invalid cluster in clusters bitmap");
+ exfat_error("invalid cluster 0x%x in clusters bitmap",
+ ef->cmap.start_cluster);
goto error;
}
ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) -
le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8);
goto error;
}
- ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster);
/* FIXME bitmap can be rather big, up to 512 MB */
ef->cmap.chunk_size = ef->cmap.size;
ef->cmap.chunk = malloc(le64_to_cpu(bitmap->size));
goto error;
}
- exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size),
- exfat_c2o(ef, ef->cmap.start_cluster), ef->fd);
+ exfat_pread(ef->dev, ef->cmap.chunk, le64_to_cpu(bitmap->size),
+ exfat_c2o(ef, ef->cmap.start_cluster));
break;
case EXFAT_ENTRY_LABEL:
next_entry(ef, node->parent, &cluster, &offset);
meta2_offset = co2o(ef, cluster, offset);
- exfat_read_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
+ exfat_pread(ef->dev, &meta1, sizeof(meta1), meta1_offset);
if (meta1.type != EXFAT_ENTRY_FILE)
exfat_bug("invalid type of meta1: 0x%hhx", meta1.type);
meta1.attrib = cpu_to_le16(node->flags);
exfat_unix2exfat(node->mtime, &meta1.mdate, &meta1.mtime, &meta1.mtime_cs);
exfat_unix2exfat(node->atime, &meta1.adate, &meta1.atime, NULL);
- exfat_read_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
+ exfat_pread(ef->dev, &meta2, sizeof(meta2), meta2_offset);
if (meta2.type != EXFAT_ENTRY_FILE_INFO)
exfat_bug("invalid type of meta2: 0x%hhx", meta2.type);
meta2.size = meta2.real_size = cpu_to_le64(node->size);
meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
- exfat_write_raw(&meta1, sizeof(meta1), meta1_offset, ef->fd);
- exfat_write_raw(&meta2, sizeof(meta2), meta2_offset, ef->fd);
+ exfat_pwrite(ef->dev, &meta1, sizeof(meta1), meta1_offset);
+ exfat_pwrite(ef->dev, &meta2, sizeof(meta2), meta2_offset);
node->flags &= ~EXFAT_ATTRIB_DIRTY;
}
uint8_t entry_type;
entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
- exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
next_entry(ef, node->parent, &cluster, &offset);
entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
- exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
while (name_entries--)
{
next_entry(ef, node->parent, &cluster, &offset);
entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
- exfat_write_raw(&entry_type, 1, co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
}
}
meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);
- exfat_write_raw(&meta1, sizeof(meta1), co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &meta1, sizeof(meta1), co2o(ef, cluster, offset));
next_entry(ef, dir, &cluster, &offset);
- exfat_write_raw(&meta2, sizeof(meta2), co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &meta2, sizeof(meta2), co2o(ef, cluster, offset));
for (i = 0; i < name_entries; i++)
{
struct exfat_entry_name name_entry = {EXFAT_ENTRY_FILE_NAME, 0};
memcpy(name_entry.name, node->name + i * EXFAT_ENAME_MAX,
EXFAT_ENAME_MAX * sizeof(le16_t));
next_entry(ef, dir, &cluster, &offset);
- exfat_write_raw(&name_entry, sizeof(name_entry),
- co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
+ co2o(ef, cluster, offset));
}
init_node_meta1(node, &meta1);
const int name_entries = DIV_ROUND_UP(name_length, EXFAT_ENAME_MAX);
int i;
- exfat_read_raw(&meta1, sizeof(meta1), co2o(ef, old_cluster, old_offset),
- ef->fd);
+ exfat_pread(ef->dev, &meta1, sizeof(meta1),
+ co2o(ef, old_cluster, old_offset));
next_entry(ef, node->parent, &old_cluster, &old_offset);
- exfat_read_raw(&meta2, sizeof(meta2), co2o(ef, old_cluster, old_offset),
- ef->fd);
+ exfat_pread(ef->dev, &meta2, sizeof(meta2),
+ co2o(ef, old_cluster, old_offset));
meta1.continuations = 1 + name_entries;
meta2.name_hash = exfat_calc_name_hash(ef, name);
meta2.name_length = name_length;
node->entry_cluster = new_cluster;
node->entry_offset = new_offset;
- exfat_write_raw(&meta1, sizeof(meta1), co2o(ef, new_cluster, new_offset),
- ef->fd);
+ exfat_pwrite(ef->dev, &meta1, sizeof(meta1),
+ co2o(ef, new_cluster, new_offset));
next_entry(ef, dir, &new_cluster, &new_offset);
- exfat_write_raw(&meta2, sizeof(meta2), co2o(ef, new_cluster, new_offset),
- ef->fd);
+ exfat_pwrite(ef->dev, &meta2, sizeof(meta2),
+ co2o(ef, new_cluster, new_offset));
for (i = 0; i < name_entries; i++)
{
memcpy(name_entry.name, name + i * EXFAT_ENAME_MAX,
EXFAT_ENAME_MAX * sizeof(le16_t));
next_entry(ef, dir, &new_cluster, &new_offset);
- exfat_write_raw(&name_entry, sizeof(name_entry),
- co2o(ef, new_cluster, new_offset), ef->fd);
+ exfat_pwrite(ef->dev, &name_entry, sizeof(name_entry),
+ co2o(ef, new_cluster, new_offset));
}
memcpy(node->name, name, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
if (entry.length == 0)
entry.type ^= EXFAT_ENTRY_VALID;
- exfat_write_raw(&entry, sizeof(struct exfat_entry_label),
- co2o(ef, cluster, offset), ef->fd);
+ exfat_pwrite(ef->dev, &entry, sizeof(struct exfat_entry_label),
+ co2o(ef, cluster, offset));
return 0;
}