diff --git a/include/xbps.h.in b/include/xbps.h.in index 154d61ea..ab20f018 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -1713,6 +1713,30 @@ char *xbps_pkgpattern_name(const char *pattern); */ const char *xbps_pkg_version(const char *pkg); +/** + * Gets the pkgname/version componentn of a binary package string, + * i.e foo-2.0_1..xbps. + * + * @param[in] pkg Package string. + * + * @return A pointer to a malloc(ed) string with the pkgver component, + * NULL if it couldn't find the version component. The pointer should + * be free(3)d when it's no longer needed. + */ +char *xbps_binpkg_pkgver(const char *pkg); + +/** + * Gets the architecture component of a binary package string, + * i.e ..xbps. + * + * @param[in] pkg Package string. + * + * @return A pointer to a malloc(ed) string with the architecture component, + * NULL if it couldn't find the version component. The pointer should + * be free(3)d when it's no longer needed. + */ +char *xbps_binpkg_arch(const char *pkg); + /** * Gets the package version of a package pattern string specified by * the \a pattern argument. diff --git a/lib/util.c b/lib/util.c index a34b7069..11ea33b1 100644 --- a/lib/util.c +++ b/lib/util.c @@ -105,7 +105,98 @@ xbps_pkg_version(const char *pkg) if (!valid) return NULL; - return p + 1; /* skip first '_' */ + return p + 1; /* skip first '-' */ +} + +char * +xbps_binpkg_pkgver(const char *pkg) +{ + const char *fname; + char *p, *res; + unsigned int i, idx = 0; + bool valid = false; + + /* skip path if found, only interested in filename */ + if ((fname = strrchr(pkg, '/'))) + fname++; + else + fname = pkg; + + /* get the version component first */ + if ((p = strrchr(fname, '-')) == NULL) + return NULL; + + for (i = 0; i < strlen(p); i++) { + if (p[i] == '_') + break; + if (isdigit((unsigned char)p[i]) && strchr(p, '_')) { + valid = true; + break; + } + } + if (!valid) + return NULL; + + /* + * find the index until the architecture component: + * this assumes that revision contains 1 or 2 digits! + */ + for (i = 0; i < strlen(fname); i++) { + /* revision with 1 digit: _[digit]. */ + if (fname[i] == '_' && + isdigit((unsigned char)fname[i+1]) && + fname[i+2] == '.') { + idx = i+2; + break; + } + /* revision with 2 digits: _[digit][digit]. */ + if (fname[i] == '_' && + isdigit((unsigned char)fname[i+1]) && + isdigit((unsigned char)fname[i+2]) && + fname[i+3] == '.') { + idx = i+3; + break; + } + } + if (!idx) + return NULL; + + res = strdup(fname); + assert(res); + res[idx] = '\0'; + + return res; +} + +char * +xbps_binpkg_arch(const char *pkg) +{ + const char *p, *fname; + char *pkgver, *res; + + if ((pkgver = xbps_binpkg_pkgver(pkg)) == NULL) + return NULL; + + /* skip path if found, only interested in filename */ + if ((fname = strrchr(pkg, '/'))) + fname++; + else + fname = pkg; + + p = fname + strlen(pkgver); + if (!p || p == '\0') { + free(pkgver); + return NULL; + } + if (*p == '.') + p++; + + res = strdup(p); + assert(res); + free(pkgver); + res[strlen(res)-5] = '\0'; + + return res; } const char *