richard@300: /* richard@300: * Copyright (C) 2008 Kristian Høgsberg richard@300: * Copyright (C) 2008 Red Hat, Inc richard@300: * richard@300: * This program is free software; you can redistribute it and/or modify richard@300: * it under the terms of the GNU General Public License as published by richard@300: * the Free Software Foundation; either version 2 of the License, or richard@300: * (at your option) any later version. richard@300: * richard@300: * This program is distributed in the hope that it will be useful, richard@300: * but WITHOUT ANY WARRANTY; without even the implied warranty of richard@300: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the richard@300: * GNU General Public License for more details. richard@300: * richard@300: * You should have received a copy of the GNU General Public License along richard@300: * with this program; if not, write to the Free Software Foundation, Inc., richard@300: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. richard@300: */ richard@300: rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: rhughes@241: #include "razor-internal.h" rhughes@241: rhughes@241: int rhughes@241: razor_create_dir(const char *root, const char *path) rhughes@241: { rhughes@241: char buffer[PATH_MAX], *p; rhughes@241: const char *slash, *next; rhughes@241: struct stat buf; rhughes@241: rhughes@241: /* Create all sub-directories in dir. We know root exists and rhughes@241: * is a dir, root does not end in a '/', and path has a rhughes@241: * leading '/'. */ rhughes@241: rhughes@241: strcpy(buffer, root); rhughes@241: p = buffer + strlen(buffer); rhughes@241: slash = path; rhughes@241: for (slash = path; *slash != '\0'; slash = next) { rhughes@241: next = strchr(slash + 1, '/'); rhughes@241: if (next == NULL) rhughes@241: break; rhughes@241: rhughes@241: memcpy(p, slash, next - slash); rhughes@241: p += next - slash; rhughes@241: *p = '\0'; rhughes@241: rhughes@241: if (stat(buffer, &buf) == 0) { rhughes@241: if (!S_ISDIR(buf.st_mode)) { rhughes@241: fprintf(stderr, rhughes@241: "%s exists but is not a directory\n", rhughes@241: buffer); rhughes@241: return -1; rhughes@241: } rhughes@241: } else if (mkdir(buffer, 0777) < 0) { rhughes@241: fprintf(stderr, "failed to make directory %s: %m\n", rhughes@241: buffer); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: /* FIXME: What to do about permissions for dirs we rhughes@241: * have to create but are not in the cpio archive? */ rhughes@241: } rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: int rhughes@241: razor_write(int fd, const void *data, size_t size) rhughes@241: { rhughes@241: size_t rest; rhughes@241: ssize_t written; rhughes@241: const unsigned char *p; rhughes@241: rhughes@241: rest = size; rhughes@241: p = data; rhughes@241: while (rest > 0) { rhughes@241: written = write(fd, p, rest); rhughes@241: if (written < 0) { rhughes@241: fprintf(stderr, "write error: %m\n"); rhughes@241: return -1; rhughes@241: } rhughes@241: rest -= written; rhughes@241: p += written; rhughes@241: } rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: struct qsort_context { rhughes@241: size_t size; rhughes@241: razor_compare_with_data_func_t compare; rhughes@241: void *data; rhughes@241: }; rhughes@241: rhughes@241: static void rhughes@241: qsort_swap(void *p1, void *p2, size_t size) rhughes@241: { rhughes@241: char buffer[size]; rhughes@241: rhughes@241: memcpy(buffer, p1, size); rhughes@241: memcpy(p1, p2, size); rhughes@241: memcpy(p2, buffer, size); rhughes@241: } rhughes@241: rhughes@241: static void rhughes@241: __qsort_with_data(void *base, size_t nelem, uint32_t *map, rhughes@241: struct qsort_context *ctx) rhughes@241: { rhughes@241: void *p, *start, *end, *pivot; rhughes@241: uint32_t *mp, *mstart, *mend, tmp; rhughes@241: int left, right, result; rhughes@241: size_t size = ctx->size; rhughes@241: rhughes@241: p = base; rhughes@241: start = base; rhughes@241: end = base + nelem * size; rhughes@241: mp = map; rhughes@241: mstart = map; rhughes@241: mend = map + nelem; rhughes@241: pivot = base + (random() % nelem) * size; rhughes@241: rhughes@241: while (p < end) { rhughes@241: result = ctx->compare(p, pivot, ctx->data); rhughes@241: if (result < 0) { rhughes@241: qsort_swap(p, start, size); rhughes@241: tmp = *mp; rhughes@241: *mp = *mstart; rhughes@241: *mstart = tmp; rhughes@241: if (start == pivot) rhughes@241: pivot = p; rhughes@241: start += size; rhughes@241: mstart++; rhughes@241: p += size; rhughes@241: mp++; rhughes@241: } else if (result == 0) { rhughes@241: p += size; rhughes@241: mp++; rhughes@241: } else { rhughes@241: end -= size; rhughes@241: mend--; rhughes@241: qsort_swap(p, end, size); rhughes@241: tmp = *mp; rhughes@241: *mp = *mend; rhughes@241: *mend = tmp; rhughes@241: if (end == pivot) rhughes@241: pivot = p; rhughes@241: } rhughes@241: } rhughes@241: rhughes@241: left = (start - base) / size; rhughes@241: right = (base + nelem * size - end) / size; rhughes@241: if (left > 1) rhughes@241: __qsort_with_data(base, left, map, ctx); rhughes@241: if (right > 1) rhughes@241: __qsort_with_data(end, right, mend, ctx); rhughes@241: } rhughes@241: rhughes@241: uint32_t * rhughes@241: razor_qsort_with_data(void *base, size_t nelem, size_t size, rhughes@241: razor_compare_with_data_func_t compare, void *data) rhughes@241: { rhughes@241: struct qsort_context ctx; rhughes@241: uint32_t *map; rhughes@241: int i; rhughes@241: rhughes@241: if (nelem == 0) rhughes@241: return NULL; rhughes@241: rhughes@241: ctx.size = size; rhughes@241: ctx.compare = compare; rhughes@241: ctx.data = data; rhughes@241: rhughes@241: map = malloc(nelem * sizeof (uint32_t)); rhughes@241: for (i = 0; i < nelem; i++) rhughes@241: map[i] = i; rhughes@241: rhughes@241: __qsort_with_data(base, nelem, map, &ctx); rhughes@241: rhughes@241: return map; rhughes@241: }