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