1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 4 */ 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <stdint.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <libgen.h> 12 #include <getopt.h> 13 #include <stdarg.h> 14 #include <errno.h> 15 #include <sys/stat.h> 16 17 #include "md5.h" 18 19 #define ERR(fmt, ...) do { \ 20 fflush(0); \ 21 fprintf(stderr, "[%s] *** error: " fmt "\n", \ 22 progname, ## __VA_ARGS__ ); \ 23 } while (0) 24 25 #define ERRS(fmt, ...) do { \ 26 int save = errno; \ 27 fflush(0); \ 28 fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \ 29 progname, ## __VA_ARGS__, strerror(save)); \ 30 } while (0) 31 32 #define WRG_MAGIC 0x20040220 33 34 struct wrg_header { 35 char signature[32]; 36 uint32_t magic1; 37 uint32_t magic2; 38 uint32_t size; 39 uint32_t offset; 40 char devname[32]; 41 char digest[16]; 42 } __attribute__ ((packed)); 43 44 static char *progname; 45 static char *ifname; 46 static char *ofname; 47 static char *signature; 48 static char *dev_name; 49 static uint32_t offset; 50 static int big_endian; 51 52 void usage(int status) 53 { 54 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 55 56 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 57 fprintf(stream, 58 "\n" 59 "Options:\n" 60 " -b create image in big endian format\n" 61 " -i <file> read input from the file <file>\n" 62 " -d <name> set device name to <name>\n" 63 " -o <file> write output to the file <file>\n" 64 " -O <offset> set offset to <offset>\n" 65 " -s <sig> set image signature to <sig>\n" 66 " -h show this screen\n" 67 ); 68 69 exit(status); 70 } 71 72 static void put_u32(void *data, uint32_t val) 73 { 74 unsigned char *p = data; 75 76 if (big_endian) { 77 p[0] = (val >> 24) & 0xff; 78 p[1] = (val >> 16) & 0xff; 79 p[2] = (val >> 8) & 0xff; 80 p[3] = val & 0xff; 81 } else { 82 p[3] = (val >> 24) & 0xff; 83 p[2] = (val >> 16) & 0xff; 84 p[1] = (val >> 8) & 0xff; 85 p[0] = val & 0xff; 86 } 87 } 88 89 static void get_digest(struct wrg_header *header, char *data, int size) 90 { 91 MD5_CTX ctx; 92 93 MD5_Init(&ctx); 94 95 MD5_Update(&ctx, (char *)&header->offset, sizeof(header->offset)); 96 MD5_Update(&ctx, (char *)&header->devname, sizeof(header->devname)); 97 MD5_Update(&ctx, data, size); 98 99 MD5_Final((unsigned char *)header->digest, &ctx); 100 } 101 102 int main(int argc, char *argv[]) 103 { 104 struct wrg_header *header; 105 char *buf; 106 struct stat st; 107 int buflen; 108 int err; 109 int res = EXIT_FAILURE; 110 111 FILE *outfile, *infile; 112 113 progname = basename(argv[0]); 114 115 while ( 1 ) { 116 int c; 117 118 c = getopt(argc, argv, "bd:i:o:s:O:h"); 119 if (c == -1) 120 break; 121 122 switch (c) { 123 case 'b': 124 big_endian = 1; 125 break; 126 case 'd': 127 dev_name = optarg; 128 break; 129 case 'i': 130 ifname = optarg; 131 break; 132 case 'o': 133 ofname = optarg; 134 break; 135 case 's': 136 signature = optarg; 137 break; 138 case 'O': 139 offset = strtoul(optarg, NULL, 0); 140 break; 141 case 'h': 142 usage(EXIT_SUCCESS); 143 break; 144 145 default: 146 usage(EXIT_FAILURE); 147 break; 148 } 149 } 150 151 if (signature == NULL) { 152 ERR("no signature specified"); 153 goto err; 154 } 155 156 if (ifname == NULL) { 157 ERR("no input file specified"); 158 goto err; 159 } 160 161 if (ofname == NULL) { 162 ERR("no output file specified"); 163 goto err; 164 } 165 166 if (dev_name == NULL) { 167 ERR("no device name specified"); 168 goto err; 169 } 170 171 err = stat(ifname, &st); 172 if (err){ 173 ERRS("stat failed on %s", ifname); 174 goto err; 175 } 176 177 buflen = st.st_size + sizeof(struct wrg_header); 178 buf = malloc(buflen); 179 if (!buf) { 180 ERR("no memory for buffer\n"); 181 goto err; 182 } 183 184 infile = fopen(ifname, "r"); 185 if (infile == NULL) { 186 ERRS("could not open \"%s\" for reading", ifname); 187 goto err_free; 188 } 189 190 errno = 0; 191 fread(buf + sizeof(struct wrg_header), st.st_size, 1, infile); 192 if (errno != 0) { 193 ERRS("unable to read from file %s", ifname); 194 goto close_in; 195 } 196 197 header = (struct wrg_header *) buf; 198 memset(header, '\0', sizeof(struct wrg_header)); 199 200 strncpy(header->signature, signature, sizeof(header->signature)); 201 strncpy(header->devname, dev_name, sizeof(header->signature)); 202 put_u32(&header->magic1, WRG_MAGIC); 203 put_u32(&header->magic2, WRG_MAGIC); 204 put_u32(&header->size, st.st_size); 205 put_u32(&header->offset, offset); 206 207 get_digest(header, buf + sizeof(struct wrg_header), st.st_size); 208 209 outfile = fopen(ofname, "w"); 210 if (outfile == NULL) { 211 ERRS("could not open \"%s\" for writing", ofname); 212 goto close_in; 213 } 214 215 errno = 0; 216 fwrite(buf, buflen, 1, outfile); 217 if (errno) { 218 ERRS("unable to write to file %s", ofname); 219 goto close_out; 220 } 221 222 fflush(outfile); 223 224 res = EXIT_SUCCESS; 225 226 close_out: 227 fclose(outfile); 228 if (res != EXIT_SUCCESS) 229 unlink(ofname); 230 close_in: 231 fclose(infile); 232 err_free: 233 free(buf); 234 err: 235 return res; 236 } 237
This page was automatically generated by LXR 0.3.1. • OpenWrt