dexter has uploaded this change for review.
pySim-shell: enable export of DF and ADF files
Since we now have the ability to provide export methods for all files
in the file system (this also includes DF and ADF files), we need
to support this at shell command level as well.
Related: OS#6092
Change-Id: I3ee661dbae5c11fec23911775f352ac13bc2c6e5
---
M pySim-shell.py
1 file changed, 82 insertions(+), 11 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/41/37641/1
diff --git a/pySim-shell.py b/pySim-shell.py
index 168c916..8fc348e 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -494,12 +494,22 @@
self._cmd.poutput(directory_str)
self._cmd.poutput("%d files" % len(selectables))
+ def _walk_action(self, action, file, context, **kwargs):
+ df_before_action = self._cmd.lchan.selected_file
+ action(file, context, **kwargs)
+ # When walking through the file system tree the action must not
+ # always restore the currently selected file to the file that
+ # was selected before executing the action() callback.
+ if df_before_action != self._cmd.lchan.selected_file:
+ raise RuntimeError("inconsistent walk, %s is currently selected but expecting %s to be selected"
+ % (str(self._cmd.lchan.selected_file), str(df_before_action)))
+
def walk(self, indent=0, action_ef=None, action_df=None, context=None, **kwargs):
"""Recursively walk through the file system, starting at the currently selected DF"""
if isinstance(self._cmd.lchan.selected_file, CardDF):
if action_df:
- action_df(context, **kwargs)
+ self._walk_action(action_df, self._cmd.lchan.selected_file.name, context, **kwargs)
files = self._cmd.lchan.selected_file.get_selectables(
flags=['FNAMES', 'ANAMES'])
@@ -536,14 +546,7 @@
self._cmd.lchan.select_parent(self._cmd)
elif action_ef:
- df_before_action = self._cmd.lchan.selected_file
- action_ef(f, context, **kwargs)
- # When walking through the file system tree the action must not
- # always restore the currently selected file to the file that
- # was selected before executing the action() callback.
- if df_before_action != self._cmd.lchan.selected_file:
- raise RuntimeError("inconsistent walk, %s is currently selected but expecting %s to be selected"
- % (str(self._cmd.lchan.selected_file), str(df_before_action)))
+ self._walk_action(action_ef, f, context, **kwargs)
def do_tree(self, opts):
"""Display a filesystem-tree with all selectable files"""
@@ -594,11 +597,58 @@
self._cmd.poutput("#")
+ def export_df(self, filename, context, as_json):
+ """ Select and export a single application dedicated file (ADF) """
+ context['COUNT'] += 1
+ df = self._cmd.lchan.selected_file
+
+ # The currently selected file (not the file we are going to export)
+ # must always be an ADF or DF. From this starting point we select
+ # the ADF we want to export. To maintain consistency we will then
+ # select the current DF again (see comment below).
+ if not isinstance(df, CardDF):
+ raise RuntimeError(
+ "currently selected file %s is not a DF or ADF" % str(df))
+
+ df_path_list = df.fully_qualified_path(True)
+ df_path = df.fully_qualified_path_str(True)
+ df_path_fid = df.fully_qualified_path_str(False)
+
+ file_str = df_path + "/" + str(filename)
+ self._cmd.poutput(boxed_heading_str(file_str))
+
+ self._cmd.poutput("# directory: %s (%s)" % (df_path, df_path_fid))
+ try:
+ fcp_dec = self._cmd.lchan.select(filename, self._cmd)
+ self._cmd.poutput("# file: %s (%s)" %
+ (self._cmd.lchan.selected_file.name, self._cmd.lchan.selected_file.aid))
+ self._cmd.poutput("# RAW FCP Template: %s" % str(self._cmd.lchan.selected_file_fcp_hex))
+ self._cmd.poutput("# Decoded FCP Template: %s" % str(self._cmd.lchan.selected_file_fcp))
+ self._cmd.poutput("select " + self._cmd.lchan.selected_file.fully_qualified_path_str())
+ self._cmd.poutput(self._cmd.lchan.selected_file.export(as_json, self._cmd.lchan))
+
+ except Exception as e:
+ bad_file_str = df_path + "/" + str(filename) + ", " + str(e)
+ self._cmd.poutput("# bad file: %s" % bad_file_str)
+ context['ERR'] += 1
+ context['BAD'].append(bad_file_str)
+
+ # When reading the file is done, make sure the parent file is
+ # selected again. This will be the usual case, however we need
+ # to check before since we must not select the same DF twice
+ if df != self._cmd.lchan.selected_file:
+ self._cmd.lchan.select_parent(self._cmd)
+
+ self._cmd.poutput("#")
+
+
export_parser = argparse.ArgumentParser()
export_parser.add_argument(
'--filename', type=str, default=None, help='only export specific file')
export_parser.add_argument(
'--json', action='store_true', help='export as JSON (less reliable)')
+ export_parser.add_argument(
+ '--include_df', action='store_true', help='also export DF and ADF files (where possible)')
@cmd2.with_argparser(export_parser)
def do_export(self, opts):
@@ -609,10 +659,17 @@
exception_str_add = ""
if opts.filename:
- self.export_ef(opts.filename, context, **kwargs_export)
+ file = self._cmd.lchan.get_file_for_filename(opts.filename)
+ if isinstance(file, CardDF):
+ self.export_df(opts.filename, context, **kwargs_export)
+ else:
+ self.export_ef(opts.filename, context, **kwargs_export)
else:
try:
- self.walk(0, self.export_ef, None, context, **kwargs_export)
+ if opts.include_df:
+ self.walk(0, self.export_ef, self.export_df, context, **kwargs_export)
+ else:
+ self.walk(0, self.export_ef, None, context, **kwargs_export)
except Exception as e:
print("# Stopping early here due to exception: " + str(e))
print("#")
To view, visit change 37641. To unsubscribe, or for help writing mail filters, visit settings.