diff --git a/bin/xbps-bin/check.c b/bin/xbps-bin/check.c index ff7812cc..f63d457a 100644 --- a/bin/xbps-bin/check.c +++ b/bin/xbps-bin/check.c @@ -264,7 +264,7 @@ xbps_check_pkg_integrity(const char *pkgname) } while ((obj = prop_object_iterator_next(iter))) { reqpkg = prop_string_cstring_nocopy(obj); - if (xbps_check_is_installed_pkg(reqpkg) < 0) { + if (xbps_check_is_installed_pkg(reqpkg) <= 0) { rv = ENOENT; printf("%s: dependency not satisfied: %s\n", pkgname, reqpkg); diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index 62a47179..f7f53158 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -64,7 +64,7 @@ show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "version", &version); if (pkgname && version) { - printf(" * Missing binary package for: %s >= %s\n", + printf(" * Missing binary package for: %s%s\n", pkgname, version); return 0; } diff --git a/bin/xbps-bin/show-deps.c b/bin/xbps-bin/show-deps.c index 427b2651..0cbe7199 100644 --- a/bin/xbps-bin/show-deps.c +++ b/bin/xbps-bin/show-deps.c @@ -44,12 +44,12 @@ list_deps(prop_object_t obj, void *arg, bool *loop_done) assert(prop_object_type(obj) == PROP_TYPE_STRING); - pkgname = xbps_get_pkg_name(prop_string_cstring_nocopy(obj)); - version = xbps_get_pkg_version(prop_string_cstring_nocopy(obj)); - if (strcmp(version, "0") == 0) + pkgname = xbps_get_pkgdep_name(prop_string_cstring_nocopy(obj)); + version = xbps_get_pkgdep_version(prop_string_cstring_nocopy(obj)); + if (strcmp(version, ">=0") == 0) printf("%s\n", pkgname); else - printf("%s >= %s\n", pkgname, version); + printf("%s%s\n", pkgname, version); free(pkgname); diff --git a/bin/xbps-pkgdb/main.c b/bin/xbps-pkgdb/main.c index 0d41005d..7027dbe6 100644 --- a/bin/xbps-pkgdb/main.c +++ b/bin/xbps-pkgdb/main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -58,13 +59,15 @@ usage(void) printf("usage: xbps-pkgdb [options] [action] [args]\n" "\n" " Available actions:\n" - " getpkgname, getpkgrevision, getpkgversion, register\n" - " sanitize-plist, unregister, version\n" + " getpkgdepname, getpkgname, getpkgrevision, getpkgversion,\n" + " pkgmatch, register, sanitize-plist, unregister, version\n" "\n" " Action arguments:\n" + " getpkgdepname\t\n" " getpkgname\t\t\n" " getpkgrevision\t\n" " getpkgversion\t\n" + " pkgmatch\t\t \n" " register\t\t \n" " sanitize-plist\t\n" " unregister\t\t \n" @@ -248,6 +251,26 @@ main(int argc, char **argv) printf("%s\n", version); + } else if (strcasecmp(argv[0], "getpkgdepname") == 0) { + /* Returns the pkgname of a dependency */ + if (argc != 2) + usage(); + + pkgname = xbps_get_pkgdep_name(argv[1]); + if (pkgname == NULL) + exit(EXIT_FAILURE); + + printf("%s\n", pkgname); + free(pkgname); + + } else if (strcasecmp(argv[0], "pkgmatch") == 0) { + /* Matches a pkg with a pattern */ + if (argc != 3) + usage(); + + rv = xbps_pkgdep_match(argv[1], argv[2]); + exit(rv); + } else { usage(); } diff --git a/include/xbps_api.h b/include/xbps_api.h index 68db3d31..5ea11fdd 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -37,7 +37,7 @@ #include /* Current release version */ -#define XBPS_RELVER "0.2.99.1" +#define XBPS_RELVER "20091107" /* Default root PATH for xbps to store metadata info. */ #define XBPS_META_PATH "/var/db/xbps" @@ -125,6 +125,9 @@ int SYMEXPORT xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t); /* From lib/orphans.c */ prop_array_t SYMEXPORT xbps_find_orphan_packages(void); +/* From lib/pkgmatch.c */ +int SYMEXPORT xbps_pkgdep_match(const char *, char *); + /* From lib/plist.c */ bool SYMEXPORT xbps_add_obj_to_dict(prop_dictionary_t, prop_object_t, const char *); @@ -145,7 +148,8 @@ prop_dictionary_t SYMEXPORT xbps_find_pkg_in_dict(prop_dictionary_t, const char *, const char *); prop_dictionary_t SYMEXPORT xbps_find_pkg_from_plist(const char *, const char *); -prop_dictionary_t SYMEXPORT xbps_find_pkg_installed_from_plist(const char *); +prop_dictionary_t SYMEXPORT + xbps_find_pkg_installed_from_plist(const char *); bool SYMEXPORT xbps_find_string_in_array(prop_array_t, const char *); prop_dictionary_t SYMEXPORT xbps_prepare_regpkgdb_dict(void); @@ -207,12 +211,15 @@ int SYMEXPORT xbps_unpack_binary_pkg(prop_dictionary_t, bool); char SYMEXPORT *xbps_xasprintf(const char *, ...); char SYMEXPORT *xbps_get_file_hash(const char *); int SYMEXPORT xbps_check_file_hash(const char *, const char *); -int SYMEXPORT xbps_check_pkg_file_hash(prop_dictionary_t, const char *); +int SYMEXPORT xbps_check_pkg_file_hash(prop_dictionary_t, + const char *); int SYMEXPORT xbps_check_is_installed_pkg(const char *); bool SYMEXPORT xbps_check_is_installed_pkgname(const char *); char SYMEXPORT *xbps_get_pkg_index_plist(const char *); char SYMEXPORT *xbps_get_pkg_name(const char *); +char SYMEXPORT *xbps_get_pkgdep_name(const char *); const char SYMEXPORT *xbps_get_pkg_version(const char *); +const char SYMEXPORT *xbps_get_pkgdep_version(const char *); const char SYMEXPORT *xbps_get_pkg_revision(const char *); bool SYMEXPORT xbps_pkg_has_rundeps(prop_dictionary_t); void SYMEXPORT xbps_set_rootdir(const char *); diff --git a/lib/Makefile b/lib/Makefile index ff44993d..93c41973 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -13,7 +13,7 @@ OBJS = fetch/common.o fetch/fetch.o fetch/file.o fetch/ftp.o fetch/http.o OBJS += configure.o cmpver.o depends.o download.o fexec.o findpkg.o 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 +OBJS += sync_remote_pkgidx.o unpack.o util.o pkgmatch.o ifdef STATIC all: libfetch libxbps.a diff --git a/lib/depends.c b/lib/depends.c index ee7dcd4e..967f53e0 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -279,11 +279,15 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, /* * Check if required dep is satisfied and installed. */ - if (xbps_check_is_installed_pkg(reqpkg) >= 0) + if (xbps_check_is_installed_pkg(reqpkg)) continue; - pkgname = xbps_get_pkg_name(reqpkg); - reqvers = xbps_get_pkg_version(reqpkg); + pkgname = xbps_get_pkgdep_name(reqpkg); + reqvers = xbps_get_pkgdep_version(reqpkg); + if (pkgname == NULL || reqvers == NULL) { + rv = EINVAL; + break; + } /* * Check if package is already added in the * array of unsorted deps. diff --git a/lib/pkgmatch.c b/lib/pkgmatch.c new file mode 100644 index 00000000..81b83a80 --- /dev/null +++ b/lib/pkgmatch.c @@ -0,0 +1,170 @@ +/* + * FreeBSD install - a package for the installation and maintenance + * of non-core utilities. + * + * 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. + * + * Maxim Sobolev + * 31 July 2001 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static int +csh_match(const char *pattern, const char *string, int flags) +{ + const char *nextchoice = pattern, *current = NULL; + int ret = FNM_NOMATCH, prefixlen = -1, curlen = 0, level = 0; + + do { + const char *pos = nextchoice; + const char *postfix = NULL; + bool quoted = false; + + nextchoice = NULL; + do { + const char *eb; + if (!*pos) { + postfix = pos; + } else if (quoted) { + quoted = false; + } else { + switch (*pos) { + case '{': + ++level; + if (level == 1) { + current = pos + 1; + prefixlen = pos - pattern; + } + break; + case ',': + if (level == 1 && !nextchoice) { + nextchoice = pos + 1; + curlen = pos - current; + } + break; + case '}': + if (level == 1) { + postfix = pos + 1; + if (!nextchoice) + curlen = pos - current; + } + level--; + break; + case '[': + eb = pos+1; + if (*eb == '!' || *eb == '^') + eb++; + if (*eb == ']') + eb++; + while (*eb && *eb != ']') + eb++; + if (*eb) + pos = eb; + break; + case '\\': + quoted = true; + break; + default: + ; + } + } + pos++; + } while (!postfix); + + if (current) { + char buf[FILENAME_MAX]; + snprintf(buf, sizeof(buf), "%.*s%.*s%s", prefixlen, + pattern, curlen, current, postfix); + ret = csh_match(buf, string, flags); + if (ret) { + current = nextchoice; + level = 1; + } else + current = NULL; + } else + ret = fnmatch(pattern, string, flags); + } while (current); + + return ret; +} + +int SYMEXPORT +xbps_pkgdep_match(const char *instpkg, char *pattern) +{ + const char *fname = instpkg; + char basefname[PATH_MAX], condchar = '\0', *condition; + int rv = 0; + + condition = strpbrk(pattern, "><="); + if (condition) { + const char *ch; + if (condition > pattern && condition[-1] == '!') + condition--; + condchar = *condition; + *condition = '\0'; + ch = strrchr(fname, '-'); + if (ch && ch - fname < PATH_MAX) { + strncpy(basefname, fname, ch - fname); + fname = basefname; + } + } + + rv = (csh_match(pattern, fname, 0) == 0) ? 1 : 0; + + while (condition) { + *condition = condchar; + if (rv == 1) { + char *nextcondition; + int match = 0; + if (*++condition == '=') { + match = 2; + condition++; + } + switch (condchar) { + case '<': + match |= 1; + break; + case '>': + match |= 4; + break; + case '=': + match |= 2; + break; + case '!': + match = 5; + break; + } + nextcondition = strpbrk(condition, "<>=!"); + if (nextcondition) { + condchar = *nextcondition; + *nextcondition = '\0'; + } + if ((match & + (1 << (xbps_cmpver(instpkg, condition) + 1))) == 0) + rv = 0; + condition = nextcondition; + } else { + break; + } + } + + return rv; +} diff --git a/lib/requiredby.c b/lib/requiredby.c index 43d51012..cca552f8 100644 --- a/lib/requiredby.c +++ b/lib/requiredby.c @@ -153,7 +153,7 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) prop_array_t rdeps; prop_object_t obj, obj2; prop_object_iterator_t iter, iter2; - const char *reqname, *pkgname, *version; + const char *reqname, *pkgname, *version, *str; char *rdepname, *fpkgn; int rv = 0; @@ -176,7 +176,8 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) } while ((obj = prop_object_iterator_next(iter)) != NULL) { - rdepname = xbps_get_pkg_name(prop_string_cstring_nocopy(obj)); + str = prop_string_cstring_nocopy(obj); + rdepname = xbps_get_pkgdep_name(str); iter2 = prop_array_iterator(regar); if (iter2 == NULL) { free(rdepname); diff --git a/lib/sortdeps.c b/lib/sortdeps.c index 098391fb..15457473 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -62,7 +62,7 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps) prop_object_iterator_t iter, iter2; struct sorted_dependency *sdep; size_t ndeps = 0, rundepscnt = 0, cnt = 0; - const char *pkgname; + const char *pkgname, *str; char *curpkgnamedep; int rv = 0; @@ -125,8 +125,8 @@ again: * were already added in the sorted list. */ while ((obj2 = prop_object_iterator_next(iter2)) != NULL) { - curpkgnamedep = - xbps_get_pkg_name(prop_string_cstring_nocopy(obj2)); + str = prop_string_cstring_nocopy(obj2); + curpkgnamedep = xbps_get_pkgdep_name(str); /* * If dependency is already installed or queued, * pass to the next one. diff --git a/lib/util.c b/lib/util.c index 5f8ed3fa..a6c90eae 100644 --- a/lib/util.c +++ b/lib/util.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include "sha256.h" @@ -113,20 +115,21 @@ int SYMEXPORT xbps_check_is_installed_pkg(const char *pkg) { prop_dictionary_t dict; - const char *reqver, *instver; - char *pkgname; + const char *instver; + char *pkgname, *instpkg; int rv = 0; pkg_state_t state = 0; assert(pkg != NULL); - pkgname = xbps_get_pkg_name(pkg); - reqver = xbps_get_pkg_version(pkg); + pkgname = xbps_get_pkgdep_name(pkg); + if (pkgname == NULL) + return -1; dict = xbps_find_pkg_installed_from_plist(pkgname); if (dict == NULL) { free(pkgname); - return -1; /* not installed */ + return 0; /* not installed */ } /* @@ -142,15 +145,19 @@ xbps_check_is_installed_pkg(const char *pkg) if (state != XBPS_PKG_STATE_INSTALLED) { prop_object_release(dict); - return -1; + return 0; } /* Get version from installed package */ prop_dictionary_get_cstring_nocopy(dict, "version", &instver); - - /* Compare installed and required version. */ - rv = xbps_cmpver(instver, reqver); - + instpkg = xbps_xasprintf("%s-%s", pkgname, instver); + if (instpkg == NULL) { + prop_object_release(dict); + return -1; + } + /* Check if installed pkg is matched against pkgdep pattern */ + rv = xbps_pkgdep_match(instpkg, __UNCONST(pkg)); + free(instpkg); prop_object_release(dict); return rv; @@ -219,12 +226,49 @@ xbps_get_pkg_name(const char *pkg) len = strlen(pkg) - strlen(tmp) + 1; pkgname = malloc(len); - memcpy(pkgname, pkg, len - 1); + strncpy(pkgname, pkg, len); pkgname[len - 1] = '\0'; return pkgname; } +char SYMEXPORT * +xbps_get_pkgdep_name(const char *pkg) +{ + char *res, *pkgname; + size_t len; + + assert(pkg != NULL); + + res = strpbrk(pkg, "><="); + if (res == NULL) + return NULL; + + len = strlen(pkg) - strlen(res) + 1; + pkgname = malloc(len); + if (pkgname == NULL) + return NULL; + + strncpy(pkgname, pkg, len); + pkgname[len - 1] = '\0'; + + return pkgname; +} + +const char SYMEXPORT * +xbps_get_pkgdep_version(const char *pkg) +{ + char *res; + + assert(pkg != NULL); + + res = strpbrk(pkg, "><="); + if (res == NULL) + return NULL; + + return res; +} + static char * get_pkg_index_remote_plist(const char *uri, const char *machine) {