summaryrefslogtreecommitdiff
path: root/arch/relchk.py
blob: dfbf1f7300926c1cfeecea90910c3ffbaa4598a6 (plain)
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 python3

import configparser
import hashlib
import os
import re
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
from urllib.request import urlopen
try:
    import lxml
    htmlparser = 'lxml'
except ImportError:
    htmlparser = 'html.parser'

cfgpath = os.path.abspath(os.path.expanduser(
                                        '~/.config/optools/relchk/arch.ini'))

cfg = configparser.ConfigParser()
cfg['arch'] = {'url': 'https://arch.mirror.square-r00t.net/iso/latest/',
               'path': '/boot/iso/arch.iso',
               'hashtype': 'sha1',
               'hashurl': (
                'https://arch.mirror.square-r00t.net/iso/latest/sha1sums.txt')
                }

if not os.path.isfile(cfgpath):
    os.makedirs(os.path.dirname(cfgpath), exist_ok = True)
    with open(cfgpath, 'w') as f:
        cfg.write(f)
else:
    cfg.read(cfgpath)

cfg['arch']['path'] = os.path.abspath(os.path.expanduser(cfg['arch']['path']))

# We need the hashes first. We'll pop them into memory,
# no need to save locally.
# Must be in GNU checksum format (i.e. "<HASH>  <FILENAME>\n").
hashes = {}
if 'hashurl' in cfg['arch']:
    with urlopen(cfg['arch']['hashurl']) as h:
        for i in h.read().decode('utf-8').splitlines():
            line = [x.strip() for x in i.split()]
            hashes[os.path.basename(line[1])] = line[0]
chksum = hashlib.new(cfg['arch']['hashtype'])

# Now we (try to) get a list of files available for download. We're looking
# for .iso or .img files. Compressed images not currently supported; TODO.
exts = re.compile('.*\.(iso|img)$', re.IGNORECASE)
imgfiles = []
with urlopen(cfg['arch']['url']) as u:
    dlsoup = BeautifulSoup(u.read().decode('utf-8'), htmlparser)
for a in dlsoup.find_all('a'):
    if a['href']:
        if exts.search(a['href']):
            if not urlparse(a['href']).netloc:
                imgfiles.append(urljoin(cfg['arch']['url'], a['href']))
            else:
                imgfiles.append(a['href'])
if not imgfiles:
    raise RuntimeError('Could not find any ISO or IMG files at {0}'.format(
            cfg['arch']['url']))
# Not foolproof, but will handle standard Arch ISO mirrors just fine.
imgfiles.sort()
iso = imgfiles[0]

# Now we get the existing file (if it exists) and grab the hash (if we have
# one fetched).
up2date = False
if os.path.isfile(cfg['arch']['path']):
    _fname = os.path.basename(iso)
    if _fname in hashes:
        with open(cfg['arch']['path'], 'rb') as f:
            chksum.update(f.read())
        if chksum.hexdigest().lower() == hashes[_fname].lower():
            up2date = True

if not up2date:
    os.makedirs(os.path.dirname(cfg['arch']['path']), exist_ok = True)
    with open(cfg['arch']['path'], 'wb') as f, urlopen(iso) as u:
        f.write(u.read())