librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Jan 08 15:22:34 2009 +0000 (2009-01-08)
changeset 331 890a49fb2c71
parent 300 455eaa569767
child 337 c89695ed29f0
permissions -rw-r--r--
Remove unnecessary include of sys/mman.h
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>
rhughes@241
    30
#include <unistd.h>
ali@322
    31
#include <fcntl.h>
ali@322
    32
#if HAVE_SYS_MMAN_H
ali@322
    33
#include <sys/mman.h>
ali@322
    34
#endif
rhughes@241
    35
rhughes@241
    36
#include "razor-internal.h"
rhughes@241
    37
ali@322
    38
#ifndef O_BINARY
ali@322
    39
#define O_BINARY	0
ali@322
    40
#endif
ali@322
    41
rhughes@241
    42
int
rhughes@241
    43
razor_create_dir(const char *root, const char *path)
rhughes@241
    44
{
rhughes@241
    45
	char buffer[PATH_MAX], *p;
rhughes@241
    46
	const char *slash, *next;
rhughes@241
    47
	struct stat buf;
rhughes@241
    48
rhughes@241
    49
	/* Create all sub-directories in dir. We know root exists and
rhughes@241
    50
	 * is a dir, root does not end in a '/', and path has a
rhughes@241
    51
	 * leading '/'. */
rhughes@241
    52
rhughes@241
    53
	strcpy(buffer, root);
rhughes@241
    54
	p = buffer + strlen(buffer);
rhughes@241
    55
	slash = path;
rhughes@241
    56
	for (slash = path; *slash != '\0'; slash = next) {
rhughes@241
    57
		next = strchr(slash + 1, '/');
rhughes@241
    58
		if (next == NULL)
rhughes@241
    59
			break;
rhughes@241
    60
rhughes@241
    61
		memcpy(p, slash, next - slash);
rhughes@241
    62
		p += next - slash;
rhughes@241
    63
		*p = '\0';
rhughes@241
    64
rhughes@241
    65
		if (stat(buffer, &buf) == 0) {
rhughes@241
    66
			if (!S_ISDIR(buf.st_mode)) {
rhughes@241
    67
				fprintf(stderr,
rhughes@241
    68
					"%s exists but is not a directory\n",
rhughes@241
    69
					buffer);
rhughes@241
    70
				return -1;
rhughes@241
    71
			}
rhughes@241
    72
		} else if (mkdir(buffer, 0777) < 0) {
rhughes@241
    73
			fprintf(stderr, "failed to make directory %s: %m\n",
rhughes@241
    74
				buffer);
rhughes@241
    75
			return -1;
rhughes@241
    76
		}
rhughes@241
    77
rhughes@241
    78
		/* FIXME: What to do about permissions for dirs we
rhughes@241
    79
		 * have to create but are not in the cpio archive? */
rhughes@241
    80
	}
rhughes@241
    81
rhughes@241
    82
	return 0;
rhughes@241
    83
}
rhughes@241
    84
rhughes@241
    85
int
rhughes@241
    86
razor_write(int fd, const void *data, size_t size)
rhughes@241
    87
{
rhughes@241
    88
	size_t rest;
rhughes@241
    89
	ssize_t written;
rhughes@241
    90
	const unsigned char *p;
rhughes@241
    91
rhughes@241
    92
	rest = size;
rhughes@241
    93
	p = data;
rhughes@241
    94
	while (rest > 0) {
rhughes@241
    95
		written = write(fd, p, rest);
rhughes@241
    96
		if (written < 0) {
rhughes@241
    97
			fprintf(stderr, "write error: %m\n");
rhughes@241
    98
			return -1;
rhughes@241
    99
		}
rhughes@241
   100
		rest -= written;
rhughes@241
   101
		p += written;
rhughes@241
   102
	}
rhughes@241
   103
rhughes@241
   104
	return 0;
rhughes@241
   105
}
rhughes@241
   106
ali@322
   107
void *
ali@322
   108
razor_file_get_contents(const char *filename, size_t *length)
ali@322
   109
{
ali@322
   110
	int fd;
ali@322
   111
	struct stat st;
ali@322
   112
	void *addr;
ali@322
   113
#if !HAVE_SYS_MMAN_H
ali@322
   114
	size_t nb;
ali@322
   115
	ssize_t res;
ali@322
   116
#endif
ali@322
   117
ali@322
   118
	fd = open(filename, O_RDONLY | O_BINARY);
ali@322
   119
	if (fd < 0)
ali@322
   120
		return NULL;
ali@322
   121
ali@322
   122
	if (fstat(fd, &st) < 0) {
ali@322
   123
		close(fd);
ali@322
   124
		return NULL;
ali@322
   125
	}
ali@322
   126
ali@322
   127
	*length = st.st_size;
ali@322
   128
#if HAVE_SYS_MMAN_H
ali@322
   129
	addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
ali@322
   130
#else
ali@322
   131
	addr = malloc(st.st_size);
ali@322
   132
	if (addr) {
ali@322
   133
		nb = 0;
ali@322
   134
		while(nb < st.st_size) {
ali@322
   135
			res = read(fd, addr + nb, st.st_size - nb);
ali@322
   136
			if (res <= 0) {
ali@322
   137
				free(addr);
ali@322
   138
				addr = NULL;
ali@322
   139
				break;
ali@322
   140
			}
ali@322
   141
			nb += res;
ali@322
   142
		}
ali@322
   143
	}
ali@322
   144
#endif
ali@322
   145
	close(fd);
ali@322
   146
ali@322
   147
#if HAVE_SYS_MMAN_H
ali@322
   148
	if (addr == MAP_FAILED)
ali@322
   149
		addr = NULL;
ali@322
   150
#endif
ali@322
   151
ali@322
   152
	return addr;
ali@322
   153
}
ali@322
   154
