oseama: allow reading from stdin
authorRafał Miłecki <rafal@milecki.pl>
Fri, 26 Nov 2021 16:17:07 +0000 (17:17 +0100)
committerRafał Miłecki <rafal@milecki.pl>
Thu, 2 Dec 2021 07:33:30 +0000 (08:33 +0100)
This adds support for reading Seama seal from stdin when using "info" or
"extract" command. It allows e.g.

cat firmware.bin | oseama info -

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
src/oseama.c

index 75580e6cf55a52c186b90e0a6743efec1e0fa726..d3eb9b91f2d1434025cba0e9485cf4f08a077815 100644 (file)
@@ -59,6 +59,44 @@ static inline size_t oseama_min(size_t x, size_t y) {
        return x < y ? x : y;
 }
 
+/**************************************************
+ * Helpers
+ **************************************************/
+
+static FILE *oseama_open(const char *pathname, const char *mode) {
+       if (strcmp(pathname, "-"))
+               return fopen(pathname, mode);
+
+       if (isatty(fileno(stdin))) {
+               fprintf(stderr, "Reading from TTY stdin is unsupported\n");
+               return NULL;
+       }
+
+       return stdin;
+}
+
+static int oseama_skip(FILE *fp, size_t length)
+{
+       if (fseek(fp, length, SEEK_CUR)) {
+               uint8_t buf[1024];
+               size_t bytes;
+
+               do {
+                       bytes = fread(buf, 1, oseama_min(sizeof(buf), length), fp);
+                       if (bytes <= 0)
+                               return -EIO;
+                       length -= bytes;
+               } while (length);
+       }
+
+       return 0;
+}
+
+static void oseama_close(FILE *fp) {
+       if (fp != stdin)
+               fclose(fp);
+}
+
 /**************************************************
  * Info
  **************************************************/
@@ -75,7 +113,7 @@ static void oseama_info_parse_options(int argc, char **argv) {
        }
 }
 
-static int oseama_info_entities(FILE *seama) {
+static int oseama_info_entities(FILE *seama, size_t *pos) {
        struct seama_entity_header hdr;
        size_t bytes, metasize, imagesize;
        uint8_t buf[1024];
@@ -84,6 +122,8 @@ static int oseama_info_entities(FILE *seama) {
        int err = 0;
 
        while ((bytes = fread(&hdr, 1, sizeof(hdr), seama)) == sizeof(hdr)) {
+               *pos += bytes;
+
                if (be32_to_cpu(hdr.magic) != SEAMA_MAGIC) {
                        fprintf(stderr, "Invalid Seama magic: 0x%08x\n", be32_to_cpu(hdr.magic));
                        err =  -EINVAL;
@@ -93,7 +133,8 @@ static int oseama_info_entities(FILE *seama) {
                imagesize = be32_to_cpu(hdr.imagesize);
 
                if (entity_idx >= 0 && i != entity_idx) {
-                       fseek(seama, metasize + imagesize, SEEK_CUR);
+                       oseama_skip(seama, metasize + imagesize);
+                       *pos += metasize + imagesize;
                        i++;
                        continue;
                }
@@ -106,7 +147,7 @@ static int oseama_info_entities(FILE *seama) {
 
                if (entity_idx < 0)
                        printf("\n");
-               printf("Entity offset:\t%ld\n", ftell(seama) - sizeof(hdr));
+               printf("Entity offset:\t%ld\n", *pos - sizeof(hdr));
                printf("Entity size:\t%zd\n", sizeof(hdr) + metasize + imagesize);
                printf("Meta size:\t%zd\n", metasize);
                printf("Image size:\t%zd\n", imagesize);
@@ -117,6 +158,7 @@ static int oseama_info_entities(FILE *seama) {
                        err =  -EIO;
                        goto err_out;
                }
+               *pos += bytes;
 
                end = (char *)&buf[metasize - 1];
                *end = '\0';
@@ -124,7 +166,8 @@ static int oseama_info_entities(FILE *seama) {
                        printf("Meta entry:\t%s\n", tmp);
                }
 
-               fseek(seama, imagesize, SEEK_CUR);
+               oseama_skip(seama, imagesize);
+               *pos += imagesize;
                i++;
        }
 
@@ -139,6 +182,7 @@ static int oseama_info(int argc, char **argv) {
        uint16_t metasize;
        uint32_t imagesize;
        uint8_t buf[1024];
+       size_t pos = 0;
        int err = 0;
 
        if (argc < 3) {
@@ -151,7 +195,7 @@ static int oseama_info(int argc, char **argv) {
        optind = 3;
        oseama_info_parse_options(argc, argv);
 
-       seama = fopen(seama_path, "r");
+       seama = oseama_open(seama_path, "r");
        if (!seama) {
                fprintf(stderr, "Couldn't open %s\n", seama_path);
                err = -EACCES;
@@ -164,6 +208,8 @@ static int oseama_info(int argc, char **argv) {
                err =  -EIO;
                goto err_close;
        }
+       pos += bytes;
+
        metasize = be16_to_cpu(hdr.metasize);
        imagesize = be32_to_cpu(hdr.imagesize);
 
@@ -191,6 +237,7 @@ static int oseama_info(int argc, char **argv) {
                err =  -EIO;
                goto err_close;
        }
+       pos += bytes;
 
        if (entity_idx < 0) {
                char *end, *tmp;
@@ -205,10 +252,10 @@ static int oseama_info(int argc, char **argv) {
                }
        }
 
-       oseama_info_entities(seama);
+       oseama_info_entities(seama, &pos);
 
 err_close:
-       fclose(seama);
+       oseama_close(seama);
 out:
        return err;
 }
@@ -424,14 +471,18 @@ static int oseama_extract_entity(FILE *seama, FILE *out) {
                imagesize = be32_to_cpu(hdr.imagesize);
 
                if (i != entity_idx) {
-                       fseek(seama, metasize + imagesize, SEEK_CUR);
+                       oseama_skip(seama, metasize + imagesize);
                        i++;
                        continue;
                }
 
-               fseek(seama, -sizeof(hdr), SEEK_CUR);
+               if (fwrite(&hdr, 1, sizeof(hdr), out) != sizeof(hdr)) {
+                       fprintf(stderr, "Couldn't write %zu B to %s\n", sizeof(hdr), out_path);
+                       err = -EIO;
+                       break;
+               }
 
-               length = sizeof(hdr) + metasize + imagesize;
+               length = metasize + imagesize;
                while ((bytes = fread(buf, 1, oseama_min(sizeof(buf), length), seama)) > 0) {
                        if (fwrite(buf, 1, bytes, out) != bytes) {
                                fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
@@ -480,7 +531,7 @@ static int oseama_extract(int argc, char **argv) {
                goto out;
        }
 
-       seama = fopen(seama_path, "r");
+       seama = oseama_open(seama_path, "r");
        if (!seama) {
                fprintf(stderr, "Couldn't open %s\n", seama_path);
                err = -EACCES;
@@ -502,14 +553,14 @@ static int oseama_extract(int argc, char **argv) {
        }
        metasize = be16_to_cpu(hdr.metasize);
 
-       fseek(seama, metasize, SEEK_CUR);
+       oseama_skip(seama, metasize);
 
        oseama_extract_entity(seama, out);
 
 err_close_out:
        fclose(out);
 err_close_seama:
-       fclose(seama);
+       oseama_close(seama);
 out:
        return err;
 }