111int main(
int argc,
const char* argv[]) {
117 const char* action = argv[1];
118 const char* efires = argv[2];
119 const char* directory = NULL;
120 const char* filelist_fname = NULL;
121 const char** filelist = NULL;
130 filelist_fname = argv[4];
136 if (strcmp(action,
ACTION_LIST) == 0) flags |= ONLY_LIST;
138 retval =
unpack_efires(efires, directory, flags, (
char***) ((filelist_fname) ? &filelist : NULL));
140 if (!retval && filelist_fname) {
141 if (filelist == NULL) {
142 fprintf(stderr,
"Failed to build filelist\n");
151 if (filelist == NULL) {
152 fprintf(stderr,
"Failed to parse filelist\n");
159 retval = EXIT_FAILURE;
239 size_t file_size = 0;
240 const void *file_map = NULL;
242 if (filelist) *filelist = NULL;
244 if (((flags & ONLY_LIST) == 0) && (destination == NULL)) {
245 fprintf(stderr,
"Cant determine destination\n");
249 int fd = open(fname, O_RDONLY);
251 fprintf(stderr,
"Cant open resource file (%s): %s\n", fname, strerror(errno));
256 if (fstat(fd, &s) != 0) {
257 fprintf(stderr,
"fstat failed for (%s): %s\n", fname, strerror(errno));
261 file_size = s.st_size;
263 if (file_size <
sizeof(efires_hdr_t)) {
264 fprintf(stderr,
"File is too short to be an efires file\n");
268 file_map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
269 if (file_map == MAP_FAILED) {
270 fprintf(stderr,
"Cant mmap file (%s): %s\n", fname, strerror(errno));
275 const efires_hdr_t *hdr = (
const efires_hdr_t *) file_map;
277 fprintf(stderr,
"Wrong efires revision: 0x%02x (expected 0x%02x)\n", le16toh(hdr->revision),
EFIRES_CURRENT_REVISION);
281 uint16_t nentries = le16toh(hdr->nentries);
282 fprintf(stderr,
"File with 0x%x entries: %s\n", nentries, fname);
284 if (nentries *
sizeof(efires_file_t) +
sizeof(efires_hdr_t) > file_size) {
285 fprintf(stderr,
"File is too small to have so many entries\n");
289 char** filelist_iter = NULL;
292 *filelist =
malloc((nentries + 1) *
sizeof(
char*));
293 filelist_iter = *filelist;
295 *filelist_iter = NULL;
297 fprintf(stderr,
"Cant allocate memory for filelist\n");
302 if ((flags & ONLY_LIST) == 0) {
303 if (mkdir(destination, 0755) != 0) {
304 fprintf(stderr,
"Cant create destination directory '%s': %s\n", destination, strerror(errno));
308 if (chdir(destination) != 0) {
309 fprintf(stderr,
"Cant chdir to destination directory '%s': %s\n", destination, strerror(errno));
314 for (
uint16_t i = 0; i != nentries; ++i) {
315 const efires_file_t *ent = &hdr->entries[i];
316 uint32_t off = le32toh(ent->offset);
317 uint32_t len = le32toh(ent->length);
319 printf(
"0x%04x (0x%08x - 0x%08x): %s\n", i, off, off + len, ent->name);
321 if (filelist_iter) *(filelist_iter++) = strdup(ent->name);
323 if (flags & ONLY_LIST)
continue;
325 if (off + len > file_size) {
326 fprintf(stderr,
"File 0x%04x: overflows efires file -- skipping\n", i);
330 int f = open(ent->name, O_WRONLY|O_CREAT|O_EXCL, 0755);
333 fprintf(stderr,
"File 0x%04x: Failed to create file: %s\n", i, strerror(errno));
337 int wrote = write(f, (
void*) ((
uintptr_t)file_map + off), len);
339 fprintf(stderr,
"File 0x%04x: Expected to write %d bytes, wrote %d: %s\n", i, len, wrote, strerror(errno));
349 if (result && filelist && *filelist) {
355 munmap((
void*)file_map, file_size);
360int pack_efires(
const char* fname,
const char* fromdir,
const char* filelist[]) {
365 size_t file_size = 0;
366 void *file_map = NULL;
369 dir = opendir(fromdir);
371 if (dir == NULL || dfd == -1) {
372 fprintf(stderr,
"Cant open directory to pack (%s) : %s\n", fromdir, strerror(errno));
376 outfd = open(fname, O_RDWR | O_CREAT | O_EXCL, 0644);
378 fprintf(stderr,
"Cant open output file (%s) : %s\n", fname, strerror(errno));
385 if (write(outfd, &tmp,
sizeof(tmp)) == -1)
390 uint32_t full_file_len =
sizeof(efires_hdr_t) +
sizeof(efires_file_t);
392 efires_file_t cur_entr;
393 struct dirent *ep = NULL;
394 const char** itm = filelist;
396 while ((itm && *itm) || ((itm == NULL) && (ep = readdir(dir)) != NULL)) {
399 const char* d_name = NULL;
407 if (fstatat(dfd, d_name, &s, 0) != 0) {
408 fprintf(stderr,
"Cant stat file, skipping (%s/%s) : %s\n", fromdir, d_name, strerror(errno));
413 fprintf(stderr,
"Entry isn't regular file, skipping (%s/%s)\n", fromdir, d_name);
418 fprintf(stderr,
"File too big for efires, skipping (%s/%s)\n", fromdir, d_name);
422 cur_entr.length = (
uint32_t) s.st_size;
424 if (full_file_len + cur_entr.length >
UINT32_MAX) {
425 fprintf(stderr,
"File too big to fit in current state, skipping (%u bytes left, %u bytes needed) (%s/%s)\n",
UINT32_MAX - full_file_len, cur_entr.length, fromdir, d_name);
429 size_t e_name_len = strlen(d_name);
430 if (e_name_len >
sizeof(cur_entr.name)) {
431 fprintf(stderr,
"Filename too long, skipping (%s/%s)\n", fromdir, d_name);
436 memcpy(cur_entr.name, d_name, e_name_len);
438 if (e_name_len <
sizeof(cur_entr.name)) {
439 memset(cur_entr.name + e_name_len, 0,
sizeof(cur_entr.name) - e_name_len);
442 if (write(outfd, &cur_entr,
sizeof(cur_entr)) !=
sizeof(cur_entr)) {
443 fprintf(stderr,
"Write to result file failed: %s\n", strerror(errno));
447 full_file_len +=
sizeof(cur_entr) + cur_entr.length;
450 fprintf(stderr,
"Too many entries, only packing 0x%08x\n", nentries);
456 memset(&cur_entr, 0,
sizeof(cur_entr));
457 if (write(outfd, &cur_entr,
sizeof(cur_entr)) !=
sizeof(cur_entr)) {
458 fprintf(stderr,
"Write to result file failed: %s\n", strerror(errno));
462 if (ftruncate(outfd, full_file_len) != 0) {
463 fprintf(stderr,
"Failed to expand result file to needed size: %s\n", strerror(errno));
467 file_map = mmap(NULL, full_file_len, PROT_READ | PROT_WRITE, MAP_SHARED, outfd, 0);
469 if (file_map == MAP_FAILED) {
470 fprintf(stderr,
"Cant mmap result file: %s\n", strerror(errno));
475 efires_hdr_t *hdr = (efires_hdr_t *) file_map;
477 hdr->nentries = htole16(nentries);
480 uint32_t current_offset =
sizeof(efires_hdr_t) + (nentries + 1) *
sizeof(efires_file_t);
481 for (
uint16_t i = 0; i != nentries; ++i) {
482 efires_file_t *ent = &hdr->entries[i];
486 current_offset += length;
488 ent->length = htole32(length);
489 ent->offset = htole32(offset);
491 printf(
"0x%04x (0x%08x - 0x%08x): %s\n", i, offset, offset + length, ent->name);
493 int entfd = openat(dfd, ent->name, O_RDONLY);
496 fprintf(stderr,
"Cant open file, leaving zeroed (%s/%s): %s\n", fromdir, ent->name, strerror(errno));
500 if (read(entfd, (
void*) ((
uintptr_t)file_map + offset), length) != length) {
501 fprintf(stderr,
"Cant read %u bytes from file, contents in efires undefined (%s/%s): %s\n", length, fromdir, ent->name, strerror(errno));
514 if (file_map != NULL) {
515 munmap(file_map, file_size);