Правильно ли проводить различие между сжатыми файлами.gz и заархивированными файлами tar.gz?

Как правильно различать простой сжатый файл в формате gzip или bzip2 (например,.gz) и архив, сжатый с помощью gzip или bzip2 (например,.tar.gz). Идентификация с использованием расширений суффиксов не является надежным вариантом. как это возможно файлы могут быть переименованы.

Теперь в командной строке я могу сделать что-то вроде этого:

bzip2 -dc test.tar.bz2 |head|file -

Поэтому я попытался сделать что-то подобное в python с помощью следующей функции:

def get_magic(self, store_file, buffer=False, look_deeper=False):
    # see what we're indexing
    if look_deeper == True:
        m = magic.Magic(mime=True, uncompress=True)
    else:
        m = magic.Magic(mime=True) 

    if buffer == False:
        try:
            file_type = m.from_file(store_file)

        except Exception, e:
            raise e

    else:
        try:
            file_type = m.from_buffer(store_file)

        except Exception, e:
            raise e

    return file_type 

Затем, при попытке прочитать сжатый архив, я передам в буфер из другого места через:

    file_buffer = open(file_name).read(8096) 
    archive_check = self.get_magic(file_buffer, True, True)

К сожалению, это становится проблематичным при использовании флага uncompress в python-magic, потому что кажется, что python-magic ожидает, что я передам весь файл, хотя я только хочу, чтобы он прочитал буфер. Я заканчиваю с исключением:

bzip2 ERROR: Compressed file ends unexpectedly

Учитывая, что файлы, на которые я смотрю, могут иметь размер от 2 до 20 ГБ, это становится довольно проблематичным. Я не хочу читать весь файл.

Можно ли его взломать, отключить конец сжатого файла и добавить его в буфер? Лучше ли игнорировать идею распаковки файла с помощью python-magic и вместо этого делать это, прежде чем передать в буфер для идентификации через:

    file_buffer = open(file_name, "r:bz2").read(8096) 

Есть ли способ лучше?

2 ответа

Решение

Весьма вероятно, что tar-файл имеет несжатые данные со смещением 257 "ustar" или если несжатые данные в целом составляют 1024 нулевых байта (пустой tar-файл).

Вы можете прочитать только первые 1024 байта несжатых данных, используя z = zlib.decompressobj() или же z = bz2.BZ2Decompressor(), а также z.decompress(),

Я на самом деле собираюсь отметить ответ Марка как правильный, поскольку он дал мне подсказку.

Я закончил тем, что бросил проект, чтобы заняться другими делами в течение хороших шести месяцев, и был озадачен, так как bz2.BZ2Decompressor, похоже, не работал так, как предполагалось. Оказывается, проблема не решаема в 1024 байта.

#!/usr/bin/env python

import os
import bz2
import magic

store_file = "10mb_test_file.tar.bz2"
m = magic.Magic(mime=True)

file_buffer = open(store_file, "rb").read(1000000)
buffer_chunk = ""

decompressor = bz2.BZ2Decompressor()
print ( "encapsulating bz2" )
print ( type(file_buffer) )
print ( len(file_buffer) )
file_type = m.from_buffer(file_buffer)
print ( "file type: %s :" % file_type)

buffer_chunk += decompressor.decompress( file_buffer )
print ( "compressed file contents" )
print ( type(buffer_chunk) )
print ( len(buffer_chunk) )

file_type = m.from_buffer(buffer_chunk)
print ( "file type: %s :" % file_type)

Странно, но с файлом tar.bz2 размером 20 МБ я могу использовать значение 200 000 байт, а не 1 000 000 байт, но это значение не будет работать с тестовым файлом 10 МБ. Я не знаю, является ли он специфичным для задействованного архива tar.bz2, и я не изучал задействованные алгоритмы, чтобы увидеть, находятся ли они в определенных точках, но чтение примерно 10 МБ данных до сих пор работает на каждом архивном файле. до 5 ГБ. Open(). Read(buffer) будет читать до размера буфера или EOF, так что все в порядке.

Другие вопросы по тегам