librazor/importer.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Oct 04 18:12:58 2014 +0100 (2014-10-04)
changeset 454 56ff755c268c
parent 438 fab0b8a61dcb
child 458 3f841a46eab5
permissions -rw-r--r--
Only export symbols starting with razor_ in dynamic library.

Apart from being good practice to avoid clashes with higher-level
libraries and the application, this also fixes an obscure bug: The
gnulib library is used both by librazor (the dynamic library) and
by razor (the executable). In doing so, we want to have two separate
copies of the library despite the code duplication this involves.
Without the explicit limit to export only razor_ symbols, the razor
executable under mingw64 was picking up the getopt_long function
from librazor and the optind variable from libgnu which meant that
it did not see optind changing. Hiding librazor's copy of getopt
causes the linker to find libgnu's copy and everything works.

Note that under mingw librazor-#.dll still contains undocumented
(private) razor_ symbols but these will do no harm as long as nobody
tries to use them.
krh@248
     1
/*
krh@248
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
krh@248
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@369
     4
 * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
krh@248
     5
 *
krh@248
     6
 * This program is free software; you can redistribute it and/or modify
krh@248
     7
 * it under the terms of the GNU General Public License as published by
krh@248
     8
 * the Free Software Foundation; either version 2 of the License, or
krh@248
     9
 * (at your option) any later version.
krh@248
    10
 *
krh@248
    11
 * This program is distributed in the hope that it will be useful,
krh@248
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
krh@248
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
krh@248
    14
 * GNU General Public License for more details.
krh@248
    15
 *
krh@248
    16
 * You should have received a copy of the GNU General Public License along
krh@248
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
krh@248
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
krh@248
    19
 */
krh@248
    20
krh@248
    21
#define _GNU_SOURCE
krh@248
    22
ali@438
    23
#include "config.h"
krh@248
    24
#include <string.h>
krh@248
    25
#include "razor-internal.h"
krh@248
    26
#include "razor.h"
krh@248
    27
krh@309
    28
/**
krh@309
    29
 * razor_importer_create:
krh@309
    30
 *
krh@309
    31
 * Create a new %razor_importer.
krh@309
    32
 *
krh@309
    33
 * Returns: the new %razor_importer.
krh@309
    34
 **/
krh@309
    35
RAZOR_EXPORT struct razor_importer *
krh@309
    36
razor_importer_create(void)
krh@309
    37
{
krh@309
    38
	struct razor_importer *importer;
krh@309
    39
krh@309
    40
	importer = zalloc(sizeof *importer);
krh@309
    41
	importer->set = razor_set_create();
krh@309
    42
	hashtable_init(&importer->table, &importer->set->string_pool);
krh@309
    43
	hashtable_init(&importer->details_table,
krh@309
    44
		       &importer->set->details_string_pool);
krh@309
    45
	hashtable_init(&importer->file_table,
krh@309
    46
		       &importer->set->file_string_pool);
krh@309
    47
krh@309
    48
	return importer;
krh@309
    49
}
krh@309
    50
krh@309
    51
/**
krh@309
    52
 * razor_importer_destroy:
krh@309
    53
 * @importer: the %razor_importer
krh@309
    54
 *
krh@309
    55
 * Destroy an importer without creating a %razor_set.  Normally,
krh@309
    56
 * %razor_importer_finish will create a new %razor_set and destroy the
krh@309
    57
 * importer.  If the import must be aborted without creating the set,
krh@309
    58
 * just destroy the import using this function.
krh@309
    59
 **/
krh@309
    60
RAZOR_EXPORT void
krh@309
    61
razor_importer_destroy(struct razor_importer *importer)
krh@309
    62
{
krh@309
    63
	/* FIXME: write this */
krh@309
    64
}
krh@309
    65
krh@309
    66
krh@309
    67
