11 个稳定版本
3.1.5 | 2024 年 5 月 28 日 |
---|---|
3.1.4 | 2024 年 3 月 15 日 |
3.0.3 | 2022 年 1 月 1 日 |
3.0.2 | 2021 年 8 月 31 日 |
1.0.0 |
|
在 解析器实现 中排名第 42
每月下载量 90,036
用于 137 个 包(直接使用 29 个)
45KB
594 行
tree_magic_mini
tree_magic_mini
是一个 Rust 包,用于确定给定文件或字节流的 MIME 类型。
请参阅 https://docs.rs/tree_magic_mini/ 中的文档
这是 Allison Hancock 的 tree_magic 包的分支。它包括以下更改
- 更新依赖项。
- 减少复制和内存分配,略微提高速度并降低内存使用。
- 减少 API 面积。一些之前公开的 API 现在是内部的。
- 移除了可选的
cli
功能和tmagic
二进制文件。 - 将 GPL 许可的文件数据拆分为独立的可选包。
这些更改旨在使库更高效,并简化维护和优化分支的工作。我最终希望将这些更改合并回原始的 tree_magic
包,并在有需求的情况下恢复一些被删除的功能。
许可和 MIME 数据库
默认情况下,tree_magic_mini
将在运行时尝试从标准位置加载共享 MIME 信息数据库。
如果您没有数据库文件可用,或者希望将其包含在二进制文件中以简化操作,您可以通过启用 tree_magic_db
功能来可选地嵌入数据库信息。
由于魔术数据库文件本身根据 GPL 许可,您必须确保您的项目使用兼容的许可协议,如果启用此行为。
继续阅读原始的 tree_magic
文档。
关于 tree_magic
与libmagic和file(1)使用的典型方法不同,这种方法根据子类在树形结构中加载所有文件类型。(例如:application/vnd.openxmlformats-officedocument.wordprocessingml.document
(MS Office 2007)子类 application/zip
,它又子类 application/octet-stream
)然后,而不是将文件与所有文件类型进行比较,它可以沿着树向下遍历,仅检查有意义的文件类型。(毕竟,最快的是根本不运行的检查。)
这个库还提供了检查文件是否为特定类型的能力,而无需逐个检查所有文件类型。
性能
这很快。非常快。
这是在OpenSUSE Tumbleweed上对我的下载文件夹(抱歉,找不到一组好的公开随机文件集)进行的测试。(tmagic
是用cargo build --release
编译的,而file
来自OpenSUSE仓库。这是一个热运行,这意味着我已经运行了这两个程序几次。系统是双核Intel Core i7 640M,结果是用time
测量的。
程序 | 实际 | 用户 | 系统 |
---|---|---|---|
tmagic 0.2.0 | 0m0.063s | 0m0.052s | 0m0.004s |
file-5.30 --mime-type | 0m0.924s | 0.800s | 0.116s |
有几个因素导致了这种情况。主要是
-
由于图方法,解析的类型更少。
-
首先加载文件的4K内容,然后传递给所有解析器,而不是不断从磁盘重新加载。(这样做时,时间大约在~0.130s。)
-
在检查罕见类型之前,先检查最常见的类型(如image/png、image/jpeg、application/zip等)。
-
所有可以延迟初始化的内容都是。
夜间用户还可以运行cargo bench
进行一些基准测试。对于同一硬件上的tree_magic 0.2.0
test from_u8::application_zip ... bench: 17,086 ns/iter (+/- 845)
test from_u8::image_gif ... bench: 5,027 ns/iter (+/- 520)
test from_u8::image_png ... bench: 4,421 ns/iter (+/- 1,795)
test from_u8::text_plain ... bench: 112,578 ns/iter (+/- 11,778)
test match_u8::application_zip ... bench: 222 ns/iter (+/- 144)
test match_u8::image_gif ... bench: 140 ns/iter (+/- 14)
test match_u8::image_png ... bench: 139 ns/iter (+/- 18)
test match_u8::text_plain ... bench: 44 ns/iter (+/- 3)
然而,应该注意的是,FreeDesktop.org的magic文件比libmagic使用的magic文件少。 (在我的系统中,tree_magic支持400种类型,而/usr/share/misc/magic
包含855个!:mime
标签。)然而,它解析起来要容易得多,因为它只涉及魔数,而不涉及属性或其他内容。有关计划修复此问题的详细信息,请参阅TODO部分。
兼容性
这已在Windows 7和OpenSUSE Tumbleweed Linux上使用Rust Stable和Nightly进行了测试。
所有MIME信息和关系信息都从描述在https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html中的共享MIME信息数据库加载。如果您认为您的系统上没有此数据库,请关闭sys_fdo_magic
功能标志。
这提供了最常见的文件类型,但仍缺少一些重要的类型,如LibreOffice或MS Office 2007+支持或ISO文件。预计这会得到改善,尤其是在添加zip
检查器时。
架构
tree_magic
被拆分为不同的 "检查器" 模块。每个检查器处理一组特定的文件类型,仅处理这些类型。例如,basetype
检查器处理 inode
和 text/plain
类型,而 fdo_magic
检查器处理任何具有魔数的文件。这里的想法是,我们可以专门选择最适合文件格式的检查器,而不是像 libmagic
那样采用一个适合所有文件的单一魔数描述符格式。
在库初始化期间,每个检查器都会查询它支持的类型以及它们之间的父-子关系。在此期间,检查器可以加载任何规则、模式等到内存中。这里的一个大原则是,检查阶段的时间比初始化阶段的时间价值高得多。库只初始化一次,并且在程序的生命周期内可以检查成千上万的文件。
从文件类型和关系的列表中构建一个有向图,并将每个节点添加到哈希映射中。如果需要,库用户可以直接使用这些信息来找到给定 MIME 的父级、子级等。
当需要将文件与某个 MIME 进行比较时(match_*),会查询每个检查器以查看它是否支持该类型,如果支持,则运行检查器。如果检查器返回 true,则该文件必须是那种类型。
当需要找到文件的 MIME 类型(from_*)时,库从类型图中的 all/all
节点开始(或用户指定的任何节点)向下遍历树。如果找到匹配项,它将继续搜索该分支。如果没有找到匹配项,它将检索找到的最深 MIME 类型。
待办事项
改进 fdo-magic 检查器
目前,fdo-magic
检查器不处理字节序。它也不处理存储在用户主目录中的魔数文件。
额外的检查器
计划为许多类型提供自定义文件检查函数。以下是一些想法
-
zip
:可以通过查看 zip 的目录列表来确定所有继承自application/zip
的内容。 -
grep
:可以使用正则表达式(或最佳选择)解析程序脚本和配置文件等文本文件。 -
json
、toml
、xml
等:检查给定的文件是否与模式匹配,并返回匹配结果。(到这一点,潜在匹配项应该很少,因此可以加载整个文件) -
(专用解析器):没有魔数的二进制(或文本)文件可以与快速且简单的
nom
解析器进行比较,而不是像 libmagic 那样使用奇怪的经验法则。
要添加额外的检查器类型,添加一个导出
-
init::get_supported() -> Vec<(String)>
-
init::get_subclasses() -> Vec<String, String)>
-
test::from_u8(&[u8], &str) -> bool
-
test::from_filpath(&str, &str) -> Result<bool, std::io::Error>
并将这些函数的引用添加到 lib.rs
中的 CHECKERS lazy_static! 中。最底部的条目先搜索。
缓存
从现在开始,检查器(如 basetype
的元数据或 json/toml/xml 示例)能够缓存文件的内存表示,以便不需要为每个新类型重新加载和重新解析,这是非常重要的。在当前架构中,这相当困难实现。
多种文件类型
外面有一些奇怪的文件(例如多语言quine)。它们是多种文件类型。出于安全考虑,这可能值得处理。(但这并不是一个特别重要的事情。)
并行处理
目前这是单线程的。这是一个相当并行化的任务(多个文件、多种类型、每种类型的多个规则...),因此应该会有很大的速度提升。
不要做的事情
文件属性
libmagic
和 file
默认情况下会打印出描述性字符串,详细说明文件类型,以及像JPEG图像或ELF文件这样的一些元数据。由于这完全是多余的,tree_magic
永远不会支持这一点。最好在一个单独的crate中处理属性,该crate可以提取出可预测的、机器可读的格式。
依赖关系
~2.7–9.5MB
~82K SLoC