Automatically fetch and checksum OpenBSD snapshots

I run OpenBSD on all my machines. I think its a great operating system with excellent range of features and all the components fit together nicely. One of my favourite things about OpenBSD is the highly aggressive release schedule. While a stable release is cut every 6 months, Theo is producing complete, full builds of the system for most architectures from CVS HEAD on a nearly daily basis. The entire ports tree is baked into binary packages very frequently too - although since this is much more time-consuming it is more like a full package build appears on mirrors every week or two. Such releases are called ’snapshots’.

In any case, I don’t run OpenBSD ‘release’ or ’stable’ builds on any of my machines - I run snapshots everywhere. So I am frequently downloading new snapshots. While its not exactly difficult to mirror a directory via FTP by hand, I wrote a small Python program to do it for me. The Python program has a few nice options. It defaults to using ftp.openbsd.org as the mirror, but this can be trivially overriden by the -m flag. I typically use -m rt.fm, rt.fm I have found to be an excellent mirror for the USA. The program also automatically detects the architecture of the machine you are running on - but you can override this via the -a flag. It also doesn’t download the very large ISO images which are built along with the snapshots. Finally, once it has completed downloading everything, it will (if there is an MD5 file present) verify the MD5 checksums of each downloaded file.

This isn’t a complicated program, but I find it useful, and I thought I’d share. Here it is in its 80-odd line entirety (or download it here).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env python
# $Id: autosnap.py,v 1.5 2008/11/19 04:20:25 niallo Exp $
 
import fnmatch
import ftplib
import getopt
import hashlib
import os
import sys
 
MIRROR="ftp.openbsd.org"
PATH="/pub/OpenBSD/snapshots/"
DROP_DIR="."
 
ARCH=os.uname()[4]
# list of files not to download - globs supported
FILE_EXCEPT = ['*.iso*']
 
def usage():
    print >> sys.stderr, "autosnap.py [-a arch] [-d drop dir] [-m mirror] [-p path]"
    sys.exit(2)
 
def main():
    ftp = ftplib.FTP(MIRROR)
    ftp.login()
    ftp.cwd("%s/%s" %(PATH, ARCH))
    files = ftp.nlst()
    remove = []
    for p in FILE_EXCEPT:
        remove.extend(fnmatch.filter(files, p))
    for r in remove:
        files.remove(r)
    for f in files:
        print "fetching file %s" %(f)
        ftp.retrbinary("RETR %s" %(f), open("%s/%s" %(DROP_DIR, f), 'wb').write, 4096)
    ftp.quit()
    if 'MD5' in files:
        print "Verifying MD5sums"
        f = open("%s/MD5" %(DROP_DIR), "r")
        md5sums = {}
        for line in f:
            filename = line[line.index('(')+1:line.index(')')]
            if filename in files:
                hash = line.split('=')[1].strip()
                md5sums[filename] = str(hash)
        f.close()
        files.remove('MD5')
        good = 0
        for filename in md5sums.keys():
            f = open("%s/%s" %(DROP_DIR, filename), "r")
            d = f.read()
            f.close()
            m = hashlib.md5()
            m.update(d)
            digest = m.hexdigest()
            if digest == md5sums[filename]:
                print "%s OK" %(filename)
                good += 1
            else:
                print "%s FAIL" %(filename)
        print "%d/%d files verified OK" %(good, len(md5sums))
        if good == len(md5sums):
            sys.exit(0)
        else:
            sys.exit(1)
if __name__ == "__main__":
    try:
        opts, args = getopt.getopt(sys.argv[1:], "a:d:m:p:")
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    for o, a in opts:
        if o == "-a":
            ARCH = a
        if o == "-d":
            DROP_DIR = a
        if o == "-m":
            MIRROR = a
        if o == "-p":
            PATH = a
    main()
Share this on a social bookmarking site:
  • Digg
  • del.icio.us
  • Netvouz
  • description
  • ThisNext
  • MisterWong
  • Reddit
  • StumbleUpon

Tags: , , ,

Related posts:
  • OpenBSD’s omalloc: Bug and buffer overflow detection
  • Porting software from OpenBSD to Windows
  • Porting software from OpenBSD to Linux II
  • OpenBSD 4.2, FFS2 and large disks
  • sys/queue.h sucks on Linux
  • 7 Responses to “Automatically fetch and checksum OpenBSD snapshots”

    1. chris says:

      Could you please discuss about OpenBSD’s snapshot, as in how it’s different from running -current or -stable?

      Thanks.

    2. niallo says:

      Snapshots are effectively the same as running -current. Sometimes patches can be in snapshots which have not been committed, though.

    3. chris says:

      Just a suggestion: you could write it in Perl, since Perl is in the base system and Python is not.

    4. Artis says:

      Pretty much like Han’s OpenBSD-binary-upgrade: . I’d consider rsync mirrors over http://ftp.

    5. niallo says:

      This script doesn’t do any upgrading, it just downloads and checksums things.

    6. [...] has made OpenBSD’s malloc even stricter. I upgraded my home machine over the weekend to the latest snapshot with these commits, and I’m currently running a bunch of Unworkable BitTorrent download [...]

    Leave a Reply