编写 TAR 文件头 - 需要验证

发布于 2024-10-16 01:59:53 字数 2617 浏览 5 评论 0 原文

在 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);
    }

In .NET on windows I've tried a couple of open source tar libraries to write a tar archive (directly from memory, the input files never actually exist).

They produce tar files that can be parsed and extracted by the tar libraries but programs like 7zip report that the tar is an error. Also gtar on Unix is throwing errors.

I'm not getting any specific feed back in the error messages, so I don't know what is wrong.

I have tried writing the tar files directly using the tar spec on wikipedia: http://en.wikipedia.org/wiki/Tar_(file_format), but that yields the same situation.

Does anyone know of a good util that can validate and tell me specifically what is wrong with the tar files I'm generating?

Here's my custom code for writing the archive. At the end of the archive I write 2 512 length blocks of nul as a terminator. Note, that this code generates an archive that extracts fine using this opensource lib: http://www.icsharpcode.net/opensource/sharpziplib/
but like i said, it appears invalid to 7zip and gtar on unix.

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);
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

难如初 2024-10-23 01:59:54

好的 - 我设法解决了这个问题...我在这里找到了这篇文章: 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);

Okay - I managed to solve this one... I found this post here: http://www.3dartist.com/WP/formats/index.html#tar

This reminded me that the date/time and file size all have to be in base-8 (i'd done the checksum, but not those two).

After making that fix it works fine. Given this error, I'm kind of surprised the archive was parsable by open source library at all.

Here are the changed lines of code to the above:

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文