diff -r d15a16347c77 -r 891991677a7f librazor/rpm.c --- a/librazor/rpm.c Tue Jul 07 22:50:22 2009 +0100 +++ b/librazor/rpm.c Thu Feb 09 20:45:27 2012 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Kristian Høgsberg * Copyright (C) 2008 Red Hat, Inc - * Copyright (C) 2009 J. Ali Harlow + * Copyright (C) 2009, 2011 J. Ali Harlow * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -602,24 +602,29 @@ } RAZOR_EXPORT struct razor_rpm * -razor_rpm_open(const char *filename) +razor_rpm_open(const char *filename, struct razor_atomic *atomic) { struct razor_rpm *rpm; struct rpm_header_index *base, *index; unsigned int count, i, nindex, hsize; const char *name, *prefix; + char *s; assert (filename != NULL); - rpm = malloc(sizeof *rpm); - if (rpm == NULL) + rpm = zalloc(sizeof *rpm); + if (rpm == NULL) { + razor_atomic_abort(atomic, "Not enough memory"); return NULL; + } memset(rpm, 0, sizeof *rpm); rpm->map = razor_file_get_contents(filename, &rpm->size); if (!rpm->map) { - fprintf(stderr, "couldn't get contents of %s (%s)\n", filename, - strerror(errno)); + s = razor_concat(filename, ": ", strerror(errno), NULL); + razor_atomic_abort(atomic, s); + free(s); + free(rpm); return NULL; } @@ -648,7 +653,11 @@ name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES, &count); if (name) { - fprintf(stderr, "old filenames not supported\n"); + razor_rpm_close(rpm); + s = razor_concat(filename, + ": Old filenames not supported", NULL); + razor_atomic_abort(atomic, s); + free(s); return NULL; } } @@ -666,7 +675,12 @@ prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX, &count); if (prefix) { - fprintf(stderr, "default prefix not supported\n"); + razor_rpm_close(rpm); + s = razor_concat(filename, + ": Default prefix not supported", + NULL); + razor_atomic_abort(atomic, s); + free(s); return NULL; } } @@ -711,6 +725,7 @@ struct installer { const char *root; struct razor_rpm *rpm; + struct razor_atomic *atomic; z_stream stream; unsigned char buffer[32768]; size_t rest, length; @@ -731,8 +746,7 @@ installer->stream.avail_out = length; err = inflate(&installer->stream, Z_SYNC_FLUSH); if (err != Z_OK && err != Z_STREAM_END) { - fprintf(stderr, "inflate error: %d (%s)\n", err, - strerror(errno)); + razor_atomic_abort(installer->atomic, "Failed to inflate"); return -1; } @@ -757,8 +771,7 @@ err = inflate(&installer->stream, Z_SYNC_FLUSH); if (err != Z_OK && err != Z_STREAM_END) { - fprintf(stderr, "inflate error: %d (%s)\n", err, - strerror(errno)); + razor_atomic_abort(installer->atomic, "Failed to inflate"); return -1; } @@ -768,80 +781,74 @@ static int create_path(struct installer *installer, const char *path, unsigned int mode) { - char buffer[PATH_MAX]; - struct stat buf; - int fd, ret; + char *s, *buffer; + int h, ret; - if (razor_create_dir(installer->root, path) < 0) + if (razor_atomic_make_dirs(installer->atomic, installer->root, path)) return -1; - snprintf(buffer, sizeof buffer, "%s%s", installer->root, path); + buffer = razor_concat(installer->root, path, NULL); switch (mode >> 12) { case REG: /* FIXME: handle the case where a file is already there. */ - fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, - mode & 0x1ff); - if (fd < 0){ - fprintf(stderr, "failed to create file %s\n", buffer); + h = razor_atomic_create_file(installer->atomic, buffer, mode); + free(buffer); + if (h < 0) return -1; + while (installer->rest > 0) { + if (installer_inflate(installer)) + return -1; + if (razor_atomic_write(installer->atomic, h, + installer->buffer, + installer->length)) + return -1; } - while (installer->rest > 0) { - if (installer_inflate(installer)) { - fprintf(stderr, "failed to inflate\n"); - return -1; - } - if (razor_write(fd, installer->buffer, - installer->length)) { - fprintf(stderr, "failed to write payload\n"); - return -1; - } - } - if (close(fd) < 0) { - fprintf(stderr, "failed to close %s: %s\n", buffer, - strerror(errno)); - return -1; - } - return 0; + return razor_atomic_close(installer->atomic, h); case XDIR: - ret = mkdir(buffer, mode & 0x1ff); - if (ret == 0 || errno != EEXIST) - return ret; - if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) { - /* FIXME: also check that mode match. */ - fprintf(stderr, - "%s exists but is not a directory\n", buffer); - return -1; - } - return 0; + ret = razor_atomic_create_dir(installer->atomic, buffer, mode); + free(buffer); + return ret; case LINK: #if HAVE_SYMLINK - if (installer_inflate(installer)) { - fprintf(stderr, "failed to inflate\n"); + if (installer_inflate(installer)) return -1; - } if (installer->length >= sizeof installer->buffer) { - fprintf(stderr, "link name too long\n"); + razor_atomic_abort(installer->atomic, + "Link target too long"); return -1; } installer->buffer[installer->length] = '\0'; - if (symlink((const char *) installer->buffer, buffer)) { - perror("failed to create symlink"); - return -1; - } - return 0; + ret = razor_atomic_create_symlink(installer->atomic, + (const char *)installer->buffer, buffer); + free(buffer); + return ret; #else - /* fall through */ + s = "Symbolic links"; + goto unsupported; #endif case PIPE: + s = "Named pipes"; +unsupported: + free(buffer); + buffer = razor_concat(s, " are not supported on this platform", + NULL); + razor_atomic_abort(installer->atomic, buffer); + free(buffer); + return -1; case CDEV: + s = "Character devices"; + goto unsupported; case BDEV: + s = "Block devices"; + goto unsupported; case SOCK: - printf("%s: unhandled file type %d\n", buffer, mode >> 12); - return 0; + s = "Named sockets"; + goto unsupported; default: - printf("%s: unknown file type %d\n", buffer, mode >> 12); - return 0; + free(buffer); + razor_atomic_abort(installer->atomic, "Unknown file type"); + return -1; } } @@ -1046,10 +1053,12 @@ { unsigned char *gz_header; int method, flags, err; + char buffer[32], *s; gz_header = installer->rpm->payload; if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) { - fprintf(stderr, "payload section doesn't have gz header\n"); + razor_atomic_abort(installer->atomic, + "Payload section doesn't have gz header"); return -1; } @@ -1057,8 +1066,9 @@ flags = gz_header[3]; if (method != Z_DEFLATED || flags != 0) { - fprintf(stderr, - "unknown payload compression method or flags set\n"); + razor_atomic_abort(installer->atomic, + "Unknown payload compression method or " + "flags set"); return -1; } @@ -1075,7 +1085,10 @@ err = inflateInit2(&installer->stream, -MAX_WBITS); if (err != Z_OK) { - fprintf(stderr, "inflateInit error: %d\n", err); + sprintf(buffer, "%d", err); + s = razor_concat("inflateEnd error: ", s, NULL); + razor_atomic_abort(installer->atomic, s); + free(s); return -1; } @@ -1086,15 +1099,18 @@ installer_finish(struct installer *installer) { int err; + char buffer[32], *s; err = inflateEnd(&installer->stream); if (err != Z_OK) { - fprintf(stderr, "inflateEnd error: %d\n", err); - return -1; + sprintf(buffer, "%d", err); + s = razor_concat("inflateEnd error: ", s, NULL); + razor_atomic_abort(installer->atomic, s); + free(s); } - return 0; + return razor_atomic_in_error_state(installer->atomic); } static unsigned long @@ -1114,73 +1130,86 @@ } RAZOR_EXPORT int -razor_rpm_install(struct razor_rpm *rpm, const char *root, int install_count) +razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic, + const char *root, int install_count, + enum razor_stage_type stage) { struct installer installer; struct cpio_file_header *header; struct stat buf; unsigned int mode; - const char *path; + const char *path, *name; size_t filesize; + char *s; assert (rpm != NULL); assert (root != NULL); installer.rpm = rpm; installer.root = root; + installer.atomic = atomic; /* FIXME: Only do this before a transaction, not per rpm. */ if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) { - fprintf(stderr, - "root installation directory \"%s\" does not exist\n", - root); + s = razor_concat(root, ": Directory does not exist", NULL); + razor_atomic_abort(stderr, s); + free(s); return -1; } if (rpm->relocations) razor_relocations_set_rpm(rpm->relocations, rpm); - if (installer_init(&installer)) - return -1; + if (stage & RAZOR_STAGE_SCRIPTS_PRE) + run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN, + install_count); - run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN, install_count); - - while (installer.stream.avail_in > 0) { - installer.rest = sizeof *header; - if (installer_inflate(&installer)) + if (stage & RAZOR_STAGE_FILES) { + if (installer_init(&installer)) return -1; - header = (struct cpio_file_header *) installer.buffer; - mode = fixed_hex_to_ulong(header->mode, sizeof header->mode); - filesize = fixed_hex_to_ulong(header->filesize, - sizeof header->filesize); + while (installer.stream.avail_in > 0) { + installer.rest = sizeof *header; + if (installer_inflate(&installer)) + break; - installer.rest = fixed_hex_to_ulong(header->namesize, - sizeof header->namesize); + header = (struct cpio_file_header *) installer.buffer; + mode = fixed_hex_to_ulong(header->mode, + sizeof header->mode); + filesize = fixed_hex_to_ulong(header->filesize, + sizeof header->filesize); - if (installer_inflate(&installer) || - installer_align(&installer, 4)) - return -1; + installer.rest = + fixed_hex_to_ulong(header->namesize, + sizeof header->namesize); - path = (const char *) installer.buffer; - /* This convention is so lame... */ - if (strcmp(path, "TRAILER!!!") == 0) - break; + if (installer_inflate(&installer) || + installer_align(&installer, 4)) + break; - installer.rest = filesize; - path++; - if (rpm->relocations) - path = razor_relocations_apply(rpm->relocations, path); - if (create_path(&installer, path, mode) < 0) - return -1; - if (installer_align(&installer, 4)) + path = (const char *) installer.buffer; + /* This convention is so lame... */ + if (strcmp(path, "TRAILER!!!") == 0) + break; + + installer.rest = filesize; + path++; + if (rpm->relocations) + path = razor_relocations_apply(rpm->relocations, + path); + if (create_path(&installer, path, mode)) + break; + if (installer_align(&installer, 4)) + break; + } + + if (installer_finish(&installer)) return -1; } - if (installer_finish(&installer)) - return -1; - - run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN, install_count); + if (stage & RAZOR_STAGE_SCRIPTS_POST) + run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN, + install_count); return 0; }