[svn] commit: r1265 - in /trunk/src: bin/loadzone/b10-loadzone.py.in lib/python/isc/auth/master.py lib/python/isc/auth/sqlite3_ds.py
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Mar 10 06:56:48 UTC 2010
Author: each
Date: Wed Mar 10 06:56:47 2010
New Revision: 1265
Log:
change the zone master file parser to a python class, "MasterFile"
Modified:
trunk/src/bin/loadzone/b10-loadzone.py.in
trunk/src/lib/python/isc/auth/master.py
trunk/src/lib/python/isc/auth/sqlite3_ds.py
Modified: trunk/src/bin/loadzone/b10-loadzone.py.in
==============================================================================
--- trunk/src/bin/loadzone/b10-loadzone.py.in (original)
+++ trunk/src/bin/loadzone/b10-loadzone.py.in Wed Mar 10 06:56:47 2010
@@ -17,7 +17,7 @@
import sys; sys.path.append ('@@PYTHONPATH@@')
import re, getopt
import isc.auth
-import isc.auth.master
+from isc.auth.master import MasterFile
#########################################################################
# usage: print usage note and exit
@@ -58,19 +58,19 @@
zonefile = args[0]
try:
- zf = isc.auth.master.openzone(zonefile, initial_origin)
+ master = MasterFile(zonefile, initial_origin)
except Exception as e:
print("Error reading zone file: " + str(e))
exit(1)
try:
- zone = isc.auth.master.zonename(zf, initial_origin)
+ zone = master.zonename()
except Exception as e:
print("Error reading zone file: " + str(e))
exit(1)
try:
- isc.auth.sqlite3_ds.load(dbfile, zone, isc.auth.master.zonedata, zf)
+ isc.auth.sqlite3_ds.load(dbfile, zone, master.zonedata)
except Exception as e:
print("Error loading database: " + str(e))
exit(1)
Modified: trunk/src/lib/python/isc/auth/master.py
==============================================================================
--- trunk/src/lib/python/isc/auth/master.py (original)
+++ trunk/src/lib/python/isc/auth/master.py Wed Mar 10 06:56:47 2010
@@ -22,10 +22,18 @@
pass
#########################################################################
-# global variables
-#########################################################################
-maxttl = 0x7fffffff
-defclass = 'IN'
+# pop: remove the first word from a line
+# input: a line
+# returns: first word, rest of the line
+#########################################################################
+def pop(line):
+ list = line.split()
+ first, rest = '', ''
+ if len(list) != 0:
+ first = list[0]
+ if len(list) > 1:
+ rest = ' '.join(list[1:])
+ return first, rest
#########################################################################
# cleanup: removes excess content from zone file data, including comments
@@ -43,6 +51,87 @@
s = s.strip().expandtabs()
s = decomment.sub('', s)
return ' '.join(s.split())
+
+#########################################################################
+# istype: check whether a string is a known RR type.
+# returns: boolean
+#########################################################################
+rrtypes = set(['a', 'aaaa', 'afsdb', 'apl', 'cert', 'cname', 'dhcid',
+ 'dlv', 'dname', 'dnskey', 'ds', 'gpos', 'hinfo', 'hip',
+ 'ipseckey', 'isdn', 'key', 'kx', 'loc', 'mb', 'md',
+ 'mf', 'mg', 'minfo', 'mr', 'mx', 'naptr', 'ns', 'nsap',
+ 'nsap-ptr', 'nsec', 'nsec3', 'nsec3param', 'null',
+ 'nxt', 'opt', 'ptr', 'px', 'rp', 'rrsig', 'rt', 'sig',
+ 'soa', 'spf', 'srv', 'sshfp', 'tkey', 'tsig', 'txt',
+ 'x25', 'wks'])
+def istype(s):
+ global rrtypes
+ if s.lower() in rrtypes:
+ return True
+ else:
+ return False
+
+#########################################################################
+# isclass: check whether a string is a known RR class. (only 'IN' is
+# supported, but the others must still be recognizable.)
+# returns: boolean
+#########################################################################
+rrclasses = set(['in', 'ch', 'chaos', 'hs', 'hesiod'])
+def isclass(s):
+ global rrclasses
+ if s.lower() in rrclasses:
+ return True
+ else:
+ return False
+
+#########################################################################
+# isname: check whether a string is a valid DNS name.
+# returns: boolean
+#########################################################################
+name_regex = re.compile('[-\w\$\d\/*]+(?:\.[-\w\$\d\/]+)*\.?')
+def isname(s):
+ global name_regex
+ if s == '.' or name_regex.match(s):
+ return True
+ else:
+ return False
+
+#########################################################################
+# isttl: check whether a string is a valid TTL specifier.
+# returns: boolean
+#########################################################################
+ttl_regex = re.compile('[0-9]+[wdhms]?', re.I)
+def isttl(s):
+ global ttl_regex
+ if ttl_regex.match(s):
+ return True
+ else:
+ return False
+
+#########################################################################
+# parse_ttl: convert a TTL field into an integer TTL value
+# (multiplying as needed for minutes, hours, etc.)
+# input:
+# string
+# returns:
+# int
+# throws:
+# MasterFileError
+#########################################################################
+def parse_ttl(s):
+ m = re.match('([0-9]+)(.*)', s)
+ if not m:
+ raise MasterFileError('Invalid TTL: ' + s)
+ ttl, suffix = int(m.group(1)), m.group(2)
+ if suffix.lower() == 'w':
+ ttl *= 604800
+ elif suffix.lower() == 'd':
+ ttl *= 86400
+ elif suffix.lower() == 'h':
+ ttl *= 3600
+ elif suffix.lower() == 'm':
+ ttl *= 60
+ return ttl
#########################################################################
# records: generator function to return complete RRs from the zone file,
@@ -84,379 +173,286 @@
yield ret
#########################################################################
-# pop: remove the first word from a line
-# input: a line
-# returns: first word, rest of the line
-#########################################################################
-def pop(line):
- list = line.split()
- first, rest = '', ''
- if len(list) != 0:
- first = list[0]
- if len(list) > 1:
- rest = ' '.join(list[1:])
- return first, rest
-
-#########################################################################
-# istype: check whether a string is a known RR type.
-# returns: boolean
-#########################################################################
-rrtypes = set(['a', 'aaaa', 'afsdb', 'apl', 'cert', 'cname', 'dhcid',
- 'dlv', 'dname', 'dnskey', 'ds', 'gpos', 'hinfo', 'hip',
- 'ipseckey', 'isdn', 'key', 'kx', 'loc', 'mb', 'md',
- 'mf', 'mg', 'minfo', 'mr', 'mx', 'naptr', 'ns', 'nsap',
- 'nsap-ptr', 'nsec', 'nsec3', 'nsec3param', 'null',
- 'nxt', 'opt', 'ptr', 'px', 'rp', 'rrsig', 'rt', 'sig',
- 'soa', 'spf', 'srv', 'sshfp', 'tkey', 'tsig', 'txt',
- 'x25', 'wks'])
-def istype(s):
- global rrtypes
- if s.lower() in rrtypes:
- return True
- else:
- return False
-
-#########################################################################
-# isclass: check whether a string is a known RR class. (only 'IN' is
-# supported, but the others must still be recognizable.)
-# returns: boolean
-#########################################################################
-rrclasses = set(['in', 'ch', 'chaos', 'hs', 'hesiod'])
-def isclass(s):
- global rrclasses
- if s.lower() in rrclasses:
- return True
- else:
- return False
-
-#########################################################################
-# isname: check whether a string is a valid DNS name.
-# returns: boolean
-#########################################################################
-name_regex = re.compile('[-\w\$\d\/*]+(?:\.[-\w\$\d\/]+)*\.?')
-def isname(s):
- global name_regex
- if s == '.' or name_regex.match(s):
- return True
- else:
- return False
-
-#########################################################################
-# isttl: check whether a string is a valid TTL specifier.
-# returns: boolean
-#########################################################################
-ttl_regex = re.compile('[0-9]+[wdhms]?', re.I)
-def isttl(s):
- global ttl_regex
- if ttl_regex.match(s):
- return True
- else:
- return False
-
-#########################################################################
-# parse_ttl: convert a TTL field into an integer TTL value
-# (multiplying as needed for minutes, hours, etc.)
-# input:
-# string
-# returns:
-# int
-# throws:
-# MasterFileError
-#########################################################################
-def parse_ttl(s):
- m = re.match('([0-9]+)(.*)', s)
- if not m:
- raise MasterFileError('Invalid TTL: ' + s)
- ttl, suffix = int(m.group(1)), m.group(2)
- if suffix.lower() == 'w':
- ttl *= 604800
- elif suffix.lower() == 'd':
- ttl *= 86400
- elif suffix.lower() == 'h':
- ttl *= 3600
- elif suffix.lower() == 'm':
- ttl *= 60
- return ttl
-
-#########################################################################
-# directive: handle $ORIGIN, $TTL and $GENERATE directives
-# (currently only $ORIGIN and $TTL are implemented)
-# input:
-# a line from a zone file
-# returns:
-# a boolean indicating whether a directive was found
-# throws:
-# MasterFileError
-#########################################################################
-def directive(s):
- global origin, defttl, maxttl
- first, more = pop(s)
- second, more = pop(more)
- if re.match('\$origin', first, re.I):
- if not second or not isname(second):
- raise MasterFileError('Invalid $ORIGIN')
- if more:
- raise MasterFileError('Invalid $ORIGIN')
- if second == '.':
- origin = ''
- elif second[-1] == '.':
- origin = second
+# define the MasterFile class for reading zone master files
+#########################################################################
+class MasterFile:
+ __defclass = 'IN'
+ __maxttl = 0x7fffffff
+ __defttl = ''
+ __zonefile = ''
+ __name = ''
+
+ def __init__(self, filename, initial_origin = ''):
+ if initial_origin == '.':
+ initial_origin = ''
+ self.__initial_origin = initial_origin
+ self.__origin = initial_origin
+ try:
+ self.__zonefile = open(filename, 'r')
+ except:
+ raise MasterFileError("Could not open " + filename)
+
+ def __del__(self):
+ if self.__zonefile:
+ self.__zonefile.close()
+
+ #########################################################################
+ # handle $ORIGIN, $TTL and $GENERATE directives
+ # (currently only $ORIGIN and $TTL are implemented)
+ # input:
+ # a line from a zone file
+ # returns:
+ # a boolean indicating whether a directive was found
+ # throws:
+ # MasterFileError
+ #########################################################################
+ def __directive(self, s):
+ first, more = pop(s)
+ second, more = pop(more)
+ if re.match('\$origin', first, re.I):
+ if not second or not isname(second):
+ raise MasterFileError('Invalid $ORIGIN')
+ if more:
+ raise MasterFileError('Invalid $ORIGIN')
+ if second == '.':
+ self.__origin = ''
+ elif second[-1] == '.':
+ self.__origin = second
+ else:
+ self.__origin = second + '.' + self.__origin
+ return True
+ elif re.match('\$ttl', first, re.I):
+ if not second or not isttl(second):
+ raise MasterFileError('Invalid TTL: "' + second + '"')
+ if more:
+ raise MasterFileError('Invalid $TTL statement')
+ self.__defttl = parse_ttl(second)
+ if self.__defttl > self.__maxttl:
+ raise MasterFileError('TTL too high: ' + second)
+ return True
+ elif re.match('\$generate', first, re.I):
+ raise MasterFileError('$GENERATE not yet implemented')
else:
- origin = second + '.' + origin
- return True
- elif re.match('\$ttl', first, re.I):
- if not second or not isttl(second):
- raise MasterFileError('Invalid TTL: "' + second + '"')
- if more:
- raise MasterFileError('Invalid $TTL statement')
- defttl = parse_ttl(second)
- if defttl > maxttl:
- raise MasterFileError('TTL too high: ' + second)
- return True
- elif re.match('\$generate', first, re.I):
- raise MasterFileError('$GENERATE not yet implemented')
- else:
- return False
-
-#########################################################################
-# include: handle $INCLUDE directives
-# input:
-# a line from a zone file
-# returns:
-# the parsed output of the included file, if any, or an empty array
-# throws:
-# MasterFileError
-#########################################################################
-filename=re.compile('[\"\']*([^\'\"]+)[\"\']*')
-def include(s):
- global origin, defttl, maxttl
- first, rest = pop(s)
- if re.match('\$include', first, re.I):
- m = filename.match(rest)
- if m:
- file = m.group(1)
- return file
-
-#########################################################################
-# four: try parsing on the assumption that the RR type is specified in
-# field 4, and name, ttl and class are in fields 1-3
-# are all specified, with type in field 4
-# input:
-# a record to parse, and the most recent name found in prior records
-# returns:
-# empty list if parse failed, else name, ttl, class, type, rdata
-#########################################################################
-def four(record, curname):
- ret = ''
- list = record.split()
- if len(list) <= 4:
+ return False
+
+ #########################################################################
+ # handle $INCLUDE directives
+ # input:
+ # a line from a zone file
+ # returns:
+ # the parsed output of the included file, if any, or an empty array
+ # throws:
+ # MasterFileError
+ #########################################################################
+ __filename = re.compile('[\"\']*([^\'\"]+)[\"\']*')
+ def __include(self, s):
+ first, rest = pop(s)
+ if re.match('\$include', first, re.I):
+ m = self.__filename.match(rest)
+ if m:
+ file = m.group(1)
+ return file
+
+ #########################################################################
+ # try parsing an RR on the assumption that the type is specified in
+ # field 4, and name, ttl and class are in fields 1-3
+ # are all specified, with type in field 4
+ # input:
+ # a record to parse, and the most recent name found in prior records
+ # returns:
+ # empty list if parse failed, else name, ttl, class, type, rdata
+ #########################################################################
+ def __four(self, record, curname):
+ ret = ''
+ list = record.split()
+ if len(list) <= 4:
+ return ret
+ if istype(list[3]):
+ if isclass(list[2]) and isttl(list[1]) and isname(list[0]):
+ name, ttl, rrclass, rrtype = list[0:4]
+ rdata = ' '.join(list[4:])
+ ret = name, ttl, rrclass, rrtype, rdata
return ret
- if istype(list[3]):
- if isclass(list[2]) and isttl(list[1]) and isname(list[0]):
- name, ttl, rrclass, rrtype = list[0:4]
- rdata = ' '.join(list[4:])
+
+ #########################################################################
+ # try parsing an RR on the assumption that the type is specified
+ # in field 3, and one of name, ttl, or class has been omitted
+ # input:
+ # a record to parse, and the most recent name found in prior records
+ # returns:
+ # empty list if parse failed, else name, ttl, class, type, rdata
+ #########################################################################
+ def __three(self, record, curname):
+ ret = ''
+ list = record.split()
+ if len(list) <= 3:
+ return ret
+ if istype(list[2]) and not istype(list[1]):
+ if isclass(list[1]) and not isttl(list[0]) and isname(list[0]):
+ rrclass = list[1]
+ ttl = self.__defttl
+ name = list[0]
+ elif not isclass(list[1]) and isttl(list[1]) and isname(list[0]):
+ rrclass = self.__defclass
+ ttl = parse_ttl(list[1])
+ name = list[0]
+ elif curname and isclass(list[1]) and isttl(list[0]):
+ rrclass = self.__defclass
+ ttl = parse_ttl(list[0])
+ name = curname
+ else:
+ return ret
+
+ rrtype = list[2]
+ rdata = ' '.join(list[3:])
ret = name, ttl, rrclass, rrtype, rdata
- return ret
-
-#########################################################################
-# three: try parsing on the assumption that the RR type is specified in
-# field 3, and one of name, ttl, or class has been omitted
-# input:
-# a record to parse, and the most recent name found in prior records
-# returns:
-# empty list if parse failed, else name, ttl, class, type, rdata
-#########################################################################
-def three(record, curname):
- global defttl, defclass
- ret = ''
- list = record.split()
- if len(list) <= 3:
return ret
- if istype(list[2]) and not istype(list[1]):
- if isclass(list[1]) and not isttl(list[0]) and isname(list[0]):
- rrclass = list[1]
- ttl = defttl
- name = list[0]
- elif not isclass(list[1]) and isttl(list[1]) and isname(list[0]):
- rrclass = defclass
- ttl = parse_ttl(list[1])
- name = list[0]
- elif curname and isclass(list[1]) and isttl(list[0]):
- rrclass = defclass
- ttl = parse_ttl(list[0])
- name = curname
- else:
+
+ #########################################################################
+ # try parsing an RR on the assumption that the type is specified in
+ # field 2, and field 1 is either name or ttl
+ # input:
+ # a record to parse, and the most recent name found in prior records
+ # returns:
+ # empty list if parse failed, else name, ttl, class, type, rdata
+ # throws:
+ # MasterFileError
+ #########################################################################
+ def __two(self, record, curname):
+ ret = ''
+ list = record.split()
+ if len(list) <= 2:
return ret
- rrtype = list[2]
- rdata = ' '.join(list[3:])
- ret = name, ttl, rrclass, rrtype, rdata
- return ret
-
-#########################################################################
-# two: try parsing on the assumption that the RR type is specified in
-# field 2, and field 1 is either name or ttl
-# input:
-# a record to parse, and the most recent name found in prior records
-# returns:
-# empty list if parse failed, else name, ttl, class, type, rdata
-# throws:
-# MasterFileError
-#########################################################################
-def two(record, curname):
- global defttl, defclass
- ret = ''
- list = record.split()
- if len(list) <= 2:
+ if istype(list[1]):
+ rrclass = self.__defclass
+ rrtype = list[1]
+ if list[0].lower() == 'rrsig':
+ name = curname
+ ttl = self.__defttl
+ rrtype = list[0]
+ rdata = ' '.join(list[1:])
+ elif isttl(list[0]):
+ ttl = parse_ttl(list[0])
+ name = curname
+ rdata = ' '.join(list[2:])
+ elif isname(list[0]):
+ name = list[0]
+ ttl = self.__defttl
+ rdata = ' '.join(list[2:])
+ else:
+ raise MasterFileError("Cannot parse RR: " + record)
+
+ ret = name, ttl, rrclass, rrtype, rdata
+
return ret
- if istype(list[1]):
- rrclass = defclass
- rrtype = list[1]
- if list[0].lower() == 'rrsig':
- name = curname
- ttl = defttl
- rrtype = list[0]
- rdata = ' '.join(list[1:])
- elif isttl(list[0]):
- ttl = parse_ttl(list[0])
- name = curname
- rdata = ' '.join(list[2:])
- elif isname(list[0]):
- name = list[0]
- ttl = defttl
- rdata = ' '.join(list[2:])
- else:
- raise MasterFileError("Cannot parse RR: " + record)
-
- ret = name, ttl, rrclass, rrtype, rdata
-
- return ret
-
-
-#########################################################################
-# reset: reset the state of the master file parser; use when parsing
-# more than one file
-#########################################################################
-def reset():
- global defttl, origin
- defttl = ''
- origin = ''
-
-#########################################################################
-# openzone: open a zone master file, set initial origin, return descriptor
-#########################################################################
-def openzone(filename, initial_origin = ''):
- global origin
- try:
- zf = open(filename, 'r')
- except:
- raise MasterFileError("Could not open " + filename)
- if initial_origin == '.':
- initial_origin = ''
- origin = initial_origin
- return zf
-
-#########################################################################
-# zonedata: generator function to parse a zone master file and return
-# each RR as a (name, ttl, type, class, rdata) tuple
-#########################################################################
-def zonedata(zone):
- global defttl, origin, defclass
-
- name = ''
-
- for record in records(zone):
- if directive(record):
- continue
-
- incl = include(record)
- if incl:
- sub = openzone(incl, origin)
- for name, ttl, rrclass, rrtype, rdata in zonedata(sub):
- yield (name, ttl, rrclass, rrtype, rdata)
- sub.close()
- continue
-
- # replace @ with origin
- rl = record.split()
- if rl[0] == '@':
- rl[0] = origin
- if not origin:
- rl[0] = '.'
- record = ' '.join(rl)
-
- result = four(record, name)
-
- if not result:
- result = three(record, name)
-
- if not result:
- result = two(record, name)
-
- if not result:
- first, rdata = pop(record)
- if istype(first):
- result = name, defttl, defclass, first, rdata
-
- if not result:
- raise MasterFileError("Cannot parse RR: " + record)
-
- name, ttl, rrclass, rrtype, rdata = result
- if name[-1] != '.':
- name += '.' + origin
-
- if rrclass.upper() != 'IN':
- raise MasterFileError("CH and HS zones not supported")
-
- if not ttl:
- raise MasterFileError("No TTL specified; zone rejected")
-
- # add origin to rdata containing names, if necessary
- if rrtype.lower() in ('cname', 'dname', 'ns', 'ptr'):
- if not isname(rdata):
- raise MasterFileError("Invalid " + rrtype + ": " + rdata)
- if rdata[-1] != '.':
- rdata += '.' + origin
- if rrtype.lower() == 'soa':
- soa = rdata.split()
- if len(soa) < 2 or not isname(soa[0]) or not isname(soa[1]):
- raise MasterFileError("Invalid " + rrtype + ": " + rdata)
- if soa[0][-1] != '.':
- soa[0] += '.' + origin
- if soa[1][-1] != '.':
- soa[1] += '.' + origin
- rdata = ' '.join(soa)
- if rrtype.lower() == 'mx':
- mx = rdata.split()
- if len(mx) != 2 or not isname(mx[1]):
- raise MasterFileError("Invalid " + rrtype + ": " + rdata)
- if mx[1][-1] != '.':
- mx[1] += '.' + origin
- rdata = ' '.join(mx)
-
- yield (name, ttl, rrclass, rrtype, rdata)
-
-#########################################################################
-# zonename: scans zone data for an SOA record, returns its name, restores
-# the zone file to its prior state
-#########################################################################
-def zonename(zone, initial_origin = ''):
- global origin
- old_origin = origin
- if initial_origin == '.':
- initial_origin = ''
- origin = initial_origin
- old_location = zone.tell()
- zone.seek(0)
- for name, ttl, rrclass, rrtype, rdata in zonedata(zone):
- if rrtype.lower() == 'soa':
- break
- zone.seek(old_location)
- origin = old_origin
- if rrtype.lower() != 'soa':
- raise MasterFileError("No SOA found")
- return name
+ #########################################################################
+ # zonedata: generator function to parse a zone master file and return
+ # each RR as a (name, ttl, type, class, rdata) tuple
+ #########################################################################
+ def zonedata(self):
+ name = ''
+
+ for record in records(self.__zonefile):
+ if self.__directive(record):
+ continue
+
+ incl = self.__include(record)
+ if incl:
+ sub = MasterFile(incl, self.__origin)
+ for name, ttl, rrclass, rrtype, rdata in sub.zonedata():
+ yield (name, ttl, rrclass, rrtype, rdata)
+ del sub
+ continue
+
+ # replace @ with origin
+ rl = record.split()
+ if rl[0] == '@':
+ rl[0] = self.__origin
+ if not self.__origin:
+ rl[0] = '.'
+ record = ' '.join(rl)
+
+ result = self.__four(record, name)
+
+ if not result:
+ result = self.__three(record, name)
+
+ if not result:
+ result = self.__two(record, name)
+
+ if not result:
+ first, rdata = pop(record)
+ if istype(first):
+ result = name, self.__defttl, self.__defclass, first, rdata
+
+ if not result:
+ raise MasterFileError("Cannot parse RR: " + record)
+
+ name, ttl, rrclass, rrtype, rdata = result
+ if name[-1] != '.':
+ name += '.' + self.__origin
+
+ if rrclass.lower() != 'in':
+ raise MasterFileError("CH and HS zones not supported")
+
+ if not ttl:
+ raise MasterFileError("No TTL specified; zone rejected")
+
+ # add origin to rdata containing names, if necessary
+ if rrtype.lower() in ('cname', 'dname', 'ns', 'ptr'):
+ if not isname(rdata):
+ raise MasterFileError("Invalid " + rrtype + ": " + rdata)
+ if rdata[-1] != '.':
+ rdata += '.' + self.__origin
+ if rrtype.lower() == 'soa':
+ soa = rdata.split()
+ if len(soa) < 2 or not isname(soa[0]) or not isname(soa[1]):
+ raise MasterFileError("Invalid " + rrtype + ": " + rdata)
+ if soa[0][-1] != '.':
+ soa[0] += '.' + self.__origin
+ if soa[1][-1] != '.':
+ soa[1] += '.' + self.__origin
+ rdata = ' '.join(soa)
+ if rrtype.lower() == 'mx':
+ mx = rdata.split()
+ if len(mx) != 2 or not isname(mx[1]):
+ raise MasterFileError("Invalid " + rrtype + ": " + rdata)
+ if mx[1][-1] != '.':
+ mx[1] += '.' + self.__origin
+ rdata = ' '.join(mx)
+
+ yield (name, ttl, rrclass, rrtype, rdata)
+
+ #########################################################################
+ # zonename: scans zone data for an SOA record, returns its name, restores
+ # the zone file to its prior state
+ #########################################################################
+ def zonename(self):
+ if self.__name:
+ return self.__name
+ old_origin = self.__origin
+ self.__origin = self.__initial_origin
+ old_location = self.__zonefile.tell()
+ self.__zonefile.seek(0)
+ for name, ttl, rrclass, rrtype, rdata in self.zonedata():
+ if rrtype.lower() == 'soa':
+ break
+ self.__zonefile.seek(old_location)
+ self.__origin = old_origin
+ if rrtype.lower() != 'soa':
+ raise MasterFileError("No SOA found")
+ self.__name = name
+ return name
+
+ #########################################################################
+ # reset: reset the state of the master file
+ #########################################################################
+ def reset(self):
+ self.__zonefile.seek(0)
+ self.__origin = self.__initial_origin
+ self.__defttl = ''
#########################################################################
# main: used for testing; parse a zone file and print out each record
@@ -467,20 +463,17 @@
file = sys.argv[1]
except:
file = 'testfile'
- zf = openzone(file, '.')
- print ('zone name: ' + zonename(zf))
+ master = MasterFile(file, '.')
+ print ('zone name: ' + master.zonename())
print ('---------------------')
- for name, ttl, rrclass, rrtype, rdata in zonedata(zf):
+ for name, ttl, rrclass, rrtype, rdata in master.zonedata():
print ('name: ' + name)
print ('ttl: ' + str(ttl))
print ('rrclass: ' + rrclass)
print ('rrtype: ' + rrtype)
print ('rdata: ' + rdata)
print ('---------------------')
- zf.close()
-
-# initialize
-reset()
+ del master
if __name__ == "__main__":
main()
Modified: trunk/src/lib/python/isc/auth/sqlite3_ds.py
==============================================================================
--- trunk/src/lib/python/isc/auth/sqlite3_ds.py (original)
+++ trunk/src/lib/python/isc/auth/sqlite3_ds.py Wed Mar 10 06:56:47 2010
@@ -119,9 +119,10 @@
# input:
# dbfile: the sqlite3 database fileanme
# zone: the zone origin
-# zonedata: an iterable set of name/ttl/class/rrtype/rdata-text tuples
+# reader: an generator function producing an iterable set of
+# name/ttl/class/rrtype/rdata-text tuples
#########################################################################
-def load(dbfile, zone, reader, file):
+def load(dbfile, zone, reader):
conn, cur = open(dbfile)
old_zone_id = get_zoneid(zone, cur)
@@ -130,7 +131,7 @@
new_zone_id = cur.lastrowid
try:
- for name, ttl, rdclass, rdtype, rdata in reader(file):
+ for name, ttl, rdclass, rdtype, rdata in reader():
sigtype = ''
if rdtype.lower() == 'rrsig':
sigtype = rdata.split()[0]
More information about the bind10-changes
mailing list