diff --git a/include/install.h b/include/install.h index 3c214f6d57..776e1168e8 100644 --- a/include/install.h +++ b/include/install.h @@ -35,7 +35,8 @@ int xbps_register_pkg(prop_dictionary_t, const char *, const char *, const char *, bool); int xbps_unpack_binary_pkg(prop_dictionary_t, prop_dictionary_t, const char *, int); -int xbps_update_pkg_requiredby(prop_array_t, prop_dictionary_t); +int xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t); +int xbps_requiredby_pkg_remove(const char *); int xbps_find_deps_in_pkg(prop_dictionary_t); prop_dictionary_t xbps_get_pkg_deps_dictionary(void); diff --git a/include/plist.h b/include/plist.h index c41cd14c2b..d982dd3940 100644 --- a/include/plist.h +++ b/include/plist.h @@ -64,6 +64,9 @@ xbps_find_pkg_in_dict(prop_dictionary_t, const char *, const char *); prop_dictionary_t xbps_find_pkg_from_plist(const char *, const char *); +prop_dictionary_t +xbps_find_pkg_installed_from_plist(const char *); + /* * Finds a string object in an array. * diff --git a/lib/install.c b/lib/install.c index e5fac16111..6c6f46e67a 100644 --- a/lib/install.c +++ b/lib/install.c @@ -83,10 +83,10 @@ xbps_install_binary_pkg(const char *pkgname, const char *destdir, int flags) assert(pkgname != NULL); if (destdir) { - if ((rv = chdir(destdir)) != 0) + if (chdir(destdir) == -1) return errno; } else { - if ((rv = chdir("/")) != 0) + if (chdir("/") == -1) return errno; destdir = "NOTSET"; } @@ -138,6 +138,10 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) return 0; } + /* + * Check SHA256 hash for binary package before anything else. + */ + /* * Check if this package needs dependencies. */ @@ -167,7 +171,6 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) if ((rv = xbps_install_pkg_deps(pkgname, destdir, cb->flags)) == 0) { rv = xbps_install_binary_pkg_fini(repod, pkgrd, destdir, cb->flags); - prop_object_release(repod); if (rv == 0) *cbloop_done = true; } @@ -176,6 +179,8 @@ install_binpkg_repo_cb(prop_object_t obj, void *arg, bool *cbloop_done) if (rv == 0) errno = 0; + prop_object_release(repod); + return rv; } @@ -263,7 +268,7 @@ xbps_register_pkg(prop_dictionary_t pkgrd, const char *pkgname, automatic); if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) { - rv = xbps_update_pkg_requiredby(array, pkgrd); + rv = xbps_requiredby_pkg_add(array, pkgrd); if (rv != 0) { prop_object_release(pkgd); goto out; diff --git a/lib/plist.c b/lib/plist.c index 5fd8d354fb..b07c1731a1 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -130,8 +130,7 @@ xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key, prop_dictionary_t xbps_find_pkg_from_plist(const char *plist, const char *pkgname) { - prop_dictionary_t dict; - prop_dictionary_t obj, res; + prop_dictionary_t dict, obj, res; assert(plist != NULL); assert(pkgname != NULL); @@ -155,6 +154,22 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname) return res; } +prop_dictionary_t +xbps_find_pkg_installed_from_plist(const char *pkgname) +{ + prop_dictionary_t pkgd; + char *plist; + + plist = xbps_append_full_path(true, NULL, XBPS_REGPKGDB); + if (plist == NULL) + return NULL; + + pkgd = xbps_find_pkg_from_plist(plist, pkgname); + free(plist); + + return prop_dictionary_copy(pkgd); +} + prop_dictionary_t xbps_find_pkg_in_dict(prop_dictionary_t dict, const char *key, const char *pkgname) diff --git a/lib/remove.c b/lib/remove.c index b8e98b35d9..b2c6b5e8ba 100644 --- a/lib/remove.c +++ b/lib/remove.c @@ -172,7 +172,7 @@ out: int xbps_remove_binary_pkg(const char *pkgname, const char *destdir, int flags) { - prop_dictionary_t fdict; + prop_dictionary_t dict; struct rm_cbarg rmcbarg; char path[PATH_MAX - 1], *buf; int fd, rv = 0; @@ -202,18 +202,22 @@ xbps_remove_binary_pkg(const char *pkgname, const char *destdir, int flags) return -1; } - /* Find out if the REMOVE file exists */ + /* + * Find out if the REMOVE file exists. + */ if ((fd = open(buf, O_RDONLY)) == -1) { if (errno != ENOENT) { free(buf); return errno; } } else { - /* Run the preremove action */ + /* + * Run the pre remove action. + */ (void)close(fd); prepostf = true; - if ((rv = xbps_file_exec(buf, destdir, "pre", pkgname, - NULL)) != 0) { + rv = xbps_file_exec(buf, destdir, "pre", pkgname, NULL); + if (rv != 0) { printf("%s: prerm action target error (%s)\n", pkgname, strerror(errno)); free(buf); @@ -228,8 +232,8 @@ xbps_remove_binary_pkg(const char *pkgname, const char *destdir, int flags) (void)snprintf(path, sizeof(path), "%s%s/metadata/%s/files.plist", destdir, XBPS_META_PATH, pkgname); - fdict = prop_dictionary_internalize_from_file(path); - if (fdict == NULL) { + dict = prop_dictionary_internalize_from_file(path); + if (dict == NULL) { free(buf); return errno; } @@ -237,18 +241,19 @@ xbps_remove_binary_pkg(const char *pkgname, const char *destdir, int flags) rmcbarg.destdir = destdir; rmcbarg.flags = flags; - rv = xbps_callback_array_iter_in_dict(fdict, "filelist", + rv = xbps_callback_array_iter_in_dict(dict, "filelist", remove_pkg_files, (void *)&rmcbarg); if (rv != 0) { free(buf); - prop_object_release(fdict); + prop_object_release(dict); return rv; } - prop_object_release(fdict); + prop_object_release(dict); - /* If successful, unregister pkg from db */ - if (((rv = xbps_unregister_pkg(pkgname)) == 0) && prepostf) { - /* Run the postremove action target */ + /* + * Run the post remove action if REMOVE file is there. + */ + if (prepostf) { if ((rv = xbps_file_exec(buf, destdir, "post", pkgname, NULL)) != 0) { printf("%s: postrm action target error (%s)\n", @@ -257,9 +262,24 @@ xbps_remove_binary_pkg(const char *pkgname, const char *destdir, int flags) return rv; } } - free(buf); - rv = xbps_remove_binary_pkg_meta(pkgname, destdir, flags); - return rv; + /* + * Update the required_by array of all required dependencies. + */ + rv = xbps_requiredby_pkg_remove(pkgname); + if (rv != 0) + return rv; + + /* + * Unregister pkg from database. + */ + rv = xbps_unregister_pkg(pkgname); + if (rv != 0) + return rv; + + /* + * Remove pkg metadata directory. + */ + return xbps_remove_binary_pkg_meta(pkgname, destdir, flags); } diff --git a/lib/requiredby.c b/lib/requiredby.c index 4aca53d179..f35a9a803a 100644 --- a/lib/requiredby.c +++ b/lib/requiredby.c @@ -35,7 +35,7 @@ #include static int -add_pkg_into_requiredby(prop_dictionary_t pkgd, const char *reqname) +add_pkg_into_reqby(prop_dictionary_t pkgd, const char *reqname) { prop_array_t array; prop_string_t reqstr; @@ -80,8 +80,77 @@ add_pkg_into_requiredby(prop_dictionary_t pkgd, const char *reqname) return 0; } +static int +remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done) +{ + prop_array_t array; + prop_object_t obj2; + prop_object_iterator_t iter; + const char *pkgname = arg; + char *curpkgname; + size_t idx = 0; + bool found = false; + + (void)loop_done; + + array = prop_dictionary_get(obj, "requiredby"); + if (array == NULL || prop_array_count(array) == 0) + return 0; + + iter = prop_array_iterator(array); + if (iter == NULL) + return ENOMEM; + + while ((obj2 = prop_object_iterator_next(iter)) != NULL) { + curpkgname = + xbps_get_pkg_name(prop_string_cstring_nocopy(obj2)); + if (strcmp(curpkgname, pkgname) == 0) { + free(curpkgname); + found = true; + break; + } + free(curpkgname); + idx++; + } + prop_object_iterator_release(iter); + if (found) + prop_array_remove(array, idx); + + return 0; +} + int -xbps_update_pkg_requiredby(prop_array_t regar, prop_dictionary_t pkg) +xbps_requiredby_pkg_remove(const char *pkgname) +{ + prop_dictionary_t dict; + char *plist; + int rv = 0; + + plist = xbps_append_full_path(true, NULL, XBPS_REGPKGDB); + if (plist == NULL) + return EINVAL; + + dict = prop_dictionary_internalize_from_file(plist); + if (dict == NULL) { + free(plist); + return errno; + } + + rv = xbps_callback_array_iter_in_dict(dict, "packages", + remove_pkg_from_reqby, (void *)pkgname); + if (rv == 0) { + if (!prop_dictionary_externalize_to_file(dict, plist)) + rv = errno; + } + + prop_object_release(dict); + free(plist); + + return rv; +} + +int +xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) { prop_array_t rdeps; prop_object_t obj, obj2; @@ -114,13 +183,11 @@ xbps_update_pkg_requiredby(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)); - iter2 = prop_array_iterator(regar); if (iter2 == NULL) { - free(fpkgn); free(rdepname); - prop_object_iterator_release(iter); - return ENOMEM; + rv = ENOMEM; + goto out; } /* @@ -131,7 +198,7 @@ xbps_update_pkg_requiredby(prop_array_t regar, prop_dictionary_t pkg) prop_dictionary_get_cstring_nocopy(obj2, "pkgname", &reqname); if (strcmp(rdepname, reqname) == 0) { - rv = add_pkg_into_requiredby(obj2, fpkgn); + rv = add_pkg_into_reqby(obj2, fpkgn); if (rv != 0) { free(rdepname); prop_object_iterator_release(iter2); @@ -140,8 +207,8 @@ xbps_update_pkg_requiredby(prop_array_t regar, prop_dictionary_t pkg) break; } } - free(rdepname); prop_object_iterator_release(iter2); + free(rdepname); } out: diff --git a/lib/unpack.c b/lib/unpack.c index 922922fab2..2950a01d3c 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -123,7 +123,7 @@ unpack_archive_init(prop_dictionary_t pkg, const char *destdir, * is really on storage (if possible). */ if (rv == 0) - if ((rv = fdatasync(pkg_fd)) == -1) + if (fdatasync(pkg_fd) == -1) rv = errno; archive_read_finish(ar); @@ -149,11 +149,10 @@ unpack_archive_fini(struct archive *ar, const char *destdir, int flags, prop_dictionary_t pkg) { struct archive_entry *entry; - struct stat st; size_t len; const char *prepost = "./INSTALL"; const char *pkgname, *version; - char *buf, *path; + char *buf; int rv = 0, lflags = 0; bool actgt = false; @@ -183,23 +182,6 @@ unpack_archive_fini(struct archive *ar, const char *destdir, int flags, } while (archive_read_next_header(ar, &entry) == ARCHIVE_OK) { - /* - * Check that entry doesn't already exist. - */ - path = xbps_append_full_path(false, destdir, - archive_entry_pathname(entry)); - if (path == NULL) { - rv = ENOMEM; - break; - } - - rv = stat(path, &st); - if (rv == 0) { - free(path); - continue; - } - free(path); - /* * Run the pre installation action target if there's a script * before writing data to disk. @@ -211,9 +193,10 @@ unpack_archive_fini(struct archive *ar, const char *destdir, int flags, archive_entry_set_pathname(entry, buf); - rv = archive_read_extract(ar, entry, lflags); - if (rv != 0 && errno != EEXIST) - break; + if (archive_read_extract(ar, entry, lflags) != 0) { + if ((rv = archive_errno(ar)) != EEXIST) + break; + } if ((rv = xbps_file_exec(buf, destdir, "pre", pkgname, version, NULL)) != 0) { @@ -229,19 +212,24 @@ unpack_archive_fini(struct archive *ar, const char *destdir, int flags, /* * Extract all data from the archive now. */ - rv = archive_read_extract(ar, entry, lflags); - if (rv != 0 && errno != EEXIST) { - printf("ERROR: couldn't unpack %s (%s), exiting!\n", - archive_entry_pathname(entry), strerror(errno)); - (void)fflush(stdout); - break; - } else if (rv != 0 && errno == EEXIST) { - if (flags & XBPS_UNPACK_VERBOSE) { - printf("WARNING: ignoring existent path: %s.\n", - archive_entry_pathname(entry)); + if (archive_read_extract(ar, entry, lflags) != 0) { + rv = archive_errno(ar); + if (rv != EEXIST) { + printf("ERROR: couldn't unpack %s (%s), " + "exiting!\n", archive_entry_pathname(entry), + archive_error_string(ar)); (void)fflush(stdout); + break; + } else if (rv == EEXIST) { + if (flags & XBPS_UNPACK_VERBOSE) { + printf("WARNING: ignoring existent " + "path: %s\n", + archive_entry_pathname(entry)); + (void)fflush(stdout); + } + rv = 0; + continue; } - continue; } if (flags & XBPS_UNPACK_VERBOSE) { diff --git a/lib/util.c b/lib/util.c index 8a08220deb..48d24a9361 100644 --- a/lib/util.c +++ b/lib/util.c @@ -64,49 +64,29 @@ xbps_check_file_hash(const char *path, const char *sha256) int xbps_check_is_installed_pkg(const char *pkg) { - prop_dictionary_t dict, pkgdict; - prop_object_t obj; + prop_dictionary_t dict; const char *reqver, *instver; - char *plist, *pkgname; + char *pkgname; int rv = 0; assert(pkg != NULL); - plist = xbps_append_full_path(true, NULL, XBPS_REGPKGDB); - if (plist == NULL) - return -1; - pkgname = xbps_get_pkg_name(pkg); reqver = xbps_get_pkg_version(pkg); - /* Get package dictionary from plist */ - dict = prop_dictionary_internalize_from_file(plist); + dict = xbps_find_pkg_installed_from_plist(pkgname); if (dict == NULL) { free(pkgname); - free(plist); - return 1; /* not installed */ - } - - pkgdict = xbps_find_pkg_in_dict(dict, "packages", pkgname); - if (pkgdict == NULL) { - prop_object_release(dict); - free(pkgname); - free(plist); 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); + prop_dictionary_get_cstring_nocopy(dict, "version", &instver); /* Compare installed and required version. */ rv = xbps_cmpver_versions(instver, reqver); free(pkgname); - free(plist); prop_object_release(dict); return rv; @@ -116,16 +96,10 @@ bool xbps_check_is_installed_pkgname(const char *pkgname) { prop_dictionary_t pkgd; - char *plist; assert(pkgname != NULL); - plist = xbps_append_full_path(true, NULL, XBPS_REGPKGDB); - if (plist == NULL) - return false; - - pkgd = xbps_find_pkg_from_plist(plist, pkgname); - free(plist); + pkgd = xbps_find_pkg_installed_from_plist(pkgname); if (pkgd) { prop_object_release(pkgd); return true;