librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Aug 23 11:13:48 2014 +0100 (2014-08-23)
changeset 440 48204dea0b9f
parent 416 d0aa9e0a6d04
child 441 cf499fd51df7
permissions -rw-r--r--
Remove INTLLIBS from librazor_la_LIBADD.

This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  * Copyright (C) 2009, 2011, 2012  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 zalloc(size_t size)
    56 {
    57 	void *p;
    58 
    59 	p = malloc(size);
    60 	memset(p, 0, size);
    61 
    62 	return p;
    63 }
    64 
    65 void *
    66 razor_file_get_contents(const char *filename, size_t *length, int private,
    67 			struct razor_error **error)
    68 {
    69 	int fd;
    70 	struct stat st;
    71 	void *addr = NULL;
    72 	size_t nb;
    73 	ssize_t res;
    74 
    75 	fd = open(filename, O_RDONLY | O_BINARY);
    76 	if (fd < 0) {
    77 		razor_set_error(error, filename, strerror(errno));
    78 		return NULL;
    79 	}
    80 
    81 	if (fstat(fd, &st) < 0) {
    82 		razor_set_error(error, filename, strerror(errno));
    83 		close(fd);
    84 		return NULL;
    85 	}
    86 
    87 	*length = st.st_size;
    88 #if HAVE_SYS_MMAN_H
    89 	if (!private) {
    90 		addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    91 		if (addr == MAP_FAILED)
    92 			addr = NULL;
    93 	}
    94 #endif
    95 	if (!addr) {
    96 		addr = malloc(st.st_size);
    97 		if (addr) {
    98 			nb = 0;
    99 			while(nb < st.st_size) {
   100 				res = read(fd, addr + nb, st.st_size - nb);
   101 				if (res <= 0) {
   102 					razor_set_error(error, filename,
   103 							strerror(errno));
   104 					free(addr);
   105 					addr = NULL;
   106 					break;
   107 				}
   108 				nb += res;
   109 			}
   110 		} else
   111 			razor_set_error(error, NULL, "Not enough memory");
   112 	}
   113 	close(fd);
   114 
   115 	return addr;
   116 }
   117 
   118 int razor_file_free_contents(void *addr, size_t length)
   119 {
   120 #if HAVE_SYS_MMAN_H
   121 	return munmap(addr, length);
   122 #else
   123 	free(addr);
   124 	return 0;
   125 #endif
   126 }
   127 
   128 struct qsort_context {
   129 	size_t size;
   130 	razor_compare_with_data_func_t compare;
   131 	void *data;
   132 };
   133 
   134 static void
   135 qsort_swap(void *p1, void *p2, size_t size)
   136 {
   137 	char buffer[size];
   138 
   139 	if (p1 != p2) {
   140 		memcpy(buffer, p1, size);
   141 		memcpy(p1, p2, size);
   142 		memcpy(p2, buffer, size);
   143 	}
   144 }
   145 
   146 static void
   147 __qsort_with_data(void *base, size_t nelem, uint32_t *map,
   148 		  struct qsort_context *ctx)
   149 {
   150 	void *p, *start, *end, *pivot;
   151 	uint32_t *mp, *mstart, *mend, tmp;
   152 	int left, right, result;
   153 	size_t size = ctx->size;
   154 
   155 	p = base;
   156 	start = base;
   157 	end = base + nelem * size;
   158 	mp = map;
   159 	mstart = map;
   160 	mend = map + nelem;
   161 	pivot = base + (rand() % nelem) * size;
   162 
   163 	while (p < end) {
   164 		result = ctx->compare(p, pivot, ctx->data);
   165 		if (result < 0) {
   166 			qsort_swap(p, start, size);
   167 			tmp = *mp;
   168 			*mp = *mstart;
   169 			*mstart = tmp;
   170 			if (start == pivot)
   171 				pivot = p;
   172 			start += size;
   173 			mstart++;
   174 			p += size;
   175 			mp++;
   176 		} else if (result == 0) {
   177 			p += size;
   178 			mp++;
   179 		} else {
   180  			end -= size;
   181 			mend--;
   182 			qsort_swap(p, end, size);
   183 			tmp = *mp;
   184 			*mp = *mend;
   185 			*mend = tmp;
   186 			if (end == pivot)
   187 				pivot = p;
   188 		}
   189 	}
   190 
   191 	left = (start - base) / size;
   192 	right = (base + nelem * size - end) / size;
   193 	if (left > 1)
   194 		__qsort_with_data(base, left, map, ctx);
   195 	if (right > 1)
   196 		__qsort_with_data(end, right, mend, ctx);
   197 }
   198 
   199 uint32_t *
   200 razor_qsort_with_data(void *base, size_t nelem, size_t size,
   201 		      razor_compare_with_data_func_t compare, void *data)
   202 {
   203 	struct qsort_context ctx;
   204 	uint32_t *map;
   205 	int i;
   206 
   207 	if (nelem == 0)
   208 		return NULL;
   209 
   210 	ctx.size = size;
   211 	ctx.compare = compare;
   212 	ctx.data = data;
   213 
   214 	map = malloc(nelem * sizeof (uint32_t));
   215 	for (i = 0; i < nelem; i++)
   216 		map[i] = i;
   217 
   218 	__qsort_with_data(base, nelem, map, &ctx);
   219 
   220 	return map;
   221 }
   222 
   223 void environment_init(struct environment *env)
   224 {
   225 	env->is_set = 0;
   226 	array_init(&env->string_pool);
   227 	array_init(&env->vars);
   228 }
   229 
   230 void environment_add_variable(struct environment *env,
   231 			      const char *variable, const char *value)
   232 {
   233 	char *s;
   234 	uint32_t *r;
   235 	assert(!env->is_set);
   236 
   237 	s = array_add(&env->string_pool,
   238 		      strlen(variable) + strlen(value) + 2);
   239 	sprintf(s, "%s=%s", variable, value);
   240 	r = array_add(&env->vars, sizeof *r);
   241 	*r = s - (char *)env->string_pool.data;
   242 }
   243 
   244 void environment_set(struct environment *env)
   245 {
   246 	int i, count;
   247 	char *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 #ifdef WIN32
   256 			putenv(s);
   257 #else
   258 			t = strchr(s, '=');
   259 			*t = '\0';
   260 			setenv(s, t + 1, 1);
   261 			*t = '=';
   262 #endif
   263 		}
   264 
   265 		env->is_set = 1;
   266 	}
   267 }
   268 
   269 void environment_unset(struct environment *env)
   270 {
   271 	int i, count;
   272 	char c, *s, *t;
   273         uint32_t *r;
   274 
   275 	if (env->is_set) {
   276 		count = env->vars.size / sizeof(uint32_t);
   277 		r = (uint32_t *)env->vars.data;
   278 		for (i = 0; i < count; i++) {
   279 			s = env->string_pool.data + *r++;
   280 			t = strchr(s, '=');
   281 #ifdef WIN32
   282 			t++;
   283 			c = *t;
   284 			*t = '\0';
   285 			putenv(s);
   286 			*t = c;
   287 #else
   288 			c = *t;
   289 			*t = '\0';
   290 			unsetenv(s);
   291 			*t = c;
   292 #endif
   293 		}
   294 
   295 		env->is_set = 0;
   296 	}
   297 }
   298 
   299 void environment_release(struct environment *env)
   300 {
   301 	environment_unset(env);
   302 	array_release(&env->string_pool);
   303 	array_release(&env->vars);
   304 }
   305 
   306 RAZOR_EXPORT char *razor_concat(const char *s, ...)
   307 {
   308 	va_list args;
   309 	const char *string;
   310 	char *concat;
   311 	size_t n, len;
   312 
   313 	va_start(args, s);
   314 
   315 	len = strlen(s);
   316 	while((string = va_arg(args, const char *)))
   317 		len += strlen(string);
   318 
   319 	va_end(args);
   320 
   321 	concat = malloc(len + 1);
   322 
   323 	if (!concat)
   324 		return NULL;
   325 
   326 	va_start(args, s);
   327 
   328 	len = strlen(s);
   329 	memcpy(concat, s, len);
   330 	n = len;
   331 	while((string = va_arg(args, const char *))) {
   332 		len = strlen(string);
   333 		memcpy(concat + n, string, len);
   334 		n += len;
   335 	}
   336 
   337 	va_end(args);
   338 
   339 	concat[n] = '\0';
   340 
   341 	return concat;
   342 }
   343 
   344 RAZOR_EXPORT const char *razor_system_arch(void)
   345 {
   346 #ifdef MSWIN_API
   347 	SYSTEM_INFO si;
   348 
   349 	GetNativeSystemInfo(&si);
   350 	switch(si.wProcessorArchitecture)
   351 	{
   352 		case PROCESSOR_ARCHITECTURE_INTEL:
   353 			return "i686";
   354 		case PROCESSOR_ARCHITECTURE_AMD64:
   355 			return "x86_64";
   356 		default:
   357 			return NULL;
   358 	}
   359 #else
   360 	static struct utsname un;
   361 
   362 	if (uname(&un))
   363 		return NULL;
   364 	else
   365 		return un.machine;
   366 #endif
   367 }
   368 
   369 #ifdef MSWIN_API
   370 
   371 char *razor_utf16_to_utf8(const wchar_t *utf16, int len)
   372 {
   373 	int n;
   374 	char *utf8;
   375 
   376 	n = WideCharToMultiByte(CP_UTF8, 0, utf16, len, NULL, 0, NULL, NULL);
   377 	if (len >= 0 && utf16[len])
   378 		n++;
   379 	utf8 = malloc(n);
   380 	(void)WideCharToMultiByte(CP_UTF8, 0, utf16, len, utf8, n, NULL, NULL);
   381 	if (len >= 0 && utf16[len])
   382 		utf8[n - 1] = 0;
   383 
   384 	return utf8;
   385 }
   386 
   387 wchar_t *razor_utf8_to_utf16(const char *utf8, int len)
   388 {
   389 	int n;
   390 	wchar_t *utf16;
   391 
   392 	n = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
   393 	if (len >= 0 && utf8[len])
   394 		n++;
   395 	utf16 = malloc(n * sizeof(wchar_t));
   396 	(void)MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, n);
   397 	if (len >= 0 && utf8[len])
   398 		utf16[n - 1] = 0;
   399 
   400 	return utf16;
   401 }
   402 
   403 #endif	/* MSWIN_API */