librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Tue Mar 27 21:29:53 2012 +0100 (2012-03-27)
changeset 434 2c25dc58c6d2
parent 416 d0aa9e0a6d04
child 441 cf499fd51df7
permissions -rw-r--r--
Start 0.5.6
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 */