librazor/util.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 23:13:09 2008 -0400 (2008-06-20)
changeset 257 0c3db660514d
child 300 455eaa569767
permissions -rw-r--r--
When uniquifying properties, also sort them on the owning package.

This ensures that whenever two packages provide or (or require, obsolete
or conflict) the same property, they appear in the same order in the
propertys list of packages.
     1 #include <limits.h>
     2 #include <string.h>
     3 #include <sys/stat.h>
     4 #include <stdlib.h>
     5 #include <stdio.h>
     6 #include <stdint.h>
     7 #include <unistd.h>
     8 
     9 #include "razor-internal.h"
    10 
    11 int
    12 razor_create_dir(const char *root, const char *path)
    13 {
    14 	char buffer[PATH_MAX], *p;
    15 	const char *slash, *next;
    16 	struct stat buf;
    17 
    18 	/* Create all sub-directories in dir. We know root exists and
    19 	 * is a dir, root does not end in a '/', and path has a
    20 	 * leading '/'. */
    21 
    22 	strcpy(buffer, root);
    23 	p = buffer + strlen(buffer);
    24 	slash = path;
    25 	for (slash = path; *slash != '\0'; slash = next) {
    26 		next = strchr(slash + 1, '/');
    27 		if (next == NULL)
    28 			break;
    29 
    30 		memcpy(p, slash, next - slash);
    31 		p += next - slash;
    32 		*p = '\0';
    33 
    34 		if (stat(buffer, &buf) == 0) {
    35 			if (!S_ISDIR(buf.st_mode)) {
    36 				fprintf(stderr,
    37 					"%s exists but is not a directory\n",
    38 					buffer);
    39 				return -1;
    40 			}
    41 		} else if (mkdir(buffer, 0777) < 0) {
    42 			fprintf(stderr, "failed to make directory %s: %m\n",
    43 				buffer);
    44 			return -1;
    45 		}
    46 
    47 		/* FIXME: What to do about permissions for dirs we
    48 		 * have to create but are not in the cpio archive? */
    49 	}
    50 
    51 	return 0;
    52 }
    53 
    54 int
    55 razor_write(int fd, const void *data, size_t size)
    56 {
    57 	size_t rest;
    58 	ssize_t written;
    59 	const unsigned char *p;
    60 
    61 	rest = size;
    62 	p = data;
    63 	while (rest > 0) {
    64 		written = write(fd, p, rest);
    65 		if (written < 0) {
    66 			fprintf(stderr, "write error: %m\n");
    67 			return -1;
    68 		}
    69 		rest -= written;
    70 		p += written;
    71 	}
    72 
    73 	return 0;
    74 }
    75 
    76 struct qsort_context {
    77 	size_t size;
    78 	razor_compare_with_data_func_t compare;
    79 	void *data;
    80 };
    81 
    82 static void
    83 qsort_swap(void *p1, void *p2, size_t size)
    84 {
    85 	char buffer[size];
    86 
    87 	memcpy(buffer, p1, size);
    88 	memcpy(p1, p2, size);
    89 	memcpy(p2, buffer, size);
    90 }
    91 
    92 static void
    93 __qsort_with_data(void *base, size_t nelem, uint32_t *map,
    94 		  struct qsort_context *ctx)
    95 {
    96 	void *p, *start, *end, *pivot;
    97 	uint32_t *mp, *mstart, *mend, tmp;
    98 	int left, right, result;
    99 	size_t size = ctx->size;
   100 
   101 	p = base;
   102 	start = base;
   103 	end = base + nelem * size;
   104 	mp = map;
   105 	mstart = map;
   106 	mend = map + nelem;
   107 	pivot = base + (random() % nelem) * size;
   108 
   109 	while (p < end) {
   110 		result = ctx->compare(p, pivot, ctx->data);
   111 		if (result < 0) {
   112 			qsort_swap(p, start, size);
   113 			tmp = *mp;
   114 			*mp = *mstart;
   115 			*mstart = tmp;
   116 			if (start == pivot)
   117 				pivot = p;
   118 			start += size;
   119 			mstart++;
   120 			p += size;
   121 			mp++;
   122 		} else if (result == 0) {
   123 			p += size;
   124 			mp++;
   125 		} else {
   126  			end -= size;
   127 			mend--;
   128 			qsort_swap(p, end, size);
   129 			tmp = *mp;
   130 			*mp = *mend;
   131 			*mend = tmp;
   132 			if (end == pivot)
   133 				pivot = p;
   134 		}
   135 	}
   136 
   137 	left = (start - base) / size;
   138 	right = (base + nelem * size - end) / size;
   139 	if (left > 1)
   140 		__qsort_with_data(base, left, map, ctx);
   141 	if (right > 1)
   142 		__qsort_with_data(end, right, mend, ctx);
   143 }
   144 
   145 uint32_t *
   146 razor_qsort_with_data(void *base, size_t nelem, size_t size,
   147 		      razor_compare_with_data_func_t compare, void *data)
   148 {
   149 	struct qsort_context ctx;
   150 	uint32_t *map;
   151 	int i;
   152 
   153 	if (nelem == 0)
   154 		return NULL;
   155 
   156 	ctx.size = size;
   157 	ctx.compare = compare;
   158 	ctx.data = data;
   159 
   160 	map = malloc(nelem * sizeof (uint32_t));
   161 	for (i = 0; i < nelem; i++)
   162 		map[i] = i;
   163 
   164 	__qsort_with_data(base, nelem, map, &ctx);
   165 
   166 	return map;
   167 }