Skip to content

Commit 45d0023

Browse files
committed
dd sha256 validation
1 parent 3fd629e commit 45d0023

File tree

1 file changed

+60
-16
lines changed

1 file changed

+60
-16
lines changed

apt-sync.py

+60-16
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
DOWNLOAD_TIMEOUT=int(os.getenv('DOWNLOAD_TIMEOUT', '1800'))
3535
REPO_SIZE_FILE = os.getenv('REPO_SIZE_FILE', '')
3636

37+
package_info = {}
38+
3739
pattern_os_template = re.compile(r"@\{(.+)\}")
3840
pattern_package_name = re.compile(r"^Filename: (.+)$", re.MULTILINE)
3941
pattern_package_size = re.compile(r"^Size: (\d+)$", re.MULTILINE)
@@ -98,6 +100,38 @@ def mkdir_with_dot_tmp(folder: Path)->Tuple[Path, Path]:
98100
shutil.rmtree(str(tmpdir))
99101
tmpdir.mkdir(parents=True, exist_ok=True)
100102
return (folder, tmpdir)
103+
104+
def flush_package_info(content: str):
105+
106+
global package_info
107+
108+
for pkg in content.split('\n\n'):
109+
if len(pkg) < 10: # ignore blanks
110+
continue
111+
try:
112+
pkg_filename = pattern_package_name.search(pkg).group(1)
113+
pkg_size = int(pattern_package_size.search(pkg).group(1))
114+
pkg_checksum = pattern_package_sha256.search(pkg).group(1)
115+
if pkg_filename not in package_info:
116+
pkg_info = {
117+
'size': pkg_size,
118+
'sha256': {
119+
'new': pkg_checksum,
120+
'old': None
121+
}
122+
}
123+
else:
124+
pkg_info = package_info[pkg_filename]
125+
pkg_info['size'] = pkg_size
126+
if pkg_info['sha256']['new'] is not None and pkg_info['sha256']['old'] is None:
127+
pkg_info['sha256']['old'] = pkg_checksum
128+
package_info.update({
129+
pkg_filename: pkg_info
130+
})
131+
except:
132+
print("Failed to parse one package description", flush=True)
133+
traceback.print_exc()
134+
return 1
101135

102136
def move_files_in(src: Path, dst: Path):
103137
empty = True
@@ -110,6 +144,9 @@ def move_files_in(src: Path, dst: Path):
110144
print(f"{src} is empty")
111145

112146
def apt_mirror(base_url: str, dist: str, repo: str, arch: str, dest_base_dir: Path, deb_set: Dict[str, int])->int:
147+
148+
global package_info
149+
113150
if not dest_base_dir.is_dir():
114151
print("Destination directory is empty, cannot continue")
115152
return 1
@@ -134,6 +171,7 @@ def apt_mirror(base_url: str, dist: str, repo: str, arch: str, dest_base_dir: Pa
134171
pkgidx_dir,pkgidx_tmp_dir = mkdir_with_dot_tmp(comp_dir / arch_dir)
135172
with open(release_file, "r") as fd:
136173
pkgidx_content=None
174+
pkgidx_file_old = None
137175
cnt_start=False
138176
for line in fd:
139177
if cnt_start:
@@ -146,6 +184,8 @@ def apt_mirror(base_url: str, dist: str, repo: str, arch: str, dest_base_dir: Pa
146184
filename.startswith(f"Contents-{arch}"):
147185
fn = Path(filename)
148186
pkgidx_file = dist_dir / fn.parent / ".tmp" / fn.name
187+
if pkgidx_file.stem == 'Packages' and pkgidx_file.suffix == '':
188+
pkgidx_file_old = Path(f'{dist_dir}/{filename}')
149189
else:
150190
print(f"Ignore the file {filename}")
151191
continue
@@ -176,12 +216,25 @@ def apt_mirror(base_url: str, dist: str, repo: str, arch: str, dest_base_dir: Pa
176216
pkgidx_content = content.decode('utf-8')
177217
else:
178218
print("unsupported format")
219+
continue
220+
221+
flush_package_info(pkgidx_content)
222+
223+
with pkgidx_file_old.open('rb') as t: content = t.read()
224+
if pkgidx_file_old.stem == 'Packages':
225+
print(f"getting packages index content from s {pkgidx_file_old.name}", flush=True)
226+
pkgidx_content_old = content.decode('utf-8')
227+
print(pkgidx_content_old)
228+
229+
flush_package_info(pkgidx_content_old)
230+
179231

180232
# Currently only support SHA-256 checksum, because
181233
# "Clients may not use the MD5Sum and SHA1 fields for security purposes, and must require a SHA256 or a SHA512 field."
182234
# from https://wiki.debian.org/DebianRepository/Format#A.22Release.22_files
183235
if line.startswith('SHA256:'):
184236
cnt_start = True
237+
185238
if not cnt_start:
186239
print("Cannot find SHA-256 checksum")
187240
return 1
@@ -216,18 +269,9 @@ def collect_tmp_dir():
216269
err = 0
217270
deb_count = 0
218271
deb_size = 0
219-
for pkg in pkgidx_content.split('\n\n'):
220-
if len(pkg) < 10: # ignore blanks
221-
continue
222-
try:
223-
pkg_filename = pattern_package_name.search(pkg).group(1)
224-
pkg_size = int(pattern_package_size.search(pkg).group(1))
225-
pkg_checksum = pattern_package_sha256.search(pkg).group(1)
226-
except:
227-
print("Failed to parse one package description", flush=True)
228-
traceback.print_exc()
229-
err = 1
230-
continue
272+
for pkg_filename, pkg_info in package_info.items():
273+
pkg_size = pkg_info['size']
274+
pkg_checksum = pkg_info['sha256']
231275
deb_count += 1
232276
deb_size += pkg_size
233277

@@ -237,8 +281,8 @@ def collect_tmp_dir():
237281
dest_dir.mkdir(parents=True, exist_ok=True)
238282
if dest_filename.suffix == '.deb':
239283
deb_set[str(dest_filename.relative_to(dest_base_dir))] = pkg_size
240-
if dest_filename.is_file() and dest_filename.stat().st_size == pkg_size:
241-
print(f"Skipping {pkg_filename}, size {pkg_size}")
284+
if dest_filename.is_file() and ( dest_filename.stat().st_size == pkg_size and pkg_checksum['old'] == pkg_checksum['new']):
285+
print(f"Skipping {pkg_filename}, size {pkg_size}, sha256 {pkg_checksum['new']}")
242286
continue
243287

244288
pkg_url=f"{base_url}/{pkg_filename}"
@@ -253,8 +297,8 @@ def collect_tmp_dir():
253297
with dest_tmp_filename.open("rb") as f:
254298
for block in iter(lambda: f.read(1024**2), b""):
255299
sha.update(block)
256-
if sha.hexdigest() != pkg_checksum:
257-
print(f"Invalid checksum of {dest_filename}, expected {pkg_checksum}")
300+
if sha.hexdigest() != pkg_checksum['new']:
301+
print(f"Invalid checksum of {dest_filename}, expected {pkg_checksum['new']}")
258302
dest_tmp_filename.unlink()
259303
continue
260304
dest_tmp_filename.rename(dest_filename)

0 commit comments

Comments
 (0)