lib/transaction_files.c: better error and debug messages and minor cleanup
This commit is contained in:
parent
f6bf9b44ce
commit
f2b119ef31
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user