/**
krh@309
    68
 * razor_importer_begin_package:
krh@309
    69
 * @importer: the %razor_importer
krh@309
    70
 * @name: the name of the new package
krh@309
    71
 * @version: the version of the new package
krh@309
    72
 * @arch: the architechture of the new package.
krh@309
    73
 *
krh@309
    74
 * Begin describing a new package to the importer.  This creates a new
krh@309
    75
 * package and sets the %name, %version and %arch.  Subsequent calls
krh@309
    76
 * to %razor_importer_add_details, %razor_importer_add_property and
krh@309
    77
 * %razor_importer_add_file further describe this package and
krh@309
    78
 * %razor_importer_finish_package marks the end of meta data for this
krh@309
    79
 * package.
krh@309
    80
 **/
krh@269
    81
RAZOR_EXPORT void
krh@248
    82
razor_importer_begin_package(struct razor_importer *importer,
krh@248
    83
			     const char *name,
krh@248
    84
			     const char *version,
krh@248
    85
			     const char *arch)
krh@248
    86
{
ali@369
    87
	uint32_t empty;
krh@248
    88
	struct razor_package *p;
krh@248
    89
krh@248
    90
	p = array_add(&importer->set->packages, sizeof *p);
krh@248
    91
	p->name = hashtable_tokenize(&importer->table, name);
krh@248
    92
	p->flags = 0;
krh@248
    93
	p->version = hashtable_tokenize(&importer->table, version);
krh@248
    94
	p->arch = hashtable_tokenize(&importer->table, arch);
krh@248
    95
krh@248
    96
	importer->package = p;
krh@248
    97
	array_init(&importer->properties);
ali@372
    98
	array_init(&importer->install_prefixes);
ali@369
    99
ali@369
   100
	empty = hashtable_tokenize(&importer->details_table, "");
ali@369
   101
	importer->package->preun.program = empty;
ali@369
   102
	importer->package->preun.body = empty;
ali@369
   103
	importer->package->postun.program = empty;
ali@369
   104
	importer->package->postun.body = empty;
krh@248
   105
}
krh@248
   106
krh@309
   107
/**
krh@309
   108
 * razor_importer_finish_package:
krh@309
   109
 * @importer: the %razor_importer
krh@309
   110
 *
krh@309
   111
 * Tells the importer that the current package is complete.
krh@309
   112
 **/
krh@269
   113
RAZOR_EXPORT void
krh@248
   114
razor_importer_finish_package(struct razor_importer *importer)
krh@248
   115
{
krh@248
   116
	list_set_array(&importer->package->properties,
krh@248
   117
		       &importer->set->property_pool,
krh@248
   118
		       &importer->properties,
krh@248
   119
		       1);
krh@248
   120
ali@372
   121
	list_set_array(&importer->package->install_prefixes,
ali@372
   122
		       &importer->set->prefix_pool,
ali@372
   123
		       &importer->install_prefixes,
ali@372
   124
		       0);
ali@372
   125
krh@248
   126
	array_release(&importer->properties);
ali@372
   127
	array_release(&importer->install_prefixes);
krh@248
   128
}
krh@248
   129
krh@309
   130
/**
krh@309
   131
 * razor_importer_add_details:
krh@309
   132
 * @importer: the %razor_importer
krh@309
   133
 * @summary: the package summary
krh@309
   134
 * @description: the package description
krh@309
   135
 * @url: the package url
krh@309
   136
 * @license: the package license
krh@309
   137
 *
krh@309
   138
 * Provide additional information for the current package.
krh@309
   139
 **/
krh@269
   140
RAZOR_EXPORT void
jbowes@258
   141
razor_importer_add_details(struct razor_importer *importer,
jbowes@258
   142
			   const char *summary,
jbowes@258
   143
			   const char *description,
jbowes@258
   144
			   const char *url,
jbowes@258
   145
			   const char *license)
jbowes@258
   146
{
jbowes@258
   147
	importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
jbowes@258
   148
	importer->package->description = hashtable_tokenize(&importer->details_table, description);
jbowes@258
   149
	importer->package->url = hashtable_tokenize(&importer->details_table, url);
jbowes@258
   150
	importer->package->license = hashtable_tokenize(&importer->details_table, license);
jbowes@258
   151
}
jbowes@258
   152
krh@309
   153
