diff --git a/bin/xbps-repo/util.c b/bin/xbps-repo/util.c index eaeed0cc0a2..1a720d39e5c 100644 --- a/bin/xbps-repo/util.c +++ b/bin/xbps-repo/util.c @@ -35,13 +35,7 @@ #include #include "util.h" -struct show_files_cb { - const char *destdir; - bool check_hash; -}; - static void show_pkg_info(prop_dictionary_t); -static int show_pkg_files(prop_object_t, void *, bool *); static int show_pkg_namedesc(prop_object_t, void *, bool *); static void @@ -206,11 +200,14 @@ int show_pkg_files_from_metadir(const char *pkgname, bool hash) { prop_dictionary_t pkgd; - struct show_files_cb sfc; - const char *destdir = xbps_get_rootdir(); - char *plist; - int rv = 0; + prop_array_t array; + prop_object_iterator_t iter = NULL; + prop_object_t obj; + const char *destdir, *file, *sha256; + char *plist, *path = NULL, *array_str = "files"; + int i, rv = 0; + destdir = xbps_get_rootdir(); plist = xbps_xasprintf("%s/%s/metadata/%s/%s", destdir, XBPS_META_PATH, pkgname, XBPS_PKGFILES); if (plist == NULL) @@ -221,65 +218,81 @@ show_pkg_files_from_metadir(const char *pkgname, bool hash) free(plist); return errno; } - - sfc.destdir = destdir; - sfc.check_hash = hash; - rv = xbps_callback_array_iter_in_dict(pkgd, "filelist", - show_pkg_files, (void *)&sfc); - prop_object_release(pkgd); free(plist); - return rv; -} - -static int -show_pkg_files(prop_object_t obj, void *arg, bool *loop_done) -{ - struct show_files_cb *sfc = arg; - const char *file = NULL, *sha256, *type; - char *path = NULL; - int rv = 0; - - (void)loop_done; - - prop_dictionary_get_cstring_nocopy(obj, "file", &file); - prop_dictionary_get_cstring_nocopy(obj, "type", &type); - if (strcmp(type, "dir") == 0) - return 0; - - if (sfc->check_hash == false && file != NULL) { - printf("%s\n", file); - return 0; - } - - if (strcmp(type, "link") == 0) - return 0; - - if (sfc->check_hash && file != NULL) { - printf("%s", file); - if (sfc->destdir) { - path = xbps_xasprintf("%s/%s", sfc->destdir, file); - if (path == NULL) - return EINVAL; + /* Links. */ + array = prop_dictionary_get(pkgd, "links"); + if (array && prop_array_count(array) > 0) { + iter = xbps_get_array_iter_from_dict(pkgd, "links"); + if (iter == NULL) { + rv = EINVAL; + goto out; } - - prop_dictionary_get_cstring_nocopy(obj, "sha256", &sha256); - if (sfc->destdir) - rv = xbps_check_file_hash(path, sha256); - else - rv = xbps_check_file_hash(file, sha256); - - if (rv != 0 && rv != ERANGE) - printf(" (can't check: %s)", strerror(rv)); - else if (rv == ERANGE) - printf(" WARNING! SHA256 HASH MISMATCH!"); - - printf("\n"); - if (sfc->destdir) - free(path); + while ((obj = prop_object_iterator_next(iter))) { + prop_dictionary_get_cstring_nocopy(obj, "file", &file); + printf("%s\n", file); + } + prop_object_iterator_release(iter); + iter = NULL; } - return 0; + /* Files and configuration files. */ + for (i = 0; i < 2; i++) { + if (i == 0) + array_str = "conf_files"; + else + array_str = "files"; + + array = prop_dictionary_get(pkgd, array_str); + if (array == NULL || prop_array_count(array) == 0) + continue; + + iter = xbps_get_array_iter_from_dict(pkgd, array_str); + if (iter == NULL) { + rv = EINVAL; + goto out; + } + while ((obj = prop_object_iterator_next(iter))) { + prop_dictionary_get_cstring_nocopy(obj, "file", &file); + if (hash == false) { + printf("%s\n", file); + continue; + } + + printf("%s", file); + if (destdir) { + path = xbps_xasprintf("%s/%s", destdir, file); + if (path == NULL) { + rv = EINVAL; + goto out2; + } + } + prop_dictionary_get_cstring_nocopy(obj, + "sha256", &sha256); + if (destdir) + rv = xbps_check_file_hash(path, sha256); + else + rv = xbps_check_file_hash(file, sha256); + + if (rv != 0 && rv != ERANGE) + printf(" (can't check: %s)", strerror(rv)); + else if (rv == ERANGE) + printf(" WARNING! SHA256 HASH MISMATCH!"); + + printf("\n"); + if (destdir) + free(path); + } + prop_object_iterator_release(iter); + iter = NULL; + } +out2: + if (iter != NULL) + prop_object_iterator_release(iter); +out: + prop_object_release(pkgd); + + return rv; } int diff --git a/doc/TODO b/doc/TODO index a8d37a83928..557e6d8ba16 100644 --- a/doc/TODO +++ b/doc/TODO @@ -26,8 +26,6 @@ xbps-bin: overwritting files on disk and updating required_by if required. Perhaps change the automatic-install object to false, like pkg_install from NetBSD do. - * When checking file hash integrity (with -C files), it doesn't take - into account configuration files. * Implement shell style match patterns with fnmatch(). * Make -f flag to overwrite files when installing, and to ignore files with wrong checksum or unexistent when removing. diff --git a/lib/remove.c b/lib/remove.c index 93f1da01493..efa1d7b1ba6 100644 --- a/lib/remove.c +++ b/lib/remove.c @@ -36,7 +36,7 @@ #include -static int remove_pkg_files(prop_object_t, void *, bool *); +static int remove_pkg_files(prop_dictionary_t); int xbps_unregister_pkg(const char *pkgname) @@ -111,99 +111,161 @@ xbps_remove_binary_pkg_meta(const char *pkgname) } static int -remove_pkg_files(prop_object_t obj, void *arg, bool *loop_done) +remove_pkg_files(prop_dictionary_t dict) { + prop_array_t array; + prop_object_iterator_t iter; + prop_object_t obj; prop_bool_t bobj; - const char *file, *rootdir, *sha256, *type; + const char *file, *rootdir, *sha256, *array_str, *curftype; char *path = NULL; - int flags = 0, rv = 0; - - (void)arg; - (void)loop_done; + int i, flags = 0, rv = 0; rootdir = xbps_get_rootdir(); flags = xbps_get_flags(); - if (!prop_dictionary_get_cstring_nocopy(obj, "file", &file)) + /* Links */ + array = prop_dictionary_get(dict, "links"); + if (array == NULL || prop_array_count(array) == 0) + goto files; + + iter = xbps_get_array_iter_from_dict(dict, "links"); + if (iter == NULL) return EINVAL; - path = xbps_xasprintf("%s/%s", rootdir, file); - if (path == NULL) - return EINVAL; - - if (!prop_dictionary_get_cstring_nocopy(obj, "type", &type)) { - free(path); - return EINVAL; - } - - if (strcmp(type, "file") == 0) { - prop_dictionary_get_cstring_nocopy(obj, "sha256", &sha256); - rv = xbps_check_file_hash(path, sha256); - if (rv != 0 && rv != ERANGE) { - free(path); - return rv; + while ((obj = prop_object_iterator_next(iter))) { + if (!prop_dictionary_get_cstring_nocopy(obj, "file", &file)) { + prop_object_iterator_release(iter); + return EINVAL; } - - bobj = prop_dictionary_get(obj, "conf_file"); - if (bobj != NULL) { - /* - * If hash is the same than the one provided by - * package, that means the file hasn't been changed - * and therefore can be removed. Otherwise keep it. - */ - if (rv == ERANGE) - goto out; + path = xbps_xasprintf("%s/%s", rootdir, file); + if (path == NULL) { + prop_object_iterator_release(iter); + return EINVAL; } - - if (rv == ERANGE) { - if (flags & XBPS_VERBOSE) - printf("WARNING: SHA256 doesn't match for " - "file %s, ignoring...\n", file); - goto out; - } - - if ((rv = remove(path)) == -1) { - if (flags & XBPS_VERBOSE) - printf("WARNING: can't remove file %s (%s)\n", - file, strerror(errno)); - goto out; - } - if (flags & XBPS_VERBOSE) - printf("Removed file: %s\n", file); - - goto out; - } else if (strcmp(type, "dir") == 0) { - if ((bobj = prop_dictionary_get(obj, "keep")) != NULL) { - /* Skip permanent directory. */ - return 0; - } - - if ((rv = rmdir(path)) == -1) { - if (errno == ENOTEMPTY) - goto out; - - if (flags & XBPS_VERBOSE) { - printf("WARNING: can't remove " - "directory %s (%s)\n", file, - strerror(errno)); - goto out; - } - if (flags & XBPS_VERBOSE) - printf("Removed directory: %s\n", file); - } - } else if (strcmp(type, "link") == 0) { if ((rv = remove(path)) == -1) { if (flags & XBPS_VERBOSE) printf("WARNING: can't remove link %s (%s)\n", file, strerror(errno)); - goto out; + free(path); + continue; } if (flags & XBPS_VERBOSE) printf("Removed link: %s\n", file); + + free(path); + } + prop_object_iterator_release(iter); + path = NULL; + +files: + /* Regular files and configuration files */ + for (i = 0; i < 2; i++) { + if (i == 0) { + array_str = "conf_files"; + curftype = "config file"; + } else { + array_str = "files"; + curftype = "file"; + } + array = prop_dictionary_get(dict, array_str); + if (array == NULL || prop_array_count(array) == 0) { + if (i == 0) + continue; + else + goto dirs; + } + iter = xbps_get_array_iter_from_dict(dict, array_str); + if (iter == NULL) + return EINVAL; + + while ((obj = prop_object_iterator_next(iter))) { + if (!prop_dictionary_get_cstring_nocopy(obj, + "file", &file)) { + prop_object_iterator_release(iter); + return EINVAL; + } + path = xbps_xasprintf("%s/%s", rootdir, file); + if (path == NULL) { + prop_object_iterator_release(iter); + return EINVAL; + } + prop_dictionary_get_cstring_nocopy(obj, + "sha256", &sha256); + rv = xbps_check_file_hash(path, sha256); + if (rv != 0 && rv != ERANGE) { + free(path); + prop_object_iterator_release(iter); + return rv; + } + if (rv == ERANGE) { + if (flags & XBPS_VERBOSE) + printf("WARNING: SHA256 doesn't match " + "for %s %s, ignoring...\n", + curftype, file); + free(path); + continue; + } + if ((rv = remove(path)) == -1) { + if (flags & XBPS_VERBOSE) + printf("WARNING: can't remove " + "%s %s (%s)\n", curftype, file, + strerror(errno)); + free(path); + continue; + } + if (flags & XBPS_VERBOSE) + printf("Removed %s: %s\n", curftype, file); + + free(path); + } + prop_object_iterator_release(iter); + path = NULL; } -out: - free(path); +dirs: + /* Directories */ + array = prop_dictionary_get(dict, "dirs"); + if (array == NULL || prop_array_count(array) == 0) + return 0; + + iter = xbps_get_array_iter_from_dict(dict, "dirs"); + if (iter == NULL) + return EINVAL; + + while ((obj = prop_object_iterator_next(iter))) { + if ((bobj = prop_dictionary_get(obj, "keep")) != NULL) { + /* Skip permanent directory. */ + continue; + } + if (!prop_dictionary_get_cstring_nocopy(obj, "file", &file)) { + prop_object_iterator_release(iter); + return EINVAL; + } + path = xbps_xasprintf("%s/%s", rootdir, file); + if (path == NULL) { + prop_object_iterator_release(iter); + return EINVAL; + } + if ((rv = rmdir(path)) == -1) { + if (errno == ENOTEMPTY) { + free(path); + continue; + } + if (flags & XBPS_VERBOSE) { + printf("WARNING: can't remove " + "directory %s (%s)\n", file, + strerror(errno)); + free(path); + continue; + } + } + if (flags & XBPS_VERBOSE) + printf("Removed directory: %s\n", file); + + free(path); + } + prop_object_iterator_release(iter); return 0; } @@ -244,8 +306,6 @@ xbps_remove_binary_pkg(const char *pkgname, bool update) * Run the pre remove action. */ prepostf = true; - (void)printf("\n"); - (void)fflush(stdout); rv = xbps_file_chdir_exec(rootdir, buf, "pre", pkgname, NULL); if (rv != 0) { printf("%s: prerm action target error (%s)\n", pkgname, @@ -274,8 +334,7 @@ xbps_remove_binary_pkg(const char *pkgname, bool update) } free(path); - rv = xbps_callback_array_iter_in_dict(dict, "filelist", - remove_pkg_files, NULL); + rv = remove_pkg_files(dict); if (rv != 0) { free(buf); prop_object_release(dict); diff --git a/shutils/metadata.sh b/shutils/metadata.sh index f08fbd0a994..7158074fb1e 100644 --- a/shutils/metadata.sh +++ b/shutils/metadata.sh @@ -32,8 +32,6 @@ write_metadata_flist_header() -filelist - _EOF } @@ -92,7 +90,7 @@ xbps_write_metadata_pkg() xbps_write_metadata_pkg_real() { local metadir=${DESTDIR}/var/db/xbps/metadata/$pkgname - local f i j arch dirat lnkat newlnk lver TMPFLIST TMPFPLIST + local f i j found arch dirat lnkat newlnk lver TMPFLIST TMPFPLIST local fpattern="s|${DESTDIR}||g;s|^\./$||g;/^$/d" if [ ! -d "${DESTDIR}" ]; then @@ -186,6 +184,8 @@ xbps_write_metadata_pkg_real() write_metadata_flist_header $TMPFPLIST # Pass 1: add links. + echo "links" >> $TMPFPLIST + echo "" >> $TMPFPLIST for f in $(find ${DESTDIR} -type l); do j=$(echo $f|sed -e "$fpattern") [ "$j" = "" ] && continue @@ -193,34 +193,34 @@ xbps_write_metadata_pkg_real() echo "" >> $TMPFPLIST echo "file" >> $TMPFPLIST echo "$j" >> $TMPFPLIST - echo "type" >> $TMPFPLIST - echo "link" >> $TMPFPLIST echo "" >> $TMPFPLIST done + echo "" >> $TMPFPLIST # Pass 2: add regular files. + echo "files" >> $TMPFPLIST + echo "" >> $TMPFPLIST for f in $(find ${DESTDIR} -type f); do j=$(echo $f|sed -e "$fpattern") [ "$j" = "" ] && continue echo "$j" >> $TMPFLIST + # Skip configuration files. + for i in ${conf_files}; do + [ "$j" = "$i" ] && found=1 && break + done + [ -n "$found" ] && unset found && continue echo "" >> $TMPFPLIST echo "file" >> $TMPFPLIST echo "$j" >> $TMPFPLIST - echo "type" >> $TMPFPLIST - echo "file" >> $TMPFPLIST echo "sha256" >> $TMPFPLIST echo "$(xbps-digest $f)" >> $TMPFPLIST - for i in ${conf_files}; do - if [ "$j" = "$i" ]; then - echo "conf_file" >> $TMPFPLIST - echo "" >> $TMPFPLIST - break - fi - done echo "" >> $TMPFPLIST done + echo "" >> $TMPFPLIST # Pass 3: add directories. + echo "dirs" >> $TMPFPLIST + echo "" >> $TMPFPLIST for f in $(find ${DESTDIR} -type d|sort -ur); do j=$(echo $f|sed -e "$fpattern") [ "$j" = "" ] && continue @@ -228,8 +228,6 @@ xbps_write_metadata_pkg_real() echo "" >> $TMPFPLIST echo "file" >> $TMPFPLIST echo "$j" >> $TMPFPLIST - echo "type" >> $TMPFPLIST - echo "dir" >> $TMPFPLIST for i in ${keep_dirs}; do if [ "$j" = "$i" ]; then echo "keep" >> $TMPFPLIST @@ -240,6 +238,24 @@ xbps_write_metadata_pkg_real() echo "" >> $TMPFPLIST done echo "" >> $TMPFPLIST + + # Add configuration files into its own array. + if [ -n "${conf_files}" ]; then + echo "conf_files" >> $TMPFPLIST + echo "" >> $TMPFPLIST + for f in ${conf_files}; do + i=${DESTDIR}/${f} + [ ! -f ${i} ] && continue + echo "" >> $TMPFPLIST + echo "file" >> $TMPFPLIST + echo "$f" >> $TMPFPLIST + echo "sha256" >> $TMPFPLIST + echo "$(xbps-digest ${i})" >> $TMPFPLIST + echo "" >> $TMPFPLIST + done + echo "" >> $TMPFPLIST + fi + echo "" >> $TMPFPLIST echo "" >> $TMPFPLIST sed -i -e /^$/d $TMPFLIST