From ea8b9e22cbafe5a0179142d7480495ad7c1313ca Mon Sep 17 00:00:00 2001 From: doron zarhi Date: Thu, 22 Apr 2021 18:20:50 +0300 Subject: [PATCH] cli: afc: developer: add recusive option to all dirlists --- pymobiledevice3/cli/afc.py | 23 +++++--- pymobiledevice3/cli/developer.py | 11 ++-- pymobiledevice3/services/afc.py | 93 +++++++++++++++++--------------- 3 files changed, 72 insertions(+), 55 deletions(-) diff --git a/pymobiledevice3/cli/afc.py b/pymobiledevice3/cli/afc.py index 3629b736f..49de83f45 100644 --- a/pymobiledevice3/cli/afc.py +++ b/pymobiledevice3/cli/afc.py @@ -1,4 +1,4 @@ -from pprint import pprint +import posixpath import click @@ -28,7 +28,7 @@ def afc_shell(lockdown): @click.argument('remote_file', type=click.Path(exists=False)) @click.argument('local_file', type=click.File('wb')) def afc_pull(lockdown, remote_file, local_file): - """ open an AFC shell rooted at /var/mobile/Media """ + """ pull remote file from /var/mobile/Media """ local_file.write(AfcService(lockdown=lockdown).get_file_contents(remote_file)) @@ -36,19 +36,28 @@ def afc_pull(lockdown, remote_file, local_file): @click.argument('local_file', type=click.File('rb')) @click.argument('remote_file', type=click.Path(exists=False)) def afc_push(lockdown, local_file, remote_file): - """ open an AFC shell rooted at /var/mobile/Media """ + """ push local file into /var/mobile/Media """ AfcService(lockdown=lockdown).set_file_contents(remote_file, local_file.read()) +def show_dirlist(afc, dirname, recursive=False): + for filename in afc.listdir(dirname): + filename = posixpath.join(dirname, filename) + print(filename) + if recursive and afc.isdir(filename): + show_dirlist(afc, filename, recursive=recursive) + + @afc.command('ls', cls=Command) @click.argument('remote_file', type=click.Path(exists=False)) -def afc_ls(lockdown, remote_file): - """ open an AFC shell rooted at /var/mobile/Media """ - pprint(AfcService(lockdown=lockdown).listdir(remote_file)) +@click.option('-r', '--recursive', is_flag=True) +def afc_ls(lockdown, remote_file, recursive): + """ perform a dirlist rooted at /var/mobile/Media """ + show_dirlist(AfcService(lockdown=lockdown), remote_file, recursive=recursive) @afc.command('rm', cls=Command) @click.argument('remote_file', type=click.Path(exists=False)) def afc_rm(lockdown, remote_file): - """ open an AFC shell rooted at /var/mobile/Media """ + """ remove a file rooted at /var/mobile/Media """ AfcService(lockdown=lockdown).rm(remote_file) diff --git a/pymobiledevice3/cli/developer.py b/pymobiledevice3/cli/developer.py index aa3970701..f887b315d 100644 --- a/pymobiledevice3/cli/developer.py +++ b/pymobiledevice3/cli/developer.py @@ -1,12 +1,11 @@ import posixpath import shlex -from pprint import pprint import click +from pymobiledevice3.cli.cli_common import print_object, Command from pymobiledevice3.exceptions import DvtDirListError from pymobiledevice3.services.dvt_secure_socket_proxy import DvtSecureSocketProxyService -from pymobiledevice3.cli.cli_common import print_object, Command @click.group() @@ -75,7 +74,7 @@ def shell(lockdown): dvt.shell() -def show_dirlist(dvt, dirname, recusive=False): +def show_dirlist(dvt, dirname, recursive=False): try: filenames = dvt.ls(dirname) except DvtDirListError: @@ -84,8 +83,8 @@ def show_dirlist(dvt, dirname, recusive=False): for filename in filenames: filename = posixpath.join(dirname, filename) print(filename) - if recusive: - show_dirlist(dvt, filename, recusive=recusive) + if recursive: + show_dirlist(dvt, filename, recursive=recursive) @developer.command('ls', cls=Command) @@ -94,7 +93,7 @@ def show_dirlist(dvt, dirname, recusive=False): def ls(lockdown, path, recursive): """ List directory. """ with DvtSecureSocketProxyService(lockdown=lockdown) as dvt: - show_dirlist(dvt, path, recusive=recursive) + show_dirlist(dvt, path, recursive=recursive) @developer.command('device-information', cls=Command) diff --git a/pymobiledevice3/services/afc.py b/pymobiledevice3/services/afc.py index 8a10a81ba..3b84ffdda 100755 --- a/pymobiledevice3/services/afc.py +++ b/pymobiledevice3/services/afc.py @@ -474,57 +474,57 @@ def __init__(self, lockdown: LockdownClient, service_name='com.apple.afc', compl self.complete_ls = self._complete self._update_prompt() - def _update_prompt(self): - self.prompt = highlight(f'mobile@AFC ({self.curdir})$ ', lexers.BashSessionLexer(), - formatters.TerminalTrueColorFormatter(style='colorful')).strip() - - def do_exit(self, p): + def do_exit(self, args): return True - def do_quit(self, p): + def do_quit(self, args): return True - def do_pwd(self, p): + def do_pwd(self, args): print(self.curdir) @safe_cmd - def do_link(self, p): - z = p.split() + def do_link(self, args): + z = args.split() self.afc.link(afc_link_type_t.SYMLINK, z[0], z[1]) @safe_cmd - def do_cd(self, p): - if not p.startswith('/'): - new = posixpath.join(self.curdir, p) + def do_cd(self, args): + if not args.startswith('/'): + new = posixpath.join(self.curdir, args) else: - new = p + new = args - new = os.path.normpath(new).replace('\\', '/').replace('//', '/') + new = posixpath.normpath(new) if self.afc.listdir(new): self.curdir = new self._update_prompt() else: self.logger.error('%s does not exist', new) - def _complete(self, text, line, begidx, endidx): - dirname = posixpath.join(self.curdir, posixpath.dirname(text)) - prefix = posixpath.basename(text) - return [filename for filename in self.afc.listdir(dirname) if filename.startswith(prefix)] - @safe_cmd - def do_ls(self, p): - filename = posixpath.join(self.curdir, p) + def do_ls(self, args): + filename = posixpath.join(self.curdir, args) if self.curdir.endswith('/'): - filename = self.curdir + p + filename = posixpath.join(self.curdir, args) filenames = self.afc.listdir(filename) if filenames: for filename in filenames: print(filename) @safe_cmd - def do_cat(self, p): - data = self.afc.get_file_contents(posixpath.join(self.curdir, p)) - if data and p.endswith('.plist'): + def do_walk(self, args): + dirname = posixpath.join(self.curdir, args) + for filename in self.afc.listdir(dirname): + filename = posixpath.join(dirname, filename) + print(filename) + if self.afc.isdir(filename): + self.do_walk(filename) + + @safe_cmd + def do_cat(self, args): + data = self.afc.get_file_contents(posixpath.join(self.curdir, args)) + if data and args.endswith('.plist'): pprint(plistlib.loads(data)) else: print(data) @@ -535,11 +535,11 @@ def do_rm(self, args): self.afc.rm(filename) @safe_cmd - def do_pull(self, user_args): + def do_pull(self, args): def log(src, dst): logging.info(f'{src} --> {dst}') - args = shlex.split(user_args) + args = shlex.split(args) if len(args) != 2: logging.error('pull expects ') return @@ -551,11 +551,11 @@ def log(src, dst): self.afc.pull(remote_path, local_path, callback=log) @safe_cmd - def do_push(self, user_args): + def do_push(self, args): def log(src, dst): logging.info(f'{src} --> {dst}') - args = shlex.split(user_args) + args = shlex.split(args) if len(args) != 2: logging.error('push expects ') return @@ -567,29 +567,38 @@ def log(src, dst): self.afc.push(local_path, remote_path, callback=log) @safe_cmd - def do_head(self, p): - print(self.afc.get_file_contents(posixpath.join(self.curdir, p))[:32]) + def do_head(self, args): + print(self.afc.get_file_contents(posixpath.join(self.curdir, args))[:32]) @safe_cmd - def do_hexdump(self, filename): - filename = posixpath.join(self.curdir, filename) - print(hexdump.hexdump(self.afc.get_file_contents(filename))) + def do_hexdump(self, args): + args = posixpath.join(self.curdir, args) + print(hexdump.hexdump(self.afc.get_file_contents(args))) @safe_cmd - def do_mkdir(self, p): - self.afc.mkdir(p) + def do_mkdir(self, args): + self.afc.mkdir(args) @safe_cmd - def do_info(self, p): + def do_info(self, args): for k, v in self.afc.get_device_info().items(): print(k, '\t:\t', v) @safe_cmd - def do_mv(self, p): - t = p.split() + def do_mv(self, args): + t = args.split() return self.afc.rename(t[0], t[1]) @safe_cmd - def do_stat(self, filename): - filename = posixpath.join(self.curdir, filename) - pprint(self.afc.stat(filename)) + def do_stat(self, args): + args = posixpath.join(self.curdir, args) + pprint(self.afc.stat(args)) + + def _update_prompt(self): + self.prompt = highlight(f'mobile@AFC ({self.curdir})$ ', lexers.BashSessionLexer(), + formatters.TerminalTrueColorFormatter(style='colorful')).strip() + + def _complete(self, text, line, begidx, endidx): + dirname = posixpath.join(self.curdir, posixpath.dirname(text)) + prefix = posixpath.basename(text) + return [filename for filename in self.afc.listdir(dirname) if filename.startswith(prefix)]