/**
ali@369
   154
 * razor_importer_add_script:
ali@369
   155
 * @importer: the %razor_importer
ali@369
   156
 * @script: either %RAZOR_PROPERTY_PREUN or %RAZOR_PROPERTY_POSTUN
ali@369
   157
 * @program: the program to run the script
ali@369
   158
 * @body: the body of the script
ali@369
   159
 *
ali@369
   160
 * Provide a script to use when uninstalling the current package.
ali@369
   161
 **/
ali@369
   162
RAZOR_EXPORT void
ali@369
   163
razor_importer_add_script(struct razor_importer *importer,
ali@369
   164
			  enum razor_property_flags script,
ali@369
   165
			  const char *program,
ali@369
   166
			  const char *body)
ali@369
   167
{
ali@369
   168
	switch (script) {
ali@369
   169
	case RAZOR_PROPERTY_PREUN:
ali@369
   170
		importer->package->preun.program =
ali@369
   171
			hashtable_tokenize(&importer->table, program);
ali@369
   172
		importer->package->preun.body =
ali@369
   173
			hashtable_tokenize(&importer->table, body);
ali@369
   174
		break;
ali@369
   175
	case RAZOR_PROPERTY_POSTUN:
ali@369
   176
		importer->package->postun.program =
ali@369
   177
			hashtable_tokenize(&importer->table, program);
ali@369
   178
		importer->package->postun.body =
ali@369
   179
			hashtable_tokenize(&importer->table, body);
ali@369
   180
		break;
ali@369
   181
	default:
ali@369
   182
		break;
ali@369
   183
	}
ali@369
   184
}
ali@369
   185
ali@369
   186
/**
ali@372
   187
 * razor_importer_add_install_prefixes:
ali@372
   188
 * @importer: the %razor_importer
ali@372
   189
 * @install_prefix: the relocated prefix
ali@372
   190
 *
ali@372
   191
 * Adds a relocated prefix for the current package.
ali@372
   192
 **/
ali@372
   193
RAZOR_EXPORT void
ali@372
   194
razor_importer_add_install_prefix(struct razor_importer *importer,
ali@372
   195
				  const char *install_prefix)
ali@372
   196
{
ali@372
   197
	uint32_t *r;
ali@372
   198
ali@372
   199
	r = array_add(&importer->install_prefixes, sizeof *r);
ali@372
   200
	*r = hashtable_tokenize(&importer->table, install_prefix);
ali@372
   201
}
ali@372
   202
ali@372
   203
/**
krh@309
   204
 * razor_importer_add_property:
krh@309
   205
 * @importer: the %razor_importer
krh@309
   206
 * @name: name of the property
krh@309
   207
 * @flags: property flags
krh@309
   208
 * @version: version of the property or %NULL
krh@309
   209
 *
krh@309
   210
 * Add a property for the current package.  The %flags parameter
krh@309
   211
 * determines the type of the property and optionally the relation to
krh@309
   212
 * the specified version and the availability constraint.  See
krh@309
   213
 * %razor_property_flags for further information about the flag
krh@309
   214
 * parameter.
krh@309
   215
 **/
krh@269
   216
RAZOR_EXPORT void
krh@248
   217
razor_importer_add_property(struct razor_importer *importer,
krh@248
   218
			    const char *name,
krh@248
   219
			    uint32_t flags,
krh@248
   220
			    const char *version)
krh@248
   221
{
krh@248
   222
	struct razor_property *p;
krh@248
   223
	uint32_t *r;
krh@248
   224
krh@248
   225
	p = array_add(&importer->set->properties, sizeof *p);
krh@248
   226
	p->name = hashtable_tokenize(&importer->table, name);
krh@248
   227
	p->flags = flags;
krh@248
   228
	p->version = hashtable_tokenize(&importer->table, version);
krh@248
   229
	list_set_ptr(&p->packages, importer->package -
krh@248
   230
		     (struct razor_package *) importer->set->packages.data);
krh@248
   231
krh@248
   232
	r = array_add(&importer->properties, sizeof *r);
krh@248
   233
	*r = p - (struct razor_property *) importer->set->properties.data;
krh@248
   234
krh@248
   235
	if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
krh@248
   236
	    *name == '/') {
krh@248
   237
		r = array_add(&importer->file_requires, sizeof *r);
krh@248
   238
		*r = p->name;
krh@248
   239
	}
