librazor/rpm.c
changeset 416 d0aa9e0a6d04
parent 376 d15a16347c77
child 422 6fa783097ca1
     1.1 --- a/librazor/rpm.c	Tue Jul 07 22:50:22 2009 +0100
     1.2 +++ b/librazor/rpm.c	Thu Feb 09 20:42:08 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  }