librazor/util.c
author James Bowes <jbowes@redhat.com>
Wed Jul 09 10:11:13 2008 -0400 (2008-07-09)
changeset 318 829d6711b316
parent 241 c3eb520e2219
child 322 66c281524c98
permissions -rw-r--r--
Use strings to identify section types in the on-disk repo format.

Previously, a given razor file type had a fixed number of sections in a
fixed order, identified by an integer type. Now, sections are identified
by a named string (stored in a string pool after the section lists).

This will allow for razor files to contain arbitrary sections.

For bonus points, also drop the 4k section alignment and change the
magic byte string to "RZDB".

committer: Kristian H?gsberg <krh@redhat.com>
     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 }