librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Feb 09 20:15:00 2012 +0000 (2012-02-09)
changeset 415 fbd3a02dcfde
parent 403 e63951c1d0f8
child 416 d0aa9e0a6d04
permissions -rw-r--r--
Add mkdtemp to gnulib modules used
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  * Copyright (C) 2009, 2011  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 #ifdef MSWIN_API
    34 #include <windows.h>
    35 #include <direct.h>
    36 #else
    37 #include <sys/utsname.h>
    38 #endif
    39 #if HAVE_SYS_MMAN_H
    40 #include <sys/mman.h>
    41 #endif
    42 #include <assert.h>
    43 
    44 #include "razor.h"
    45 #include "razor-internal.h"
    46 
    47 #ifndef O_BINARY
    48 #define O_BINARY	0
    49 #endif
    50 
    51 /* Required by gnulib on non-libc platforms */
    52 char *program_name = "librazor";
    53 
    54 void *
    55 razor_file_get_contents(const char *filename, size_t *length)
    56 {
    57 	int fd;
    58 	struct stat st;
    59 	void *addr;
    60 #if !HAVE_SYS_MMAN_H
    61 	size_t nb;
    62 	ssize_t res;
    63 #endif
    64 
    65 	fd = open(filename, O_RDONLY | O_BINARY);
    66 	if (fd < 0)
    67 		return NULL;
    68 
    69 	if (fstat(fd, &st) < 0) {
    70 		close(fd);
    71 		return NULL;
    72 	}
    73 
    74 	*length = st.st_size;
    75 #if HAVE_SYS_MMAN_H
    76 	addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    77 #else
    78 	addr = malloc(st.st_size);
    79 	if (addr) {
    80 		nb = 0;
    81 		while(nb < st.st_size) {
    82 			res = read(fd, addr + nb, st.st_size - nb);
    83 			if (res <= 0) {
    84 				free(addr);
    85 				addr = NULL;
    86 				break;
    87 			}
    88 			nb += res;
    89 		}
    90 	}
    91 #endif
    92 	close(fd);
    93 
    94 #if HAVE_SYS_MMAN_H
    95 	if (addr == MAP_FAILED)
    96 		addr = NULL;
    97 #endif
    98 
    99 	return addr;
   100 }
   101 
   102 razor_file_free_contents(void *addr, size_t length)
   103 {
   104 #if HAVE_SYS_MMAN_H
   105 	return munmap(addr, length);
   106 #else
   107 	free(addr);
   108 	return 0;
   109 #endif
   110 }
   111 
   112 struct qsort_context {
   113 	size_t size;
   114 	razor_compare_with_data_func_t compare;
   115 	void *data;
   116 };
   117 
   118 static void
   119 qsort_swap(void *p1, void *p2, size_t size)
   120 {
   121 	char buffer[size];
   122 
   123 	if (p1 != p2) {
   124 		memcpy(buffer, p1, size);
   125 		memcpy(p1, p2, size);
   126 		memcpy(p2, buffer, size);
   127 	}
   128 }
   129 
   130 static void
   131 __qsort_with_data(void *base, size_t nelem, uint32_t *map,
   132 		  struct qsort_context *ctx)
   133 {
   134 	void *p, *start, *end, *pivot;
   135 	uint32_t *mp, *mstart, *mend, tmp;
   136 	int left, right, result;
   137 	size_t size = ctx->size;
   138 
   139 	p = base;
   140 	start = base;
   141 	end = base + nelem * size;
   142 	mp = map;
   143 	mstart = map;
   144 	mend = map + nelem;
   145 	pivot = base + (rand() % nelem) * size;
   146 
   147 	while (p < end) {
   148 		result = ctx->compare(p, pivot, ctx->data);
   149 		if (result < 0) {
   150 			qsort_swap(p, start, size);
   151 			tmp = *mp;
   152 			*mp = *mstart;
   153 			*mstart = tmp;
   154 			if (start == pivot)
   155 				pivot = p;
   156 			start += size;
   157 			mstart++;
   158 			p += size;
   159 			mp++;
   160 		} else if (result == 0) {
   161 			p += size;
   162 			mp++;
   163 		} else {
   164  			end -= size;
   165 			mend--;
   166 			qsort_swap(p, end, size);
   167 			tmp = *mp;
   168 			*mp = *mend;
   169 			*mend = tmp;
   170 			if (end == pivot)
   171 				pivot = p;
   172 		}
   173 	}
   174 
   175 	left = (start - base) / size;
   176 	right = (base + nelem * size - end) / size;
   177 	if (left > 1)
   178 		__qsort_with_data(base, left, map, ctx);
   179 	if (right > 1)
   180 		__qsort_with_data(end, right, mend, ctx);
   181 }
   182 
   183 uint32_t *
   184 razor_qsort_with_data(void *base, size_t nelem, size_t size,
   185 		      razor_compare_with_data_func_t compare, void *data)
   186 {
   187 	struct qsort_context ctx;
   188 	uint32_t *map;
   189 	int i;
   190 
   191 	if (nelem == 0)
   192 		return NULL;
   193 
   194 	ctx.size = size;
   195 	ctx.compare = compare;
   196 	ctx.data = data;
   197 
   198 	map = malloc(nelem * sizeof (uint32_t));
   199 	for (i = 0; i < nelem; i++)
   200 		map[i] = i;
   201 
   202 	__qsort_with_data(base, nelem, map, &ctx);
   203 
   204 	return map;
   205 }
   206 
   207 void environment_init(struct environment *env)
   208 {
   209 	env->is_set = 0;
   210 	array_init(&env->string_pool);
   211 	array_init(&env->vars);
   212 }
   213 
   214 void environment_add_variable(struct environment *env,
   215 			      const char *variable, const char *value)
   216 {
   217 	char *s;
   218 	uint32_t *r;
   219 	assert(!env->is_set);
   220 
   221 	s = array_add(&env->string_pool,
   222 		      strlen(variable) + strlen(value) + 2);
   223 	sprintf(s, "%s=%s", variable, value);
   224 	r = array_add(&env->vars, sizeof *r);
   225 	*r = s - (char *)env->string_pool.data;
   226 }
   227 
   228 void environment_set(struct environment *env)
   229 {
   230 	int i, count;
   231 	char *s, *t;
   232         uint32_t *r;
   233 
   234 	if (!env->is_set) {
   235 		count = env->vars.size / sizeof(uint32_t);
   236 		r = (uint32_t *)env->vars.data;
   237 		for (i = 0; i < count; i++) {
   238 			s = env->string_pool.data + *r++;
   239 #ifdef WIN32
   240 			putenv(s);
   241 #else
   242 			t = strchr(s, '=');
   243 			*t = '\0';
   244 			setenv(s, t + 1, 1);
   245 			*t = '=';
   246 #endif
   247 		}
   248 
   249 		env->is_set = 1;
   250 	}
   251 }
   252 
   253 void environment_unset(struct environment *env)
   254 {
   255 	int i, count;
   256 	char c, *s, *t;
   257         uint32_t *r;
   258 
   259 	if (env->is_set) {
   260 		count = env->vars.size / sizeof(uint32_t);
   261 		r = (uint32_t *)env->vars.data;
   262 		for (i = 0; i < count; i++) {
   263 			s = env->string_pool.data + *r++;
   264 			t = strchr(s, '=');
   265 #ifdef WIN32
   266 			t++;
   267 			c = *t;
   268 			*t = '\0';
   269 			putenv(s);
   270 			*t = c;
   271 #else
   272 			c = *t;
   273 			*t = '\0';
   274 			unsetenv(s);
   275 			*t = c;
   276 #endif
   277 		}
   278 
   279 		env->is_set = 0;
   280 	}
   281 }
   282 
   283 void environment_release(struct environment *env)
   284 {
   285 	environment_unset(env);
   286 	array_release(&env->string_pool);
   287 	array_release(&env->vars);
   288 }
   289 
   290 RAZOR_EXPORT char *razor_concat(const char *s, ...)
   291 {
   292 	va_list args;
   293 	const char *string;
   294 	char *concat;
   295 	size_t n, len;
   296 
   297 	va_start(args, s);
   298 
   299 	len = strlen(s);
   300 	while((string = va_arg(args, const char *)))
   301 		len += strlen(string);
   302 
   303 	va_end(args);
   304 
   305 	concat = malloc(len + 1);
   306 
   307 	if (!concat)
   308 		return NULL;
   309 
   310 	va_start(args, s);
   311 
   312 	len = strlen(s);
   313 	memcpy(concat, s, len);
   314 	n = len;
   315 	while((string = va_arg(args, const char *))) {
   316 		len = strlen(string);
   317 		memcpy(concat + n, string, len);
   318 		n += len;
   319 	}
   320 
   321 	va_end(args);
   322 
   323 	concat[n] = '\0';
   324 
   325 	return concat;
   326 }
   327 
   328 RAZOR_EXPORT const char *razor_system_arch(void)
   329 {
   330 #ifdef MSWIN_API
   331 	SYSTEM_INFO si;
   332 
   333 	GetNativeSystemInfo(&si);
   334 	switch(si.wProcessorArchitecture)
   335 	{
   336 		case PROCESSOR_ARCHITECTURE_INTEL:
   337 			return "i686";
   338 		case PROCESSOR_ARCHITECTURE_AMD64:
   339 			return "x86_64";
   340 		default:
   341 			return NULL;
   342 	}
   343 #else
   344 	static struct utsname un;
   345 
   346 	if (uname(&un))
   347 		return NULL;
   348 	else
   349 		return un.machine;
   350 #endif
   351 }