krh@248
   240
}
krh@248
   241
krh@309
   242
/**
krh@309
   243
 * razor_importer_add_file:
krh@309
   244
 * @importer: the %razor_importer
krh@309
   245
 * @name: name of the file
krh@309
   246
 *
krh@309
   247
 * Add a file to the current package.
krh@309
   248
 **/
krh@269
   249
RAZOR_EXPORT void
krh@248
   250
razor_importer_add_file(struct razor_importer *importer, const char *name)
krh@248
   251
{
krh@248
   252
	struct import_entry *e;
krh@248
   253
krh@248
   254
	e = array_add(&importer->files, sizeof *e);
krh@248
   255
krh@248
   256
	e->package = importer->package -
krh@248
   257
		(struct razor_package *) importer->set->packages.data;
krh@248
   258
	e->name = strdup(name);
krh@248
   259
}
krh@248
   260
krh@248
   261
static int
krh@248
   262
compare_packages(const void *p1, const void *p2, void *data)
krh@248
   263
{
krh@248
   264
	const struct razor_package *pkg1 = p1, *pkg2 = p2;
krh@248
   265
	struct razor_set *set = data;
krh@248
   266
	char *pool = set->string_pool.data;
krh@248
   267
krh@248
   268
	/* FIXME: what if the flags are different? */
krh@248
   269
	if (pkg1->name == pkg2->name)
krh@248
   270
		return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
krh@248
   271
	else
krh@248
   272
		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
krh@248
   273
}
krh@248
   274
krh@248
   275
static int
krh@248
   276
compare_properties(const void *p1, const void *p2, void *data)
krh@248
   277
{
krh@248
   278
	const struct razor_property *prop1 = p1, *prop2 = p2;
krh@248
   279
	struct razor_set *set = data;
krh@248
   280
	char *pool = set->string_pool.data;
krh@248
   281
krh@248
   282
	if (prop1->name != prop2->name)
krh@248
   283
		return strcmp(&pool[prop1->name], &pool[prop2->name]);
krh@248
   284
	else if (prop1->flags != prop2->flags)
krh@248
   285
		return prop1->flags - prop2->flags;
krh@257
   286
	else if (prop1->version != prop2->version)
krh@257
   287
		return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
krh@248
   288
	else
krh@257
   289
		return prop1->packages.list_ptr - prop2->packages.list_ptr;
krh@248
   290
}
krh@248
   291
krh@248
   292
static uint32_t *
krh@248
   293
uniqueify_properties(struct razor_set *set)
krh@248
   294
{
krh@248
   295
	struct razor_property *rp, *up, *rp_end;
krh@248
   296
	struct array *pkgs, *p;
krh@248
   297
	struct list_head *r;
krh@248
   298
	uint32_t *map, *rmap;
krh@248
   299
	int i, count, unique;
krh@248
   300
krh@248
   301
	count = set->properties.size / sizeof(struct razor_property);
krh@248
   302
	map = razor_qsort_with_data(set->properties.data,
krh@248
   303
				    count,
krh@248
   304
				    sizeof(struct razor_property),
krh@248
   305
				    compare_properties,
krh@248
   306
				    set);
krh@248
   307
krh@248
   308
	rp_end = set->properties.data + set->properties.size;
krh@248
   309
	rmap = malloc(count * sizeof *map);
krh@248
   310
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   311
	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
krh@248
   312
		if (rp->name != up->name ||
krh@248
   313
		    rp->flags != up->flags ||
krh@248
   314
		    rp->version != up->version) {
krh@248
   315
			up++;
krh@248
   316
			up->name = rp->name;
krh@248
   317
			up->flags = rp->flags;
krh@248
   318
			up->version = rp->version;
krh@248
   319
		}
krh@248
   320
krh@248
   321
		unique = up - (struct razor_property *) set->properties.data;
krh@248
   322
		rmap[map[i]] = unique;
krh@248
   323
		r = array_add(&pkgs[unique], sizeof *r);
krh@248
   324
		*r = rp->packages;
krh@248
   325
	}
