librazor/util.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 09 17:27:41 2014 +0100 (2014-10-09)
changeset 455 df914f383f5c
parent 447 0a5e583393e1
child 458 3f841a46eab5
permissions -rw-r--r--
Support downloading from local repository even without libcurl

Using the --url option of the razor executable, it is possible
to specify a yum repository on the local machine (eg., on installation
media) and import from there, eg.,:

C> razor --url file:///d:/ import-yum

This will be handled by libcurl if available but if not, an internal
copy routine will be used.

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