[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Finding the origin of a package installed by APT



My current machine has a number of packages installed from backports
which no longer exist, so will not be upgraded should there be any
security problems. I am about to reinstall my machine so would like to
avoid this in the future. I have a partial solution, but have hit a
problem in my understanding of APT, so would appreciate any advice.

More generally, my goal is to be able to find out where an installed
package came from. Using "apt-cache policy" will do this for packages
which still exist in the APT database, but if a repository goes
offline, I belived this information is lost. 

For example, for gzip, this works fine - it tells me that the current
version (1.3.2-3woody4), came from security.debian.org:

sjm217@kelvin:~$ apt-cache policy gzip
gzip:
  Installed: 1.3.2-3woody4
  Candidate: 1.3.2-3woody4
  Version Table:
 *** 1.3.2-3woody4 0
        500 http://security.debian.org woody/updates/main Packages
        100 /var/lib/dpkg/status
     1.3.2-3woody3 0
        500 http://www.uk.debian.org woody/main Packages

But for r-base-core, which comes from a repository I couldn't download
at the last "apt-get update". It tells me that the current version
(2.1.0-0woody1) is only known from /var/lib/dpkg/status:

sjm217@kelvin:~$ apt-cache policy r-base-core
r-base-core:
  Installed: 2.1.0-0woody1
  Candidate: 2.1.0-0woody1
  Version Table:
 *** 2.1.0-0woody1 0
        100 /var/lib/dpkg/status
     1.5.1-0woody1 0
        500 http://www.uk.debian.org woody/main Packages

As far as I understand, once the relevant entry on /var/lib/apt/lists
has gone, there is no record of where a package came from.

So I wrote a program, which is run after an "apt-get
install/update/upgrade" that records the origin of all packages
currently installed. Then when there is a change, for example an APT
repository going offline, it can recover the last known origin. This
works using the python-apt package, to interface to libapt-pkg. For
each package in the cache it queries the CurrentVersion, and for each
PackageFile in the FileList associated with CurrentVersion, it stores
the FileName. This works for most cases, but not where there are
multiple PackageFiles of type "Debian Package Index".

To illustrate the problem, I have attached a small Python script which
gets origin information of two packages. Here is the output from a
Debian Woody box, for gzip:

P:  gzip V: 1.3.2-3woody4
 F: /var/lib/apt/lists/security.debian.org... (Debian Package Index)
 F: /var/lib/dpkg/status (Debian dpkg status file)

This shows the current version is 1.3.2-3woody4, and that there is
only one PackageFile entry of type "Debian Package Index", and that
this package came from security.debian.org. My program would store
security.debian.org, which works fine.

Here is the output for imlib1:

P:  imlib1 V: 1.9.14-2woody2
 F: /var/lib/apt/lists/www.uk.debian.org... (Debian Package Index)
 F: /var/lib/apt/lists/security.debian.org... (Debian Package Index)
 F: /var/lib/dpkg/status (Debian dpkg status file)

This shows that the current version of imlib1 is 1.9.14-2woody2, but
there are two entries of type "Debian Package Index", so I don't know
how to find out whether this package came from www.uk.debian.org or
security.debian.org.

My question is that, in cases like this, where there are several
sources for a package, how can I reliably find out from which source
is the currently installed package from?

In this particular example, it's not that much of a problem since they
both came from the Debian project, but say a third-party APT
repository publishes a package with the same version number as an
official Debian package. If that repository goes offline, how can I
find out whether the package came from Debian or from the third party?

Thank you,
Steven Murdoch.

-- 
w: http://www.cl.cam.ac.uk/users/sjm217/
#!/usr/bin/python

import apt_pkg
apt_pkg.init()

for package in apt_pkg.GetCache().Packages:
    if not (package.CurrentState==6 and
    (package.Name=="imlib1" or package.Name=="gzip")):
        continue
    ver=package.CurrentVer
    print "P: ",package.Name, "V:", ver.VerStr
    for f, n in ver.FileList:
        print " F:",f.FileName, "(%s)"%f.IndexType

Attachment: pgpZcZR5n1nei.pgp
Description: PGP signature


Reply to: