util.c
author Kristian H?gsberg <krh@redhat.com>
Mon Jun 09 12:47:37 2008 -0400 (2008-06-09)
changeset 230 c1e2aed8dd07
parent 186 7f45d0401e37
permissions -rw-r--r--
Rewrite depsolver to use a series of passes over all packages.

The big change is that we follow one step of the depedency chain for
each package to resolve in each iteration, and repeat until there are
no more possible moves. In contrast the old depsolver would try to
follow the dependency chain completely for one package at a time.

This new approach is simpler and faster, and at the same time more
roboust. Instead of knowing how one newly installed package may
affect other packages (obsoleting, pulling in new packages etc), the
new algorithm just looks at the total list of requires, provides,
obsoletes and conflicts after installing new packages.
krh@91
     1
#include <limits.h>
krh@91
     2
#include <string.h>
krh@91
     3
#include <sys/stat.h>
krh@91
     4
#include <stdlib.h>
krh@91
     5
#include <stdio.h>
krh@186
     6
#include <stdint.h>
krh@91
     7
#include <unistd.h>
krh@91
     8
danw@136
     9
#include "razor-internal.h"
danw@136
    10
krh@91
    11
int
krh@91
    12
razor_create_dir(const char *root, const char *path)
krh@91
    13
{
krh@91
    14
	char buffer[PATH_MAX], *p;
krh@91
    15
	const char *slash, *next;
krh@91
    16
	struct stat buf;
krh@91
    17
krh@211
    18
	/* Create all sub-directories in dir. We know root exists and
krh@211
    19
	 * is a dir, root does not end in a '/', and path has a
krh@211
    20
	 * leading '/'. */
krh@91
    21
krh@91
    22
	strcpy(buffer, root);
krh@91
    23
	p = buffer + strlen(buffer);
krh@91
    24
	slash = path;
krh@149
    25
	for (slash = path; *slash != '\0'; slash = next) {
krh@91
    26
		next = strchr(slash + 1, '/');
krh@149
    27
		if (next == NULL)
krh@211
    28
			break;
krh@149
    29
krh@91
    30
		memcpy(p, slash, next - slash);
krh@91
    31
		p += next - slash;
krh@91
    32
		*p = '\0';
krh@91
    33
krh@91
    34
		if (stat(buffer, &buf) == 0) {
krh@91
    35
			if (!S_ISDIR(buf.st_mode)) {
krh@91
    36
				fprintf(stderr,
krh@91
    37
					"%s exists but is not a directory\n",
krh@91
    38
					buffer);
krh@91
    39
				return -1;
krh@91
    40
			}
krh@91
    41
		} else if (mkdir(buffer, 0777) < 0) {
krh@91
    42
			fprintf(stderr, "failed to make directory %s: %m\n",
krh@91
    43
				buffer);
krh@91
    44
			return -1;
krh@91
    45
		}
krh@91
    46
krh@91
    47
		/* FIXME: What to do about permissions for dirs we
krh@91
    48
		 * have to create but are not in the cpio archive? */
krh@91
    49
	}
krh@91
    50
krh@91
    51
	return 0;
krh@91
    52
}
krh@91
    53
krh@91
    54
int
krh@91
    55
razor_write(int fd, const void *data, size_t size)
krh@91
    56
{
krh@91
    57
	size_t rest;
krh@91
    58
	ssize_t written;
krh@91
    59
	const unsigned char *p;
krh@91
    60
krh@91
    61
	rest = size;
krh@91
    62
	p = data;
krh@91
    63
	while (rest > 0) {
krh@91
    64
		written = write(fd, p, rest);
krh@91
    65
		if (written < 0) {
krh@91
    66
			fprintf(stderr, "write error: %m\n");
krh@91
    67
			return -1;
krh@91
    68
		}
krh@91
    69
		rest -= written;
krh@91
    70
		p += written;
krh@91
    71
	}
krh@91
    72
krh@91
    73
	return 0;
krh@91
    74
}
krh@186
    75
krh@186
    76
