lib/transaction_files.c: better error and debug messages and minor cleanup

This commit is contained in:
Duncaen 2019-06-18 13:00:06 +02:00 committed by Duncan Overbruck
parent f6bf9b44ce
commit f2b119ef31

View File

@ -125,6 +125,18 @@ addItem(const char *file)
return item; 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 static bool
can_delete_directory(struct xbps_handle *xhp, const char *file, size_t len, size_t max) 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); dp = opendir(file);
if (dp == NULL) { if (dp == NULL) {
xbps_dbg_printf(xhp, "[files] "
"%s wtf: %s\n", file, strerror(errno));
if (errno == ENOENT) { if (errno == ENOENT) {
return true; return true;
} else { } else {
xbps_dbg_printf(xhp, "[files] %s: %s: %s\n",
__func__, file, strerror(errno));
return false; return false;
} }
} }
@ -169,9 +181,10 @@ can_delete_directory(struct xbps_handle *xhp, const char *file, size_t len, size
/* ignore '.' and '..' */ /* ignore '.' and '..' */
fcount -= 2; fcount -= 2;
xbps_dbg_printf(xhp, "[files] " if (fcount <= rmcount) {
"transaction deletes %lu out of %lu files in: %s\n", xbps_dbg_printf(xhp, "[files] only removed %lu out of %lu files: %s\n",
rmcount, fcount, file); rmcount, fcount, file);
}
return fcount <= rmcount; return fcount <= rmcount;
} }
@ -236,9 +249,9 @@ collect_obsoletes(struct xbps_handle *xhp)
*/ */
if (access(item->file, F_OK) == 0) { if (access(item->file, F_OK) == 0) {
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
rv, item->new.pkgver, EEXIST, item->new.pkgver,
"%s: [files] file `%s': %s", "%s: file `%s' already exists.",
item->new.pkgver, item->file, strerror(EEXIST)); item->new.pkgver, item->file);
rv = EEXIST; rv = EEXIST;
break; break;
} }
@ -250,13 +263,13 @@ collect_obsoletes(struct xbps_handle *xhp)
* Directory replaced by a file or symlink. * Directory replaced by a file or symlink.
* We MUST be able to delete the directory. * We MUST be able to delete the directory.
*/ */
xbps_dbg_printf(xhp, "[files] " xbps_dbg_printf(xhp, "[files] %s: directory changed to %s: %s\n",
"%s changed from directory to file\n", item->file); item->new.pkgver, typestr(item->new.type), item->file);
if (!can_delete_directory(xhp, item->file, item->len, i)) { if (!can_delete_directory(xhp, item->file, item->len, i)) {
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
rv, item->old.pkgver, ENOTEMPTY, item->old.pkgver,
"%s: [files] Directory `%s' can not be deleted", "%s: directory `%s' can not be deleted.",
item->old.pkgver, item->file); item->old.pkgver, item->file);
return ENOTEMPTY; return ENOTEMPTY;
} }
} else if (item->new.type != item->old.type) { } 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++) { for (uint8_t x = 0; x < __arraycount(basesymlinks); x++) {
if (strcmp(item->file+1, basesymlinks[x]) == 0) { if (strcmp(item->file+1, basesymlinks[x]) == 0) {
found = true; found = true;
xbps_dbg_printf(xhp, "[obsoletes] ignoring "
"%s removal\n", item->file);
break; break;
} }
} }
@ -319,8 +330,8 @@ collect_obsoletes(struct xbps_handle *xhp)
} }
assert(pkgname); assert(pkgname);
xbps_dbg_printf(xhp, "[obsoletes] " xbps_dbg_printf(xhp, "[obsoletes] %s: removes %s: %s\n",
"%s\n", item->file); pkgname, typestr(item->old.type), item->file);
/* /*
* Mark file as being deleted, this is used when * 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) const char *sha256, enum type type, bool remove)
{ {
struct item *item; struct item *item;
int rv = 0;
assert(file); assert(file);
@ -382,8 +392,9 @@ collect_file(struct xbps_handle *xhp, const char *file, size_t size,
* Multiple packages removing the same file. * Multiple packages removing the same file.
* Shouldn't happen, but its not fatal. * Shouldn't happen, but its not fatal.
*/ */
xbps_dbg_printf(xhp, "%s: [files] file `%s' already removed" xbps_dbg_printf(xhp, "[files] %s: file already removed"
"by `%s'\n", pkgname, file, item->old.pkgname); " by package `%s': %s\n", pkgver, item->old.pkgver, file);
return 0; return 0;
} }
goto add; 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. * This should never happen in a transaction.
*/ */
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
rv, pkgver, EEXIST, pkgver,
"%s: [files] file already installed by package `%s': %s", "%s: file `%s' already installed by package %s.",
pkgver, item->new.pkgname, pkgname, file); pkgver, file, item->new.pkgver);
return EEXIST; return EEXIST;
} }
goto add; goto add;
@ -438,11 +449,13 @@ add:
*/ */
if (strcmp(item->new.pkgname, item->old.pkgname) != 0) { if (strcmp(item->new.pkgname, item->old.pkgname) != 0) {
if (remove) { if (remove) {
xbps_dbg_printf(xhp, "%s: [files] file `%s' moved to" xbps_dbg_printf(xhp, "[files] %s: %s moved to"
" package `%s'\n", pkgname, file, item->new.pkgname); " package `%s': %s\n", pkgver, typestr(item->old.type),
item->new.pkgver, file);
} else { } else {
xbps_dbg_printf(xhp, "%s: [files] file `%s' moved from" xbps_dbg_printf(xhp, "[files] %s: %s moved from"
" package `%s'\n", pkgname, file, item->new.pkgname); " package `%s': %s\n", pkgver, typestr(item->new.type),
item->old.pkgver, file);
} }
} }
} }
@ -521,7 +534,7 @@ out:
} }
static int 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) unsigned int idx)
{ {
xbps_dictionary_t filesd; xbps_dictionary_t filesd;
@ -565,7 +578,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
rv = errno; rv = errno;
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
rv, pkgver, rv, pkgver,
"%s: [files] failed to open binary package `%s': %s", "%s: failed to open binary package `%s': %s",
pkgver, bpkg, strerror(rv)); pkgver, bpkg, strerror(rv));
goto out; goto out;
} }
@ -573,7 +586,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
rv = errno; rv = errno;
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
rv, pkgver, rv, pkgver,
"%s: [files] failed to fstat binary package `%s': %s", "%s: failed to fstat binary package `%s': %s",
pkgver, bpkg, strerror(rv)); pkgver, bpkg, strerror(rv));
goto out; goto out;
} }
@ -581,7 +594,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
rv = archive_errno(ar); rv = archive_errno(ar);
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL,
rv, pkgver, rv, pkgver,
"%s: [files] failed to read binary package `%s': %s", "%s: failed to read binary package `%s': %s",
pkgver, bpkg, strerror(rv)); pkgver, bpkg, strerror(rv));
goto out; goto out;
} }
@ -602,7 +615,7 @@ add_from_archive(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod,
goto out; goto out;
} }
rv = collect_files(xhp, filesd, pkgname, pkgver, idx, false); rv = collect_files(xhp, filesd, pkgname, pkgver, idx, false);
break; goto out;
} }
archive_read_data_skip(ar); archive_read_data_skip(ar);
} }
@ -617,30 +630,6 @@ out:
return rv; 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 static int
pathcmp(const void *l1, const void *l2) 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_dictionary_t pkgd, filesd;
xbps_object_t obj; xbps_object_t obj;
const char *trans, *pkgver; const char *trans, *pkgver;
char *pkgname = NULL;
int rv = 0; int rv = 0;
unsigned int idx = 0; unsigned int idx = 0;
@ -663,7 +653,6 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter)
return EINVAL; return EINVAL;
while ((obj = xbps_object_iterator_next(iter)) != NULL) { while ((obj = xbps_object_iterator_next(iter)) != NULL) {
char *pkgname;
/* /*
* `idx` is used as package install index, to chose which * `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); pkgname = xbps_pkg_name(pkgver);
assert(pkgname); assert(pkgname);
xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, pkgver,
"%s: collecting files...", pkgname);
if ((strcmp(trans, "install") == 0) || if ((strcmp(trans, "install") == 0) ||
(strcmp(trans, "update") == 0)) { (strcmp(trans, "update") == 0)) {
rv = add_from_archive(xhp, obj, idx); xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, pkgver,
if (rv != 0) { "%s: collecting files...", pkgver);
free(pkgname); rv = collect_binpkg_files(xhp, obj, idx);
break; if (rv != 0)
} goto out;
} }
/* /*
@ -709,40 +696,45 @@ xbps_transaction_files(struct xbps_handle *xhp, xbps_object_iterator_t iter)
if (pkgd) { if (pkgd) {
const char *oldpkgver; const char *oldpkgver;
bool preserve = false; bool preserve = false;
xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &oldpkgver); xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &oldpkgver);
xbps_dictionary_get_bool(obj, "preserve", &preserve); if (!xbps_dictionary_get_bool(obj, "preserve", &preserve))
/* preserve = false;
* Skip files from packages with `preserve`.
*/
if (preserve) {
free(pkgname);
continue;
}
filesd = xbps_pkgdb_get_pkg_files(xhp, pkgname); filesd = xbps_pkgdb_get_pkg_files(xhp, pkgname);
if (filesd == NULL) { if (filesd == NULL) {
free(pkgname); free(pkgname);
pkgname = NULL;
continue; continue;
} }
assert(oldpkgver); assert(oldpkgver);
rv = collect_files(xhp, filesd, pkgname, pkgver, idx, true); xbps_set_cb_state(xhp, XBPS_STATE_FILES, 0, oldpkgver,
if (rv != 0) { "%s: collecting files...", oldpkgver);
free(pkgname); rv = collect_files(xhp, filesd, pkgname, pkgver, idx, preserve, true);
break; if (rv != 0)
} goto out;
} }
free(pkgname); free(pkgname);
pkgname = NULL;
} }
xbps_object_iterator_reset(iter); 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); qsort(items, itemsidx, sizeof (struct item *), pathcmp);
if (chdir(xhp->rootdir) == -1) { if (chdir(xhp->rootdir) == -1) {
rv = errno; rv = errno;
xbps_set_cb_state(xhp, XBPS_STATE_FILES_FAIL, rv, xhp->rootdir, 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)); xhp->rootdir, strerror(errno));
} }
out:
free(pkgname);
if (rv != 0) if (rv != 0)
return rv; return rv;
return collect_obsoletes(xhp); return collect_obsoletes(xhp);