pkgadd: avoid fake installations if unpacking fails

This patch aborts the package installation and remove the package
from the database on any extraction error. This fixes FS#620.

I don't know why the extraction errors were ignored (even documented).
The initial commit already had this behaviour. Another odd thing
is that the install status of the package was commited to the database
before it was installed while there are exceptions used in pkg_install():
 - archive open error
 - empty archive
 - archive read error
Any of these errors will falsely mark the package as installed (maybe
not a big problem with upgrades).

To avoid breaking something (else), this fix kicks in
only with fresh installs (not upgrades).

Thanks Erich Eckner, for pointing out that the issue
is reproductible with a read-only destination. Otherwise,
I don't think I would have looked at this issue.

A test case is presented with the FS issue, just in case someone
who loves C++ enough to dig deeper or have more knowledge about
the history of this program would take a closer look.
This commit is contained in:
just_fun 2017-06-18 14:30:15 +03:00 committed by Fredrik Rinnestam
parent 62e416b52c
commit a11b004805
3 changed files with 15 additions and 4 deletions

View File

@ -103,7 +103,15 @@ void pkgadd::run(int argc, char** argv)
db_add_pkg(package.first, package.second);
db_commit();
pkg_install(o_package, keep_list, non_install_files);
try {
pkg_install(o_package, keep_list, non_install_files, installed);
} catch (runtime_error&) {
if (!installed) {
db_rm_pkg(package.first);
db_commit();
throw runtime_error("failed");
}
}
ldconfig();
}
}

View File

@ -383,7 +383,7 @@ pair<string, pkgutil::pkginfo_t> pkgutil::pkg_open(const string& filename) const
return result;
}
void pkgutil::pkg_install(const string& filename, const set<string>& keep_list, const set<string>& non_install_list) const
void pkgutil::pkg_install(const string& filename, const set<string>& keep_list, const set<string>& non_install_list, bool upgrade) const
{
struct archive* archive;
struct archive_entry* entry;
@ -435,9 +435,12 @@ void pkgutil::pkg_install(const string& filename, const set<string>& keep_list,
if (archive_read_extract(archive, entry, flags) != ARCHIVE_OK) {
// If a file fails to install we just print an error message and
// continue trying to install the rest of the package.
// continue trying to install the rest of the package,
// unless this is not an upgrade.
const char* msg = archive_error_string(archive);
cerr << utilname << ": could not install " + archive_filename << ": " << msg << endl;
if (!upgrade)
throw runtime_error("extract error: " + archive_filename + ": " + msg);
continue;
}

View File

@ -71,7 +71,7 @@ protected:
// Tar.gz
pair<string, pkginfo_t> pkg_open(const string& filename) const;
void pkg_install(const string& filename, const set<string>& keep_list, const set<string>& non_install_files) const;
void pkg_install(const string& filename, const set<string>& keep_list, const set<string>& non_install_files, bool upgrade) const;
void pkg_footprint(string& filename) const;
void ldconfig() const;