Учим 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, с моими изменениями. Чтобы вы тоже могли развлечься.
Комментарии (13)
Sabubu
11.10.2018 17:36Мне не нравится ваше решение. Это годится только в одном случае: если нужно срочно сделать приватный патч для себя для одноразовой задачи.
Нормальное решение — не накапливать различия между ОС, а портировать API из Netbsd (если оно совместимо с FreeBSD). Работа с атрибутами должна вестись через разделяемую библиотеку, как в Windows, а не так, что каждая программа содержит свой вариант реализации.Karpion
11.10.2018 22:46Вот это правильный совет. Делать «каждая программа содержит свой вариант реализации» допустимо на уровне разработки, как proof of concept. Но потом надо будет нормально портировать.
И если в NetBSD всё эт уже есть — то надо не патчить программы самостоятельно, а просто портировать. Желательно — с минимальными изменениями.
И кстати — надо предусмотреть вариант, когда исходная или целевая файловая система не поддерживает эти атрибуты.scifinder Автор
12.10.2018 07:04Во FreeBSD это всё тоже есть, только в виде отдельных команд. В NetBSD просто добавили удобную оболочку для этой последовательности. В итоге, во FreeBSD нужно выполнить цепочку команд «получить список атрибутов файла А — пройтись по списку и прочитать атрибуты — запомнить в буфер — записать атрибуты в файл Б из буфера», а в NetBSD просто «скопировать атрибуты из файла А в файл Б» (а под капотом у неё та же самая последовательность).
Apx
13.10.2018 22:57Всего один вопрос why not alias/function в своём rc файле любимого терминала? Может быть глобальным, действие/кодинг выполняется всего один раз, сохраняет "атомарность" cp.
Sirikid
14.10.2018 08:19Разумный дефолт, тем более что копирует не по умолчанию, а с флагом. Вот его то в алиас и заворачивать.
eirnym
11.10.2018 23:11Это идеальное решение в случае наличия ресурсов у автора и/или поддерживающего окружения. Можно начать с двух feature request, при положительном отклике со стороны FreeBSD — сделать остальное. В случае reject можно сделать порт в виде патча к исходному коду и установке в качестве отдельной программы (в этом случае даже отдельного репозитория не нужно)
scifinder Автор
12.10.2018 06:57Согласен, что в библиотеку extattr во FreeBSD неплохо бы перенести дополнительный функционал из таковой для NetBSD. Сам очень удивился, когда обнаружил, что читать, писать и удалять расширенные атрибуты FreeBSD может, а скопировать из одного файла в другой — нет. Когда стал разбираться внимательнее, понял, что FreeBSD умеет всё это делать, но по частям. Например, чтобы скопировать расширенные атрибуты, нужно последовательно выполнить lsextattr и getextattr на первом файле и setextattr на втором. А в NetBSD для всей этой последовательности просто придумали красивую обёртку и добавили в библиотеку extattr. FreeBSD, как более консервативная система, скорее всего, придерживается взгляда, что раз функционал можно выполнить последовательностью команд, то нет смысла создавать для этой последовательности обёртку в виде одной команды.
Поэтому я и принял решение обёртку над последовательностью стандартных команд lsextattr, getextattr и setextattr добавить в файл utils.c исходников утилиты cp. В результате, мой код точно также использует разделяемую библиотеку.
eirnym
11.10.2018 23:19Есть одно замечание по существу.
В среде *BSD принято, что если что-то меняется, это либо должно быть очень хорошо обосновано, либо быть опциональным. Я пока не вижу ни одного "за", почему предложенный функционал (1) должен быть включён по-умолчанию и (2) не может быть выключен.
scifinder Автор
12.10.2018 06:31Конечно, можно добавить проверку на флаг -p и копировать атрибуты только с включённым флагом. А для своей задачи создать alias вида «cp -p» -> «cp». Именно поэтому я ещё в предыдущей публикации утверждал, что оба моих патча — это только proof of concept. С другой стороны, в ОС от Apple копирование расширенных атрибутов вместе с файлом включено по-умолчанию. Чтобы разобраться, как будет лучше и удобнее, я и опубликовал свои наработки.
KYuri
Чувствую, так и до KDE дело дойдёт)
scifinder Автор
А в KDE тоже проблема с extattr?))
SemmZemm
Вряд ли, Хабр не специализируется на аниме
ivan386
Хмм.
поиск по слову "аниме"
Публикации 263
Хабы и компании 1
Пользователи 238
Комментарии 1k
Первая статья в списке "Как создается аниме"