librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Jul 04 10:48:18 2016 +0100 (2016-07-04)
changeset 475 008c75a5e08d
parent 458 3f841a46eab5
child 477 6ba4c0f3c9d1
permissions -rw-r--r--
Switch to a URI-based API
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@475
     4
 * Copyright (C) 2009, 2011, 2012, 2014, 2016  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>
rhughes@241
    25
#include <stdlib.h>
rhughes@241
    26
#include <stdio.h>
rhughes@241
    27
#include <stdint.h>
ali@339
    28
#include <errno.h>
rhughes@241
    29
#include <unistd.h>
ali@475
    30
#ifndef MSWIN_API
ali@403
    31
#include <sys/utsname.h>
ali@359
    32
#endif
ali@372
    33
#include <assert.h>
rhughes@241
    34
ali@359
    35
#include "razor.h"
ali@475
    36
#include "types/types.h"
rhughes@241
    37
#include "razor-internal.h"
rhughes@241
    38
ali@338
    39
/* Required by gnulib on non-libc platforms */
ali@338
    40
char *program_name = "librazor";
ali@338
    41
ali@322
    42
void *
ali@424
    43
zalloc(size_t size)
ali@424
    44
{
ali@424
    45
	void *p;
ali@424
    46
ali@424
    47
	p = malloc(size);
ali@424
    48
	memset(p, 0, size);
ali@424
    49
ali@424
    50
	return p;
ali@424
    51
}
ali@424
    52
rhughes@241
    53
struct qsort_context {
rhughes@241
    54
	size_t size;
rhughes@241
    55
	razor_compare_with_data_func_t compare;
rhughes@241
    56
	void *data;
rhughes@241
    57
};
rhughes@241
    58
rhughes@241
    59
static void
rhughes@241
    60
qsort_swap(void *p1, void *p2, size_t size)
rhughes@241
    61
{
rhughes@241
    62
	char buffer[size];
rhughes@241
    63
ali@406
    64
	if (p1 != p2) {
ali@406
    65
		memcpy(buffer, p1, size);
ali@406
    66
		memcpy(p1, p2, size);
ali@406
    67
		memcpy(p2, buffer, size);
ali@406
    68
	}
rhughes@241
    69
}
rhughes@241
    70
rhughes@241
    71
static void
rhughes@241
    72
__qsort_with_data(void *base, size_t nelem, uint32_t *map,
rhughes@241
    73
		  struct qsort_context *ctx)
rhughes@241
    74
{
rhughes@241
    75
	void *p, *start, *end, *pivot;
rhughes@241
    76
	uint32_t *mp, *mstart, *mend, tmp;
rhughes@241
    77
	int left, right, result;
rhughes@241
    78
	size_t size = ctx->size;
rhughes@241
    79
rhughes@241
    80
	p = base;
rhughes@241
    81
	start = base;
rhughes@241
    82
	end = base + nelem * size;
rhughes@241
    83
	mp = map;
rhughes@241
    84
	mstart = map;
rhughes@241
    85
	mend = map + nelem;
ali@337
    86
	pivot = base + (rand() % nelem) * size;
rhughes@241
    87
rhughes@241
    88
	while (p < end) {
rhughes@241
    89
		result = ctx->compare(p, pivot, ctx->data);
rhughes@241
    90
		if (result < 0) {
rhughes@241
    91
			qsort_swap(p, start, size);
rhughes@241
    92
			tmp = *mp;
rhughes@241
    93
			*mp = *mstart;
rhughes@241
    94
			*mstart = tmp;
rhughes@241
    95
			if (start == pivot)
rhughes@241
    96
				pivot = p;
rhughes@241
    97
			start += size;
rhughes@241
    98
			mstart++;
rhughes@241
    99
			p += size;
rhughes@241
   100
			mp++;
rhughes@241
   101
		} else if (result == 0) {
rhughes@241
   102
			p += size;
rhughes@241
   103
			mp++;
rhughes@241
   104
		} else {
rhughes@241
   105
 			end -= size;
rhughes@241
   106
			mend--;
rhughes@241
   107
			qsort_swap(p, end, size);
rhughes@241
   108
			tmp = *mp;
rhughes@241
   109
			*mp = *mend;
rhughes@241
   110
			*mend = tmp;
rhughes@241
   111
			if (end == pivot)
rhughes@241
   112
				pivot = p;
rhughes@241
   113
		}
rhughes@241
   114
	}
rhughes@241
   115
rhughes@241
   116
	left = (start - base) / size;
rhughes@241
   117
	right = (base + nelem * size - end) / size;
rhughes@241
   118
	if (left > 1)
rhughes@241
   119
		__qsort_with_data(base, left, map, ctx);
rhughes@241
   120
	if (right > 1)
rhughes@241
   121
		__qsort_with_data(end, right, mend, ctx);
rhughes@241
   122
}
rhughes@241
   123
