librazor/rpm.c
changeset 477 6ba4c0f3c9d1
parent 460 b8638c3c7eee
child 479 4204db81cdbc
     1.1 --- a/librazor/rpm.c	Wed Oct 22 12:09:47 2014 +0100
     1.2 +++ b/librazor/rpm.c	Tue Jul 05 09:40:01 2016 +0100
     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, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
     1.8 + * Copyright (C) 2009, 2011, 2012, 2014, 2016  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 @@ -25,13 +25,10 @@
    1.13  #include <stdlib.h>
    1.14  #include <string.h>
    1.15  #include <errno.h>
    1.16 -#include <sys/stat.h>
    1.17 -#include <sys/types.h>
    1.18  #if HAVE_SYS_WAIT_H
    1.19  #include <sys/wait.h>
    1.20  #endif
    1.21  #include <fcntl.h>
    1.22 -#include <dirent.h>
    1.23  #include <unistd.h>
    1.24  #if MSWIN_API
    1.25  #include <winsock2.h>	/* For ntohl() */
    1.26 @@ -620,7 +617,7 @@
    1.27  }
    1.28  
    1.29  RAZOR_EXPORT struct razor_rpm *
    1.30 -razor_rpm_open(const char *filename, struct razor_error **error)
    1.31 +razor_rpm_open(const char *uri, struct razor_error **error)
    1.32  {
    1.33  	struct rpm_lead *lead;
    1.34  	struct razor_rpm *rpm;
    1.35 @@ -628,7 +625,7 @@
    1.36  	unsigned int count, i, nindex, hsize;
    1.37  	const char *name, *prefix;
    1.38  
    1.39 -	assert (filename != NULL);
    1.40 +	assert (uri != NULL);
    1.41  
    1.42  	rpm = zalloc(sizeof *rpm);
    1.43  	if (rpm == NULL) {
    1.44 @@ -638,7 +635,7 @@
    1.45  	}
    1.46  	memset(rpm, 0, sizeof *rpm);
    1.47  
    1.48 -	rpm->map = razor_file_get_contents(filename, &rpm->size, 0, error);
    1.49 +	rpm->map = razor_uri_get_contents(uri, &rpm->size, 0, error);
    1.50  	if (!rpm->map) {
    1.51  		free(rpm);
    1.52  		return NULL;
    1.53 @@ -646,11 +643,11 @@
    1.54  
    1.55  	lead = rpm->map;
    1.56  	if (rpm->size < RPM_LEAD_SIZE ||
    1.57 -	    strncmp(lead->magic,RPM_LEAD_MAGIC,4) || lead->major != 3) {
    1.58 +	    strncmp((char *)lead->magic,RPM_LEAD_MAGIC,4) || lead->major != 3) {
    1.59  		razor_rpm_close(rpm);
    1.60  		razor_set_error(error, RAZOR_GENERAL_ERROR,
    1.61  				RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
    1.62 -				filename, "Not a recognized RPM format file");
    1.63 +				uri, "Not a recognized RPM format file");
    1.64  		return NULL;
    1.65  	}
    1.66  
    1.67 @@ -682,8 +679,7 @@
    1.68  			razor_rpm_close(rpm);
    1.69  			razor_set_error(error, RAZOR_GENERAL_ERROR,
    1.70  					RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
    1.71 -					filename,
    1.72 -					"Old filenames not supported");
    1.73 +					uri, "Old filenames not supported");
    1.74  			return NULL;
    1.75  		}
    1.76  	}
    1.77 @@ -704,8 +700,7 @@
    1.78  			razor_rpm_close(rpm);
    1.79  			razor_set_error(error, RAZOR_GENERAL_ERROR,
    1.80  					RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
    1.81 -					filename,
    1.82 -					"Default prefix not supported");
    1.83 +					uri, "Default prefix not supported");
    1.84  			return NULL;
    1.85  		}
    1.86  	}
    1.87 @@ -748,7 +743,7 @@
    1.88  #define RESERVED     0xE0 /* bits 5..7: reserved */
    1.89  
    1.90  struct installer {
    1.91 -	const char *root;
    1.92 +	const char *root_uri;
    1.93  	struct razor_rpm *rpm;
    1.94  	struct razor_atomic *atomic;
    1.95  	z_stream stream;
    1.96 @@ -808,13 +803,47 @@
    1.97  static int
    1.98  create_path(struct installer *installer, const char *path, unsigned int mode)
    1.99  {
   1.100 -	char *s, *buffer;
   1.101 -	int h, ret;
   1.102 +	const char *s, *relative;
   1.103 +	char *uri, *buffer;
   1.104 +	int h, ret, is_within_root;
   1.105 +	struct razor_error *tmp_error = NULL;
   1.106  
   1.107 -	if (razor_atomic_make_dirs(installer->atomic, installer->root, path))
   1.108 +	uri = razor_path_to_uri(path);
   1.109 +
   1.110 +	if (str_has_prefix(uri, "file:///"))
   1.111 +		relative = uri + 8;
   1.112 +	else if (str_has_prefix(uri, "file:/"))
   1.113 +		relative = uri + 6;
   1.114 +	else if (str_has_prefix(uri, "file:"))
   1.115 +		relative = uri + 5;
   1.116 +	else if (str_has_prefix(uri, "/"))
   1.117 +		relative = uri + 1;
   1.118 +	else
   1.119 +		relative = uri;
   1.120 +
   1.121 +	buffer = razor_resolve_uri_root(installer->root_uri, relative, 1,
   1.122 +					&tmp_error);
   1.123 +
   1.124 +	if (!buffer) {
   1.125 +		razor_atomic_propagate_error(installer->atomic, tmp_error,
   1.126 +					     NULL);
   1.127 +		free(uri);
   1.128  		return -1;
   1.129 +	}
   1.130  
   1.131 -	buffer = razor_concat(installer->root, path, NULL);
   1.132 +	is_within_root = installer->root_uri &&
   1.133 +			 str_has_prefix(buffer, installer->root_uri);
   1.134 +
   1.135 +	if (is_within_root)
   1.136 +		ret = razor_atomic_make_dirs(installer->atomic,
   1.137 +					     installer->root_uri, relative);
   1.138 +	else
   1.139 +		ret = razor_atomic_make_dirs(installer->atomic, "", buffer);
   1.140 +
   1.141 +	free(uri);
   1.142 +
   1.143 +	if (ret)
   1.144 +		return ret;
   1.145  
   1.146  	switch (mode >> 12) {
   1.147  	case REG:
   1.148 @@ -831,7 +860,8 @@
   1.149  					       installer->length))
   1.150  				return -1;
   1.151  		}
   1.152 -		return razor_atomic_close(installer->atomic, h);
   1.153 +		ret = razor_atomic_close(installer->atomic, h);
   1.154 +		break;
   1.155  	case XDIR:
   1.156  		ret = razor_atomic_create_dir(installer->atomic, buffer, mode);
   1.157  		free(buffer);
   1.158 @@ -842,16 +872,17 @@
   1.159  			return -1;
   1.160  		if (installer->length >= sizeof installer->buffer) {
   1.161  			razor_atomic_abort(installer->atomic,
   1.162 -			  RAZOR_GENERAL_ERROR,
   1.163 -			  RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
   1.164 -			  "Link target too long");
   1.165 +					   RAZOR_GENERAL_ERROR,
   1.166 +					   RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
   1.167 +					   "Link target too long");
   1.168  			return -1;
   1.169  		}
   1.170  		installer->buffer[installer->length] = '\0';
   1.171  		ret = razor_atomic_create_symlink(installer->atomic,
   1.172 -		  (const char *)installer->buffer, buffer);
   1.173 +						  (const char *)installer->buffer,
   1.174 +						  buffer);
   1.175  		free(buffer);
   1.176 -		return ret;
   1.177 +		break;
   1.178  #else
   1.179  		s = "Symbolic links";
   1.180  		goto unsupported;
   1.181 @@ -861,9 +892,9 @@
   1.182  unsupported:
   1.183  		free(buffer);
   1.184  		buffer = razor_concat(s, " are not supported on this platform",
   1.185 -		  NULL);
   1.186 +				      NULL);
   1.187  		razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
   1.188 -		  RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, buffer);
   1.189 +				   RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, buffer);
   1.190  		free(buffer);
   1.191  		return -1;
   1.192  	case CDEV:
   1.193 @@ -878,9 +909,12 @@
   1.194  	default:
   1.195  		free(buffer);
   1.196  		razor_atomic_abort(installer->atomic, RAZOR_GENERAL_ERROR,
   1.197 -		  RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED, "Unknown file type");
   1.198 +				   RAZOR_GENERAL_ERROR_RPM_UNSUPPORTED,
   1.199 +				   "Unknown file type");
   1.200  		return -1;
   1.201  	}
   1.202 +
   1.203 +	return ret;
   1.204  }
   1.205  
   1.206  static int chroot_push(const char *root)
   1.207 @@ -912,12 +946,14 @@
   1.208  }
   1.209  
   1.210  static int
   1.211 -run_script_lua(const char *root, unsigned int script_tag, const char *script,
   1.212 -	       int arg1)
   1.213 +run_script_lua(const char *root_uri, unsigned int script_tag,
   1.214 +	       const char *script, int arg1, struct razor_error **error)
   1.215  {
   1.216  	int root_fd, retval;
   1.217 +	const char *name;
   1.218  #if HAVE_LUA
   1.219 -	const char *name;
   1.220 +	char *root;
   1.221 +#endif
   1.222  
   1.223  	switch(script_tag) {
   1.224  		case RPMTAG_PREIN:
   1.225 @@ -936,12 +972,19 @@
   1.226  			name = "script";
   1.227  			break;
   1.228  	}
   1.229 -	root_fd = chroot_push(root);
   1.230 +
   1.231 +#if HAVE_LUA
   1.232 +	root = razor_path_from_uri(root_uri, error);
   1.233 +	if (!root)
   1.234 +		return -1;
   1.235 +	root_fd = root ? chroot_push(root) : -1;
   1.236  	retval = run_lua_script(root_fd < 0 ? root : NULL, name, script, -1,
   1.237  				arg1);
   1.238 +	free(root);
   1.239  	chroot_pop(root_fd);
   1.240  #else	/* HAVE_LUA */
   1.241 -	fprintf(stderr, "lua not available to run script\n");
   1.242 +	razor_set_error(error, RAZOR_GENERAL_ERROR, RAZOR_GENERAL_ERROR_FAILED,
   1.243 +			name, "lua not available to run script");
   1.244  	retval = -1;
   1.245  #endif	/* HAVE_LUA */
   1.246  
   1.247 @@ -949,12 +992,12 @@
   1.248  }
   1.249  
   1.250  static int
   1.251 -run_script_external(const char *root, const char *program, const char *script,
   1.252 -		    int arg1)
   1.253 +run_script_external(const char *root_uri, const char *program,
   1.254 +		    const char *script, int arg1, struct razor_error **error)
   1.255  {
   1.256  	int root_fd, retval;
   1.257  	FILE *fp;
   1.258 -	char buf[32], *command;
   1.259 +	char buf[32], *command, *root;
   1.260  
   1.261  	if (program == NULL) {
   1.262  #if MSWIN_API
   1.263 @@ -971,7 +1014,11 @@
   1.264  #endif
   1.265  	}
   1.266  
   1.267 +	root = razor_path_from_uri(root_uri, error);
   1.268 +	if (!root)
   1.269 +		return -1;
   1.270  	root_fd = chroot_push(root);
   1.271 +	free(root);
   1.272  	if (arg1 >= 0) {
   1.273  		sprintf(buf, "%d", arg1);
   1.274  		command = malloc(strlen(program) + strlen(buf) + 2);
   1.275 @@ -982,10 +1029,11 @@
   1.276  	free(command);
   1.277  
   1.278  	if (!fp) {
   1.279 -		perror(program);
   1.280 +		razor_set_error_posix(error, program);
   1.281  		retval = -1;
   1.282  	} else if (script && fwrite(script, strlen(script), 1, fp) != 1) {
   1.283 -		perror("failed to write script to program");
   1.284 +		razor_set_error_posix(error,
   1.285 +				      "failed to write script to program");
   1.286  		retval = -1;
   1.287  	} else
   1.288  		retval = 0;
   1.289 @@ -998,8 +1046,8 @@
   1.290  }
   1.291  
   1.292  static int
   1.293 -run_script(struct installer *installer,
   1.294 -	   unsigned int program_tag, unsigned int script_tag, int arg1)
   1.295 +run_script(struct installer *installer, unsigned int program_tag,
   1.296 +	   unsigned int script_tag, int arg1, struct razor_error **error)
   1.297  {
   1.298  	int i, retval;
   1.299  	struct razor_rpm *rpm = installer->rpm;
   1.300 @@ -1024,11 +1072,11 @@
   1.301  	}
   1.302  
   1.303  	if (program && strcmp(program, "<lua>") == 0)
   1.304 -		retval = run_script_lua(installer->root, script_tag, script,
   1.305 -					arg1);
   1.306 +		retval = run_script_lua(installer->root_uri, script_tag,
   1.307 +					script, arg1, error);
   1.308  	else
   1.309 -		retval = run_script_external(installer->root, program, script,
   1.310 -					     arg1);
   1.311 +		retval = run_script_external(installer->root_uri, program,
   1.312 +					     script, arg1, error);
   1.313  
   1.314  	if (rpm->relocations) {
   1.315  		environment_unset(&env);
   1.316 @@ -1040,7 +1088,8 @@
   1.317  
   1.318  int
   1.319  razor_run_script(const char *root, enum razor_property_flags script,
   1.320 -		 const char *program, const char *body, int arg1)
   1.321 +		 const char *program, const char *body, int arg1,
   1.322 +		 struct razor_error **error)
   1.323  {
   1.324  	int retval;
   1.325  	unsigned int script_tag;
   1.326 @@ -1071,10 +1120,10 @@
   1.327  			script_tag = 0;
   1.328  			break;
   1.329  		}
   1.330 -		retval = run_script_lua(root, script_tag, body, arg1);
   1.331 +		retval = run_script_lua(root, script_tag, body, arg1, error);
   1.332  	}
   1.333  	else
   1.334 -		retval = run_script_external(root, program, body, arg1);
   1.335 +		retval = run_script_external(root, program, body, arg1, error);
   1.336  
   1.337  	return retval;
   1.338  }
   1.339 @@ -1164,30 +1213,38 @@
   1.340  
   1.341  RAZOR_EXPORT int
   1.342  razor_rpm_install(struct razor_rpm *rpm, struct razor_atomic *atomic,
   1.343 -		  const char *root, int install_count,
   1.344 +		  const char *root_uri, int install_count,
   1.345  		  enum razor_stage_type stage)
   1.346  {
   1.347  	struct installer installer;
   1.348  	struct cpio_file_header *header;
   1.349 -	struct stat buf;
   1.350  	unsigned int mode;
   1.351  	const char *path;
   1.352  	size_t filesize;
   1.353  	char *s;
   1.354 -	int retval = 0, code;
   1.355 +	int retval = 0, domain, code;
   1.356 +	struct razor_error *tmp_error = NULL;
   1.357  
   1.358  	assert (rpm != NULL);
   1.359 -	assert (root != NULL);
   1.360 +	assert (root_uri != NULL);
   1.361  
   1.362  	installer.rpm = rpm;
   1.363 -	installer.root = root;
   1.364 +	installer.root_uri = root_uri;
   1.365  	installer.atomic = atomic;
   1.366  
   1.367  	/* FIXME: Only do this before a transaction, not per rpm. */
   1.368 -	if (*root && ((retval = stat(root, &buf)) || !S_ISDIR(buf.st_mode))) {
   1.369 -		code = retval ? errno : ENOTDIR;
   1.370 -		s = razor_concat(root, ": Directory does not exist", NULL);
   1.371 -		razor_atomic_abort(atomic, RAZOR_POSIX_ERROR, code, s);
   1.372 +	if (*root_uri && razor_uri_is_directory(root_uri, &tmp_error) <= 0) {
   1.373 +		if (tmp_error) {
   1.374 +			domain = razor_error_get_domain(tmp_error);
   1.375 +			code = razor_error_get_code(tmp_error);
   1.376 +			razor_error_free(tmp_error);
   1.377 +			tmp_error = NULL;
   1.378 +		} else {
   1.379 +			domain = RAZOR_POSIX_ERROR;
   1.380 +			code = ENOTDIR;
   1.381 +		}
   1.382 +		s = razor_concat(root_uri, ": Directory does not exist", NULL);
   1.383 +		razor_atomic_abort(atomic, domain, code, s);
   1.384  		free(s);
   1.385  		return -1;
   1.386  	}
   1.387 @@ -1195,9 +1252,14 @@
   1.388  	if (rpm->relocations)
   1.389  		razor_relocations_set_rpm(rpm->relocations, rpm);
   1.390  
   1.391 -	if (stage & RAZOR_STAGE_SCRIPTS_PRE)
   1.392 +	if (stage & RAZOR_STAGE_SCRIPTS_PRE) {
   1.393  		retval = run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN,
   1.394 -				    install_count);
   1.395 +				    install_count, &tmp_error);
   1.396 +		if (retval) {
   1.397 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.398 +			tmp_error = NULL;
   1.399 +		}
   1.400 +	}
   1.401  
   1.402  	if (!retval && (stage & RAZOR_STAGE_FILES)) {
   1.403  		if (installer_init(&installer))
   1.404 @@ -1244,9 +1306,14 @@
   1.405  		retval = razor_atomic_in_error_state(atomic);
   1.406  	}
   1.407  
   1.408 -	if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST))
   1.409 +	if (!retval && (stage & RAZOR_STAGE_SCRIPTS_POST)) {
   1.410  		retval = run_script(&installer, RPMTAG_POSTINPROG,
   1.411 -				    RPMTAG_POSTIN, install_count);
   1.412 +				    RPMTAG_POSTIN, install_count, &tmp_error);
   1.413 +		if (retval) {
   1.414 +			razor_atomic_propagate_error(atomic, tmp_error, NULL);
   1.415 +			tmp_error = NULL;
   1.416 +		}
   1.417 +	}
   1.418  
   1.419  	return retval;
   1.420  }
   1.421 @@ -1260,7 +1327,7 @@
   1.422  
   1.423  	free(rpm->dirs);
   1.424  	free(rpm->prefixes);
   1.425 -	err = razor_file_free_contents(rpm->map, rpm->size);
   1.426 +	err = razor_uri_free_contents(rpm->map, rpm->size);
   1.427  	free(rpm->evr);
   1.428  	free(rpm);
   1.429