Учим FreeBSD копировать вместе с файлами их расширенные атрибуты
Я большой поклонник cp — по изящности и несокрушимости эта утилита, на мой взгляд, уступает только утилите dd. Но под FreeBSD у неё есть один скромный недостаток — при копировании файла cp теряет его расширенные атрибуты (extattr). В предыдущей публикации я предложил патч для команды find, который добавляет возможность осуществлять поиск файлов по содержимому их расширенных атрибутов. Но какой в этом смысл, если ваши ключевые слова и комментарии потеряются при копировании файла? Пора брать последний бастион на пути полной поддержки расширенных атрибутов во фряшечке.
Как всегда, помог Google. Во-первых, нашлась интересная статья "Extended attributes: the good, the not so good, the bad", в которой предлагается обходной путь решения задачи поиска файлов по содержимому их расширенных атрибутов. То есть, то, что я в предыдущей публикации пытался решить на уровне патча утилиты find, здесь решено штатными средствами ОС. Из этой же статьи следует, что завоевание cp — похоже, действительно, последний рубеж, который необходимо преодолеть для активации полноценной поддержки extattr во фряшечке.
Далее, Google подсовывает патч для NetBSD, заставляющий cp копировать расширенные атрибуты. Его почитать — так там вообще делать нечего. Стоит только в нужном месте исходного кода добавить эту строку:
if (pflag && (fcpxattr(from_fd, to_fd) != 0))
warn("%s: error copying extended attributes", to.p_path);
И всё. Можно копировать. Хорошо, идём в исходники FreeBSD, открываем файл utils.c, добавляем в него заветные строки и… Приехали. FreeBSD не знает, что такое fcpxattr(). Вообще, за объявление этой функции отвечает заголовочный файл sys/extattr.h, но он о ней тоже не знает. Все эти fcpxattr — это фишка NetBSD. У них sys/extattr.h проапгрейден относительно FreeBSD.
Но моя задача была — обучить cp копировать расширенные атрибуты, а не перелопачивать половину ядра системы. Поэтому, ничтоже сумняшеся, я решил требуемый extattr-функционал включить в исходники cp. Конечно, с точки зрения целостности системы это неправильно, но как патч под конкретную задачу — сойдёт.
Чтобы наделать поменьше ошибок в коде, я поискал NetBSD-шные исходники extattr.c и взял их за образец.
В итоге, у меня получился такой патч (для FreeBSD 11.2.0-RELEASE).
Применить его можно так:
cd /usr/src/bin/cp
patch < /patch-cp.diff
make
make install clean
Если вы обратили внимание, в моём варианте расширенные атрибуты копируются всегда, а не только с флагом -p, как в варианте для NetBSD. Мне показалось, что так удобнее. В любом случае, как и в предыдущей публикации, я выложил на Github полный код утилиты cp, скопированный из репозитория FreeBSD, с моими изменениями. Чтобы вы тоже могли развлечься.
Автор: scifinder