From 81958f7958bd48c1ff1785fe1561a42b9a8cb172 Mon Sep 17 00:00:00 2001 From: Andrei Gherzan Date: Fri, 6 Mar 2020 16:55:09 +0000 Subject: [PATCH] bmaptool: Implement flag to interact with psplash progress This flag is implemented as a best effort to avoid breaking the writing functionality when psplash is not available. For example when bmap is used during boot where psplash might or might not be available. Signed-off-by: Andrei Gherzan --- bmaptools/BmapCopy.py | 34 ++++++++++++++++++++++++++++++++++ bmaptools/CLI.py | 7 +++++++ 2 files changed, 41 insertions(+) diff --git a/bmaptools/BmapCopy.py b/bmaptools/BmapCopy.py index b0e251e..c6a2603 100644 --- a/bmaptools/BmapCopy.py +++ b/bmaptools/BmapCopy.py @@ -172,6 +172,7 @@ def __init__(self, image, dest, bmap=None, image_size=None): self._progress_file = None self._progress_format = None self.set_progress_indicator(None, None) + self._psplash_pipe = None self._f_image = image self._image_path = image.name @@ -211,6 +212,28 @@ def __init__(self, image, dest, bmap=None, image_size=None): self._batch_blocks = self._batch_bytes // self.block_size + def set_psplash_pipe(self, path): + """ + Set the psplash named pipe file path to be used when updating the + progress - best effort. + + The 'path' argument is the named pipe used by the psplash process to get + progress bar commands. When the path argument doesn't exist or is not a + pipe, the function will ignore with a warning. This behavior is + considered as such because the progress is considered a decoration + functionality which might or might not be available even if requested. + When used as a boot service, the unavailability of the psplash service + (due to various reasons: no screen, racing issues etc.) should not + break the writting process. This is why this implementation is done as + a best effort. + """ + + if os.path.exists(pipe) and stat.S_ISFIFO(os.stat(pipe).st_mode): + self._psplash_pipe = pipe + else: + _log.warning("'%s' is not a pipe, so psplash progress will not be " + "updated" % pipe) + def set_progress_indicator(self, file_obj, format_string): """ Setup the progress indicator which shows how much data has been copied @@ -404,6 +427,17 @@ def _update_progress(self, blocks_written): self._progress_file.write(progress) self._progress_file.flush() + # Update psplash progress when configured. This is using a best effort + # strategy to not affect the writing process when psplash breaks, is + # not available early enough or screen is not available. + if self._psplash_pipe and self.mapped_cnt: + try: + mode = os.O_WRONLY | os.O_NONBLOCK + with os.fdopen(os.open(self._psplash_pipe, mode), 'w') as p_fo: + p_fo.write("PROGRESS %d\n" % percent) + except: + pass + def _get_block_ranges(self): """ This is a helper generator that parses the bmap XML file and for each diff --git a/bmaptools/CLI.py b/bmaptools/CLI.py index 49a3d3f..4a39c04 100644 --- a/bmaptools/CLI.py +++ b/bmaptools/CLI.py @@ -482,6 +482,9 @@ def copy_command(args): % (os.path.basename(args.image), dest_str, os.path.basename(bmap_path))) + if args.psplash_pipe: + writer.set_psplash_pipe(args.psplash_pipe) + try: try: writer.copy(False, not args.no_verify) @@ -640,6 +643,10 @@ def parse_arguments(): text = "do not verify the data checksum while writing" parser_copy.add_argument("--no-verify", action="store_true", help=text) + # The --psplash-pipe option + text = "write progress to a psplash pipe" + parser_copy.add_argument("--psplash-pipe", help=text) + return parser.parse_args()