librazor/dump.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Jun 08 18:02:33 2018 +0100 (2018-06-08)
changeset 500 f98d77376544
parent 457 51a084acef49
permissions -rw-r--r--
Release 0.7
     1 /*
     2  * Copyright (C) 2014, 2016  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License along
    15  * with this program; if not, write to the Free Software Foundation, Inc.,
    16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    17  */
    18 
    19 #include "config.h"
    20 
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include <string.h>
    24 
    25 #include "razor.h"
    26 #include "razor-internal.h"
    27 
    28 static size_t
    29 dump_raw(FILE *fp, void *raw, char *what, size_t length, size_t offset)
    30 {
    31 	size_t i, n = 0;
    32 	unsigned char *bytes = raw;
    33 
    34 	while (length) {
    35 		fprintf(fp, "%05lX %s", (unsigned long)(offset + n), what);
    36 		for (i = 0; (i < 16) && (length > 0);) {
    37 			if (length >= 4) {
    38 				fprintf(fp, " %08X", *(uint32_t *)bytes);
    39 				bytes += 4;
    40 				n += 4;
    41 				length -= 4;
    42 				i += 4;
    43 			} else if (length >= 2) {
    44 				fprintf(fp, " %04X", *(unsigned short *)bytes);
    45 				bytes += 2;
    46 				n += 2;
    47 				length -= 2;
    48 				i += 2;
    49 			} else {
    50 				fprintf(fp, " %02X", *bytes);
    51 				bytes++;
    52 				n++;
    53 				length--;
    54 				i++;
    55 			}
    56 		}
    57 		fprintf(fp, "\n");
    58 	}
    59 
    60 	return n;
    61 }
    62 
    63 static size_t
    64 dump_string(FILE *fp, char *pool, size_t length, size_t offset)
    65 {
    66 	size_t n = 0;
    67 	unsigned char c;
    68 
    69 	fprintf(fp, "\"");
    70 	while (offset + n < length) {
    71 		c = pool[offset + n++];
    72 		if (c == '\0') {
    73 			fprintf(fp, "\\0");
    74 			break;
    75 		}
    76 		else if (c == '\\' || c == '"')
    77 			fprintf(fp, "\\%c", c);
    78 		else if (c >= ' ' && c <= '~')
    79 			fprintf(fp, "%c", c);
    80 		else
    81 			fprintf(fp, "\\x%02X", c);
    82 	}
    83 	fprintf(fp, "\"");
    84 
    85 	return n;
    86 }
    87 
    88 static size_t
    89 dump_pool(FILE *fp, char *pool, char *what, size_t length, size_t offset)
    90 {
    91 	size_t n = 0;
    92 
    93 	fprintf(fp, "%05lX %s {\n", (unsigned long)offset, what);
    94 
    95 	while (n < length) {
    96 		fprintf(fp, "    %08X ", (uint32_t)n);
    97 		n += dump_string(fp, pool, length, n);
    98 		fprintf(fp, "\n");
    99 	}
   100 
   101 	fprintf(fp, "}\n");
   102 
   103 	return n;
   104 }
   105 
   106 static size_t
   107 dump_header(FILE *fp, struct razor_set_header *header, size_t length,
   108 	    size_t offset)
   109 {
   110 	if (length >= sizeof(*header)) {
   111 		fprintf(fp, "%05lX header ", (unsigned long)offset);
   112 		fprintf(fp, "{ magic=%08X version=%08X num_sections=%08X }\n",
   113 			header->magic, header->version, header->num_sections);
   114 		return sizeof(*header);
   115 	} else
   116 		return dump_raw(fp, header, "unknown", length, offset);
   117 }
   118 
   119 static size_t
   120 dump_section(FILE *fp, struct razor_set_section *section, size_t length,
   121 	     size_t offset, int indx)
   122 {
   123 	if (length >= sizeof(*section)) {
   124 		fprintf(fp, "%05lX section %X ", (unsigned long)offset, indx);
   125 		fprintf(fp, "{ name=%08X offset=%08X size=%08X }\n",
   126 			section->name, section->offset, section->size);
   127 		return sizeof(*section);
   128 	} else
   129 		return dump_raw(fp, section, "unknown", length, offset);
   130 }
   131 
   132 static void
   133 dump_list_head(FILE *fp, struct list_head *head)
   134 {
   135 	fprintf(fp, "{ list_ptr=%06X flags=%02X ",
   136 		head->list_ptr, head->flags);
   137 	if (head->flags == RAZOR_EMPTY_LIST)
   138 		fprintf(fp, "(EMPTY_LIST) ");
   139 	else if (head->flags == RAZOR_IMMEDIATE)
   140 		fprintf(fp, "(IMMEDIATE) ");
   141 	fprintf(fp,"}");
   142 }
   143 
   144 static void
   145 dump_list_link(FILE *fp, struct list *list)
   146 {
   147 	fprintf(fp, "{ data=%06X flags=%02X ",
   148 		list->data, list->flags);
   149 	if (list->flags == RAZOR_ENTRY_LAST)
   150 		fprintf(fp, "(ENTRY_LAST) ");
   151 	else if (list->flags == RAZOR_ENTRY_FIRST)
   152 		fprintf(fp, "(ENTRY_FIRST) ");
   153 	fprintf(fp,"}");
   154 }
   155 
   156 static void
   157 expand_pooled_string(FILE *fp, struct array *pool, uint32_t str)
   158 {
   159 	if (pool->data && str < pool->size) {
   160 		fprintf(fp, "(");
   161 		dump_string(fp, pool->data, pool->size, str);
   162 		fprintf(fp, ") ");
   163 	}
   164 }
   165 
   166 static size_t
   167 dump_package(FILE *fp, struct razor_package *package, size_t length,
   168 	     size_t offset, struct array *string_pool, int indx)
   169 {
   170 	if (length >= sizeof(*package)) {
   171 		fprintf(fp, "    %05lX package %X ", (unsigned long)offset,
   172 			indx);
   173 		fprintf(fp, "{ name=%06X ", package->name);
   174 		expand_pooled_string(fp, string_pool, package->name);
   175 		fprintf(fp, "flags=%02X\n            version=%08X ",
   176 			package->flags, package->version);
   177 		expand_pooled_string(fp, string_pool, package->version);
   178 		fprintf(fp, "arch=%08X ", package->arch);
   179 		expand_pooled_string(fp, string_pool, package->arch);
   180 		fprintf(fp, "\n            "
   181 			"summary=%08X description=%08X url=%08X license=%08X\n",
   182 			package->summary, package->description,
   183 			package->url, package->license);
   184 		fprintf(fp,"            properties=");
   185 		dump_list_head(fp, &package->properties);
   186 		fprintf(fp,"\n");
   187 		fprintf(fp,"            files=");
   188 		dump_list_head(fp, &package->files);
   189 		fprintf(fp,"\n");
   190 		fprintf(fp,"            install_prefixes=");
   191 		dump_list_head(fp, &package->install_prefixes);
   192 		fprintf(fp,"\n");
   193 		fprintf(fp,"            preun={ program=%08X body=%08X }\n",
   194 		        package->preun.program, package->preun.body);
   195 		fprintf(fp,"            postun={ program=%08X body=%08X }\n",
   196 		        package->postun.program, package->postun.body);
   197 		fprintf(fp,"    }\n");
   198 		return sizeof(*package);
   199 	} else
   200 		return dump_raw(fp, package, "unknown", length, offset);
   201 }
   202 
   203 static size_t
   204 dump_packages(FILE *fp, struct razor_package *packages, size_t length,
   205 	      size_t offset, struct array *string_pool)
   206 {
   207 	size_t n = 0;
   208 	int i = 0;
   209 
   210 	fprintf(fp, "%05lX packages {\n", (unsigned long)offset);
   211 
   212 	while (n < length) {
   213 		n += dump_package(fp, packages, length - n, n, string_pool, i);
   214 		packages++;
   215 		i++;
   216 	}
   217 
   218 	fprintf(fp, "}\n");
   219 
   220 	return n;
   221 }
   222 
   223 static size_t
   224 dump_property(FILE *fp, struct razor_property *property, size_t length,
   225 	      size_t offset, struct array *string_pool)
   226 {
   227 	if (length >= sizeof(*property)) {
   228 		fprintf(fp, "    %05lX property ", (unsigned long)offset);
   229 		fprintf(fp, "{ name=%08X ", property->name);
   230 		expand_pooled_string(fp, string_pool, property->name);
   231 		fprintf(fp, "\n            flags=%08X (", property->flags);
   232 		if (property->flags & RAZOR_PROPERTY_LESS)
   233 			fprintf(fp, "<");
   234 		if (property->flags & RAZOR_PROPERTY_GREATER)
   235 			fprintf(fp, ">");
   236 		if (property->flags & RAZOR_PROPERTY_EQUAL)
   237 			fprintf(fp, "=");
   238 		switch (property->flags & RAZOR_PROPERTY_TYPE_MASK) {
   239 		case RAZOR_PROPERTY_REQUIRES:
   240 			fprintf(fp, " requires");
   241 			break;
   242 		case RAZOR_PROPERTY_PROVIDES:
   243 			fprintf(fp, " provides");
   244 			break;
   245 		case RAZOR_PROPERTY_CONFLICTS:
   246 			fprintf(fp, " conflicts");
   247 			break;
   248 		case RAZOR_PROPERTY_OBSOLETES:
   249 			fprintf(fp, " obsoletes");
   250 			break;
   251 		}
   252 		if (property->flags & RAZOR_PROPERTY_PRE)
   253 			fprintf(fp, " pre");
   254 		if (property->flags & RAZOR_PROPERTY_POST)
   255 			fprintf(fp, " post");
   256 		if (property->flags & RAZOR_PROPERTY_PREUN)
   257 			fprintf(fp, " preun");
   258 		if (property->flags & RAZOR_PROPERTY_POSTUN)
   259 			fprintf(fp, " postun");
   260 		fprintf(fp, ") version=%08X ", property->version);
   261 		expand_pooled_string(fp, string_pool, property->version);
   262 		fprintf(fp,"\n            packages=");
   263 		dump_list_head(fp, &property->packages);
   264 		fprintf(fp,"\n");
   265 		fprintf(fp,"    }\n");
   266 		return sizeof(*property);
   267 	} else
   268 		return dump_raw(fp, property, "unknown", length, offset);
   269 }
   270 
   271 static size_t
   272 dump_properties(FILE *fp, struct razor_property *properties, size_t length,
   273 		size_t offset, struct array *string_pool)
   274 {
   275 	size_t n = 0;
   276 
   277 	fprintf(fp, "%05lX properties {\n", (unsigned long)offset);
   278 
   279 	while (n < length) {
   280 		n += dump_property(fp, properties, length - n, n, string_pool);
   281 		properties++;
   282 	}
   283 
   284 	fprintf(fp, "}\n");
   285 
   286 	return n;
   287 }
   288 
   289 static size_t
   290 dump_entry(FILE *fp, struct razor_entry *entry, size_t length, size_t offset,
   291 	   struct array *string_pool, int indx)
   292 {
   293 	if (length >= sizeof(*entry)) {
   294 		fprintf(fp, "    %05lX entry %X ", (unsigned long)offset, indx);
   295 		fprintf(fp, "{ name=%06X ", entry->name);
   296 		expand_pooled_string(fp, string_pool, entry->name);
   297 		fprintf(fp, "\n            flags=%02X ", entry->flags);
   298 		if (entry->flags == RAZOR_ENTRY_LAST)
   299 			fprintf(fp, "(LAST) ");
   300 		fprintf(fp, "start=%08X", entry->start);
   301 		if (!entry->start)
   302 			fprintf(fp, " (NONE)");
   303 		fprintf(fp,"\n            packages=");
   304 		dump_list_head(fp, &entry->packages);
   305 		fprintf(fp,"\n");
   306 		fprintf(fp,"    }\n");
   307 		return sizeof(*entry);
   308 	} else
   309 		return dump_raw(fp, entry, "unknown", length, offset);
   310 }
   311 
   312 static size_t
   313 dump_files(FILE *fp, struct razor_entry *entries, size_t length, size_t offset,
   314 	   struct array *string_pool)
   315 {
   316 	size_t n = 0;
   317 	int i = 0;
   318 
   319 	fprintf(fp, "%05lX files {\n", (unsigned long)offset);
   320 
   321 	while (n < length) {
   322 		n += dump_entry(fp, entries, length - n, n, string_pool, i);
   323 		i++;
   324 		entries++;
   325 	}
   326 
   327 	fprintf(fp, "}\n");
   328 
   329 	return n;
   330 }
   331 
   332 static size_t
   333 dump_lists(FILE *fp, struct list *lists, char *what, size_t length,
   334 	   size_t offset)
   335 {
   336 	int i = 0;
   337 	size_t n = 0;
   338 
   339 	fprintf(fp, "%05lX %s {\n", (unsigned long)offset, what);
   340 
   341 	while (n + sizeof(*lists) <= length) {
   342 		fprintf(fp, "    list %06X ", i);
   343 		dump_list_link(fp, lists);
   344 		fprintf(fp, "\n");
   345 		n += sizeof(*lists);
   346 		lists++;
   347 		i++;
   348 	}
   349 
   350 	if (length - n)
   351 		n += dump_raw(fp, lists, "unknown", length - n, offset + n);
   352 
   353 	fprintf(fp, "}\n");
   354 
   355 	return n;
   356 }
   357 
   358 RAZOR_EXPORT int
   359 razor_dump_database(FILE *fp, const char *root_uri, const char *filename,
   360 		    struct razor_error **error)
   361 {
   362 	int i;
   363 	char *s, *uri, *data;
   364 	struct array pool = { 0, };
   365 	struct array string_pool = { 0, };
   366 	struct array file_string_pool = { 0, };
   367 	struct array details_string_pool = { 0, };
   368 	unsigned char *contents;
   369 	size_t length, len, n, min_offset;
   370 	struct razor_set_header *header;
   371 	struct razor_set_section *section, *sections;
   372 	struct razor_package *package;
   373 	struct razor_property *prop;
   374 	struct razor_entry *entry;
   375 	struct list *list;
   376 
   377 	if (!filename)
   378 		filename = "system.rzdb";
   379 
   380 	uri = razor_resolve_database_file(root_uri, filename, error);
   381 
   382 	if (!uri)
   383 		return -1;
   384 
   385 	contents = razor_uri_get_contents(uri, &length, 0, error);
   386 
   387 	free(uri);
   388 
   389 	if (!contents)
   390 		return -1;
   391 
   392 	n = 0;
   393 
   394 	header = (void *)contents;
   395 
   396 	if (length - n)
   397 		n += dump_header(fp, header, length - n, n);
   398 
   399 	min_offset = length;
   400 	sections = (void *)(contents + n);
   401 	for (i = 0; i < header->num_sections; i++) {
   402 		if (n == length)
   403 			break;
   404 		section = (void *)(contents + n);
   405 		if (section->offset < min_offset)
   406 			min_offset = section->offset;
   407 		n += dump_section(fp, section, length - n, n, i);
   408 	}
   409 
   410 	if (length - n) {
   411 		pool.data = (char *)(contents + n);
   412 		pool.size = min_offset - n;
   413 		n += dump_pool(fp, pool.data, "pool", pool.size, n);
   414 	}
   415 
   416 	if ((length - n) && PADDING(n, 4))
   417 		n += dump_raw(fp, contents + n, "padding", PADDING(n, 4), n);
   418 
   419 	for (i = 0; length - n && i < header->num_sections; i++) {
   420 		if (sections[i].name < pool.size &&
   421 		    ((char *)pool.data)[pool.size - 1] == '\0')
   422 			s = pool.data + sections[i].name;
   423 		else
   424 			continue;
   425 
   426 		data = (char *)(contents + sections[i].offset);
   427 
   428 		if (!strcmp(s, "string_pool")) {
   429 			string_pool.data = data;
   430 			string_pool.size = sections[i].size;
   431 		} else if (!strcmp(s, "file_string_pool")) {
   432 			file_string_pool.data = data;
   433 			file_string_pool.size = sections[i].size;
   434 		} else if (!strcmp(s, "details_string_pool")) {
   435 			details_string_pool.data = data;
   436 			details_string_pool.size = sections[i].size;
   437 		}
   438 	}
   439 
   440 	for (i = 0; i < header->num_sections; i++) {
   441 		if (n == length)
   442 			break;
   443 		section = sections + i;
   444 		if (section->offset != n)
   445 			continue;
   446 		len = section->size;
   447 		if (len > length - n)
   448 			len = length - n;
   449 
   450 		if (section->name < pool.size &&
   451 		    ((char *)pool.data)[pool.size - 1] == '\0')
   452 			s = pool.data + section->name;
   453 		else
   454 			s = "unknown";
   455 
   456 		if (!strcmp(s, "string_pool") ||
   457 		    !strcmp(s, "file_string_pool") ||
   458 		    !strcmp(s, "details_string_pool"))
   459 			n += dump_pool(fp, (char *)(contents + n), s, len, n);
   460 		else if (!strcmp(s, "packages")) {
   461 			package = (void *)(contents + n);
   462 			n += dump_packages(fp, package, len, n, &string_pool);
   463 		} else if (!strcmp(s, "properties")) {
   464 			prop = (void *)(contents + n);
   465 			n += dump_properties(fp, prop, len, n, &string_pool);
   466 		} else if (!strcmp(s, "files")) {
   467 			entry = (void *)(contents + n);
   468 			n += dump_files(fp, entry, len, n, &file_string_pool);
   469 		} else if (!strcmp(s, "package_pool") ||
   470 			   !strcmp(s, "property_pool") ||
   471 			   !strcmp(s, "prefix_pool") ||
   472 			   !strcmp(s, "file_pool")) {
   473 			list = (void *)(contents + n);
   474 			n += dump_lists(fp, list, s, len, n);
   475 		} else
   476 			n += dump_raw(fp, contents + n, s, len, n);
   477 
   478 		if ((length - n) && PADDING(n, 4))
   479 			n += dump_raw(fp, contents + n, "padding",
   480 				      PADDING(n, 4), n);
   481 	}
   482 
   483 	if (length - n)
   484 		n += dump_raw(fp, contents + n, "unknown", length - n, n);
   485 
   486 	fprintf(fp, "%05lX EOF\n", (unsigned long)n);
   487 
   488 	razor_uri_free_contents(contents, length);
   489 
   490 	return 0;
   491 }