From 8fdee1e46065036caff72194ad887b14638effb8 Mon Sep 17 00:00:00 2001 From: hedger Date: Thu, 13 Oct 2022 19:05:07 +0400 Subject: [PATCH] Scripts: simpler tar format (#1871) * scriptsL simpler tar format * scripts: shorter names for files in update bundle * scripts: limiting max OTA package dir name length to 80 * scripts: resource bundle: checks for file name length * scripts: made resource packing errors critical --- scripts/flipper/assets/copro.py | 2 +- scripts/sconsdist.py | 6 +++++- scripts/update.py | 37 +++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/scripts/flipper/assets/copro.py b/scripts/flipper/assets/copro.py index 33c3ac23..d39f3033 100644 --- a/scripts/flipper/assets/copro.py +++ b/scripts/flipper/assets/copro.py @@ -60,7 +60,7 @@ class Copro: array.append({"name": filename, "sha256": file_sha256(source_file), **kwargs}) def bundle(self, output_file, stack_file_name, stack_type, stack_addr=None): - self.output_tar = tarfile.open(output_file, "w:gz") + self.output_tar = tarfile.open(output_file, "w:gz", format=tarfile.USTAR_FORMAT) stack_file = os.path.join(self.mcu_copro, stack_file_name) # Form Manifest diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index 45ae03e3..cb4f8f5a 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -20,6 +20,7 @@ class ProjectDir: class Main(App): DIST_FILE_PREFIX = "flipper-z-" + DIST_FOLDER_MAX_NAME_LENGTH = 80 def init(self): self.subparsers = self.parser.add_subparsers(help="sub-command help") @@ -129,7 +130,9 @@ class Main(App): ) if self.args.version: - bundle_dir_name = f"{self.target}-update-{self.args.suffix}" + bundle_dir_name = f"{self.target}-update-{self.args.suffix}"[ + : self.DIST_FOLDER_MAX_NAME_LENGTH + ] bundle_dir = join(self.output_dir_path, bundle_dir_name) bundle_args = [ "generate", @@ -170,6 +173,7 @@ class Main(App): ), "w:gz", compresslevel=9, + format=tarfile.USTAR_FORMAT, ) as tar: tar.add(bundle_dir, arcname=bundle_dir_name) diff --git a/scripts/update.py b/scripts/update.py index 52391965..6be1dce0 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -22,6 +22,7 @@ class Main(App): RESOURCE_TAR_MODE = "w:" RESOURCE_TAR_FORMAT = tarfile.USTAR_FORMAT RESOURCE_FILE_NAME = "resources.tar" + RESOURCE_ENTRY_NAME_MAX_LENGTH = 100 WHITELISTED_STACK_TYPES = set( map( @@ -76,9 +77,9 @@ class Main(App): self.parser_generate.set_defaults(func=self.generate) def generate(self): - stage_basename = basename(self.args.stage) - dfu_basename = basename(self.args.dfu) - radiobin_basename = basename(self.args.radiobin) + stage_basename = "updater.bin" # used to be basename(self.args.stage) + dfu_basename = "firmware.dfu" # used to be basename(self.args.dfu) + radiobin_basename = "radio.bin" # used to be basename(self.args.radiobin) resources_basename = "" radio_version = 0 @@ -120,9 +121,10 @@ class Main(App): ) if self.args.resources: resources_basename = self.RESOURCE_FILE_NAME - self.package_resources( + if not self.package_resources( self.args.resources, join(self.args.directory, resources_basename) - ) + ): + return 3 if not self.layout_check(dfu_size, radio_addr): self.logger.warn("Memory layout looks suspicious") @@ -199,11 +201,28 @@ class Main(App): "Please confirm that you REALLY want to do that with --I-understand-what-I-am-doing=yes" ) + def _tar_filter(self, tarinfo: tarfile.TarInfo): + if len(tarinfo.name) > self.RESOURCE_ENTRY_NAME_MAX_LENGTH: + self.logger.error( + f"Cannot package resource: name '{tarinfo.name}' too long" + ) + raise ValueError("Resource name too long") + return tarinfo + def package_resources(self, srcdir: str, dst_name: str): - with tarfile.open( - dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT - ) as tarball: - tarball.add(srcdir, arcname="") + try: + with tarfile.open( + dst_name, self.RESOURCE_TAR_MODE, format=self.RESOURCE_TAR_FORMAT + ) as tarball: + tarball.add( + srcdir, + arcname="", + filter=self._tar_filter, + ) + return True + except ValueError as e: + self.logger.error(f"Cannot package resources: {e}") + return False @staticmethod def copro_version_as_int(coprometa, stacktype):