diff -r ed134fdfe95f -r f960eb19dca2 librazor/razor.c --- a/librazor/razor.c Wed Apr 28 11:59:02 2010 +0100 +++ b/librazor/razor.c Fri Jan 27 07:55:30 2012 +0000 @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Kristian Høgsberg * Copyright (C) 2008 Red Hat, Inc - * Copyright (C) 2009, 2010 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 @@ -93,10 +93,16 @@ set = zalloc(sizeof *set); - empty = array_add(&set->string_pool, 1); - *empty = '\0'; + if (set) { + empty = array_add(&set->string_pool, 1); + *empty = '\0'; - set->lock_fd = -1; + set->lock_fd = -1; + + set->ref_count = 1; + + set->header_version = RAZOR_HEADER_VERSION; + } return set; } @@ -118,6 +124,24 @@ return set; } +RAZOR_EXPORT uint32_t +razor_set_get_header_version(struct razor_set *set) +{ + return set->header_version; +} + +RAZOR_EXPORT int +razor_set_set_header_version(struct razor_set *set, uint32_t header_version) +{ + if (header_versionRAZOR_HEADER_VERSION) + return -1; + else { + set->header_version = header_version; + return 0; + } +} + struct razor_mapped_file { struct razor_set_header *header; size_t size; @@ -125,32 +149,52 @@ }; RAZOR_EXPORT int -razor_set_bind_sections(struct razor_set *set, const char *filename) +razor_set_bind_sections(struct razor_set *set, struct razor_atomic *atomic, + const char *filename) { struct razor_set_section *s, *sections; struct razor_mapped_file *file; - const char *pool; + const char *pool, *reason; + char *msg; struct array *array; int i, j; file = zalloc(sizeof *file); - if (file == NULL) + if (file == NULL) { + razor_atomic_abort(atomic, "Not enough memory"); return -1; + } file->header = razor_file_get_contents(filename, &file->size); if (!file->header) { + msg = razor_concat(filename, ": ", strerror(errno), NULL); + razor_atomic_abort(atomic, msg); + free(msg); free(file); return -1; } - if (file->size < sizeof *file->header || - file->header->magic != RAZOR_MAGIC || - file->header->version != RAZOR_VERSION) { + if (file->size < sizeof *file->header) + reason = "Premature EOF"; + else if (file->header->magic != RAZOR_MAGIC) + reason = "Bad magic number"; + else if (file->header->version < RAZOR_HEADER_VERSION_MIN || + file->header->version > RAZOR_HEADER_VERSION) + reason = "Incompatible file version"; + else + reason = NULL; + + if (reason) { + msg = razor_concat(filename, ": ", reason, NULL); + razor_atomic_abort(atomic, msg); + free(msg); razor_file_free_contents(file->header, file->size); free(file); return -1; } + set->header_version = file->header->version; + if (set->mapped_files == NULL) { for (i = 0; i < ARRAY_SIZE(razor_sections); i++) { array = (void *) set + razor_sections[i].offset; @@ -182,13 +226,18 @@ } RAZOR_EXPORT struct razor_set * -razor_set_open(const char *filename) +razor_set_open(const char *filename, struct razor_atomic *atomic) { struct razor_set *set; set = zalloc(sizeof *set); + if (!set) { + razor_atomic_abort(atomic, "Not enough memory"); + return NULL; + } + set->lock_fd = -1; - if (razor_set_bind_sections(set, filename)){ + if (razor_set_bind_sections(set, atomic, filename)) { free(set); return NULL; } @@ -215,12 +264,14 @@ if (exclusive) flags |= LOCKFILE_EXCLUSIVE_LOCK; - if (fd >= 0 && !LockFileEx(_get_osfhandle(fd), flags, 0, 1, 0, &lock)) { + if (fd >= 0 && !LockFileEx((HANDLE)_get_osfhandle(fd), flags, 0, 1, 0, + &lock)) { close(fd); return -1; } if (set->lock_fd >= 0) - (void)UnlockFile(_get_osfhandle(set->lock_fd), 0, 0, 1, 0); + (void)UnlockFile((HANDLE)_get_osfhandle(set->lock_fd), 0, 0, 1, + 0); #else struct flock lock = {0}; @@ -245,7 +296,7 @@ return 0; } -RAZOR_EXPORT void +static void razor_set_destroy(struct razor_set *set) { struct razor_mapped_file *file, *next; @@ -271,8 +322,24 @@ free(set); } -RAZOR_EXPORT int -razor_set_write_to_fd(struct razor_set *set, int fd, uint32_t section_mask) +RAZOR_EXPORT void +razor_set_unref(struct razor_set *set) +{ + if (set && !--set->ref_count) + razor_set_destroy(set); +} + +RAZOR_EXPORT struct razor_set * +razor_set_ref(struct razor_set *set) +{ + if (set) + set->ref_count++; + return set; +} + +RAZOR_EXPORT void +razor_set_write_to_handle(struct razor_set *set, struct razor_atomic *atomic, + int handle, uint32_t section_mask) { struct razor_set_header header; struct razor_set_section sections[ARRAY_SIZE(razor_sections)]; @@ -298,7 +365,7 @@ count = j; header.magic = RAZOR_MAGIC; - header.version = RAZOR_VERSION; + header.version = set->header_version; header.num_sections = count; offset = sizeof header + count * sizeof *sections + ALIGN(pool.size, 4); @@ -308,38 +375,36 @@ offset += ALIGN(arrays[i]->size, 4); } - razor_write(fd, &header, sizeof header); - razor_write(fd, sections, count * sizeof *sections); - razor_write(fd, pool.data, pool.size); - razor_write(fd, padding, PADDING(pool.size, 4)); + razor_atomic_write(atomic, handle, &header, sizeof header); + razor_atomic_write(atomic, handle, sections, count * sizeof *sections); + razor_atomic_write(atomic, handle, pool.data, pool.size); + razor_atomic_write(atomic, handle, padding, PADDING(pool.size, 4)); for (i = 0; i < count; i++) { - razor_write(fd, arrays[i]->data, arrays[i]->size); - razor_write(fd, padding, PADDING(arrays[i]->size, 4)); + razor_atomic_write(atomic, handle, arrays[i]->data, + arrays[i]->size); + razor_atomic_write(atomic, handle, padding, + PADDING(arrays[i]->size, 4)); } array_release(&pool); hashtable_release(&table); - - return 0; } RAZOR_EXPORT int -razor_set_write(struct razor_set *set, const char *filename, uint32_t sections) +razor_set_write(struct razor_set *set, struct razor_atomic *atomic, + const char *filename, uint32_t sections) { - int fd, status; + int h; - fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666); - if (fd < 0) + h = razor_atomic_create_file(atomic, filename, + S_IRWXU | S_IRWXG | S_IRWXO); + if (h < 0) return -1; - status = razor_set_write_to_fd(set, fd, sections); - if (status) { - close(fd); - return status; - } + razor_set_write_to_handle(set, atomic, h, sections); - return close(fd); + return razor_atomic_close(atomic, h); } RAZOR_EXPORT void @@ -554,74 +619,86 @@ * @package: a %razor_package * @root: the root into which the package is currently installed * @install_count: the value to pass to uninstall scripts + * @stage: Limit the removal to just the scripts or the files * * Removes an installed package. **/ RAZOR_EXPORT int razor_package_remove(struct razor_set *prev, struct razor_set *next, - struct razor_package *package, const char *root, - int install_count) + struct razor_atomic *atomic, struct razor_package *package, + const char *root, int install_count, + enum razor_stage_type stage) { struct razor_file_iterator *fi; struct razor_package_iterator *pi; struct razor_package *p; - char buffer[PATH_MAX]; + char *buffer; const char *name, *program, *script; - int retval = 0, i, count; + int i, count; struct environment env; struct list *link; const char *prefix; - environment_init(&env); - link = list_first(&package->install_prefixes, &prev->prefix_pool); - for (i = 0; link; i++) { - prefix = (const char *)prev->string_pool.data + link->data; - sprintf(buffer, "RPM_INSTALL_PREFIX%d", i); - environment_add_variable(&env, buffer, prefix); - link = list_next(link); + if (stage & RAZOR_STAGE_SCRIPTS) { + environment_init(&env); + link = list_first(&package->install_prefixes, + &prev->prefix_pool); + for (i = 0; link; i++) { + prefix = (const char *)prev->string_pool.data + + link->data; + sprintf(buffer, "RPM_INSTALL_PREFIX%d", i); + environment_add_variable(&env, buffer, prefix); + link = list_next(link); + } + environment_set(&env); } - environment_set(&env); - razor_package_get_details(prev, package, - RAZOR_DETAIL_PREUNPROG, &program, - RAZOR_DETAIL_PREUN, &script, - RAZOR_DETAIL_LAST); + if (stage & RAZOR_STAGE_SCRIPTS_PRE) { + razor_package_get_details(prev, package, + RAZOR_DETAIL_PREUNPROG, &program, + RAZOR_DETAIL_PREUN, &script, + RAZOR_DETAIL_LAST); - retval = razor_run_script(root, RAZOR_PROPERTY_PREUN, program, script, - install_count); + razor_run_script(root, RAZOR_PROPERTY_PREUN, program, + script, install_count); + } - fi = razor_file_iterator_create(prev, package, 1); + if (stage & RAZOR_STAGE_FILES) { + fi = razor_file_iterator_create(prev, package, 1); - while (razor_file_iterator_next(fi, &name)) { - pi = razor_package_iterator_create_for_file(next, name); - count = 0; - while (razor_package_iterator_next(pi, &p, RAZOR_DETAIL_LAST)) - count++; - razor_package_iterator_destroy(pi); - if (count <= 0) { - snprintf(buffer, sizeof buffer, "%s%s", root, name); - if (razor_remove(buffer) && errno != ENOENT) { - perror(name); - retval = -1; + while (razor_file_iterator_next(fi, &name)) { + pi = razor_package_iterator_create_for_file(next, name); + count = 0; + while (razor_package_iterator_next(pi, &p, + RAZOR_DETAIL_LAST)) + count++; + razor_package_iterator_destroy(pi); + if (count <= 0) { + buffer = razor_concat(root, name, NULL); + razor_atomic_remove(atomic, buffer); + free(buffer); } } + + razor_file_iterator_destroy(fi); } - razor_file_iterator_destroy(fi); + if (stage & RAZOR_STAGE_SCRIPTS_POST) { + razor_package_get_details(prev, package, + RAZOR_DETAIL_POSTUNPROG, &program, + RAZOR_DETAIL_POSTUN, &script, + RAZOR_DETAIL_LAST); - razor_package_get_details(prev, package, - RAZOR_DETAIL_POSTUNPROG, &program, - RAZOR_DETAIL_POSTUN, &script, - RAZOR_DETAIL_LAST); + razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script, + install_count); + } - if (razor_run_script(root, RAZOR_PROPERTY_POSTUN, program, script, - install_count)) - retval = -1; + if (stage & RAZOR_STAGE_SCRIPTS) { + environment_unset(&env); + environment_release(&env); + } - environment_unset(&env); - environment_release(&env); - - return retval; + return razor_atomic_in_error_state(atomic); } RAZOR_EXPORT const char * @@ -887,7 +964,7 @@ struct razor_set *set; struct razor_set *next; struct array actions; - struct deque *order; + struct deque *order, *left; }; static void @@ -989,6 +1066,7 @@ } ii->order = graph_sort(&follows); + ii->left = deque_dup(ii->order); graph_release(&follows); return ii; @@ -1005,10 +1083,10 @@ struct razor_package *pkg; const char *removing, *name; - if (deque_empty(ii->order)) + if (deque_empty(ii->left)) return 0; - a = (struct install_action *)ii->actions.data + deque_pop(ii->order); + a = (struct install_action *)ii->actions.data + deque_pop(ii->left); *package = a->package; *action = a->action; *count = 0; @@ -1026,15 +1104,24 @@ (*count)++; } razor_package_iterator_destroy(pi); - } + } else + *count = 1; return 1; } RAZOR_EXPORT void +razor_install_iterator_rewind(struct razor_install_iterator *ii) +{ + deque_free(ii->left); + ii->left=deque_dup(ii->order); +} + +RAZOR_EXPORT void razor_install_iterator_destroy(struct razor_install_iterator *ii) { array_release(&ii->actions); deque_free(ii->order); + deque_free(ii->left); free(ii); }