Skip to content

Commit a254b2c

Browse files
committed
Improve the extraction from the ChromeOS image. Now it fist tries the fast search, only if that fails it uses the slow but more reliable way.
1 parent f39da1f commit a254b2c

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

lib/inputstreamhelper/widevine/arm_chromeos.py

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,47 @@ def chromeos_offset(self):
7373

7474
return offset
7575

76-
def find_file(self, filename, path_to_file=("opt", "google", "chrome", "WidevineCdm", "_platform_specific", "cros_arm")):
76+
def _find_file_naive(self, filename):
7777
"""
78-
Finds a file at a given path, or search upwards if not found.
78+
Finds a file by basically searching for the filename as bytes in the bytestream.
79+
Searches through the whole image only once, making it fast, but may be unreliable at times.
80+
7981
Returns a directory entry.
82+
"""
83+
84+
bin_filename = filename.encode('ascii')
85+
chunksize = 4 * 1024**2
86+
chunk1 = self.read_stream(chunksize)
87+
while True:
88+
chunk2 = self.read_stream(chunksize)
89+
if not chunk2:
90+
raise ChromeOSError('File {filename} not found in the ChromeOS image'.format(filename=filename))
91+
92+
chunk = chunk1 + chunk2
93+
if bin_filename in chunk:
94+
i_index_pos = chunk.index(bin_filename) - 8
95+
file_entry = self.dir_entry(chunk[i_index_pos:i_index_pos + len(filename) + 8])
96+
if file_entry['inode'] < self.sb_dict['s_inodes_count'] and file_entry['name_len'] == len(filename):
97+
break
98+
99+
log(0, 'Found filename, but checks did not pass:')
100+
log(0, 'inode number: {inode} < {count}, name_len: {name_len} == {len_filename}'.format(inode=file_entry['inode'],
101+
count=self.sb_dict['s_inodes_count'],
102+
name_len=file_entry['name_len'],
103+
len_filename=len(filename)))
104+
105+
chunk1 = chunk2
106+
107+
return file_entry
108+
109+
def _find_file_properly(self, filename, path_to_file=("opt", "google", "chrome", "WidevineCdm", "_platform_specific", "cros_arm")):
110+
"""
111+
Finds a file at a given path, or searches upwards if not found.
80112
81113
Assumes the path is roughly correct, else it might take long.
114+
It also might take long for ZIP files, since it might have to jump back and forth while traversing down the given path.
115+
116+
Returns a directory entry.
82117
"""
83118
root_inode_pos = self._calc_inode_pos(2)
84119
root_inode_dict = self._inode_table(root_inode_pos)
@@ -107,10 +142,9 @@ def find_file(self, filename, path_to_file=("opt", "google", "chrome", "Widevine
107142
def _find_file_in_dir(self, filename, dentries):
108143
"""
109144
Finds a file in a directory or recursively in its subdirectories.
110-
Returns a directory entry.
111-
112145
Can take long for deep searches.
113-
Returns the first result.
146+
147+
Returns the first result as a directory entry.
114148
"""
115149
try:
116150
return dentries[filename]
@@ -128,6 +162,23 @@ def _find_file_in_dir(self, filename, dentries):
128162

129163
return None
130164

165+
def find_file(self, filename, path_to_file=None):
166+
"""
167+
Finds a file. Supplying a path could take longer for ZIP files!
168+
169+
Returns a directory entry.
170+
"""
171+
172+
if path_to_file:
173+
return self._find_file_properly(filename, path_to_file)
174+
175+
try:
176+
return self._find_file_naive(filename)
177+
except ChromeOSError:
178+
if self.progress:
179+
self.progress.update(5, localize(30071)) # Could not find file, doing proper search
180+
return self._find_file_properly(filename)
181+
131182
def _calc_inode_pos(self, inode_num):
132183
"""Calculate the byte position of an inode from its index"""
133184
blk_group_num = (inode_num - 1) // self.sb_dict['s_inodes_per_group']
@@ -223,10 +274,10 @@ def dir_entry(chunk):
223274
dir_names = ('inode', 'rec_len', 'name_len', 'file_type', 'name')
224275
dir_fmt = '<IHBB' + str(len(chunk) - 8) + 's'
225276

226-
dir_dict = dict(list(zip(dir_names, unpack(dir_fmt, chunk))))
227-
dir_dict["name"] = dir_dict["name"][:dir_dict["name_len"]]
277+
entry = dict(list(zip(dir_names, unpack(dir_fmt, chunk))))
278+
entry["name"] = entry["name"][:entry["name_len"]]
228279

229-
return dir_dict
280+
return entry
230281

231282
def dir_entries(self, dir_file):
232283
"""Returns all directory entries of a directory file as dict of dicts with name as key"""
@@ -371,11 +422,11 @@ def extract_file(self, filename, extract_path):
371422
try:
372423
if self.progress:
373424
self.progress.update(5, localize(30061))
374-
dir_dict = self.find_file(filename)
425+
file_entry = self.find_file(filename)
375426

376427
if self.progress:
377428
self.progress.update(32, localize(30062))
378-
inode_pos = self._calc_inode_pos(dir_dict["inode"])
429+
inode_pos = self._calc_inode_pos(file_entry["inode"])
379430
inode_dict = self._inode_table(inode_pos)
380431

381432
self.write_file(inode_dict, os.path.join(extract_path, filename))

resources/language/resource.language.en_gb/strings.po

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ msgctxt "#30070"
277277
msgid "Something seems wrong with the downloaded {filename}. Shall we try to continue anyway?"
278278
msgstr ""
279279

280+
msgctxt "#30071"
281+
msgid "Could not find the Widevine CDM by a quick scan. Now doing a proper search, but this might take very long..."
282+
msgstr ""
283+
280284

281285
### INFORMATION DIALOG
282286
msgctxt "#30800"

0 commit comments

Comments
 (0)