util.c
author Kristian H?gsberg <krh@jiraiya.boston.redhat.com>
Tue Apr 08 00:10:31 2008 -0400 (2008-04-08)
changeset 209 78afac5bb7b8
parent 149 43cac7931189
child 211 cf0ca962262b
permissions -rw-r--r--
Don't add package to transaction more than once.
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@91
    18
	/* Create all sub-directories in dir and then create name. We
krh@91
    19
	 * know root exists and is a dir, root does not end in a '/',
krh@91
    20
	 * and path has a 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@149
    28
			next = slash + strlen(slash);
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
}