librazor/util.c
author Kristian H?gsberg <krh@redhat.com>
Tue Jul 08 21:59:36 2008 -0400 (2008-07-08)
changeset 315 1c52b84bfc33
parent 241 c3eb520e2219
child 322 66c281524c98
permissions -rw-r--r--
Always open all three rzdb files when we're merging package sets.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #include <limits.h>
    21 #include <string.h>
    22 #include <sys/stat.h>
    23 #include <stdlib.h>
    24 #include <stdio.h>
    25 #include <stdint.h>
    26 #include <unistd.h>
    27 
    28 #include "razor-internal.h"
    29 
    30 int
    31 razor_create_dir(const char *root, const char *path)
    32 {
    33 	char buffer[PATH_MAX], *p;
    34 	const char *slash, *next;
    35 	struct stat buf;
    36 
    37 	/* Create all sub-directories in dir. We know root exists and
    38 	 * is a dir, root does not end in a '/', and path has a
    39 	 * leading '/'. */
    40 
    41 	strcpy(buffer, root);
    42 	p = buffer + strlen(buffer);
    43 	slash = path;
    44 	for (slash = path; *slash != '\0'; slash = next) {
    45 		next = strchr(slash + 1, '/');
    46 		if (next == NULL)
    47 			break;
    48 
    49 		memcpy(p, slash, next - slash);
    50 		p += next - slash;
    51 		*p = '\0';
    52 
    53 		if (stat(buffer, &buf) == 0) {
    54 			if (!S_ISDIR(buf.st_mode)) {
    55 				fprintf(stderr,
    56 					"%s exists but is not a directory\n",
    57 					buffer);
    58 				return -1;
    59 			}
    60 		} else if (mkdir(buffer, 0777) < 0) {
    61 			fprintf(stderr, "failed to make directory %s: %m\n",
    62 				buffer);
    63 			return -1;
    64 		}
    65 
    66 		/* FIXME: What to do about permissions for dirs we
    67 		 * have to create but are not in the cpio archive? */
    68 	}
    69 
    70 	return 0;
    71 }
    72 
    73 int
    74 razor_write(int fd, const void *data, size_t size)
    75 {
    76 	size_t rest;
    77 	ssize_t written;
    78 	const unsigned char *p;
    79 
    80 	rest = size;
    81 	p = data;
    82 	while (rest > 0) {
    83 		written = write(fd, p, rest);
    84 		if (written < 0) {
    85 			fprintf(stderr, "write error: %m\n");
    86 			return -1;
    87 		}
    88 		rest -= written;
    89 		p += written;
    90 	}
    91 
    92 	return 0;
    93 }
    94 
    95 struct qsort_context {
    96 	size_t size;
    97 	razor_compare_with_data_func_t compare;
    98 	void *data;
    99 };
   100 
   101 static void
   102 qsort_swap(void *p1, void *p2, size_t size)
   103 {
   104 	char buffer[size];
   105 
   106 	memcpy(buffer, p1, size);
   107 	memcpy(p1, p2, size);
   108 	memcpy(p2, buffer, size);
   109 }
   110 
   111 static void
   112 __qsort_with_data(void *base, size_t nelem, uint32_t *map,
   113 		  struct qsort_context *ctx)
   114 {
   115 	void *p, *start, *end, *pivot;
   116 	uint32_t *mp, *mstart, *mend, tmp;
   117 	int left, right, result;
   118 	size_t size = ctx->size;
   119 
   120 	p = base;
   121 	start = base;
   122 	end = base + nelem * size;
   123 	mp = map;
   124 	mstart = map;
   125 	mend = map + nelem;
   126 	pivot = base + (random() % nelem) * size;
   127 
   128 	while (p < end) {
   129 		result = ctx->compare(p, pivot, ctx->data);
   130 		if (result < 0) {
   131 			qsort_swap(p, start, size);
   132 			tmp = *mp;
   133 			*mp = *mstart;
   134 			*mstart = tmp;
   135 			if (start == pivot)
   136 				pivot = p;
   137 			start += size;
   138 			mstart++;
   139 			p += size;
   140 			mp++;
   141 		} else if (result == 0) {
   142 			p += size;
   143 			mp++;
   144 		} else {
   145  			end -= size;
   146 			mend--;
   147 			qsort_swap(p, end, size);
   148 			tmp = *mp;
   149 			*mp = *mend;
   150 			*mend = tmp;
   151 			if (end == pivot)
   152 				pivot = p;
   153 		}
   154 	}
   155 
   156 	left = (start - base) / size;
   157 	right = (base + nelem * size - end) / size;
   158 	if (left > 1)
   159 		__qsort_with_data(base, left, map, ctx);
   160 	if (right > 1)
   161 		__qsort_with_data(end, right, mend, ctx);
   162 }
   163 
   164 uint32_t *
   165 razor_qsort_with_data(void *base, size_t nelem, size_t size,
   166 		      razor_compare_with_data_func_t compare, void *data)
   167 {
   168 	struct qsort_context ctx;
   169 	uint32_t *map;
   170 	int i;
   171 
   172 	if (nelem == 0)
   173 		return NULL;
   174 
   175 	ctx.size = size;
   176 	ctx.compare = compare;
   177 	ctx.data = data;
   178 
   179 	map = malloc(nelem * sizeof (uint32_t));
   180 	for (i = 0; i < nelem; i++)
   181 		map[i] = i;
   182 
   183 	__qsort_with_data(base, nelem, map, &ctx);
   184 
   185 	return map;
   186 }