Написание заголовка файла TAR - требуется проверка - PullRequest
2 голосов
/ 03 февраля 2011

В .NET в Windows я попробовал пару библиотек tar с открытым исходным кодом, чтобы написать архив tar (непосредственно из памяти, входные файлы никогда не существуют).

Они создают файлы tar, которые могут бытьанализируется и извлекается библиотеками tar, но программы, такие как 7zip, сообщают, что tar является ошибкой.Также gtar на Unix выбрасывает ошибки.

Я не получаю никакой обратной связи в сообщениях об ошибках, поэтому не знаю, что не так.

Я пытался писать файлы tar напрямую, используя спецификацию tar в Википедии: http://en.wikipedia.org/wiki/Tar_(file_format), но это приводит к той же ситуации.

Кто-нибудь знает о хорошем утилите, который может проверить и сказать мне конкретно, что не так с файлами tar, которые я генерирую?

Вот мой пользовательский код для написания архива.В конце архива я пишу 2 512 блоков длины nul в качестве терминатора.Обратите внимание, что этот код генерирует архив, который извлекает нормально с использованием этой библиотеки с открытым исходным кодом: http://www.icsharpcode.net/opensource/sharpziplib/, но, как я уже сказал, он кажется недопустимым для 7zip и gtar в 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);
    }

1 Ответ

1 голос
/ 03 февраля 2011

Хорошо - мне удалось решить это ... Я нашел этот пост здесь: http://www.3dartist.com/WP/formats/index.html#tar

Это напомнило мне, что дата / время и размер файла должны быть в base-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);
...