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