Как пропатчить cp под FreeBSD? +11



Учим 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):

  1. KYuri
    /#19222075 / +3

    Чувствую, так и до KDE дело дойдёт)

  2. Sabubu
    /#19222585

    Мне не нравится ваше решение. Это годится только в одном случае: если нужно срочно сделать приватный патч для себя для одноразовой задачи.

    Нормальное решение — не накапливать различия между ОС, а портировать API из Netbsd (если оно совместимо с FreeBSD). Работа с атрибутами должна вестись через разделяемую библиотеку, как в Windows, а не так, что каждая программа содержит свой вариант реализации.

    • Karpion
      /#19223895

      Вот это правильный совет. Делать «каждая программа содержит свой вариант реализации» допустимо на уровне разработки, как proof of concept. Но потом надо будет нормально портировать.
      И если в NetBSD всё эт уже есть — то надо не патчить программы самостоятельно, а просто портировать. Желательно — с минимальными изменениями.

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

      • scifinder
        /#19224759

        Во FreeBSD это всё тоже есть, только в виде отдельных команд. В NetBSD просто добавили удобную оболочку для этой последовательности. В итоге, во FreeBSD нужно выполнить цепочку команд «получить список атрибутов файла А — пройтись по списку и прочитать атрибуты — запомнить в буфер — записать атрибуты в файл Б из буфера», а в NetBSD просто «скопировать атрибуты из файла А в файл Б» (а под капотом у неё та же самая последовательность).

        • Apx
          /#19232283

          Всего один вопрос why not alias/function в своём rc файле любимого терминала? Может быть глобальным, действие/кодинг выполняется всего один раз, сохраняет "атомарность" cp.

          • Sirikid
            /#19233047

            Разумный дефолт, тем более что копирует не по умолчанию, а с флагом. Вот его то в алиас и заворачивать.

    • eirnym
      /#19223977

      Это идеальное решение в случае наличия ресурсов у автора и/или поддерживающего окружения. Можно начать с двух feature request, при положительном отклике со стороны FreeBSD — сделать остальное. В случае reject можно сделать порт в виде патча к исходному коду и установке в качестве отдельной программы (в этом случае даже отдельного репозитория не нужно)

    • scifinder
      /#19224751

      Согласен, что в библиотеку extattr во FreeBSD неплохо бы перенести дополнительный функционал из таковой для NetBSD. Сам очень удивился, когда обнаружил, что читать, писать и удалять расширенные атрибуты FreeBSD может, а скопировать из одного файла в другой — нет. Когда стал разбираться внимательнее, понял, что FreeBSD умеет всё это делать, но по частям. Например, чтобы скопировать расширенные атрибуты, нужно последовательно выполнить lsextattr и getextattr на первом файле и setextattr на втором. А в NetBSD для всей этой последовательности просто придумали красивую обёртку и добавили в библиотеку extattr. FreeBSD, как более консервативная система, скорее всего, придерживается взгляда, что раз функционал можно выполнить последовательностью команд, то нет смысла создавать для этой последовательности обёртку в виде одной команды.

      Поэтому я и принял решение обёртку над последовательностью стандартных команд lsextattr, getextattr и setextattr добавить в файл utils.c исходников утилиты cp. В результате, мой код точно также использует разделяемую библиотеку.

  3. eirnym
    /#19224013

    Есть одно замечание по существу.


    В среде *BSD принято, что если что-то меняется, это либо должно быть очень хорошо обосновано, либо быть опциональным. Я пока не вижу ни одного "за", почему предложенный функционал (1) должен быть включён по-умолчанию и (2) не может быть выключен.

    • scifinder
      /#19224713

      Конечно, можно добавить проверку на флаг -p и копировать атрибуты только с включённым флагом. А для своей задачи создать alias вида «cp -p» -> «cp». Именно поэтому я ещё в предыдущей публикации утверждал, что оба моих патча — это только proof of concept. С другой стороны, в ОС от Apple копирование расширенных атрибутов вместе с файлом включено по-умолчанию. Чтобы разобраться, как будет лучше и удобнее, я и опубликовал свои наработки.