diff --git a/lib/Makefile b/lib/Makefile index 29b3f24e..5833efc7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -43,7 +43,8 @@ OBJS += package_unpack.o package_requiredby.o package_register.o OBJS += package_purge.o package_replaces.o package_properties.o OBJS += transaction_dictionary.o transaction_sortdeps.o OBJS += cmpver.o download.o fexec.o humanize_number.o plist.o -OBJS += plist_archive_entry.o util.o pkgmatch.o mkpath.o initend.o +OBJS += plist_archive_entry.o plist_find.o plist_remove.o +OBJS += util.o pkgmatch.o mkpath.o initend.o OBJS += regpkgdb_dictionary.o repository_register.o OBJS += repository_findpkg.o repository_plist.o repository_finddeps.o OBJS += repository_pool.o repository_sync_index.o diff --git a/lib/plist.c b/lib/plist.c index d3976450..debd3df1 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -166,372 +166,6 @@ xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, return rv; } -static prop_dictionary_t -find_pkg_dict_from_plist(const char *plist, - const char *key, - const char *str, - bool bypattern) -{ - prop_dictionary_t dict, obj, res; - - assert(plist != NULL); - assert(str != NULL); - - dict = prop_dictionary_internalize_from_zfile(plist); - if (dict == NULL) { - xbps_dbg_printf("cannot internalize %s for pkg %s: %s", - plist, str, strerror(errno)); - return NULL; - } - if (bypattern) - obj = xbps_find_pkg_in_dict_by_pattern(dict, key, str); - else - obj = xbps_find_pkg_in_dict_by_name(dict, key, str); - - if (obj == NULL) { - prop_object_release(dict); - return NULL; - } - res = prop_dictionary_copy(obj); - prop_object_release(dict); - - return res; -} - -prop_dictionary_t -xbps_find_pkg_dict_from_plist_by_name(const char *plist, - const char *key, - const char *pkgname) -{ - return find_pkg_dict_from_plist(plist, key, pkgname, false); -} - -prop_dictionary_t -xbps_find_pkg_dict_from_plist_by_pattern(const char *plist, - const char *key, - const char *pattern) -{ - return find_pkg_dict_from_plist(plist, key, pattern, true); -} - -bool -xbps_find_virtual_pkg_in_dict(prop_dictionary_t d, - const char *str, - bool bypattern) -{ - prop_array_t provides; - bool found = false; - - if ((provides = prop_dictionary_get(d, "provides"))) { - if (bypattern) - found = xbps_find_pkgpattern_in_array(provides, str); - else - found = xbps_find_pkgname_in_array(provides, str); - } - return found; -} - -static prop_dictionary_t -find_pkg_in_array(prop_array_t array, const char *str, bool bypattern) -{ - prop_object_iterator_t iter; - prop_object_t obj = NULL; - const char *pkgver, *dpkgn; - - assert(array != NULL); - assert(str != NULL); - - iter = prop_array_iterator(array); - if (iter == NULL) - return NULL; - - while ((obj = prop_object_iterator_next(iter))) { - if (bypattern) { - /* - * Check if package pattern matches the - * pkgver string object in dictionary. - */ - if (!prop_dictionary_get_cstring_nocopy(obj, - "pkgver", &pkgver)) - continue; - if (xbps_pkgpattern_match(pkgver, __UNCONST(str))) - break; - /* - * Finally check if package pattern matches - * any virtual package version in dictionary. - */ - if (xbps_find_virtual_pkg_in_dict(obj, str, true)) - break; - } else { - if (!prop_dictionary_get_cstring_nocopy(obj, - "pkgname", &dpkgn)) - continue; - if (strcmp(dpkgn, str) == 0) - break; - if (xbps_find_virtual_pkg_in_dict(obj, str, false)) - break; - } - } - prop_object_iterator_release(iter); - if (obj == NULL) { - errno = ENOENT; - return NULL; - } - return obj; -} - -prop_dictionary_t -xbps_find_pkg_in_array_by_name(prop_array_t array, const char *name) -{ - return find_pkg_in_array(array, name, false); -} - -prop_dictionary_t -xbps_find_pkg_in_array_by_pattern(prop_array_t array, const char *pattern) -{ - return find_pkg_in_array(array, pattern, true); -} - -static const char * -find_virtualpkg_user_in_regpkgdb(const char *virtualpkg, bool bypattern) -{ - prop_array_t virtual; - prop_dictionary_t d; - prop_object_iterator_t iter; - prop_object_t obj; - const char *pkg = NULL; - bool found = false; - - if ((d = xbps_regpkgdb_dictionary_get()) == NULL) - return NULL; - - if ((iter = xbps_get_array_iter_from_dict(d, "properties")) == NULL) { - xbps_regpkgdb_dictionary_release(); - return NULL; - } - while ((obj = prop_object_iterator_next(iter)) != NULL) { - virtual = prop_dictionary_get(obj, "provides"); - if (virtual == NULL) - continue; - if (bypattern) - found = xbps_find_pkgpattern_in_array(virtual, virtualpkg); - else - found = xbps_find_pkgname_in_array(virtual, virtualpkg); - - if (!found) - continue; - if (bypattern) - prop_dictionary_get_cstring_nocopy(obj, - "pkgpattern", &pkg); - else - prop_dictionary_get_cstring_nocopy(obj, - "pkgname", &pkg); - - break; - } - prop_object_iterator_release(iter); - xbps_regpkgdb_dictionary_release(); - - return pkg; -} - -static prop_dictionary_t -find_virtualpkg_user_in_array(prop_array_t array, - const char *str, - bool bypattern) -{ - prop_object_t obj = NULL; - prop_object_iterator_t iter; - const char *pkgver, *dpkgn, *virtualpkg; - - assert(array != NULL); - assert(str != NULL); - - virtualpkg = find_virtualpkg_user_in_regpkgdb(str, bypattern); - if (virtualpkg == NULL) - return NULL; - - iter = prop_array_iterator(array); - if (iter == NULL) - return NULL; - - while ((obj = prop_object_iterator_next(iter))) { - if (bypattern) { - prop_dictionary_get_cstring_nocopy(obj, - "pkgver", &pkgver); - if (xbps_pkgpattern_match(pkgver, - __UNCONST(virtualpkg))) - break; - } else { - prop_dictionary_get_cstring_nocopy(obj, - "pkgname", &dpkgn); - if (strcmp(dpkgn, virtualpkg) == 0) - break; - } - } - prop_object_iterator_release(iter); - return obj; -} - -static prop_dictionary_t -find_pkg_in_dict(prop_dictionary_t d, - const char *key, - const char *str, - bool bypattern, - bool virtual) -{ - prop_array_t array; - - assert(d != NULL); - assert(str != NULL); - assert(key != NULL); - - array = prop_dictionary_get(d, key); - if (prop_object_type(array) != PROP_TYPE_ARRAY) - return NULL; - - if (virtual) - return find_virtualpkg_user_in_array(array, str, bypattern); - - return find_pkg_in_array(array, str, bypattern); -} - -prop_dictionary_t -xbps_find_pkg_in_dict_by_name(prop_dictionary_t d, - const char *key, - const char *pkgname) -{ - return find_pkg_in_dict(d, key, pkgname, false, false); -} - -prop_dictionary_t -xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t d, - const char *key, - const char *pattern) -{ - return find_pkg_in_dict(d, key, pattern, true, false); -} - -prop_dictionary_t HIDDEN -xbps_find_virtualpkg_user_in_dict_by_name(prop_dictionary_t d, - const char *key, - const char *name) -{ - return find_pkg_in_dict(d, key, name, false, true); -} - -prop_dictionary_t HIDDEN -xbps_find_virtualpkg_user_in_dict_by_pattern(prop_dictionary_t d, - const char *key, - const char *pattern) -{ - return find_pkg_in_dict(d, key, pattern, true, true); -} - -prop_dictionary_t -xbps_find_pkg_dict_installed(const char *str, bool bypattern) -{ - prop_dictionary_t d, pkgd, rpkgd = NULL; - pkg_state_t state = 0; - - assert(str != NULL); - - if ((d = xbps_regpkgdb_dictionary_get()) == NULL) - return NULL; - - pkgd = find_pkg_in_dict(d, "packages", str, bypattern, false); - if (pkgd == NULL) - goto out; - - if (xbps_get_pkg_state_dictionary(pkgd, &state) != 0) - goto out; - - switch (state) { - case XBPS_PKG_STATE_INSTALLED: - case XBPS_PKG_STATE_UNPACKED: - rpkgd = prop_dictionary_copy(pkgd); - break; - case XBPS_PKG_STATE_CONFIG_FILES: - errno = ENOENT; - xbps_dbg_printf("'%s' installed but its state is " - "config-files\n",str); - break; - default: - break; - } -out: - xbps_regpkgdb_dictionary_release(); - return rpkgd; -} - -static bool -find_string_in_array(prop_array_t array, const char *str, int mode) -{ - prop_object_iterator_t iter; - prop_object_t obj; - const char *pkgdep; - char *curpkgname; - bool found = false; - - assert(array != NULL); - assert(str != NULL); - - iter = prop_array_iterator(array); - if (iter == NULL) - return false; - - while ((obj = prop_object_iterator_next(iter))) { - assert(prop_object_type(obj) == PROP_TYPE_STRING); - if (mode == 0) { - /* match by string */ - if (prop_string_equals_cstring(obj, str)) { - found = true; - break; - } - } else if (mode == 1) { - /* match by pkgname */ - pkgdep = prop_string_cstring_nocopy(obj); - curpkgname = xbps_get_pkg_name(pkgdep); - if (curpkgname == NULL) - break; - if (strcmp(curpkgname, str) == 0) { - free(curpkgname); - found = true; - break; - } - free(curpkgname); - } else if (mode == 2) { - /* match by pkgpattern */ - pkgdep = prop_string_cstring_nocopy(obj); - if (xbps_pkgpattern_match(pkgdep, __UNCONST(str))) { - found = true; - break; - } - } - } - prop_object_iterator_release(iter); - - return found; -} - -bool -xbps_find_string_in_array(prop_array_t array, const char *str) -{ - return find_string_in_array(array, str, 0); -} - -bool -xbps_find_pkgname_in_array(prop_array_t array, const char *pkgname) -{ - return find_string_in_array(array, pkgname, 1); -} - -bool -xbps_find_pkgpattern_in_array(prop_array_t array, const char *pattern) -{ - return find_string_in_array(array, pattern, 2); -} - prop_object_iterator_t xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key) { @@ -573,118 +207,3 @@ xbps_get_pkg_dict_from_metadata_plist(const char *pkgn, const char *plist) return plistd; } - -static bool -remove_string_from_array(prop_array_t array, const char *str, int mode) -{ - prop_object_t obj; - const char *curname, *pkgdep; - char *curpkgname; - size_t i, idx = 0; - bool found = false; - - for (i = 0; i < prop_array_count(array); i++) { - obj = prop_array_get(array, i); - if (mode == 0) { - /* exact match, obj is a string */ - if (prop_string_equals_cstring(obj, str)) { - found = true; - break; - } - } else if (mode == 1) { - /* match by pkgname, obj is a string */ - pkgdep = prop_string_cstring_nocopy(obj); - curpkgname = xbps_get_pkg_name(pkgdep); - if (curpkgname == NULL) - break; - if (strcmp(curpkgname, str) == 0) { - free(curpkgname); - found = true; - break; - } - free(curpkgname); - } else if (mode == 2) { - /* match by pkgname, obj is a dictionary */ - prop_dictionary_get_cstring_nocopy(obj, - "pkgname", &curname); - if (strcmp(curname, str) == 0) { - found = true; - break; - } - } - idx++; - } - if (!found) - return false; - - prop_array_remove(array, idx); - return true; -} - -bool -xbps_remove_string_from_array(prop_array_t array, const char *str) -{ - return remove_string_from_array(array, str, 0); -} - -bool -xbps_remove_pkgname_from_array(prop_array_t array, const char *name) -{ - return remove_string_from_array(array, name, 1); -} - -bool -xbps_remove_pkg_from_array_by_name(prop_array_t array, const char *name) -{ - return remove_string_from_array(array, name, 2); -} - -bool -xbps_remove_pkg_from_dict_by_name(prop_dictionary_t dict, - const char *key, - const char *pkgname) -{ - prop_array_t array; - - assert(dict != NULL); - assert(key != NULL); - assert(pkgname != NULL); - - array = prop_dictionary_get(dict, key); - if (array == NULL) - return false; - - return xbps_remove_pkg_from_array_by_name(array, pkgname); -} - -bool -xbps_remove_pkg_dict_from_plist_by_name(const char *pkg, const char *plist) -{ - prop_dictionary_t pdict; - - assert(pkg != NULL); - assert(plist != NULL); - - pdict = prop_dictionary_internalize_from_zfile(plist); - if (pdict == NULL) { - xbps_dbg_printf("'%s' cannot read from file %s: %s\n", - pkg, plist, strerror(errno)); - return false; - } - - if (!xbps_remove_pkg_from_dict_by_name(pdict, "packages", pkg)) { - prop_object_release(pdict); - return false; - } - - if (!prop_dictionary_externalize_to_zfile(pdict, plist)) { - xbps_dbg_printf("'%s' cannot write plist file %s: %s\n", - pkg, plist, strerror(errno)); - prop_object_release(pdict); - return false; - } - - prop_object_release(pdict); - - return true; -} diff --git a/lib/plist_find.c b/lib/plist_find.c new file mode 100644 index 00000000..745621ce --- /dev/null +++ b/lib/plist_find.c @@ -0,0 +1,407 @@ +/*- + * Copyright (c) 2008-2011 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 "xbps_api_impl.h" + +/** + * @file lib/plist_find.c + * @brief PropertyList generic routines + * @defgroup plist PropertyList generic functions + * + * These functions manipulate plist files and objects shared by almost + * all library functions. + */ +static prop_dictionary_t +find_pkg_dict_from_plist(const char *plist, + const char *key, + const char *str, + bool bypattern) +{ + prop_dictionary_t dict, obj, res; + + assert(plist != NULL); + assert(str != NULL); + + dict = prop_dictionary_internalize_from_zfile(plist); + if (dict == NULL) { + xbps_dbg_printf("cannot internalize %s for pkg %s: %s", + plist, str, strerror(errno)); + return NULL; + } + if (bypattern) + obj = xbps_find_pkg_in_dict_by_pattern(dict, key, str); + else + obj = xbps_find_pkg_in_dict_by_name(dict, key, str); + + if (obj == NULL) { + prop_object_release(dict); + return NULL; + } + res = prop_dictionary_copy(obj); + prop_object_release(dict); + + return res; +} + +prop_dictionary_t +xbps_find_pkg_dict_from_plist_by_name(const char *plist, + const char *key, + const char *pkgname) +{ + return find_pkg_dict_from_plist(plist, key, pkgname, false); +} + +prop_dictionary_t +xbps_find_pkg_dict_from_plist_by_pattern(const char *plist, + const char *key, + const char *pattern) +{ + return find_pkg_dict_from_plist(plist, key, pattern, true); +} + +bool +xbps_find_virtual_pkg_in_dict(prop_dictionary_t d, + const char *str, + bool bypattern) +{ + prop_array_t provides; + bool found = false; + + if ((provides = prop_dictionary_get(d, "provides"))) { + if (bypattern) + found = xbps_find_pkgpattern_in_array(provides, str); + else + found = xbps_find_pkgname_in_array(provides, str); + } + return found; +} + +static prop_dictionary_t +find_pkg_in_array(prop_array_t array, const char *str, bool bypattern) +{ + prop_object_iterator_t iter; + prop_object_t obj = NULL; + const char *pkgver, *dpkgn; + + assert(array != NULL); + assert(str != NULL); + + iter = prop_array_iterator(array); + if (iter == NULL) + return NULL; + + while ((obj = prop_object_iterator_next(iter))) { + if (bypattern) { + /* + * Check if package pattern matches the + * pkgver string object in dictionary. + */ + if (!prop_dictionary_get_cstring_nocopy(obj, + "pkgver", &pkgver)) + continue; + if (xbps_pkgpattern_match(pkgver, __UNCONST(str))) + break; + /* + * Finally check if package pattern matches + * any virtual package version in dictionary. + */ + if (xbps_find_virtual_pkg_in_dict(obj, str, true)) + break; + } else { + if (!prop_dictionary_get_cstring_nocopy(obj, + "pkgname", &dpkgn)) + continue; + if (strcmp(dpkgn, str) == 0) + break; + if (xbps_find_virtual_pkg_in_dict(obj, str, false)) + break; + } + } + prop_object_iterator_release(iter); + if (obj == NULL) { + errno = ENOENT; + return NULL; + } + return obj; +} + +prop_dictionary_t +xbps_find_pkg_in_array_by_name(prop_array_t array, const char *name) +{ + return find_pkg_in_array(array, name, false); +} + +prop_dictionary_t +xbps_find_pkg_in_array_by_pattern(prop_array_t array, const char *pattern) +{ + return find_pkg_in_array(array, pattern, true); +} + +static const char * +find_virtualpkg_user_in_regpkgdb(const char *virtualpkg, bool bypattern) +{ + prop_array_t virtual; + prop_dictionary_t d; + prop_object_iterator_t iter; + prop_object_t obj; + const char *pkg = NULL; + bool found = false; + + if ((d = xbps_regpkgdb_dictionary_get()) == NULL) + return NULL; + + if ((iter = xbps_get_array_iter_from_dict(d, "properties")) == NULL) { + xbps_regpkgdb_dictionary_release(); + return NULL; + } + while ((obj = prop_object_iterator_next(iter)) != NULL) { + virtual = prop_dictionary_get(obj, "provides"); + if (virtual == NULL) + continue; + if (bypattern) + found = xbps_find_pkgpattern_in_array(virtual, virtualpkg); + else + found = xbps_find_pkgname_in_array(virtual, virtualpkg); + + if (!found) + continue; + if (bypattern) + prop_dictionary_get_cstring_nocopy(obj, + "pkgpattern", &pkg); + else + prop_dictionary_get_cstring_nocopy(obj, + "pkgname", &pkg); + + break; + } + prop_object_iterator_release(iter); + xbps_regpkgdb_dictionary_release(); + + return pkg; +} + +static prop_dictionary_t +find_virtualpkg_user_in_array(prop_array_t array, + const char *str, + bool bypattern) +{ + prop_object_t obj = NULL; + prop_object_iterator_t iter; + const char *pkgver, *dpkgn, *virtualpkg; + + assert(array != NULL); + assert(str != NULL); + + virtualpkg = find_virtualpkg_user_in_regpkgdb(str, bypattern); + if (virtualpkg == NULL) + return NULL; + + iter = prop_array_iterator(array); + if (iter == NULL) + return NULL; + + while ((obj = prop_object_iterator_next(iter))) { + if (bypattern) { + prop_dictionary_get_cstring_nocopy(obj, + "pkgver", &pkgver); + if (xbps_pkgpattern_match(pkgver, + __UNCONST(virtualpkg))) + break; + } else { + prop_dictionary_get_cstring_nocopy(obj, + "pkgname", &dpkgn); + if (strcmp(dpkgn, virtualpkg) == 0) + break; + } + } + prop_object_iterator_release(iter); + return obj; +} + +static prop_dictionary_t +find_pkg_in_dict(prop_dictionary_t d, + const char *key, + const char *str, + bool bypattern, + bool virtual) +{ + prop_array_t array; + + assert(d != NULL); + assert(str != NULL); + assert(key != NULL); + + array = prop_dictionary_get(d, key); + if (prop_object_type(array) != PROP_TYPE_ARRAY) + return NULL; + + if (virtual) + return find_virtualpkg_user_in_array(array, str, bypattern); + + return find_pkg_in_array(array, str, bypattern); +} + +prop_dictionary_t +xbps_find_pkg_in_dict_by_name(prop_dictionary_t d, + const char *key, + const char *pkgname) +{ + return find_pkg_in_dict(d, key, pkgname, false, false); +} + +prop_dictionary_t +xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t d, + const char *key, + const char *pattern) +{ + return find_pkg_in_dict(d, key, pattern, true, false); +} + +prop_dictionary_t HIDDEN +xbps_find_virtualpkg_user_in_dict_by_name(prop_dictionary_t d, + const char *key, + const char *name) +{ + return find_pkg_in_dict(d, key, name, false, true); +} + +prop_dictionary_t HIDDEN +xbps_find_virtualpkg_user_in_dict_by_pattern(prop_dictionary_t d, + const char *key, + const char *pattern) +{ + return find_pkg_in_dict(d, key, pattern, true, true); +} + +prop_dictionary_t +xbps_find_pkg_dict_installed(const char *str, bool bypattern) +{ + prop_dictionary_t d, pkgd, rpkgd = NULL; + pkg_state_t state = 0; + + assert(str != NULL); + + if ((d = xbps_regpkgdb_dictionary_get()) == NULL) + return NULL; + + pkgd = find_pkg_in_dict(d, "packages", str, bypattern, false); + if (pkgd == NULL) + goto out; + + if (xbps_get_pkg_state_dictionary(pkgd, &state) != 0) + goto out; + + switch (state) { + case XBPS_PKG_STATE_INSTALLED: + case XBPS_PKG_STATE_UNPACKED: + rpkgd = prop_dictionary_copy(pkgd); + break; + case XBPS_PKG_STATE_CONFIG_FILES: + errno = ENOENT; + xbps_dbg_printf("'%s' installed but its state is " + "config-files\n",str); + break; + default: + break; + } +out: + xbps_regpkgdb_dictionary_release(); + return rpkgd; +} + +static bool +find_string_in_array(prop_array_t array, const char *str, int mode) +{ + prop_object_iterator_t iter; + prop_object_t obj; + const char *pkgdep; + char *curpkgname; + bool found = false; + + assert(array != NULL); + assert(str != NULL); + + iter = prop_array_iterator(array); + if (iter == NULL) + return false; + + while ((obj = prop_object_iterator_next(iter))) { + assert(prop_object_type(obj) == PROP_TYPE_STRING); + if (mode == 0) { + /* match by string */ + if (prop_string_equals_cstring(obj, str)) { + found = true; + break; + } + } else if (mode == 1) { + /* match by pkgname */ + pkgdep = prop_string_cstring_nocopy(obj); + curpkgname = xbps_get_pkg_name(pkgdep); + if (curpkgname == NULL) + break; + if (strcmp(curpkgname, str) == 0) { + free(curpkgname); + found = true; + break; + } + free(curpkgname); + } else if (mode == 2) { + /* match by pkgpattern */ + pkgdep = prop_string_cstring_nocopy(obj); + if (xbps_pkgpattern_match(pkgdep, __UNCONST(str))) { + found = true; + break; + } + } + } + prop_object_iterator_release(iter); + + return found; +} + +bool +xbps_find_string_in_array(prop_array_t array, const char *str) +{ + return find_string_in_array(array, str, 0); +} + +bool +xbps_find_pkgname_in_array(prop_array_t array, const char *pkgname) +{ + return find_string_in_array(array, pkgname, 1); +} + +bool +xbps_find_pkgpattern_in_array(prop_array_t array, const char *pattern) +{ + return find_string_in_array(array, pattern, 2); +} diff --git a/lib/plist_remove.c b/lib/plist_remove.c new file mode 100644 index 00000000..be510b2c --- /dev/null +++ b/lib/plist_remove.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2008-2011 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 "xbps_api_impl.h" + +/** + * @file lib/plist_remove.c + * @brief PropertyList generic routines + * @defgroup plist PropertyList generic functions + * + * These functions manipulate plist files and objects shared by almost + * all library functions. + */ +static bool +remove_string_from_array(prop_array_t array, const char *str, int mode) +{ + prop_object_t obj; + const char *curname, *pkgdep; + char *curpkgname; + size_t i, idx = 0; + bool found = false; + + for (i = 0; i < prop_array_count(array); i++) { + obj = prop_array_get(array, i); + if (mode == 0) { + /* exact match, obj is a string */ + if (prop_string_equals_cstring(obj, str)) { + found = true; + break; + } + } else if (mode == 1) { + /* match by pkgname, obj is a string */ + pkgdep = prop_string_cstring_nocopy(obj); + curpkgname = xbps_get_pkg_name(pkgdep); + if (curpkgname == NULL) + break; + if (strcmp(curpkgname, str) == 0) { + free(curpkgname); + found = true; + break; + } + free(curpkgname); + } else if (mode == 2) { + /* match by pkgname, obj is a dictionary */ + prop_dictionary_get_cstring_nocopy(obj, + "pkgname", &curname); + if (strcmp(curname, str) == 0) { + found = true; + break; + } + } + idx++; + } + if (!found) + return false; + + prop_array_remove(array, idx); + return true; +} + +bool +xbps_remove_string_from_array(prop_array_t array, const char *str) +{ + return remove_string_from_array(array, str, 0); +} + +bool +xbps_remove_pkgname_from_array(prop_array_t array, const char *name) +{ + return remove_string_from_array(array, name, 1); +} + +bool +xbps_remove_pkg_from_array_by_name(prop_array_t array, const char *name) +{ + return remove_string_from_array(array, name, 2); +} + +bool +xbps_remove_pkg_from_dict_by_name(prop_dictionary_t dict, + const char *key, + const char *pkgname) +{ + prop_array_t array; + + assert(dict != NULL); + assert(key != NULL); + assert(pkgname != NULL); + + array = prop_dictionary_get(dict, key); + if (array == NULL) + return false; + + return xbps_remove_pkg_from_array_by_name(array, pkgname); +} + +bool +xbps_remove_pkg_dict_from_plist_by_name(const char *pkg, const char *plist) +{ + prop_dictionary_t pdict; + + assert(pkg != NULL); + assert(plist != NULL); + + pdict = prop_dictionary_internalize_from_zfile(plist); + if (pdict == NULL) { + xbps_dbg_printf("'%s' cannot read from file %s: %s\n", + pkg, plist, strerror(errno)); + return false; + } + + if (!xbps_remove_pkg_from_dict_by_name(pdict, "packages", pkg)) { + prop_object_release(pdict); + return false; + } + + if (!prop_dictionary_externalize_to_zfile(pdict, plist)) { + xbps_dbg_printf("'%s' cannot write plist file %s: %s\n", + pkg, plist, strerror(errno)); + prop_object_release(pdict); + return false; + } + + prop_object_release(pdict); + + return true; +}