4 * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
23 #if !defined(__BYTE_ORDER)
24 #error "Unknown byte order"
27 #if __BYTE_ORDER == __BIG_ENDIAN
28 #define cpu_to_be32(x) (x)
29 #define be32_to_cpu(x) (x)
30 #define cpu_to_be16(x) (x)
31 #define be16_to_cpu(x) (x)
32 #elif __BYTE_ORDER == __LITTLE_ENDIAN
33 #define cpu_to_be32(x) bswap_32(x)
34 #define be32_to_cpu(x) bswap_32(x)
35 #define cpu_to_be16(x) bswap_16(x)
36 #define be16_to_cpu(x) bswap_16(x)
38 #error "Unsupported endianness"
41 #define SEAMA_MAGIC 0x5ea3a417
43 struct seama_seal_header {
48 } __attribute__ ((packed));
50 struct seama_entity_header {
56 } __attribute__ ((packed));
61 static inline size_t oseama_min(size_t x, size_t y) {
65 /**************************************************
67 **************************************************/
69 static void oseama_info_parse_options(int argc, char **argv) {
72 while ((c = getopt(argc, argv, "e:")) != -1) {
75 entity_idx = atoi(optarg);
81 static int oseama_info_entities(FILE *seama) {
82 struct seama_entity_header hdr;
83 size_t bytes, metasize, imagesize;
89 while ((bytes = fread(&hdr, 1, sizeof(hdr), seama)) == sizeof(hdr)) {
90 if (be32_to_cpu(hdr.magic) != SEAMA_MAGIC) {
91 fprintf(stderr, "Invalid Seama magic: 0x%08x\n", be32_to_cpu(hdr.magic));
95 metasize = be16_to_cpu(hdr.metasize);
96 imagesize = be32_to_cpu(hdr.imagesize);
98 if (entity_idx >= 0 && i != entity_idx) {
99 fseek(seama, metasize + imagesize, SEEK_CUR);
104 if (metasize >= sizeof(buf)) {
105 fprintf(stderr, "Too small buffer (%zu B) to read all meta info (%zd B)\n", sizeof(buf), metasize);
112 printf("Entity offset:\t%ld\n", ftell(seama) - sizeof(hdr));
113 printf("Entity size:\t%zd\n", sizeof(hdr) + metasize + imagesize);
114 printf("Meta size:\t%zd\n", metasize);
115 printf("Image size:\t%zd\n", imagesize);
117 bytes = fread(buf, 1, metasize, seama);
118 if (bytes != metasize) {
119 fprintf(stderr, "Couldn't read %zd B of meta\n", metasize);
124 end = (char *)&buf[metasize - 1];
126 for (tmp = (char *)buf; tmp < end && strlen(tmp); tmp += strlen(tmp) + 1) {
127 printf("Meta entry:\t%s\n", tmp);
130 fseek(seama, imagesize, SEEK_CUR);
138 static int oseama_info(int argc, char **argv) {
140 struct seama_seal_header hdr;
148 fprintf(stderr, "No Seama file passed\n");
152 seama_path = argv[2];
155 oseama_info_parse_options(argc, argv);
157 seama = fopen(seama_path, "r");
159 fprintf(stderr, "Couldn't open %s\n", seama_path);
164 bytes = fread(&hdr, 1, sizeof(hdr), seama);
165 if (bytes != sizeof(hdr)) {
166 fprintf(stderr, "Couldn't read %s header\n", seama_path);
170 metasize = be16_to_cpu(hdr.metasize);
171 imagesize = be32_to_cpu(hdr.imagesize);
173 if (be32_to_cpu(hdr.magic) != SEAMA_MAGIC) {
174 fprintf(stderr, "Invalid Seama magic: 0x%08x\n", be32_to_cpu(hdr.magic));
179 if (metasize >= sizeof(buf)) {
180 fprintf(stderr, "Too small buffer (%zu B) to read all meta info (%d B)\n", sizeof(buf), metasize);
186 fprintf(stderr, "Invalid Seama image size: 0x%08x (should be 0)\n", imagesize);
191 bytes = fread(buf, 1, metasize, seama);
192 if (bytes != metasize) {
193 fprintf(stderr, "Couldn't read %d B of meta\n", metasize);
198 if (entity_idx < 0) {
201 printf("Meta size:\t%d\n", metasize);
202 printf("Image size:\t%d\n", imagesize);
204 end = (char *)&buf[metasize - 1];
206 for (tmp = (char *)buf; tmp < end && strlen(tmp); tmp += strlen(tmp) + 1) {
207 printf("Meta entry:\t%s\n", tmp);
211 oseama_info_entities(seama);
219 /**************************************************
221 **************************************************/
223 static ssize_t oseama_entity_append_file(FILE *seama, const char *in_path) {
229 in = fopen(in_path, "r");
231 fprintf(stderr, "Couldn't open %s\n", in_path);
235 while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
236 if (fwrite(buf, 1, bytes, seama) != bytes) {
237 fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, seama_path);
249 static ssize_t oseama_entity_append_zeros(FILE *seama, size_t length) {
252 buf = malloc(length);
255 memset(buf, 0, length);
257 if (fwrite(buf, 1, length, seama) != length) {
258 fprintf(stderr, "Couldn't write %zu B to %s\n", length, seama_path);
265 static ssize_t oseama_entity_align(FILE *seama, size_t curr_offset, size_t alignment) {
266 if (curr_offset & (alignment - 1)) {
267 size_t length = alignment - (curr_offset % alignment);
269 return oseama_entity_append_zeros(seama, length);
275 static int oseama_entity_write_hdr(FILE *seama, size_t metasize, size_t imagesize) {
276 struct seama_entity_header hdr = {};
278 size_t length = imagesize;
282 fseek(seama, sizeof(hdr) + metasize, SEEK_SET);
284 while ((bytes = fread(buf, 1, oseama_min(sizeof(buf), length), seama)) > 0) {
285 MD5_Update(&ctx, buf, bytes);
288 MD5_Final(hdr.md5, &ctx);
290 hdr.magic = cpu_to_be32(SEAMA_MAGIC);
291 hdr.metasize = cpu_to_be16(metasize);
292 hdr.imagesize = cpu_to_be32(imagesize);
294 fseek(seama, 0, SEEK_SET);
295 bytes = fwrite(&hdr, 1, sizeof(hdr), seama);
296 if (bytes != sizeof(hdr)) {
297 fprintf(stderr, "Couldn't write Seama entity header to %s\n", seama_path);
304 static int oseama_entity(int argc, char **argv) {
307 size_t curr_offset = sizeof(struct seama_entity_header);
308 size_t metasize = 0, imagesize = 0;
313 fprintf(stderr, "No Seama file passed\n");
317 seama_path = argv[2];
319 seama = fopen(seama_path, "w+");
321 fprintf(stderr, "Couldn't open %s\n", seama_path);
325 fseek(seama, curr_offset, SEEK_SET);
328 while ((c = getopt(argc, argv, "m:f:b:")) != -1) {
331 sbytes = fwrite(optarg, 1, strlen(optarg) + 1, seama);
333 fprintf(stderr, "Failed to write meta %s\n", optarg);
335 curr_offset += sbytes;
339 sbytes = oseama_entity_align(seama, curr_offset, 4);
341 fprintf(stderr, "Failed to append zeros\n");
343 curr_offset += sbytes;
355 while ((c = getopt(argc, argv, "m:f:b:")) != -1) {
360 sbytes = oseama_entity_append_file(seama, optarg);
362 fprintf(stderr, "Failed to append file %s\n", optarg);
364 curr_offset += sbytes;
369 sbytes = strtol(optarg, NULL, 0) - curr_offset;
371 fprintf(stderr, "Current Seama entity length is 0x%zx, can't pad it with zeros to 0x%lx\n", curr_offset, strtol(optarg, NULL, 0));
373 sbytes = oseama_entity_append_zeros(seama, sbytes);
375 fprintf(stderr, "Failed to append zeros\n");
377 curr_offset += sbytes;
387 oseama_entity_write_hdr(seama, metasize, imagesize);
394 /**************************************************
396 **************************************************/
398 static void usage() {
401 printf("Info about Seama seal (container):\n");
402 printf("\toseama info <file> [options]\n");
403 printf("\t-e\t\t\t\tprint info about specified entity only\n");
405 printf("Create Seama entity:\n");
406 printf("\toseama entity <file> [options]\n");
407 printf("\t-m meta\t\t\t\tmeta into to put in header\n");
408 printf("\t-f file\t\t\t\tappend content from file\n");
409 printf("\t-b offset\t\t\tappend zeros till reaching absolute offset\n");
412 int main(int argc, char **argv) {
414 if (!strcmp(argv[1], "info"))
415 return oseama_info(argc, argv);
416 else if (!strcmp(argv[1], "entity"))
417 return oseama_entity(argc, argv);