lib/transaction_files.c: better error and debug messages and minor cleanup
This commit is contained in:
		
				
					committed by
					
						
						Duncan Overbruck
					
				
			
			
				
	
			
			
			
						parent
						
							f6bf9b44ce
						
					
				
				
					commit
					f2b119ef31
				
			@@ -125,6 +125,18 @@ addItem(const char *file)
 | 
			
		||||
	return item;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *
 | 
			
		||||
typestr(enum type typ)
 | 
			
		||||
{
 | 
			
		||||
	switch (typ) {
 | 
			
		||||
	case TYPE_LINK:     return "symlink";
 | 
			
		||||
	case TYPE_DIR:      return "directory";
 | 
			
		||||
	case TYPE_FILE:     return "file";
 | 
			
		||||
	case TYPE_CONFFILE: return "configuration file";
 | 
			
		||||
	default:            return NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
can_delete_directory(struct xbps_handle *xhp, const char *file, size_t len, size_t max)
 | 
			
		||||
{
 | 
			
		||||
@@ -134,11 +146,11 @@ can_delete_directory(struct xbps_handle *xhp, const char *file, size_t len, size
 | 
			
		||||
 | 
			
		||||
	dp = opendir(file);
 | 
			
		||||
	if (dp == NULL) {
 | 
			
		||||
		xbps_dbg_printf(xhp, "[files] "
 | 
			
		||||
			"%s wtf: %s\n", file, strerror(errno));
 | 
			
		||||
		if (errno == ENOENT) {
 | 
			
		||||
			return true;
 | 
			
		||||
		} else {
 | 
			
		||||
			xbps_dbg_printf(xhp, "[files] %s: %s: %s\n",
 | 
			
		||||
			    __func__, file, strerror(errno));
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -169,9 +181,10 @@ can_delete_directory(struct xbps_handle *xhp, const char *file, size_t len, size
 | 
			
		||||
	/* ignore '.' and '..' */
 | 
			
		||||
	fcount -= 2;
 | 
			
		||||
 | 
			
		||||
	xbps_dbg_printf(xhp, "[files] "
 | 
			
		||||
		"transaction deletes %lu out of %lu files in: %s\n",
 | 
			
		||||
	   rmcount, fcount, file);
 | 
			
		||||
	if (fcount <= rmcount) {
 | 
			
		||||
		xbps_dbg_printf(xhp, "[files] only removed %lu out of %lu files: %s\n",
 | 
			
		||||
		    rmcount, fcount, file);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fcount <= rmcount;
 | 
			
		||||
}
 | 
			
		||||
@@ -236,9 +249,9 @@ collect_obsoletes(struct xbps_handle *xhp)
 | 
			
		||||
			 */
 | 
			
		||||
			if (access(item->file, F_OK) == 0) {
 | 
			
		||||
				xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
 | 
			
		||||
					rv, item->new.pkgver,
 | 
			
		||||
					"%s: [files] file `%s': %s",
 | 
			
		||||
					item->new.pkgver, item->file, strerror(EEXIST));
 | 
			
		||||
				    EEXIST, item->new.pkgver,
 | 
			
		||||
				    "%s: file `%s' already exists.",
 | 
			
		||||
				    item->new.pkgver, item->file);
 | 
			
		||||
				rv = EEXIST;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
@@ -250,13 +263,13 @@ collect_obsoletes(struct xbps_handle *xhp)
 | 
			
		||||
			 * Directory replaced by a file or symlink.
 | 
			
		||||
			 * We MUST be able to delete the directory.
 | 
			
		||||
			 */
 | 
			
		||||
			xbps_dbg_printf(xhp, "[files] "
 | 
			
		||||
				"%s changed from directory to file\n", item->file);
 | 
			
		||||
			xbps_dbg_printf(xhp, "[files] %s: directory changed to %s: %s\n",
 | 
			
		||||
			    item->new.pkgver, typestr(item->new.type), item->file);
 | 
			
		||||
			if (!can_delete_directory(xhp, item->file, item->len, i)) {
 | 
			
		||||
				xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
 | 
			
		||||
					rv, item->old.pkgver,
 | 
			
		||||
					"%s: [files] Directory `%s' can not be deleted",
 | 
			
		||||
					item->old.pkgver, item->file);
 | 
			
		||||
				    ENOTEMPTY, item->old.pkgver,
 | 
			
		||||
				    "%s: directory `%s' can not be deleted.",
 | 
			
		||||
				    item->old.pkgver, item->file);
 | 
			
		||||
				return ENOTEMPTY;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (item->new.type != item->old.type) {
 | 
			
		||||
@@ -273,8 +286,6 @@ collect_obsoletes(struct xbps_handle *xhp)
 | 
			
		||||
		for (uint8_t x = 0; x < __arraycount(basesymlinks); x++) {
 | 
			
		||||
			if (strcmp(item->file+1, basesymlinks[x]) == 0) {
 | 
			
		||||
				found = true;
 | 
			
		||||
				xbps_dbg_printf(xhp, "[obsoletes] ignoring "
 | 
			
		||||
					"%s removal\n", item->file);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -319,8 +330,8 @@ collect_obsoletes(struct xbps_handle *xhp)
 | 
			
		||||
		}
 | 
			
		||||
		assert(pkgname);
 | 
			
		||||
 | 
			
		||||
		xbps_dbg_printf(xhp, "[obsoletes] "
 | 
			
		||||
			"%s\n", item->file);
 | 
			
		||||
		xbps_dbg_printf(xhp, "[obsoletes] %s: removes %s: %s\n",
 | 
			
		||||
		    pkgname, typestr(item->old.type), item->file);
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * Mark file as being deleted, this is used when
 | 
			
		||||
@@ -355,7 +366,6 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size,
 | 
			
		||||
		const char *sha256, enum type type, bool remove)
 | 
			
		||||
{
 | 
			
		||||
	struct item *item;
 | 
			
		||||
	int rv = 0;
 | 
			
		||||
 | 
			
		||||
	assert(file);
 | 
			
		||||
 | 
			
		||||
@@ -382,8 +392,9 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size,
 | 
			
		||||
			 * Multiple packages removing the same file.
 | 
			
		||||
			 * Shouldn't happen, but its not fatal.
 | 
			
		||||
			 */
 | 
			
		||||
			xbps_dbg_printf(xhp, "%s: [files] file `%s' already removed"
 | 
			
		||||
				"by `%s'\n", pkgname, file, item->old.pkgname);
 | 
			
		||||
			xbps_dbg_printf(xhp, "[files] %s: file already removed"
 | 
			
		||||
			    " by package `%s': %s\n", pkgver, item->old.pkgver, file);
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		goto add;
 | 
			
		||||
@@ -406,9 +417,9 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size,
 | 
			
		||||
			 * This should never happen in a transaction.
 | 
			
		||||
			 */
 | 
			
		||||
			xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
 | 
			
		||||
				rv, pkgver,
 | 
			
		||||
				"%s: [files] file already installed by package `%s': %s",
 | 
			
		||||
				pkgver, item->new.pkgname, pkgname, file);
 | 
			
		||||
			    EEXIST, pkgver,
 | 
			
		||||
			    "%s: file `%s' already installed by package %s.",
 | 
			
		||||
			    pkgver, file, item->new.pkgver);
 | 
			
		||||
			return EEXIST;
 | 
			
		||||
		}
 | 
			
		||||
		goto add;
 | 
			
		||||
@@ -438,11 +449,13 @@ add:
 | 
			
		||||
		 */
 | 
			
		||||
		if (strcmp(item->new.pkgname, item->old.pkgname) != 0) {
 | 
			
		||||
			if (remove) {
 | 
			
		||||
				xbps_dbg_printf(xhp, "%s: [files] file `%s' moved to"
 | 
			
		||||
				    " package `%s'\n", pkgname, file, item->new.pkgname);
 | 
			
		||||
				xbps_dbg_printf(xhp, "[files] %s: %s moved to"
 | 
			
		||||
				    " package `%s': %s\n", pkgver, typestr(item->old.type),
 | 
			
		||||
				    item->new.pkgver, file);
 | 
			
		||||
			} else {
 | 
			
		||||
				xbps_dbg_printf(xhp, "%s: [files] file `%s' moved from"
 | 
			
		||||
				    " package `%s'\n", pkgname, file, item->new.pkgname);
 | 
			
		||||
				xbps_dbg_printf(xhp, "[files] %s: %s moved from"
 | 
			
		||||
				    " package `%s': %s\n", pkgver, typestr(item->new.type),
 | 
			
		||||
				    item->old.pkgver, file);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -521,7 +534,7 @@ out:
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
 | 
			
		||||
collect_binpkg_files(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
 | 
			
		||||
		unsigned int idx)
 | 
			
		||||
{
 | 
			
		||||
	xbps_dictionary_t filesd;
 | 
			
		||||
@@ -565,7 +578,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
 | 
			
		||||
		rv = errno;
 | 
			
		||||
		xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
 | 
			
		||||
		    rv, pkgver,
 | 
			
		||||
		    "%s: [files] failed to open binary package `%s': %s",
 | 
			
		||||
		    "%s: failed to open binary package `%s': %s",
 | 
			
		||||
		    pkgver, bpkg, strerror(rv));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -573,7 +586,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
 | 
			
		||||
		rv = errno;
 | 
			
		||||
		xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
 | 
			
		||||
		    rv, pkgver,
 | 
			
		||||
		    "%s: [files] failed to fstat binary package `%s': %s",
 | 
			
		||||
		    "%s: failed to fstat binary package `%s': %s",
 | 
			
		||||
		    pkgver, bpkg, strerror(rv));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -581,7 +594,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
 | 
			
		||||
		rv = archive_errno(ar);
 | 
			
		||||
		xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
 | 
			
		||||
		    rv, pkgver,
 | 
			
		||||
		    "%s: [files] failed to read binary package `%s': %s",
 | 
			
		||||
		    "%s: failed to read binary package `%s': %s",
 | 
			
		||||
		    pkgver, bpkg, strerror(rv));
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
@@ -602,7 +615,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
 | 
			
		||||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
			rv = collect_files(xhp, filesd, pkgname, pkgver, idx, false);
 | 
			
		||||
			break;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		archive_read_data_skip(ar);
 | 
			
		||||
	}
 | 
			
		||||
@@ -617,30 +630,6 @@ out:
 | 
			
		||||
	return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
bool HIDDEN
 | 
			
		||||
xbps_transaction_is_file_obsolete(struct xbps_handle *xhp, const char *file)
 | 
			
		||||
{
 | 
			
		||||
	struct item *item;
 | 
			
		||||
	/*
 | 
			
		||||
	 * If there is no transaction then consider the files obsolete.
 | 
			
		||||
	 * This only happens if `xbps_find_pkg_obsoletes` or this function
 | 
			
		||||
	 * is called without a transaction, e.g. in tests.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!xhp->transd)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	item = lookupItem(file);
 | 
			
		||||
	assert(item);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The `file` is obsolete, if a package removed the `file`
 | 
			
		||||
	 * and no other package created `file`.
 | 
			
		||||
	 */
 | 
			
		||||
	return item->new.type == 0 && item->old.type != 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
pathcmp(const void *l1, const void *l2)
 | 
			
		||||
{
 | 
			
		||||
@@ -655,6 +644,7 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter)
 | 
			
		||||
	xbps_dictionary_t pkgd, filesd;
 | 
			
		||||
	xbps_object_t obj;
 | 
			
		||||
	const char *trans, *pkgver;
 | 
			
		||||
	char *pkgname = NULL;
 | 
			
		||||
	int rv = 0;
 | 
			
		||||
	unsigned int idx = 0;
 | 
			
		||||
 | 
			
		||||
@@ -663,7 +653,6 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter)
 | 
			
		||||
		return EINVAL;
 | 
			
		||||
 | 
			
		||||
	while ((obj = xbps_object_iterator_next(iter)) != NULL) {
 | 
			
		||||
		char *pkgname;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * `idx` is used as package install index, to chose which
 | 
			
		||||
@@ -685,16 +674,14 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter)
 | 
			
		||||
		pkgname = xbps_pkg_name(pkgver);
 | 
			
		||||
		assert(pkgname);
 | 
			
		||||
 | 
			
		||||
		xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, pkgver,
 | 
			
		||||
			"%s: collecting files...", pkgname);
 | 
			
		||||
 | 
			
		||||
		if ((strcmp(trans, "install") == 0) ||
 | 
			
		||||
		    (strcmp(trans, "update") == 0)) {
 | 
			
		||||
			rv = add_from_archive(xhp, obj, idx);
 | 
			
		||||
			if (rv != 0) {
 | 
			
		||||
				free(pkgname);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, pkgver,
 | 
			
		||||
			    "%s: collecting files...", pkgver);
 | 
			
		||||
			rv = collect_binpkg_files(xhp, obj, idx);
 | 
			
		||||
			if (rv != 0)
 | 
			
		||||
				goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
@@ -709,40 +696,45 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter)
 | 
			
		||||
		if (pkgd) {
 | 
			
		||||
			const char *oldpkgver;
 | 
			
		||||
			bool preserve = false;
 | 
			
		||||
 | 
			
		||||
			xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &oldpkgver);
 | 
			
		||||
			xbps_dictionary_get_bool(obj, "preserve", &preserve);
 | 
			
		||||
			/*
 | 
			
		||||
			 * Skip files from packages with `preserve`.
 | 
			
		||||
			 */
 | 
			
		||||
			if (preserve) {
 | 
			
		||||
				free(pkgname);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (!xbps_dictionary_get_bool(obj, "preserve", &preserve))
 | 
			
		||||
				preserve = false;
 | 
			
		||||
 | 
			
		||||
			filesd = xbps_pkgdb_get_pkg_files(xhp, pkgname);
 | 
			
		||||
			if (filesd == NULL) {
 | 
			
		||||
				free(pkgname);
 | 
			
		||||
				pkgname = NULL;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			assert(oldpkgver);
 | 
			
		||||
			rv = collect_files(xhp, filesd, pkgname, pkgver, idx, true);
 | 
			
		||||
			if (rv != 0) {
 | 
			
		||||
				free(pkgname);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, oldpkgver,
 | 
			
		||||
			    "%s: collecting files...", oldpkgver);
 | 
			
		||||
			rv = collect_files(xhp, filesd, pkgname, pkgver, idx, preserve, true);
 | 
			
		||||
			if (rv != 0)
 | 
			
		||||
				goto out;
 | 
			
		||||
		}
 | 
			
		||||
		free(pkgname);
 | 
			
		||||
		pkgname = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	xbps_object_iterator_reset(iter);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Sort items by path length, to make it easier to find files in
 | 
			
		||||
	 * directories.
 | 
			
		||||
	 */
 | 
			
		||||
	qsort(items, itemsidx, sizeof (struct item *), pathcmp);
 | 
			
		||||
 | 
			
		||||
	if (chdir(xhp->rootdir) == -1) {
 | 
			
		||||
		rv = errno;
 | 
			
		||||
		xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, rv, xhp->rootdir,
 | 
			
		||||
		    "[files] failed to chdir to rootdir `%s': %s",
 | 
			
		||||
		    "failed to chdir to rootdir `%s': %s",
 | 
			
		||||
		    xhp->rootdir, strerror(errno));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	free(pkgname);
 | 
			
		||||
	if (rv != 0)
 | 
			
		||||
		return rv;
 | 
			
		||||
	return collect_obsoletes(xhp);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user