【问题标题】:Writing a TAR file header - need validation编写 TAR 文件头 - 需要验证
【发布时间】:2011-02-03 20:16:00
【问题描述】:

在 Windows 上的 .NET 中,我尝试了几个开源 tar 库来编写 tar 存档(直接从内存中,输入文件实际上从未存在)。

它们生成的 tar 文件可以由 tar 库解析和提取,但 7zip 等程序报告 tar 是一个错误。 Unix 上的 gtar 也会抛出错误。

我在错误消息中没有得到任何具体的反馈,所以我不知道出了什么问题。

我曾尝试使用维基百科上的 tar 规范直接编写 tar 文件:http://en.wikipedia.org/wiki/Tar_(file_format),但这会产生相同的情况。

有没有人知道一个可以验证并具体告诉我我正在生成的 tar 文件有什么问题的好工具?

这是我编写存档的自定义代码。在存档的末尾,我写了 2 512 个长度的 nul 块作为终止符。请注意,此代码会生成一个存档,该存档可以使用此开源库进行精细提取:http://www.icsharpcode.net/opensource/sharpziplib/ 但就像我说的,它对 unix 上的 7zip 和 gtar 似乎无效。

public static void WriteTarEntry(string filename, byte[] data, Stream outputStream)
    {
        WriteTarEntryHeader(filename, data.Length, outputStream);
        WriteTarEntryData(data, outputStream);
    }
    static void WriteTarEntryHeader(string fileName, int fileSize, Stream outputStream)
    {
        var header = new byte[512];
        WriteStringToByteArray(fileName, header, 0, 100);
        WriteStringToByteArray(fileSize.ToString(), header, 124, 12);
        var unixTime = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
        WriteStringToByteArray(unixTime, header, 136, 12);
        WriteStringToByteArray("0", header, 156, 1);
        WriteStringToByteArray("ustar ", header, 257, 6);
        WriteStringToByteArray(" ", header, 263, 2);

        WriteStringToByteArray(Environment.UserName, header, 265, 32);
        WriteStringToByteArray(Environment.UserDomainName, header, 297, 32);

        WriteStringToByteArray("        ", header, 148, 8);
        var checksum =  Convert.ToString(header.Sum(b => b), 8).PadLeft(6, Char.Parse("0"));
        WriteStringToByteArray(checksum, header, 148, 6);
        header[148 + 6] = 0;
        header[148 + 7] = 32;
        outputStream.Write(header, 0, header.Length);
    }

    static void WriteStringToByteArray(string value, byte[] array, int start, int maxWidth)
    {
        var len = Math.Min(maxWidth, value.Length);
        var sourceBytes = Encoding.ASCII.GetBytes(value);
        Buffer.BlockCopy(sourceBytes, 0, array, start, len);
    }


    static void WriteTarEntryData(byte[] data, Stream outputStream)
    {
        int totalBytes = 0;
        while (totalBytes < data.Length)
        {
            totalBytes += 512;
        }
        var alldata = new byte[totalBytes];
        Buffer.BlockCopy(data, 0, alldata, 0, data.Length);
        outputStream.Write(alldata, 0, alldata.Length);
    }

【问题讨论】:

  • 您使用的是哪些开源库?您可以发布一些您尝试过的示例代码吗?
  • 我会小心地将char 转换为byte;使用Encoding.ASCII 将字符串转换为字节。
  • 我相信 GNU tar(可能还有其他人)对原始格式使用了一些扩展,这样 GNU tar 可以读取原始创建的所有文件,但原始可能无法读取创建的文件由 GNU 焦油。我不知道这是否有帮助,但这是一个数据点。
  • 好的有道理。我会尝试一下。虽然我事先将 char 数据编码为 ASCII...
  • 对 WriteStringToByteArray 进行了更改以使用 ASCII 编码。没有不同。我没有写任何 uid groupid,所以我想知道这是否是一个问题。我会玩 - 如果有人想到其他任何事情,请告诉我 - 谢谢!

标签: .net format tar


【解决方案1】:

好的 - 我设法解决了这个问题...我在这里找到了这篇文章:http://www.3dartist.com/WP/formats/index.html#tar

这提醒我日期/时间和文件大小都必须以 8 为基数(我已经完成了校验和,但不是这两个)。

进行修复后,它工作正常。考虑到这个错误,我有点惊讶存档完全可以被开源库解析。

以下是对上述代码行的更改:

static void WriteTarEntryHeader(string fileName, int fileSize, Stream outputStream)
    {
        var header = new byte[512];
        WriteStringToByteArray(fileName, header, 0, 100);
        WriteStringToByteArray(Convert.ToString(fileSize, 8), header, 124, 12);
        WriteStringToByteArray(0x1ff.ToString(), header, 100, 8);
        var unixTime = Convert.ToInt64((DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds);
        WriteStringToByteArray(Convert.ToString(unixTime, 8), header, 136, 12);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 2012-08-30
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多