Package: pycramfs
pycramfsRequirementsInstallationUsageReferencesA 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 usingcramfsckon Linux and 7-Zip on Windows for better compatibility.RequirementsPython 3.8+.Installationpip install pycramfsUsageAPIHere's an overview of what you can do:frompycramfsimportCramfsfrompycramfs.extractimportextract_dir,extract_filefrompycramfs.utilimportfind_superblocksfsimage="cramfs.bin"superblocks=find_superblocks(fsimage)withCramfs.from_file(fsimage,offset=superblocks[0]["offset"])ascramfs:# 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 superblockprint(sblock.name)print(dict(sblock))# Superblock as a dictionaryassertcramfs.calculate_crc()==sblock.fsid.crcrootdir=cramfs.rootdir# root directoryprint(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"incramfs)# Check if path exists# Iterate over the whole file system.forfileincramfs:print(file.parent)# Instance of Directory (None for the root directory)print(fileincramfs)# Check if file belongs to this imageiffile.is_symlink:# Check the file's typeprint(file.readlink())# Symlink targetetc=cramfs.select("/etc")# Select a specific file or directoryetc=cramfs.select("etc")# Can also be a relative pathrootdir=etc.select("..")# And a special entryassertrootdir==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 instancesprint(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"inetc)# Check if directory contains this fileprint(passwdinetc)# Also works with instances of File# Iterate over this directory's files.forfileinetc: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.forfileinetc.riter():print(file.name)# File name, equivalent to file.path.nameprint(file.filemode)# File mode as a string, for example drwxrwxrwx# Iterate over files in the subtree that match a pattern.forconfig_fileinetc.itermatch("*.conf"):print(config_file.read_bytes())# Read the file's raw contentprint(config_file.read_text("utf8"))# Or as a string with optional encodingassertetc>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 /bincramfs.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 treeextract_file(passwd,"extract/passwd")# Extract a single fileCommand linepycramfs comes with a command-line interface that consists of 4 sub-commands.Infousage: pycramfs info [-h] file

Show information about all the superblocks that can be found in a file

positional arguments:
  fileExample 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:    8157Listusage: 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, cExample 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) foundExtractusage: 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: FalseOn Linux, just likecramfsck -xyou 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.CheckThis command is similar to runningcramfsck -c filebut 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: 0Referencescramfs readmecramfs_fs.hcramfsck.cmkcramfs.c