more sorting
[platform/upstream/crda.git] / db2bin.py
1 #!/usr/bin/env python
2
3 from cStringIO import StringIO
4 import struct
5 import sha
6 from dbparse import DBParser, create_rules, create_collections
7
8 MAGIC = 0x52474442
9 VERSION = 19
10
11 def be32(output, val):
12     output.write(struct.pack('>I', val))
13
14 class PTR(object):
15     def __init__(self, output):
16         self._output = output
17         self._pos = output.tell()
18         be32(output, 0xFFFFFFFF)
19
20     def set(self, val=None):
21         if val is None:
22             val = self._output.tell()
23         self._offset = val
24         pos = self._output.tell()
25         self._output.seek(self._pos)
26         be32(self._output, val)
27         self._output.seek(pos)
28
29     def get(self):
30         return self._offset
31
32 p = DBParser()
33 bands, power, countries = p.parse(file('db.txt'))
34 rules = create_rules(countries)
35 rules.sort(cmp=lambda x, y: cmp(bands[x[0]], bands[y[0]]))
36 collections = create_collections(countries)
37 collections.sort(cmp=lambda x, y: cmp(bands[x[0][0]], bands[y[0][0]]))
38
39 output = StringIO()
40
41 # struct regdb_file_header
42 be32(output, MAGIC)
43 be32(output, VERSION)
44 reg_country_ptr = PTR(output)
45 # add number of countries
46 be32(output, len(countries))
47 siglen = PTR(output)
48
49 power_rules = {}
50 pi = [(i, p) for i, p in power.iteritems()]
51 pi.sort(cmp=lambda x, y: cmp(x[1], y[1]))
52 for power_rule_id, pr in pi:
53     environ = pr[0]
54     pr = [int(v * 100) for v in pr[1:]]
55     power_rules[power_rule_id] = output.tell()
56     # struct regdb_file_power_rule
57     output.write(struct.pack('>cxxxIIIII', str(environ), *pr))
58
59 freq_ranges = {}
60 bi = [(f, i) for f, i in bands.iteritems()]
61 bi.sort(cmp=lambda x, y: cmp(x[1], y[1]))
62 for freq_range_id, fr in bands.iteritems():
63     freq_ranges[freq_range_id] = output.tell()
64     fl = fr[3]
65     fr = [int(f * 1000) for f in fr[:3]]
66     # struct regdb_file_freq_range
67     output.write(struct.pack('>IIIII', fr[0], fr[1], fr[2], fl, 0))
68
69
70 reg_rules = {}
71 for reg_rule in rules:
72     freq_range_id, power_rule_id = reg_rule
73     reg_rules[reg_rule] = output.tell()
74     # struct regdb_file_reg_rule
75     output.write(struct.pack('>II', freq_ranges[freq_range_id], power_rules[power_rule_id]))
76
77
78 reg_rules_collections = {}
79
80 for coll in collections:
81     reg_rules_collections[coll] = output.tell()
82     # struct regdb_file_reg_rules_collection
83     be32(output, len(coll))
84     coll = list(coll)
85     coll.sort(cmp=lambda x, y: cmp(bands[x[0]], bands[y[0]]))
86     for regrule in coll:
87         be32(output, reg_rules[regrule])
88
89 # update country pointer now!
90 reg_country_ptr.set()
91
92 countrynames = countries.keys()
93 countrynames.sort()
94 for alpha2 in countrynames:
95     coll = countries[alpha2]
96     # struct regdb_file_reg_country
97     output.write(struct.pack('>ccxxI', str(alpha2[0]), str(alpha2[1]), reg_rules_collections[coll]))
98
99 # Load RSA only now so people can use this script
100 # without having those libraries installed to verify
101 # their SQL changes
102 from M2Crypto import RSA
103
104 # determine signature length
105 key = RSA.load_key('key.priv.pem')
106 hash = sha.new()
107 hash.update(output.getvalue())
108 sig = key.sign(hash.digest())
109 # write it to file
110 siglen.set(len(sig))
111 # sign again
112 hash = sha.new()
113 hash.update(output.getvalue())
114 sig = key.sign(hash.digest())
115
116 output.write(sig)
117
118 outfile = open('regulatory.bin', 'w')
119 outfile.write(output.getvalue())