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.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  * Copyright (C) 2009, 2011  J. Ali Harlow <ali@juiblex.co.uk>
     5  *
     6  * This program is free software; you can redistribute it and/or modify
     7  * it under the terms of the GNU General Public License as published by
     8  * the Free Software Foundation; either version 2 of the License, or
     9  * (at your option) any later version.
    10  *
    11  * This program is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  * GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along
    17  * with this program; if not, write to the Free Software Foundation, Inc.,
    18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    19  */
    20 
    21 #include "config.h"
    22 
    23 #include <limits.h>
    24 #include <string.h>
    25 #include <sys/types.h>
    26 #include <sys/stat.h>
    27 #include <stdlib.h>
    28 #include <stdio.h>
    29 #include <stdint.h>
    30 #include <errno.h>
    31 #include <unistd.h>
    32 #include <fcntl.h>
    33 #ifdef MSWIN_API
    34 #include <windows.h>
    35 #include <direct.h>
    36 #else
    37 #include <sys/utsname.h>
    38 #endif
    39 #if HAVE_SYS_MMAN_H
    40 #include <sys/mman.h>
    41 #endif
    42 #include <assert.h>
    43 
    44 #include "razor.h"
    45 #include "razor-internal.h"
    46 
    47 #ifndef O_BINARY
    48 #define O_BINARY	0
    49 #endif
    50 
    51 /* Required by gnulib on non-libc platforms */
    52 char *program_name = "librazor";
    53 
    54 void *
    55 razor_file_get_contents(const char *filename, size_t *length)
    56 {
    57 	int fd;
    58 	struct stat st;
    59 	void *addr;
    60 #if !HAVE_SYS_MMAN_H
    61 	size_t nb;
    62 	ssize_t res;
    63 #endif
    64 
    65 	fd = open(filename, O_RDONLY | O_BINARY);
    66 	if (fd < 0)
    67 		return NULL;
    68 
    69 	if (fstat(fd, &st) < 0) {
    70 		close(fd);
    71 		return NULL;
    72 	}
    73 
    74 	*length = st.st_size;
    75 #if HAVE_SYS_MMAN_H
    76 	addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    77 #else
    78 	addr = malloc(st.st_size);
    79 	if (addr) {
    80 		nb = 0;
    81 		while(nb < st.st_size) {
    82 			res = read(fd, addr + nb, st.st_size - nb);
    83 			if (res <= 0) {
    84 				free(addr);
    85 				addr = NULL;
    86 				break;
    87 			}
    88 			nb += res;
    89 		}
    90 	}
    91 #endif
    92 	close(fd);
    93 
    94 #if HAVE_SYS_MMAN_H
    95 	if (addr == MAP_FAILED)
    96 		addr = NULL;
    97 #endif
    98 
    99 	return addr;
   100 }
   101 
   102 razor_file_free_contents(void *addr, size_t length)
   103 {
   104 #if HAVE_SYS_MMAN_H
   105 	return munmap(addr, length);
   106 #else
   107 	free(addr);
   108 	return 0;
   109 #endif
   110 }
   111 
   112 struct qsort_context {
   113 	size_t size;
   114 	razor_compare_with_data_func_t compare;
   115 	void *data;
   116 };
   117 
   118 static void
   119 qsort_swap(void *p1, void *p2, size_t size)
   120 {
   121 	char buffer[size];
   122 
   123 	if (p1 != p2) {
   124 		memcpy(buffer, p1, size);
   125 		memcpy(p1, p2, size);
   126 		memcpy(p2, buffer, size);
   127 	}
   128 }
   129 
   130 static void
   131 __qsort_with_data(void *base, size_t nelem, uint32_t *map,
   132 		  struct qsort_context *ctx)
   133 {
   134 	void *p, *start, *end, *pivot;
   135 	uint32_t *mp, *mstart, *mend, tmp;
   136 	int left, right, result;
   137 	size_t size = ctx->size;
   138 
   139 	p = base;
   140 	start = base;
   141 	end = base + nelem * size;
   142 	mp = map;
   143 	mstart = map;
   144 	mend = map + nelem;
   145 	pivot = base + (rand() % nelem) * size;
   146 
   147 	while (p < end) {
   148 		result = ctx->compare(p, pivot, ctx->data);
   149 		if (result < 0) {
   150 			qsort_swap(p, start, size);
   151 			tmp = *mp;
   152 			*mp = *mstart;
   153 			*mstart = tmp;
   154 			if (start == pivot)
   155 				pivot = p;
   156 			start += size;
   157 			mstart++;
   158 			p += size;
   159 			mp++;
   160 		} else if (result == 0) {
   161 			p += size;
   162 			mp++;
   163 		} else {
   164  			end -= size;
   165 			mend--;
   166 			qsort_swap(p, end, size);
   167 			tmp = *mp;
   168 			*mp = *mend;
   169 			*mend = tmp;
   170 			if (end == pivot)
   171 				pivot = p;
   172 		}
   173 	}
   174 
   175 	left = (start - base) / size;
   176 	right = (base + nelem * size - end) / size;
   177 	if (left > 1)
   178 		__qsort_with_data(base, left, map, ctx);
   179 	if (right > 1)
   180 		__qsort_with_data(end, right, mend, ctx);
   181 }
   182 
   183 uint32_t *
   184 razor_qsort_with_data(void *base, size_t nelem, size_t size,
   185 		      razor_compare_with_data_func_t compare, void *data)
   186 {
   187 	struct qsort_context ctx;
   188 	uint32_t *map;
   189 	int i;
   190 
   191 	if (nelem == 0)
   192 		return NULL;
   193 
   194 	ctx.size = size;
   195 	ctx.compare = compare;
   196 	ctx.data = data;
   197 
   198 	map = malloc(nelem * sizeof (uint32_t));
   199 	for (i = 0; i < nelem; i++)
   200 		map[i] = i;
   201 
   202 	__qsort_with_data(base, nelem, map, &ctx);
   203 
   204 	return map;
   205 }
   206 
   207 void environment_init(struct environment *env)
   208 {
   209 	env->is_set = 0;
   210 	array_init(&env->string_pool);
   211 	array_init(&env->vars);
   212 }
   213 
   214 void environment_add_variable(struct environment *env,
   215 			      const char *variable, const char *value)
   216 {
   217 	char *s;
   218 	uint32_t *r;
   219 	assert(!env->is_set);
   220 
   221 	s = array_add(&env->string_pool,
   222 		      strlen(variable) + strlen(value) + 2);
   223 	sprintf(s, "%s=%s", variable, value);
   224 	r = array_add(&env->vars, sizeof *r);
   225 	*r = s - (char *)env->string_pool.data;
   226 }
   227 
   228 void environment_set(struct environment *env)
   229 {
   230 	int i, count;
   231 	char *s, *t;
   232         uint32_t *r;
   233 
   234 	if (!env->is_set) {
   235 		count = env->vars.size / sizeof(uint32_t);
   236 		r = (uint32_t *)env->vars.data;
   237 		for (i = 0; i < count; i++) {
   238 			s = env->string_pool.data + *r++;
   239 #ifdef WIN32
   240 			putenv(s);
   241 #else
   242 			t = strchr(s, '=');
   243 			*t = '\0';
   244 			setenv(s, t + 1, 1);
   245 			*t = '=';
   246 #endif
   247 		}
   248 
   249 		env->is_set = 1;
   250 	}
   251 }
   252 
   253 void environment_unset(struct environment *env)
   254 {
   255 	int i, count;
   256 	char c, *s, *t;
   257         uint32_t *r;
   258 
   259 	if (env->is_set) {
   260 		count = env->vars.size / sizeof(uint32_t);
   261 		r = (uint32_t *)env->vars.data;
   262 		for (i = 0; i < count; i++) {
   263 			s = env->string_pool.data + *r++;
   264 			t = strchr(s, '=');
   265 #ifdef WIN32
   266 			t++;
   267 			c = *t;
   268 			*t = '\0';
   269 			putenv(s);
   270 			*t = c;
   271 #else
   272 			c = *t;
   273 			*t = '\0';
   274 			unsetenv(s);
   275 			*t = c;
   276 #endif
   277 		}
   278 
   279 		env->is_set = 0;
   280 	}
   281 }
   282 
   283 void environment_release(struct environment *env)
   284 {
   285 	environment_unset(env);
   286 	array_release(&env->string_pool);
   287 	array_release(&env->vars);
   288 }
   289 
   290 RAZOR_EXPORT char *razor_concat(const char *s, ...)
   291 {
   292 	va_list args;
   293 	const char *string;
   294 	char *concat;
   295 	size_t n, len;
   296 
   297 	va_start(args, s);
   298 
   299 	len = strlen(s);
   300 	while((string = va_arg(args, const char *)))
   301 		len += strlen(string);
   302 
   303 	va_end(args);
   304 
   305 	concat = malloc(len + 1);
   306 
   307 	if (!concat)
   308 		return NULL;
   309 
   310 	va_start(args, s);
   311 
   312 	len = strlen(s);
   313 	memcpy(concat, s, len);
   314 	n = len;
   315 	while((string = va_arg(args, const char *))) {
   316 		len = strlen(string);
   317 		memcpy(concat + n, string, len);
   318 		n += len;
   319 	}
   320 
   321 	va_end(args);
   322 
   323 	concat[n] = '\0';
   324 
   325 	return concat;
   326 }
   327 
   328 RAZOR_EXPORT const char *razor_system_arch(void)
   329 {
   330 #ifdef MSWIN_API
   331 	SYSTEM_INFO si;
   332 
   333 	GetNativeSystemInfo(&si);
   334 	switch(si.wProcessorArchitecture)
   335 	{
   336 		case PROCESSOR_ARCHITECTURE_INTEL:
   337 			return "i686";
   338 		case PROCESSOR_ARCHITECTURE_AMD64:
   339 			return "x86_64";
   340 		default:
   341 			return NULL;
   342 	}
   343 #else
   344 	static struct utsname un;
   345 
   346 	if (uname(&un))
   347 		return NULL;
   348 	else
   349 		return un.machine;
   350 #endif
   351 }
   352 
   353 #ifdef MSWIN_API
   354 
   355 char *razor_utf16_to_utf8(const wchar_t *utf16, int len)
   356 {
   357 	int n;
   358 	char *utf8;
   359 
   360 	n = WideCharToMultiByte(CP_UTF8, 0, utf16, len, NULL, 0, NULL, NULL);
   361 	if (len >= 0 && utf16[len])
   362 		n++;
   363 	utf8 = malloc(n);
   364 	(void)WideCharToMultiByte(CP_UTF8, 0, utf16, len, utf8, n, NULL, NULL);
   365 	if (len >= 0 && utf16[len])
   366 		utf8[n - 1] = 0;
   367 
   368 	return utf8;
   369 }
   370 
   371 wchar_t *razor_utf8_to_utf16(const char *utf8, int len)
   372 {
   373 	int n;
   374 	wchar_t *utf16;
   375 
   376 	n = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
   377 	if (len >= 0 && utf8[len])
   378 		n++;
   379 	utf16 = malloc(n * sizeof(wchar_t));
   380 	(void)MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, n);
   381 	if (len >= 0 && utf8[len])
   382 		utf16[n - 1] = 0;
   383 
   384 	return utf16;
   385 }
   386 
   387 #endif	/* MSWIN_API */