librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Apr 17 21:09:55 2009 +0100 (2009-04-17)
changeset 357 39f8dab73084
parent 338 47f3e27cb978
child 359 c9c90315ea24
permissions -rw-r--r--
Add hashtable test to expose confusion as to whether 0 is a valid value or not
richard@300
     1
/*
richard@300
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
richard@300
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@322
     4
 * Copyright (C) 2009  J. Ali Harlow <ali@juiblex.co.uk>
richard@300
     5
 *
richard@300
     6
 * This program is free software; you can redistribute it and/or modify
richard@300
     7
 * it under the terms of the GNU General Public License as published by
richard@300
     8
 * the Free Software Foundation; either version 2 of the License, or
richard@300
     9
 * (at your option) any later version.
richard@300
    10
 *
richard@300
    11
 * This program is distributed in the hope that it will be useful,
richard@300
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
richard@300
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
richard@300
    14
 * GNU General Public License for more details.
richard@300
    15
 *
richard@300
    16
 * You should have received a copy of the GNU General Public License along
richard@300
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
richard@300
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
richard@300
    19
 */
richard@300
    20
ali@322
    21
#include "config.h"
ali@322
    22
rhughes@241
    23
#include <limits.h>
rhughes@241
    24
#include <string.h>
ali@322
    25
#include <sys/types.h>
rhughes@241
    26
#include <sys/stat.h>
rhughes@241
    27
#include <stdlib.h>
rhughes@241
    28
#include <stdio.h>
rhughes@241
    29
#include <stdint.h>
ali@339
    30
#include <errno.h>
rhughes@241
    31
#include <unistd.h>
ali@322
    32
#include <fcntl.h>
ali@322
    33
#if HAVE_SYS_MMAN_H
ali@322
    34
#include <sys/mman.h>
ali@322
    35
#endif
rhughes@241
    36
rhughes@241
    37
#include "razor-internal.h"
rhughes@241
    38
ali@322
    39
#ifndef O_BINARY
ali@322
    40
#define O_BINARY	0
ali@322
    41
#endif
ali@322
    42
ali@338
    43
/* Required by gnulib on non-libc platforms */
ali@338
    44
char *program_name = "librazor";
ali@338
    45
rhughes@241
    46
int
rhughes@241
    47
razor_create_dir(const char *root, const char *path)
rhughes@241
    48
{
rhughes@241
    49
	char buffer[PATH_MAX], *p;
rhughes@241
    50
	const char *slash, *next;
rhughes@241
    51
	struct stat buf;
rhughes@241
    52
rhughes@241
    53
	/* Create all sub-directories in dir. We know root exists and
rhughes@241
    54
	 * is a dir, root does not end in a '/', and path has a
rhughes@241
    55
	 * leading '/'. */
rhughes@241
    56
rhughes@241
    57
	strcpy(buffer, root);
rhughes@241
    58
	p = buffer + strlen(buffer);
rhughes@241
    59
	slash = path;
rhughes@241
    60
	for (slash = path; *slash != '\0'; slash = next) {
rhughes@241
    61
		next = strchr(slash + 1, '/');
rhughes@241
    62
		if (next == NULL)
rhughes@241
    63
			break;
rhughes@241
    64
rhughes@241
    65
		memcpy(p, slash, next - slash);
rhughes@241
    66
		p += next - slash;
rhughes@241
    67
		*p = '\0';
rhughes@241
    68
rhughes@241
    69
		if (stat(buffer, &buf) == 0) {
rhughes@241
    70
			if (!S_ISDIR(buf.st_mode)) {
rhughes@241
    71
				fprintf(stderr,
rhughes@241
    72
					"%s exists but is not a directory\n",
rhughes@241
    73
					buffer);
rhughes@241
    74
				return -1;
rhughes@241
    75
			}
rhughes@241
    76
		} else if (mkdir(buffer, 0777) < 0) {
ali@339
    77
			fprintf(stderr, "failed to make directory %s: %s\n",
ali@339
    78
				buffer, strerror(errno));
rhughes@241
    79
			return -1;
rhughes@241
    80
		}
rhughes@241
    81
rhughes@241
    82
		/* FIXME: What to do about permissions for dirs we
rhughes@241
    83
		 * have to create but are not in the cpio archive? */
rhughes@241
    84
	}
rhughes@241
    85
rhughes@241
    86
	return 0;
rhughes@241
    87
}
rhughes@241
    88