rhughes@241
   124
uint32_t *
rhughes@241
   125
razor_qsort_with_data(void *base, size_t nelem, size_t size,
rhughes@241
   126
		      razor_compare_with_data_func_t compare, void *data)
rhughes@241
   127
{
rhughes@241
   128
	struct qsort_context ctx;
rhughes@241
   129
	uint32_t *map;
rhughes@241
   130
	int i;
rhughes@241
   131
rhughes@241
   132
	if (nelem == 0)
rhughes@241
   133
		return NULL;
rhughes@241
   134
rhughes@241
   135
	ctx.size = size;
rhughes@241
   136
	ctx.compare = compare;
rhughes@241
   137
	ctx.data = data;
rhughes@241
   138
rhughes@241
   139
	map = malloc(nelem * sizeof (uint32_t));
rhughes@241
   140
	for (i = 0; i < nelem; i++)
rhughes@241
   141
		map[i] = i;
rhughes@241
   142
rhughes@241
   143
	__qsort_with_data(base, nelem, map, &ctx);
rhughes@241
   144
rhughes@241
   145
	return map;
rhughes@241
   146
}
ali@372
   147
ali@372
   148
void environment_init(struct environment *env)
ali@372
   149
{
ali@372
   150
	env->is_set = 0;
ali@372
   151
	array_init(&env->string_pool);
ali@372
   152
	array_init(&env->vars);
ali@372
   153
}
ali@372
   154
ali@372
   155
void environment_add_variable(struct environment *env,
ali@372
   156
			      const char *variable, const char *value)
ali@372
   157
{
ali@372
   158
	char *s;
ali@372
   159
	uint32_t *r;
ali@372
   160
	assert(!env->is_set);
ali@372
   161
ali@372
   162
	s = array_add(&env->string_pool,
ali@372
   163
		      strlen(variable) + strlen(value) + 2);
ali@372
   164
	sprintf(s, "%s=%s", variable, value);
ali@372
   165
	r = array_add(&env->vars, sizeof *r);
ali@372
   166
	*r = s - (char *)env->string_pool.data;
ali@372
   167
}
ali@372
   168
ali@372
   169
void environment_set(struct environment *env)
ali@372
   170
{
ali@372
   171
	int i, count;
ali@442
   172
	char *s;
ali@442
   173
#ifndef WIN32
ali@442
   174
	char *t;
ali@442
   175
#endif
ali@372
   176
        uint32_t *r;
ali@372
   177
ali@372
   178
	if (!env->is_set) {
ali@372
   179
		count = env->vars.size / sizeof(uint32_t);
ali@372
   180
		r = (uint32_t *)env->vars.data;
ali@372
   181
		for (i = 0; i < count; i++) {
ali@372
   182
			s = env->string_pool.data + *r++;
ali@406
   183
#ifdef WIN32
ali@372
   184
			putenv(s);
ali@406
   185
#else
ali@406
   186
			t = strchr(s, '=');
ali@406
   187
			*t = '\0';
ali@406
   188
			setenv(s, t + 1, 1);
ali@406
   189
			*t = '=';
ali@406
   190
#endif
ali@372
   191
		}
ali@372
   192
ali@372
   193
		env->is_set = 1;
ali@372
   194
	}
ali@372
   195
}
ali@372
   196
ali@372
   197
void environment_unset(struct environment *env)
ali@372
   198
{
ali@372
   199
	int i, count;
ali@372
   200
	char c, *s, *t;
ali@372
   201
        uint32_t *r;
ali@372
   202
ali@372
   203
	if (env->is_set) {
ali@372
   204
		count = env->vars.size / sizeof(uint32_t);
ali@372
   205
		r = (uint32_t *)env->vars.data;
ali@372
   206
		for (i = 0; i < count; i++) {
ali@372
   207
			s = env->string_pool.data + *r++;
ali@406
   208
			t = strchr(s, '=');
ali@406
   209
#ifdef WIN32
ali@406
   210
			t++;
ali@372
   211
			c = *t;
ali@372
   212
			*t = '\0';
ali@372
   213
			putenv(s);
ali@372
   214
			*t = c;
ali@406
   215
#else
ali@406
   216
			c = *t;
ali@406
   217
			*t = '\0';
ali@406
   218
			unsetenv(s);
ali@406
   219
			*t = c;
ali@406
   220
#endif
ali@372
   221
		}
ali@372
   222
ali@372
   223
		env->is_set = 0;
ali@372
   224
	}
ali@372
   225
}
ali@372
   226
