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