7.4. Определение является ли файл бинарным, текстовым или содержащим данные

Описание:  Системы BSD используют соглашения об именовании файлов, для того, чтобы было проще определить чем является файл. Однако кандидат должен понимать, что это только соглашения и уметь использовать базу данных magic для определения того, чем является файл.

Практика: file(1), magic(5)

Комментарий

Команда file(1) предназначена для того, чтобы определить тип файла.

$ file test.pdf
test.pdf: PDF document, version 1.4
$ mv test.pdf test
$ file test
test: PDF document, version 1.4
        

Как видите, команда file(1) в состоянии распознать тип файла даже если он лишён расширения. Делает это она при помощи некоторой базы данных с «магическими» числами: /usr/share/misc/magic. Формат этой базы описан в странице man magic(5).

Первым делом команда file(1) пытается выяснить чем собственно является файл не изучая его содержимого, при помощи системного вызова stat(2). Таким образом определяется является ли файл файлом, каталогом, символьной ссылкой, сокетом, устройством или именованным каналом. Если это файл, то не пуст ли он.

Затем, если это файл, изучается его содержимое. На этой стадии выясняется является ли этот файл исполнимым, если да, то в каком формате. Ниже я скопировал исполнимый файл /bin/bash с Linux-машины и напустил команду file(1) на него и на bash собранный для FreeBSD.

$ file ./bash /usr/local/bin/bash
./bash:              ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
for GNU/Linux 2.0.0, dynamically linked (uses shared libs), stripped
/usr/local/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1
(FreeBSD), for FreeBSD 5.0.2, dynamically linked (uses shared libs), stripped
        

Как видите, file отличает для какой операционной системы скомпилирована программа. Правила, по которым она это делает, как уже говорилось, прописаны в базе данных /usr/share/misc/magic. В этом файле сказано что где и как надо искать в файле для того, чтобы отнести его к какому-нибудь виду. Например, файлы в формате PDF как правило начинаются со стороки

$ head -1 test.pdf
%PDF-1.4
        

В базе magic(5) про формат PDF написано так:

#------------------------------------------------------------------------------
# pdf:  file(1) magic for Portable Document Format
#

0       string          %PDF-           PDF document   1
>5      byte            x               \b, version %c 2
>7      byte            x               \b.%c          3
        

1 Начиная с нулевого байта искать строку %PDF- (т.е. файл обязан начинаться именно так).
2 Пятый байт обозначает номер версии
3 Седьмой байт — младший номер версии