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