aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Danny van Dyk <dvandyk@exherbo.org> 2006-06-11 18:48:11 +0000
committerAvatar Danny van Dyk <dvandyk@exherbo.org> 2006-06-11 18:48:11 +0000
commit7b983109aec7356ec090eb5e53f78fd17401be38 (patch)
tree80c621d94edbb02546a2513fa34420e75fd13e7b
parent6169ea393b161e69f184e19dd8aeed54b10cf1c0 (diff)
downloadpaludis-7b983109aec7356ec090eb5e53f78fd17401be38.tar.gz
paludis-7b983109aec7356ec090eb5e53f78fd17401be38.tar.xz
Add support for PackageSetOptions. Revise security algorithm. Add support for --list-vulnerabilities commandline option.
-rw-r--r--paludis/config_file.cc31
-rw-r--r--paludis/config_file.hh65
-rw-r--r--paludis/default_environment.cc3
-rw-r--r--paludis/default_environment.hh3
-rw-r--r--paludis/environment.cc4
-rw-r--r--paludis/environment.hh6
-rw-r--r--paludis/portage_repository.cc240
-rw-r--r--paludis/portage_repository.hh66
-rw-r--r--paludis/repository.hh39
-rw-r--r--paludis/vdb_repository.cc2
-rw-r--r--paludis/vdb_repository.hh2
-rw-r--r--paludis/version_operator.hh8
-rw-r--r--src/command_line.cc1
-rw-r--r--src/command_line.hh3
-rw-r--r--src/list.cc147
-rw-r--r--src/list.hh3
-rw-r--r--src/paludis.cc9
17 files changed, 447 insertions, 185 deletions
diff --git a/paludis/config_file.cc b/paludis/config_file.cc
index 4548347..a2257e8 100644
--- a/paludis/config_file.cc
+++ b/paludis/config_file.cc
@@ -311,30 +311,6 @@ KeyValueConfigFile::strip_quotes(const std::string & s) const
return s;
}
-AdvisoryLine::AdvisoryLine(const std::string & s) :
- _line(s),
- _is_range(false)
-{
- WhitespaceTokeniser::get_instance()->tokenise(s, std::back_inserter(_tokens));
-
- if ((_tokens.size() < 1) || (_tokens.size() > 2))
- throw AdvisoryFileError("Wrong count of atoms on line.");
-
- if (_tokens.size() == 2)
- {
- if (!(is_range_token(0) && is_range_token(1)))
- throw AdvisoryFileError("Line must exactly contain 1 non-range atom or 2 range atoms.");
-
- if (is_range_bigger(0) && is_range_bigger(1))
- throw AdvisoryFileError("Broken range: Two bigger/bigger than atoms.");
-
- if (is_range_smaller(0) && is_range_smaller(1))
- throw AdvisoryFileError("Broken range: Two smaller/smaller than atoms.");
-
- _is_range = true;
- }
-}
-
AdvisoryFileError::AdvisoryFileError(const std::string & msg,
const std::string & filename) throw () :
ConfigurationError("Advisory file error" +
@@ -419,9 +395,9 @@ AdvisoryFile::accept_line(const std::string & line) const
|| (key == "Reviewed-By"))
{
if (key == "Affected")
- _affected.push_back(AdvisoryLine(value));
+ _affected.push_back(value);
else if (key == "Unaffected")
- _unaffected.push_back(AdvisoryLine(value));
+ _unaffected.push_back(value);
if (!_entries[key].empty())
value = "\n" + value;
@@ -451,9 +427,6 @@ AdvisoryFile::sanitise()
if (_entries["Reviewed-By"].empty())
throw AdvisoryFileError("Missing mandatory key: 'Reviewed-by'.");
-
- if ((_entries["Affected"].size() + _entries["Unaffected"].size()) == 0)
- throw AdvisoryFileError("Missing either 'Affected' or 'Unaffected' key.");
}
NewsFile::NewsFile(const FSEntry & filename) :
diff --git a/paludis/config_file.hh b/paludis/config_file.hh
index 75417a7..7e34f2c 100644
--- a/paludis/config_file.hh
+++ b/paludis/config_file.hh
@@ -308,56 +308,6 @@ namespace paludis
};
/**
- * An AdvisoryLine represents one of the Affected: or Unaffected: lines in an AdvisoryFile.
- *
- * \ingroup grpadvisoryconfigfile
- */
- class AdvisoryLine
- {
- private:
- enum RangeChars {
- rc_is_bigger = '>',
- rc_is_smaller = '<'
- };
- std::string _line;
- std::vector<std::string> _tokens;
- bool _is_range;
-
- protected:
- bool is_range_bigger(int i) const
- {
- return _tokens[i][0] == rc_is_bigger;
- }
-
- bool is_range_smaller(int i) const
- {
- return _tokens[i][0] == rc_is_smaller;
- }
-
- bool is_range_token(int i) const
- {
- return is_range_smaller(i) || is_range_bigger(i);
- }
-
- public:
- AdvisoryLine(const std::string & s);
- const std::string operator[] (int i) const
- {
- return _tokens[i];
- }
-
- const std::string & line() const
- {
- return _line;
- }
-
- bool is_range() const
- {
- return _is_range;
- }
- };
-
- /**
* An AdvisoryFile is a file containing all necessary information to
* update one or more packages in order to avoid a security problem.
*
@@ -374,8 +324,8 @@ namespace paludis
{
private:
mutable std::map<std::string, std::string> _entries;
- mutable std::list<AdvisoryLine> _affected;
- mutable std::list<AdvisoryLine> _unaffected;
+ mutable std::list<std::string> _affected;
+ mutable std::list<std::string> _unaffected;
mutable bool _end_of_header;
protected:
@@ -428,7 +378,7 @@ namespace paludis
* Iterator over our lines.
*/
typedef std::map<std::string, std::string>::const_iterator EntriesIterator;
- typedef std::list<AdvisoryLine>::const_iterator LineIterator;
+ typedef std::list<std::string>::const_iterator LineIterator;
/**
* Iterator to the start of our lines.
@@ -486,15 +436,6 @@ namespace paludis
return _entries[key];
}
- std::list<AdvisoryLine> & affected() const
- {
- return _affected;
- }
-
- std::list<AdvisoryLine> & unaffected() const
- {
- return _unaffected;
- }
};
/**
diff --git a/paludis/default_environment.cc b/paludis/default_environment.cc
index 699df23..baae411 100644
--- a/paludis/default_environment.cc
+++ b/paludis/default_environment.cc
@@ -442,7 +442,8 @@ DefaultEnvironment::hook_dirs() const
}
DepAtom::Pointer
-DefaultEnvironment::local_package_set(const std::string & s) const
+DefaultEnvironment::local_package_set(const std::string & s,
+ const PackageSetOptions &) const
{
Context context("When looking for package set '" + s + "' in default environment:");
diff --git a/paludis/default_environment.hh b/paludis/default_environment.hh
index 59bdcd8..5c4ca00 100644
--- a/paludis/default_environment.hh
+++ b/paludis/default_environment.hh
@@ -49,7 +49,8 @@ namespace paludis
~DefaultEnvironment();
protected:
- DepAtom::Pointer local_package_set(const std::string &) const;
+ DepAtom::Pointer local_package_set(const std::string &,
+ const PackageSetOptions & = PackageSetOptions(false)) const;
public:
virtual bool query_use(const UseFlagName &, const PackageDatabaseEntry *) const;
diff --git a/paludis/environment.cc b/paludis/environment.cc
index d024430..80115f8 100644
--- a/paludis/environment.cc
+++ b/paludis/environment.cc
@@ -242,7 +242,7 @@ Environment::end_provide_map() const
}
DepAtom::Pointer
-Environment::package_set(const std::string & s) const
+Environment::package_set(const std::string & s, const PackageSetOptions & o) const
{
if (s == "everything" || s == "system" || s == "world" || s == "security")
{
@@ -255,7 +255,7 @@ Environment::package_set(const std::string & s) const
if (! (*r)->get_interface<repo_sets>())
continue;
- DepAtom::Pointer add((*r)->get_interface<repo_sets>()->package_set(s));
+ DepAtom::Pointer add((*r)->get_interface<repo_sets>()->package_set(s, o));
if (0 != add)
result->add_child(add);
diff --git a/paludis/environment.hh b/paludis/environment.hh
index 0d06040..189c09d 100644
--- a/paludis/environment.hh
+++ b/paludis/environment.hh
@@ -95,7 +95,8 @@ namespace paludis
/**
* Local package set, or zero.
*/
- virtual DepAtom::Pointer local_package_set(const std::string &) const
+ virtual DepAtom::Pointer local_package_set(const std::string &,
+ const PackageSetOptions & = PackageSetOptions(false)) const
{
return DepAtom::Pointer(0);
}
@@ -200,7 +201,8 @@ namespace paludis
/**
* Fetch a named package set.
*/
- DepAtom::Pointer package_set(const std::string &) const;
+ DepAtom::Pointer package_set(const std::string &,
+ const PackageSetOptions & = PackageSetOptions(false)) const;
/**
* Add packages to world, if they are not there already, and if they are
diff --git a/paludis/portage_repository.cc b/paludis/portage_repository.cc
index 5b3b79a..5d6f5e4 100644
--- a/paludis/portage_repository.cc
+++ b/paludis/portage_repository.cc
@@ -24,6 +24,7 @@
#include <paludis/dep_atom.hh>
#include <paludis/dep_atom_flattener.hh>
#include <paludis/ebuild.hh>
+#include <paludis/environment.hh>
#include <paludis/hashed_containers.hh>
#include <paludis/match_package.hh>
#include <paludis/package_database.hh>
@@ -1592,25 +1593,10 @@ namespace
std::string s("=" + stringify(n) + "-" + stringify(v));
return PackageDepAtom::Pointer(new PackageDepAtom(s));
}
-
- struct IsNotMemberOfCollection
- {
- PackageDatabaseEntryCollection::ConstPointer _c;
- IsNotMemberOfCollection(const PackageDatabaseEntryCollection::ConstPointer & c) :
- _c(c)
- {
- }
-
- bool operator() (const PackageDatabaseEntry & e) const
- {
- bool result = (_c->find(e) == _c->end());
- return result;
- }
- };
}
PackageDatabaseEntryCollection::Iterator
-PortageRepository::find_best(PackageDatabaseEntryCollection::Pointer & c, const PackageDatabaseEntry & e) const
+PortageRepository::find_best(PackageDatabaseEntryCollection & c, const PackageDatabaseEntry & e) const
{
Context local("When finding best update for '" + stringify(e.get<pde_name>()) + "-" +
stringify(e.get<pde_version>()) + "':");
@@ -1618,7 +1604,7 @@ PortageRepository::find_best(PackageDatabaseEntryCollection::Pointer & c, const
QualifiedPackageName n(e.get<pde_name>());
SlotName s(_imp->env->package_database()->fetch_repository(e.get<pde_repository>())->version_metadata(
e.get<pde_name>(), e.get<pde_version>())->get<vm_slot>());
- PackageDatabaseEntryCollection::Iterator i(c->begin()), i_end(c->end()), i_best(c->end());
+ PackageDatabaseEntryCollection::Iterator i(c.begin()), i_end(c.end()), i_best(c.end());
for ( ; i != i_end; ++i)
{
if (n != i->get<pde_name>())
@@ -1633,12 +1619,66 @@ PortageRepository::find_best(PackageDatabaseEntryCollection::Pointer & c, const
return i_best;
}
+AdvisoryVisitor::AdvisoryVisitor(const Environment * const env, const CompositeDepAtom & a) :
+ _env(env),
+ _a(a)
+{
+ Context c("When flattening the AdvisoryFile line:");
+ std::for_each(a.begin(), a.end(), accept_visitor(this));
+ if (_atoms.size() == 2)
+ {
+ VersionOperatorValue v1(_atoms[0]->version_operator().value()),
+ v2(_atoms[1]->version_operator().value());
+
+ if ((v1 == vo_equal) || (v2 == vo_equal))
+ throw AdvisoryFileError("Broken line: Forbidden 'equal' atom in range");
+ }
+}
+
+void
+AdvisoryVisitor::visit(const AllDepAtom * a)
+{
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+}
+
+void
+AdvisoryVisitor::visit(const AnyDepAtom *)
+{
+ throw AdvisoryFileError("Unexpected AnyDepAtom in line");
+}
+
+void
+AdvisoryVisitor::visit(const UseDepAtom * a)
+{
+ if (_env->query_use(a->flag(), 0) ^ a->inverse())
+ std::for_each(a->begin(), a->end(), accept_visitor(this));
+}
+
+void
+AdvisoryVisitor::visit(const PackageDepAtom * a)
+{
+ _atoms.push_back(a);
+}
+
+void
+AdvisoryVisitor::visit(const PlainTextDepAtom *)
+{
+}
+
+void
+AdvisoryVisitor::visit(const BlockDepAtom *)
+{
+}
+
DepAtom::Pointer
-PortageRepository::do_security_set() const
+PortageRepository::do_security_set(const PackageSetOptions & o) const
{
Context c("When building security package set:");
AllDepAtom::Pointer security_packages(new AllDepAtom);
+ bool list_affected_only(o.get<pso_list_affected_only>());
+ InstallState affected_state(list_affected_only ? is_either : is_installed_only);
+
if (!_imp->securitydir.is_directory())
return DepAtom::Pointer(new AllDepAtom);
@@ -1650,87 +1690,127 @@ PortageRepository::do_security_set() const
std::list<FSEntry>::const_iterator f(advisories.begin()),
f_end(advisories.end());
+ std::set<std::pair<PackageDatabaseEntry, std::string> > affected;
+ PackageDatabaseEntryCollection unaffected;
+ std::map<std::string, std::string> advisory_map;
+
for ( ; f != f_end; ++f)
{
Context c("When parsing security advisory '" + stringify(*f) + "':");
- AdvisoryFile advisory(*f);
-
- GLSADepTag::Pointer advisory_tag(new GLSADepTag(advisory.get("Id"),
- advisory.get("Title")));
- PackageDatabaseEntryCollection::Pointer affected(new PackageDatabaseEntryCollection),
- unaffected(new PackageDatabaseEntryCollection);
- std::list<AdvisoryLine>::const_iterator u(advisory.begin_unaffected()), u_end(advisory.end_unaffected());
- for ( ; u != u_end ; ++u)
+ try
{
- Context c("When parsing 'Unaffected:' line '" + u->line() + "':");
- if (u->is_range())
- {
- PackageDepAtom::Pointer p(new PackageDepAtom((*u)[0]));
- PackageDatabaseEntryCollection::ConstPointer c_one = _imp->db->query(p, is_either);
- p.assign(new PackageDepAtom((*u)[1]));
- PackageDatabaseEntryCollection::ConstPointer c_two = _imp->db->query(p, is_either);
- std::set_intersection(c_one->begin(), c_one->end(), c_two->begin(), c_two->end(),
- filter_inserter(unaffected->inserter(), IsNotMemberOfCollection(unaffected)));
- }
- else
- {
- PackageDepAtom::Pointer p(new PackageDepAtom((*u)[0]));
- PackageDatabaseEntryCollection::ConstPointer c = _imp->db->query(p, is_either);
- std::copy(c->begin(), c->end(), filter_inserter(unaffected->inserter(), IsNotMemberOfCollection(unaffected)));
- }
- }
+ AdvisoryFile advisory(*f);
+ std::string advisory_id(advisory.get("Id"));
+ advisory_map[advisory_id] = advisory.get("Title");
- std::list<AdvisoryLine>::const_iterator a(advisory.begin_affected()), a_end(advisory.end_affected());
- for ( ; a != a_end ; ++a)
- {
- Context c("When parsing 'Affected:' line '" + a->line() + "':");
- if (a->is_range())
+
+ AdvisoryFile::LineIterator a(advisory.begin_affected()), a_end(advisory.end_affected());
+ for ( ; a != a_end ; ++a)
{
- PackageDepAtom::Pointer p(new PackageDepAtom((*a)[0]));
- PackageDatabaseEntryCollection::ConstPointer installed_one = _imp->db->query(p, is_installed_only);
- PackageDatabaseEntryCollection::ConstPointer either_one = _imp->db->query(p, is_either);
- p.assign(new PackageDepAtom((*a)[1]));
- PackageDatabaseEntryCollection::ConstPointer installed_two = _imp->db->query(p, is_installed_only);
- PackageDatabaseEntryCollection::ConstPointer either_two = _imp->db->query(p, is_either);
- std::set_intersection(installed_one->begin(), installed_one->end(), installed_two->begin(), installed_two->end(),
- filter_inserter(affected->inserter(), IsNotMemberOfCollection(affected)));
- PackageDatabaseEntryCollection::Iterator e(either_one->begin()), e_end(either_one->end());
- for ( ; e != e_end; ++e)
+ Context c("When parsing line 'Affected: " + *a + "':");
+
+ CompositeDepAtom::ConstPointer line(PortageDepParser::parse(*a));
+ AdvisoryVisitor atoms(_imp->env, *line);
+
+ if ((0 == atoms.size()) || (2 < atoms.size()))
{
- IsNotMemberOfCollection f(either_two);
- if (f(*e))
- continue;
+ continue;
+ }
+
+ bool is_range(2 == atoms.size());
- if (unaffected->find(*e) != unaffected->end())
- unaffected->erase(*e);
+ PackageDatabaseEntryCollection::ConstPointer affected_collection1(_imp->db->query(*atoms.at(0), affected_state));
+ PackageDatabaseEntryCollection::ConstPointer affected_collection2(new PackageDatabaseEntryCollection);
+ PackageDatabaseEntryCollection::Iterator p(affected_collection1->begin()), p_end(affected_collection1->end());
+
+ if (is_range)
+ affected_collection2 = _imp->db->query(*atoms.at(1), affected_state);
+
+ for ( ; p != p_end ; ++p)
+ {
+ if ((affected.end() != affected.find(std::make_pair(*p, advisory_id))))
+ continue;
+ if ((! is_range) || (affected_collection2->end() != affected_collection2->find(*p)))
+ affected.insert(std::make_pair(*p, advisory_id));
}
}
- else
+
+ AdvisoryFile::LineIterator u(advisory.begin_unaffected()), u_end(advisory.end_unaffected());
+ for ( ; u != u_end ; ++u)
{
- PackageDepAtom::Pointer p(new PackageDepAtom((*a)[0]));
- PackageDatabaseEntryCollection::ConstPointer c = _imp->db->query(p, is_installed_only);
- std::copy(c->begin(), c->end(), filter_inserter(affected->inserter(), IsNotMemberOfCollection(affected)));
- PackageDatabaseEntryCollection::Iterator e(c->begin()), e_end(c->end());
- for ( ; e != e_end; ++e)
+ Context c("When parsing line 'Unaffected: " + *u + "':");
+
+ CompositeDepAtom::ConstPointer line(PortageDepParser::parse(*u));
+ AdvisoryVisitor atoms(_imp->env, *line);
+
+ if ((0 == atoms.size()) || (2 < atoms.size()))
+ {
+ continue;
+ }
+
+ bool is_range(2 == atoms.size());
+
+ PackageDatabaseEntryCollection::ConstPointer unaffected_collection1(_imp->db->query(*atoms.at(0), is_either));
+ PackageDatabaseEntryCollection::ConstPointer unaffected_collection2(new PackageDatabaseEntryCollection);
+ PackageDatabaseEntryCollection::Iterator p(unaffected_collection1->begin()), p_end(unaffected_collection1->end());
+
+ if (is_range)
+ unaffected_collection2 = _imp->db->query(*atoms.at(1), is_either);
+
+ for ( ; p != p_end ; ++p)
{
- if (unaffected->find(*e) != unaffected->end())
- unaffected->erase(*e);
+ if ((! is_range) || (unaffected_collection2->end() != unaffected_collection2->find(*p)))
+ {
+ unaffected.insert(*p);
+ std::set<std::pair<PackageDatabaseEntry, std::string> >::iterator
+ a(affected.find(std::make_pair(*p, advisory_id)));
+ if (a != affected.end())
+ affected.erase(a);
+ }
}
}
}
+ catch (const AdvisoryFileError & e)
+ {
+ Log::get_instance()->message(ll_warning, "Malformed advisory file '" + stringify(*f) + "': " + e.message());
+ }
+ catch (const InternalError & e)
+ {
+ throw;
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_warning, "Exception caught while parsing advisory '" + stringify(*f) +
+ "': " + e.message());
+ }
- PackageDatabaseEntryCollection::Iterator i(affected->begin()), i_end(affected->end());
+ }
+
+ std::set<std::pair<PackageDatabaseEntry, std::string> >::const_iterator i(affected.begin()), i_end(affected.end());
+ if (list_affected_only)
+ {
+ for ( ; i != i_end ; ++i)
+ {
+ Context c("When creating adding vulnerable package '" + stringify(i->first) + "':");
+
+ PackageDepAtom::Pointer p(make_atom(i->first));
+ p->set_tag(GLSADepTag::Pointer(new GLSADepTag(i->second, advisory_map[i->second])));
+ security_packages->add_child(p);
+ }
+ }
+ else
+ {
for ( ; i != i_end ; ++i)
{
- Context c("When finding best update for package '" + stringify(*i) + "':");
+ Context c("When finding best update for package '" + stringify(i->first) + "', affected by '" + i->second + "':");
- PackageDatabaseEntryCollection::Iterator e = find_best(unaffected, *i);
- if (e == unaffected->end())
- throw AllMaskedError("No best update available for package '" + stringify(*i) + "':");
+ PackageDatabaseEntryCollection::Iterator best = find_best(unaffected, i->first);
+ if (best == unaffected.end())
+ throw AllMaskedError("No best update available for package '" + stringify(i->first) + "':");
- PackageDepAtom::Pointer p(make_atom(*e));
- p->set_tag(advisory_tag);
+ PackageDepAtom::Pointer p(make_atom(*best));
+ p->set_tag(GLSADepTag::Pointer(new GLSADepTag(i->second, advisory_map[i->second])));
security_packages->add_child(p);
}
}
@@ -1739,7 +1819,7 @@ PortageRepository::do_security_set() const
}
DepAtom::Pointer
-PortageRepository::do_package_set(const std::string & s) const
+PortageRepository::do_package_set(const std::string & s, const PackageSetOptions & o) const
{
if ("system" == s)
{
@@ -1747,7 +1827,7 @@ PortageRepository::do_package_set(const std::string & s) const
return _imp->system_packages;
}
else if ("security" == s)
- return do_security_set();
+ return do_security_set(o);
else if ((_imp->setsdir / (s + ".conf")).exists())
{
GeneralSetDepTag::Pointer tag(new GeneralSetDepTag(s));
diff --git a/paludis/portage_repository.hh b/paludis/portage_repository.hh
index 9700426..2dd6f1b 100644
--- a/paludis/portage_repository.hh
+++ b/paludis/portage_repository.hh
@@ -116,9 +116,9 @@ namespace paludis
void need_category_names() const;
void need_version_names(const QualifiedPackageName &) const;
void need_virtual_names() const;
- PackageDatabaseEntryCollection::Iterator find_best(PackageDatabaseEntryCollection::Pointer & c,
+ PackageDatabaseEntryCollection::Iterator find_best(PackageDatabaseEntryCollection & c,
const PackageDatabaseEntry & e) const;
- DepAtom::Pointer do_security_set() const;
+ DepAtom::Pointer do_security_set(const PackageSetOptions & o) const;
protected:
/**
@@ -171,7 +171,7 @@ namespace paludis
virtual void do_install(const QualifiedPackageName &, const VersionSpec &,
const InstallOptions &) const;
- virtual DepAtom::Pointer do_package_set(const std::string & s) const;
+ virtual DepAtom::Pointer do_package_set(const std::string &, const PackageSetOptions &) const;
virtual bool do_sync() const;
@@ -212,6 +212,66 @@ namespace paludis
};
/**
+ * Class to convert AdvisoryFile lines to PackageDepAtom(s).
+ */
+ class AdvisoryVisitor :
+ private InstantiationPolicy<AdvisoryVisitor, instantiation_method::NonCopyableTag>,
+ public DepAtomVisitorTypes::ConstVisitor
+ {
+ private:
+ const Environment * const _env;
+
+ mutable const CompositeDepAtom & _a;
+
+ mutable std::vector<const PackageDepAtom *> _atoms;
+
+ protected:
+ ///\name Visit methods
+ ///{
+ void visit(const AllDepAtom *);
+ void visit(const AnyDepAtom *) PALUDIS_ATTRIBUTE((noreturn));
+ void visit(const UseDepAtom *);
+ void visit(const PlainTextDepAtom *);
+ void visit(const PackageDepAtom *);
+ void visit(const BlockDepAtom *);
+ ///}
+
+ public:
+ /**
+ * Constructor.
+ */
+ AdvisoryVisitor(const Environment * const env, const CompositeDepAtom & a);
+
+ /**
+ * Destructor.
+ */
+ ~AdvisoryVisitor()
+ {
+ }
+
+ /**
+ * Iterate over our dep atoms.
+ */
+ typedef std::vector<const PackageDepAtom *>::iterator Iterator;
+
+ /**
+ * Grab element by index.
+ */
+ const PackageDepAtom * at(std::vector<const PackageDepAtom *>::size_type n) const
+ {
+ return _atoms[n];
+ }
+
+ /**
+ * Return the number of atoms.
+ */
+ std::vector<const PackageDepAtom *>::size_type size() const
+ {
+ return _atoms.size();
+ }
+ };
+
+ /**
* Thrown if invalid parameters are provided for
* PortageRepository::make_portage_repository.
*
diff --git a/paludis/repository.hh b/paludis/repository.hh
index 7adae2a..dd17af2 100644
--- a/paludis/repository.hh
+++ b/paludis/repository.hh
@@ -79,6 +79,38 @@ namespace paludis
typedef MakeSmartRecord<InstallOptionsTag>::Type InstallOptions;
/**
+ * Keys for PackageSetOptions.
+ *
+ * \see PackageSetOptions
+ * \ingroup grprepository
+ */
+ enum PackageSetOptionsKeys
+ {
+ pso_list_affected_only, ///< Only list affected packages in the set
+ last_pso
+ };
+
+ /**
+ * Tag for PackageSetOptions.
+ *
+ * \see PackageSetOptions
+ * \ingroup grprepository
+ */
+ struct PackageSetOptionsTag :
+ SmartRecordTag<comparison_mode::NoComparisonTag, void>,
+ SmartRecordKeys<PackageSetOptionsKeys, last_pso>,
+ SmartRecordKey<pso_list_affected_only, bool>
+ {
+ };
+
+ /**
+ * Defines various options for package installation.
+ *
+ * \ingroup grprepository
+ */
+ typedef MakeSmartRecord<PackageSetOptionsTag>::Type PackageSetOptions;
+
+ /**
* Capability keys for a repository.
*/
enum RepositoryCapabilitiesKeys
@@ -592,15 +624,16 @@ namespace paludis
/**
* Override in descendents: package list.
*/
- virtual DepAtom::Pointer do_package_set(const std::string & id) const = 0;
+ virtual DepAtom::Pointer do_package_set(const std::string & id, const PackageSetOptions & o) const = 0;
public:
/**
* Fetch a package set.
*/
- virtual DepAtom::Pointer package_set(const std::string & s) const
+ virtual DepAtom::Pointer package_set(const std::string & s,
+ const PackageSetOptions & o = PackageSetOptions(false)) const
{
- return do_package_set(s);
+ return do_package_set(s, o);
}
};
diff --git a/paludis/vdb_repository.cc b/paludis/vdb_repository.cc
index 42666d5..6930455 100644
--- a/paludis/vdb_repository.cc
+++ b/paludis/vdb_repository.cc
@@ -744,7 +744,7 @@ VDBRepository::do_uninstall(const QualifiedPackageName & q, const VersionSpec &
}
DepAtom::Pointer
-VDBRepository::do_package_set(const std::string & s) const
+VDBRepository::do_package_set(const std::string & s, const PackageSetOptions &) const
{
Context context("When fetching package set '" + s + "' from '" +
stringify(name()) + "':");
diff --git a/paludis/vdb_repository.hh b/paludis/vdb_repository.hh
index 67692fc..93404c4 100644
--- a/paludis/vdb_repository.hh
+++ b/paludis/vdb_repository.hh
@@ -132,7 +132,7 @@ namespace paludis
virtual void do_uninstall(const QualifiedPackageName &, const VersionSpec &,
const InstallOptions &) const;
- virtual DepAtom::Pointer do_package_set(const std::string &) const;
+ virtual DepAtom::Pointer do_package_set(const std::string &, const PackageSetOptions & o) const;
public:
/**
diff --git a/paludis/version_operator.hh b/paludis/version_operator.hh
index f5e031c..83c192a 100644
--- a/paludis/version_operator.hh
+++ b/paludis/version_operator.hh
@@ -105,6 +105,14 @@ namespace paludis
}
/**
+ * Return value.
+ */
+ VersionOperatorValue value() const
+ {
+ return _v;
+ }
+
+ /**
* Return a pointer to member operator for VersionSpec that
* corresponds to a particular operator.
*/
diff --git a/src/command_line.cc b/src/command_line.cc
index 3a2a9c4..d99b665 100644
--- a/src/command_line.cc
+++ b/src/command_line.cc
@@ -41,6 +41,7 @@ CommandLine::CommandLine() :
a_list_sync_protocols(&action_args_internal, "list-sync-protocols", '\0', "List available sync protocols"),
a_list_repository_formats(&action_args_internal, "list-repository-formats", '\0', "List available repository formats"),
a_list_dep_tag_categories(&action_args_internal, "list-dep-tag-categories", '\0', "List known dep tag categories"),
+ a_list_vulnerabilities(&action_args_internal, "list-vulnerabilities", '\0', "List known vulnerabilities"),
a_update_news(&action_args_internal, "update-news", '\0', "Regenerate news.unread files"),
general_args(this, "General options"),
diff --git a/src/command_line.hh b/src/command_line.hh
index b7af345..61d0968 100644
--- a/src/command_line.hh
+++ b/src/command_line.hh
@@ -101,6 +101,9 @@ class CommandLine :
/// --list-dep-tag-categories
paludis::args::SwitchArg a_list_dep_tag_categories;
+ /// --list-vulnerabilities
+ paludis::args::SwitchArg a_list_vulnerabilities;
+
/// --update-news
paludis::args::SwitchArg a_update_news;
diff --git a/src/list.cc b/src/list.cc
index fd8bef6..f714921 100644
--- a/src/list.cc
+++ b/src/list.cc
@@ -24,6 +24,8 @@
#include <list>
#include <map>
#include <paludis/paludis.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/visitor.hh>
namespace p = paludis;
@@ -168,3 +170,148 @@ do_list_packages()
return ret_code;
}
+namespace
+{
+ /**
+ * Print dependency atoms as returned by do_package_set("security").
+ *
+ * \ingroup grpvulnerabilitiesprinter
+ */
+ class VulnerabilitiesPrinter :
+ public p::DepAtomVisitorTypes::ConstVisitor
+ {
+ private:
+ unsigned _size;
+
+ public:
+ /**
+ * Constructor.
+ */
+ VulnerabilitiesPrinter() :
+ _size(0)
+ {
+ }
+
+ /// \name Visit functions
+ ///{
+ void visit(const p::AllDepAtom * const);
+
+ void visit(const p::AnyDepAtom * const);
+
+ void visit(const p::UseDepAtom * const);
+
+ void visit(const p::PackageDepAtom * const);
+
+ void visit(const p::PlainTextDepAtom * const);
+
+ void visit(const p::BlockDepAtom * const);
+ ///}
+
+ /**
+ * Return number of visited atoms.
+ */
+ unsigned size() const
+ {
+ return _size;
+ }
+ };
+
+ void
+ VulnerabilitiesPrinter::visit(const p::AllDepAtom * const a)
+ {
+ std::for_each(a->begin(), a->end(), p::accept_visitor(this));
+ }
+
+ void
+ VulnerabilitiesPrinter::visit(const p::AnyDepAtom * const a)
+ {
+ std::for_each(a->begin(), a->end(), p::accept_visitor(this));
+ }
+
+ void
+ VulnerabilitiesPrinter::visit(const p::UseDepAtom * const a)
+ {
+ p::Log::get_instance()->message(p::ll_warning, "UseDepAtom encounter in do_package_set(\"security\").");
+ std::for_each(a->begin(), a->end(), p::accept_visitor(this));
+ }
+
+ void
+ VulnerabilitiesPrinter::visit(const p::PackageDepAtom * const a)
+ {
+ p::QualifiedPackageName q(a->package());
+
+ std::string c(p::stringify(q.get<p::qpn_category>()));
+ if (CommandLine::get_instance()->a_category.specified())
+ if (CommandLine::get_instance()->a_category.args_end() == std::find(
+ CommandLine::get_instance()->a_category.args_begin(),
+ CommandLine::get_instance()->a_category.args_end(),
+ c))
+ return;
+
+ std::string p(p::stringify(q.get<p::qpn_package>()));
+ if (CommandLine::get_instance()->a_package.specified())
+ if (CommandLine::get_instance()->a_package.args_end() == std::find(
+ CommandLine::get_instance()->a_package.args_begin(),
+ CommandLine::get_instance()->a_package.args_end(),
+ p))
+ return;
+
+ std::cout << "* " << colour(cl_package_name, p::stringify(q));
+ if (0 != a->tag())
+ std::cout << "-" << p::stringify(*a->version_spec_ptr());
+ if (0 != a->tag())
+ std::cout << " " << colour(cl_tag, "<" + a->tag()->short_text() + ">");
+ std::cout << std::endl;
+ ++_size;
+ }
+
+ void
+ VulnerabilitiesPrinter::visit(const p::PlainTextDepAtom * const)
+ {
+ }
+
+ void
+ VulnerabilitiesPrinter::visit(const p::BlockDepAtom * const)
+ {
+ }
+}
+
+int
+do_list_vulnerabilities()
+{
+ int ret_code = 0;
+
+ p::Context context("When performing list-vulnerabilities action from command line:");
+ p::Environment * const env(p::DefaultEnvironment::get_instance());
+ p::PackageSetOptions opts(true);
+
+ p::CompositeDepAtom::Pointer vulnerabilities(new p::AllDepAtom);
+
+ for (p::IndirectIterator<p::PackageDatabase::RepositoryIterator, const p::Repository>
+ r(env->package_database()->begin_repositories()), r_end(env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ {
+ if (CommandLine::get_instance()->a_repository.specified())
+ if (CommandLine::get_instance()->a_repository.args_end() == std::find(
+ CommandLine::get_instance()->a_repository.args_begin(),
+ CommandLine::get_instance()->a_repository.args_end(),
+ stringify(r->name())))
+ continue;
+
+ if (! r->get_interface<p::repo_sets>())
+ continue;
+
+ p::DepAtom::Pointer dep = r->get_interface<p::repo_sets>()->package_set("security", opts);
+ if (0 != dep)
+ vulnerabilities->add_child(dep);
+ }
+
+ VulnerabilitiesPrinter vp;
+ std::for_each(vulnerabilities->begin(), vulnerabilities->end(), p::accept_visitor(&vp));
+
+ if (vp.size() == 0)
+ ret_code = 1;
+
+ return ret_code;
+}
+
diff --git a/src/list.hh b/src/list.hh
index e3465c1..5cae90f 100644
--- a/src/list.hh
+++ b/src/list.hh
@@ -33,4 +33,7 @@ int do_list_categories();
/// Handle --list-packages.
int do_list_packages();
+/// Handle --list-vulnerabilities.
+int do_list_vulnerabilities();
+
#endif
diff --git a/src/paludis.cc b/src/paludis.cc
index 35f3de9..0b91eda 100644
--- a/src/paludis.cc
+++ b/src/paludis.cc
@@ -96,6 +96,7 @@ main(int argc, char *argv[])
CommandLine::get_instance()->a_list_sync_protocols.specified() +
CommandLine::get_instance()->a_list_repository_formats.specified() +
CommandLine::get_instance()->a_list_dep_tag_categories.specified() +
+ CommandLine::get_instance()->a_list_vulnerabilities.specified() +
CommandLine::get_instance()->a_contents.specified() +
CommandLine::get_instance()->a_owner.specified() +
CommandLine::get_instance()->a_has_version.specified() +
@@ -150,6 +151,14 @@ main(int argc, char *argv[])
return do_list_dep_tag_categories();
}
+ if (CommandLine::get_instance()->a_list_vulnerabilities.specified())
+ {
+ if (! CommandLine::get_instance()->empty())
+ throw DoHelp("list-vulnerabilities action takes no paramters");
+
+ return do_list_vulnerabilities();
+ }
+
/* these actions do need DefaultConfig */
std::string paludis_command(argv[0]);