Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e1f17e9 authored by Colin Cross's avatar Colin Cross
Browse files

libsparse: add support for including fds

Add sparse_file_add_fd to include all or part of the contents
of an fd in the output file.  Will be useful for re-sparsing files
where fd will point to the input sparse file.

Change-Id: I5d4ab07fb37231e8e9c1912f62a2968c8b0a00ef
parent b55dceea
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -34,6 +34,10 @@ struct backed_block {
			char *filename;
			int64_t offset;
		} file;
		struct {
			int fd;
			int64_t offset;
		} fd;
		struct {
			uint32_t val;
		} fill;
@@ -78,10 +82,20 @@ const char *backed_block_filename(struct backed_block *bb)
	return bb->file.filename;
}

int backed_block_fd(struct backed_block *bb)
{
	assert(bb->type == BACKED_BLOCK_FD);
	return bb->fd.fd;
}

int64_t backed_block_file_offset(struct backed_block *bb)
{
	assert(bb->type == BACKED_BLOCK_FILE);
	assert(bb->type == BACKED_BLOCK_FILE || bb->type == BACKED_BLOCK_FD);
	if (bb->type == BACKED_BLOCK_FILE) {
		return bb->file.offset;
	} else { /* bb->type == BACKED_BLOCK_FD */
		return bb->fd.offset;
	}
}

uint32_t backed_block_fill_val(struct backed_block *bb)
@@ -211,3 +225,22 @@ int backed_block_add_file(struct backed_block_list *bbl, const char *filename,

	return queue_bb(bbl, bb);
}

/* Queues a chunk of a fd to be written to the specified data blocks */
int backed_block_add_fd(struct backed_block_list *bbl, int fd, int64_t offset,
		unsigned int len, unsigned int block)
{
	struct backed_block *bb = calloc(1, sizeof(struct backed_block));
	if (bb == NULL) {
		return -ENOMEM;
	}

	bb->block = block;
	bb->len = len;
	bb->type = BACKED_BLOCK_FD;
	bb->fd.fd = fd;
	bb->fd.offset = offset;
	bb->next = NULL;

	return queue_bb(bbl, bb);
}
+4 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ struct backed_block;
enum backed_block_type {
	BACKED_BLOCK_DATA,
	BACKED_BLOCK_FILE,
	BACKED_BLOCK_FD,
	BACKED_BLOCK_FILL,
};

@@ -34,6 +35,8 @@ int backed_block_add_fill(struct backed_block_list *bbl, unsigned int fill_val,
		unsigned int len, unsigned int block);
int backed_block_add_file(struct backed_block_list *bbl, const char *filename,
		int64_t offset, unsigned int len, unsigned int block);
int backed_block_add_fd(struct backed_block_list *bbl, int fd,
		int64_t offset, unsigned int len, unsigned int block);

struct backed_block *backed_block_iter_new(struct backed_block_list *bbl);
struct backed_block *backed_block_iter_next(struct backed_block *bb);
@@ -41,6 +44,7 @@ unsigned int backed_block_len(struct backed_block *bb);
unsigned int backed_block_block(struct backed_block *bb);
void *backed_block_data(struct backed_block *bb);
const char *backed_block_filename(struct backed_block *bb);
int backed_block_fd(struct backed_block *bb);
int64_t backed_block_file_offset(struct backed_block *bb);
uint32_t backed_block_fill_val(struct backed_block *bb);
enum backed_block_type backed_block_type(struct backed_block *bb);
+26 −0
Original line number Diff line number Diff line
@@ -110,6 +110,32 @@ int sparse_file_add_file(struct sparse_file *s,
		const char *filename, int64_t file_offset, unsigned int len,
		unsigned int block);

/**
 * sparse_file_add_file - associate a chunk of a file with a sparse file
 *
 * @s - sparse file cookie
 * @filename - filename of the file to be copied
 * @file_offset - offset into the copied file
 * @len - length of the copied block
 * @block - offset in blocks into the sparse file to place the file chunk
 *
 * Associates a chunk of an existing fd with a sparse file cookie.
 * The region [block * block_size : block * block_size + len) must not already
 * be used in the sparse file. If len is not a multiple of the block size the
 * data will be padded with zeros.
 *
 * Allows adding large amounts of data to a sparse file without needing to keep
 * it all mapped.  File size is limited by available virtual address space,
 * exceptionally large files may need to be added in multiple chunks.
 *
 * The fd must remain open until the sparse file is closed or the fd block is
 * removed from the sparse file.
 *
 * Returns 0 on success, negative errno on error.
 */
int sparse_file_add_fd(struct sparse_file *s,
		int fd, int64_t file_offset, unsigned int len, unsigned int block);

/**
 * sparse_file_write - write a sparse file to a file
 *
+22 −15
Original line number Diff line number Diff line
@@ -511,38 +511,28 @@ int write_fill_chunk(struct output_file *out, unsigned int len,
	return out->sparse_ops->write_fill_chunk(out, len, fill_val);
}

/* Write a contiguous region of data blocks from a file */
int write_file_chunk(struct output_file *out, unsigned int len,
		const char *file, int64_t offset)
int write_fd_chunk(struct output_file *out, unsigned int len,
		int fd, int64_t offset)
{
	int ret;
	int64_t aligned_offset;
	int aligned_diff;
	int buffer_size;

	int file_fd = open(file, O_RDONLY | O_BINARY);
	if (file_fd < 0) {
		return -errno;
	}

	aligned_offset = offset & ~(4096 - 1);
	aligned_diff = offset - aligned_offset;
	buffer_size = len + aligned_diff;

#ifndef USE_MINGW
	char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, file_fd,
	char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd,
			aligned_offset);
	if (data == MAP_FAILED) {
		ret = -errno;
		close(file_fd);
		return ret;
		return -errno;
	}
#else
	char *data = malloc(buffer_size);
	if (!data) {
		ret = -errno;
		close(file_fd);
		return ret;
		return -errno;
	}
	memset(data, 0, buffer_size);
#endif
@@ -554,6 +544,23 @@ int write_file_chunk(struct output_file *out, unsigned int len,
#else
	free(data);
#endif

	return ret;
}

/* Write a contiguous region of data blocks from a file */
int write_file_chunk(struct output_file *out, unsigned int len,
		const char *file, int64_t offset)
{
	int ret;

	int file_fd = open(file, O_RDONLY | O_BINARY);
	if (file_fd < 0) {
		return -errno;
	}

	ret = write_fd_chunk(out, len, file_fd, offset);

	close(file_fd);

	return ret;
+2 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ int write_fill_chunk(struct output_file *out, unsigned int len,
		uint32_t fill_val);
int write_file_chunk(struct output_file *out, unsigned int len,
		const char *file, int64_t offset);
int write_fd_chunk(struct output_file *out, unsigned int len,
		int fd, int64_t offset);
int write_skip_chunk(struct output_file *out, int64_t len);
void close_output_file(struct output_file *out);

Loading