/* pkg_vec.c - the opkg package management system Steven M. Ayer Copyright (C) 2002 Compaq Computer Corporation 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 the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "pkg.h" #include "opkg_message.h" #include "libbb/libbb.h" pkg_vec_t *pkg_vec_alloc(void) { pkg_vec_t *vec = xcalloc(1, sizeof(pkg_vec_t)); vec->pkgs = NULL; vec->len = 0; return vec; } void pkg_vec_free(pkg_vec_t * vec) { if (!vec) return; if (vec->pkgs) free(vec->pkgs); free(vec); } /* * assumption: all names in a vector are identical * assumption: all version strings are trimmed, * so identical versions have identical version strings, * implying identical packages; let's marry these */ void pkg_vec_insert_merge(pkg_vec_t * vec, pkg_t * pkg, int set_status) { int i; int found = 0; char *pkg_version = pkg_get_string(pkg, PKG_VERSION); char *pkg_architecture = pkg_get_architecture(pkg); char *vec_architecture; /* look for a duplicate pkg by name, version, and architecture */ for (i = 0; i < vec->len; i++) { vec_architecture = pkg_get_architecture(vec->pkgs[i]); opkg_msg(DEBUG2, "%s %s arch=%s vs. %s %s arch=%s.\n", pkg->name, pkg_version, pkg_architecture, vec->pkgs[i]->name, pkg_get_string(vec->pkgs[i], PKG_VERSION), vec_architecture); /* if the name,ver,arch matches, or the name matches and the * package is marked deinstall/hold */ if ((!strcmp(pkg->name, vec->pkgs[i]->name)) && ((pkg->state_want == SW_DEINSTALL && (pkg->state_flag & SF_HOLD)) || ((pkg_compare_versions(pkg, vec->pkgs[i]) == 0) && (!strcmp(pkg_architecture, vec_architecture))))) { found = 1; opkg_msg(DEBUG2, "Duplicate for pkg=%s version=%s arch=%s.\n", pkg->name, pkg_version, pkg_architecture); break; } } /* we didn't find one, add it */ if (!found) { opkg_msg(DEBUG2, "Adding new pkg=%s version=%s arch=%s.\n", pkg->name, pkg_version, pkg_architecture); pkg_vec_insert(vec, pkg); return; } /* update the one that we have */ opkg_msg(DEBUG2, "Merging %s %s arch=%s, set_status=%d.\n", pkg->name, pkg_version, pkg_architecture, set_status); if (set_status) { /* This is from the status file, * so need to merge with existing database */ pkg_merge(pkg, vec->pkgs[i]); } /* overwrite the old one */ pkg_deinit(vec->pkgs[i]); free(vec->pkgs[i]); vec->pkgs[i] = pkg; } void pkg_vec_insert(pkg_vec_t * vec, const pkg_t * pkg) { vec->pkgs = xrealloc(vec->pkgs, (vec->len + 1) * sizeof(pkg_t *)); vec->pkgs[vec->len] = (pkg_t *) pkg; vec->len++; } int pkg_vec_contains(pkg_vec_t * vec, pkg_t * apkg) { int i; for (i = 0; i < vec->len; i++) if (vec->pkgs[i] == apkg) return 1; return 0; } void pkg_vec_sort(pkg_vec_t * vec, compare_fcn_t compar) { qsort(vec->pkgs, vec->len, sizeof(pkg_t *), compar); } int pkg_vec_clear_marks(pkg_vec_t * vec) { int npkgs = vec->len; int i; for (i = 0; i < npkgs; i++) { pkg_t *pkg = vec->pkgs[i]; pkg->state_flag &= ~SF_MARKED; } return 0; } int pkg_vec_mark_if_matches(pkg_vec_t * vec, const char *pattern) { int matching_count = 0; pkg_t **pkgs = vec->pkgs; int npkgs = vec->len; int i; abstract_pkg_t **providers, *provider; for (i = 0; i < npkgs; i++) { pkg_t *pkg = pkgs[i]; if (fnmatch(pattern, pkg->name, 0) == 0) { pkg->state_flag |= SF_MARKED; matching_count++; } else { providers = pkg_get_ptr(pkg, PKG_PROVIDES); while (providers && *providers) { provider = *providers++; if (fnmatch(pattern, provider->name, 0) == 0) { pkg->state_flag |= SF_MARKED; matching_count++; } } } } return matching_count; } abstract_pkg_vec_t *abstract_pkg_vec_alloc(void) { abstract_pkg_vec_t *vec; vec = xcalloc(1, sizeof(abstract_pkg_vec_t)); vec->pkgs = NULL; vec->len = 0; return vec; } void abstract_pkg_vec_free(abstract_pkg_vec_t * vec) { if (!vec) return; free(vec->pkgs); free(vec); } /* * assumption: all names in a vector are unique */ void abstract_pkg_vec_insert(abstract_pkg_vec_t * vec, abstract_pkg_t * pkg) { vec->pkgs = xrealloc(vec->pkgs, (vec->len + 1) * sizeof(abstract_pkg_t *)); vec->pkgs[vec->len] = pkg; vec->len++; } abstract_pkg_t *abstract_pkg_vec_get(abstract_pkg_vec_t * vec, int i) { if (vec->len > i) return vec->pkgs[i]; else return NULL; } int abstract_pkg_vec_contains(abstract_pkg_vec_t * vec, abstract_pkg_t * apkg) { int i; for (i = 0; i < vec->len; i++) if (vec->pkgs[i] == apkg) return 1; return 0; } void abstract_pkg_vec_sort(abstract_pkg_vec_t * vec, compare_fcn_t compar) { qsort(vec->pkgs, vec->len, sizeof(pkg_t *), compar); } int pkg_compare_names(const void *p1, const void *p2) { const pkg_t *pkg1 = *(const pkg_t **)p1; const pkg_t *pkg2 = *(const pkg_t **)p2; if (pkg1->name == NULL) return 1; if (pkg2->name == NULL) return -1; return (strcmp(pkg1->name, pkg2->name)); }