Name | pycramfs JSON |
Version |
1.1.0
JSON |
| download |
home_page | |
Summary | Read and extract cramfs images. |
upload_time | 2023-07-01 13:12:09 |
maintainer | |
docs_url | None |
author | |
requires_python | >=3.8 |
license | |
keywords |
cramfs
filesystem
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# pycramfs
<p align="left">
<a><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/pycramfs"></a>
<a href="https://pypi.org/project/pycramfs/"><img alt="PyPI" src="https://img.shields.io/pypi/v/pycramfs"></a>
<a href="https://github.com/AT0myks/pycramfs/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/pycramfs"></a>
</p>
* [Requirements](#requirements)
* [Installation](#installation)
* [Usage](#usage)
* [References](#references)
A library and tool to read and extract cramfs images.
It is far from being as complete as the tools it's based on,
but should be enough for simple images.
For example, as of right now it only supports contiguous data layout.
Only little endian images are supported.
It also provides ways to extract data from an image,
although you might prefer using
[`cramfsck`](https://github.com/npitre/cramfs-tools)
on Linux and 7-Zip on Windows for better compatibility.
## Requirements
Python 3.8+.
## Installation
```
pip install pycramfs
```
## Usage
### API
Here's an overview of what you can do:
```py
from pycramfs import Cramfs
from pycramfs.extract import extract_dir, extract_file
from pycramfs.util import find_superblocks
fsimage = "cramfs.bin"
superblocks = find_superblocks(fsimage)
with Cramfs.from_file(fsimage, offset=superblocks[0]["offset"]) as cramfs:
# Optional offset for start of file system.
# You can also create Cramfs instances from bytes or a file descriptor.
sblock = cramfs.super # Access the file system's superblock
print(sblock.name)
print(dict(sblock)) # Superblock as a dictionary
assert cramfs.calculate_crc() == sblock.fsid.crc
rootdir = cramfs.rootdir # root directory
print(cramfs.size) # File system size in bytes (shortcut to sblock.size)
# Number of files in the whole file system (shortcut to sblock.fsid.files).
print(len(cramfs))
print("/etc/passwd" in cramfs) # Check if path exists
# Iterate over the whole file system.
for file in cramfs:
print(file.parent) # Instance of Directory (None for the root directory)
print(file in cramfs) # Check if file belongs to this image
if file.is_symlink: # Check the file's type
print(file.readlink()) # Symlink target
etc = cramfs.select("/etc") # Select a specific file or directory
etc = cramfs.select("etc") # Can also be a relative path
rootdir = etc.select("..") # And a special entry
assert rootdir == rootdir.select('.')
print(etc) # print the file or directory's name
# The file or directory's absolute path (an instance of PurePosixPath).
print(etc.path)
print(etc.files) # A dictionary mapping file names to File instances
print(len(etc)) # Number of entries in the directory (shortcut to len(etc.files))
print(etc.total) # Number of entries in this whole subtree
# A list of this directory's children (shortcut to list(etc.files.values())).
print(list(etc))
# Find the first file in this subtree that has this name.
passwd = cramfs.find("passwd")
# Return the child entry if present else raise KeyError (shortcut to etc.files["passwd"]).
passwd = etc["passwd"]
print("passwd" in etc) # Check if directory contains this file
print(passwd in etc) # Also works with instances of File
# Iterate over this directory's files.
for file in etc:
print(file.inode) # Access inode information
# These attributes are shortcuts to file.inode.<attr>
print(file.mode)
print(file.uid)
print(file.size)
print(file.gid)
# Iterate over this whole subtree.
for file in etc.riter():
print(file.name) # File name, equivalent to file.path.name
print(file.filemode) # File mode as a string, for example drwxrwxrwx
# Iterate over files in the subtree that match a pattern.
for config_file in etc.itermatch("*.conf"):
print(config_file.read_bytes()) # Read the file's raw content
print(config_file.read_text("utf8")) # Or as a string with optional encoding
assert etc > cramfs.select("/bin") # Comparing instances of File compares their name
# You can use absolute paths from any directory.
cramfs.select("/my/dir/over/here").select("/bin") # Selects /bin
cramfs.select("/my/dir/over/here").select("bin") # Selects /my/dir/over/here/bin
# Calling find(), select() and itermatch() on cramfs
# is the same as calling them on cramfs.rootdir.
extract_dir(etc, "extract/etc") # Extract a directory tree
extract_file(passwd, "extract/passwd") # Extract a single file
```
### Command line
pycramfs comes with a command-line interface that consists of 4 sub-commands.
#### Info
```
usage: pycramfs info [-h] file
Show information about all the superblocks that can be found in a file
positional arguments:
file
```
Example output:
```
$ pycramfs info cramfs.bin
Superblock #1
Magic: 0x28CD3D45
Size: 282,624
Flags: <Flag.SORTED_DIRS|FSID_VERSION_2: 3>
Future: 0
Signature: Compressed ROMFS
Name: Compressed
CRC: 0xDEADBEEF
Edition: 0
Blocks: 6,926
Files: 420
Offset: 8157
```
#### List
```
usage: pycramfs list [-h] [-o OFFSET] [-p PATTERN] [-t TYPE [TYPE ...]] file
List the contents of the file system
positional arguments:
file
options:
-o OFFSET, --offset OFFSET absolute position of file system's start. Default: 0
-p PATTERN, --pattern PATTERN filter by file name pattern with fnmatch
-t TYPE [TYPE ...], --type TYPE [TYPE ...]
filter by file type with f, d, l, p, s, b, c
```
Example that lists only directories and symlinks that match a pattern:
```
$ pycramfs list cramfs.bin -t d l -p "*bin*"
drwxrwxr-x 256 123:0 /bin
lrwxrwxrwx 7 123:0 /bin/ash -> busybox
lrwxrwxrwx 7 123:0 /bin/base64 -> busybox
3 file(s) found
```
#### Extract
```
usage: pycramfs extract [-h] [-o OFFSET] [-d DEST] [-p PATH] [-f] [-q] file
Extract files from the file system
positional arguments:
file
options:
-o OFFSET, --offset OFFSET absolute position of file system's start. Default: 0
-d DEST, --dest DEST destination directory. Default: next to file
-p PATH, --path PATH absolute path of directory or file to extract. Default: '/'
-f, --force overwrite files that already exist. Default: False
-q, --quiet don't print extraction status. Default: False
```
On Linux, just like `cramfsck -x` you need to run as root
if you want to preserve file mode, owner and group.
On Windows, the only reason to run as a privileged user is to be able to create
symlinks.
Unprivileged accounts can create symlinks if Developer Mode is enabled.
Otherwise, a regular file containing the target will be created.
Special files will always just be empty files.
#### Check
This command is similar to running `cramfsck -c file` but is not as thorough.
```
usage: pycramfs check [-h] [-o OFFSET] file
Make a few superficial checks of the file system
positional arguments:
file
options:
-o OFFSET, --offset OFFSET absolute position of file system's start. Default: 0
```
## References
- [cramfs readme](https://github.com/torvalds/linux/blob/master/fs/cramfs/README)
- [cramfs_fs.h](https://github.com/npitre/cramfs-tools/blob/master/linux/cramfs_fs.h)
- [cramfsck.c](https://github.com/npitre/cramfs-tools/blob/master/cramfsck.c)
- [mkcramfs.c](https://github.com/npitre/cramfs-tools/blob/master/mkcramfs.c)
Raw data
{
"_id": null,
"home_page": "",
"name": "pycramfs",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "cramfs,filesystem",
"author": "",
"author_email": "AT0myks <at0myks.dev@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/c0/c3/2267655bc9a03f8e6c4248d42ebab724760f94e46324e7f6331f01b24359/pycramfs-1.1.0.tar.gz",
"platform": null,
"description": "# pycramfs\n\n<p align=\"left\">\n<a><img alt=\"Python versions\" src=\"https://img.shields.io/pypi/pyversions/pycramfs\"></a>\n<a href=\"https://pypi.org/project/pycramfs/\"><img alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/pycramfs\"></a>\n<a href=\"https://github.com/AT0myks/pycramfs/blob/main/LICENSE\"><img alt=\"License\" src=\"https://img.shields.io/pypi/l/pycramfs\"></a>\n</p>\n\n* [Requirements](#requirements)\n* [Installation](#installation)\n* [Usage](#usage)\n* [References](#references)\n\nA library and tool to read and extract cramfs images.\n\nIt is far from being as complete as the tools it's based on,\nbut should be enough for simple images.\nFor example, as of right now it only supports contiguous data layout.\nOnly little endian images are supported.\n\nIt also provides ways to extract data from an image,\nalthough you might prefer using\n[`cramfsck`](https://github.com/npitre/cramfs-tools)\non Linux and 7-Zip on Windows for better compatibility.\n\n## Requirements\n\nPython 3.8+.\n\n## Installation\n\n```\npip install pycramfs\n```\n\n## Usage\n\n### API\n\nHere's an overview of what you can do:\n```py\nfrom pycramfs import Cramfs\nfrom pycramfs.extract import extract_dir, extract_file\nfrom pycramfs.util import find_superblocks\n\nfsimage = \"cramfs.bin\"\nsuperblocks = find_superblocks(fsimage)\n\nwith Cramfs.from_file(fsimage, offset=superblocks[0][\"offset\"]) as cramfs:\n # Optional offset for start of file system.\n # You can also create Cramfs instances from bytes or a file descriptor.\n\n sblock = cramfs.super # Access the file system's superblock\n print(sblock.name)\n print(dict(sblock)) # Superblock as a dictionary\n assert cramfs.calculate_crc() == sblock.fsid.crc\n\n rootdir = cramfs.rootdir # root directory\n print(cramfs.size) # File system size in bytes (shortcut to sblock.size)\n # Number of files in the whole file system (shortcut to sblock.fsid.files).\n print(len(cramfs))\n print(\"/etc/passwd\" in cramfs) # Check if path exists\n\n # Iterate over the whole file system.\n for file in cramfs:\n print(file.parent) # Instance of Directory (None for the root directory)\n print(file in cramfs) # Check if file belongs to this image\n if file.is_symlink: # Check the file's type\n print(file.readlink()) # Symlink target\n\n etc = cramfs.select(\"/etc\") # Select a specific file or directory\n etc = cramfs.select(\"etc\") # Can also be a relative path\n rootdir = etc.select(\"..\") # And a special entry\n assert rootdir == rootdir.select('.')\n print(etc) # print the file or directory's name\n # The file or directory's absolute path (an instance of PurePosixPath).\n print(etc.path)\n print(etc.files) # A dictionary mapping file names to File instances\n print(len(etc)) # Number of entries in the directory (shortcut to len(etc.files))\n print(etc.total) # Number of entries in this whole subtree\n # A list of this directory's children (shortcut to list(etc.files.values())).\n print(list(etc))\n\n # Find the first file in this subtree that has this name.\n passwd = cramfs.find(\"passwd\")\n # Return the child entry if present else raise KeyError (shortcut to etc.files[\"passwd\"]).\n passwd = etc[\"passwd\"]\n print(\"passwd\" in etc) # Check if directory contains this file\n print(passwd in etc) # Also works with instances of File\n\n # Iterate over this directory's files.\n for file in etc:\n print(file.inode) # Access inode information\n # These attributes are shortcuts to file.inode.<attr>\n print(file.mode)\n print(file.uid)\n print(file.size)\n print(file.gid)\n\n # Iterate over this whole subtree.\n for file in etc.riter():\n print(file.name) # File name, equivalent to file.path.name\n print(file.filemode) # File mode as a string, for example drwxrwxrwx\n \n # Iterate over files in the subtree that match a pattern.\n for config_file in etc.itermatch(\"*.conf\"):\n print(config_file.read_bytes()) # Read the file's raw content\n print(config_file.read_text(\"utf8\")) # Or as a string with optional encoding\n\n assert etc > cramfs.select(\"/bin\") # Comparing instances of File compares their name\n\n # You can use absolute paths from any directory.\n cramfs.select(\"/my/dir/over/here\").select(\"/bin\") # Selects /bin\n cramfs.select(\"/my/dir/over/here\").select(\"bin\") # Selects /my/dir/over/here/bin\n\n # Calling find(), select() and itermatch() on cramfs\n # is the same as calling them on cramfs.rootdir.\n\n extract_dir(etc, \"extract/etc\") # Extract a directory tree\n extract_file(passwd, \"extract/passwd\") # Extract a single file\n```\n\n### Command line\n\npycramfs comes with a command-line interface that consists of 4 sub-commands.\n\n#### Info\n\n```\nusage: pycramfs info [-h] file\n\nShow information about all the superblocks that can be found in a file\n\npositional arguments:\n file\n```\n\nExample output:\n```\n$ pycramfs info cramfs.bin\nSuperblock #1\nMagic: 0x28CD3D45\nSize: 282,624\nFlags: <Flag.SORTED_DIRS|FSID_VERSION_2: 3>\nFuture: 0\nSignature: Compressed ROMFS\nName: Compressed\nCRC: 0xDEADBEEF\nEdition: 0\nBlocks: 6,926\nFiles: 420\nOffset: 8157\n```\n\n#### List\n\n```\nusage: pycramfs list [-h] [-o OFFSET] [-p PATTERN] [-t TYPE [TYPE ...]] file\n\nList the contents of the file system\n\npositional arguments:\n file\n\noptions:\n -o OFFSET, --offset OFFSET absolute position of file system's start. Default: 0\n -p PATTERN, --pattern PATTERN filter by file name pattern with fnmatch\n -t TYPE [TYPE ...], --type TYPE [TYPE ...]\n filter by file type with f, d, l, p, s, b, c\n```\n\nExample that lists only directories and symlinks that match a pattern:\n```\n$ pycramfs list cramfs.bin -t d l -p \"*bin*\"\ndrwxrwxr-x 256 123:0 /bin \nlrwxrwxrwx 7 123:0 /bin/ash -> busybox\nlrwxrwxrwx 7 123:0 /bin/base64 -> busybox\n3 file(s) found\n```\n\n#### Extract\n\n```\nusage: pycramfs extract [-h] [-o OFFSET] [-d DEST] [-p PATH] [-f] [-q] file\n\nExtract files from the file system\n\npositional arguments:\n file\n\noptions:\n -o OFFSET, --offset OFFSET absolute position of file system's start. Default: 0\n -d DEST, --dest DEST destination directory. Default: next to file\n -p PATH, --path PATH absolute path of directory or file to extract. Default: '/'\n -f, --force overwrite files that already exist. Default: False\n -q, --quiet don't print extraction status. Default: False\n```\n\nOn Linux, just like `cramfsck -x` you need to run as root\nif you want to preserve file mode, owner and group.\n\nOn Windows, the only reason to run as a privileged user is to be able to create\nsymlinks.\nUnprivileged accounts can create symlinks if Developer Mode is enabled.\nOtherwise, a regular file containing the target will be created.\nSpecial files will always just be empty files.\n\n#### Check\n\nThis command is similar to running `cramfsck -c file` but is not as thorough.\n\n```\nusage: pycramfs check [-h] [-o OFFSET] file\n\nMake a few superficial checks of the file system\n\npositional arguments:\n file\n\noptions:\n -o OFFSET, --offset OFFSET absolute position of file system's start. Default: 0\n```\n\n## References\n\n- [cramfs readme](https://github.com/torvalds/linux/blob/master/fs/cramfs/README)\n- [cramfs_fs.h](https://github.com/npitre/cramfs-tools/blob/master/linux/cramfs_fs.h)\n- [cramfsck.c](https://github.com/npitre/cramfs-tools/blob/master/cramfsck.c)\n- [mkcramfs.c](https://github.com/npitre/cramfs-tools/blob/master/mkcramfs.c)\n",
"bugtrack_url": null,
"license": "",
"summary": "Read and extract cramfs images.",
"version": "1.1.0",
"project_urls": {
"Issues": "https://github.com/AT0myks/pycramfs/issues",
"Source": "https://github.com/AT0myks/pycramfs"
},
"split_keywords": [
"cramfs",
"filesystem"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "7071d1ee584248b45278e40aab7fe35b48781a18694aa3d4e46023391f191cf4",
"md5": "d0de6b7d761584f6fe10655e39813272",
"sha256": "bb7b92ca4fa4862447ffa08690f417182732b1d5c8da2d16185c353fc2933365"
},
"downloads": -1,
"filename": "pycramfs-1.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d0de6b7d761584f6fe10655e39813272",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 29012,
"upload_time": "2023-07-01T13:12:08",
"upload_time_iso_8601": "2023-07-01T13:12:08.423583Z",
"url": "https://files.pythonhosted.org/packages/70/71/d1ee584248b45278e40aab7fe35b48781a18694aa3d4e46023391f191cf4/pycramfs-1.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c0c32267655bc9a03f8e6c4248d42ebab724760f94e46324e7f6331f01b24359",
"md5": "6e9a40cc84220d321bc2f0d96a3900c3",
"sha256": "8b01d3f7c86d89917e7bfdf3ac5229ab780f25da6c3b40ceccbe960695c9bf18"
},
"downloads": -1,
"filename": "pycramfs-1.1.0.tar.gz",
"has_sig": false,
"md5_digest": "6e9a40cc84220d321bc2f0d96a3900c3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 28511,
"upload_time": "2023-07-01T13:12:09",
"upload_time_iso_8601": "2023-07-01T13:12:09.806185Z",
"url": "https://files.pythonhosted.org/packages/c0/c3/2267655bc9a03f8e6c4248d42ebab724760f94e46324e7f6331f01b24359/pycramfs-1.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-01 13:12:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "AT0myks",
"github_project": "pycramfs",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pycramfs"
}