util.c
author James Bowes <jbowes@redhat.com>
Sun Jun 08 11:56:11 2008 -0400 (2008-06-08)
changeset 223 e1d7ed03e5d9
parent 186 7f45d0401e37
permissions -rw-r--r--
Clean up some segfaults in the test driver
     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 }