Fix long standing bug in lrf-meta that could cause corruption when setting metadata. This affects the 'Save to disk' and 'Send to device' actions

This commit is contained in:
Kovid Goyal 2008-05-24 17:25:33 -07:00
parent e0e796ebdd
commit 32bf0d62ed

View File

@ -12,7 +12,7 @@ to get and set meta information. For example:
>>> lrf.category = "History" >>> lrf.category = "History"
""" """
import struct, zlib, sys import struct, zlib, sys, os
from shutil import copyfileobj from shutil import copyfileobj
from cStringIO import StringIO from cStringIO import StringIO
import xml.dom.minidom as dom import xml.dom.minidom as dom
@ -147,6 +147,7 @@ class xml_field(object):
if not val: if not val:
val = '' val = ''
document = obj.info document = obj.info
def create_elem(): def create_elem():
elem = document.createElement(self.tag_name) elem = document.createElement(self.tag_name)
parent = document.getElementsByTagName(self.parent)[0] parent = document.getElementsByTagName(self.parent)[0]
@ -173,6 +174,7 @@ class xml_field(object):
else: else:
elem = create_elem() elem = create_elem()
elem.appendChild(document.createTextNode(val)) elem.appendChild(document.createTextNode(val))
obj.info = document obj.info = document
@ -370,6 +372,7 @@ class LRFMetaFile(object):
self.compressed_info_size = len(stream) + 4 self.compressed_info_size = len(stream) + 4
delta = insert_into_file(self._file, stream, self.info_start, \ delta = insert_into_file(self._file, stream, self.info_start, \
self.info_start + orig_size - 4) self.info_start + orig_size - 4)
self.toc_object_offset += delta self.toc_object_offset += delta
self.object_index_offset += delta self.object_index_offset += delta
self.update_object_offsets(delta) self.update_object_offsets(delta)
@ -441,27 +444,16 @@ class LRFMetaFile(object):
def update_object_offsets(self, delta): def update_object_offsets(self, delta):
""" Run through the LRF Object index changing the offset by C{delta}. """ """ Run through the LRF Object index changing the offset by C{delta}. """
self._file.seek(self.object_index_offset) self._file.seek(self.object_index_offset)
while(True): count = self.number_of_objects
try: while count > 0:
self._file.read(4) raw = self._file.read(8)
except EOFError: new_offset = struct.unpack(DWORD, raw[4:8])[0] + delta
break if new_offset >= (2**8)**4 or new_offset < 0x4C:
pos = self._file.tell() raise LRFException(_('Invalid LRF file. Could not set metadata.'))
try: self._file.seek(-4, os.SEEK_CUR)
offset = self.unpack(fmt=DWORD, start=pos)[0] + delta self._file.write(struct.pack(DWORD, new_offset))
except struct.error: self._file.seek(8, os.SEEK_CUR)
break count -= 1
if offset >= (2**8)**4:
# New offset is larger than a DWORD, so leave
# offset unchanged. I'm assuming offset is an offset from
# the previous object, otherwise this would impose a ~ 4MB limit
# on LRF files.
offset -= delta
self.pack(offset, fmt=DWORD, start=pos)
try:
self._file.read(12)
except EOFError:
break
self._file.flush() self._file.flush()
@safe @safe
@ -474,7 +466,6 @@ class LRFMetaFile(object):
""" """
end = start + struct.calcsize(fmt) end = start + struct.calcsize(fmt)
self._file.seek(start) self._file.seek(start)
self._file.seek(start)
ret = struct.unpack(fmt, self._file.read(end-start)) ret = struct.unpack(fmt, self._file.read(end-start))
return ret return ret