librazor/dump.c
changeset 460 b8638c3c7eee
child 475 008c75a5e08d
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/librazor/dump.c	Wed Oct 22 12:09:47 2014 +0100
     1.3 @@ -0,0 +1,488 @@
     1.4 +/*
     1.5 + * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
     1.6 + *
     1.7 + * This program is free software; you can redistribute it and/or modify
     1.8 + * it under the terms of the GNU General Public License as published by
     1.9 + * the Free Software Foundation; either version 2 of the License, or
    1.10 + * (at your option) any later version.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License along
    1.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
    1.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    1.20 + */
    1.21 +
    1.22 +#include "config.h"
    1.23 +
    1.24 +#include <stdlib.h>
    1.25 +#include <stdio.h>
    1.26 +#include <string.h>
    1.27 +
    1.28 +#include "razor.h"
    1.29 +#include "razor-internal.h"
    1.30 +
    1.31 +static size_t
    1.32 +dump_raw(FILE *fp, void *raw, char *what, size_t length, size_t offset)
    1.33 +{
    1.34 +	size_t i, n = 0;
    1.35 +	unsigned char *bytes = raw;
    1.36 +
    1.37 +	while (length) {
    1.38 +		fprintf(fp, "%05lX %s", (unsigned long)(offset + n), what);
    1.39 +		for (i = 0; (i < 16) && (length > 0);) {
    1.40 +			if (length >= 4) {
    1.41 +				fprintf(fp, " %08X", *(uint32_t *)bytes);
    1.42 +				bytes += 4;
    1.43 +				n += 4;
    1.44 +				length -= 4;
    1.45 +				i += 4;
    1.46 +			} else if (length >= 2) {
    1.47 +				fprintf(fp, " %04X", *(unsigned short *)bytes);
    1.48 +				bytes += 2;
    1.49 +				n += 2;
    1.50 +				length -= 2;
    1.51 +				i += 2;
    1.52 +			} else {
    1.53 +				fprintf(fp, " %02X", *bytes);
    1.54 +				bytes++;
    1.55 +				n++;
    1.56 +				length--;
    1.57 +				i++;
    1.58 +			}
    1.59 +		}
    1.60 +		fprintf(fp, "\n");
    1.61 +	}
    1.62 +
    1.63 +	return n;
    1.64 +}
    1.65 +
    1.66 +static size_t
    1.67 +dump_string(FILE *fp, char *pool, size_t length, size_t offset)
    1.68 +{
    1.69 +	size_t n = 0;
    1.70 +	unsigned char c;
    1.71 +
    1.72 +	fprintf(fp, "\"");
    1.73 +	while (offset + n < length) {
    1.74 +		c = pool[offset + n++];
    1.75 +		if (c == '\0') {
    1.76 +			fprintf(fp, "\\0");
    1.77 +			break;
    1.78 +		}
    1.79 +		else if (c == '\\' || c == '"')
    1.80 +			fprintf(fp, "\\%c", c);
    1.81 +		else if (c >= ' ' && c <= '~')
    1.82 +			fprintf(fp, "%c", c);
    1.83 +		else
    1.84 +			fprintf(fp, "\\x%02X", c);
    1.85 +	}
    1.86 +	fprintf(fp, "\"");
    1.87 +
    1.88 +	return n;
    1.89 +}
    1.90 +
    1.91 +static size_t
    1.92 +dump_pool(FILE *fp, char *pool, char *what, size_t length, size_t offset)
    1.93 +{
    1.94 +	size_t n = 0;
    1.95 +
    1.96 +	fprintf(fp, "%05lX %s {\n", (unsigned long)offset, what);
    1.97 +
    1.98 +	while (n < length) {
    1.99 +		fprintf(fp, "    %08X ", (uint32_t)n);
   1.100 +		n += dump_string(fp, pool, length, n);
   1.101 +		fprintf(fp, "\n");
   1.102 +	}
   1.103 +
   1.104 +	fprintf(fp, "}\n");
   1.105 +
   1.106 +	return n;
   1.107 +}
   1.108 +
   1.109 +static size_t
   1.110 +dump_header(FILE *fp, struct razor_set_header *header, size_t length,
   1.111 +	    size_t offset)
   1.112 +{
   1.113 +	if (length >= sizeof(*header)) {
   1.114 +		fprintf(fp, "%05lX header ", (unsigned long)offset);
   1.115 +		fprintf(fp, "{ magic=%08X version=%08X num_sections=%08X }\n",
   1.116 +			header->magic, header->version, header->num_sections);
   1.117 +		return sizeof(*header);
   1.118 +	} else
   1.119 +		return dump_raw(fp, header, "unknown", length, offset);
   1.120 +}
   1.121 +
   1.122 +static size_t
   1.123 +dump_section(FILE *fp, struct razor_set_section *section, size_t length,
   1.124 +	     size_t offset, int indx)
   1.125 +{
   1.126 +	if (length >= sizeof(*section)) {
   1.127 +		fprintf(fp, "%05lX section %X ", (unsigned long)offset, indx);
   1.128 +		fprintf(fp, "{ name=%08X offset=%08X size=%08X }\n",
   1.129 +			section->name, section->offset, section->size);
   1.130 +		return sizeof(*section);
   1.131 +	} else
   1.132 +		return dump_raw(fp, section, "unknown", length, offset);
   1.133 +}
   1.134 +
   1.135 +static void
   1.136 +dump_list_head(FILE *fp, struct list_head *head)
   1.137 +{
   1.138 +	fprintf(fp, "{ list_ptr=%06X flags=%02X ",
   1.139 +		head->list_ptr, head->flags);
   1.140 +	if (head->flags == RAZOR_EMPTY_LIST)
   1.141 +		fprintf(fp, "(EMPTY_LIST) ");
   1.142 +	else if (head->flags == RAZOR_IMMEDIATE)
   1.143 +		fprintf(fp, "(IMMEDIATE) ");
   1.144 +	fprintf(fp,"}");
   1.145 +}
   1.146 +
   1.147 +static void
   1.148 +dump_list_link(FILE *fp, struct list *list)
   1.149 +{
   1.150 +	fprintf(fp, "{ data=%06X flags=%02X ",
   1.151 +		list->data, list->flags);
   1.152 +	if (list->flags == RAZOR_ENTRY_LAST)
   1.153 +		fprintf(fp, "(ENTRY_LAST) ");
   1.154 +	else if (list->flags == RAZOR_ENTRY_FIRST)
   1.155 +		fprintf(fp, "(ENTRY_FIRST) ");
   1.156 +	fprintf(fp,"}");
   1.157 +}
   1.158 +
   1.159 +static void
   1.160 +expand_pooled_string(FILE *fp, struct array *pool, uint32_t str)
   1.161 +{
   1.162 +	if (pool->data && str < pool->size) {
   1.163 +		fprintf(fp, "(");
   1.164 +		dump_string(fp, pool->data, pool->size, str);
   1.165 +		fprintf(fp, ") ");
   1.166 +	}
   1.167 +}
   1.168 +
   1.169 +static size_t
   1.170 +dump_package(FILE *fp, struct razor_package *package, size_t length,
   1.171 +	     size_t offset, struct array *string_pool, int indx)
   1.172 +{
   1.173 +	if (length >= sizeof(*package)) {
   1.174 +		fprintf(fp, "    %05lX package %X ", (unsigned long)offset,
   1.175 +			indx);
   1.176 +		fprintf(fp, "{ name=%06X ", package->name);
   1.177 +		expand_pooled_string(fp, string_pool, package->name);
   1.178 +		fprintf(fp, "flags=%02X\n            version=%08X ",
   1.179 +			package->flags, package->version);
   1.180 +		expand_pooled_string(fp, string_pool, package->version);
   1.181 +		fprintf(fp, "arch=%08X ", package->arch);
   1.182 +		expand_pooled_string(fp, string_pool, package->arch);
   1.183 +		fprintf(fp, "\n            "
   1.184 +			"summary=%08X description=%08X url=%08X license=%08X\n",
   1.185 +			package->summary, package->description,
   1.186 +			package->url, package->license);
   1.187 +		fprintf(fp,"            properties=");
   1.188 +		dump_list_head(fp, &package->properties);
   1.189 +		fprintf(fp,"\n");
   1.190 +		fprintf(fp,"            files=");
   1.191 +		dump_list_head(fp, &package->files);
   1.192 +		fprintf(fp,"\n");
   1.193 +		fprintf(fp,"            install_prefixes=");
   1.194 +		dump_list_head(fp, &package->install_prefixes);
   1.195 +		fprintf(fp,"\n");
   1.196 +		fprintf(fp,"            preun={ program=%08X body=%08X }\n",
   1.197 +		        package->preun.program, package->preun.body);
   1.198 +		fprintf(fp,"            postun={ program=%08X body=%08X }\n",
   1.199 +		        package->postun.program, package->postun.body);
   1.200 +		fprintf(fp,"    }\n");
   1.201 +		return sizeof(*package);
   1.202 +	} else
   1.203 +		return dump_raw(fp, package, "unknown", length, offset);
   1.204 +}
   1.205 +
   1.206 +static size_t
   1.207 +dump_packages(FILE *fp, struct razor_package *packages, size_t length,
   1.208 +	      size_t offset, struct array *string_pool)
   1.209 +{
   1.210 +	size_t n = 0;
   1.211 +	int i = 0;
   1.212 +
   1.213 +	fprintf(fp, "%05lX packages {\n", (unsigned long)offset);
   1.214 +
   1.215 +	while (n < length) {
   1.216 +		n += dump_package(fp, packages, length - n, n, string_pool, i);
   1.217 +		packages++;
   1.218 +		i++;
   1.219 +	}
   1.220 +
   1.221 +	fprintf(fp, "}\n");
   1.222 +
   1.223 +	return n;
   1.224 +}
   1.225 +
   1.226 +static size_t
   1.227 +dump_property(FILE *fp, struct razor_property *property, size_t length,
   1.228 +	      size_t offset, struct array *string_pool)
   1.229 +{
   1.230 +	if (length >= sizeof(*property)) {
   1.231 +		fprintf(fp, "    %05lX property ", (unsigned long)offset);
   1.232 +		fprintf(fp, "{ name=%08X ", property->name);
   1.233 +		expand_pooled_string(fp, string_pool, property->name);
   1.234 +		fprintf(fp, "\n            flags=%08X (", property->flags);
   1.235 +		if (property->flags & RAZOR_PROPERTY_LESS)
   1.236 +			fprintf(fp, "<");
   1.237 +		if (property->flags & RAZOR_PROPERTY_GREATER)
   1.238 +			fprintf(fp, ">");
   1.239 +		if (property->flags & RAZOR_PROPERTY_EQUAL)
   1.240 +			fprintf(fp, "=");
   1.241 +		switch (property->flags & RAZOR_PROPERTY_TYPE_MASK) {
   1.242 +		case RAZOR_PROPERTY_REQUIRES:
   1.243 +			fprintf(fp, " requires");
   1.244 +			break;
   1.245 +		case RAZOR_PROPERTY_PROVIDES:
   1.246 +			fprintf(fp, " provides");
   1.247 +			break;
   1.248 +		case RAZOR_PROPERTY_CONFLICTS:
   1.249 +			fprintf(fp, " conflicts");
   1.250 +			break;
   1.251 +		case RAZOR_PROPERTY_OBSOLETES:
   1.252 +			fprintf(fp, " obsoletes");
   1.253 +			break;
   1.254 +		}
   1.255 +		if (property->flags & RAZOR_PROPERTY_PRE)
   1.256 +			fprintf(fp, " pre");
   1.257 +		if (property->flags & RAZOR_PROPERTY_POST)
   1.258 +			fprintf(fp, " post");
   1.259 +		if (property->flags & RAZOR_PROPERTY_PREUN)
   1.260 +			fprintf(fp, " preun");
   1.261 +		if (property->flags & RAZOR_PROPERTY_POSTUN)
   1.262 +			fprintf(fp, " postun");
   1.263 +		fprintf(fp, ") version=%08X ", property->version);
   1.264 +		expand_pooled_string(fp, string_pool, property->version);
   1.265 +		fprintf(fp,"\n            packages=");
   1.266 +		dump_list_head(fp, &property->packages);
   1.267 +		fprintf(fp,"\n");
   1.268 +		fprintf(fp,"    }\n");
   1.269 +		return sizeof(*property);
   1.270 +	} else
   1.271 +		return dump_raw(fp, property, "unknown", length, offset);
   1.272 +}
   1.273 +
   1.274 +static size_t
   1.275 +dump_properties(FILE *fp, struct razor_property *properties, size_t length,
   1.276 +		size_t offset, struct array *string_pool)
   1.277 +{
   1.278 +	size_t n = 0;
   1.279 +
   1.280 +	fprintf(fp, "%05lX properties {\n", (unsigned long)offset);
   1.281 +
   1.282 +	while (n < length) {
   1.283 +		n += dump_property(fp, properties, length - n, n, string_pool);
   1.284 +		properties++;
   1.285 +	}
   1.286 +
   1.287 +	fprintf(fp, "}\n");
   1.288 +
   1.289 +	return n;
   1.290 +}
   1.291 +
   1.292 +static size_t
   1.293 +dump_entry(FILE *fp, struct razor_entry *entry, size_t length, size_t offset,
   1.294 +	   struct array *string_pool, int indx)
   1.295 +{
   1.296 +	if (length >= sizeof(*entry)) {
   1.297 +		fprintf(fp, "    %05lX entry %X ", (unsigned long)offset, indx);
   1.298 +		fprintf(fp, "{ name=%06X ", entry->name);
   1.299 +		expand_pooled_string(fp, string_pool, entry->name);
   1.300 +		fprintf(fp, "\n            flags=%02X ", entry->flags);
   1.301 +		if (entry->flags == RAZOR_ENTRY_LAST)
   1.302 +			fprintf(fp, "(LAST) ");
   1.303 +		fprintf(fp, "start=%08X", entry->start);
   1.304 +		if (!entry->start)
   1.305 +			fprintf(fp, " (NONE)");
   1.306 +		fprintf(fp,"\n            packages=");
   1.307 +		dump_list_head(fp, &entry->packages);
   1.308 +		fprintf(fp,"\n");
   1.309 +		fprintf(fp,"    }\n");
   1.310 +		return sizeof(*entry);
   1.311 +	} else
   1.312 +		return dump_raw(fp, entry, "unknown", length, offset);
   1.313 +}
   1.314 +
   1.315 +static size_t
   1.316 +dump_files(FILE *fp, struct razor_entry *entries, size_t length, size_t offset,
   1.317 +	   struct array *string_pool)
   1.318 +{
   1.319 +	size_t n = 0;
   1.320 +	int i = 0;
   1.321 +
   1.322 +	fprintf(fp, "%05lX files {\n", (unsigned long)offset);
   1.323 +
   1.324 +	while (n < length) {
   1.325 +		n += dump_entry(fp, entries, length - n, n, string_pool, i);
   1.326 +		i++;
   1.327 +		entries++;
   1.328 +	}
   1.329 +
   1.330 +	fprintf(fp, "}\n");
   1.331 +
   1.332 +	return n;
   1.333 +}
   1.334 +
   1.335 +static size_t
   1.336 +dump_lists(FILE *fp, struct list *lists, char *what, size_t length,
   1.337 +	   size_t offset)
   1.338 +{
   1.339 +	int i = 0;
   1.340 +	size_t n = 0;
   1.341 +
   1.342 +	fprintf(fp, "%05lX %s {\n", (unsigned long)offset, what);
   1.343 +
   1.344 +	while (n + sizeof(*lists) <= length) {
   1.345 +		fprintf(fp, "    list %06X ", i);
   1.346 +		dump_list_link(fp, lists);
   1.347 +		fprintf(fp, "\n");
   1.348 +		n += sizeof(*lists);
   1.349 +		lists++;
   1.350 +		i++;
   1.351 +	}
   1.352 +
   1.353 +	if (length - n)
   1.354 +		n += dump_raw(fp, lists, "unknown", length - n, offset + n);
   1.355 +
   1.356 +	fprintf(fp, "}\n");
   1.357 +
   1.358 +	return n;
   1.359 +}
   1.360 +
   1.361 +RAZOR_EXPORT int
   1.362 +razor_dump_database(FILE *fp, const char *root, const char *filename,
   1.363 +		    struct razor_error **error)
   1.364 +{
   1.365 +	int i;
   1.366 +	char *s, *path, *data;
   1.367 +	struct array pool = { 0, };
   1.368 +	struct array string_pool = { 0, };
   1.369 +	struct array file_string_pool = { 0, };
   1.370 +	struct array details_string_pool = { 0, };
   1.371 +	unsigned char *contents;
   1.372 +	size_t length, len, n, min_offset;
   1.373 +	struct razor_set_header *header;
   1.374 +	struct razor_set_section *section, *sections;
   1.375 +	struct razor_package *package;
   1.376 +	struct razor_property *prop;
   1.377 +	struct razor_entry *entry;
   1.378 +	struct list *list;
   1.379 +
   1.380 +	if (!filename)
   1.381 +		filename = "system.rzdb";
   1.382 +
   1.383 +	s = razor_concat(razor_get_database_path(), "/", filename, NULL);
   1.384 +	path = razor_path_add_root(s, root);
   1.385 +	free(s);
   1.386 +	contents = razor_file_get_contents(path, &length, 0, error);
   1.387 +	free(path);
   1.388 +
   1.389 +	if (!contents)
   1.390 +		return -1;
   1.391 +
   1.392 +	n = 0;
   1.393 +
   1.394 +	header = (void *)contents;
   1.395 +
   1.396 +	if (length - n)
   1.397 +		n += dump_header(fp, header, length - n, n);
   1.398 +
   1.399 +	min_offset = length;
   1.400 +	sections = (void *)(contents + n);
   1.401 +	for (i = 0; i < header->num_sections; i++) {
   1.402 +		if (n == length)
   1.403 +			break;
   1.404 +		section = (void *)(contents + n);
   1.405 +		if (section->offset < min_offset)
   1.406 +			min_offset = section->offset;
   1.407 +		n += dump_section(fp, section, length - n, n, i);
   1.408 +	}
   1.409 +
   1.410 +	if (length - n) {
   1.411 +		pool.data = (char *)(contents + n);
   1.412 +		pool.size = min_offset - n;
   1.413 +		n += dump_pool(fp, pool.data, "pool", pool.size, n);
   1.414 +	}
   1.415 +
   1.416 +	if ((length - n) && PADDING(n, 4))
   1.417 +		n += dump_raw(fp, contents + n, "padding", PADDING(n, 4), n);
   1.418 +
   1.419 +	for (i = 0; length - n && i < header->num_sections; i++) {
   1.420 +		if (sections[i].name < pool.size &&
   1.421 +		    ((char *)pool.data)[pool.size - 1] == '\0')
   1.422 +			s = pool.data + sections[i].name;
   1.423 +		else
   1.424 +			continue;
   1.425 +
   1.426 +		data = (char *)(contents + sections[i].offset);
   1.427 +
   1.428 +		if (!strcmp(s, "string_pool")) {
   1.429 +			string_pool.data = data;
   1.430 +			string_pool.size = sections[i].size;
   1.431 +		} else if (!strcmp(s, "file_string_pool")) {
   1.432 +			file_string_pool.data = data;
   1.433 +			file_string_pool.size = sections[i].size;
   1.434 +		} else if (!strcmp(s, "details_string_pool")) {
   1.435 +			details_string_pool.data = data;
   1.436 +			details_string_pool.size = sections[i].size;
   1.437 +		}
   1.438 +	}
   1.439 +
   1.440 +	for (i = 0; i < header->num_sections; i++) {
   1.441 +		if (n == length)
   1.442 +			break;
   1.443 +		section = sections + i;
   1.444 +		if (section->offset != n)
   1.445 +			continue;
   1.446 +		len = section->size;
   1.447 +		if (len > length - n)
   1.448 +			len = length - n;
   1.449 +
   1.450 +		if (section->name < pool.size &&
   1.451 +		    ((char *)pool.data)[pool.size - 1] == '\0')
   1.452 +			s = pool.data + section->name;
   1.453 +		else
   1.454 +			s = "unknown";
   1.455 +
   1.456 +		if (!strcmp(s, "string_pool") ||
   1.457 +		    !strcmp(s, "file_string_pool") ||
   1.458 +		    !strcmp(s, "details_string_pool"))
   1.459 +			n += dump_pool(fp, (char *)(contents + n), s, len, n);
   1.460 +		else if (!strcmp(s, "packages")) {
   1.461 +			package = (void *)(contents + n);
   1.462 +			n += dump_packages(fp, package, len, n, &string_pool);
   1.463 +		} else if (!strcmp(s, "properties")) {
   1.464 +			prop = (void *)(contents + n);
   1.465 +			n += dump_properties(fp, prop, len, n, &string_pool);
   1.466 +		} else if (!strcmp(s, "files")) {
   1.467 +			entry = (void *)(contents + n);
   1.468 +			n += dump_files(fp, entry, len, n, &file_string_pool);
   1.469 +		} else if (!strcmp(s, "package_pool") ||
   1.470 +			   !strcmp(s, "property_pool") ||
   1.471 +			   !strcmp(s, "prefix_pool") ||
   1.472 +			   !strcmp(s, "file_pool")) {
   1.473 +			list = (void *)(contents + n);
   1.474 +			n += dump_lists(fp, list, s, len, n);
   1.475 +		} else
   1.476 +			n += dump_raw(fp, contents + n, s, len, n);
   1.477 +
   1.478 +		if ((length - n) && PADDING(n, 4))
   1.479 +			n += dump_raw(fp, contents + n, "padding",
   1.480 +				      PADDING(n, 4), n);
   1.481 +	}
   1.482 +
   1.483 +	if (length - n)
   1.484 +		n += dump_raw(fp, contents + n, "unknown", length - n, n);
   1.485 +
   1.486 +	fprintf(fp, "%05lX EOF\n", (unsigned long)n);
   1.487 +
   1.488 +	razor_file_free_contents(contents, length);
   1.489 +
   1.490 +	return 0;
   1.491 +}