librazor/razor.c
changeset 404 bd740859c4a0
parent 395 ed134fdfe95f
child 406 5ab137def3d1
     1.1 --- a/librazor/razor.c	Wed Apr 28 11:59:02 2010 +0100
     1.2 +++ b/librazor/razor.c	Thu Nov 10 10:35:21 2011 +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, 2010  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 @@ -93,10 +93,16 @@
    1.13  
    1.14  	set = zalloc(sizeof *set);
    1.15  
    1.16 -	empty = array_add(&set->string_pool, 1);
    1.17 -	*empty = '\0';
    1.18 +	if (set) {
    1.19 +		empty = array_add(&set->string_pool, 1);
    1.20 +		*empty = '\0';
    1.21  
    1.22 -	set->lock_fd = -1;
    1.23 +		set->lock_fd = -1;
    1.24 +
    1.25 +		set->ref_count = 1;
    1.26 +
    1.27 +		set->header_version = RAZOR_HEADER_VERSION;
    1.28 +	}
    1.29  
    1.30  	return set;
    1.31  }
    1.32 @@ -118,6 +124,24 @@
    1.33  	return set;
    1.34  }
    1.35  
    1.36 +RAZOR_EXPORT uint32_t
    1.37 +razor_set_get_header_version(struct razor_set *set)
    1.38 +{
    1.39 +	return set->header_version;
    1.40 +}
    1.41 +
    1.42 +RAZOR_EXPORT int
    1.43 +razor_set_set_header_version(struct razor_set *set, uint32_t header_version)
    1.44 +{
    1.45 +	if (header_version<RAZOR_HEADER_VERSION_MIN ||
    1.46 +	    header_version>RAZOR_HEADER_VERSION)
    1.47 +		return -1;
    1.48 +	else {
    1.49 +		set->header_version = header_version;
    1.50 +		return 0;
    1.51 +	}
    1.52 +}
    1.53 +
    1.54  struct razor_mapped_file {
    1.55  	struct razor_set_header *header;
    1.56  	size_t size;
    1.57 @@ -125,32 +149,52 @@
    1.58  };
    1.59  
    1.60  RAZOR_EXPORT int
    1.61 -razor_set_bind_sections(struct razor_set *set, const char *filename)
    1.62 +razor_set_bind_sections(struct razor_set *set, struct razor_atomic *atomic,
    1.63 +			const char *filename)
    1.64  {
    1.65  	struct razor_set_section *s, *sections;
    1.66  	struct razor_mapped_file *file;
    1.67 -	const char *pool;
    1.68 +	const char *pool, *reason;
    1.69 +	char *msg;
    1.70  	struct array *array;
    1.71  	int i, j;
    1.72  
    1.73  	file = zalloc(sizeof *file);
    1.74 -	if (file == NULL)
    1.75 +	if (file == NULL) {
    1.76 +		razor_atomic_abort(atomic, "Not enough memory");
    1.77  		return -1;
    1.78 +	}
    1.79  
    1.80  	file->header = razor_file_get_contents(filename, &file->size);
    1.81  	if (!file->header) {
    1.82 +		msg = razor_concat(filename, ": ", strerror(errno), NULL);
    1.83 +		razor_atomic_abort(atomic, msg);
    1.84 +		free(msg);
    1.85  		free(file);
    1.86  		return -1;
    1.87  	}
    1.88  
    1.89 -	if (file->size < sizeof *file->header ||
    1.90 -	    file->header->magic != RAZOR_MAGIC ||
    1.91 -	    file->header->version != RAZOR_VERSION) {
    1.92 +	if (file->size < sizeof *file->header)
    1.93 +		reason = "Premature EOF";
    1.94 +	else if (file->header->magic != RAZOR_MAGIC)
    1.95 +		reason = "Bad magic number";
    1.96 +	else if (file->header->version < RAZOR_HEADER_VERSION_MIN ||
    1.97 +		 file->header->version > RAZOR_HEADER_VERSION)
    1.98 +		reason = "Incompatible file version";
    1.99 +	else
   1.100 +		reason = NULL;
   1.101 +
   1.102 +	if (reason) {
   1.103 +		msg = razor_concat(filename, ": ", reason, NULL);
   1.104 +		razor_atomic_abort(atomic, msg);
   1.105 +		free(msg);
   1.106  		razor_file_free_contents(file->header, file->size);
   1.107  		free(file);
   1.108  		return -1;
   1.109  	}
   1.110  
   1.111 +	set->header_version = file->header->version;
   1.112 +
   1.113  	if (set->mapped_files == NULL) {
   1.114  		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
   1.115  			array = (void *) set + razor_sections[i].offset;
   1.116 @@ -182,13 +226,18 @@
   1.117  }
   1.118  
   1.119  RAZOR_EXPORT struct razor_set *
   1.120 -razor_set_open(const char *filename)
   1.121 +razor_set_open(const char *filename, struct razor_atomic *atomic)
   1.122  {
   1.123  	struct razor_set *set;
   1.124  
   1.125  	set = zalloc(sizeof *set);
   1.126 +	if (!set) {
   1.127 +		razor_atomic_abort(atomic, "Not enough memory");
   1.128 +		return NULL;
   1.129 +	}
   1.130 +
   1.131  	set->lock_fd = -1;
   1.132 -	if (razor_set_bind_sections(set, filename)){
   1.133 +	if (razor_set_bind_sections(set, atomic, filename)) {
   1.134  		free(set);
   1.135  		return NULL;
   1.136  	}
   1.137 @@ -215,12 +264,14 @@
   1.138  
   1.139  	if (exclusive)
   1.140  		flags |= LOCKFILE_EXCLUSIVE_LOCK;
   1.141 -	if (fd >= 0 && !LockFileEx(_get_osfhandle(fd), flags, 0, 1, 0, &lock)) {
   1.142 +	if (fd >= 0 && !LockFileEx((HANDLE)_get_osfhandle(fd), flags, 0, 1, 0,
   1.143 +				   &lock)) {
   1.144  		close(fd);
   1.145  		return -1;
   1.146  	}
   1.147  	if (set->lock_fd >= 0)
   1.148 -		(void)UnlockFile(_get_osfhandle(set->lock_fd), 0, 0, 1, 0);
   1.149 +		(void)UnlockFile((HANDLE)_get_osfhandle(set->lock_fd), 0, 0, 1,
   1.150 +				 0);
   1.151  #else
   1.152  	struct flock lock = {0};
   1.153  
   1.154 @@ -245,7 +296,7 @@
   1.155  	return 0;
   1.156  }
   1.157  
   1.158 -RAZOR_EXPORT void
   1.159 +static void
   1.160  razor_set_destroy(struct razor_set *set)
   1.161  {
   1.162  	struct razor_mapped_file *file, *next;
   1.163 @@ -271,8 +322,24 @@
   1.164  	free(set);
   1.165  }
   1.166  
   1.167 -RAZOR_EXPORT int
   1.168 -razor_set_write_to_fd(struct razor_set *set, int fd, uint32_t section_mask)
   1.169 +RAZOR_EXPORT void
   1.170 +razor_set_unref(struct razor_set *set)
   1.171 +{
   1.172 +	if (set && !--set->ref_count)
   1.173 +		razor_set_destroy(set);
   1.174 +}
   1.175 +
   1.176 +RAZOR_EXPORT struct razor_set *
   1.177 +razor_set_ref(struct razor_set *set)
   1.178 +{
   1.179 +	if (set)
   1.180 +		set->ref_count++;
   1.181 +	return set;
   1.182 +}
   1.183 +
   1.184 +RAZOR_EXPORT void
   1.185 +razor_set_write_to_handle(struct razor_set *set, struct razor_atomic *atomic,
   1.186 +			  int handle, uint32_t section_mask)
   1.187  {
   1.188  	struct razor_set_header header;
   1.189  	struct razor_set_section sections[ARRAY_SIZE(razor_sections)];
   1.190 @@ -298,7 +365,7 @@
   1.191  
   1.192  	count = j;
   1.193  	header.magic = RAZOR_MAGIC;
   1.194 -	header.version = RAZOR_VERSION;
   1.195 +	header.version = set->header_version;
   1.196  	header.num_sections = count;
   1.197  	offset = sizeof header + count * sizeof *sections + ALIGN(pool.size, 4);
   1.198  
   1.199 @@ -308,38 +375,36 @@
   1.200  		offset += ALIGN(arrays[i]->size, 4);
   1.201  	}
   1.202  
   1.203 -	razor_write(fd, &header, sizeof header);
   1.204 -	razor_write(fd, sections, count * sizeof *sections);
   1.205 -	razor_write(fd, pool.data, pool.size);
   1.206 -	razor_write(fd, padding, PADDING(pool.size, 4));
   1.207 +	razor_atomic_write(atomic, handle, &header, sizeof header);
   1.208 +	razor_atomic_write(atomic, handle, sections, count * sizeof *sections);
   1.209 +	razor_atomic_write(atomic, handle, pool.data, pool.size);
   1.210 +	razor_atomic_write(atomic, handle, padding, PADDING(pool.size, 4));
   1.211  
   1.212  	for (i = 0; i < count; i++) {
   1.213 -		razor_write(fd, arrays[i]->data, arrays[i]->size);
   1.214 -		razor_write(fd, padding, PADDING(arrays[i]->size, 4));
   1.215 +		razor_atomic_write(atomic, handle, arrays[i]->data,
   1.216 +				   arrays[i]->size);
   1.217 +		razor_atomic_write(atomic, handle, padding,
   1.218 +				   PADDING(arrays[i]->size, 4));
   1.219  	}
   1.220  
   1.221  	array_release(&pool);
   1.222  	hashtable_release(&table);
   1.223 -
   1.224 -	return 0;
   1.225  }
   1.226  
   1.227  RAZOR_EXPORT int
   1.228 -razor_set_write(struct razor_set *set, const char *filename, uint32_t sections)
   1.229 +razor_set_write(struct razor_set *set, struct razor_atomic *atomic,
   1.230 +		const char *filename, uint32_t sections)
   1.231  {
   1.232 -	int fd, status;
   1.233 +	int h;
   1.234  
   1.235 -	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666);
   1.236 -	if (fd < 0)
   1.237 +	h = razor_atomic_create_file(atomic, filename,
   1.238 +				     S_IRWXU | S_IRWXG | S_IRWXO);
   1.239 +	if (h < 0)
   1.240  		return -1;
   1.241  
   1.242 -	status = razor_set_write_to_fd(set, fd, sections);
   1.243 -	if (status) {
   1.244 -	    close(fd);
   1.245 -	    return status;
   1.246 -	}
   1.247 +	razor_set_write_to_handle(set, atomic, h, sections);
   1.248  
   1.249 -	return close(fd);
   1.250 +	return razor_atomic_close(atomic, h);
   1.251  }
   1.252  
   1.253  RAZOR_EXPORT void
   1.254 @@ -554,74 +619,86 @@
   1.255   * @package: a %razor_package
   1.256   * @root: the root into which the package is currently installed
   1.257   * @install_count: the value to pass to uninstall scripts
   1.258 + * @stage: Limit the removal to just the scripts or the files
   1.259   *
   1.260   * Removes an installed package.
   1.261   **/
   1.262  RAZOR_EXPORT int
   1.263  razor_package_remove(struct razor_set *prev, struct razor_set *next,
   1.264 -		     struct razor_package *package, const char *root,
   1.265 -		     int install_count)
   1.266 +		     struct razor_atomic *atomic, struct razor_package *package,
   1.267 +		     const char *root, int install_count,
   1.268 +		     enum razor_stage_type stage)
   1.269  {
   1.270  	struct razor_file_iterator *fi;
   1.271  	struct razor_package_iterator *pi;
   1.272  	struct razor_package *p;
   1.273 -	char buffer[PATH_MAX];
   1.274 +	char *buffer;
   1.275  	const char *name, *program, *script;
   1.276 -	int retval = 0, i, count;
   1.277 +	int i, count;
   1.278  	struct environment env;
   1.279  	struct list *link;
   1.280  	const char *prefix;
   1.281  
   1.282 -	environment_init(&env);
   1.283 -	link = list_first(&package->install_prefixes, &prev->prefix_pool);
   1.284 -	for (i = 0; link; i++) {
   1.285 -		prefix = (const char *)prev->string_pool.data + link->data;
   1.286 -		sprintf(buffer, "RPM_INSTALL_PREFIX%d", i);
   1.287 -		environment_add_variable(&env, buffer, prefix);
   1.288 -		link = list_next(link);
   1.289 +	if (stage & RAZOR_STAGE_SCRIPTS) {
   1.290 +		environment_init(&env);
   1.291 +		link = list_first(&package->install_prefixes,
   1.292 +				  &prev->prefix_pool);
   1.293 +		for (i = 0; link; i++) {
   1.294 +			prefix = (const char *)prev->string_pool.data +
   1.295 +				 link->data;
   1.296 +			sprintf(buffer, "RPM_INSTALL_PREFIX%d", i);
   1.297 +			environment_add_variable(&env, buffer, prefix);
   1.298 +			link = list_next(link);
   1.299 +		}
   1.300 +		environment_set(&env);
   1.301  	}
   1.302 -	environment_set(&env);
   1.303  
   1.304 -	razor_package_get_details(prev, package,
   1.305 -				  RAZOR_DETAIL_PREUNPROG, &program,
   1.306 -				  RAZOR_DETAIL_PREUN, &script,
   1.307 -				  RAZOR_DETAIL_LAST);
   1.308 +	if (stage & RAZOR_STAGE_SCRIPTS_PRE) {
   1.309 +		razor_package_get_details(prev, package,
   1.310 +					  RAZOR_DETAIL_PREUNPROG, &program,
   1.311 +					  RAZOR_DETAIL_PREUN, &script,
   1.312 +					  RAZOR_DETAIL_LAST);
   1.313  
   1.314 -	retval = razor_run_script(root, RAZOR_PROPERTY_PREUN, program, script,
   1.315 -				  install_count);
   1.316 +		razor_run_script(root, RAZOR_PROPERTY_PREUN, program,
   1.317 +				 script, install_count);
   1.318 +	}
   1.319  
   1.320 -	fi = razor_file_iterator_create(prev, package, 1);
   1.321 +	if (stage & RAZOR_STAGE_FILES) {
   1.322 +		fi = razor_file_iterator_create(prev, package, 1);
   1.323  
   1.324 -	while (razor_file_iterator_next(fi, &name)) {
   1.325 -		pi = razor_package_iterator_create_for_file(next, name);
   1.326 -		count = 0;
   1.327 -		while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST))
   1.328 -			count++;
   1.329 -		razor_package_iterator_destroy(pi);
   1.330 -		if (count <= 0) {
   1.331 -			snprintf(buffer, sizeof buffer, "%s%s", root, name);
   1.332 -			if (razor_remove(buffer) && errno != ENOENT) {
   1.333 -				perror(name);
   1.334 -				retval = -1;
   1.335 +		while (razor_file_iterator_next(fi, &name)) {
   1.336 +			pi = razor_package_iterator_create_for_file(next, name);
   1.337 +			count = 0;
   1.338 +			while (razor_package_iterator_next(pi, &p,
   1.339 +							   RAZOR_DETAIL_LAST))
   1.340 +				count++;
   1.341 +			razor_package_iterator_destroy(pi);
   1.342 +			if (count <= 0) {
   1.343 +				buffer = razor_concat(root, name, NULL);
   1.344 +				razor_atomic_remove(atomic, buffer);
   1.345 +				free(buffer);
   1.346  			}
   1.347  		}
   1.348 +
   1.349 +		razor_file_iterator_destroy(fi);
   1.350  	}
   1.351  
   1.352 -	razor_file_iterator_destroy(fi);
   1.353 +	if (stage & RAZOR_STAGE_SCRIPTS_POST) {
   1.354 +		razor_package_get_details(prev, package,
   1.355 +					  RAZOR_DETAIL_POSTUNPROG, &program,
   1.356 +					  RAZOR_DETAIL_POSTUN, &script,
   1.357 +					  RAZOR_DETAIL_LAST);
   1.358  
   1.359 -	razor_package_get_details(prev, package,
   1.360 -				  RAZOR_DETAIL_POSTUNPROG, &program,
   1.361 -				  RAZOR_DETAIL_POSTUN, &script,
   1.362 -				  RAZOR_DETAIL_LAST);
   1.363 +		razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script,
   1.364 +				 install_count);
   1.365 +	}
   1.366  
   1.367 -	if (razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script,
   1.368 -			     install_count))
   1.369 -		retval = -1;
   1.370 +	if (stage & RAZOR_STAGE_SCRIPTS) {
   1.371 +		environment_unset(&env);
   1.372 +		environment_release(&env);
   1.373 +	}
   1.374  
   1.375 -	environment_unset(&env);
   1.376 -	environment_release(&env);
   1.377 -
   1.378 -	return retval;
   1.379 +	return razor_atomic_in_error_state(atomic);
   1.380  }
   1.381  
   1.382  RAZOR_EXPORT const char *
   1.383 @@ -887,7 +964,7 @@
   1.384  	struct razor_set *set;
   1.385  	struct razor_set *next;
   1.386  	struct array actions;
   1.387 -	struct deque *order;
   1.388 +	struct deque *order, *left;
   1.389  };
   1.390  
   1.391  static void
   1.392 @@ -989,6 +1066,7 @@
   1.393  	}
   1.394  
   1.395  	ii->order = graph_sort(&follows);
   1.396 +	ii->left = deque_dup(ii->order);
   1.397  	graph_release(&follows);
   1.398  
   1.399  	return ii;
   1.400 @@ -1005,10 +1083,10 @@
   1.401  	struct razor_package *pkg;
   1.402  	const char *removing, *name;
   1.403  
   1.404 -	if (deque_empty(ii->order))
   1.405 +	if (deque_empty(ii->left))
   1.406  		return 0;
   1.407  
   1.408 -	a = (struct install_action *)ii->actions.data + deque_pop(ii->order);
   1.409 +	a = (struct install_action *)ii->actions.data + deque_pop(ii->left);
   1.410  	*package = a->package;
   1.411  	*action = a->action;
   1.412  	*count = 0;
   1.413 @@ -1026,15 +1104,24 @@
   1.414  				(*count)++;
   1.415  		}
   1.416  		razor_package_iterator_destroy(pi);
   1.417 -	}
   1.418 +	} else
   1.419 +		*count = 1;
   1.420  
   1.421  	return 1;
   1.422  }
   1.423  
   1.424  RAZOR_EXPORT void
   1.425 +razor_install_iterator_rewind(struct razor_install_iterator *ii)
   1.426 +{
   1.427 +	deque_free(ii->left);
   1.428 +	ii->left=deque_dup(ii->order);
   1.429 +}
   1.430 +
   1.431 +RAZOR_EXPORT void
   1.432  razor_install_iterator_destroy(struct razor_install_iterator *ii)
   1.433  {
   1.434  	array_release(&ii->actions);
   1.435  	deque_free(ii->order);
   1.436 +	deque_free(ii->left);
   1.437  	free(ii);
   1.438  }