krh@248
   326
	free(map);
krh@248
   327
krh@248
   328
	if (up != rp)
krh@248
   329
		up++;
krh@248
   330
	set->properties.size = (void *) up - set->properties.data;
krh@248
   331
	rp_end = up;
krh@248
   332
	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
krh@248
   333
		list_set_array(&rp->packages, &set->package_pool, p, 0);
krh@248
   334
		array_release(p);
krh@248
   335
	}
krh@248
   336
krh@248
   337
	free(pkgs);
krh@248
   338
krh@248
   339
	return rmap;
krh@248
   340
}
krh@248
   341
krh@248
   342
static int
krh@248
   343
compare_filenames(const void *p1, const void *p2, void *data)
krh@248
   344
{
krh@248
   345
	const struct import_entry *e1 = p1;
krh@248
   346
	const struct import_entry *e2 = p2;
krh@248
   347
	const char *n1 = e1->name;
krh@248
   348
	const char *n2 = e2->name;
krh@248
   349
krh@248
   350
	/* Need to make sure that the contents of a directory
krh@248
   351
	 * are sorted immediately after it. So "foo/bar" has to
krh@248
   352
	 * sort before "foo.conf"
krh@248
   353
	 *
krh@248
   354
	 * FIXME: this is about 60% slower than strcmp
krh@248
   355
	 */
krh@248
   356
	while (*n1 && *n2) {
krh@248
   357
		if (*n1 < *n2)
krh@248
   358
			return *n2 == '/' ? 1 : -1;
krh@248
   359
		else if (*n1 > *n2)
krh@248
   360
			return *n1 == '/' ? -1 : 1;
krh@248
   361
		n1++;
krh@248
   362
		n2++;
krh@248
   363
	}
krh@248
   364
	if (*n1)
krh@248
   365
		return 1;
krh@248
   366
	else if (*n2)
krh@248
   367
		return -1;
krh@248
   368
	else
krh@248
   369
		return 0;
krh@248
   370
}
krh@248
   371
krh@248
   372
static void
krh@248
   373
count_entries(struct import_directory *d)
krh@248
   374
{
krh@248
   375
	struct import_directory *p, *end;
krh@248
   376
krh@248
   377
	p = d->files.data;
krh@248
   378
	end = d->files.data + d->files.size;
krh@248
   379
	d->count = 0;
krh@248
   380
	while (p < end) {
krh@248
   381
		count_entries(p);
krh@248
   382
		d->count += p->count + 1;
krh@248
   383
		p++;
krh@248
   384
	}
krh@248
   385
}
krh@248
   386
krh@248
   387
static void
krh@248
   388
serialize_files(struct razor_set *set,
krh@248
   389
		struct import_directory *d, struct array *array)
krh@248
   390
{
krh@248
   391
	struct import_directory *p, *end;
krh@248
   392
	struct razor_entry *e = NULL;
krh@248
   393
	uint32_t s;
krh@248
   394
krh@248
   395
	p = d->files.data;
krh@248
   396
	end = d->files.data + d->files.size;
krh@248
   397
	s = array->size / sizeof *e + d->files.size / sizeof *p;
krh@248
   398
	while (p < end) {
krh@248
   399
		e = array_add(array, sizeof *e);
krh@248
   400
		e->name = p->name;
krh@248
   401
		e->flags = 0;
krh@248
   402
		e->start = p->count > 0 ? s : 0;
krh@248
   403
		s += p->count;
krh@248
   404
krh@248
   405
		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
krh@248
   406
		array_release(&p->packages);
krh@248
   407
		p++;
krh@248
   408
	}
krh@248
   409
	if (e != NULL)
krh@248
   410
		e->flags |= RAZOR_ENTRY_LAST;
krh@248
   411
krh@248
   412
	p = d->files.data;
krh@248
   413
	end = d->files.data + d->files.size;
krh@248
   414
	while (p < end) {
krh@248
   415
		serialize_files(set, p, array);
krh@248
   416
		p++;
krh@248
   417
	}
krh@248
   418
}
krh@248
   419
