Coverage for diffoscope/comparators/iso9660.py: 62%
52 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-07 13:38 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-07 13:38 +0000
1#
2# diffoscope: in-depth comparison of files, archives, and directories
3#
4# Copyright © 2015 Jérémy Bobbio <lunar@debian.org>
5# Copyright © 2015-2020 Chris Lamb <lamby@debian.org>
6#
7# diffoscope is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# diffoscope is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
20import re
21import subprocess
23from diffoscope.tools import tool_required
24from diffoscope.difference import Difference
26from .utils.file import File
27from .utils.command import Command, our_check_output
28from .utils.libarchive import LibarchiveContainerWithFilelist
31@tool_required("isoinfo")
32def get_iso9660_names(path):
33 return (
34 our_check_output(
35 (
36 "isoinfo",
37 "-R", # Always use RockRidge for names
38 "-f",
39 "-i",
40 path,
41 ),
42 )
43 .strip()
44 .split("\n")
45 )
48class ISO9660PVD(Command):
49 @tool_required("isoinfo")
50 def cmdline(self):
51 return ["isoinfo", "-d", "-i", self.path]
54class ISO9660Listing(Command):
55 def __init__(self, path, extension=None, *args, **kwargs):
56 self._extension = extension
57 super().__init__(path, *args, **kwargs)
59 @tool_required("isoinfo")
60 def cmdline(self):
61 cmd = ["isoinfo", "-l", "-i", self.path]
63 if self._extension == "joliet":
64 cmd.extend(["-J", "-j", "iso8859-15"])
65 elif self._extension == "rockridge":
66 cmd.extend(["-R"])
68 return cmd
70 def filter(self, line):
71 if self._extension == "joliet":
72 return line.decode("iso-8859-15").encode("utf-8")
73 return line
76class Iso9660File(File):
77 DESCRIPTION = "ISO 9660 CD images"
78 CONTAINER_CLASSES = [LibarchiveContainerWithFilelist]
79 FILE_TYPE_RE = re.compile(r"\bISO 9660\b")
81 @classmethod
82 def recognizes(cls, file):
83 if file.magic_file_type and cls.FILE_TYPE_RE.search(
84 file.magic_file_type
85 ):
86 return True
88 # Sometimes CDs put things like MBRs at the front which is an expected
89 # part of the ISO9660 standard, but file(1)/libmagic doesn't detect
90 # this. <https://en.wikipedia.org/wiki/ISO_9660#Specifications>.
91 with open(file.path, "rb") as f:
92 f.seek(32769)
93 return f.read(5) == b"CD001"
95 return False
97 def compare_details(self, other, source=None):
98 differences = []
100 for klass in (ISO9660PVD, ISO9660Listing):
101 differences.append(
102 Difference.from_operation(klass, self.path, other.path)
103 )
105 for x in ("joliet", "rockridge"):
106 try:
107 differences.append(
108 Difference.from_operation(
109 ISO9660Listing,
110 self.path,
111 other.path,
112 operation_args=(x,),
113 )
114 )
115 except subprocess.CalledProcessError:
116 # Probably no joliet or rockridge data
117 pass
119 return differences