librazor/util.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 23:13:09 2008 -0400 (2008-06-20)
changeset 257 0c3db660514d
child 300 455eaa569767
permissions -rw-r--r--
When uniquifying properties, also sort them on the owning package.

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