librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Nov 10 10:35:21 2011 +0000 (2011-11-10)
changeset 403 e63951c1d0f8
parent 377 5549419824b4
child 406 5ab137def3d1
permissions -rw-r--r--
Use Windows KTM (atomic transactions) where supported.
Increment current header version to 2
     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 	memcpy(buffer, p1, size);
   124 	memcpy(p1, p2, size);
   125 	memcpy(p2, buffer, size);
   126 }
   127 
   128 static void
   129 __qsort_with_data(void *base, size_t nelem, uint32_t *map,
   130 		  struct qsort_context *ctx)
   131 {
   132 	void *p, *start, *end, *pivot;
   133 	uint32_t *mp, *mstart, *mend, tmp;
   134 	int left, right, result;
   135 	size_t size = ctx->size;
   136 
   137 	p = base;
   138 	start = base;
   139 	end = base + nelem * size;
   140 	mp = map;
   141 	mstart = map;
   142 	mend = map + nelem;
   143 	pivot = base + (rand() % nelem) * size;
   144 
   145 	while (p < end) {
   146 		result = ctx->compare(p, pivot, ctx->data);
   147 		if (result < 0) {
   148 			qsort_swap(p, start, size);
   149 			tmp = *mp;
   150 			*mp = *mstart;
   151 			*mstart = tmp;
   152 			if (start == pivot)
   153 				pivot = p;
   154 			start += size;
   155 			mstart++;
   156 			p += size;
   157 			mp++;
   158 		} else if (result == 0) {
   159 			p += size;
   160 			mp++;
   161 		} else {
   162  			end -= size;
   163 			mend--;
   164 			qsort_swap(p, end, size);
   165 			tmp = *mp;
   166 			*mp = *mend;
   167 			*mend = tmp;
   168 			if (end == pivot)
   169 				pivot = p;
   170 		}
   171 	}
   172 
   173 	left = (start - base) / size;
   174 	right = (base + nelem * size - end) / size;
   175 	if (left > 1)
   176 		__qsort_with_data(base, left, map, ctx);
   177 	if (right > 1)
   178 		__qsort_with_data(end, right, mend, ctx);
   179 }
   180 
   181 uint32_t *
   182 razor_qsort_with_data(void *base, size_t nelem, size_t size,
   183 		      razor_compare_with_data_func_t compare, void *data)
   184 {
   185 	struct qsort_context ctx;
   186 	uint32_t *map;
   187 	int i;
   188 
   189 	if (nelem == 0)
   190 		return NULL;
   191 
   192 	ctx.size = size;
   193 	ctx.compare = compare;
   194 	ctx.data = data;
   195 
   196 	map = malloc(nelem * sizeof (uint32_t));
   197 	for (i = 0; i < nelem; i++)
   198 		map[i] = i;
   199 
   200 	__qsort_with_data(base, nelem, map, &ctx);
   201 
   202 	return map;
   203 }
   204 
   205 void environment_init(struct environment *env)
   206 {
   207 	env->is_set = 0;
   208 	array_init(&env->string_pool);
   209 	array_init(&env->vars);
   210 }
   211 
   212 void environment_add_variable(struct environment *env,
   213 			      const char *variable, const char *value)
   214 {
   215 	char *s;
   216 	uint32_t *r;
   217 	assert(!env->is_set);
   218 
   219 	s = array_add(&env->string_pool,
   220 		      strlen(variable) + strlen(value) + 2);
   221 	sprintf(s, "%s=%s", variable, value);
   222 	r = array_add(&env->vars, sizeof *r);
   223 	*r = s - (char *)env->string_pool.data;
   224 }
   225 
   226 void environment_set(struct environment *env)
   227 {
   228 	int i, count;
   229 	char *s;
   230         uint32_t *r;
   231 
   232 	if (!env->is_set) {
   233 		count = env->vars.size / sizeof(uint32_t);
   234 		r = (uint32_t *)env->vars.data;
   235 		for (i = 0; i < count; i++) {
   236 			s = env->string_pool.data + *r++;
   237 			putenv(s);
   238 		}
   239 
   240 		env->is_set = 1;
   241 	}
   242 }
   243 
   244 void environment_unset(struct environment *env)
   245 {
   246 	int i, count;
   247 	char c, *s, *t;
   248         uint32_t *r;
   249 
   250 	if (env->is_set) {
   251 		count = env->vars.size / sizeof(uint32_t);
   252 		r = (uint32_t *)env->vars.data;
   253 		for (i = 0; i < count; i++) {
   254 			s = env->string_pool.data + *r++;
   255 			t = strchr(s, '=') + 1;
   256 			c = *t;
   257 			*t = '\0';
   258 			putenv(s);
   259 			*t = c;
   260 		}
   261 
   262 		env->is_set = 0;
   263 	}
   264 }
   265 
   266 void environment_release(struct environment *env)
   267 {
   268 	environment_unset(env);
   269 	array_release(&env->string_pool);
   270 	array_release(&env->vars);
   271 }
   272 
   273 RAZOR_EXPORT char *razor_concat(const char *s, ...)
   274 {
   275 	va_list args;
   276 	const char *string;
   277 	char *concat;
   278 	size_t n, len;
   279 
   280 	va_start(args, s);
   281 
   282 	len = strlen(s);
   283 	while((string = va_arg(args, const char *)))
   284 		len += strlen(string);
   285 
   286 	va_end(args);
   287 
   288 	concat = malloc(len + 1);
   289 
   290 	if (!concat)
   291 		return NULL;
   292 
   293 	va_start(args, s);
   294 
   295 	len = strlen(s);
   296 	memcpy(concat, s, len);
   297 	n = len;
   298 	while((string = va_arg(args, const char *))) {
   299 		len = strlen(string);
   300 		memcpy(concat + n, string, len);
   301 		n += len;
   302 	}
   303 
   304 	va_end(args);
   305 
   306 	concat[n] = '\0';
   307 
   308 	return concat;
   309 }
   310 
   311 RAZOR_EXPORT const char *razor_system_arch(void)
   312 {
   313 #ifdef MSWIN_API
   314 	SYSTEM_INFO si;
   315 
   316 	GetNativeSystemInfo(&si);
   317 	switch(si.wProcessorArchitecture)
   318 	{
   319 		case PROCESSOR_ARCHITECTURE_INTEL:
   320 			return "i686";
   321 		case PROCESSOR_ARCHITECTURE_AMD64:
   322 			return "x86_64";
   323 		default:
   324 			return NULL;
   325 	}
   326 #else
   327 	static struct utsname un;
   328 
   329 	if (uname(&un))
   330 		return NULL;
   331 	else
   332 		return un.machine;
   333 #endif
   334 }