|
6 | 6 |
|
7 | 7 | from littlefs import LittleFS, __version__ |
8 | 8 | from littlefs.errors import LittleFSError |
| 9 | +from littlefs.repl import LittleFSRepl |
| 10 | +from littlefs.context import UserContextFile |
9 | 11 |
|
10 | 12 | # Dictionary mapping suffixes to their size in bytes |
11 | 13 | _suffix_map = { |
@@ -110,7 +112,7 @@ def create(parser: argparse.ArgumentParser, args: argparse.Namespace) -> int: |
110 | 112 | compact_fs.fs_grow(args.block_count) |
111 | 113 | data = compact_fs.context.buffer |
112 | 114 | if not args.no_pad: |
113 | | - data = data.ljust(args.fs_size, b"\xFF") |
| 115 | + data = data.ljust(args.fs_size, b"\xff") |
114 | 116 | else: |
115 | 117 | data = fs.context.buffer |
116 | 118 |
|
@@ -188,6 +190,47 @@ def extract(parser: argparse.ArgumentParser, args: argparse.Namespace) -> int: |
188 | 190 | return 0 |
189 | 191 |
|
190 | 192 |
|
| 193 | +def repl(parser: argparse.ArgumentParser, args: argparse.Namespace) -> int: |
| 194 | + """Inspect an existing LittleFS image through an interactive shell.""" |
| 195 | + |
| 196 | + source: Path = args.source |
| 197 | + if not source.is_file(): |
| 198 | + parser.error(f"Source image '{source}' does not exist.") |
| 199 | + |
| 200 | + image_size = source.stat().st_size |
| 201 | + if not image_size or image_size % args.block_size: |
| 202 | + parser.error( |
| 203 | + f"Image size ({image_size} bytes) is not a multiple of the supplied block size ({args.block_size})." |
| 204 | + ) |
| 205 | + |
| 206 | + block_count = image_size // args.block_size |
| 207 | + if block_count == 0: |
| 208 | + parser.error("Image is smaller than a single block; cannot mount.") |
| 209 | + |
| 210 | + context = UserContextFile(str(source)) |
| 211 | + fs = LittleFS( |
| 212 | + context=context, |
| 213 | + block_size=args.block_size, |
| 214 | + block_count=block_count, |
| 215 | + name_max=args.name_max, |
| 216 | + mount=False, |
| 217 | + ) |
| 218 | + |
| 219 | + shell = LittleFSRepl(fs) |
| 220 | + try: |
| 221 | + try: |
| 222 | + shell.do_mount() |
| 223 | + except LittleFSError as exc: |
| 224 | + parser.error(f"Failed to mount '{source}': {exc}") |
| 225 | + shell.cmdloop() |
| 226 | + finally: |
| 227 | + if shell._mounted: |
| 228 | + with suppress(LittleFSError): |
| 229 | + fs.unmount() |
| 230 | + |
| 231 | + return 0 |
| 232 | + |
| 233 | + |
191 | 234 | def get_parser(): |
192 | 235 | if sys.argv[0].endswith("__main__.py"): |
193 | 236 | prog = f"python -m littlefs" |
@@ -299,6 +342,19 @@ def add_command(handler, name="", help=""): |
299 | 342 | help="LittleFS block size.", |
300 | 343 | ) |
301 | 344 |
|
| 345 | + parser_repl = add_command(repl) |
| 346 | + parser_repl.add_argument( |
| 347 | + "source", |
| 348 | + type=Path, |
| 349 | + help="Source LittleFS filesystem binary.", |
| 350 | + ) |
| 351 | + parser_repl.add_argument( |
| 352 | + "--block-size", |
| 353 | + type=size_parser, |
| 354 | + required=True, |
| 355 | + help="LittleFS block size.", |
| 356 | + ) |
| 357 | + |
302 | 358 | return parser |
303 | 359 |
|
304 | 360 |
|
|
0 commit comments