Package PAR2Set and derived classes
[rarslave2.git] / Par2Parser.py
index c57d1e6..6940101 100644 (file)
@@ -43,60 +43,67 @@ def get_protected_files (dir, filename):
        expected_file_ids = None
        filenames = []
 
-       while 1:
-               d = file.read(pkt_header_size)
-               if not d:
-                       break
-
-               magic, pkt_len, pkt_md5, set_id, pkt_type = struct.unpack(pkt_header_fmt, d)
-
-               if docrcchecks:
-                       control_md5 = md5.new()
-                       control_md5.update(d[0x20:])
-                       d = file.read(pkt_len - pkt_header_size)
-                       control_md5.update(d)
+       # This try is here to ensure that we close the open file before
+       # returning. Since this code was (pretty much) borrowed verbatim
+       # from the cfv project, I didn't want to refactor it to make file
+       # closing more sane, so I just used a try / finally clause.
+       try:
+               while 1:
+                       d = file.read(pkt_header_size)
+                       if not d:
+                               break
 
-                       if control_md5.digest() != pkt_md5:
-                               raise EnvironmentError, (errno.EINVAL, \
-                                       "corrupt par2 file - bad packet hash")
+                       magic, pkt_len, pkt_md5, set_id, pkt_type = struct.unpack(pkt_header_fmt, d)
 
-               if pkt_type == 'PAR 2.0\0FileDesc':
-                       if not docrcchecks:
+                       if docrcchecks:
+                               control_md5 = md5.new()
+                               control_md5.update(d[0x20:])
                                d = file.read(pkt_len - pkt_header_size)
+                               control_md5.update(d)
 
-                       file_id, file_md5, file_md5_16k, file_size = \
-                               struct.unpack(file_pkt_fmt, d[:file_pkt_size])
+                               if control_md5.digest() != pkt_md5:
+                                       raise EnvironmentError, (errno.EINVAL, \
+                                               "corrupt par2 file - bad packet hash")
 
-                       if seen_file_ids.get(file_id) is None:
-                               seen_file_ids[file_id] = 1
-                               filename = chompnulls(d[file_pkt_size:])
-                               filenames.append(filename)
+                       if pkt_type == 'PAR 2.0\0FileDesc':
+                               if not docrcchecks:
+                                       d = file.read(pkt_len - pkt_header_size)
 
-               elif pkt_type == "PAR 2.0\0Main\0\0\0\0":
-                       if not docrcchecks:
-                               d = file.read(pkt_len - pkt_header_size)
+                               file_id, file_md5, file_md5_16k, file_size = \
+                                       struct.unpack(file_pkt_fmt, d[:file_pkt_size])
+
+                               if seen_file_ids.get(file_id) is None:
+                                       seen_file_ids[file_id] = 1
+                                       filename = chompnulls(d[file_pkt_size:])
+                                       filenames.append(filename)
 
-                       if expected_file_ids is None:
-                               expected_file_ids = []
-                               slice_size, num_files = struct.unpack(main_pkt_fmt, d[:main_pkt_size])
-                               num_nonrecovery = (len(d)-main_pkt_size)/16 - num_files
+                       elif pkt_type == "PAR 2.0\0Main\0\0\0\0":
+                               if not docrcchecks:
+                                       d = file.read(pkt_len - pkt_header_size)
 
-                               for i in range(main_pkt_size,main_pkt_size+(num_files+num_nonrecovery)*16,16):
-                                       expected_file_ids.append(d[i:i+16])
+                               if expected_file_ids is None:
+                                       expected_file_ids = []
+                                       slice_size, num_files = struct.unpack(main_pkt_fmt, d[:main_pkt_size])
+                                       num_nonrecovery = (len(d)-main_pkt_size)/16 - num_files
 
-               else:
-                       if not docrcchecks:
-                               file.seek(pkt_len - pkt_header_size, 1)
+                                       for i in range(main_pkt_size,main_pkt_size+(num_files+num_nonrecovery)*16,16):
+                                               expected_file_ids.append(d[i:i+16])
 
-       if expected_file_ids is None:
-               raise EnvironmentError, (errno.EINVAL, \
-                       "corrupt or unsupported par2 file - no main packet found")
+                       else:
+                               if not docrcchecks:
+                                       file.seek(pkt_len - pkt_header_size, 1)
 
-       for id in expected_file_ids:
-               if not seen_file_ids.has_key(id):
+               if expected_file_ids is None:
                        raise EnvironmentError, (errno.EINVAL, \
-                               "corrupt or unsupported par2 file - " \
-                               "expected file description packet not found")
+                               "corrupt or unsupported par2 file - no main packet found")
+
+               for id in expected_file_ids:
+                       if not seen_file_ids.has_key(id):
+                               raise EnvironmentError, (errno.EINVAL, \
+                                       "corrupt or unsupported par2 file - " \
+                                       "expected file description packet not found")
+       finally:
+               file.close ()
 
        return filenames