rhughes@241
    89
int
rhughes@241
    90
razor_write(int fd, const void *data, size_t size)
rhughes@241
    91
{
rhughes@241
    92
	size_t rest;
rhughes@241
    93
	ssize_t written;
rhughes@241
    94
	const unsigned char *p;
rhughes@241
    95
rhughes@241
    96
	rest = size;
rhughes@241
    97
	p = data;
rhughes@241
    98
	while (rest > 0) {
rhughes@241
    99
		written = write(fd, p, rest);
rhughes@241
   100
		if (written < 0) {
ali@339
   101
			perror("write error");
rhughes@241
   102
			return -1;
rhughes@241
   103
		}
rhughes@241
   104
		rest -= written;
rhughes@241
   105
		p += written;
rhughes@241
   106
	}
rhughes@241
   107
rhughes@241
   108
	return 0;
rhughes@241
   109
}
rhughes@241
   110
ali@322
   111
void *
ali@322
   112
razor_file_get_contents(const char *filename, size_t *length)
ali@322
   113
{
ali@322
   114
	int fd;
ali@322
   115
	struct stat st;
ali@322
   116
	void *addr;
ali@322
   117
#if !HAVE_SYS_MMAN_H
ali@322
   118
	size_t nb;
ali@322
   119
	ssize_t res;
ali@322
   120
#endif
ali@322
   121
ali@322
   122
	fd = open(filename, O_RDONLY | O_BINARY);
ali@322
   123
	if (fd < 0)
ali@322
   124
		return NULL;
ali@322
   125
ali@322
   126
	if (fstat(fd, &st) < 0) {
ali@322
   127
		close(fd);
ali@322
   128
		return NULL;
ali@322
   129
	}
ali@322
   130
ali@322
   131
	*length = st.st_size;
ali@322
   132
#if HAVE_SYS_MMAN_H
ali@322
   133
	addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
ali@322
   134
#else
ali@322
   135
	addr = malloc(st.st_size);
ali@322
   136
	if (addr) {
ali@322
   137
		nb = 0;
ali@322
   138
		while(nb < st.st_size) {
ali@322
   139
			res = read(fd, addr + nb, st.st_size - nb);
ali@322
   140
			if (res <= 0) {
ali@322
   141
				free(addr);
ali@322
   142
				addr = NULL;
ali@322
   143
				break;
ali@322
   144
			}
ali@322
   145
			nb += res;
ali@322
   146
		}
ali@322
   147
	}
ali@322
   148
#endif
ali@322
   149
	close(fd);
ali@322
   150
ali@322
   151
#if HAVE_SYS_MMAN_H
ali@322
   152
	if (addr == MAP_FAILED)
ali@322
   153
		addr = NULL;
ali@322
   154
#endif
ali@322
   155
ali@322
   156
	return addr;
ali@322
   157
}
ali@322
   158
ali@322
   159
int
ali@322
   160
razor_file_free_contents(void *addr, size_t length)
ali@322
   161
{
ali@322
   162
#if HAVE_SYS_MMAN_H
ali@322
   163
	return munmap(addr, length);
ali@322
   164
#else
ali@322
   165
	free(addr);
ali@322
   166
	return 0;
ali@322
   167
#endif
ali@322
   168
}
ali@322
   169
rhughes@241
   170
struct qsort_context {
rhughes@241
   171
	size_t size;
rhughes@241
   172
	razor_compare_with_data_func_t compare;
rhughes@241
   173
	void *data;
rhughes@241
   174
};
rhughes@241
   175
rhughes@241
   176
static void
rhughes@241
   177
