From 26c054d7738bf6134e1e0dab4242b8387fa40cfb Mon Sep 17 00:00:00 2001 From: Juan RP Date: Tue, 23 Dec 2008 12:28:21 +0100 Subject: [PATCH] Checkpoint for installation of binary packages. --HG-- extra : convert_revision : 0bc55ebae04b2e1e5ab20feca786b649fc2e0335 --- bin/Makefile | 4 +- bin/xbps-bin.c | 87 +++++++++++---------- bin/xbps-cmpver.c | 69 ++--------------- bin/xbps-pkgdb.c | 19 ++--- bin/xbps-src.sh | 5 +- include/plist.h | 25 ++++-- include/xbps_api.h | 21 +++-- lib/Makefile | 6 +- lib/cmpver.c | 66 ++++++++++++++++ lib/depends.c | 189 +++++++++++++++++++++++++++++++++++++++++++++ lib/install.c | 131 +++++++++++++++++++++++++++++++ lib/plist.c | 73 ++++++----------- 12 files changed, 510 insertions(+), 185 deletions(-) create mode 100644 lib/cmpver.c create mode 100644 lib/depends.c create mode 100644 lib/install.c diff --git a/bin/Makefile b/bin/Makefile index 4f8877f1432..7e420de5fdb 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -1,7 +1,7 @@ include ../vars.mk EXTRA_CFLAGS = -funroll-all-loops -ftree-loop-linear -LDFLAGS += -L../lib -lxbps +LDFLAGS += -L../lib -L$(PREFIX)/lib -lxbps BINS = xbps-bin xbps-cmpver xbps-digest xbps-pkgdb @@ -12,7 +12,7 @@ xbps-bin: xbps-bin.o $(CC) $(LDFLAGS) $^ -o $@ xbps-cmpver: xbps-cmpver.o - $(CC) $^ -o $@ + $(CC) $(LDFLAGS) $^ -o $@ xbps-digest: xbps-digest.o $(CC) $(EXTRA_CFLAGS) $(LDFLAGS) $^ -o $@ diff --git a/bin/xbps-bin.c b/bin/xbps-bin.c index 94910278e12..e8054d1b12d 100644 --- a/bin/xbps-bin.c +++ b/bin/xbps-bin.c @@ -40,7 +40,7 @@ typedef struct repository_info { uint64_t total_pkgs; } repo_info_t; -static const char *sanitize_localpath(const char *); +static bool sanitize_localpath(char *, const char *); static prop_dictionary_t getrepolist_dict(void); static bool pkgindex_getinfo(prop_dictionary_t, repo_info_t *); static void usage(void); @@ -100,8 +100,12 @@ static prop_dictionary_t getrepolist_dict(void) { prop_dictionary_t dict; + char plist[PATH_MAX]; - dict = prop_dictionary_internalize_from_file(XBPS_REPOLIST_PATH); + if (!xbps_append_full_path(plist, NULL, XBPS_REPOLIST)) + exit(1); + + dict = prop_dictionary_internalize_from_file(plist); if (dict == NULL) { printf("ERROR: cannot find repository plist file (%s).\n", strerror(errno)); @@ -111,45 +115,46 @@ getrepolist_dict(void) return dict; } -static const char * -sanitize_localpath(const char *path) +static bool +sanitize_localpath(char *buf, const char *path) { - static char strtmp[PATH_MAX]; - char *dirnp, *basenp, *dir, *base; - const char *res; + char *dirnp, *basenp, *dir, *base, *tmp; dir = strdup(path); if (dir == NULL) - return NULL; + return false; base = strdup(path); - if (base == NULL) - goto fail2; + if (base == NULL) { + free(dir); + return false; + } dirnp = dirname(dir); if (strcmp(dirnp, ".") == 0) - goto fail; + goto error; basenp = basename(base); if (strcmp(basenp, base) == 0) - goto fail; + goto error; - strncpy(strtmp, dirnp, sizeof(strtmp) - 1); - strtmp[sizeof(strtmp) - 1] = '\0'; + tmp = strncpy(buf, dirnp, PATH_MAX - 1); + if (sizeof(*tmp) >= PATH_MAX) + goto error; + + buf[strlen(buf) + 1] = '\0'; if (strcmp(dirnp, "/")) - strncat(strtmp, "/", sizeof(strtmp) - strlen(strtmp) - 1); - strncat(strtmp, basenp, sizeof(strtmp) - strlen(strtmp) -1); - + strncat(buf, "/", 1); + strncat(buf, basenp, PATH_MAX - strlen(buf) - 1); free(dir); free(base); - res = strtmp; - return res; -fail: + return true; + +error: free(base); -fail2: free(dir); - return NULL; + return false; } int @@ -157,8 +162,8 @@ main(int argc, char **argv) { prop_dictionary_t dict; repo_info_t *rinfo = NULL; - const char *dpkgidx; - char *repolist; + char dpkgidx[PATH_MAX], repolist[PATH_MAX]; + int rv = 0; if (argc < 2) usage(); @@ -168,41 +173,37 @@ main(int argc, char **argv) if (argc != 3) usage(); - dpkgidx = sanitize_localpath(argv[2]); - if (dpkgidx == NULL) + if (!sanitize_localpath(dpkgidx, argv[2])) exit(EINVAL); /* Temp buffer to verify pkgindex file. */ - repolist = xbps_get_pkgidx_string(dpkgidx); - if (repolist == NULL) + if (!xbps_append_full_path(repolist, dpkgidx, XBPS_PKGINDEX)) exit(EINVAL); dict = prop_dictionary_internalize_from_file(repolist); if (dict == NULL) { printf("Directory %s does not contain any " "xbps pkgindex file.\n", dpkgidx); - free(repolist); exit(EINVAL); } rinfo = malloc(sizeof(*rinfo)); if (rinfo == NULL) { - free(repolist); + prop_object_release(dict); exit(ENOMEM); } if (!pkgindex_getinfo(dict, rinfo)) { printf("'%s' is incomplete.\n", repolist); + prop_object_release(dict); free(rinfo); - free(repolist); exit(EINVAL); } - free(repolist); - if (!xbps_register_repository(dpkgidx)) { printf("ERROR: couldn't register repository (%s)\n", strerror(errno)); + prop_object_release(dict); free(rinfo); exit(EINVAL); } @@ -210,6 +211,7 @@ main(int argc, char **argv) printf("Added repository at %s (%s) with %ju packages.\n", rinfo->location_local, rinfo->index_version, rinfo->total_pkgs); + prop_object_release(dict); free(rinfo); } else if (strcasecmp(argv[1], "repo-list") == 0) { @@ -217,16 +219,17 @@ main(int argc, char **argv) if (argc != 2) usage(); - xbps_callback_array_iter_in_dict(getrepolist_dict(), + dict = getrepolist_dict(); + xbps_callback_array_iter_in_dict(dict, "repository-list", xbps_list_strings_in_array, NULL); + prop_object_release(dict); } else if (strcasecmp(argv[1], "repo-rm") == 0) { /* Remove a repository from the pool. */ if (argc != 3) usage(); - dpkgidx = sanitize_localpath(argv[2]); - if (dpkgidx == NULL) + if (!sanitize_localpath(dpkgidx, argv[2])) exit(EINVAL); if (!xbps_unregister_repository(dpkgidx)) { @@ -244,27 +247,33 @@ main(int argc, char **argv) if (argc != 3) usage(); - xbps_callback_array_iter_in_dict(getrepolist_dict(), + dict = getrepolist_dict(); + xbps_callback_array_iter_in_dict(dict, "repository-list", xbps_search_string_in_pkgs, argv[2]); + prop_object_release(dict); } else if (strcasecmp(argv[1], "show") == 0) { /* Shows info about a binary package. */ if (argc != 3) usage(); - if (!xbps_callback_array_iter_in_dict(getrepolist_dict(), - "repository-list", + dict = getrepolist_dict(); + if (!xbps_callback_array_iter_in_dict(dict, "repository-list", xbps_show_pkg_info_from_repolist, argv[2])) { printf("ERROR: unable to locate package '%s'.\n", argv[2]); exit(EINVAL); } + prop_object_release(dict); } else if (strcasecmp(argv[1], "install") == 0) { /* Installs a binary package and required deps. */ if (argc != 3) usage(); + rv = xbps_install_binary_pkg(argv[2], "/home/juan/root_xbps"); + if (rv) + exit(rv); } else { usage(); } diff --git a/bin/xbps-cmpver.c b/bin/xbps-cmpver.c index 612b298af1a..6169a737652 100644 --- a/bin/xbps-cmpver.c +++ b/bin/xbps-cmpver.c @@ -7,61 +7,14 @@ #include #include -static int chkchr(const char *ch) +int main(int argc, char **argv) { - if (*ch>='0' && *ch<='9') - return *ch-'0'; - if (ch[1]=='\0') { - if (*ch>='a'&&*ch<='z'){ - return *ch-'a'; - } + if (argc<3) { + printf("Usage: xbps-cmpver [old] [new]\n"); + printf(" xbpks-cmpver foo-1.2 foo-2.2 # $? = 1\n"); + printf(" xbpks-cmpver foo-1.2 foo-1.2 # $? = 0\n"); + return 1; } - switch(*ch) { - case 'a': if (ch[1]=='l') - return 0xa; - return -1; - case 'b': return 0xb; - case 'r': return 0xc; - } - return -1; -} - -static int ver2int(const char *a0, int *pow, int mpow) -{ - int r,ret = 0; - int pos = 0; - const char *a = a0+strlen(a0)-1; - for(*pow=0;a>=a0;a=a-1) { - if (*a=='.') { - *pow=*pow+1; - } else { - r = chkchr(a); - if (r != -1) - ret+=((r+1)*((*pow)+1))<0 && *pow > mpow) - break; - } - return ret; -} - -int chkver(const char *a0, const char *a1) -{ - int p0,p1; - int v0 = ver2int(a0, &p0, 0); - int v1 = ver2int(a1, &p1, p0); - return v1-v0; -} - -int chkpkg(const char *a0, const char *b0) -{ - char *a = strrchr(a0, '-'); - char *b = strrchr(b0, '-'); - - assert(a != NULL || b != NULL); - - return chkver(a+1, b+1); -} #if UNIT_TEST printf("1.2 2.2 = %d\n", chkver("1.2", "2.2")); @@ -72,13 +25,5 @@ int chkpkg(const char *a0, const char *b0) printf("1.0beta 1.0rc1 = %d\n", chkver("1.0beta", "1.0rc1")); #endif -int main(int argc, char **argv) -{ - if (argc<3) { - printf("Usage: xbps-cmpver [old] [new]\n"); - printf(" xbpks-cmpver foo-1.2 foo-2.2 # $? = 1\n"); - printf(" xbpks-cmpver foo-1.2 foo-1.2 # $? = 0\n"); - return 1; - } - return (chkpkg(argv[1], argv[2]) > 0)?1:0; + return (xbps_cmpver_packages(argv[1], argv[2]) > 0)?1:0; } diff --git a/bin/xbps-pkgdb.c b/bin/xbps-pkgdb.c index 0d61482dabe..c5321e5ff7c 100644 --- a/bin/xbps-pkgdb.c +++ b/bin/xbps-pkgdb.c @@ -125,26 +125,17 @@ main(int argc, char **argv) prop_array_t dbarray = NULL; pkg_data_t pkg; const char *version; - char dbfile[PATH_MAX], *dbfileenv, *tmppath, *in_chroot_env; + char dbfile[PATH_MAX], *in_chroot_env; bool in_chroot = false; if (argc < 2) usage(); - if ((dbfileenv = getenv("XBPS_REGPKGDB_PATH")) != NULL) { - /* Use path as defined by XBPS_REGPKGDB_PATH env var */ - tmppath = strncpy(dbfile, dbfileenv, sizeof(dbfile) - 1); - if (sizeof(*tmppath) >= sizeof(dbfile)) - exit(1); - } else { - /* Use default path */ - tmppath = - strncpy(dbfile, XBPS_REGPKGDB_DEFPATH, sizeof(dbfile) - 1); - if (sizeof(*tmppath) >= sizeof(dbfile)) - exit(1); + if (!xbps_append_full_path(dbfile, NULL, XBPS_REGPKGDB)) { + printf("=> ERROR: couldn't find regpkdb file (%s)\n", + strerror(errno)); + exit(EINVAL); } - /* nul terminate string */ - dbfile[sizeof(dbfile) - 1] = '\0'; in_chroot_env = getenv("in_chroot"); if (in_chroot_env != NULL) diff --git a/bin/xbps-src.sh b/bin/xbps-src.sh index 0561d66dfc5..56859428ef1 100755 --- a/bin/xbps-src.sh +++ b/bin/xbps-src.sh @@ -100,7 +100,7 @@ set_defvars() : ${XBPS_TEMPLATESDIR:=$XBPS_DISTRIBUTIONDIR/templates} : ${XBPS_HELPERSDIR:=$XBPS_TEMPLATESDIR/helpers} : ${XBPS_CACHEDIR:=$XBPS_MASTERDIR/var/cache/xbps} - : ${XBPS_REGPKGDB_PATH:=$XBPS_CACHEDIR/regpkgdb.plist} + : ${XBPS_META_PATH:=$XBPS_CACHEDIR/} : ${XBPS_PKGMETADIR:=$XBPS_CACHEDIR/metadata} : ${XBPS_SHUTILSDIR:=$XBPS_DISTRIBUTIONDIR/shutils} @@ -110,8 +110,7 @@ set_defvars() [ ! -d "$val" ] && msg_error "cannot find $i, aborting." done - XBPS_REGPKGDB_CMD="env XBPS_REGPKGDB_PATH=$XBPS_REGPKGDB_PATH \ - xbps-pkgdb" + XBPS_REGPKGDB_CMD="env XBPS_META_PATH=$XBPS_META_PATH xbps-pkgdb" } # diff --git a/include/plist.h b/include/plist.h index c509f7c731f..226e227d49d 100644 --- a/include/plist.h +++ b/include/plist.h @@ -140,13 +140,22 @@ void xbps_show_pkg_info(prop_dictionary_t); /* * Internal functions. */ -bool xbps_list_pkgs_in_dict(prop_object_t, void *, bool *); -bool xbps_list_strings_in_array(prop_object_t, void *, bool *); -bool xbps_list_strings_in_array2(prop_object_t, void *, bool *); -bool xbps_remove_string_from_array(prop_object_t, void *, bool *); -bool xbps_show_pkg_info_from_repolist(prop_object_t obj, void *, bool *); -bool xbps_show_pkg_namedesc(prop_object_t, void *, bool *); -bool xbps_search_string_in_pkgs(prop_object_t, void *, bool *); -char *xbps_get_pkgidx_string(const char *); +bool xbps_list_pkgs_in_dict(prop_object_t, void *, bool *); +bool xbps_list_strings_in_array(prop_object_t, void *, bool *); +bool xbps_list_strings_in_array2(prop_object_t, void *, bool *); +bool xbps_remove_string_from_array(prop_object_t, void *, bool *); +bool xbps_show_pkg_info_from_repolist(prop_object_t obj, void *, bool *); +bool xbps_show_pkg_namedesc(prop_object_t, void *, bool *); +bool xbps_search_string_in_pkgs(prop_object_t, void *, bool *); +int xbps_install_binary_pkg(const char *, const char *); +int xbps_unpack_binary_pkg(const char *, int (*cb)(struct archive *)); +int xbps_cmpver_packages(const char *, const char *); +int xbps_cmpver_versions(const char *, const char *); +int xbps_check_reqdeps_in_pkg(const char *, prop_dictionary_t); + +/* Utils */ +const char * xbps_get_pkg_version(const char *); +char * xbps_get_pkg_name(const char *); +bool xbps_append_full_path(char *, const char *, const char *); #endif /* !_XBPS_PLIST_H_ */ diff --git a/include/xbps_api.h b/include/xbps_api.h index 232a40fdfc7..6347a9c3c52 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -28,19 +28,30 @@ #include #include -#define NDEBUG #include #include +#include +#include -/* Default PATH for the repositories plist file. */ -#define XBPS_REPOLIST_PATH "/var/cache/xbps/repositories.plist" +/* Default root PATH for xbps to store metadata info. */ +#define XBPS_META_PATH "/var/cache/xbps/" + +/* Filename for the repositories plist file. */ +#define XBPS_REPOLIST "repositories.plist" /* Filename of the package index plist for a repository. */ #define XBPS_PKGINDEX "pkg-index.plist" -/* Default PATH for the plist file to register installed packages. */ -#define XBPS_REGPKGDB_DEFPATH "/var/cache/xbps/regpkgdb.plist" +/* Filename of the packages register. */ +#define XBPS_REGPKGDB "regpkgdb.plist" + +/* Return values for xbps_install_binary_pkg() */ +#define XBPS_PKG_ENOTINREPO 1 /* Not found in repos */ +#define XBPS_PKG_EEXIST 2 /* Already installed */ +#define XBPS_PKG_EINDEPS 3 /* Check deps failed */ +#define XBPS_PKG_ECHDIRDEST 4 /* chdir() to dest failed */ +#define XBPS_PKG_EEMPTY 5 /* empty pkg list */ #include "humanize_number.h" #include "plist.h" diff --git a/lib/Makefile b/lib/Makefile index 13f597cec04..c8a3aaffda3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -6,12 +6,14 @@ MINOR = 0 MICRO = 0 LIBXBPS_SO = $(LIBXBPS).$(MAJOR).$(MINOR).$(MICRO) LIBXBPS = libxbps.so -LIBXBPS_LDFLAGS = -lprop -shared -Wl,-soname,$(LIBXBPS).$(MAJOR) +LIBXBPS_LDFLAGS = -larchive -lprop -shared -Wl,-soname,$(LIBXBPS).$(MAJOR) + +OBJECTS = cmpver.o depends.o humanize_number.o install.o plist.o sha256.o all: $(LIBXBPS) .PHONY: all -$(LIBXBPS): sha256.o plist.o humanize_number.o +$(LIBXBPS): $(OBJECTS) $(CC) $(LIBXBPS_LDFLAGS) $^ -o $(LIBXBPS_SO) -ln -sf $(LIBXBPS_SO) $(LIBXBPS).$(MAJOR) -ln -sf $(LIBXBPS_SO) $(LIBXBPS) diff --git a/lib/cmpver.c b/lib/cmpver.c new file mode 100644 index 00000000000..72e6985a3b9 --- /dev/null +++ b/lib/cmpver.c @@ -0,0 +1,66 @@ +/* + * Compare package and version strings + * @ 2008 + * Author: pancake + */ +#include +#include +#include + +static int chkchr(const char *ch) +{ + if (*ch>='0' && *ch<='9') + return *ch-'0'; + if (ch[1]=='\0') { + if (*ch>='a'&&*ch<='z'){ + return *ch-'a'; + } + } + switch(*ch) { + case 'a': if (ch[1]=='l') + return 0xa; + return -1; + case 'b': return 0xb; + case 'r': return 0xc; + } + return -1; +} + +static int ver2int(const char *a0, int *pow, int mpow) +{ + int r,ret = 0; + int pos = 0; + const char *a = a0+strlen(a0)-1; + for(*pow=0;a>=a0;a=a-1) { + if (*a=='.') { + *pow=*pow+1; + } else { + r = chkchr(a); + if (r != -1) + ret+=((r+1)*((*pow)+1))<0 && *pow > mpow) + break; + } + return ret; +} + +int +xbps_cmpver_versions(const char *a0, const char *a1) +{ + int p0,p1; + int v0 = ver2int(a0, &p0, 0); + int v1 = ver2int(a1, &p1, p0); + return v1-v0; +} + +int +xbps_cmpver_packages(const char *a0, const char *b0) +{ + char *a = strrchr(a0, '-'); + char *b = strrchr(b0, '-'); + + assert(a != NULL || b != NULL); + + return xbps_cmpver_versions(a+1, b+1); +} diff --git a/lib/depends.c b/lib/depends.c new file mode 100644 index 00000000000..25975fd46a7 --- /dev/null +++ b/lib/depends.c @@ -0,0 +1,189 @@ +/*- + * Copyright (c) 2008 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 + +const char * +xbps_get_pkg_version(const char *pkg) +{ + const char *tmp; + + /* Get the required version */ + tmp = strrchr(pkg, '-'); + assert(tmp != NULL); + return tmp + 1; /* skip first '-' */ +} + +char * +xbps_get_pkg_name(const char *pkg) +{ + const char *tmp; + char *pkgname; + size_t len; + + /* Get the required version */ + tmp = strrchr(pkg, '-'); + assert(tmp != NULL); + len = strlen(pkg) - strlen(tmp); + + /* Get package name */ + pkgname = malloc(len + 1); + memcpy(pkgname, pkg, len); + pkgname[len + 1] = '\0'; + + return pkgname; +} + +bool +xbps_append_full_path(char *buf, const char *root, const char *plistf) +{ + const char *env, *tmp; + size_t len = 0; + + assert(buf != NULL); + assert(plistf != NULL); + + if (root) + env = root; + else { + env = getenv("XBPS_META_PATH"); + if (env == NULL) + env = XBPS_META_PATH; + } + + tmp = strncpy(buf, env, PATH_MAX - 1); + if (sizeof(*tmp) >= PATH_MAX) { + errno = ENOSPC; + return false; + } + + len = strlen(buf); + buf[len + 1] = '\0'; + if (buf[len - 2] != '/') + strncat(buf, "/", 1); + strncat(buf, plistf, sizeof(buf) - strlen(buf) - 1); + + return true; +} + +static int +xbps_check_is_installed_pkg(const char *plist, const char *pkg) +{ + prop_dictionary_t dict, pkgdict; + prop_object_t obj; + const char *reqver, *instver; + char *pkgname; + + pkgname = xbps_get_pkg_name(pkg); + reqver = xbps_get_pkg_version(pkg); + + /* Get package dictionary from plist */ + dict = prop_dictionary_internalize_from_file(plist); + if (dict == NULL) { + free(pkgname); + return XBPS_PKG_EEMPTY; + } + + pkgdict = xbps_find_pkg_in_dict(dict, pkgname); + if (pkgdict == NULL) { + prop_object_release(dict); + free(pkgname); + return 1; /* not installed */ + } + + /* Get version from installed package */ + obj = prop_dictionary_get(pkgdict, "version"); + assert(obj != NULL); + assert(prop_object_type(obj) == PROP_TYPE_STRING); + instver = prop_string_cstring_nocopy(obj); + assert(instver != NULL); + free(pkgname); + prop_object_release(dict); + + return (xbps_cmpver_versions(instver, reqver) > 0) ? 1 : 0; +} + +int +xbps_check_reqdeps_in_pkg(const char *plist, prop_dictionary_t pkg) +{ + prop_array_t array; + prop_object_t obj; + prop_object_iterator_t iter; + const char *reqpkg; + int rv = 0; + bool need_deps = false; + + assert(pkg != NULL); + assert(prop_object_type(pkg) == PROP_TYPE_DICTIONARY); + assert(prop_dictionary_count(pkg) != 0); + assert(plist != NULL); + + array = prop_dictionary_get(pkg, "run_depends"); + if (array == NULL) { + /* Package has no required rundeps */ + return 0; + } + + assert(prop_object_type(array) == PROP_TYPE_ARRAY); + assert(prop_array_count(array) != 0); + + iter = prop_array_iterator(array); + if (iter == NULL) { + errno = ENOMEM; + return -1; + } + + while ((obj = prop_object_iterator_next(iter))) { + assert(prop_object_type(obj) == PROP_TYPE_STRING); + reqpkg = prop_string_cstring_nocopy(obj); + + rv = xbps_check_is_installed_pkg(plist, reqpkg); + if (rv == XBPS_PKG_EEMPTY) { + /* No packages registered yet. */ + need_deps = true; + printf("Package '%s' not installed\n", reqpkg); + //xbps_add_pkg_dependency(reqpkg); + + } else if (rv == 1) { + need_deps = true; + printf("Package '%s' required.\n", reqpkg); + + } else if (rv == 0) { + printf("Package '%s' already installed.\n", reqpkg); + + } + } + + prop_object_iterator_release(iter); + + return need_deps; +} diff --git a/lib/install.c b/lib/install.c new file mode 100644 index 00000000000..9806ef6593f --- /dev/null +++ b/lib/install.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2008 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 + +static int unpack_archive_cb(struct archive *); + +int +xbps_install_binary_pkg(const char *pkgname, const char *dest) +{ + prop_dictionary_t repo_dict, pkg_rdict, dict; + prop_object_t obj; + const char *repo = "/storage/xbps/binpkgs/pkg-index.plist"; + char dbfile[PATH_MAX], binfile[PATH_MAX]; + int rv = 0; + + assert(pkgname != NULL); + if (dest) { + if ((rv = chdir(dest)) != 0) + return XBPS_PKG_ECHDIRDEST; + } + + /* Get pkg metadata from a repository */ + repo_dict = prop_dictionary_internalize_from_file(repo); + pkg_rdict = xbps_find_pkg_in_dict(repo_dict, pkgname); + if (pkg_rdict == NULL) + return XBPS_PKG_ENOTINREPO; + + if (!xbps_append_full_path(dbfile, NULL, XBPS_REGPKGDB)) + return EINVAL; + + /* Check if package is already installed. */ + dict = prop_dictionary_internalize_from_file(dbfile); + if (dict && xbps_find_pkg_in_dict(dict, pkgname)) + return XBPS_PKG_EEXIST; + + /* Looks like it's not, check dependencies and install */ + switch (xbps_check_reqdeps_in_pkg(dbfile, pkg_rdict)) { + case -1: + /* There was an error checking pkg deps */ + return XBPS_PKG_EINDEPS; + case 0: + /* Package has no deps, just install it */ + obj = prop_dictionary_get(pkg_rdict, "filename"); + strncpy(binfile, "/storage/xbps/binpkgs/", PATH_MAX - 1); + strncat(binfile, prop_string_cstring_nocopy(obj), PATH_MAX - 1); + obj = prop_dictionary_get(pkg_rdict, "version"); + + printf("=> Installing %s-%s ... ", pkgname, + prop_string_cstring_nocopy(obj)); + + rv = xbps_unpack_binary_pkg(binfile, unpack_archive_cb); + break; + case 1: + /* Package needs deps */ + break; + } + + return rv; +} + +static int +unpack_archive_cb(struct archive *ar) +{ + struct archive_entry *entry; + int rv = 0; + + while (archive_read_next_header(ar, &entry) == ARCHIVE_OK) { + if ((rv = archive_read_extract(ar, entry, 0)) != 0) { + printf("couldn't write %s (%s), ignoring!\n", + archive_entry_pathname(entry), strerror(errno)); + } + } + + printf("done.\n"); + archive_read_finish(ar); + return rv; +} + +int +xbps_unpack_binary_pkg(const char *filename, int (*cb)(struct archive *)) +{ + struct archive *ar; + int rv; + + assert(filename != NULL); + + ar = archive_read_new(); + if (ar == NULL) + return ENOMEM; + + /* Enable support for all format and compression methods */ + archive_read_support_compression_all(ar); + archive_read_support_format_all(ar); + + if ((rv = archive_read_open_filename(ar, filename, 2048)) != 0) { + archive_read_finish(ar); + return rv; + } + + return (*cb)(ar); +} diff --git a/lib/plist.c b/lib/plist.c index e98fced178f..b69e9bee8dd 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -155,32 +155,6 @@ xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key) return prop_array_iterator(array); } -char * -xbps_get_pkgidx_string(const char *repofile) -{ - char plist[PATH_MAX], *dest, *result; - size_t len = 0; - - assert(repofile != NULL); - - /* Add full path to pkg-index.plist file */ - dest = strncpy(plist, repofile, sizeof(plist) - 1); - if (sizeof(*dest) >= sizeof(plist)) - return NULL; - - plist[sizeof(plist) - 1] = '\0'; - strncat(plist, "/", sizeof(plist) - strlen(plist) - 1); - strncat(plist, XBPS_PKGINDEX, sizeof(plist) - strlen(plist) - 1); - - len = strlen(plist); - result = malloc(len + 1); - if (result == NULL) - return NULL; - - strncpy(result, plist, len); - return result; -} - bool xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist) { @@ -250,11 +224,17 @@ xbps_register_repository(const char *uri) prop_dictionary_t dict; prop_array_t array = NULL; prop_object_t obj; + char plist[PATH_MAX]; assert(uri != NULL); + if (!xbps_append_full_path(plist, NULL, XBPS_REPOLIST)) { + errno = EINVAL; + return false; + } + /* First check if we have the repository plist file. */ - dict = prop_dictionary_internalize_from_file(XBPS_REPOLIST_PATH); + dict = prop_dictionary_internalize_from_file(plist); if (dict == NULL) { /* Looks like not, create it. */ dict = prop_dictionary_create(); @@ -276,8 +256,7 @@ xbps_register_repository(const char *uri) goto fail; /* Write dictionary into plist file. */ - if (!prop_dictionary_externalize_to_file(dict, - XBPS_REPOLIST_PATH)) + if (!prop_dictionary_externalize_to_file(dict, plist)) goto fail; prop_object_release(dict); @@ -302,8 +281,7 @@ xbps_register_repository(const char *uri) } /* Write dictionary into plist file. */ - if (!prop_dictionary_externalize_to_file(dict, - XBPS_REPOLIST_PATH)) { + if (!prop_dictionary_externalize_to_file(dict, plist)) { prop_object_release(obj); return false; } @@ -324,11 +302,17 @@ xbps_unregister_repository(const char *uri) prop_dictionary_t dict; prop_array_t array; struct callback_args *cb; + char plist[PATH_MAX]; bool done = false; assert(uri != NULL); - dict = prop_dictionary_internalize_from_file(XBPS_REPOLIST_PATH); + if (!xbps_append_full_path(plist, NULL, XBPS_REPOLIST)) { + errno = EINVAL; + return false; + } + + dict = prop_dictionary_internalize_from_file(plist); if (dict == NULL) return false; @@ -354,8 +338,7 @@ xbps_unregister_repository(const char *uri) prop_array_remove(array, cb->number); /* Update plist file. */ - if (prop_dictionary_externalize_to_file(dict, - XBPS_REPOLIST_PATH)) { + if (prop_dictionary_externalize_to_file(dict, plist)) { free(cb); return true; } @@ -475,7 +458,7 @@ xbps_search_string_in_pkgs(prop_object_t obj, void *arg, bool *loop_done) { prop_dictionary_t dict; const char *repofile; - char *plist; + char plist[PATH_MAX]; assert(prop_object_type(obj) == PROP_TYPE_STRING); @@ -483,23 +466,17 @@ xbps_search_string_in_pkgs(prop_object_t obj, void *arg, bool *loop_done) repofile = prop_string_cstring_nocopy(obj); assert(repofile != NULL); - /* Get string for pkg-index.plist with full path. */ - plist = xbps_get_pkgidx_string(repofile); - if (plist == NULL) + if (!xbps_append_full_path(plist, repofile, XBPS_PKGINDEX)) return false; dict = prop_dictionary_internalize_from_file(plist); - if (dict == NULL || prop_dictionary_count(dict) == 0) { - free(plist); + if (dict == NULL) return false; - } printf("From %s repository ...\n", repofile); xbps_callback_array_iter_in_dict(dict, "packages", xbps_show_pkg_namedesc, arg); - free(plist); - return true; } @@ -509,7 +486,7 @@ xbps_show_pkg_info_from_repolist(prop_object_t obj, void *arg, bool *loop_done) prop_dictionary_t dict, pkgdict; prop_string_t oloc; const char *repofile, *repoloc; - char *plist; + char plist[PATH_MAX]; assert(prop_object_type(obj) == PROP_TYPE_STRING); @@ -517,17 +494,13 @@ xbps_show_pkg_info_from_repolist(prop_object_t obj, void *arg, bool *loop_done) repofile = prop_string_cstring_nocopy(obj); /* Get string for pkg-index.plist with full path. */ - plist = xbps_get_pkgidx_string(repofile); - if (plist == NULL) + if (!xbps_append_full_path(plist, repofile, XBPS_PKGINDEX)) return false; dict = prop_dictionary_internalize_from_file(plist); - if (dict == NULL || prop_dictionary_count(dict) == 0) { - free(plist); + if (dict == NULL || prop_dictionary_count(dict) == 0) return false; - } - free(plist); pkgdict = xbps_find_pkg_in_dict(dict, arg); if (pkgdict == NULL) return false;