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_MAGIC			0x30524448
 | 
				
			||||||
#define TRX_FLAGS_OFFSET		12
 | 
					#define TRX_FLAGS_OFFSET		12
 | 
				
			||||||
 | 
					#define TRX_MAX_PARTS			3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct trx_header {
 | 
					struct trx_header {
 | 
				
			||||||
	uint32_t magic;
 | 
						uint32_t magic;
 | 
				
			||||||
@@ -40,12 +41,14 @@ struct trx_header {
 | 
				
			|||||||
enum mode {
 | 
					enum mode {
 | 
				
			||||||
	MODE_UNKNOWN,
 | 
						MODE_UNKNOWN,
 | 
				
			||||||
	MODE_CHECK,
 | 
						MODE_CHECK,
 | 
				
			||||||
 | 
						MODE_EXTRACT,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum mode mode = MODE_UNKNOWN;
 | 
					enum mode mode = MODE_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *trx_path;
 | 
					char *trx_path;
 | 
				
			||||||
size_t trx_offset = 0;
 | 
					size_t trx_offset = 0;
 | 
				
			||||||
 | 
					char *partition[TRX_MAX_PARTS] = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**************************************************
 | 
					/**************************************************
 | 
				
			||||||
 * CRC32
 | 
					 * CRC32
 | 
				
			||||||
@@ -195,6 +198,107 @@ out:
 | 
				
			|||||||
	return err;
 | 
						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
 | 
					 * Start
 | 
				
			||||||
 **************************************************/
 | 
					 **************************************************/
 | 
				
			||||||
@@ -202,15 +306,28 @@ out:
 | 
				
			|||||||
static void parse_options(int argc, char **argv) {
 | 
					static void parse_options(int argc, char **argv) {
 | 
				
			||||||
	int c;
 | 
						int c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((c = getopt(argc, argv, "c:o:")) != -1) {
 | 
						while ((c = getopt(argc, argv, "c:e:o:1:2:3:")) != -1) {
 | 
				
			||||||
		switch (c) {
 | 
							switch (c) {
 | 
				
			||||||
		case 'c':
 | 
							case 'c':
 | 
				
			||||||
			mode = MODE_CHECK;
 | 
								mode = MODE_CHECK;
 | 
				
			||||||
			trx_path = optarg;
 | 
								trx_path = optarg;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case 'e':
 | 
				
			||||||
 | 
								mode = MODE_EXTRACT;
 | 
				
			||||||
 | 
								trx_path = optarg;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case 'o':
 | 
							case 'o':
 | 
				
			||||||
			trx_offset = atoi(optarg);
 | 
								trx_offset = atoi(optarg);
 | 
				
			||||||
			break;
 | 
								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("Checking TRX file:\n");
 | 
				
			||||||
	printf("\t-c file\t\tcheck if file is a valid TRX\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("\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) {
 | 
					int main(int argc, char **argv) {
 | 
				
			||||||
@@ -229,6 +353,8 @@ int main(int argc, char **argv) {
 | 
				
			|||||||
	switch (mode) {
 | 
						switch (mode) {
 | 
				
			||||||
	case MODE_CHECK:
 | 
						case MODE_CHECK:
 | 
				
			||||||
		return otrx_check();
 | 
							return otrx_check();
 | 
				
			||||||
 | 
						case MODE_EXTRACT:
 | 
				
			||||||
 | 
							return otrx_extract();
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		usage();
 | 
							usage();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user