krh@248
   420
static void
krh@248
   421
remap_property_package_links(struct array *properties, uint32_t *rmap)
krh@248
   422
{
krh@248
   423
	struct razor_property *p, *end;
krh@248
   424
krh@248
   425
	end = properties->data + properties->size;
krh@248
   426
	for (p = properties->data; p < end; p++)
krh@248
   427
		list_remap_head(&p->packages, rmap);
krh@248
   428
}
krh@248
   429
krh@248
   430
static void
krh@248
   431
build_file_tree(struct razor_importer *importer)
krh@248
   432
{
krh@248
   433
	int count, i, length;
krh@248
   434
	struct import_entry *filenames;
krh@248
   435
	char *f, *end;
ali@359
   436
	uint32_t name, *r, s;
ali@442
   437
	char dirname[256];
ali@359
   438
	struct import_directory *d, *last_root;
ali@359
   439
	struct array roots;
krh@248
   440
	struct razor_entry *e;
krh@248
   441
krh@248
   442
	count = importer->files.size / sizeof (struct import_entry);
ali@359
   443
	filenames = importer->files.data;
ali@359
   444
	razor_qsort_with_data(filenames,
krh@248
   445
			      count,
krh@248
   446
			      sizeof (struct import_entry),
krh@248
   447
			      compare_filenames,
krh@248
   448
			      NULL);
krh@248
   449
ali@359
   450
	array_init(&roots);
ali@359
   451
	last_root = NULL;
krh@248
   452
krh@248
   453
	for (i = 0; i < count; i++) {
krh@248
   454
		f = filenames[i].name;
ali@359
   455
		d = NULL;
krh@248
   456
		while (*f) {
krh@248
   457
			end = strchr(f, '/');
krh@248
   458
			if (end == NULL)
krh@248
   459
				end = f + strlen(f);
krh@248
   460
			length = end - f;
krh@248
   461
			memcpy(dirname, f, length);
ali@359
   462
			dirname[length] = '\0';
jbowes@264
   463
			name = hashtable_tokenize(&importer->file_table,
jbowes@264
   464
						  dirname);
ali@359
   465
			if (!d) {
ali@359
   466
				if (!last_root || last_root->name != name) {
ali@359
   467
					d = array_add(&roots, sizeof *d);
ali@359
   468
					d->name = name;
ali@359
   469
					d->last = NULL;
ali@359
   470
					array_init(&d->files);
ali@359
   471
					array_init(&d->packages);
ali@359
   472
					last_root = d;
ali@359
   473
				}
ali@359
   474
				d = last_root;
ali@359
   475
			} else {
ali@359
   476
				if (!d->last || d->last->name != name) {
ali@359
   477
					d->last = array_add(&d->files,
ali@359
   478
							    sizeof *d);
ali@359
   479
					d->last->name = name;
ali@359
   480
					d->last->last = NULL;
ali@359
   481
					array_init(&d->last->files);
ali@359
   482
					array_init(&d->last->packages);
ali@359
   483
				}
ali@359
   484
				d = d->last;
krh@248
   485
			}
krh@248
   486
			f = end + 1;
krh@248
   487
			if (*end == '\0')
krh@248
   488
				break;
krh@248
   489
		}
krh@248
   490
krh@248
   491
		r = array_add(&d->packages, sizeof *r);
krh@248
   492
		*r = filenames[i].package;
krh@248
   493
		free(filenames[i].name);
krh@248
   494
	}
krh@248
   495
ali@359
   496
	count = roots.size / sizeof (struct import_directory);
ali@359
   497
	d = roots.data;
ali@359
   498
	s = count;
ali@359
   499
	for (i = 0; i < count; i++) {
ali@359
   500
		count_entries(d);
ali@359
   501
		if (i)
ali@359
   502
			e = array_add(&importer->set->files, sizeof *e);
ali@359
   503
		else
ali@359
   504
			e = importer->set->files.data;
ali@359
   505
		e->name = d->name;
ali@359
   506
		e->flags = 0;
ali@359
   507
		e->start = d->count > 0 ? s : 0;
ali@359
   508
		s += d->count;
ali@359
   509
		list_set_empty(&e->packages);
ali@359
   510
		d++;
ali@359
   511
	}
ali@359
   512
	if (count)
ali@359
   513
		e->flags |= RAZOR_ENTRY_LAST;
krh@248
   514
ali@359
   515
	d = roots.data;
ali@359
   516
	for (i = 0; i < count; i++) {
ali@359
   517
		serialize_files(importer->set, d, &importer->set->files);
ali@359
   518
		d++;
ali@359
   519
	}
krh@248
   520
krh@248
   521
	array_release(&importer->files);
ali@359
   522
	array_release(&roots);
krh@248
   523
}
krh@248
   524
