Skip to content

EXT packer#709

Open
paulnoalhyt wants to merge 4 commits into
masterfrom
feature/ext_packer
Open

EXT packer#709
paulnoalhyt wants to merge 4 commits into
masterfrom
feature/ext_packer

Conversation

@paulnoalhyt
Copy link
Copy Markdown
Collaborator

@paulnoalhyt paulnoalhyt commented Feb 9, 2026

  • I have reviewed the OFRAK contributor guide and attest that this pull request is in accordance with it.
  • I have made or updated a changelog entry for the changes in this pull request.

One sentence summary of this PR (This should go in the CHANGELOG!)

Add EXT packer, analyzer and tests.

Link to Related Issue(s)

#529

Please describe the changes in your request.

  • Add ExtAnalyzer that uses the dumpe2fs command to determine all the EXT attributes.
  • Add ExtPacker that uses the mke2fs command and the analysis from the ExtAnalyzer to create an EXT2/3/4 filesystem without having to mount anything or use loop devices.
  • Add tests using FilesystemPackUnpackVerifyPattern and a round trip test to make sure attributes are preserved
  • Note that I had to modify the _validate_folder_equality method in pytest_ofrak/src/pytest_ofrak/patterns/pack_unpack_filesystem.py because linux will sometimes create a lost+found directory when extracting the filesystem. But it could also be present in the original filesystem. So I just removed that from the equality comparison.

Compared to #558 PR, this merge request is more compact and less complex (no need to write a debugfs script, etc).

Anyone you think should look at this, specifically?

No

@rbs-jacob
Copy link
Copy Markdown
Member

Before I get a chance to review this, how does it compare to these other components that Albert worked on? Also, does it happen to address concerns I raised a long time ago, when the EXT unpacking components were introduced?

Note that this would close #529.

@paulnoalhyt
Copy link
Copy Markdown
Collaborator Author

@rbs-jacob, mentioned some of this in the PR description but can elaborate a bit more.

  • WIP ExtAnalyzer and ExtPacker components #558 was brought to my attention as I was almost done writing this implementation. I think this implementation is more compact: I use the mke2fs to create an extfs from an existing directory, intead of building complex debugfs scripts.
  • regarding EXT Filesystem Components #337 (comment), this PR does not make use of any loop device and doesn't require mounting anything. Everything is done in userspace using mke2fs for filesystem creation and dumpe2fs for getting information from extfs files.

Comment on lines +166 to 171
# a "lost+found" directory might be created when flushed to disk, but might also happen to be present in the filesystem, so ignore it:
if "lost+found" in old_files:
old_files.remove("lost+found")
if "lost+found" in new_files:
new_files.remove("lost+found")
assert len(old_files) == len(new_files) and set(old_files) == set(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems suspect? I don't think we want our packer to introduce files like this. Are we sure this is needed?

"-h",
temp_path,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.DEVNULL,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably capture stderr to attach to an exception if this fails.

Comment on lines +205 to +226
if ext_view.blocks_per_group:
cmd.extend(["-g", str(ext_view.blocks_per_group)])
if ext_view.inode_size:
cmd.extend(["-I", str(ext_view.inode_size)])
if ext_view.number_of_inodes:
cmd.extend(["-N", str(ext_view.number_of_inodes)])
if ext_view.reserved_block_count and ext_view.block_count > 0:
percentage = round(ext_view.reserved_block_count / ext_view.block_count * 100)
cmd.extend(["-m", str(percentage)])
if ext_view.creator_os:
cmd.extend(["-o", ext_view.creator_os])
if ext_view.filesystem_features:
features = "none," + ext_view.filesystem_features.replace(" ", ",")
cmd.extend(["-O", features])
if ext_view.filesystem_revision:
cmd.extend(["-r", str(ext_view.filesystem_revision)])
if ext_view.volume_label:
cmd.extend(["-L", ext_view.volume_label])
if ext_view.last_mounted_directory:
cmd.extend(["-M", ext_view.last_mounted_directory])
if ext_view.uuid:
cmd.extend(["-U", ext_view.uuid])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If any of these values are zero, they will not be set. These checks should probably be explicit about confirming is not None.

Comment on lines +245 to +251
for item in os.listdir(temp_dir):
src = os.path.join(temp_dir, item)
dst = os.path.join(str(extract_dir), item)
if os.path.isdir(src):
shutil.copytree(src, dst, symlinks=True)
else:
shutil.copy2(src, dst)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do this instead of extracting directly to the extract dir?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants