|
|
@@ -3,6 +3,8 @@
|
|
|
* pkg-db.c - Low level package database routines (hash tables, etc.)
|
|
|
*
|
|
|
* Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
|
|
|
+ * Copyright © 2011 Linaro Limited
|
|
|
+ * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
|
|
|
*
|
|
|
* This is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
@@ -37,7 +39,7 @@
|
|
|
#define BINS 8191
|
|
|
|
|
|
static struct pkgset *bins[BINS];
|
|
|
-static int npackages;
|
|
|
+static int npkg, nset;
|
|
|
|
|
|
#define FNV_offset_basis 2166136261ul
|
|
|
#define FNV_mixing_prime 16777619ul
|
|
|
@@ -57,8 +59,24 @@ static unsigned int hash(const char *name) {
|
|
|
return h;
|
|
|
}
|
|
|
|
|
|
-struct pkginfo *
|
|
|
-pkg_db_find(const char *inname)
|
|
|
+/**
|
|
|
+ * Return the package set with the given name.
|
|
|
+ *
|
|
|
+ * If the package already exists in the internal database, then it returns
|
|
|
+ * the existing structure. Otherwise it allocates a new one and will return
|
|
|
+ * it. The actual name associated to the package set is a lowercase version
|
|
|
+ * of the name given in parameter.
|
|
|
+ *
|
|
|
+ * A package set (struct pkgset) can be composed of multiple package instances
|
|
|
+ * (struct pkginfo) where each instance is distinguished by its architecture
|
|
|
+ * (as recorded in pkg.installed.architecture and pkg.available.architecture).
|
|
|
+ *
|
|
|
+ * @param inname Name of the package set.
|
|
|
+ *
|
|
|
+ * @return The package set.
|
|
|
+ */
|
|
|
+struct pkgset *
|
|
|
+pkg_db_find_set(const char *inname)
|
|
|
{
|
|
|
struct pkgset **pointerp, *newpkg;
|
|
|
char *name = m_strdup(inname), *p;
|
|
|
@@ -71,7 +89,7 @@ pkg_db_find(const char *inname)
|
|
|
pointerp= &(*pointerp)->next;
|
|
|
if (*pointerp) {
|
|
|
free(name);
|
|
|
- return &(*pointerp)->pkg;
|
|
|
+ return *pointerp;
|
|
|
}
|
|
|
|
|
|
newpkg = nfmalloc(sizeof(struct pkgset));
|
|
|
@@ -79,16 +97,65 @@ pkg_db_find(const char *inname)
|
|
|
newpkg->name= nfstrsave(name);
|
|
|
newpkg->next= NULL;
|
|
|
*pointerp= newpkg;
|
|
|
- npackages++;
|
|
|
+ nset++;
|
|
|
+ npkg++;
|
|
|
|
|
|
free(name);
|
|
|
- return &newpkg->pkg;
|
|
|
+ return newpkg;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the package instance with the given name and architecture.
|
|
|
+ *
|
|
|
+ * @param name The package name.
|
|
|
+ * @param arch The requested architecture.
|
|
|
+ *
|
|
|
+ * @return The package instance.
|
|
|
+ */
|
|
|
+struct pkginfo *
|
|
|
+pkg_db_find_pkg(const char *name, const struct dpkg_arch *arch)
|
|
|
+{
|
|
|
+ struct pkgset *set;
|
|
|
+ struct pkginfo *pkg;
|
|
|
+
|
|
|
+ set = pkg_db_find_set(name);
|
|
|
+ pkg = &set->pkg;
|
|
|
+
|
|
|
+ return pkg;
|
|
|
+}
|
|
|
+
|
|
|
+struct pkginfo *
|
|
|
+pkg_db_find(const char *name)
|
|
|
+{
|
|
|
+ return pkg_db_find_pkg(name, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the number of package sets available in the database.
|
|
|
+ *
|
|
|
+ * @return The number of package sets.
|
|
|
+ */
|
|
|
+int
|
|
|
+pkg_db_count_set(void)
|
|
|
+{
|
|
|
+ return nset;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the number of package instances available in the database.
|
|
|
+ *
|
|
|
+ * @return The number of package instances.
|
|
|
+ */
|
|
|
+int
|
|
|
+pkg_db_count_pkg(void)
|
|
|
+{
|
|
|
+ return npkg;
|
|
|
}
|
|
|
|
|
|
int
|
|
|
pkg_db_count(void)
|
|
|
{
|
|
|
- return npackages;
|
|
|
+ return nset;
|
|
|
}
|
|
|
|
|
|
struct pkgiterator {
|
|
|
@@ -96,6 +163,13 @@ struct pkgiterator {
|
|
|
int nbinn;
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * Create a new package iterator.
|
|
|
+ *
|
|
|
+ * It can iterate either over package sets or over package instances.
|
|
|
+ *
|
|
|
+ * @return The iterator.
|
|
|
+ */
|
|
|
struct pkgiterator *
|
|
|
pkg_db_iter_new(void)
|
|
|
{
|
|
|
@@ -106,8 +180,52 @@ pkg_db_iter_new(void)
|
|
|
return i;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Return the next package set in the database.
|
|
|
+ *
|
|
|
+ * If no further package set is available, it will return NULL.
|
|
|
+ *
|
|
|
+ * @name iter The iterator.
|
|
|
+ *
|
|
|
+ * @return A package set.
|
|
|
+ */
|
|
|
+struct pkgset *
|
|
|
+pkg_db_iter_next_set(struct pkgiterator *iter)
|
|
|
+{
|
|
|
+ struct pkgset *set;
|
|
|
+
|
|
|
+ while (!iter->pigp) {
|
|
|
+ if (iter->nbinn >= BINS)
|
|
|
+ return NULL;
|
|
|
+ if (bins[iter->nbinn])
|
|
|
+ iter->pigp = &bins[iter->nbinn]->pkg;
|
|
|
+ iter->nbinn++;
|
|
|
+ }
|
|
|
+
|
|
|
+ set = iter->pigp->set;
|
|
|
+ if (set->next)
|
|
|
+ iter->pigp = &set->next->pkg;
|
|
|
+ else
|
|
|
+ iter->pigp = NULL;
|
|
|
+
|
|
|
+ return set;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the next package instance in the database.
|
|
|
+ *
|
|
|
+ * If no further package instance is available, it will return NULL. Note
|
|
|
+ * that it will return all instances of a given package set in sequential
|
|
|
+ * order. The first instance for a given package set will always correspond
|
|
|
+ * to the native architecture even if that package is not installed or
|
|
|
+ * available.
|
|
|
+ *
|
|
|
+ * @name i The iterator.
|
|
|
+ *
|
|
|
+ * @return A package instance.
|
|
|
+ */
|
|
|
struct pkginfo *
|
|
|
-pkg_db_iter_next(struct pkgiterator *i)
|
|
|
+pkg_db_iter_next_pkg(struct pkgiterator *i)
|
|
|
{
|
|
|
struct pkginfo *r;
|
|
|
|
|
|
@@ -129,6 +247,17 @@ pkg_db_iter_next(struct pkgiterator *i)
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
+struct pkginfo *
|
|
|
+pkg_db_iter_next(struct pkgiterator *iter)
|
|
|
+{
|
|
|
+ return pkg_db_iter_next_pkg(iter);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Free the package database iterator.
|
|
|
+ *
|
|
|
+ * @name i The iterator.
|
|
|
+ */
|
|
|
void
|
|
|
pkg_db_iter_free(struct pkgiterator *i)
|
|
|
{
|
|
|
@@ -142,7 +271,8 @@ pkg_db_reset(void)
|
|
|
|
|
|
dpkg_arch_reset_list();
|
|
|
nffreeall();
|
|
|
- npackages= 0;
|
|
|
+ nset = 0;
|
|
|
+ npkg = 0;
|
|
|
for (i=0; i<BINS; i++) bins[i]= NULL;
|
|
|
}
|
|
|
|
|
|
@@ -153,14 +283,15 @@ pkg_db_report(FILE *file)
|
|
|
struct pkgset *pkg;
|
|
|
int *freq;
|
|
|
|
|
|
- freq= m_malloc(sizeof(int)*npackages+1);
|
|
|
- for (i=0; i<=npackages; i++) freq[i]= 0;
|
|
|
+ freq = m_malloc(sizeof(int) * nset + 1);
|
|
|
+ for (i = 0; i <= nset; i++)
|
|
|
+ freq[i] = 0;
|
|
|
for (i=0; i<BINS; i++) {
|
|
|
for (c=0, pkg= bins[i]; pkg; c++, pkg= pkg->next);
|
|
|
fprintf(file,"bin %5d has %7d\n",i,c);
|
|
|
freq[c]++;
|
|
|
}
|
|
|
- for (i=npackages; i>0 && freq[i]==0; i--);
|
|
|
+ for (i = nset; i > 0 && freq[i] == 0; i--);
|
|
|
while (i >= 0) {
|
|
|
fprintf(file, "size %7d occurs %5d times\n", i, freq[i]);
|
|
|
i--;
|