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

Commit bdc6d39e authored by Colin Cross's avatar Colin Cross
Browse files

libsparse: add function to resparse a file and a utility to use it

Add sparse_file_repsarse, which splits chunks in an existing sparse
file such that the maximum size of a chunk, plus a header and footer,
is smaller than the given size.  This will allow multiple smaller
sparse files to result in the same data as a large sparse file.

Change-Id: I177abdb958a23d5afd394ff265c5b0c6a3ff22fa
parent 1e17b313
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -83,6 +83,15 @@ include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := simg2simg.c
LOCAL_MODULE := simg2simg
LOCAL_MODULE_TAGS := debug
LOCAL_STATIC_LIBRARIES := libsparse libz

include $(BUILD_HOST_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_MODULE := simg_dump.py
LOCAL_MODULE_TAGS := debug
LOCAL_SRC_FILES := simg_dump.py
+87 −0
Original line number Diff line number Diff line
@@ -141,6 +141,52 @@ void backed_block_list_destroy(struct backed_block_list *bbl)
	free(bbl);
}

void backed_block_list_move(struct backed_block_list *from,
		struct backed_block_list *to, struct backed_block *start,
		struct backed_block *end)
{
	struct backed_block *bb;

	if (start == NULL) {
		start = from->data_blocks;
	}

	if (!end) {
		for (end = start; end && end->next; end = end->next)
			;
	}

	if (start == NULL || end == NULL) {
		return;
	}

	from->last_used = NULL;
	to->last_used = NULL;
	if (from->data_blocks == start) {
		from->data_blocks = end->next;
	} else {
		for (bb = from->data_blocks; bb; bb = bb->next) {
			if (bb->next == start) {
				bb->next = end->next;
				break;
			}
		}
	}

	if (!to->data_blocks) {
		to->data_blocks = start;
		end->next = NULL;
	} else {
		for (bb = to->data_blocks; bb; bb = bb->next) {
			if (!bb->next || bb->next->block > start->block) {
				end->next = bb->next;
				bb->next = start;
				break;
			}
		}
	}
}

/* may free b */
static int merge_bb(struct backed_block_list *bbl,
		struct backed_block *a, struct backed_block *b)
@@ -311,3 +357,44 @@ int backed_block_add_fd(struct backed_block_list *bbl, int fd, int64_t offset,

	return queue_bb(bbl, bb);
}

int backed_block_split(struct backed_block_list *bbl, struct backed_block *bb,
		unsigned int max_len)
{
	struct backed_block *new_bb;

	max_len = ALIGN_DOWN(max_len, bbl->block_size);

	if (bb->len <= max_len) {
		return 0;
	}

	new_bb = malloc(sizeof(struct backed_block));
	if (bb == NULL) {
		return -ENOMEM;
	}

	*new_bb = *bb;

	new_bb->len = bb->len - max_len;
	new_bb->block = bb->block + max_len / bbl->block_size;
	new_bb->next = bb->next;
	bb->next = new_bb;
	bb->len = max_len;

	switch (bb->type) {
	case BACKED_BLOCK_DATA:
		new_bb->data.data = (char *)bb->data.data + max_len;
		break;
	case BACKED_BLOCK_FILE:
		new_bb->file.offset += max_len;
		break;
	case BACKED_BLOCK_FD:
		new_bb->fd.offset += max_len;
		break;
	case BACKED_BLOCK_FILL:
		break;
	}

	return 0;
}
+6 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ 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);
int backed_block_split(struct backed_block_list *bbl, struct backed_block *bb,
		unsigned int max_len);

struct backed_block *backed_block_iter_new(struct backed_block_list *bbl);
struct backed_block *backed_block_iter_next(struct backed_block *bb);
@@ -55,4 +57,8 @@ struct backed_block *backed_block_iter_next(struct backed_block *bb);
struct backed_block_list *backed_block_list_new(unsigned int block_size);
void backed_block_list_destroy(struct backed_block_list *bbl);

void backed_block_list_move(struct backed_block_list *from,
		struct backed_block_list *to, struct backed_block *start,
		struct backed_block *end);

#endif
+14 −0
Original line number Diff line number Diff line
@@ -227,6 +227,20 @@ struct sparse_file *sparse_file_import(int fd, bool verbose, bool crc);
 */
struct sparse_file *sparse_file_import_auto(int fd, bool crc);

/** sparse_file_resparse - rechunk an existing sparse file into smaller files
 *
 * @in_s - sparse file cookie of the existing sparse file
 * @max_len - maximum file size
 * @out_s - array of sparse file cookies
 * @out_s_count - size of out_s array
 *
 * Splits chunks of an existing sparse file into smaller sparse files such that
 * each sparse file is less than max_len.  Returns the number of sparse_files
 * that would have been written to out_s if out_s were big enough.
 */
int sparse_file_resparse(struct sparse_file *in_s, unsigned int max_len,
		struct sparse_file **out_s, int out_s_count);

/**
 * sparse_file_verbose - set a sparse file cookie to print verbose errors
 *
+34 −22
Original line number Diff line number Diff line
@@ -26,38 +26,41 @@
#include <sys/types.h>
#include <unistd.h>

#ifndef O_BINARY
#define O_BINARY 0
#endif

void usage()
{
  fprintf(stderr, "Usage: simg2img <sparse_image_file> <raw_image_file>\n");
  fprintf(stderr, "Usage: simg2img <sparse_image_files> <raw_image_file>\n");
}

int main(int argc, char *argv[])
{
	int in;
	int out;
	unsigned int i;
	int i;
	int ret;
	struct sparse_file *s;

	if (argc != 3) {
	if (argc < 3) {
		usage();
		exit(-1);
	}

	if (strcmp(argv[1], "-") == 0) {
		in = STDIN_FILENO;
	} else {
		if ((in = open(argv[1], O_RDONLY)) == 0) {
			fprintf(stderr, "Cannot open input file %s\n", argv[1]);
	out = open(argv[argc - 1], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
	if (out < 0) {
		fprintf(stderr, "Cannot open output file %s\n", argv[argc - 1]);
		exit(-1);
	}
	}

	if (strcmp(argv[2], "-") == 0) {
		out = STDOUT_FILENO;
	for (i = 1; i < argc - 1; i++) {
		if (strcmp(argv[i], "-") == 0) {
			in = STDIN_FILENO;
		} else {
		if ((out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666)) == 0) {
			fprintf(stderr, "Cannot open output file %s\n", argv[2]);
			in = open(argv[i], O_RDONLY | O_BINARY);
			if (in < 0) {
				fprintf(stderr, "Cannot open input file %s\n", argv[i]);
				exit(-1);
			}
		}
@@ -67,9 +70,18 @@ int main(int argc, char *argv[])
			fprintf(stderr, "Failed to read sparse file\n");
			exit(-1);
		}
	ret = sparse_file_write(s, out, false, false, false);

		lseek(out, SEEK_SET, 0);

		ret = sparse_file_write(s, out, false, false, false);
		if (ret < 0) {
			fprintf(stderr, "Cannot write output file\n");
			exit(-1);
		}
		sparse_file_destroy(s);
		close(in);
	}

	close(out);

	exit(0);
Loading