qsort_swap(void *p1, void *p2, size_t size)
rhughes@241
   178
{
rhughes@241
   179
	char buffer[size];
rhughes@241
   180
rhughes@241
   181
	memcpy(buffer, p1, size);
rhughes@241
   182
	memcpy(p1, p2, size);
rhughes@241
   183
	memcpy(p2, buffer, size);
rhughes@241
   184
}
rhughes@241
   185
rhughes@241
   186
static void
rhughes@241
   187
__qsort_with_data(void *base, size_t nelem, uint32_t *map,
rhughes@241
   188
		  struct qsort_context *ctx)
rhughes@241
   189
{
rhughes@241
   190
	void *p, *start, *end, *pivot;
rhughes@241
   191
	uint32_t *mp, *mstart, *mend, tmp;
rhughes@241
   192
	int left, right, result;
rhughes@241
   193
	size_t size = ctx->size;
rhughes@241
   194
rhughes@241
   195
	p = base;
rhughes@241
   196
	start = base;
rhughes@241
   197
	end = base + nelem * size;
rhughes@241
   198
	mp = map;
rhughes@241
   199
	mstart = map;
rhughes@241
   200
	mend = map + nelem;
ali@337
   201
	pivot = base + (rand() % nelem) * size;
rhughes@241
   202
rhughes@241
   203
	while (p < end) {
rhughes@241
   204
		result = ctx->compare(p, pivot, ctx->data);
rhughes@241
   205
		if (result < 0) {
rhughes@241
   206
			qsort_swap(p, start, size);
rhughes@241
   207
			tmp = *mp;
rhughes@241
   208
			*mp = *mstart;
rhughes@241
   209
			*mstart = tmp;
rhughes@241
   210
			if (start == pivot)
rhughes@241
   211
				pivot = p;
rhughes@241
   212
			start += size;
rhughes@241
   213
			mstart++;
rhughes@241
   214
			p += size;
rhughes@241
   215
			mp++;
rhughes@241
   216
		} else if (result == 0) {
rhughes@241
   217
			p += size;
rhughes@241
   218
			mp++;
rhughes@241
   219
		} else {
rhughes@241
   220
 			end -= size;
rhughes@241
   221
			mend--;
rhughes@241
   222
			qsort_swap(p, end, size);
rhughes@241
   223
			tmp = *mp;
rhughes@241
   224
			*mp = *mend;
rhughes@241
   225
			*mend = tmp;
rhughes@241
   226
			if (end == pivot)
rhughes@241
   227
				pivot = p;
rhughes@241
   228
		}
rhughes@241
   229
	}
rhughes@241
   230
rhughes@241
   231
	left = (start - base) / size;
rhughes@241
   232
	right = (base + nelem * size - end) / size;
rhughes@241
   233
	if (left > 1)
rhughes@241
   234
		__qsort_with_data(base, left, map, ctx);
rhughes@241
   235
	if (right > 1)
rhughes@241
   236
		__qsort_with_data(end, right, mend, ctx);
rhughes@241
   237
}
rhughes@241
   238
rhughes@241
   239
uint32_t *
rhughes@241
   240
razor_qsort_with_data(void *base, size_t nelem, size_t size,
rhughes@241
   241
		      razor_compare_with_data_func_t compare, void *data)
rhughes@241
   242
{
rhughes@241
   243
	struct qsort_context ctx;
rhughes@241
   244
	uint32_t *map;
rhughes@241
   245
	int i;
rhughes@241
   246
rhughes@241
   247
	if (nelem == 0)
rhughes@241
   248
		return NULL;
rhughes@241
   249
rhughes@241
   250
	ctx.size = size;
rhughes@241
   251
	ctx.compare = compare;
rhughes@241
   252
	ctx.data = data;
rhughes@241
   253
rhughes@241
   254
	map = malloc(nelem * sizeof (uint32_t));
rhughes@241
   255
	for (i = 0; i < nelem; i++)
rhughes@241
   256
		map[i] = i;
rhughes@241
   257
rhughes@241
   258
	__qsort_with_data(base, nelem, map, &ctx);
rhughes@241
   259
rhughes@241
   260
	return map;
rhughes@241
   261
}