krh@248
   525
static void
krh@248
   526
list_to_array(struct list *list, struct array *array)
krh@248
   527
{
krh@248
   528
	uint32_t *item;
krh@248
   529
krh@248
   530
	while (list) {
krh@248
   531
		 item = array_add(array, sizeof *item);
krh@248
   532
		 *item = list->data;
krh@248
   533
		 list = list_next(list);
krh@248
   534
	}
krh@248
   535
}
krh@248
   536
krh@248
   537
static int
krh@248
   538
compare_file_requires(const void *p1, const void *p2, void *data)
krh@248
   539
{
krh@248
   540
	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
krh@248
   541
	const char *pool = data;
krh@248
   542
krh@248
   543
	return strcmp(&pool[*f1], &pool[*f2]);
krh@248
   544
}
krh@248
   545
krh@248
   546
static void
krh@248
   547
find_file_provides(struct razor_importer *importer)
krh@248
   548
{
krh@248
   549
	struct razor_property *prop;
krh@248
   550
	struct razor_entry *top, *entry;
krh@248
   551
	struct razor_package *packages;
krh@248
   552
	struct array pkgprops;
krh@248
   553
	struct list *pkg;
krh@248
   554
	uint32_t *req, *req_start, *req_end;
krh@248
   555
	uint32_t *map, *newprop;
krh@248
   556
	char *pool;
krh@248
   557
krh@248
   558
	pool = importer->set->string_pool.data;
krh@248
   559
	packages = importer->set->packages.data;
krh@248
   560
	top = importer->set->files.data;
krh@248
   561
krh@248
   562
	req = req_start = importer->file_requires.data;
krh@248
   563
	req_end = importer->file_requires.data + importer->file_requires.size;
krh@248
   564
	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
krh@248
   565
				    compare_file_requires, pool);
krh@248
   566
	free(map);
krh@248
   567
krh@248
   568
	for (req = req_start; req < req_end; req++) {
krh@248
   569
		if (req > req_start && req[0] == req[-1])
krh@248
   570
			continue;
krh@248
   571
		entry = razor_set_find_entry(importer->set, top, &pool[*req]);
krh@248
   572
		if (!entry)
krh@248
   573
			continue;
krh@248
   574
krh@248
   575
		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
krh@248
   576
			prop = array_add(&importer->set->properties, sizeof *prop);
krh@248
   577
			prop->name = *req;
krh@248
   578
			prop->flags =
krh@248
   579
				RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
krh@248
   580
			prop->version = hashtable_tokenize(&importer->table, "");
krh@248
   581
			list_set_ptr(&prop->packages, pkg->data);
krh@248
   582
krh@248
   583
			/* Update property list of pkg */
krh@248
   584
			array_init(&pkgprops);
krh@248
   585
			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
krh@248
   586
			newprop = array_add(&pkgprops, sizeof *newprop);
krh@248
   587
			*newprop = prop - (struct razor_property *)importer->set->properties.data;
krh@248
   588
			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
krh@248
   589
			array_release(&pkgprops);
krh@248
   590
		}
krh@248
   591
	}
krh@248
   592
