[PATCH firmware-utils 1/2] oseama: allow reading from stdin

Rafał Miłecki zajec5 at gmail.com
Fri Nov 26 08:17:07 PST 2021


From: Rafał Miłecki <rafal at milecki.pl>

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 at milecki.pl>
---
 src/oseama.c | 77 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 64 insertions(+), 13 deletions(-)

diff --git a/src/oseama.c b/src/oseama.c
index 75580e6..d3eb9b9 100644
--- a/src/oseama.c
+++ b/src/oseama.c
@@ -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;
 }
-- 
2.31.1




More information about the openwrt-devel mailing list