pkgutils/pkgutil.h
just_fun a11b004805 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.
2017-09-19 23:44:01 +02:00

111 lines
3.2 KiB
C++

//
// pkgutils
//
// Copyright (c) 2000-2005 Per Liden
// Copyright (c) 2006-2017 by CRUX team (http://crux.nu)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
#ifndef PKGUTIL_H
#define PKGUTIL_H
#include <string>
#include <set>
#include <map>
#include <iostream>
#include <stdexcept>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <dirent.h>
#define PKG_EXT ".pkg.tar."
#define PKG_DIR "var/lib/pkg"
#define PKG_DB "var/lib/pkg/db"
#define PKG_REJECTED "var/lib/pkg/rejected"
#define VERSION_DELIM '#'
#define LDCONFIG "/sbin/ldconfig"
#define LDCONFIG_CONF "/etc/ld.so.conf"
using namespace std;
class pkgutil {
public:
struct pkginfo_t {
string version;
set<string> files;
};
typedef map<string, pkginfo_t> packages_t;
explicit pkgutil(const string& name);
virtual ~pkgutil() {}
virtual void run(int argc, char** argv) = 0;
virtual void print_help() const = 0;
void print_version() const;
protected:
// Database
void db_open(const string& path);
void db_commit();
void db_add_pkg(const string& name, const pkginfo_t& info);
bool db_find_pkg(const string& name);
void db_rm_pkg(const string& name);
void db_rm_pkg(const string& name, const set<string>& keep_list);
void db_rm_files(set<string> files, const set<string>& keep_list);
set<string> db_find_conflicts(const string& name, const pkginfo_t& info);
// 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, bool upgrade) const;
void pkg_footprint(string& filename) const;
void ldconfig() const;
string utilname;
packages_t packages;
string root;
};
class db_lock {
public:
db_lock(const string& root, bool exclusive);
~db_lock();
private:
DIR* dir;
};
class runtime_error_with_errno : public runtime_error {
public:
explicit runtime_error_with_errno(const string& msg) throw()
: runtime_error(msg + string(": ") + strerror(errno)) {}
explicit runtime_error_with_errno(const string& msg, int e) throw()
: runtime_error(msg + string(": ") + strerror(e)) {}
};
// Utility functions
void assert_argument(char** argv, int argc, int index);
string itos(unsigned int value);
string mtos(mode_t mode);
string trim_filename(const string& filename);
bool file_exists(const string& filename);
bool file_empty(const string& filename);
bool file_equal(const string& file1, const string& file2);
bool permissions_equal(const string& file1, const string& file2);
void file_remove(const string& basedir, const string& filename);
#endif /* PKGUTIL_H */