diff -r 000000000000 -r b8638c3c7eee librazor/dump.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/librazor/dump.c Wed Oct 22 12:09:47 2014 +0100 @@ -0,0 +1,488 @@ +/* + * Copyright (C) 2014 J. Ali Harlow + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include + +#include "razor.h" +#include "razor-internal.h" + +static size_t +dump_raw(FILE *fp, void *raw, char *what, size_t length, size_t offset) +{ + size_t i, n = 0; + unsigned char *bytes = raw; + + while (length) { + fprintf(fp, "%05lX %s", (unsigned long)(offset + n), what); + for (i = 0; (i < 16) && (length > 0);) { + if (length >= 4) { + fprintf(fp, " %08X", *(uint32_t *)bytes); + bytes += 4; + n += 4; + length -= 4; + i += 4; + } else if (length >= 2) { + fprintf(fp, " %04X", *(unsigned short *)bytes); + bytes += 2; + n += 2; + length -= 2; + i += 2; + } else { + fprintf(fp, " %02X", *bytes); + bytes++; + n++; + length--; + i++; + } + } + fprintf(fp, "\n"); + } + + return n; +} + +static size_t +dump_string(FILE *fp, char *pool, size_t length, size_t offset) +{ + size_t n = 0; + unsigned char c; + + fprintf(fp, "\""); + while (offset + n < length) { + c = pool[offset + n++]; + if (c == '\0') { + fprintf(fp, "\\0"); + break; + } + else if (c == '\\' || c == '"') + fprintf(fp, "\\%c", c); + else if (c >= ' ' && c <= '~') + fprintf(fp, "%c", c); + else + fprintf(fp, "\\x%02X", c); + } + fprintf(fp, "\""); + + return n; +} + +static size_t +dump_pool(FILE *fp, char *pool, char *what, size_t length, size_t offset) +{ + size_t n = 0; + + fprintf(fp, "%05lX %s {\n", (unsigned long)offset, what); + + while (n < length) { + fprintf(fp, " %08X ", (uint32_t)n); + n += dump_string(fp, pool, length, n); + fprintf(fp, "\n"); + } + + fprintf(fp, "}\n"); + + return n; +} + +static size_t +dump_header(FILE *fp, struct razor_set_header *header, size_t length, + size_t offset) +{ + if (length >= sizeof(*header)) { + fprintf(fp, "%05lX header ", (unsigned long)offset); + fprintf(fp, "{ magic=%08X version=%08X num_sections=%08X }\n", + header->magic, header->version, header->num_sections); + return sizeof(*header); + } else + return dump_raw(fp, header, "unknown", length, offset); +} + +static size_t +dump_section(FILE *fp, struct razor_set_section *section, size_t length, + size_t offset, int indx) +{ + if (length >= sizeof(*section)) { + fprintf(fp, "%05lX section %X ", (unsigned long)offset, indx); + fprintf(fp, "{ name=%08X offset=%08X size=%08X }\n", + section->name, section->offset, section->size); + return sizeof(*section); + } else + return dump_raw(fp, section, "unknown", length, offset); +} + +static void +dump_list_head(FILE *fp, struct list_head *head) +{ + fprintf(fp, "{ list_ptr=%06X flags=%02X ", + head->list_ptr, head->flags); + if (head->flags == RAZOR_EMPTY_LIST) + fprintf(fp, "(EMPTY_LIST) "); + else if (head->flags == RAZOR_IMMEDIATE) + fprintf(fp, "(IMMEDIATE) "); + fprintf(fp,"}"); +} + +static void +dump_list_link(FILE *fp, struct list *list) +{ + fprintf(fp, "{ data=%06X flags=%02X ", + list->data, list->flags); + if (list->flags == RAZOR_ENTRY_LAST) + fprintf(fp, "(ENTRY_LAST) "); + else if (list->flags == RAZOR_ENTRY_FIRST) + fprintf(fp, "(ENTRY_FIRST) "); + fprintf(fp,"}"); +} + +static void +expand_pooled_string(FILE *fp, struct array *pool, uint32_t str) +{ + if (pool->data && str < pool->size) { + fprintf(fp, "("); + dump_string(fp, pool->data, pool->size, str); + fprintf(fp, ") "); + } +} + +static size_t +dump_package(FILE *fp, struct razor_package *package, size_t length, + size_t offset, struct array *string_pool, int indx) +{ + if (length >= sizeof(*package)) { + fprintf(fp, " %05lX package %X ", (unsigned long)offset, + indx); + fprintf(fp, "{ name=%06X ", package->name); + expand_pooled_string(fp, string_pool, package->name); + fprintf(fp, "flags=%02X\n version=%08X ", + package->flags, package->version); + expand_pooled_string(fp, string_pool, package->version); + fprintf(fp, "arch=%08X ", package->arch); + expand_pooled_string(fp, string_pool, package->arch); + fprintf(fp, "\n " + "summary=%08X description=%08X url=%08X license=%08X\n", + package->summary, package->description, + package->url, package->license); + fprintf(fp," properties="); + dump_list_head(fp, &package->properties); + fprintf(fp,"\n"); + fprintf(fp," files="); + dump_list_head(fp, &package->files); + fprintf(fp,"\n"); + fprintf(fp," install_prefixes="); + dump_list_head(fp, &package->install_prefixes); + fprintf(fp,"\n"); + fprintf(fp," preun={ program=%08X body=%08X }\n", + package->preun.program, package->preun.body); + fprintf(fp," postun={ program=%08X body=%08X }\n", + package->postun.program, package->postun.body); + fprintf(fp," }\n"); + return sizeof(*package); + } else + return dump_raw(fp, package, "unknown", length, offset); +} + +static size_t +dump_packages(FILE *fp, struct razor_package *packages, size_t length, + size_t offset, struct array *string_pool) +{ + size_t n = 0; + int i = 0; + + fprintf(fp, "%05lX packages {\n", (unsigned long)offset); + + while (n < length) { + n += dump_package(fp, packages, length - n, n, string_pool, i); + packages++; + i++; + } + + fprintf(fp, "}\n"); + + return n; +} + +static size_t +dump_property(FILE *fp, struct razor_property *property, size_t length, + size_t offset, struct array *string_pool) +{ + if (length >= sizeof(*property)) { + fprintf(fp, " %05lX property ", (unsigned long)offset); + fprintf(fp, "{ name=%08X ", property->name); + expand_pooled_string(fp, string_pool, property->name); + fprintf(fp, "\n flags=%08X (", property->flags); + if (property->flags & RAZOR_PROPERTY_LESS) + fprintf(fp, "<"); + if (property->flags & RAZOR_PROPERTY_GREATER) + fprintf(fp, ">"); + if (property->flags & RAZOR_PROPERTY_EQUAL) + fprintf(fp, "="); + switch (property->flags & RAZOR_PROPERTY_TYPE_MASK) { + case RAZOR_PROPERTY_REQUIRES: + fprintf(fp, " requires"); + break; + case RAZOR_PROPERTY_PROVIDES: + fprintf(fp, " provides"); + break; + case RAZOR_PROPERTY_CONFLICTS: + fprintf(fp, " conflicts"); + break; + case RAZOR_PROPERTY_OBSOLETES: + fprintf(fp, " obsoletes"); + break; + } + if (property->flags & RAZOR_PROPERTY_PRE) + fprintf(fp, " pre"); + if (property->flags & RAZOR_PROPERTY_POST) + fprintf(fp, " post"); + if (property->flags & RAZOR_PROPERTY_PREUN) + fprintf(fp, " preun"); + if (property->flags & RAZOR_PROPERTY_POSTUN) + fprintf(fp, " postun"); + fprintf(fp, ") version=%08X ", property->version); + expand_pooled_string(fp, string_pool, property->version); + fprintf(fp,"\n packages="); + dump_list_head(fp, &property->packages); + fprintf(fp,"\n"); + fprintf(fp," }\n"); + return sizeof(*property); + } else + return dump_raw(fp, property, "unknown", length, offset); +} + +static size_t +dump_properties(FILE *fp, struct razor_property *properties, size_t length, + size_t offset, struct array *string_pool) +{ + size_t n = 0; + + fprintf(fp, "%05lX properties {\n", (unsigned long)offset); + + while (n < length) { + n += dump_property(fp, properties, length - n, n, string_pool); + properties++; + } + + fprintf(fp, "}\n"); + + return n; +} + +static size_t +dump_entry(FILE *fp, struct razor_entry *entry, size_t length, size_t offset, + struct array *string_pool, int indx) +{ + if (length >= sizeof(*entry)) { + fprintf(fp, " %05lX entry %X ", (unsigned long)offset, indx); + fprintf(fp, "{ name=%06X ", entry->name); + expand_pooled_string(fp, string_pool, entry->name); + fprintf(fp, "\n flags=%02X ", entry->flags); + if (entry->flags == RAZOR_ENTRY_LAST) + fprintf(fp, "(LAST) "); + fprintf(fp, "start=%08X", entry->start); + if (!entry->start) + fprintf(fp, " (NONE)"); + fprintf(fp,"\n packages="); + dump_list_head(fp, &entry->packages); + fprintf(fp,"\n"); + fprintf(fp," }\n"); + return sizeof(*entry); + } else + return dump_raw(fp, entry, "unknown", length, offset); +} + +static size_t +dump_files(FILE *fp, struct razor_entry *entries, size_t length, size_t offset, + struct array *string_pool) +{ + size_t n = 0; + int i = 0; + + fprintf(fp, "%05lX files {\n", (unsigned long)offset); + + while (n < length) { + n += dump_entry(fp, entries, length - n, n, string_pool, i); + i++; + entries++; + } + + fprintf(fp, "}\n"); + + return n; +} + +static size_t +dump_lists(FILE *fp, struct list *lists, char *what, size_t length, + size_t offset) +{ + int i = 0; + size_t n = 0; + + fprintf(fp, "%05lX %s {\n", (unsigned long)offset, what); + + while (n + sizeof(*lists) <= length) { + fprintf(fp, " list %06X ", i); + dump_list_link(fp, lists); + fprintf(fp, "\n"); + n += sizeof(*lists); + lists++; + i++; + } + + if (length - n) + n += dump_raw(fp, lists, "unknown", length - n, offset + n); + + fprintf(fp, "}\n"); + + return n; +} + +RAZOR_EXPORT int +razor_dump_database(FILE *fp, const char *root, const char *filename, + struct razor_error **error) +{ + int i; + char *s, *path, *data; + struct array pool = { 0, }; + struct array string_pool = { 0, }; + struct array file_string_pool = { 0, }; + struct array details_string_pool = { 0, }; + unsigned char *contents; + size_t length, len, n, min_offset; + struct razor_set_header *header; + struct razor_set_section *section, *sections; + struct razor_package *package; + struct razor_property *prop; + struct razor_entry *entry; + struct list *list; + + if (!filename) + filename = "system.rzdb"; + + s = razor_concat(razor_get_database_path(), "/", filename, NULL); + path = razor_path_add_root(s, root); + free(s); + contents = razor_file_get_contents(path, &length, 0, error); + free(path); + + if (!contents) + return -1; + + n = 0; + + header = (void *)contents; + + if (length - n) + n += dump_header(fp, header, length - n, n); + + min_offset = length; + sections = (void *)(contents + n); + for (i = 0; i < header->num_sections; i++) { + if (n == length) + break; + section = (void *)(contents + n); + if (section->offset < min_offset) + min_offset = section->offset; + n += dump_section(fp, section, length - n, n, i); + } + + if (length - n) { + pool.data = (char *)(contents + n); + pool.size = min_offset - n; + n += dump_pool(fp, pool.data, "pool", pool.size, n); + } + + if ((length - n) && PADDING(n, 4)) + n += dump_raw(fp, contents + n, "padding", PADDING(n, 4), n); + + for (i = 0; length - n && i < header->num_sections; i++) { + if (sections[i].name < pool.size && + ((char *)pool.data)[pool.size - 1] == '\0') + s = pool.data + sections[i].name; + else + continue; + + data = (char *)(contents + sections[i].offset); + + if (!strcmp(s, "string_pool")) { + string_pool.data = data; + string_pool.size = sections[i].size; + } else if (!strcmp(s, "file_string_pool")) { + file_string_pool.data = data; + file_string_pool.size = sections[i].size; + } else if (!strcmp(s, "details_string_pool")) { + details_string_pool.data = data; + details_string_pool.size = sections[i].size; + } + } + + for (i = 0; i < header->num_sections; i++) { + if (n == length) + break; + section = sections + i; + if (section->offset != n) + continue; + len = section->size; + if (len > length - n) + len = length - n; + + if (section->name < pool.size && + ((char *)pool.data)[pool.size - 1] == '\0') + s = pool.data + section->name; + else + s = "unknown"; + + if (!strcmp(s, "string_pool") || + !strcmp(s, "file_string_pool") || + !strcmp(s, "details_string_pool")) + n += dump_pool(fp, (char *)(contents + n), s, len, n); + else if (!strcmp(s, "packages")) { + package = (void *)(contents + n); + n += dump_packages(fp, package, len, n, &string_pool); + } else if (!strcmp(s, "properties")) { + prop = (void *)(contents + n); + n += dump_properties(fp, prop, len, n, &string_pool); + } else if (!strcmp(s, "files")) { + entry = (void *)(contents + n); + n += dump_files(fp, entry, len, n, &file_string_pool); + } else if (!strcmp(s, "package_pool") || + !strcmp(s, "property_pool") || + !strcmp(s, "prefix_pool") || + !strcmp(s, "file_pool")) { + list = (void *)(contents + n); + n += dump_lists(fp, list, s, len, n); + } else + n += dump_raw(fp, contents + n, s, len, n); + + if ((length - n) && PADDING(n, 4)) + n += dump_raw(fp, contents + n, "padding", + PADDING(n, 4), n); + } + + if (length - n) + n += dump_raw(fp, contents + n, "unknown", length - n, n); + + fprintf(fp, "%05lX EOF\n", (unsigned long)n); + + razor_file_free_contents(contents, length); + + return 0; +}