From 88ba635780723be9cd3ada430fcc9a6ca1f34e42 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sat, 28 Nov 2009 05:43:21 +0100 Subject: [PATCH] Split unpack.c config files and remove obsoletes code into its own files. --HG-- extra : convert_revision : xtraeme%40gmail.com-20091128044321-6kmhrrxggv2h681w --- include/xbps_api.h | 27 +++- lib/Makefile | 1 + lib/config_files.c | 225 +++++++++++++++++++++++++++++++ lib/remove_obsoletes.c | 121 +++++++++++++++++ lib/unpack.c | 298 +---------------------------------------- 5 files changed, 373 insertions(+), 299 deletions(-) create mode 100644 lib/config_files.c create mode 100644 lib/remove_obsoletes.c diff --git a/include/xbps_api.h b/include/xbps_api.h index 5f1e8528..da980cd5 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -69,6 +69,13 @@ #define ARCHIVE_READ_BLOCKSIZE 10240 +#define EXTRACT_FLAGS ARCHIVE_EXTRACT_SECURE_NODOTDOT | \ + ARCHIVE_EXTRACT_SECURE_SYMLINKS | \ + ARCHIVE_EXTRACT_NO_OVERWRITE | \ + ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER +#define FEXTRACT_FLAGS ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | \ + ARCHIVE_EXTRACT_TIME | EXTRACT_FLAGS + #ifndef __UNCONST #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #endif @@ -87,6 +94,13 @@ __BEGIN_DECLS +/* From lib/config_files.c */ +int xbps_config_file_from_archive_entry(prop_dictionary_t, + struct archive_entry *, + const char *, + int *, + bool *); + /* From lib/configure.c */ int SYMEXPORT xbps_configure_pkg(const char *, const char *, bool); int SYMEXPORT xbps_configure_all_pkgs(void); @@ -157,12 +171,14 @@ bool SYMEXPORT xbps_find_string_in_array(prop_array_t, const char *); prop_object_iterator_t SYMEXPORT xbps_get_array_iter_from_dict(prop_dictionary_t, const char *); -prop_dictionary_t SYMEXPORT xbps_read_dict_from_archive_entry(struct archive *, - struct archive_entry *); +prop_dictionary_t SYMEXPORT + xbps_read_dict_from_archive_entry(struct archive *, + struct archive_entry *); int SYMEXPORT xbps_remove_pkg_dict_from_file(const char *, const char *); -int SYMEXPORT xbps_remove_pkg_from_dict(prop_dictionary_t, const char *, - const char *); +int SYMEXPORT + xbps_remove_pkg_from_dict(prop_dictionary_t, const char *, + const char *); int SYMEXPORT xbps_remove_string_from_array(prop_array_t, const char *); /* From lib/purge.c */ @@ -180,6 +196,9 @@ void SYMEXPORT xbps_regpkgs_dictionary_release(void); /* From lib/remove.c */ int SYMEXPORT xbps_remove_pkg(const char *, const char *, bool); +/* From lib/remove_obsoletes.c */ +int xbps_remove_obsoletes(prop_dictionary_t, prop_dictionary_t); + /* From lib/repository.c */ int SYMEXPORT xbps_register_repository(const char *); int SYMEXPORT xbps_unregister_repository(const char *); diff --git a/lib/Makefile b/lib/Makefile index 6c6e28c2..38c643a5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -19,6 +19,7 @@ OBJS += humanize_number.o orphans.o plist.o purge.o register.o remove.o OBJS += repository.o requiredby.o sha256.o sortdeps.o state.o OBJS += sync_remote_pkgidx.o unpack.o util.o pkgmatch.o mkpath.o OBJS += regpkgs_dictionary.o repository_plist.o repository_pool.o +OBJS += remove_obsoletes.o config_files.o .PHONY: all all: libfetch libxbps.so libxbps.a diff --git a/lib/config_files.c b/lib/config_files.c new file mode 100644 index 00000000..01e8d652 --- /dev/null +++ b/lib/config_files.c @@ -0,0 +1,225 @@ +/*- + * Copyright (c) 2009 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include + +int +xbps_config_file_from_archive_entry(prop_dictionary_t d, + struct archive_entry *entry, + const char *pkgname, + int *flags, + bool *skip) +{ + prop_dictionary_t forigd; + prop_object_t obj, obj2; + prop_object_iterator_t iter, iter2; + const char *cffile, *sha256_new = NULL; + char *buf, *sha256_cur = NULL, *sha256_orig = NULL; + int rv = 0; + bool install_new = false; + + if (d == NULL) + return 0; + + iter = xbps_get_array_iter_from_dict(d, "conf_files"); + if (iter == NULL) + return 0; + + /* + * Get original hash for the file from current + * installed package. + */ + buf = xbps_xasprintf(".%s/metadata/%s/%s", XBPS_META_PATH, + pkgname, XBPS_PKGFILES); + if (buf == NULL) + return errno; + + forigd = prop_dictionary_internalize_from_file(buf); + free(buf); + if (forigd == NULL) { + install_new = true; + goto out; + } + + iter2 = xbps_get_array_iter_from_dict(forigd, "conf_files"); + if (iter2 != NULL) { + while ((obj2 = prop_object_iterator_next(iter2))) { + if (!prop_dictionary_get_cstring_nocopy(obj2, + "file", &cffile)) { + prop_object_iterator_release(iter2); + rv = errno; + goto out; + } + buf = xbps_xasprintf(".%s", cffile); + if (buf == NULL) { + prop_object_iterator_release(iter2); + rv = errno; + goto out; + } + if (strcmp(archive_entry_pathname(entry), buf) == 0) { + prop_dictionary_get_cstring(obj2, "sha256", + &sha256_orig); + free(buf); + break; + } + free(buf); + buf = NULL; + } + prop_object_iterator_release(iter2); + } + prop_object_release(forigd); + /* + * First case: original hash not found, install new file. + */ + if (sha256_orig == NULL) { + install_new = true; + goto out; + } + + /* + * Compare original, installed and new hash for current file. + */ + while ((obj = prop_object_iterator_next(iter))) { + if (!prop_dictionary_get_cstring_nocopy(obj, + "file", &cffile)) { + prop_object_iterator_release(iter); + return errno; + } + buf = xbps_xasprintf(".%s", cffile); + if (buf == NULL) { + prop_object_iterator_release(iter); + return errno; + } + if (strcmp(archive_entry_pathname(entry), buf)) { + free(buf); + buf = NULL; + continue; + } + sha256_cur = xbps_get_file_hash(buf); + free(buf); + if (!prop_dictionary_get_cstring_nocopy(obj, + "sha256", &sha256_new)) { + rv = EINVAL; + break; + } + if (sha256_cur == NULL) { + if (errno == ENOENT) { + /* + * File not installed, install new one. + */ + install_new = true; + break; + } else { + rv = errno; + break; + } + } + + /* + * Orig = X, Curr = X, New = X + * + * Install new file. + */ + if ((strcmp(sha256_orig, sha256_cur) == 0) && + (strcmp(sha256_orig, sha256_new) == 0) && + (strcmp(sha256_cur, sha256_new) == 0)) { + install_new = true; + break; + /* + * Orig = X, Curr = X, New = Y + * + * Install new file. + */ + } else if ((strcmp(sha256_orig, sha256_cur) == 0) && + (strcmp(sha256_orig, sha256_new)) && + (strcmp(sha256_cur, sha256_new))) { + printf("Updating %s file with new version.\n", + cffile); + install_new = true; + break; + /* + * Orig = X, Curr = Y, New = X + * + * Keep current file as is. + */ + } else if ((strcmp(sha256_orig, sha256_new) == 0) && + (strcmp(sha256_cur, sha256_new)) && + (strcmp(sha256_orig, sha256_cur))) { + printf("Keeping modified file %s.\n", cffile); + *skip = true; + break; + /* + * Orig = X, Curr = Y, New = Y + * + * Install new file. + */ + } else if ((strcmp(sha256_cur, sha256_new) == 0) && + (strcmp(sha256_orig, sha256_new)) && + (strcmp(sha256_orig, sha256_cur))) { + install_new = true; + break; + /* + * Orig = X, Curr = Y, New = Z + * + * Install new file as file.new. + */ + } else if ((strcmp(sha256_orig, sha256_cur)) && + (strcmp(sha256_cur, sha256_new)) && + (strcmp(sha256_orig, sha256_new))) { + buf = xbps_xasprintf(".%s.new", cffile); + if (buf == NULL) { + rv = errno; + break; + } + printf("Keeping modified file %s.\n", cffile); + printf("Installing new version as %s.new.\n", cffile); + install_new = true; + archive_entry_set_pathname(entry, buf); + free(buf); + break; + } + } + +out: + if (install_new) { + *flags &= ~ARCHIVE_EXTRACT_NO_OVERWRITE; + *flags &= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; + } + if (sha256_orig) + free(sha256_orig); + if (sha256_cur) + free(sha256_cur); + + prop_object_iterator_release(iter); + + return rv; +} diff --git a/lib/remove_obsoletes.c b/lib/remove_obsoletes.c new file mode 100644 index 00000000..4c275188 --- /dev/null +++ b/lib/remove_obsoletes.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2009 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include + +int +xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd) +{ + prop_object_iterator_t iter, iter2; + prop_object_t obj, obj2; + prop_string_t oldstr, newstr; + const char *array_str = "files"; + char *buf = NULL; + int rv = 0; + bool found, dolinks = false; + + iter = iter2 = NULL; + obj = obj2 = NULL; + oldstr = newstr = NULL; + +again: + iter = xbps_get_array_iter_from_dict(oldd, array_str); + if (iter == NULL) + return errno; + iter2 = xbps_get_array_iter_from_dict(newd, array_str); + if (iter2 == NULL) { + prop_object_iterator_release(iter); + return errno; + } + /* + * Check for obsolete files, i.e files/links available in + * the old package list not found in new package list. + */ + while ((obj = prop_object_iterator_next(iter))) { + found = false; + oldstr = prop_dictionary_get(obj, "file"); + if (oldstr == NULL) { + rv = errno; + goto out; + } + while ((obj2 = prop_object_iterator_next(iter2))) { + newstr = prop_dictionary_get(obj2, "file"); + if (newstr == NULL) { + rv = errno; + goto out; + } + if (prop_string_equals(oldstr, newstr)) { + found = true; + break; + } + } + prop_object_iterator_reset(iter2); + if (found) + continue; + + /* + * Obsolete file found, remove it. + */ + buf = xbps_xasprintf(".%s", prop_string_cstring_nocopy(oldstr)); + if (buf == NULL) { + rv = errno; + goto out; + } + if (remove(buf) == -1) { + printf("WARNING: couldn't remove obsolete %s: %s\n", + dolinks ? "link" : "file", + prop_string_cstring_nocopy(oldstr)); + free(buf); + continue; + } + printf("Removed obsolete %s: %s\n", + dolinks ? "link" : "file", + prop_string_cstring_nocopy(oldstr)); + free(buf); + } + if (!dolinks) { + /* + * Now look for obsolete links. + */ + dolinks = true; + array_str = "links"; + prop_object_iterator_release(iter2); + prop_object_iterator_release(iter); + iter = iter2 = NULL; + goto again; + } + +out: + prop_object_iterator_release(iter2); + prop_object_iterator_release(iter); + + return rv; +} diff --git a/lib/unpack.c b/lib/unpack.c index d6296c7b..a444ff83 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -33,7 +33,6 @@ #include static int unpack_archive_fini(struct archive *, prop_dictionary_t, bool); -static int remove_obsoletes(prop_dictionary_t, prop_dictionary_t); static void set_extract_flags(int *); int SYMEXPORT @@ -102,19 +101,6 @@ out: return rv; } -/* - * Flags for extracting files in binary packages. If a package - * is marked as "essential", its files will be overwritten and then - * the old and new dictionaries are compared to find out if there - * are some files that were in the old package that should be removed. - */ -#define EXTRACT_FLAGS ARCHIVE_EXTRACT_SECURE_NODOTDOT | \ - ARCHIVE_EXTRACT_SECURE_SYMLINKS | \ - ARCHIVE_EXTRACT_NO_OVERWRITE | \ - ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER -#define FEXTRACT_FLAGS ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | \ - ARCHIVE_EXTRACT_TIME | EXTRACT_FLAGS - static void set_extract_flags(int *flags) { @@ -125,195 +111,6 @@ set_extract_flags(int *flags) *flags = EXTRACT_FLAGS; } -static int -install_config_file(prop_dictionary_t d, struct archive_entry *entry, - const char *pkgname, int *flags, bool *skip) -{ - prop_dictionary_t forigd; - prop_object_t obj, obj2; - prop_object_iterator_t iter, iter2; - const char *cffile, *sha256_new = NULL; - char *buf, *sha256_cur = NULL, *sha256_orig = NULL; - int rv = 0; - bool install_new = false; - - if (d == NULL) - return 0; - - iter = xbps_get_array_iter_from_dict(d, "conf_files"); - if (iter == NULL) - return 0; - - /* - * Get original hash for the file from current - * installed package. - */ - buf = xbps_xasprintf(".%s/metadata/%s/%s", XBPS_META_PATH, - pkgname, XBPS_PKGFILES); - if (buf == NULL) - return errno; - - forigd = prop_dictionary_internalize_from_file(buf); - free(buf); - if (forigd == NULL) { - install_new = true; - goto out; - } - - iter2 = xbps_get_array_iter_from_dict(forigd, "conf_files"); - if (iter2 != NULL) { - while ((obj2 = prop_object_iterator_next(iter2))) { - if (!prop_dictionary_get_cstring_nocopy(obj2, - "file", &cffile)) { - prop_object_iterator_release(iter2); - rv = errno; - goto out; - } - buf = xbps_xasprintf(".%s", cffile); - if (buf == NULL) { - prop_object_iterator_release(iter2); - rv = errno; - goto out; - } - if (strcmp(archive_entry_pathname(entry), buf) == 0) { - prop_dictionary_get_cstring(obj2, "sha256", - &sha256_orig); - free(buf); - break; - } - free(buf); - buf = NULL; - } - prop_object_iterator_release(iter2); - } - prop_object_release(forigd); - /* - * First case: original hash not found, install new file. - */ - if (sha256_orig == NULL) { - install_new = true; - goto out; - } - - /* - * Compare original, installed and new hash for current file. - */ - while ((obj = prop_object_iterator_next(iter))) { - if (!prop_dictionary_get_cstring_nocopy(obj, - "file", &cffile)) { - prop_object_iterator_release(iter); - return errno; - } - buf = xbps_xasprintf(".%s", cffile); - if (buf == NULL) { - prop_object_iterator_release(iter); - return errno; - } - if (strcmp(archive_entry_pathname(entry), buf)) { - free(buf); - buf = NULL; - continue; - } - sha256_cur = xbps_get_file_hash(buf); - free(buf); - if (!prop_dictionary_get_cstring_nocopy(obj, - "sha256", &sha256_new)) { - rv = EINVAL; - break; - } - if (sha256_cur == NULL) { - if (errno == ENOENT) { - /* - * File not installed, install new one. - */ - install_new = true; - break; - } else { - rv = errno; - break; - } - } - - /* - * Orig = X, Curr = X, New = X - * - * Install new file. - */ - if ((strcmp(sha256_orig, sha256_cur) == 0) && - (strcmp(sha256_orig, sha256_new) == 0) && - (strcmp(sha256_cur, sha256_new) == 0)) { - install_new = true; - break; - /* - * Orig = X, Curr = X, New = Y - * - * Install new file. - */ - } else if ((strcmp(sha256_orig, sha256_cur) == 0) && - (strcmp(sha256_orig, sha256_new)) && - (strcmp(sha256_cur, sha256_new))) { - printf("Updating %s file with new version.\n", - cffile); - install_new = true; - break; - /* - * Orig = X, Curr = Y, New = X - * - * Keep current file as is. - */ - } else if ((strcmp(sha256_orig, sha256_new) == 0) && - (strcmp(sha256_cur, sha256_new)) && - (strcmp(sha256_orig, sha256_cur))) { - printf("Keeping modified file %s.\n", cffile); - *skip = true; - break; - /* - * Orig = X, Curr = Y, New = Y - * - * Install new file. - */ - } else if ((strcmp(sha256_cur, sha256_new) == 0) && - (strcmp(sha256_orig, sha256_new)) && - (strcmp(sha256_orig, sha256_cur))) { - install_new = true; - break; - /* - * Orig = X, Curr = Y, New = Z - * - * Install new file as file.new. - */ - } else if ((strcmp(sha256_orig, sha256_cur)) && - (strcmp(sha256_cur, sha256_new)) && - (strcmp(sha256_orig, sha256_new))) { - buf = xbps_xasprintf(".%s.new", cffile); - if (buf == NULL) { - rv = errno; - break; - } - printf("Keeping modified file %s.\n", cffile); - printf("Installing new version as %s.new.\n", cffile); - install_new = true; - archive_entry_set_pathname(entry, buf); - free(buf); - break; - } - } - -out: - if (install_new) { - *flags &= ~ARCHIVE_EXTRACT_NO_OVERWRITE; - *flags &= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; - } - if (sha256_orig) - free(sha256_orig); - if (sha256_cur) - free(sha256_cur); - - prop_object_iterator_release(iter); - - return rv; -} - /* * TODO: remove printfs and return appropiate errors to be interpreted by * the consumer. @@ -425,8 +222,8 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, /* * Handle configuration files. */ - if ((rv = install_config_file(filesd, entry, pkgname, - &lflags, &skip_entry)) != 0) { + if ((rv = xbps_config_file_from_archive_entry(filesd, + entry, pkgname, &lflags, &skip_entry)) != 0) { prop_object_release(filesd); return rv; } @@ -480,7 +277,7 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, free(buf2); return errno; } - rv = remove_obsoletes(old_filesd, filesd); + rv = xbps_remove_obsoletes(old_filesd, filesd); if (rv != 0) { prop_object_release(old_filesd); prop_object_release(filesd); @@ -505,92 +302,3 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, return rv; } - -static int -remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd) -{ - prop_object_iterator_t iter, iter2; - prop_object_t obj, obj2; - prop_string_t oldstr, newstr; - const char *array_str = "files"; - char *buf = NULL; - int rv = 0; - bool found, dolinks = false; - - iter = iter2 = NULL; - obj = obj2 = NULL; - oldstr = newstr = NULL; - -again: - iter = xbps_get_array_iter_from_dict(oldd, array_str); - if (iter == NULL) - return errno; - iter2 = xbps_get_array_iter_from_dict(newd, array_str); - if (iter2 == NULL) { - prop_object_iterator_release(iter); - return errno; - } - /* - * Check for obsolete files, i.e files/links available in - * the old package list not found in new package list. - */ - while ((obj = prop_object_iterator_next(iter))) { - found = false; - oldstr = prop_dictionary_get(obj, "file"); - if (oldstr == NULL) { - rv = errno; - goto out; - } - while ((obj2 = prop_object_iterator_next(iter2))) { - newstr = prop_dictionary_get(obj2, "file"); - if (newstr == NULL) { - rv = errno; - goto out; - } - if (prop_string_equals(oldstr, newstr)) { - found = true; - break; - } - } - prop_object_iterator_reset(iter2); - if (found) - continue; - - /* - * Obsolete file found, remove it. - */ - buf = xbps_xasprintf(".%s", prop_string_cstring_nocopy(oldstr)); - if (buf == NULL) { - rv = errno; - goto out; - } - if (remove(buf) == -1) { - printf("WARNING: couldn't remove obsolete %s: %s\n", - dolinks ? "link" : "file", - prop_string_cstring_nocopy(oldstr)); - free(buf); - continue; - } - printf("Removed obsolete %s: %s\n", - dolinks ? "link" : "file", - prop_string_cstring_nocopy(oldstr)); - free(buf); - } - if (!dolinks) { - /* - * Now look for obsolete links. - */ - dolinks = true; - array_str = "links"; - prop_object_iterator_release(iter2); - prop_object_iterator_release(iter); - iter = iter2 = NULL; - goto again; - } - -out: - prop_object_iterator_release(iter2); - prop_object_iterator_release(iter); - - return rv; -}