Как пропатчить find под FreeBSD?

habr.png

Учим FreeBSD искать файлы по расширенным атрибутам


Аннотация: в ОС FreeBSD на уровне файловой системы реализован механизм управления расширенными атрибутами файла (extattr). При помощи стандартных команд setextattr, getextattr и rmextattr можно создавать, читать и удалять комментарии, ключевые слова и другие метаданные файлов. А вот искать файлы по расширенным атрибутам пока нельзя. К тому же, расширенные атрибуты теряются при копировании файла. В двух статьях я предложу свои патчи для команд find и cp, устраняющие эти недостатки. Однако, я не профессиональный программист и делал патчи под свои задачи, поэтому предложенное решение стоит рассматривать исключительно как proof of concept и дорабатывать напильником.
В наследство от древних времён нам достались монструозные и неповоротливые иерархические файловые системы. Но вместе со стремительным увеличением объёма информации всё ярче проявляется их главный недостаток — ограниченные возможности классификации. Таких возможностей, собственно, две: задавать осмысленные имена файлов и рассортировывать эти файлы по каталогам с осмысленными названиями. Это хорошо работало, когда самая распространённая фотоплёнка содержала всего 36 кадров. Их расходовали неторопливо, подчас в течение нескольких месяцев, тщательно выбирая объекты съёмки. Потом 36 фотографий можно было отсканировать и разместить по папкам «Дача», «Отпуск» и «Кошки». Но сейчас, когда на камеру смартфона можно сделать сотни снимков за день, а из Интернета скачать пару сотен PDF-инструкций за час, такой подход становится чрезмерно трудоёмким. Возросший объём информации уже не получается классифицировать иерархически — человеческий мозг просто запутается в такой иерархии. Поэтому на компьютере со временем появляются каталоги «Новая папка (2)», «Все фотки» и «Разобрать».

В ответ на возникшие ограничения появилась концепция семантической файловой системы. В такой ФС файлам присваиваются некоторые метаданные, по которым затем и осуществляются классификация и поиск. Иерархия каталогов здесь уже не имеет значения, как и имя файла. Яркий пример — облачные объектные хранилища, в которых все объекты располагаются в плоском адресном пространстве и снабжены описывающими их метаданными. Вот только предназначены они для работы на уровне API, а не на уровне пользователя. До настольных систем объектные хранилища пока не добрались.

А мне захотелось присваивать всем своим файлам ключевые слова и хранить их на одном уровне на своей локальной машине прямо сейчас. У меня много интересов, а, поскольку всего не упомнишь, постоянно приходится записывать заметки, рецепты, методики, инструкции и фотографии. Распихивать всё это по папкам — уже нет ни сил, ни времени.

К счастью, настольные ФС подтягиваются к тренду. Во многих из них уже давно можно задавать ключевые слова некоторым типам файлов (в Windows, насколько мне известно, — для вордовских документов и изображений). Правда, в большинстве случаев эти метаданные сохраняются в самом файле, а не на уровне файловой системы (отсюда и ограничение по типу файлов — не все поддерживают EXIF и IPTC). Но моя любимая FreeBSD предоставляет механизм управления расширенными атрибутами файла любого типа именно на уровне файловой системы. Я так понимаю, где-то в недрах ФС создаётся мета-файл, намертво связанный с основным файлом, и все метаданные записываются в него. Для работы с расширенными атрибутами во FreeBSD существует семейство команд setextattr, getextattr и rmextattr.

Простой пример:

$ setextattr user comment cats cat.jpg
$ getextattr user comment cat.jpg
cat.jpg cats


В принципе, с этим уже что-то можно сделать. Если бы не одно «но»: во фряшечке нет механизма поиска файлов по расширенным атрибутам. Что толку от тегирования файлов, если я всё равно не смогу найти их по тегам?

Но если гора не идёт к Магомету… В общем, я решил сам научить фряшечку искать мои документы по ключевым словам. Но я ведь химик-аналитик, а не программист, и кодинг изучал самостоятельно по гуглу. Поэтому, прежде всего я к гуглу и обратился. Вдруг всё давно придумано до меня, и мне не придётся мучительно вспоминать особенности работы с указателями в Си? Оказалось — да, придумано. Я нашёл один патч для команды find. Вот только незадача — патч обучал команду find проверять, установлен ли конкретный атрибут у файла. И всё. А искать по содержимому этого атрибута — увольте.

Пришлось, всё-таки, мучиться с указателями и памятью на Си. Пара бессонных ночей, три литра зелёного чаю и чёрный пояс по гуглению — и у меня получился такой патч (для FreeBSD 11.2.0-RELEASE).

Применить его можно так (во FreeBSD должны быть установлены исходники):

cd /usr/src/usr.bin/find
patch < /patch-find.diff
make
make install clean


А использовать так:

find . -userattr comment=cats
./cat.jpg


Эта команда найдёт все файлы, у которых атрибут comment содержит подстроку cats.

Конечно, о каком-то рабочем решении здесь говорить рановато — в моём коде практически нет проверок входного параметра, да и размеры буферов взяты от балды (где-то читал, что ограничение на размер расширенного атрибута — 1024 байта, но потом не смог найти эту информацию). Приглашаю всех желающих поучаствовать в доведении проекта до готовности и выкладываю полный код утилиты find, честно скопированный из официального репозитория FreeBSD, с моими изменениями.

… Итак, теперь я мог худо-бедно искать файлы по ключевым словам. Но возникла новая напасть: при копировании файла все связанные с ним расширенные атрибуты терялись… Проблема была в команде cp, но об этом в следующий раз.

© Habrahabr.ru