Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions dissect/target/tools/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,16 +650,26 @@ def prompt(self) -> str:
return self.prompt_ps1.format(base=self.prompt_base, cwd=self.cwd, **ANSI_COLORS)

def completedefault(self, text: str, line: str, begidx: int, endidx: int) -> list[str]:
path = self.resolve_path(line[:begidx].rsplit(" ")[-1])
"""Attempt to autocomplete the current commandline based on the target filesystem."""

# Line also contains the base command and possibly spaces in the path.
path = self.resolve_path(line[:begidx].replace("\\ ", "\00").rsplit(" ")[-1].replace("\00", " "))

textlower = text.lower()

suggestions = []
for fpath, fname in ls_scandir(path):
if not fname.lower().startswith(textlower):
continue

# Do not suggest non-directories for autocompletion with cd command.
if line.startswith("cd ") and not fpath.is_dir():
continue

# Add a trailing slash to directories, to allow for easier traversal of the filesystem
suggestion = f"{fname}/" if fpath.is_dir() else fname
# Add trailing slashes for directories and escape spaces in paths
suggestion = (f"{fname}/" if fpath.is_dir() else fname).replace(" ", "\\ ")

suggestions.append(suggestion)
return suggestions

Expand All @@ -670,7 +680,7 @@ def resolve_path(self, path: str) -> fsutil.TargetPath:
if isinstance(path, fsutil.TargetPath):
return path

path = fsutil.abspath(path, cwd=str(self.cwd), alt_separator=self.target.fs.alt_separator)
path = fsutil.abspath(path.replace("\\ ", " "), cwd=str(self.cwd), alt_separator=self.target.fs.alt_separator)
return self.target.fs.path(path)

def resolve_glob_path(self, path: str) -> Iterator[fsutil.TargetPath]:
Expand Down Expand Up @@ -1133,9 +1143,9 @@ def cmd_zcat(self, args: argparse.Namespace, stdout: TextIO) -> bool:
@alias("xxd")
def cmd_hexdump(self, args: argparse.Namespace, stdout: TextIO) -> bool:
"""print a hexdump of file(s)"""
paths = list(self.resolve_glob_path(args.path))
paths = [p for p in self.resolve_glob_path(args.path) if p.is_file()]
if not paths:
print(f"{args.path}: No such file or directory")
print(f"{args.path}: No such file")
return False

for path in paths:
Expand Down