扩展库 / zip

zip

创建、读取和修改 ZIP/ZIP64 归档,支持内存与文件入口、二进制条目和资源限制。

版本 1.0.0 · C / xlang · 依赖 _libzip

快速开始

以下顶层示例按 JIT 验证。固定发布物的顶层 native-backed 对象 AOT 仍受 M2 退役问题阻断;不以打印正确等同进程正常退出,原代码保留作回归。

import zip

zip.ZipArchive writer = zip.create()
writer.add("hello.txt", "你好")
Buffer packed = writer.finish()

zip.ZipArchive reader = zip.open(packed)
println(reader.readText("hello.txt"))
reader.close()

输出 你好。readText 接管独立读取缓冲并按长度保存 UTF-8 文本,内嵌 NUL 不截断;无效 UTF-8 会被拒绝。二进制数据使用 add(name, Buffer) 与 read(name) as Buffer。

接口

入口用途
create / open(Buffer) / open(path, mode)创建内存归档,或打开内存/文件归档;文件模式为 r、w、a、x。
ZipArchive.add / addFile / mkdir加入文本、Buffer、磁盘文件或目录条目。
contains / names / info / read / readText查找、读取条目与元数据;ZipInfo 可显式声明。
remove / rename / setComment / setEntryComment修改归档内容或注释。
extractAll(destination, overwrite = false)检查归档路径、已有链接与输出限额后解压;目标目录须由应用控制。
close / finish关闭归档;内存归档使用 finish() 取走独立 Buffer。

工厂限额要求为正;条目数、大小、压缩比和输出量由 XRT ZIP 后端约束。条目名、文件路径、注释与解压目标拒绝内嵌 NUL;归档条目内容仍允许任意二进制字节。解压会拒绝目标目录已有父级、根目录和下级中已存在的链接,但尚不能抵御其他进程并发替换目录;不要把不可信或可并发修改的目标目录当作安全沙箱。

2026-10-30 修复内存归档提交扩容失败被误报 I/O 的问题。真实内存失败保留 MemoryError,解除故障可重试;没有增加成功路径复制或分配。普通错误的完整描述当前另受 M12 阻断,不能只根据异常类别正确签收诊断。

C 对照

手动编译下面的片段,须将 ZIP 公共 include 目录加入头文件搜索路径,并按包清单链接 C 实现及依赖。

#include "xrt_zip.h"

int main(void)
{
    xrtziparchive* archive = xrtZipArchiveCreate(NULL);
    if (archive == NULL) return 1;
    const char text[] = "hello";
    if (!xrtZipArchiveAdd(archive, "hello.txt", text, sizeof(text) - 1u,
        false, XRT_ZIP_METHOD_DEFAULT, -1) || !xrtZipArchiveClose(archive)) {
        xrtZipArchiveDestroy(archive);
        return 2;
    }
    xbuffer* packed = xrtZipArchiveTakeBuffer(archive);
    xrtZipArchiveDestroy(archive);
    if (packed == NULL) return 3;
    xrtBufferDestroy(packed);
    return 0;
}

公共头为 extlibs/zip/include/xrt_zip.h。C 选项用 xrtZipOptionsInit 初始化;ZIP 只执行输入、输出、单项、条目数及压缩倍率限额,节点数、深度、资源标志和保留字段必须为零,尺寸/版本必须匹配。完整双语对照范例位于 examples/extlibs/zip.xl 与 examples/extlibs/zip_c.c;C 返回的 xbuffer 由调用方销毁。C 范例依赖多份 ZIP 封装源和 _libzip,从仓库根目录使用 tools/run_extlib_c.ps1 -Package zip -Source release/examples/extlibs/zip_c.c 按包清单运行;单独 xl run zip_c.c 不会自动链接这些源。

大正文与所有权

包内 extlibs/zip/examples/memory_roundtrip.xl 与 memory_roundtrip_c.c 用同样的 131072 字节正文、STORE 方法及注释,验证输入提前释放、完整正文/CRC 和关闭归档后的独立结果。正常执行不写文件;显式提供路径才导出 ZIP。XLang 的文件导出有 toBytes() 转换,不承诺该路径零复制。

entries: 1
bytes: 131072
comment: stable
snapshot: true

仓库根目录可执行 xl run release/extlibs/zip/examples/memory_roundtrip.xl。C 侧使用 tools/run_extlib_c.ps1 -Package zip -Source release/extlibs/zip/examples/memory_roundtrip_c.c;Linux/Windows 还可用显式 import 的构建方式,命令及清理责任见包内 examples/README.md。

验证状态

xl run release/extlibs/zip/test/boundaries.xl
xl run release/examples/extlibs/zip.xl
powershell -ExecutionPolicy Bypass -File tools/run_extlib_c.ps1 -Package zip -Source release/extlibs/zip/test/test_zip.c

2026-10-30 固定 Windows/Linux 发布物:提交故障 C100 场景/80 个真实 XRT OOM,旧源 30 条失败断言变为 0;C/XLang JIT/AOT、32 个真实生成声明、双向 ZIP 互通、新范例五种执行路径及九条正常独立程序路径通过。Linux C 含 ASan/UBSan/泄漏检查;Python 独立检查完整正文、CRC、方法和注释。没有修改主线或同步开发中的 XRT。

默认门禁仍失败,不是发布验收通过:M2 顶层 AOT 退役、M3 包外私有构造器、M12 诊断 getter 丢失待查询错误;RFS 并发目录提交也未闭环。Linux 链接专项因首项精确消息断言失败,独立 probe 只证实该项已拒绝且链接外无文件,不能声称余下组合已通过。无包最小源、复现建议及完整现场见包内 docs/commit-memory-audit-2026-10-30.md。官网源更新仅生成到隔离目录,不代表已部署。