static struct dentry *find_file_in_archive(const struct directory *dir, const char *name) { struct dentry *entry; uintptr_t start; int i; if (!dir) { printf("%s: archive not loaded\n", __func__); return NULL; } /* calculate start of the file content section */ start = get_first_offset(dir); entry = get_first_dentry(dir); for (i = 0; i < dir->count; i++) { if (strncmp(entry[i].name, name, NAME_LENGTH)) continue; /* validate offset & size */ if (entry[i].offset < start || entry[i].offset + entry[i].size > dir->size || entry[i].offset > dir->size || entry[i].size > dir->size) { printf("%s: '%s' has invalid offset or size\n", __func__, name); return NULL; } return &entry[i]; } printf("%s: file '%s' not found\n", __func__, name); return NULL; }
static int set_file_name(const char *path, struct dentry *dest) { struct dentry *entry; char *name, *copy; int i; copy = strdup(path); name = basename(copy); /* check name length */ if (strlen(name) > NAME_LENGTH) { fprintf(stderr, "Error: file name '%s' exceeds %d chars\n", name, NAME_LENGTH); free(copy); return -1; } /* check if there is a duplicate name */ entry = get_first_dentry(archive); for (i = 0; i < archive->count && &entry[i] != dest; i++) { if (!strncmp(entry[i].name, name, NAME_LENGTH)) { fprintf(stderr, "Error: duplicate name '%s'\n", name); free(copy); return -1; } } /* copy the name to the entry */ strncpy(dest->name, name, NAME_LENGTH); free(copy); return 0; }
/* * Load archive into RAM */ static VbError_t load_archive(const char *name, struct directory **dest) { struct directory *dir; struct dentry *entry; size_t size; int i; printf("%s: loading %s\n", __func__, name); *dest = NULL; /* load archive from cbfs */ dir = cbfs_get_file_content(ro_cbfs, name, CBFS_TYPE_RAW, &size); if (!dir || !size) { printf("%s: failed to load %s\n", __func__, name); return VBERROR_INVALID_BMPFV; } /* convert endianness of archive header */ dir->count = le32toh(dir->count); dir->size = le32toh(dir->size); /* validate the total size */ if (dir->size != size) { printf("%s: archive size does not match\n", __func__); return VBERROR_INVALID_BMPFV; } /* validate magic field */ if (memcmp(dir->magic, CBAR_MAGIC, sizeof(CBAR_MAGIC))) { printf("%s: invalid archive magic\n", __func__); return VBERROR_INVALID_BMPFV; } /* validate count field */ if (get_first_offset(dir) > dir->size) { printf("%s: invalid count\n", __func__); return VBERROR_INVALID_BMPFV; } /* convert endianness of file headers */ entry = get_first_dentry(dir); for (i = 0; i < dir->count; i++) { entry[i].offset = le32toh(entry[i].offset); entry[i].size = le32toh(entry[i].size); } *dest = dir; return VBERROR_SUCCESS; }
static void convert_endian(void) { struct dentry *entry; int i; entry = get_first_dentry(archive); for (i = 0; i < archive->count; i++) { entry[i].offset = htole32(entry[i].offset); entry[i].size = htole32(entry[i].size); } archive->version = htole32(archive->version); archive->size = htole32(archive->size); archive->count = htole32(archive->count); }
/* * Store files in archive */ static int archive_files(const char **files) { struct dentry *entry; uint32_t offset; int i; entry = get_first_dentry(archive); offset = get_first_offset(archive); for (i = 0; i < archive->count; i++) { if (add_file(files[i], entry, offset)) return -1; offset += entry->size; entry++; } return 0; }