librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Feb 09 20:45:27 2012 +0000 (2012-02-09)
changeset 418 33b825d3128d
parent 406 5ab137def3d1
child 424 8cbc438cc298
permissions -rw-r--r--
Add transaction barriers
These allow packages to be installed and removed which have scripts
that depend on each other when atomic transactions are involved.
Note that yum supports pre, but not other requires flags. post will
need similar support to the post scripts themselves pulling in the
requires flags from the rpms. Likewise preun and postun will need
similar handling to those scrips since the requires flags will need
to be stored in the razor database.
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 */