ali@372
   227
void environment_release(struct environment *env)
ali@372
   228
{
ali@372
   229
	environment_unset(env);
ali@372
   230
	array_release(&env->string_pool);
ali@372
   231
	array_release(&env->vars);
ali@372
   232
}
ali@403
   233
ali@403
   234
RAZOR_EXPORT char *razor_concat(const char *s, ...)
ali@403
   235
{
ali@403
   236
	va_list args;
ali@403
   237
	const char *string;
ali@403
   238
	char *concat;
ali@403
   239
	size_t n, len;
ali@403
   240
ali@403
   241
	va_start(args, s);
ali@403
   242
ali@403
   243
	len = strlen(s);
ali@403
   244
	while((string = va_arg(args, const char *)))
ali@403
   245
		len += strlen(string);
ali@403
   246
ali@403
   247
	va_end(args);
ali@403
   248
ali@403
   249
	concat = malloc(len + 1);
ali@403
   250
ali@403
   251
	if (!concat)
ali@403
   252
		return NULL;
ali@403
   253
ali@403
   254
	va_start(args, s);
ali@403
   255
ali@403
   256
	len = strlen(s);
ali@403
   257
	memcpy(concat, s, len);
ali@403
   258
	n = len;
ali@403
   259
	while((string = va_arg(args, const char *))) {
ali@403
   260
		len = strlen(string);
ali@403
   261
		memcpy(concat + n, string, len);
ali@403
   262
		n += len;
ali@403
   263
	}
ali@403
   264
ali@403
   265
	va_end(args);
ali@403
   266
ali@403
   267
	concat[n] = '\0';
ali@403
   268
ali@403
   269
	return concat;
ali@403
   270
}
ali@403
   271
ali@403
   272
RAZOR_EXPORT const char *razor_system_arch(void)
ali@403
   273
{
ali@403
   274
#ifdef MSWIN_API
ali@403
   275
	SYSTEM_INFO si;
ali@403
   276
ali@403
   277
	GetNativeSystemInfo(&si);
ali@403
   278
	switch(si.wProcessorArchitecture)
ali@403
   279
	{
ali@403
   280
		case PROCESSOR_ARCHITECTURE_INTEL:
ali@403
   281
			return "i686";
ali@403
   282
		case PROCESSOR_ARCHITECTURE_AMD64:
ali@403
   283
			return "x86_64";
ali@403
   284
		default:
ali@403
   285
			return NULL;
ali@403
   286
	}
ali@403
   287
#else
ali@403
   288
	static struct utsname un;
ali@403
   289
ali@403
   290
	if (uname(&un))
ali@403
   291
		return NULL;
ali@403
   292
	else
ali@403
   293
		return un.machine;
ali@403
   294
#endif
ali@403
   295
}
ali@416
   296
ali@416
   297
#ifdef MSWIN_API
ali@416
   298
ali@416
   299
char *razor_utf16_to_utf8(const wchar_t *utf16, int len)
ali@416
   300
{
ali@416
   301
	int n;
ali@416
   302
	char *utf8;
ali@416
   303
ali@455
   304
	if (len == 0)
ali@455
   305
		return strdup("");
ali@455
   306
ali@416
   307
	n = WideCharToMultiByte(CP_UTF8, 0, utf16, len, NULL, 0, NULL, NULL);
ali@455
   308
	if (len > 0)
ali@416
   309
		n++;
ali@416
   310
	utf8 = malloc(n);
ali@416
   311
	(void)WideCharToMultiByte(CP_UTF8, 0, utf16, len, utf8, n, NULL, NULL);
ali@455
   312
	if (len > 0)
ali@416
   313
		utf8[n - 1] = 0;
ali@416
   314
ali@416
   315
	return utf8;
ali@416
   316
}
ali@416
   317
ali@416
   318
wchar_t *razor_utf8_to_utf16(const char *utf8, int len)
ali@416
   319
{
ali@416
   320
	int n;
ali@416
   321
	wchar_t *utf16;
ali@416
   322
ali@455
   323
	if (len == 0) {
ali@455
   324
		utf16 = calloc(1, sizeof(wchar_t));
ali@455
   325
		return utf16;
ali@455
   326
	}
ali@455
   327
ali@416
   328
	n = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
ali@455
   329
	if (len > 0)
ali@416
   330
		n++;
ali@416
   331
	utf16 = malloc(n * sizeof(wchar_t));
ali@416
   332
	(void)MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, n);
ali@455
   333
	if (len > 0)
ali@416
   334
		utf16[n - 1] = 0;
ali@416
   335
ali@416
   336
	return utf16;
ali@416
   337
}
ali@416
   338
ali@416
   339
#endif	/* MSWIN_API */