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