otrx: support for extracting partitions
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 45390
This commit is contained in:
		@@ -27,6 +27,7 @@
 | 
			
		||||
 | 
			
		||||
#define TRX_MAGIC			0x30524448
 | 
			
		||||
#define TRX_FLAGS_OFFSET		12
 | 
			
		||||
#define TRX_MAX_PARTS			3
 | 
			
		||||
 | 
			
		||||
struct trx_header {
 | 
			
		||||
	uint32_t magic;
 | 
			
		||||
@@ -40,12 +41,14 @@ struct trx_header {
 | 
			
		||||
enum mode {
 | 
			
		||||
	MODE_UNKNOWN,
 | 
			
		||||
	MODE_CHECK,
 | 
			
		||||
	MODE_EXTRACT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mode mode = MODE_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
char *trx_path;
 | 
			
		||||
size_t trx_offset = 0;
 | 
			
		||||
char *partition[TRX_MAX_PARTS] = {};
 | 
			
		||||
 | 
			
		||||
/**************************************************
 | 
			
		||||
 * CRC32
 | 
			
		||||
@@ -195,6 +198,107 @@ out:
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**************************************************
 | 
			
		||||
 * Extract
 | 
			
		||||
 **************************************************/
 | 
			
		||||
 | 
			
		||||
static int otrx_extract_copy(FILE *trx, size_t offset, size_t length, char *out_path) {
 | 
			
		||||
	FILE *out;
 | 
			
		||||
	size_t bytes;
 | 
			
		||||
	uint8_t *buf;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
 | 
			
		||||
	out = fopen(out_path, "w");
 | 
			
		||||
	if (!out) {
 | 
			
		||||
		fprintf(stderr, "Couldn't open %s\n", out_path);
 | 
			
		||||
		err = -EACCES;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf = malloc(length);
 | 
			
		||||
	if (!buf) {
 | 
			
		||||
		fprintf(stderr, "Couldn't alloc %zu B buffer\n", length);
 | 
			
		||||
		err =  -ENOMEM;
 | 
			
		||||
		goto err_close;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fseek(trx, offset, SEEK_SET);
 | 
			
		||||
	bytes = fread(buf, 1, length, trx);
 | 
			
		||||
	if (bytes != length) {
 | 
			
		||||
		fprintf(stderr, "Couldn't read %zu B of data from %s\n", length, trx_path);
 | 
			
		||||
		err =  -ENOMEM;
 | 
			
		||||
		goto err_free_buf;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	bytes = fwrite(buf, 1, length, out);
 | 
			
		||||
	if (bytes != length) {
 | 
			
		||||
		fprintf(stderr, "Couldn't write %zu B to %s\n", length, out_path);
 | 
			
		||||
		err =  -ENOMEM;
 | 
			
		||||
		goto err_free_buf;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printf("Extracted 0x%zx bytes into %s\n", length, out_path);
 | 
			
		||||
 | 
			
		||||
err_free_buf:
 | 
			
		||||
	free(buf);
 | 
			
		||||
err_close:
 | 
			
		||||
	fclose(out);
 | 
			
		||||
out:
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int otrx_extract() {
 | 
			
		||||
	FILE *trx;
 | 
			
		||||
	struct trx_header hdr;
 | 
			
		||||
	size_t bytes;
 | 
			
		||||
	int i;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
 | 
			
		||||
	trx = fopen(trx_path, "r");
 | 
			
		||||
	if (!trx) {
 | 
			
		||||
		fprintf(stderr, "Couldn't open %s\n", trx_path);
 | 
			
		||||
		err = -EACCES;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fseek(trx, trx_offset, SEEK_SET);
 | 
			
		||||
	bytes = fread(&hdr, 1, sizeof(hdr), trx);
 | 
			
		||||
	if (bytes != sizeof(hdr)) {
 | 
			
		||||
		fprintf(stderr, "Couldn't read %s header\n", trx_path);
 | 
			
		||||
		err =  -EIO;
 | 
			
		||||
		goto err_close;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (le32_to_cpu(hdr.magic) != TRX_MAGIC) {
 | 
			
		||||
		fprintf(stderr, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr.magic));
 | 
			
		||||
		err =  -EINVAL;
 | 
			
		||||
		goto err_close;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < TRX_MAX_PARTS; i++) {
 | 
			
		||||
		size_t length;
 | 
			
		||||
 | 
			
		||||
		if (!partition[i])
 | 
			
		||||
			continue;
 | 
			
		||||
		if (!hdr.offset[i]) {
 | 
			
		||||
			printf("TRX doesn't contain partition %d, can't extract %s\n", i + 1, partition[i]);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (i + 1 >= TRX_MAX_PARTS || !hdr.offset[i + 1])
 | 
			
		||||
			length = le32_to_cpu(hdr.length) - le32_to_cpu(hdr.offset[i]);
 | 
			
		||||
		else
 | 
			
		||||
			length = le32_to_cpu(hdr.offset[i + 1]) - le32_to_cpu(hdr.offset[i]);
 | 
			
		||||
 | 
			
		||||
		otrx_extract_copy(trx, trx_offset + le32_to_cpu(hdr.offset[i]), length, partition[i]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
err_close:
 | 
			
		||||
	fclose(trx);
 | 
			
		||||
out:
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**************************************************
 | 
			
		||||
 * Start
 | 
			
		||||
 **************************************************/
 | 
			
		||||
@@ -202,15 +306,28 @@ out:
 | 
			
		||||
static void parse_options(int argc, char **argv) {
 | 
			
		||||
	int c;
 | 
			
		||||
 | 
			
		||||
	while ((c = getopt(argc, argv, "c:o:")) != -1) {
 | 
			
		||||
	while ((c = getopt(argc, argv, "c:e:o:1:2:3:")) != -1) {
 | 
			
		||||
		switch (c) {
 | 
			
		||||
		case 'c':
 | 
			
		||||
			mode = MODE_CHECK;
 | 
			
		||||
			trx_path = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'e':
 | 
			
		||||
			mode = MODE_EXTRACT;
 | 
			
		||||
			trx_path = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case 'o':
 | 
			
		||||
			trx_offset = atoi(optarg);
 | 
			
		||||
			break;
 | 
			
		||||
		case '1':
 | 
			
		||||
			partition[0] = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case '2':
 | 
			
		||||
			partition[1] = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		case '3':
 | 
			
		||||
			partition[2] = optarg;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -221,6 +338,13 @@ static void usage() {
 | 
			
		||||
	printf("Checking TRX file:\n");
 | 
			
		||||
	printf("\t-c file\t\tcheck if file is a valid TRX\n");
 | 
			
		||||
	printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
 | 
			
		||||
	printf("\n");
 | 
			
		||||
	printf("Extracting from TRX file:\n");
 | 
			
		||||
	printf("\t-e file\t\tfile with TRX to extract from\n");
 | 
			
		||||
	printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
 | 
			
		||||
	printf("\t-1 file\t\tfile to extract 1st partition to (optional)\n");
 | 
			
		||||
	printf("\t-2 file\t\tfile to extract 2nd partition to (optional)\n");
 | 
			
		||||
	printf("\t-3 file\t\tfile to extract 3rd partition to (optional)\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
@@ -229,6 +353,8 @@ int main(int argc, char **argv) {
 | 
			
		||||
	switch (mode) {
 | 
			
		||||
	case MODE_CHECK:
 | 
			
		||||
		return otrx_check();
 | 
			
		||||
	case MODE_EXTRACT:
 | 
			
		||||
		return otrx_extract();
 | 
			
		||||
	default:
 | 
			
		||||
		usage();
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user