Как определить, верны ли данные tar-файла без файла?

Моя форма загрузки ожидает файл tar, и я хочу проверить, действительны ли загруженные данные. Модуль tarfile поддерживает is_tarfile(), но ожидает имя файла — я не хочу тратить ресурсы на запись файла на диск только для проверки его правильности.

Есть ли способ проверить, что данные являются действительным файлом tar без записи на диск, используя стандартные библиотеки Python?


person hoju    schedule 24.11.2009    source источник


Ответы (4)


Допустим, ваши загруженные данные содержатся в строке data.

from tarfile import TarFile, TarError
from StringIO import StringIO

sio = StringIO(data)
try:
    tf = TarFile(fileobj=sio)
    # process the file....
except TarError:
    print "Not a tar file"

Существуют дополнительные сложности, такие как обработка различных форматов файлов tar и сжатие. Дополнительная информация доступна в документации tarfile.

person mhawke    schedule 24.11.2009
comment
Возникает вопрос: поддерживает ли модуль Python tarfile различные форматы tar, о которых вы говорите с помощью is_tarfile() при непосредственной проверке файлов? - person Brōtsyorfuzthrāx; 29.01.2016
comment
@Shule Чтобы ответить на этот вопрос, вы можете взглянуть на исходный код модуля для is_tarfile(). - person mhawke; 29.01.2016

Формат файла tar находится здесь в Википедии.

Я подозреваю, что вам лучше всего проверить правильность контрольной суммы заголовка для первого файла. Вы также можете проверить правильность имени файла, но это может быть ненадежно, в зависимости от имен файлов, которые там хранятся.

Дублирую соответствующую информацию здесь:

Offset  Size  Description
     0   100  File name
   100     8  File mode
   108     8  Owner's numeric user ID
   116     8  Group's numeric user ID
   124    12  File size in bytes
   136    12  Last modification time in numeric Unix time format
   148     8  Checksum for header block
   156     1  Link indicator (file type)
   157   100  Name of linked file

Контрольная сумма вычисляется путем взятия суммы значений байтов без знака блока заголовка с восемью байтами контрольной суммы, принятыми за пробелы ASCII (десятичное значение 32).

Он хранится в виде шестизначного восьмеричного числа с ведущими нулями, за которыми следует нуль, а затем пробел.

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

Читатели должны вычислять контрольную сумму в обоих направлениях и рассматривать ее как правильную, если сумма со знаком или без знака совпадает с включенной контрольной суммой.

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

В качестве альтернативы, поскольку Python является открытым исходным кодом, вы можете увидеть, как работает is_tarfile, и адаптировать его для проверки вашего потока, а не файла. Исходный код доступен здесь под Python-3.1.1/Lib/tarfile.py, но он не для слабонервных. сердце :-)

person paxdiablo    schedule 24.11.2009
comment
Существует ли соглашение для кодирования имен файлов, отличных от ASCII? В этой статье упоминается проблема, но не упоминается решение. - person John Machin; 24.11.2009

Метод open класса tarfile принимает файлоподобный объект в качестве аргумента fileObj. Это может быть экземпляр StringIO

person Eli Bendersky    schedule 24.11.2009

Класс TarFile принимает объект fileobj. Я думаю, вы можете передать любой объект частичной загрузки, который вы получаете из своей веб-инфраструктуры.

__init__(self, name=None, mode='r', fileobj=None)

Добавлю к сообщению paxdiablo: tar — очень сложный и сложный формат файла, несмотря на его кажущуюся простоту. Вы можете проверить базовое ограничение, но если вам нужно поддерживать все возможные существующие диалекты tar, вы потеряете много времени. Большая часть его сложности связана со следующими проблемами:

  • отсутствие реального стандарта до тех пор, пока не существовал стандарт де-факто (UStar/pax)
  • пробелы в спецификации оставляют поставщикам серые зоны, где каждый из них реализовал свое собственное решение
  • продавцы говорят "наш tar лучше, и он завоюет мир t3h"
  • ограничения и обходные пути для этих ограничений (например, длина имени файла)

Кроме того, в этом формате нет предварительного заголовка, поэтому единственный способ проверить, в порядке ли весь архив, — это полностью просмотреть файл, отловить каждую запись и проверить каждую.

person Stefano Borini    schedule 24.11.2009
comment
ах, ты опередил меня на полминуты :-) - person Eli Bendersky; 24.11.2009
comment
не совсем, ваш метод - еще один (возможно, лучший) способ добиться того же. - person Stefano Borini; 24.11.2009