otrx: support for creating simple TRX files
authorRafał Miłecki <zajec5@gmail.com>
Tue, 14 Apr 2015 20:50:53 +0000 (20:50 +0000)
committerRafał Miłecki <zajec5@gmail.com>
Tue, 14 Apr 2015 20:50:53 +0000 (20:50 +0000)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
SVN-Revision: 45444

package/utils/otrx/src/otrx.c

index 25e0592737a487541c8059cd4e54f593dc25e5bc..fbdad319125da5d8301ae9211517de56827d97b5 100644 (file)
@@ -220,6 +220,184 @@ out:
        return err;
 }
 
+/**************************************************
+ * Create
+ **************************************************/
+
+static void otrx_create_parse_options(int argc, char **argv) {
+}
+
+static ssize_t otrx_create_append_file(FILE *trx, const char *in_path) {
+       FILE *in;
+       size_t bytes;
+       ssize_t length = 0;
+       uint8_t buf[128];
+
+       in = fopen(in_path, "r");
+       if (!in) {
+               fprintf(stderr, "Couldn't open %s\n", in_path);
+               return -EACCES;
+       }
+
+       while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
+               if (fwrite(buf, 1, bytes, trx) != bytes) {
+                       fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, trx_path);
+                       length = -EIO;
+                       break;
+               }
+               length += bytes;
+       }
+
+       fclose(in);
+
+       return length;
+}
+
+static ssize_t otrx_create_append_zeros(FILE *trx, size_t length) {
+       uint8_t *buf;
+
+       buf = malloc(length);
+       if (!buf)
+               return -ENOMEM;
+       memset(buf, 0, length);
+
+       if (fwrite(buf, 1, length, trx) != length) {
+               fprintf(stderr, "Couldn't write %zu B to %s\n", length, trx_path);
+               return -EIO;
+       }
+
+       return length;
+}
+
+static ssize_t otrx_create_align(FILE *trx, size_t curr_offset, size_t alignment) {
+       if (curr_offset & (alignment - 1)) {
+               size_t length = alignment - (curr_offset % alignment);
+               return otrx_create_append_zeros(trx, length);
+       }
+
+       return 0;
+}
+
+static int otrx_create_write_hdr(FILE *trx, struct trx_header *hdr) {
+       size_t bytes, length;
+       uint8_t *buf;
+       uint32_t crc32;
+
+       hdr->magic = cpu_to_le32(TRX_MAGIC);
+       hdr->version = 1;
+
+       fseek(trx, 0, SEEK_SET);
+       bytes = fwrite(hdr, 1, sizeof(struct trx_header), trx);
+       if (bytes != sizeof(struct trx_header)) {
+               fprintf(stderr, "Couldn't write TRX header to %s\n", trx_path);
+               return -EIO;
+       }
+
+       length = le32_to_cpu(hdr->length);
+
+       buf = malloc(length);
+       if (!buf) {
+               fprintf(stderr, "Couldn't alloc %zu B buffer\n", length);
+               return -ENOMEM;
+       }
+
+       fseek(trx, 0, 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);
+               return -ENOMEM;
+       }
+
+       crc32 = otrx_crc32(buf + TRX_FLAGS_OFFSET, length - TRX_FLAGS_OFFSET);
+       hdr->crc32 = cpu_to_le32(crc32);
+
+       fseek(trx, 0, SEEK_SET);
+       bytes = fwrite(hdr, 1, sizeof(struct trx_header), trx);
+       if (bytes != sizeof(struct trx_header)) {
+               fprintf(stderr, "Couldn't write TRX header to %s\n", trx_path);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int otrx_create(int argc, char **argv) {
+       FILE *trx;
+       struct trx_header hdr = {};
+       ssize_t sbytes;
+       size_t curr_idx = 0;
+       size_t curr_offset = sizeof(hdr);
+       int c;
+       int err = 0;
+
+       if (argc < 3) {
+               fprintf(stderr, "No TRX file passed\n");
+               err = -EINVAL;
+               goto out;
+       }
+       trx_path = argv[2];
+
+       optind = 3;
+       otrx_create_parse_options(argc, argv);
+
+       trx = fopen(trx_path, "w+");
+       if (!trx) {
+               fprintf(stderr, "Couldn't open %s\n", trx_path);
+               err = -EACCES;
+               goto out;
+       }
+       fseek(trx, curr_offset, SEEK_SET);
+
+       optind = 3;
+       while ((c = getopt(argc, argv, "f:b:")) != -1) {
+               switch (c) {
+               case 'f':
+                       if (curr_idx >= TRX_MAX_PARTS) {
+                               err = -ENOSPC;
+                               fprintf(stderr, "Reached TRX partitions limit, no place for %s\n", optarg);
+                               goto err_close;
+                       }
+
+                       sbytes = otrx_create_append_file(trx, optarg);
+                       if (sbytes < 0) {
+                               fprintf(stderr, "Failed to append file %s\n", optarg);
+                       } else {
+                               hdr.offset[curr_idx++] = curr_offset;
+                               curr_offset += sbytes;
+                       }
+
+                       sbytes = otrx_create_align(trx, curr_offset, 4);
+                       if (sbytes < 0)
+                               fprintf(stderr, "Failed to append zeros\n");
+                       else
+                               curr_offset += sbytes;
+
+                       break;
+               case 'b':
+                       sbytes = strtol(optarg, NULL, 0) - curr_offset;
+                       if (sbytes < 0) {
+                               fprintf(stderr, "Current TRX length is 0x%zx, can't pad it with zeros to 0x%lx\n", curr_offset, strtol(optarg, NULL, 0));
+                       } else {
+                               sbytes = otrx_create_append_zeros(trx, sbytes);
+                               if (sbytes < 0)
+                                       fprintf(stderr, "Failed to append zeros\n");
+                               else
+                                       curr_offset += sbytes;
+                       }
+                       break;
+               }
+               if (err)
+                       break;
+       }
+
+       hdr.length = curr_offset;
+       otrx_create_write_hdr(trx, &hdr);
+err_close:
+       fclose(trx);
+out:
+       return err;
+}
+
 /**************************************************
  * Extract
  **************************************************/
@@ -363,6 +541,11 @@ static void usage() {
        printf("\totrx check <file> [options]\tcheck if file is a valid TRX\n");
        printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n");
        printf("\n");
+       printf("Creating new TRX file:\n");
+       printf("\totrx create <file> [options] [partitions]\n");
+       printf("\t-f file\t\t\t\t[partition] start new partition with content copied from file\n");
+       printf("\t-b offset\t\t\t[partition] append zeros to partition till reaching absolute offset\n");
+       printf("\n");
        printf("Extracting from TRX file:\n");
        printf("\totrx extract <file> [options]\textract partitions from TRX file\n");
        printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n");
@@ -375,6 +558,8 @@ int main(int argc, char **argv) {
        if (argc > 1) {
                if (!strcmp(argv[1], "check"))
                        return otrx_check(argc, argv);
+               else if (!strcmp(argv[1], "create"))
+                       return otrx_create(argc, argv);
                else if (!strcmp(argv[1], "extract"))
                        return otrx_extract(argc, argv);
        }