ali@322
   155
int
ali@322
   156
razor_file_free_contents(void *addr, size_t length)
ali@322
   157
{
ali@322
   158
#if HAVE_SYS_MMAN_H
ali@322
   159
	return munmap(addr, length);
ali@322
   160
#else
ali@322
   161
	free(addr);
ali@322
   162
	return 0;
ali@322
   163
#endif
ali@322
   164
}
ali@322
   165
rhughes@241
   166
struct qsort_context {
rhughes@241
   167
	size_t size;
rhughes@241
   168
	razor_compare_with_data_func_t compare;
rhughes@241
   169
	void *data;
rhughes@241
   170
};
rhughes@241
   171
rhughes@241
   172
static void
rhughes@241
   173
qsort_swap(void *p1, void *p2, size_t size)
rhughes@241
   174
{
rhughes@241
   175
	char buffer[size];
rhughes@241
   176
rhughes@241
   177
	memcpy(buffer, p1, size);
rhughes@241
   178
	memcpy(p1, p2, size);
rhughes@241
   179
	memcpy(p2, buffer, size);
rhughes@241
   180
}
rhughes@241
   181
rhughes@241
   182
static void
rhughes@241
   183
__qsort_with_data(void *base, size_t nelem, uint32_t *map,
rhughes@241
   184
		  struct qsort_context *ctx)
rhughes@241
   185
{
rhughes@241
   186
	void *p, *start, *end, *pivot;
rhughes@241
   187
	uint32_t *mp, *mstart, *mend, tmp;
rhughes@241
   188
	int left, right, result;
rhughes@241
   189
	size_t size = ctx->size;
rhughes@241
   190
rhughes@241
   191
	p = base;
rhughes@241
   192
	start = base;
rhughes@241
   193
	end = base + nelem * size;
rhughes@241
   194
	mp = map;
rhughes@241
   195
	mstart = map;
rhughes@241
   196
	mend = map + nelem;
rhughes@241
   197
	pivot = base + (random() % nelem) * size;
rhughes@241
   198
rhughes@241
   199
	while (p < end) {
rhughes@241
   200
		result = ctx->compare(p, pivot, ctx->data);
rhughes@241
   201
		if (result < 0) {
rhughes@241
   202
			qsort_swap(p, start, size);
rhughes@241
   203
			tmp = *mp;
rhughes@241
   204
			*mp = *mstart;
rhughes@241
   205
			*mstart = tmp;
rhughes@241
   206
			if (start == pivot)
rhughes@241
   207
				pivot = p;
rhughes@241
   208
			start += size;
rhughes@241
   209
			mstart++;
rhughes@241
   210
			p += size;
rhughes@241
   211
			mp++;
rhughes@241
   212
		} else if (result == 0) {
rhughes@241
   213
			p += size;
rhughes@241
   214
			mp++;
rhughes@241
   215
		} else {
rhughes@241
   216
 			end -= size;
rhughes@241
   217
			mend--;
rhughes@241
   218
			qsort_swap(p, end, size);
rhughes@241
   219
			tmp = *mp;
rhughes@241
   220
			*mp = *mend;
rhughes@241
   221
			*mend = tmp;
rhughes@241
   222
			if (end == pivot)
rhughes@241
   223
				pivot = p;
rhughes@241
   224
		}
rhughes@241
   225
	}
rhughes@241
   226
rhughes@241
   227
	left = (start - base) / size;
rhughes@241
   228
	right = (base + nelem * size - end) / size;
rhughes@241
   229
	if (left > 1)
rhughes@241
   230
		__qsort_with_data(base, left, map, ctx);
rhughes@241
   231
	if (right > 1)
rhughes@241
   232
		__qsort_with_data(end, right, mend, ctx);
rhughes@241
   233
}
rhughes@241
   234
rhughes@241
   235
uint32_t *
rhughes@241
   236
razor_qsort_with_data(void *base, size_t nelem, size_t size,
rhughes@241
   237
		      razor_compare_with_data_func_t compare, void *data)
rhughes@241
   238
{
rhughes@241
   239
	struct qsort_context ctx;
rhughes@241
   240
	uint32_t *map;
rhughes@241
   241
	int i;
rhughes@241
   242
rhughes@241
   243
	if (nelem == 0)
rhughes@241
   244
		return NULL;
rhughes@241
   245
rhughes@241
   246
	ctx.size = size;
rhughes@241
   247
	ctx.compare = compare;
rhughes@241
   248
	ctx.data = data;
rhughes@241
   249
rhughes@241
   250
	map = malloc(nelem * sizeof (uint32_t));
rhughes@241
   251
	for (i = 0; i < nelem; i++)
rhughes@241
   252
		map[i] = i;
rhughes@241
   253
rhughes@241
   254
	__qsort_with_data(base, nelem, map, &ctx);
rhughes@241
   255
rhughes@241
   256
	return map;
rhughes@241
   257
}