chiark / gitweb /
9eb27a4c26c24834ff4dfe32694fcd0742e31b45
[rcheck] / check.d / 50.updates
1 #! /usr/bin/python
2 ###
3 ### Report on available package updates, including security updates.
4
5 import time as T
6 import os as OS
7 import errno as E
8
9 import apt_pkg as APT
10 import apt.cache as AC
11
12 ###--------------------------------------------------------------------------
13 ### Some utility functions.
14
15 def cache_up_to_date_p():
16   """Answer whether the cache is up-to-date."""
17
18   ## I use the same stamp file as APT's standard periodic update service.
19   ## This needs prodding via a hook in the APT configuration.
20   now = T.time()
21   try:
22     last = OS.path.getmtime('/var/lib/apt/periodic/update-stamp')
23   except OSError, err:
24     if err.errno == E.ENOENT:
25       return False
26   return now - last < 86400
27
28 def upgradable_packages():
29   """Return a list of packages for which updates are available."""
30   cache = AC.Cache()
31   return [pkg for pkg in cache if pkg.is_upgradable]
32
33 def security_updates_p(pkg):
34   """Answer whether any update for PKG is security-relevant."""
35
36   ## There doesn't seem to be a good way of doing this.  For distributions
37   ## like `testing', security updates are folded into the main distribution
38   ## after the usual triage process, so they stop looking like security
39   ## updates.  Worse, for `unstable' there aren't distinct security updates
40   ## anyway: they're all just thrown into the mixer.  The good way to tell
41   ## would be to fetch the changelog and look for urgent changes.  Debian's
42   ## Aptitude checks explicitly for `security.debian.org'.  This check at
43   ## least also captures Ubuntu.
44   for v in pkg.versions:
45     if v < pkg.installed:
46       continue
47     for o in v.origins:
48       if o.site.startswith('security.'):
49         return True
50   return False
51
52 ###--------------------------------------------------------------------------
53 ### Main program.
54
55 if not cache_up_to_date_p():
56   print 'W: package cache is more than 24 hours of date'
57 updates = upgradable_packages()
58 if updates:
59   plural = len(updates) != 1
60   print 'I: updates available for %d %s' % \
61         (len(updates), plural and 'packages' or 'package')
62 sec = [pkg for pkg in updates if security_updates_p(pkg)]
63 if sec:
64   plural = len(sec) != 1
65   print 'W: security updates available for %d %s' % \
66         (len(sec), plural and 'packages' or 'package')
67
68 ###----- That's all, folks --------------------------------------------------