struct qsort_context {
krh@186
    77
	size_t size;
krh@186
    78
	razor_compare_with_data_func_t compare;
krh@186
    79
	void *data;
krh@186
    80
};
krh@186
    81
krh@186
    82
static void
krh@186
    83
qsort_swap(void *p1, void *p2, size_t size)
krh@186
    84
{
krh@186
    85
	char buffer[size];
krh@186
    86
krh@186
    87
	memcpy(buffer, p1, size);
krh@186
    88
	memcpy(p1, p2, size);
krh@186
    89
	memcpy(p2, buffer, size);
krh@186
    90
}
krh@186
    91
krh@186
    92
static void
krh@186
    93
__qsort_with_data(void *base, size_t nelem, uint32_t *map,
krh@186
    94
		  struct qsort_context *ctx)
krh@186
    95
{
krh@186
    96
	void *p, *start, *end, *pivot;
krh@186
    97
	uint32_t *mp, *mstart, *mend, tmp;
krh@186
    98
	int left, right, result;
krh@186
    99
	size_t size = ctx->size;
krh@186
   100
krh@186
   101
	p = base;
krh@186
   102
	start = base;
krh@186
   103
	end = base + nelem * size;
krh@186
   104
	mp = map;
krh@186
   105
	mstart = map;
krh@186
   106
	mend = map + nelem;
krh@186
   107
	pivot = base + (random() % nelem) * size;
krh@186
   108
krh@186
   109
	while (p < end) {
krh@186
   110
		result = ctx->compare(p, pivot, ctx->data);
krh@186
   111
		if (result < 0) {
krh@186
   112
			qsort_swap(p, start, size);
krh@186
   113
			tmp = *mp;
krh@186
   114
			*mp = *mstart;
krh@186
   115
			*mstart = tmp;
krh@186
   116
			if (start == pivot)
krh@186
   117
				pivot = p;
krh@186
   118
			start += size;
krh@186
   119
			mstart++;
krh@186
   120
			p += size;
krh@186
   121
			mp++;
krh@186
   122
		} else if (result == 0) {
krh@186
   123
			p += size;
krh@186
   124
			mp++;
krh@186
   125
		} else {
krh@186
   126
 			end -= size;
krh@186
   127
			mend--;
krh@186
   128
			qsort_swap(p, end, size);
krh@186
   129
			tmp = *mp;
krh@186
   130
			*mp = *mend;
krh@186
   131
			*mend = tmp;
krh@186
   132
			if (end == pivot)
krh@186
   133
				pivot = p;
krh@186
   134
		}
krh@186
   135
	}
krh@186
   136
krh@186
   137
	left = (start - base) / size;
krh@186
   138
	right = (base + nelem * size - end) / size;
krh@186
   139
	if (left > 1)
krh@186
   140
		__qsort_with_data(base, left, map, ctx);
krh@186
   141
	if (right > 1)
krh@186
   142
		__qsort_with_data(end, right, mend, ctx);
krh@186
   143
}
krh@186
   144
krh@186
   145
uint32_t *
krh@186
   146
razor_qsort_with_data(void *base, size_t nelem, size_t size,
krh@186
   147
		      razor_compare_with_data_func_t compare, void *data)
krh@186
   148
{
krh@186
   149
	struct qsort_context ctx;
krh@186
   150
	uint32_t *map;
krh@186
   151
	int i;
krh@186
   152
krh@186
   153
	if (nelem == 0)
krh@186
   154
		return NULL;
krh@186
   155
krh@186
   156
	ctx.size = size;
krh@186
   157
	ctx.compare = compare;
krh@186
   158
	ctx.data = data;
krh@186
   159
krh@186
   160
	map = malloc(nelem * sizeof (uint32_t));
krh@186
   161
	for (i = 0; i < nelem; i++)
krh@186
   162
		map[i] = i;
krh@186
   163
krh@186
   164
	__qsort_with_data(base, nelem, map, &ctx);
krh@186
   165
krh@186
   166
	return map;
krh@186
   167
}