1.1 --- a/librazor/rpm.c Tue Jul 07 22:50:22 2009 +0100
1.2 +++ b/librazor/rpm.c Wed Feb 01 12:49:13 2012 +0000
1.3 @@ -1,7 +1,7 @@
1.4 /*
1.5 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
1.6 * Copyright (C) 2008 Red Hat, Inc
1.7 - * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
1.8 + * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
1.9 *
1.10 * This program is free software; you can redistribute it and/or modify
1.11 * it under the terms of the GNU General Public License as published by
1.12 @@ -602,24 +602,29 @@
1.13 }
1.14
1.15 RAZOR_EXPORT struct razor_rpm *
1.16 -razor_rpm_open(const char *filename)
1.17 +razor_rpm_open(const char *filename, struct razor_atomic *atomic)
1.18 {
1.19 struct razor_rpm *rpm;
1.20 struct rpm_header_index *base, *index;
1.21 unsigned int count, i, nindex, hsize;
1.22 const char *name, *prefix;
1.23 + char *s;
1.24
1.25 assert (filename != NULL);
1.26
1.27 - rpm = malloc(sizeof *rpm);
1.28 - if (rpm == NULL)
1.29 + rpm = zalloc(sizeof *rpm);
1.30 + if (rpm == NULL) {
1.31 + razor_atomic_abort(atomic, "Not enough memory");
1.32 return NULL;
1.33 + }
1.34 memset(rpm, 0, sizeof *rpm);
1.35
1.36 rpm->map = razor_file_get_contents(filename, &rpm->size);
1.37 if (!rpm->map) {
1.38 - fprintf(stderr, "couldn't get contents of %s (%s)\n", filename,
1.39 - strerror(errno));
1.40 + s = razor_concat(filename, ": ", strerror(errno), NULL);
1.41 + razor_atomic_abort(atomic, s);
1.42 + free(s);
1.43 + free(rpm);
1.44 return NULL;
1.45 }
1.46
1.47 @@ -648,7 +653,11 @@
1.48 name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
1.49 &count);
1.50 if (name) {
1.51 - fprintf(stderr, "old filenames not supported\n");
1.52 + razor_rpm_close(rpm);
1.53 + s = razor_concat(filename,
1.54 + ": Old filenames not supported", NULL);
1.55 + razor_atomic_abort(atomic, s);
1.56 + free(s);
1.57 return NULL;
1.58 }
1.59 }
1.60 @@ -666,7 +675,12 @@
1.61 prefix = razor_rpm_get_indirect(rpm, RPMTAG_DEFAULTPREFIX,
1.62 &count);
1.63 if (prefix) {
1.64 - fprintf(stderr, "default prefix not supported\n");
1.65 + razor_rpm_close(rpm);
1.66 + s = razor_concat(filename,
1.67 + ": Default prefix not supported",
1.68 + NULL);
1.69 + razor_atomic_abort(atomic, s);
1.70 + free(s);
1.71 return NULL;
1.72 }
1.73 }
1.74 @@ -711,6 +725,7 @@
1.75 struct installer {
1.76 const char *root;
1.77 struct razor_rpm *rpm;
1.78 + struct razor_atomic *atomic;
1.79 z_stream stream;
1.80 unsigned char buffer[32768];
1.81 size_t rest, length;
1.82 @@ -731,8 +746,7 @@
1.83 installer->stream.avail_out = length;
1.84 err = inflate(&installer->stream, Z_SYNC_FLUSH);
1.85 if (err != Z_OK && err != Z_STREAM_END) {
1.86 - fprintf(stderr, "inflate error: %d (%s)\n", err,
1.87 - strerror(errno));
1.88 + razor_atomic_abort(installer->atomic, "Failed to inflate");
1.89 return -1;
1.90 }
1.91
1.92 @@ -757,8 +771,7 @@
1.93
1.94 err = inflate(&installer->stream, Z_SYNC_FLUSH);
1.95 if (err != Z_OK && err != Z_STREAM_END) {
1.96 - fprintf(stderr, "inflate error: %d (%s)\n", err,
1.97 - strerror(errno));
1.98 + razor_atomic_abort(installer->atomic, "Failed to inflate");
1.99 return -1;
1.100 }
1.101
1.102 @@ -768,80 +781,74 @@
1.103 static int
1.104 create_path(struct installer *installer, const char *path, unsigned int mode)
1.105 {
1.106 - char buffer[PATH_MAX];
1.107 - struct stat buf;
1.108 - int fd, ret;
1.109 + char *s, *buffer;
1.110 + int h, ret;
1.111
1.112 - if (razor_create_dir(installer->root, path) < 0)
1.113 + if (razor_atomic_make_dirs(installer->atomic, installer->root, path))
1.114 return -1;
1.115
1.116 - snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
1.117 + buffer = razor_concat(installer->root, path, NULL);
1.118
1.119 switch (mode >> 12) {
1.120 case REG:
1.121 /* FIXME: handle the case where a file is already there. */
1.122 - fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
1.123 - mode & 0x1ff);
1.124 - if (fd < 0){
1.125 - fprintf(stderr, "failed to create file %s\n", buffer);
1.126 + h = razor_atomic_create_file(installer->atomic, buffer, mode);
1.127 + free(buffer);
1.128 + if (h < 0)
1.129 return -1;
1.130 + while (installer->rest > 0) {
1.131 + if (installer_inflate(installer))
1.132 + return -1;
1.133 + if (razor_atomic_write(installer->atomic, h,
1.134 + installer->buffer,
1.135 + installer->length))
1.136 + return -1;
1.137 }
1.138 - while (installer->rest > 0) {
1.139 - if (installer_inflate(installer)) {
1.140 - fprintf(stderr, "failed to inflate\n");
1.141 - return -1;
1.142 - }
1.143 - if (razor_write(fd, installer->buffer,
1.144 - installer->length)) {
1.145 - fprintf(stderr, "failed to write payload\n");
1.146 - return -1;
1.147 - }
1.148 - }
1.149 - if (close(fd) < 0) {
1.150 - fprintf(stderr, "failed to close %s: %s\n", buffer,
1.151 - strerror(errno));
1.152 - return -1;
1.153 - }
1.154 - return 0;
1.155 + return razor_atomic_close(installer->atomic, h);
1.156 case XDIR:
1.157 - ret = mkdir(buffer, mode & 0x1ff);
1.158 - if (ret == 0 || errno != EEXIST)
1.159 - return ret;
1.160 - if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
1.161 - /* FIXME: also check that mode match. */
1.162 - fprintf(stderr,
1.163 - "%s exists but is not a directory\n", buffer);
1.164 - return -1;
1.165 - }
1.166 - return 0;
1.167 + ret = razor_atomic_create_dir(installer->atomic, buffer, mode);
1.168 + free(buffer);
1.169 + return ret;
1.170 case LINK:
1.171 #if HAVE_SYMLINK
1.172 - if (installer_inflate(installer)) {
1.173 - fprintf(stderr, "failed to inflate\n");
1.174 + if (installer_inflate(installer))
1.175 return -1;
1.176 - }
1.177 if (installer->length >= sizeof installer->buffer) {
1.178 - fprintf(stderr, "link name too long\n");
1.179 + razor_atomic_abort(installer->atomic,
1.180 + "Link target too long");
1.181 return -1;
1.182 }
1.183 installer->buffer[installer->length] = '\0';
1.184 - if (symlink((const char *) installer->buffer, buffer)) {
1.185 - perror("failed to create symlink");
1.186 - return -1;
1.187 - }
1.188 - return 0;
1.189 + ret = razor_atomic_create_symlink(installer->atomic,
1.190 + (const char *)installer->buffer, buffer);
1.191 + free(buffer);
1.192 + return ret;
1.193 #else
1.194 - /* fall through */
1.195 + s = "Symbolic links";
1.196 + goto unsupported;
1.197 #endif
1.198 case PIPE:
1.199 + s = "Named pipes";
1.200 +unsupported:
1.201 + free(buffer);
1.202 + buffer = razor_concat(s, " are not supported on this platform",
1.203 + NULL);
1.204 + razor_atomic_abort(installer->atomic, buffer);
1.205 + free(buffer);
1.206 + return -1;
1.207 case CDEV:
1.208 + s = "Character devices";
1.209 + goto unsupported;
1.210 case BDEV:
1.211 + s = "Block devices";
1.212 + goto unsupported;
1.213 case SOCK:
1.214 - printf("%s: unhandled file type %d\n", buffer, mode >> 12);
1.215 - return 0;
1.216 + s = "Named sockets";
1.217 + goto unsupported;
1.218 default:
1.219 - printf("%s: unknown file type %d\n", buffer, mode >> 12);
1.220 - return 0;
1.221 + free(buffer);
1.222 + razor_atomic_abort(installer->atomic, "Unknown file type");
1.223 + return -1;
1.224 }
1.225 }
1.226
1.227 @@ -1046,10 +1053,12 @@
1.228 {
1.229 unsigned char *gz_header;
1.230 int method, flags, err;
1.231 + char buffer[32], *s;
1.232
1.233 gz_header = installer->rpm->payload;
1.234 if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
1.235 - fprintf(stderr, "payload section doesn't have gz header\n");
1.236 + razor_atomic_abort(installer->atomic,
1.237 + "Payload section doesn't have gz header");
1.238 return -1;
1.239 }
1.240
1.241 @@ -1057,8 +1066,9 @@
1.242 flags = gz_header[3];
1.243
1.244 if (method != Z_DEFLATED || flags != 0) {
1.245 - fprintf(stderr,
1.246 - "unknown payload compression method or flags set\n");
1.247 + razor_atomic_abort(installer->atomic,
1.248 + "Unknown payload compression method or "
1.249 + "flags set");
1.250 return -1;
1.251 }
1.252
1.253 @@ -1075,7 +1085,10 @@
1.254
1.255 err = inflateInit2(&installer->stream, -MAX_WBITS);
1.256 if (err != Z_OK) {
1.257 - fprintf(stderr, "inflateInit error: %d\n", err);
1.258 + sprintf(buffer, "%d", err);
1.259 + s = razor_concat("inflateEnd error: ", s, NULL);
1.260 + razor_atomic_abort(installer->atomic, s);
1.261 + free(s);
1.262 return -1;
1.263 }
1.264
1.265 @@ -1086,15 +1099,18 @@
1.266 installer_finish(struct installer *installer)
1.267 {
1.268 int err;
1.269 + char buffer[32], *s;
1.270
1.271 err = inflateEnd(&installer->stream);
1.272
1.273 if (err != Z_OK) {
1.274 - fprintf(stderr, "inflateEnd error: %d\n", err);
1.275 - return -1;
1.276 + sprintf(buffer, "%d", err);
1.277 + s = razor_concat("inflateEnd error: ", s, NULL);
1.278 + razor_atomic_abort(installer->atomic, s);
1.279 + free(s);
1.280 }
1.281
1.282 - return 0;
1.283 + return razor_atomic_in_error_state(installer->atomic);
1.284 }
1.285
1.286 static unsigned long
1.287 @@ -1114,73 +1130,86 @@
1.288 }
1.289
1.290 RAZOR_EXPORT int
1.291 -razor_rpm_install(struct razor_rpm *rpm, const char *root, int install_count)
1.292 +razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
1.293 + const char *root, int install_count,
1.294 + enum razor_stage_type stage)
1.295 {
1.296 struct installer installer;
1.297 struct cpio_file_header *header;
1.298 struct stat buf;
1.299 unsigned int mode;
1.300 - const char *path;
1.301 + const char *path, *name;
1.302 size_t filesize;
1.303 + char *s;
1.304
1.305 assert (rpm != NULL);
1.306 assert (root != NULL);
1.307
1.308 installer.rpm = rpm;
1.309 installer.root = root;
1.310 + installer.atomic = atomic;
1.311
1.312 /* FIXME: Only do this before a transaction, not per rpm. */
1.313 if (*root && (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode))) {
1.314 - fprintf(stderr,
1.315 - "root installation directory \"%s\" does not exist\n",
1.316 - root);
1.317 + s = razor_concat(root, ": Directory does not exist", NULL);
1.318 + razor_atomic_abort(stderr, s);
1.319 + free(s);
1.320 return -1;
1.321 }
1.322
1.323 if (rpm->relocations)
1.324 razor_relocations_set_rpm(rpm->relocations, rpm);
1.325
1.326 - if (installer_init(&installer))
1.327 - return -1;
1.328 + if (stage & RAZOR_STAGE_SCRIPTS_PRE)
1.329 + run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN,
1.330 + install_count);
1.331
1.332 - run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN, install_count);
1.333 -
1.334 - while (installer.stream.avail_in > 0) {
1.335 - installer.rest = sizeof *header;
1.336 - if (installer_inflate(&installer))
1.337 + if (stage & RAZOR_STAGE_FILES) {
1.338 + if (installer_init(&installer))
1.339 return -1;
1.340
1.341 - header = (struct cpio_file_header *) installer.buffer;
1.342 - mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
1.343 - filesize = fixed_hex_to_ulong(header->filesize,
1.344 - sizeof header->filesize);
1.345 + while (installer.stream.avail_in > 0) {
1.346 + installer.rest = sizeof *header;
1.347 + if (installer_inflate(&installer))
1.348 + break;
1.349
1.350 - installer.rest = fixed_hex_to_ulong(header->namesize,
1.351 - sizeof header->namesize);
1.352 + header = (struct cpio_file_header *) installer.buffer;
1.353 + mode = fixed_hex_to_ulong(header->mode,
1.354 + sizeof header->mode);
1.355 + filesize = fixed_hex_to_ulong(header->filesize,
1.356 + sizeof header->filesize);
1.357
1.358 - if (installer_inflate(&installer) ||
1.359 - installer_align(&installer, 4))
1.360 - return -1;
1.361 + installer.rest =
1.362 + fixed_hex_to_ulong(header->namesize,
1.363 + sizeof header->namesize);
1.364
1.365 - path = (const char *) installer.buffer;
1.366 - /* This convention is so lame... */
1.367 - if (strcmp(path, "TRAILER!!!") == 0)
1.368 - break;
1.369 + if (installer_inflate(&installer) ||
1.370 + installer_align(&installer, 4))
1.371 + break;
1.372
1.373 - installer.rest = filesize;
1.374 - path++;
1.375 - if (rpm->relocations)
1.376 - path = razor_relocations_apply(rpm->relocations, path);
1.377 - if (create_path(&installer, path, mode) < 0)
1.378 - return -1;
1.379 - if (installer_align(&installer, 4))
1.380 + path = (const char *) installer.buffer;
1.381 + /* This convention is so lame... */
1.382 + if (strcmp(path, "TRAILER!!!") == 0)
1.383 + break;
1.384 +
1.385 + installer.rest = filesize;
1.386 + path++;
1.387 + if (rpm->relocations)
1.388 + path = razor_relocations_apply(rpm->relocations,
1.389 + path);
1.390 + if (create_path(&installer, path, mode))
1.391 + break;
1.392 + if (installer_align(&installer, 4))
1.393 + break;
1.394 + }
1.395 +
1.396 + if (installer_finish(&installer))
1.397 return -1;
1.398 }
1.399
1.400 - if (installer_finish(&installer))
1.401 - return -1;
1.402 -
1.403 - run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN, install_count);
1.404 + if (stage & RAZOR_STAGE_SCRIPTS_POST)
1.405 + run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN,
1.406 + install_count);
1.407
1.408 return 0;
1.409 }