Ejemplo n.º 1
0
static bool erase_entry(struct exfat* ef, struct exfat_node* node)
{
	cluster_t cluster = node->entry_cluster;
	off64_t offset = node->entry_offset;
	int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
	uint8_t entry_type;

	entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
	if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0)
	{
		exfat_error("failed to erase meta1 entry");
		return false;
	}

	next_entry(ef, node->parent, &cluster, &offset);
	entry_type = EXFAT_ENTRY_FILE_INFO & ~EXFAT_ENTRY_VALID;
	if (exfat_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset)) < 0)
	{
		exfat_error("failed to erase meta2 entry");
		return false;
	}

	while (name_entries--)
	{
		next_entry(ef, node->parent, &cluster, &offset);
		entry_type = EXFAT_ENTRY_FILE_NAME & ~EXFAT_ENTRY_VALID;
		if (exfat_pwrite(ef->dev, &entry_type, 1,
				co2o(ef, cluster, offset)) < 0)
		{
			exfat_error("failed to erase name entry");
			return false;
		}
	}
	return true;
}
Ejemplo n.º 2
0
Archivo: node.c Proyecto: ZeroJim/twrp
void exfat_flush_node(struct exfat* ef, struct exfat_node* node)
{
	cluster_t cluster;
	off64_t offset;
	off64_t meta1_offset, meta2_offset;
	struct exfat_entry_meta1 meta1;
	struct exfat_entry_meta2 meta2;

	if (ef->ro)
		exfat_bug("unable to flush node to read-only FS");

	if (node->parent == NULL)
		return; /* do not flush unlinked node */

	cluster = node->entry_cluster;
	offset = node->entry_offset;
	meta1_offset = co2o(ef, cluster, offset);
	next_entry(ef, node->parent, &cluster, &offset);
	meta2_offset = co2o(ef, cluster, offset);

	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_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);
	meta2.start_cluster = cpu_to_le32(node->start_cluster);
	meta2.flags = EXFAT_FLAG_ALWAYS1;
	/* empty files must not be marked as contiguous */
	if (node->size != 0 && IS_CONTIGUOUS(*node))
		meta2.flags |= EXFAT_FLAG_CONTIGUOUS;
	/* name hash remains unchanged, no need to recalculate it */

	meta1.checksum = exfat_calc_checksum(&meta1, &meta2, node->name);

	exfat_pwrite(ef->dev, &meta1, sizeof(meta1), meta1_offset);
	exfat_pwrite(ef->dev, &meta2, sizeof(meta2), meta2_offset);

	node->flags &= ~EXFAT_ATTRIB_DIRTY;
}
Ejemplo n.º 3
0
static bool erase_raw(struct exfat* ef, size_t size, loff_t offset)
{
	if (exfat_pwrite(ef->dev, ef->zero_cluster, size, offset) < 0)
	{
		exfat_error("failed to erase %zu bytes at %"PRId64, size, offset);
		return false;
	}
	return true;
}
Ejemplo n.º 4
0
static int commit_super_block(const struct exfat* ef)
{
	if (exfat_pwrite(ef->dev, ef->sb, sizeof(struct exfat_super_block), 0) < 0)
	{
		exfat_error("failed to write super block");
		return 1;
	}
	return exfat_fsync(ef->dev);
}
Ejemplo n.º 5
0
Archivo: node.c Proyecto: ZeroJim/twrp
static void erase_entry(struct exfat* ef, struct exfat_node* node)
{
	cluster_t cluster = node->entry_cluster;
	off64_t offset = node->entry_offset;
	int name_entries = DIV_ROUND_UP(utf16_length(node->name), EXFAT_ENAME_MAX);
	uint8_t entry_type;

	entry_type = EXFAT_ENTRY_FILE & ~EXFAT_ENTRY_VALID;
	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_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_pwrite(ef->dev, &entry_type, 1, co2o(ef, cluster, offset));
	}
}
Ejemplo n.º 6
0
static void set_next_cluster(const struct exfat* ef, int contiguous,
		cluster_t current, cluster_t next)
{
	off_t fat_offset;
	le32_t next_le32;

	if (contiguous)
		return;
	fat_offset = s2o(ef, le32_to_cpu(ef->sb->fat_sector_start))
		+ current * sizeof(cluster_t);
	next_le32 = cpu_to_le32(next);
	exfat_pwrite(ef->dev, &next_le32, sizeof(next_le32), fat_offset);
}
Ejemplo n.º 7
0
int exfat_flush(struct exfat* ef)
{
	if (ef->cmap.dirty)
	{
		if (exfat_pwrite(ef->dev, ef->cmap.chunk,
				BMAP_SIZE(ef->cmap.chunk_size),
				exfat_c2o(ef, ef->cmap.start_cluster)) < 0)
		{
			exfat_error("failed to write clusters bitmap");
			return -EIO;
		}
		ef->cmap.dirty = false;
	}
	return 0;
}
Ejemplo n.º 8
0
ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
		const void* buffer, size_t size, off64_t offset)
{
	cluster_t cluster;
	const char* bufp = buffer;
	off64_t lsize, loffset, remainder;

	if (offset > node->size)
		if (exfat_truncate(ef, node, offset, true) != 0)
			return -1;
	if (offset + size > node->size)
		if (exfat_truncate(ef, node, offset + size, false) != 0)
			return -1;
	if (size == 0)
		return 0;

	cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
	if (CLUSTER_INVALID(cluster))
	{
		exfat_error("invalid cluster 0x%x while writing", cluster);
		return -1;
	}

	loffset = offset % CLUSTER_SIZE(*ef->sb);
	remainder = size;
	while (remainder > 0)
	{
		if (CLUSTER_INVALID(cluster))
		{
			exfat_error("invalid cluster 0x%x while writing", cluster);
			return -1;
		}
		lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
		if (exfat_pwrite(ef->dev, bufp, lsize,
				exfat_c2o(ef, cluster) + loffset) < 0)
		{
			exfat_error("failed to write cluster %#x", cluster);
			ef->was_dirty = true; // Leaves the volume "mounted", to force chkdsk on it.
			return -1;
		}
		bufp += lsize;
		loffset = 0;
		remainder -= lsize;
		cluster = exfat_next_cluster(ef, node, cluster);
	}
	exfat_update_mtime(node);
	return size - remainder;
}
Ejemplo n.º 9
0
static bool set_next_cluster(const struct exfat* ef, bool contiguous,
		cluster_t current, cluster_t next)
{
	loff_t fat_offset;
	le32_t next_le32;

	if (contiguous)
		return true;
	fat_offset = s2o(ef, le32_to_cpu(ef->sb->fat_sector_start))
		+ current * sizeof(cluster_t);
	next_le32 = cpu_to_le32(next);
	if (exfat_pwrite(ef->dev, &next_le32, sizeof(next_le32), fat_offset) < 0)
	{
		exfat_error("failed to write the next cluster %#x after %#x", next,
				current);
		return false;
	}
	return true;
}
Ejemplo n.º 10
0
ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
		const void* buffer, size_t size, off_t offset)
{
	cluster_t cluster;
	const char* bufp = buffer;
	off_t lsize, loffset, remainder;

	if (offset + size > node->size)
	{
		int rc = exfat_truncate(ef, node, offset + size);
		if (rc != 0)
			return rc;
	}
	if (size == 0)
		return 0;

	cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
	if (CLUSTER_INVALID(cluster))
	{
		exfat_error("got invalid cluster");
		return -1;
	}

	loffset = offset % CLUSTER_SIZE(*ef->sb);
	remainder = size;
	while (remainder > 0)
	{
		if (CLUSTER_INVALID(cluster))
		{
			exfat_error("got invalid cluster");
			return -1;
		}
		lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
		exfat_pwrite(ef->dev, bufp, lsize, exfat_c2o(ef, cluster) + loffset);
		bufp += lsize;
		loffset = 0;
		remainder -= lsize;
		cluster = exfat_next_cluster(ef, node, cluster);
	}
	exfat_update_mtime(node);
	return size - remainder;
}
Ejemplo n.º 11
0
static void erase_raw(struct exfat* ef, size_t size, off_t offset)
{
	exfat_pwrite(ef->dev, ef->zero_cluster, size, offset);
}
Ejemplo n.º 12
0
void exfat_flush_cmap(struct exfat* ef)
{
	exfat_pwrite(ef->dev, ef->cmap.chunk, (ef->cmap.chunk_size + 7) / 8,
			exfat_c2o(ef, ef->cmap.start_cluster));
	ef->cmap.dirty = false;
}