Read content of SquashFS filesystem images. Supports navigating the directory structure and reading files in images compressed using gzip
(uses CodecZlib
) or zstd
(uses CodecZstd
). Extended attributes and other features are not implemented and not planned for foreseeable future.
Attains good performance and may easily beat reading from the regular file system. On a laptop with SSD and a SquashFS image containing 10'000 small files: 12-50k IOPS depending on the reading pattern; 250 Mb/s for reading large files. Both IOPS and bandwidth are limited by the decompression speed. Caching may help in certain scenarios of reading small files, but this is neither implemented nor planned. See the benchmark
directory for details.
Generate files that go into a SquashFS image, and create the sample image:
julia> orig_dir = pwd();
julia> tmp = mktempdir();
julia> cd(tmp);
julia> mkpath("./dir/subdir");
julia> write("./dir/filea.txt", "aaa");
julia> write("./dir/subdir/fileb.dat", "abc");
julia> write("./dir/subdir/filec.dat", "def");
julia> import squashfs_tools_jll: mksquashfs
julia> run(pipeline(`$mksquashfs dir image.sqsh`, stdout=devnull));
julia> cd(orig_dir);
Open the SquashFS image and access it with common Base
filesystem functions:
julia> import SquashFS
julia> img = SquashFS.open(joinpath(tmp, "image.sqsh"));
julia> root = SquashFS.rootdir(img);
julia> readdir(root)
2-element Vector{String}:
"filea.txt"
"subdir"
julia> isdir(root)
true
julia> isdir(joinpath(root, "subdir"))
true
julia> [basename(f) for f in readdir(root; join=true) if isfile(f)]
1-element Vector{String}:
"filea.txt"
julia> read(joinpath(root, "filea.txt"), String)
"aaa"
julia> readdir(joinpath(root, "subdir"))
2-element Vector{String}:
"fileb.dat"
"filec.dat"
julia> read.(readdir(joinpath(root, "subdir"); join=true), String)
2-element Vector{String}:
"abc"
"def"
Several specialized functions are provided as well, see reference docs below.
#
SquashFS.files_recursive
— Method.
files_recursive(img::SquashFS.Image, path::AbstractString) -> Vector{String}
Return the paths of all files contained in the directory path
within SquashFS image img
, recursively. Returned paths are relative to the specified path
.
#
SquashFS.open
— Method.
open(fname::AbstractString; threaded) -> SquashFS.Image
Open SquashFS image file. Immediately reads list of all inodes, directory structure, and fragments table. These are always kept in memory for implementation simplicity and performance.
threaded
must be set to true
to use the same image from multiple threads.
#
SquashFS.openfile
— Method.
openfile(img::SquashFS.Image, spec) -> IOBuffer
Open the file at path
in the SquashFS image img
and return as an IO
object. For now just reads the whole content of the file and wraps it into an IOBuffer
. May become more efficient in the future.
#
SquashFS.readdir
— Method.
readdir(img::SquashFS.Image, path::AbstractString; join) -> Vector{String}
Return the names in the directory path
within SquashFS image img
. When join
is false
, returns just the names in the directory as is; when join
is true
, returns joinpath(path, name)
for each name
so that the returned strings are full paths
#
SquashFS.readfile
— Method.
readfile(img::SquashFS.Image, path::AbstractString) -> Vector{UInt8}
Read content of the file at path
in the SquashFS image img
. Return a bytearray.
#
SquashFS.readfile
— Method.
readfile(img::SquashFS.Image, spec, _::Type{String}) -> String
Read content of the file spec
in the SquashFS image img
. Returns a String
. spec
can be a path or another supported value such as an inode number.
#
SquashFS.rglob
— Function.
rglob(img::SquashFS.Image, pattern) -> Vector{String}
rglob(img::SquashFS.Image, pattern, path::AbstractString) -> Vector{String}
Returns the paths of all files matching pattern
in directory path
within SquashFS image img
, recursively. pattern
can be any object that supports occursin(pattern, name::String)
: e.g. String
, Regex
, or patterns from the Glob.jl
package.