krh@248
   593
	array_release(&importer->file_requires);
krh@248
   594
}
krh@248
   595
krh@248
   596
static void
krh@248
   597
build_package_file_lists(struct razor_set *set, uint32_t *rmap)
krh@248
   598
{
krh@248
   599
	struct razor_package *p, *packages;
krh@248
   600
	struct array *pkgs;
krh@248
   601
	struct razor_entry *e, *end;
krh@248
   602
	struct list *r;
krh@248
   603
	uint32_t *q;
krh@248
   604
	int i, count;
krh@248
   605
krh@248
   606
	count = set->packages.size / sizeof *p;
krh@248
   607
	pkgs = zalloc(count * sizeof *pkgs);
krh@248
   608
krh@248
   609
	end = set->files.data + set->files.size;
krh@248
   610
	for (e = set->files.data; e < end; e++) {
krh@248
   611
		list_remap_head(&e->packages, rmap);
krh@248
   612
		r = list_first(&e->packages, &set->package_pool);
krh@248
   613
		while (r) {
krh@248
   614
			q = array_add(&pkgs[r->data], sizeof *q);
krh@248
   615
			*q = e - (struct razor_entry *) set->files.data;
krh@248
   616
			r = list_next(r);
krh@248
   617
		}
krh@248
   618
	}
krh@248
   619
krh@248
   620
	packages = set->packages.data;
krh@248
   621
	for (i = 0; i < count; i++) {
krh@248
   622
		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
krh@248
   623
		array_release(&pkgs[i]);
krh@248
   624
	}
krh@248
   625
	free(pkgs);
krh@248
   626
}
krh@248
   627
krh@309
   628
/**
krh@309
   629
 * razor_importer_finish:
krh@309
   630
 * @importer: the %razor_importer
krh@309
   631
 *
krh@309
   632
 * Finish importing packages and create the package set.  This sorts
krh@309
   633
 * and indexes all the packages, properties and files in the importer
krh@309
   634
 * and creates a new %razor_set.  After creating the new package set,
krh@309
   635
 * the importer is destroyed.
krh@309
   636
 *
krh@309
   637
 * Returns: the new %razor_set
krh@309
   638
 **/
krh@269
   639
RAZOR_EXPORT struct razor_set *
krh@248
   640
razor_importer_finish(struct razor_importer *importer)
krh@248
   641
{
krh@248
   642
	struct razor_set *set;
krh@248
   643
	uint32_t *map, *rmap;
krh@248
   644
	int i, count;
krh@248
   645
krh@248
   646
	build_file_tree(importer);
krh@248
   647
	find_file_provides(importer);
krh@248
   648
krh@248
   649
	map = uniqueify_properties(importer->set);
krh@248
   650
	list_remap_pool(&importer->set->property_pool, map);
krh@248
   651
	free(map);
krh@248
   652
krh@248
   653
	count = importer->set->packages.size / sizeof(struct razor_package);
krh@248
   654
	map = razor_qsort_with_data(importer->set->packages.data,
krh@248
   655
				    count,
krh@248
   656
				    sizeof(struct razor_package),
krh@248
   657
				    compare_packages,
krh@248
   658
				    importer->set);
krh@248
   659
krh@248
   660
	rmap = malloc(count * sizeof *rmap);
krh@248
   661
	for (i = 0; i < count; i++)
krh@248
   662
		rmap[map[i]] = i;
krh@248
   663
	free(map);
krh@248
   664
krh@248
   665
	list_remap_pool(&importer->set->package_pool, rmap);
krh@248
   666
	build_package_file_lists(importer->set, rmap);
krh@248
   667
	remap_property_package_links(&importer->set->properties, rmap);
krh@248
   668
	free(rmap);
krh@248
   669
krh@248
   670
	set = importer->set;
krh@248
   671
	hashtable_release(&importer->table);
jbowes@264
   672
	hashtable_release(&importer->details_table);
jbowes@264
   673
	hashtable_release(&importer->file_table);
krh@248
   674
	free(importer);
krh@248
   675
krh@248
   676
	return set;
krh@248
   677
}