/* Copyright (C) 2014-2015 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include #include #include #include #include #include #include "rom.h" #include "logging.h" /* Return whether or not the given ROM image size is valid. */ static bool validate_size(off_t size) { off_t kbytes = size >> 10; if (kbytes << 10 != size) return false; if (kbytes < 8 || kbytes > 1024) return false; return !(kbytes & (kbytes - 1)); } /* Create and load a ROM image located at the given path. rom_ptr will point to the new object if created successfully, and NULL will be returned. Otherwise, rom_ptr will not be modified and an error string will be returned. The error string should not be freed. */ const char* rom_open(ROM **rom_ptr, const char *path) { ROM *rom; FILE* fp; struct stat st; if (!(fp = fopen(path, "r"))) return strerror(errno); if (fstat(fileno(fp), &st)) { fclose(fp); return strerror(errno); } if (!(st.st_mode & S_IFREG)) { fclose(fp); return (st.st_mode & S_IFDIR) ? rom_err_isdir : rom_err_notfile; } if (!(rom = malloc(sizeof(ROM)))) OUT_OF_MEMORY() // Set defaults: rom->name = NULL; rom->data = NULL; rom->size = 0; // Set rom->name: if (!(rom->name = malloc(sizeof(char) * (strlen(path) + 1)))) OUT_OF_MEMORY() strcpy(rom->name, path); // Set rom->size: if (!validate_size(st.st_size)) { rom_close(rom); fclose(fp); return rom_err_badsize; } rom->size = st.st_size; // Set rom->data: if (!(rom->data = malloc(sizeof(char) * st.st_size))) OUT_OF_MEMORY() if (!(fread(rom->data, st.st_size, 1, fp))) { rom_close(rom); fclose(fp); return rom_err_badread; } fclose(fp); *rom_ptr = rom; return NULL; } /* Free a ROM object previously created with rom_open(). */ void rom_close(ROM *rom) { if (rom->name) free(rom->name); if (rom->data) free(rom->data); free(rom); }