Skip to content

Latest commit

 

History

History
1376 lines (975 loc) · 123 KB

File metadata and controls

1376 lines (975 loc) · 123 KB

Link to the English language README page

Precizer — проверка целостности данных для файловых систем любого масштаба

Крошечное, высокопроизводительное приложение для проверки целостности файлов

«По-настоящему хорошая программа всегда поместится на дискету. Есть надежда, что кто-то всё ещё помнит, что это такое… Речь идёт не о дискетах, а о качественных программах!»© :-D

Содержание

Continuous integration and automation

Гибридный интеграционно-системный набор тестов

  • In-process integration tests
  • Out-of-process CLI system tests
  • Unit tests

Test coverage:

Total completed tests
Lines of code covered by tests
Functions covered by tests
Code branches covered by tests

Automated builds:

precizer build & testing

Security:

OpenSSF Best Practices
OpenSSF Scorecard

КРАТКО О ПРОГРАММЕ

Обзор

precizer — крошечное и быстрое консольное приложение, полностью написанное на чистом Си. Предназначено для проверки целостности и сравнения файлов. Особенно полезно для проверки результатов синхронизации. Программа обходит дерево каталогов и создаёт базу данных файлов и их контрольных сумм с последующим быстрым сравнением.

precizer предназначается как для работы на embedded-платформах, так и для файловых систем гигантского размера в кластерных мейнфрейм-окружениях. С помощью программы можно находить ошибки синхронизации, сравнивая файлы и их контрольные суммы из разных источников. Также precizer можно использовать для исследования исторических изменений, сравнивая базы данных, полученные из одного и того же источника в разные моменты времени.

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

Допустим, есть две машины, у которых в /mnt1 и /mnt2 соответственно примонтированы диски большого объёма с идентичным содержимым. Стоит задача побайтно проверить, действительно ли содержимое абсолютно идентично или есть различия.

  1. Запустить программу на первой машине с hostname, например «host1»:
precizer --progress /mnt1

В результате работы программы будут исследованы все директории, начиная с /mnt1, и в текущей директории будет создана база данных host1.db. Параметр --progress визуализирует прогресс и покажет объём пространства и количество исследуемых файлов.

  1. Запустить программу на второй машине с hostname, например «host2»:
precizer --progress /mnt2

В результате будет создана база данных host2.db в текущей директории.

  1. Скопировать файлы с базами данных host1.db и host2.db на одну из машин и запустить программу с соответствующими параметрами для сравнения:
precizer --compare host1.db host2.db

На экран будет выведена следующая информация:

  • Какие файлы отсутствуют на «host1», но при этом присутствуют на «host2» и наоборот.
  • Для каких файлов, присутствующих на обоих хостах, контрольные суммы НЕ совпадают.

Относительные пути в базе данных для сравнения

Следует обратить внимание, что precizer записывает в базу данных только относительные пути. Файл

/mnt1/abc/def/aaa.txt

из приведённого примера будет записан в базу данных как

abc/def/aaa.txt

без /mnt1. То же самое произойдёт с файлом

/mnt2/abc/def/aaa.txt

Смысл в том, что, несмотря на разные точки монтирования и разные источники, файлы можно будет сравнить между собой под одинаковыми именами

abc/def/aaa.txt

и с соответствующими контрольными суммами.

Скачивание/Download

Подходящий пакет определяется по операционной системе и архитектуре процессора.

Linux

64-разрядный процессор Intel или AMD (x86_64)

Скачать precizer для Linux x86_64

Переносимая статически слинкованная сборка для большинства настольных и серверных дистрибутивов Linux. Дополнительные динамические библиотеки не требуются

64-разрядный процессор ARM (ARM64 / AArch64)

Скачать precizer для Linux ARM64

Переносимая статически слинкованная сборка для 64-разрядных ARM-систем. Дополнительные динамические библиотеки не требуются

Windows

Поддержка Windows экспериментальная.

64-разрядный процессор Intel или AMD (x64)

Скачать ZIP-пакет для Windows

Рекомендуемый пакет для Windows. После распаковки архива файлы precizer.exe и msys-2.0.dll должны находиться в одном каталоге

Скачать отдельный EXE-файл для Windows

Самораспаковывающийся исполняемый файл, не требующий отдельных файлов библиотек среды выполнения. Поддержка Windows экспериментальная и исполняемый файл не имеет цифровой подписи, поэтому Defender может показать предупреждение

macOS

Сборки для macOS используют динамические библиотеки. Необходимые для запуска пакеты перечислены в разделе «Системные библиотеки для запуска приложения».

Процессор Apple Silicon (M1 или новее, ARM64)

Скачать precizer для macOS Apple Silicon ARM64

Процессор Intel (x86_64)

Скачать precizer для macOS Intel x86_64

Автоматическое скачивание, распаковка и запуск в Linux и macOS

Этот сценарий определяет операционную систему и архитектуру процессора, скачивает подходящую сборку последнего релиза, распаковывает её и проверяет запуск precizer

# Automation for downloading and unarchiving new versions

# Download
wget -O precizer.zip -q "https://github.com/precizer/precizer/releases/latest/download/precizer_$(uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/macos/')_$(uname -m | sed 's/amd64/x86_64/')$( [ "$(uname -s)" = "Linux" ] && echo '_portable' ).zip"

# Extract the archive
unzip -jqo precizer.zip '*/precizer' -d ./

# Run
./precizer --version

Технические детали portable сборки

  • Готовая Linux сборка представляет собой один исполняемый, статически слинкованный бинарный файл в формате ELF, не привязанный к какому-либо определённому дистрибутиву. Файл может быть запущен сразу, практически на любом дистрибутиве Linux и не требует использования внешних, динамически подгружаемых библиотек.

  • Файл собирается CI/CD автосборкой actions GitHub, затем сжимается с помощью UPX (архиватора исполняемых файлов). После этого самораспаковывающийся сжатый бинарный файл вкладывается в ZIP-архив для удобного скачивания. Для использования достаточно распаковать файл из архива и запустить.

  • ZIP-пакет для Windows x64: программа собирается в среде MSYS2 (MSYS) и основные компоненты линкуются статически. Архив содержит precizer.exe и библиотеку среды выполнения msys-2.0.dll; после распаковки они должны оставаться в одном каталоге. Устанавливать MSYS2 для запуска не нужно

  • Отдельный EXE для Windows x64: самораспаковывающийся загрузчик содержит внутри те же precizer.exe и msys-2.0.dll. При запуске он извлекает их в пользовательский кэш и запускает программу, а при следующих запусках повторно использует сохранённые файлы. Загрузчик собирается средствами MinGW-w64/UCRT. Исполняемый файл сжат с помощью UPX для уменьшения размера. Отдельно устанавливать MSYS2 или размещать DLL рядом со скачанным EXE не требуется

  • На macOS статическая линковка не поддерживается. Необходимые для запуска приложения системные библиотеки перечислены в разделе «Системные библиотеки для запуска приложения».

ИСТОРИЯ ИЗМЕНЕНИЙ

Список изменений по версиям можно найти в отдельном файле CHANGELOG

ТЕХНИЧЕСКИЕ ПОДРОБНОСТИ АЛГОРИТМОВ РАБОТЫ

Рассмотрим сценарий, когда имеется основное дисковое хранилище и его копия. Например, это может быть хранилище датацентра и его Disaster Recovery‑копия. Периодически происходит синхронизация с основного хранилища на резервное, но по причине огромных объёмов данных, скорее всего, синхронизация происходит не побайтно, а за счёт вычисления изменений среди метаданных файлов на файловой системе. В таких случаях учитывается размер файла и время модификации, но изменившееся содержимое байт за байтом не исследуется. В этом есть смысл, потому что между основным датацентром и резервным Disaster Recovery‑центром, как правило, хорошие каналы связи, но полная побайтовая синхронизация может занять нецелесообразно много времени. Такие инструменты, как rsync, позволяют производить синхронизацию по обеим методикам: как с учётом изменившихся файлов, так и побайтово, но у них есть один серьёзный недостаток — состояние не сохраняется между сессиями. Что это значит, рассмотрим детально:

  • Даны: сервер «A» и сервер «B» (основной датацентр и резервный Disaster Recovery‑центр)
  • На сервере «A» изменились некоторые файлы.
  • Алгоритм rsync их определил за счёт изменившегося размера и времени модификации файла и синхронизировал на сервер «B».
  • Во время синхронизации между основным датацентром и Disaster Recovery‑центром происходили многократные сбои связи.
  • Для проверки целостности данных (эквивалентности сохранённых файлов на «A» и «B» байт в байт) обычно используют тот же rsync только с включением побайтного сравнения. Для этого:
    • rsync запускается на сервере «A» в режиме --checksum и во время одного сеанса пытается подсчитать контрольные суммы последовательно: сначала на «A», а затем на «B».
    • Этот процесс занимает неимоверно много времени для огромных дисковых массивов.
    • Так как rsync не позволяет сохранять состояние уже подсчитанных контрольных сумм между сеансами, возникает целый ряд технических сложностей. А именно:
      • В случае разрыва соединения rsync завершает сеанс и в следующий запуск всё нужно начинать сначала! С учётом огромных объёмов побайтовая проверка данных на полную идентичность таким образом превращается в нереализуемую задачу.
    • Причиной неидентичности бинарного содержимого файлов могут стать также сбои на уровне дисковой подсистемы. В таких случаях с помощью метаданных файловой системы невозможно будет определить, есть ли разница между содержимым внутри файлов на серверах «A» и «B», или нет.
    • Со временем ошибки накапливаются и появляется угроза получить неконсистентную копию системы «A» на системе «B», что сводит на нет все усилия и затраты по поддержанию Disaster Recovery‑центра. При этом стандартные утилиты не обладают возможностями проверок и технический персонал даже не будет знать о накопившихся проблемах с неэквивалентным содержанием дисковых массивов на Disaster Recovery‑центре.
  • Для устранения вышеописанных недостатков создана программа precizer. Программа позволяет выявить, какие именно файлы отличаются между «A» и «B» для проведения повторной синхронизации с устранением отличий. Программа работает максимально быстро (практически на грани аппаратных возможностей) за счёт того, что написана на чистом Си и использует современные алгоритмы, оптимизированные под высокую производительность. Программа предназначена для работы как с мелкими файлами, так и с объёмами данных, измеряемыми петабайтами, и не ограничена этими цифрами.
  • Название программы precizer происходит от слова precision (точность) и означает что-то, что увеличивает точность.
  • Программа с высокой точностью исследует содержимое директорий, субдиректорий и подсчитывает контрольные суммы для каждого встреченного файла, при этом сохраняя метаинформацию о всех файлах в SQLite базе (обычный бинарный файл).
  • precizer можно остановить и затем продолжить без риска для проверяемых данных. Программа не меняет исследуемые файлы и каталоги, а сохраняет только собственный прогресс и результаты в SQLite-базу.
  • Если пользователь нажал Ctrl+C или процесс завершился во время обработки большого файла, precizer использует уже сохранённый прогресс в БД. При следующем запуске с --update программа продолжит хеширование с ближайшей сохранённой точки, а не обязательно с самого начала файла.
  • Во время долгого подсчёта SHA512 precizer регулярно сохраняет прогресс. Сейчас программа старается делать это примерно раз в 14 930 016 475 наносекунд, поэтому после аварийного завершения обычно теряется не вся работа по большому файлу, а только небольшой участок после последнего сохранения.
  • Если файл изменился после сохранения промежуточного прогресса, старому прогрессу доверять нельзя. В таком случае precizer начнёт считать SHA512 для этого файла заново, чтобы итоговая контрольная сумма относилась к текущему содержимому файла.
  • Для промежуточного прогресса проверка специально строгая: precizer продолжает с сохранённого места только если текущий файл выглядит точно так же, как в момент сохранения прогресса. Должны совпасть размер файла, количество занятых блоков на диске, если оно доступно на этой файловой системе, а также mtime и ctime. Если отличается хотя бы один из этих признаков, программа считает, что файл мог измениться, и начинает расчёт SHA512 с начала.
  • В режимах --dry-run и --dry-run=with-checksums прогресс в БД не сохраняется, потому что эти режимы не должны изменять базу данных.
  • Для обычного файла в БД может временно храниться состояние для продолжения хеширования, а не полная SHA512. То же возможно для файла, который уже попал под --lock-checksum, но ещё не был дочитан до конца: при повторном запуске precizer продолжит расчёт с сохранённого места. После успешного завершения чтения временное состояние заменяется полной SHA512. С этого момента защищённый файл считается запечатанным: уже сохранённая полная SHA512 становится эталоном, и временная запись о ходе последующей проверки больше не затирает эту эталонную контрольную сумму.
  • Для подсчёта контрольных сумм используется криптографически стойкий, надёжный и быстрый алгоритм SHA512 с очень высокой практической устойчивостью к коллизиям. Если два больших файла различаются хотя бы на один байт, SHA512 с подавляющей вероятностью отразит это в разных контрольных суммах; в отличие от CRC32 и устаревшего SHA1, этот алгоритм предназначен именно для надёжной проверки целостности данных
  • precizer поддерживает актуальность базы с путями к файлам и их контрольными суммами без полного пересчёта. При запуске с --update в БД добавляются новые файлы и удаляются записи об исчезнувших файлах. Для файлов с уже сохранённой полной SHA512 контрольная сумма пересчитывается при изменении размера файла или времени модификации (mtime), и результат обновляетя в БД
  • При --update записи об отсутствующих файлах удаляются, но записи о недоступных файлах (например, из-за прав доступа) по умолчанию сохраняются. Такая защита нужна потому, что права могут временно меняться (владелец, ACL, проблемы монтирования), и при удалении записей в этот момент можно незаметно потерять корректную историю в БД. Использование --db-drop-inaccessible вместе с --update оправдано только если нужно действительно удалить эти записи из БД.
  • При включённом --progress предупреждения и ошибки, накопленные в течение сессии, выводятся единым блоком перед завершением программы, чтобы важные сообщения (например, об отсутствии доступа к файлам) не терялись на фоне второстепенных логов.
  • Опция --quiet-ignored отключает вывод строк о файлах, отфильтрованных через --ignore и --include. Это помогает не засорять логи программы лишними сообщенями, когда регулярные выражения для игнорирования уже отлажены и стабильны в работе; остальные предупреждения и ошибки продолжают выводиться.
  • Можно указать опцию, при которой при обновлении БД будет учитываться не только размер изменившихся файлов, но также и время изменения метаданных (ctime) или содержимого файлов (mtime). Это значит, что изменения любой метаинформации о файле приведут к пересчёту контрольной суммы SHA512 с последующим обновлением данных о файле в БД. Например, если у файла изменился ctime, но размер и mtime остались прежними, контрольная сумма не будет пересчитана при использовании только --update. Для пересчёта необходимо добавить --watch-timestamps. Эта опция не включена по умолчанию, потому что ctime могут меняться часто, например, командами chmod или chown, при том, что само содержимое файла остаётся прежним.
  • precizer может служить инструментом контроля безопасности, определяя последствия вторжения за счёт выявления несанкционированно изменённых файлов, у которых могло быть модифицировано содержимое, но метаданные могли остаться прежними.
  • Безопасность:
    • Программа никогда не меняет, не удаляет, не перемещает и не копирует ни файлы, ни исследуемые директории.
    • Программа составляет списки файлов, контрольные суммы содержимого этих файлов и сохраняет их в локальной базе данных. Все изменения происходят исключительно в границах базы данных.
    • База данных не хранит содержимое файлов, только их относительные пути, контрольные суммы и такие метаданные, как размер и даты ctime и mtime.
    • Программа не открывает сокеты.
    • Не передаёт данные куда-либо.
    • Не требует привилегированных прав для исполнения и не использует SUID-бит или какие-либо другие небезопасные биты.
    • В программе нет ничего, что может эксплуатироваться для повышения привилегий или других нарушений безопасности.
  • Производительность программы в основном упирается в производительность дисковой подсистемы. Каждый файл считывается побайтно, и для каждого файла формируется своя контрольная сумма с использованием алгоритма SHA512.
  • Программа работает очень быстро благодаря библиотекам SQLite и FTS (man 3 fts).
  • Разбор параметров строки реализован через библиотеку ARGP.
  • Для регулярных выражений выбрана библиотека PCRE2.
  • Программа безопасна для случаев с огромным количеством файлов, директорий и поддиректорий любой вложенности. Благодаря библиотеке FTS рекурсия не используется, поэтому не произойдёт переполнения стека даже в случае большой вложенности файлов.
  • За счёт своей компактности и переносимости кода программа может использоваться даже на специализированных устройствах типа NAS, а также на embedded- или IoT-устройствах.
  • Если любопытно узнать, что содержится внутри базы данных, сформированной precizer, то можно воспользоваться удобным GUI DB Browser for SQLite.

ВОПРОСЫ И БАГРЕПОРТЫ

УЧАСТИЕ В ПРОЕКТЕ

Участие в развитии проекта приветствуется. Начните с CONTRIBUTING: там описаны рабочий процесс, зависимости, шаги проверки и требования к pull request. Актуальные запросы на усовершенствования можно выбрать в списке Issues по уровню и интересу.

СБОРКА И УСТАНОВКА

Пакетирование для дистрибутивов

  • Автор был рад подготовить автоматическую сборку средствами GitHub CI Workflows и будет в дальнейшем поддерживать новые версии.
  • Автор НЕ готов самостоятельно создавать и поддерживать в будущем пакетирование программы precizer под все существующие дистрибутивы операционных систем.
  • Если Вы горите желанием создать пакет под любой дистрибутив и столкнулись с непреодолимыми трудностями по адаптации кода программы, то именно в этом случае автор будет очень рад оказать всю необходимую помощь в поддержке инициативы и оптимизации кода программы под конкретный дистрибутив или пакетный менеджер. Как связаться с автором, описано в разделе «Вопросы и багрепорты».

Сборка с помощью Docker

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

  • Almalinux
  • Alpine
  • Arch
  • Debian
  • Fedora
  • Gentoo
  • Rocky
  • Ubuntu

Ознакомиться с подробностями настроек и устанавливаемыми библиотеками можно в соответствующих Docker‑файлах в поддиректории проекта .docker/

Для сборки достаточно указать команду make, ключевое слово docker, дистрибутив debian (например), а затем цель dynamic-production или другой вариант сборки.

Пример сборки в контейнере:

make docker-gentoo-production

Команда соберёт программу в режиме production в контейнере Gentoo и сохранит готовый архив precizer_linux_<архитектура>_production.zip в корне проекта.

Инструменты сборки и библиотеки устанавливаются внутри контейнера; на основной системе достаточно только Docker. Для переносимой сборки лучше всего использовать make docker-gentoo-portable как на наиболее универсальный вариант.

Самостоятельная сборка

Для получения исходного кода требуется Git. Команды сборки выполняются из корня проекта после установки зависимостей для соответствующей операционной системы

git clone --depth=1 https://github.com/precizer/precizer.git
cd precizer

Все цели сборки учитывают переданные через окружение или командную строку переменные CPPFLAGS, CFLAGS и LDFLAGS. Обязательный стандарт языка -std=c2x добавляется отдельно и не отключается переопределением CFLAGS

При необходимости предыдущие сборки и артефакты удаляются командой:

make purge

Linux

Следующие команды устанавливают компилятор, инструменты и заголовочные файлы библиотек, необходимые для сборки приложения. UPX сжимает копию программы для архива в целях portable, production и dynamic-production; для цели distribution он не нужен

Зависимости для запуска нужны только динамическим сборкам dynamic-production и distribution. Статические сборки portable и production включают необходимые библиотеки в исполняемый файл и не требуют перечисленных ниже пакетов для запуска

Команды установки зависимостей, используемые при автоматической сборке поддерживаемых дистрибутивов, приведены в соответствующих Dockerfile в каталоге .docker/

Arch Linux

Инструменты и библиотеки для сборки:

sudo pacman -S --needed base-devel sqlite pcre2 upx zip unzip

Для запуска динамической сборки:

sudo pacman -S --needed sqlite pcre2
Ubuntu/Debian Linux

Инструменты и библиотеки для сборки:

sudo apt update
sudo apt -y install gcc make libpcre2-dev libsqlite3-dev upx-ucl zip unzip

Для запуска динамической сборки:

sudo apt -y install libpcre2-8-0 libsqlite3-0
Alpine Linux

Инструменты и библиотеки для сборки:

sudo apk add --no-cache build-base pcre2-dev pcre2-static fts-dev argp-standalone sqlite-dev upx zip unzip

Для запуска динамической сборки:

sudo apk add --no-cache pcre2 sqlite-libs argp-standalone fts
AlmaLinux/Rocky/Fedora Linux

Инструменты и библиотеки для сборки:

Набор доступных репозиториев и названия пакетов со статическими библиотеками различаются между выпусками этих дистрибутивов. Для сборки всех вариантов нужны GCC, Make, заголовочные и статические библиотеки glibc, SQLite и PCRE2, а также UPX и ZIP:

sudo dnf -y install gcc make sqlite sqlite-devel glibc-devel pcre2 pcre2-devel upx pcre2-static glibc-static zip unzip

В AlmaLinux и Rocky Linux пакеты pcre2-static и glibc-static могут потребовать предварительного подключения репозиториев CRB, EPEL и репозитория для разработчиков

Подробные команды подключения репозиториев и установки пакетов приведены в Dockerfile соответствующего дистрибутива в каталоге .docker/

Для запуска динамической сборки:

sudo dnf -y install sqlite-libs pcre2
Gentoo Linux

Инструменты и библиотеки для сборки:

echo "dev-libs/libpcre2 static-libs" | sudo tee /etc/portage/package.use/libpcre2
sudo emerge dev-libs/libpcre2 app-arch/upx app-arch/zip app-arch/unzip

Для запуска динамической сборки:

sudo emerge dev-db/sqlite dev-libs/libpcre2
Варианты сборки с помощью Make

Доступны четыре варианта сборки: portable, production, dynamic-production и distribution. Подходящий вариант определяется требованиями к переносимости, производительности и системным библиотекам

Портируемый бинарный файл

make portable

Результатом сборки будет ZIP-архив, содержащий один статически слинкованный, самораспаковывающийся сжатый UPX файл в формате ELF, без каких-либо динамических зависимостей. Этот файл представляет собой всю программу целиком и может быть запущен практически на любом современном дистрибутиве Linux. Файл переносим между системами с той же архитектурой процессора (x64, ARM и другими)

Программа оптимизирована под максимальную переносимость

Особенности компиляции и линковки: -static -O2 -mtune=generic

Альтернатива с использованием Docker:

make docker-gentoo-portable

Вместо -gentoo- может быть указан любой из перечисленных выше дистрибутивов

Единый бинарный файл с оптимизацией под локальный CPU

make production

Архив содержит заточенный под локальный CPU, статически слинкованный, самораспаковывающийся, сжатый UPX файл в формате ELF, не нуждающийся в отдельных библиотеках. Этот файл представляет собой всю программу целиком, может быть запущен на локальном компьютере и будет использовать все возможности CPU по-максимуму

Программа оптимизирована под предельно возможную производительность на локальном железе

Особенности компиляции и линковки: -static -O3 -march=native

Альтернатива с использованием Docker:

make docker-gentoo-production

Вместо -gentoo- может быть указан любой из перечисленных выше дистрибутивов

Исполняемый файл с динамически подгружаемыми библиотеками и оптимизацией под локальный CPU

make dynamic-production

Архив содержит исполняемый файл размером около 50 килобайт в формате ELF. Он будет заточен под локальный CPU, динамически слинкован с установленными в системе библиотеками, самораспаковывающийся, сжатый UPX. Этот файл может быть успешно собран и запущен на локальном компьютере, если в системе были предварительно установлены такие библиотеки, как sqlite3, pcre2, argp и fts

Файл оптимизирован под максимальную производительность и минимальный размер

При работе программа использует установленные в системе динамические библиотеки. Они могут быть собраны с параметрами оптимизации, отличающимися от параметров сборки precizer, поэтому общая производительность также зависит от этих библиотек

Особенности компиляции: -O3 -march=native

Альтернатива с использованием Docker:

make docker-gentoo-dynamic-production

Вместо -gentoo- может быть указан любой из перечисленных выше дистрибутивов

Исполняемый файл для дистрибутивного пакета

make distribution

Цель distribution предназначена для сборки пакетов Gentoo, Debian, Ubuntu, Fedora и других дистрибутивов. Программа динамически связывается с установленными системными библиотеками

Сборка учитывает стандартные переменные CPPFLAGS, CFLAGS и LDFLAGS, не добавляет настройки для процессора машины, на которой выполняется сборка, не удаляет отладочные символы и не применяет UPX

Оптимизацию, усиление защиты, обработку отладочной информации и создание пакета должна выполнять сборочная система дистрибутива

Установка

Для быстрого вызова программы исполняемый файл precizer размещается в одном из каталогов, указанных в $PATH. Сборки создают архив с этим файлом в корне проекта.

macOS

На macOS статическая линковка не поддерживается. Цель macos-zip создаёт архив со сборкой для локального процессора. Сжатие UPX не применяется.

Зависимости для сборки

Для сборки требуются инструменты командной строки Xcode и зависимости из Homebrew. Они устанавливаются следующими командами:

xcode-select --install
brew install llvm sqlite pcre2 argp-standalone
Сборка и установка

Для сборки и упаковки без оптимизации под процессор конкретного компьютера используется цель macos-zip:

make macos-zip

Результат находится в корне проекта, в ZIP-архиве. Сборка учитывает CPPFLAGS, CFLAGS и LDFLAGS и не удаляет отладочные символы. Команда make distribution доступна отдельно: она оставляет только бинарник в .builds/distribution/precizer

Для сборки с оптимизацией под локальный процессор доступна цель dynamic-production:

make dynamic-production

В этом случае результат — ./precizer_macos_<архитектура>_dynamic-production.zip

Для вызова программы по имени и без указания пути нужно поместить распакованный файл precizer в один из каталогов, указанных в $PATH

Системные библиотеки для запуска приложения

На macOS все варианты сборки только динамические. Для запуска требуются системные библиотеки из Homebrew:

brew install sqlite pcre2 argp-standalone

Windows

Подготовка MSYS2

Для сборки Windows x64 требуется MSYS2. Команды выполняются в терминале MSYS2 MSYS, а не UCRT64 или MINGW64

Перед сборкой выполняется обновление пакетов:

pacman -Syu

Если обновление требует закрытия терминала, после подтверждения терминал MSYS2 MSYS запускается повторно, а команда выполняется ещё раз для завершения обновления. Подробности — в инструкции MSYS2

Зависимости устанавливаются командой:

pacman -S --needed git gcc make libsqlite-devel pcre2-devel libargp-devel zip

Получение исходного кода описано в начале раздела «Самостоятельная сборка». Все следующие команды выполняются из корня проекта в том же терминале

Команда make msys-build собирает программу в .builds/distribution/precizer.exe без упаковки. Обе цели упаковки, windows-zip и windows-exe, автоматически выполняют эту сборку

EXE с DLL рядом

Следующая команда собирает программу и создаёт ZIP-архив с EXE, необходимой DLL, лицензией, историей изменений и обоими README:

make windows-zip

Результат — архив precizer_windows_x64_portable.zip. После распаковки precizer.exe и msys-2.0.dll должны оставаться в одном каталоге. Для запуска на другом компьютере установка MSYS2 не требуется. SQLite, PCRE2 и argp уже включены в EXE

Единый самораспаковывающийся EXE

Следующие команды устанавливают дополнительные инструменты, собирают программу и создают самораспаковывающийся EXE со встроенными программой и DLL. Предварительно выполнять make windows-zip не требуется:

pacman -S --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-binutils mingw-w64-ucrt-x86_64-upx
make windows-exe

Переключать терминал не нужно: сборка сама выбирает UCRT-компилятор. В корне проекта появится precizer_windows_x64_portable.exe. Для переноса и запуска достаточно этого файла: при запуске он самостоятельно извлекает программу и DLL в пользовательский каталог кэша

После установки всех перечисленных зависимостей оба пакета можно собрать одной командой. Эти же цели использует GitHub Actions для сборки релизов:

make windows-zip windows-exe

Исполняемый файл автоматически сжимается с помощью UPX. Для отключения сжатия используется команда:

make windows-exe UPX=true

Тестирование

Тестовый набор проверяет отдельные функции, работу приложения через командную строку и результаты обработки файлов из tests/fixtures/.

Для обычной проверки в Linux используется отладочная сборка без санитайзеров:

SLOWTEST=skip make tests-debug

Переменная SLOWTEST=skip пропускает продолжительные сценарии. Полный набор тех же тестов запускается без этой переменной:

make tests-debug

Цель make tests дополнительно включает AddressSanitizer и UndefinedBehaviorSanitizer. Этот режим требует библиотек санитайзеров и llvm-symbolizer:

make tests

Полный перечень системных пакетов и команды их установки приведены в разделе «Системные пакеты для тестирования».

ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ

Пример 1

Добавить файлы в две базы данных и сравнить их между собой:

precizer --progress --database=database1.db tests/fixtures/diffs/diff1

precizer --progress --database=database2.db tests/fixtures/diffs/diff2

precizer --compare database1.db database2.db

The comparison of database1.db and database2.db databases is starting…
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
Starting database file database2.db integrity check…
Database database2.db has been verified and is in good condition
These files are no longer in the database1.db but still exist in the database2.db
path1/AAA/BCB/CCC/b.txt
These files are no longer in the database2.db but still exist in the database1.db
path2/AAA/ZAW/D/e/f/b_file.txt
The SHA512 checksums of these files do not match between database1.db and database2.db
2/AAA/BBB/CZC/a.txt
3/AAA/BBB/CCC/a.txt
4/AAA/BBB/CCC/a.txt
path1/AAA/ZAW/D/e/f/b_file.txt
path2/AAA/BCB/CCC/a.txt
Comparison of database1.db and database2.db databases is complete
The precizer completed its execution without any issues

Фильтрация категорий отчёта сравнения

По умолчанию --compare выводит все три категории различий: пути, которые есть только в первой базе; пути, которые есть только во второй базе; пути, которые есть в обеих базах, но имеют разные SHA512. Параметр --compare-filter ограничивает отчёт одной или несколькими категориями и работает только вместе с --compare. Значение checksum-mismatch оставляет только различия SHA512. Значение first-source оставляет только пути из первой базы. Значение second-source оставляет только пути из второй базы

precizer --compare --compare-filter=checksum-mismatch database1.db database2.db

precizer --compare --compare-filter=first-source database1.db database2.db

precizer --compare \
	--compare-filter=first-source \
	--compare-filter=second-source \
	database1.db database2.db

Если --compare-filter указан несколько раз, precizer объединяет выбранные категории. В последнем примере выводятся только пути, присутствующие в одной базе и отсутствующие в другой, а различия SHA512 для общих путей не показываются

В режиме --compare параметры --ignore и --include ограничивают ту область относительных путей, по которой строится отчёт сравнения. Если фильтры скрывают часть различий, итоговые сообщения об идентичности относятся только к оставшейся отфильтрованной области. Пути, возвращённые через --include, снова участвуют и в списках различий, и в итоговых сводках

Пример 2

Актуализация базы данных

Попробуем использовать предыдущий пример ещё раз. Первая попытка. Сообщение с предупреждением.

precizer --progress --database=database1.db tests/fixtures/diffs/diff1

The database database1.db was previously created and already contains data with files and their checksums. Use the --update option only when you are certain that the database needs to be updated and when file information (including changes, deletions, and additions) should be synchronized with the database.
ERROR: The precizer process terminated unexpectedly due to an error

Должен быть добавлен параметр --update. Этот параметр необходим для защиты базы данных от потери информации из-за случайного запуска.

precizer --update --progress --database=database1.db tests/fixtures/diffs/diff1

Primary database file name: database1.db
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
File system traversal initiated to calculate file count and storage usage
Total size: 45B, total items: 58, dirs: 46, files: 12, symlnks: 0
The database file database1.db has NOT been modified since the program was launched
The precizer completed its execution without any issues

Внесём некоторые изменения:

# Modify a file
echo -n "  " >> tests/fixtures/diffs/diff1/1/AAA/BCB/CCC/a.txt

# Add a new file
touch tests/fixtures/diffs/diff1/1/AAA/BCB/CCC/c.txt

# Remove a file
rm tests/fixtures/diffs/diff1/path2/AAA/ZAW/D/e/f/b_file.txt

и запустим precizer ещё раз, но уже с параметром --update:

precizer --update --progress --database=database1.db tests/fixtures/diffs/diff1

Primary database file name: database1.db
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
File system traversal initiated to calculate file count and storage usage
Total size: 43B, total items: 58, dirs: 46, files: 12, symlnks: 0
The --update option has been used, so the information about files will be updated against the database database1.db
File traversal started
These files have been added or changed and those changes will be reflected against the DB database1.db:
1/AAA/BCB/CCC/a.txt changed lsize & ctime & mtime rehashed
1/AAA/BCB/CCC/c.txt added
File traversal complete
Total size: 43B, total items: 58, dirs: 46, files: 12, symlnks: 0
These files are no longer exist or ignored and will be deleted against the DB database1.db:
path2/AAA/ZAW/D/e/f/b_file.txt
Start vacuuming the primary database…
The primary database has been vacuumed
The database file database1.db has been modified since the program was launched
The precizer completed its execution without any issues

Метки изменений в выводе означают:

  • lsize — логический размер файла в байтах (st_size)
  • asize — размер, выделенный на диске, в байтах (st_blocks * 512)
  • ctime — время изменения метаданных/статуса
  • mtime — время изменения содержимого файла

При каждом запуске precizer обходит файловую систему, после этого проверяя, есть ли запись об определённом файле в базе данных или нет. Другими словами, приоритет для программы имеет состояние файловой системы на диске.

Обход каталогов precizer работает очень похоже на работу rsync, поскольку использует похожий алгоритм.

Для обычных файлов с полной SHA512 в базе данных precizer пересчитывает контрольную сумму при изменении размера или mtime. Опция --watch-timestamps дополнительно учитывает любые изменения в метаданных о файле кроме времени последнего доступа (atime).

Любые новые файлы, удалённые файлы или те файлы, которые изменились между запусками приложения, будут обработаны и, соответственно, все изменения будут отражены в базе данных, если указан параметр --update.

Пример 3

Использование режима --silent. При включении этого режима программа ничего не выводит на экран. Это имеет смысл при использовании precizer в скриптах.

Исключение составляет режим --compare: вместе с --silent остаётся только вывод результатов сравнения. Пути с различиями печатаются напрямую, а заголовки категорий сохраняются только тогда, когда одновременно активны несколько категорий сравнения.

Добавим параметр --silent к предыдущему примеру:

precizer --silent --update --progress --database=database1.db tests/fixtures/diffs/diff1

В результате на экране ничего не отобразится.

Пример 4

Дополнительная информация в режиме --verbose может быть полезна для отладки.

Добавим параметр --verbose к предыдущему примеру:

precizer --verbose --update --progress --database=database1.db tests/fixtures/diffs/diff1

2025-01-25 09:55:59:820 src/parse_arguments.c:442:parse_arguments:Configuration: rational_logger_mode=VERBOSE
paths=tests/fixtures/diffs/diff1; database=database1.db; db_file_name=database1.db; verbose=yes; maxdepth=-1; silent=no; force=no; update=yes; watch-timestamps=no; progress=yes; compare=no, db-drop-ignored=no, dry-run=no, check-level=FULL, rational_logger_mode=VERBOSE
2025-01-25 09:55:59:820 src/parse_arguments.c:558:parse_arguments:Arguments parsed
2025-01-25 09:55:59:820 src/detect_paths.c:025:detect_paths:Checking directory paths provided as arguments
2025-01-25 09:55:59:820 src/file_availability.c:034:file_availability:Verify that the path tests/fixtures/diffs/diff1 exists
2025-01-25 09:55:59:820 src/file_availability.c:053:file_availability:The path tests/fixtures/diffs/diff1 is exists and it is a directory
2025-01-25 09:55:59:821 src/detect_paths.c:036:detect_paths:Paths detected
2025-01-25 09:55:59:821 src/init_signals.c:034:init_signals:Set signal SIGUSR2 OK:pid:604770
2025-01-25 09:55:59:821 src/init_signals.c:043:init_signals:Set signal SIGINT OK:pid:604770
2025-01-25 09:55:59:821 src/init_signals.c:052:init_signals:Set signal SIGTERM OK:pid:604770
2025-01-25 09:55:59:821 src/init_signals.c:055:init_signals:Signals initialized
2025-01-25 09:55:59:821 src/db_determine_name.c:099:db_determine_name:Primary database file name: database1.db
2025-01-25 09:55:59:821 src/db_determine_name.c:105:db_determine_name:Primary database file path: database1.db
2025-01-25 09:55:59:821 src/db_determine_name.c:109:db_determine_name:DB name determined
2025-01-25 09:55:59:821 src/file_availability.c:034:file_availability:Verify that the path . exists
2025-01-25 09:55:59:821 src/file_availability.c:053:file_availability:The path . is exists and it is a directory
2025-01-25 09:55:59:821 src/file_availability.c:034:file_availability:Verify that the path database1.db exists
2025-01-25 09:55:59:821 src/file_availability.c:044:file_availability:The path database1.db is exists and it is a file
2025-01-25 09:55:59:821 src/db_determine_mode.c:128:db_determine_mode:Final value for config->sqlite_open_flag: SQLITE_OPEN_READWRITE
2025-01-25 09:55:59:821 src/db_determine_mode.c:129:db_determine_mode:Final value for config->db_initialize_tables: false
2025-01-25 09:55:59:821 src/db_determine_mode.c:131:db_determine_mode:DB mode determined
2025-01-25 09:55:59:821 src/db_test.c:061:db_test:Starting database file database1.db integrity check…
2025-01-25 09:55:59:821 src/db_test.c:082:db_test:The database verification level has been set to FULL
2025-01-25 09:55:59:821 src/db_test.c:126:db_test:Database database1.db has been verified and is in good condition
2025-01-25 09:55:59:822 src/db_get_version.c:087:db_get_version:Version number 1 found in database
2025-01-25 09:55:59:822 src/db_check_version.c:032:db_check_version:The database1.db database file is version 1
2025-01-25 09:55:59:822 src/db_check_version.c:061:db_check_version:The database database1.db is on version 1 and does not require any upgrades
2025-01-25 09:55:59:822 src/db_init.c:030:db_init:Successfully opened database database1.db
2025-01-25 09:55:59:822 src/db_init.c:118:db_init:The primary database and tables have NOT been initialized
2025-01-25 09:55:59:822 src/db_init.c:150:db_init:The primary database named database1.db is ready for operations
2025-01-25 09:55:59:822 src/db_init.c:167:db_init:The in-memory runtime_paths_id database successfully attached to the primary database database1.db
2025-01-25 09:55:59:822 src/db_init.c:174:db_init:Database initialization process completed
2025-01-25 09:55:59:822 src/db_compare.c:136:db_compare:Database comparison mode is not enabled. Skipping comparison
2025-01-25 09:55:59:822 src/db_contains_data.c:086:db_contains_data:The database database1.db has already been created previously
2025-01-25 09:55:59:822 src/db_validate_paths.c:192:db_validate_paths:The paths written against the database and the paths passed as arguments are completely identical
2025-01-25 09:55:59:822 src/file_list.c:143:file_list:File system traversal initiated to calculate file count and storage usage
2025-01-25 09:55:59:823 src/file_list.c:038:show_status:Total size: 43B, total items: 58, dirs: 46, files: 12, symlnks: 0
2025-01-25 09:55:59:825 src/db_get_version.c:087:db_get_version:Version number 1 found in database
2025-01-25 09:55:59:825 src/db_consider_vacuum_primary.c:025:db_consider_vacuum_primary:No changes were made. The primary database doesn't require vacuuming
2025-01-25 09:55:59:825 src/status_of_changes.c:049:status_of_changes:The database file database1.db has NOT been modified since the program was launched
2025-01-25 09:55:59:825 src/exit_status.c:027:exit_status:The precizer completed its execution without any issues

Пример 5

Исследование без рекурсии с помощью параметра --maxdepth

tree tests/fixtures/4

tests/fixtures/4
├── AAA
│   ├── BBB
│   │   ├── CCC
│   │   │   └── a.txt
│   │   └── uuu.txt
│   └── tttt.txt
└── sss.txt

3 directories, 4 files

Параметр --maxdepth со значением =0 полностью отключает рекурсию.

precizer --maxdepth=0 tests/fixtures/4

Primary database file name: myhost.db
The path myhost.db doesn't exist or it is not a file
The primary DB file not yet exists. Brand new database will be created
Recursion depth limited to: 0
File traversal started
These files will be added against the myhost.db database:
sss.txt
File traversal complete
Total size: 2B, total items: 5, dirs: 4, files: 1, symlnks: 0
Start vacuuming the primary database…
The primary database has been vacuumed
The database myhost.db has been modified since the last check (files were added, removed, or updated)
The precizer completed its execution without any issues

Пример 6

Пример пути, который следует игнорировать. Для указания шаблона игнорирования файлов или каталогов можно использовать регулярные выражения PCRE2. Внимание! Все пути в регулярном выражении должны быть указаны как относительные.

Чтобы проверить и протестировать регулярные выражения PCRE2, можно использовать ресурс https://regex101.com

Для понимания, как выглядит относительный путь, достаточно запустить сканирование директорий без опции --ignore и посмотреть, как терминал будет отображать относительные пути, записываемые в базу данных:

% tree -L 3 tests/fixtures/diffs

tests/fixtures/diffs
├── diff1
│   ├── 1
│   │   └── AAA
│   ├── 2
│   │   └── AAA
│   ├── 3
│   │   └── AAA
│   ├── 4
│   │   └── AAA
│   ├── path1
│   │   └── AAA
│   └── path2
│       └── AAA
└── diff2
    ├── 1
    │   └── AAA
    ├── 2
    │   └── AAA
    ├── 3
    │   └── AAA
    ├── 4
    │   └── AAA
    ├── path1
    │   └── AAA
    └── path2
        └── AAA

26 directories, 0 files
precizer --ignore="^diff1/1/.*" tests/fixtures/diffs

В этом примере начальный путь сканирования — ./tests/fixtures/diffs, а сформированный путь для игнорирования — ./tests/fixtures/diffs/diff1/1/ со всеми подкаталогами (/*).

Primary database file name: myhost.db
The path myhost.db doesn't exist or it is not a file
The primary DB file not yet exists. Brand new database will be created
File traversal started
These files will be added against the myhost.db database:
diff1/1/AAA/BCB/CCC/a.txt ignored & not added
diff1/1/AAA/ZAW/A/b/c/a_file.txt ignored & not added
diff1/1/AAA/ZAW/D/e/f/b_file.txt ignored & not added
diff1/2/AAA/BBB/CZC/a.txt
diff1/3/AAA/BBB/CCC/a.txt
diff1/4/AAA/BBB/CCC/a.txt
diff1/path1/AAA/BCB/CCC/a.txt
diff1/path1/AAA/ZAW/A/b/c/a_file.txt
diff1/path1/AAA/ZAW/D/e/f/b_file.txt
diff1/path2/AAA/BCB/CCC/a.txt
diff1/path2/AAA/ZAW/A/b/c/a_file.txt
diff1/path2/AAA/ZAW/D/e/f/b_file.txt
diff2/1/AAA/BCB/CCC/a.txt
diff2/1/AAA/ZAW/A/b/c/a_file.txt
diff2/1/AAA/ZAW/D/e/f/b_file.txt
diff2/2/AAA/BBB/CZC/a.txt
diff2/3/AAA/BBB/CCC/a.txt
diff2/4/AAA/BBB/CCC/a.txt
diff2/path1/AAA/BCB/CCC/a.txt
diff2/path1/AAA/BCB/CCC/b.txt
diff2/path1/AAA/ZAW/A/b/c/a_file.txt
diff2/path1/AAA/ZAW/D/e/f/b_file.txt
diff2/path2/AAA/BCB/CCC/a.txt
diff2/path2/AAA/ZAW/A/b/c/a_file.txt
File traversal complete
Total size: 97B, total items: 114, dirs: 90, files: 24, symlnks: 0
Start vacuuming the primary database…
The primary database has been vacuumed
The database myhost.db has been modified since the last check (files were added, removed, or updated)
The precizer completed its execution without any issues
Enjoy your life!

Повторим тот же пример, но без опции --ignore, чтобы добавить три ранее проигнорированных файла:

precizer --update tests/fixtures/diffs

Primary database file name: myhost.db
Starting database file myhost.db integrity check…
Database myhost.db has been verified and is in good condition
The --update option has been used, so the information about files will be updated against the database myhost.db
File traversal started
These files have been added or changed and those changes will be reflected against the DB myhost.db:
diff1/1/AAA/BCB/CCC/a.txt add
diff1/1/AAA/ZAW/A/b/c/a_file.txt add
diff1/1/AAA/ZAW/D/e/f/b_file.txt add
File traversal complete
Total size: 97B, total items: 114, dirs: 90, files: 24, symlnks: 0
Start vacuuming the primary database…
The primary database has been vacuumed
The database file myhost.db has been modified since the program was launched
The precizer completed its execution without any issues

Пример 7

Продолжение предыдущего примера Пример 6.

Несколько регулярных выражений для игнорирования можно указать одновременно, повторив опцию --ignore несколько раз.

База данных будет очищена от упоминаний файлов, соответствующих регулярным выражениям из аргументов --ignore: "diff1/1/.*" и "diff2/1/.*"

Параметр --db-drop-ignored должен быть указан дополнительно, чтобы удалить из базы данных упоминание файлов, соответствующих регулярным выражениям, переданным через опции --ignore.

На файловой системе не было изменений, но игнорируемые файлы будут удалены из БД.

# Обновить базу данных, удалив информацию о тех файлах, которые были указаны как игнорируемые:

precizer \
    --update \
    --db-drop-ignored \
    --ignore="^diff1/1/.*" \
    --ignore="^diff2/1/.*" \
    tests/fixtures/diffs

Primary database file name: myhost.db
Starting database file myhost.db integrity check…
Database myhost.db has been verified and is in good condition
The --update option has been used, so the information about files will be deleted against the database myhost.db
These files are no longer exist or ignored and will be deleted against the DB myhost.db:
diff1/1/AAA/BCB/CCC/a.txt clean ignored
diff1/1/AAA/ZAW/A/b/c/a_file.txt clean ignored
diff1/1/AAA/ZAW/D/e/f/b_file.txt clean ignored
diff2/1/AAA/BCB/CCC/a.txt clean ignored
diff2/1/AAA/ZAW/A/b/c/a_file.txt clean ignored
diff2/1/AAA/ZAW/D/e/f/b_file.txt clean ignored
Start vacuuming the primary database…
The primary database has been vacuumed
The database file myhost.db has been modified since the program was launched
The precizer completed its execution without any issues

Пример 8

Использование параметров --ignore вместе с --include

# Удалим старую базу данных и создадим новую, наполним её данными:

rm -i "${HOST}.db"

precizer tests/fixtures/diffs

Усложним задачу с использованием регулярных выражений.

Регулярные выражения PCRE2 для относительных путей, которые необходимо включить. Включаем указанные относительные пути, даже если они были исключены с помощью одного или нескольких параметров --ignore. Несколько регулярных выражений могут быть указаны с помощью --include

Чтобы проверить и протестировать регулярные выражения PCRE2, можно использовать ресурс https://regex101.com

DB будет очищена от упоминаний файлов, соответствующих регулярным выражениям из аргументов --ignore: "^.*/path2/.*" и "diff2/.*", но опция --include оставит в базе данных пути, соответствующие заданным шаблонам.

Параметр --db-drop-ignored должен быть указан дополнительно, чтобы удалить из базы данных упоминание файлов, соответствующих регулярным выражениям, переданным через опции --ignore.

# Обновить базу данных, удалив информацию о тех файлах, которые были указаны как игнорируемые за исключением шаблонов путей из --include

precizer --update \
	--progress \
	--ignore="^.*/path2/.*" \
	--ignore="^diff2/.*" \
	--include="^diff2/1/AAA/ZAW/A/b/c/.*" \
	--include="^diff2/path1/AAA/ZAW/.*" \
	--include="^diff1/path2/AAA/ZAW/A/b/c/a_file\..*" \
	--db-drop-ignored \
	tests/fixtures/diffs

Primary database file name: myhost.db
Starting database file myhost.db integrity check…
Database myhost.db has been verified and is in good condition
The --update option has been used, so the information about files will be deleted against the database myhost.db
These files are no longer exist or ignored and will be deleted against the DB myhost.db:
diff1/path2/AAA/BCB/CCC/a.txt clean ignored
diff1/path2/AAA/ZAW/A/b/c/a_file.txt clean ignored
diff1/path2/AAA/ZAW/D/e/f/b_file.txt clean ignored
diff2/1/AAA/BCB/CCC/a.txt clean ignored
diff2/1/AAA/ZAW/D/e/f/b_file.txt clean ignored
diff2/2/AAA/BBB/CZC/a.txt clean ignored
diff2/3/AAA/BBB/CCC/a.txt clean ignored
diff2/4/AAA/BBB/CCC/a.txt clean ignored
diff2/path1/AAA/BCB/CCC/a.txt clean ignored
diff2/path1/AAA/BCB/CCC/b.txt clean ignored
diff2/path2/AAA/BCB/CCC/a.txt clean ignored
diff2/path2/AAA/ZAW/A/b/c/a_file.txt clean ignored
Start vacuuming the primary database…
The primary database has been vacuumed
The database file myhost.db has been modified since the program was launched
The precizer completed its execution without any issues

Те же фильтры в режиме --compare

Та же комбинация --ignore и --include работает и при сравнении двух баз данных. Фильтры определяют не только то, какие строки будут напечатаны, но и то, какая часть относительных путей считается входящей в отчёт сравнения. Поэтому итоговые сводки и сообщения об идентичности относятся только к этой отфильтрованной области

# Продолжая Пример 1, вернём в отчёт только один путь из скрытой группы различий

precizer --compare \
	--ignore="^(?:2|3|4)/.*" \
	--ignore="^path1/.*" \
	--ignore="^path2/.*" \
	--include="^2/AAA/BBB/CZC/a\.txt$" \
	database1.db database2.db

The comparison of database1.db and database2.db databases is starting…
Starting database file database1.db integrity check…
Database database1.db has been verified and is in good condition
Starting database file database2.db integrity check…
Database database2.db has been verified and is in good condition
The SHA512 checksums of these files do not match between database1.db and database2.db
2/AAA/BBB/CZC/a.txt
Comparison of database1.db and database2.db databases is complete
The precizer completed its execution without any issues

В этом примере все различия из путей 2/, 3/, 4/, path1/ и path2/ сначала выводятся из области отчёта сравнения, а затем --include возвращает обратно только 2/AAA/BBB/CZC/a.txt. В результате в отчёте снова появится именно этот путь, а остальные скрытые различия останутся вне итоговых списков и сводок

Пример 9

Защита неизменяемых архивов с помощью --lock-checksum

Опция --lock-checksum нужна для архивных каталогов или файлов, содержимое которых не должно переписываться. Она принимает регулярные выражения PCRE2 для относительных путей (тот же формат, что и у --ignore). Пути, совпавшие с любым шаблоном, записываются в БД один раз. После этого их контрольные суммы не пересчитываются даже при --update. Любое дальнейшее изменение размера или временных меток (при использовании режима --watch-timestamps), исчезновение файла с диска, потеря доступа на чтение или неожиданный сбой проверки доступа считается порчей данных и выводится соответствующее сообщение об ошибке вместо обновления записи. Для исчезнувшего или недоступного заблокированного файла запись в БД сохраняется, чтобы нарушение не терялось между последующими запусками. Защита заблокированного пути имеет приоритет над --ignore, --db-drop-ignored и --db-drop-inaccessible: совпадение с этими фильтрами не должно молча удалять такую запись из БД. Та же защита сохраняется и в ситуации, когда --include возвращает только часть ранее скрытого поддерева. Несколько шаблонов могут быть указаны повторением добавления опции --lock-checksum:

precizer \
  --lock-checksum="^archive/2024/.*" \
  --lock-checksum="^snapshots/monthly/.*" \
  /mnt/storage

В последующих запусках необходимо сохранять те же шаблоны блокировки при актуализации базы:

precizer \
  --update \
  --lock-checksum="^archive/2024/.*" \
  --lock-checksum="^snapshots/monthly/.*" \
  /mnt/storage

Файлы вне шаблонов обновляются в обычном порядке. Для заблокированных через --lock-checksum записей любое расхождение сразу становится заметным и код возврата при завершении precizer будет больше нуля и это можно использовать в скриптах.

Пример 10

Глубокая проверка заблокированных данных с помощью --rehash-locked

Опция --rehash-locked используется только вместе с --lock-checksum. При её включении каждый файл, попавший под шаблон блокировки и уже присутствующий в базе данных, перечитывается побайтно при каждой актуализации базы данных через --update. Для такого файла заново вычисляется контрольная сумма SHA512 и выполняется сравнение с сохранённым значением. Это позволяет выполнить дополнительный аудит неизменяемых архивов ценой увеличенного дискового ввода-вывода. Наличие или отсутствие параметра --watch-timestamps не влияет на работу --rehash-locked. Если пересчитанная сумма и размер совпадают с записью в БД, файл считается консистентным; если при этом на диске отличаются ctime/mtime, новые значения сохраняются в базе данных. Если заблокированный путь одновременно совпадает с --ignore, параметр --rehash-locked всё равно обязан пройти по этому пути и выполнить проверку, а не пропустить её.

precizer --update \
  --lock-checksum="^archive/2024/.*" \
  --rehash-locked \
  /mnt/storage

Чтобы увидеть взаимодействие параметров командной строки --lock-checksum, --watch-timestamps и --rehash-locked, рассмотрим несколько случаев:

  1. Размер файла отличается Если размер, записанный в базе, не совпадает с размером на диске, файл будет помечен как «нарушение заблокированной контрольной суммы» вне зависимости от --watch-timestamps и --rehash-locked. Пересчитывать контрольную сумму бессмысленно: при изменившемся размере она всё равно не совпадёт.
  2. Совпадает размер файла, не указаны ни --watch-timestamps, ни --rehash-locked поэтому остальные значения, такие как SHA512 и временные метки не учитываются и файл считается полностью консистентным, программа завершится со статусом SUCCESS.
  3. Совпадают размер и временные метки; указана --watch-timestamps и не указана опция --rehash-locked Файл считается полностью консистентным, он не появится в выводе, а статус завершения программы будет SUCCESS.
  4. Размер совпадает, временные метки различаются; указана --watch-timestamps и не указана --rehash-locked Файл будет отмечен как «нарушение заблокированной контрольной суммы» только из-за различающихся временных меток, и программа завершится со статусом WARNING.
  5. Размер совпадает, указан параметр --rehash-locked Для проверки учитываются только контрольная сумма и размер, записанные в базе данных. Если они совпадают, файл считается консистентным. Если на диске изменились временные метки, то новые значения ctime/mtime будут сохранены в базе данных независимо от того был ли указан --watch-timestamps или нет.

Подробные примеры поведения в сложных ситуациях собраны в тесте №30 (tests/src/test0030.c). Там проверяются удаления заблокированных файлов, потеря доступа, сбои проверки доступа и взаимодействие с --ignore, --include, --db-drop-ignored и --db-drop-inaccessible.

Практический сценарий: выполнять ежедневное быстрое сканирование без --rehash-locked (и при необходимости без --watch-timestamps), чтобы поддерживать БД в актуальном состоянии, а реже запускать углублённый аудит с --rehash-locked, который гарантированно сверяет контрольные суммы «замороженных» данных.

Пример 11

Сброс записей о недоступных файлах с помощью --db-drop-inaccessible

По умолчанию, если файл недоступен из-за прав доступа, его запись в базе данных сохраняется при --update, чтобы избежать случайной потери данных. Для удаления таких записей используется дополнительный параметр командной строки --db-drop-inaccessible:

precizer --update --db-drop-inaccessible /mnt/storage

drop due to inaccessible archive/secret.bin

Важно: --db-drop-inaccessible относится не к удалённым файлам, а к файлам, которые сейчас нельзя прочитать или для которых не удалось надёжно проверить доступ. Например, могли измениться права, владелец, ACL, или файловая система временно вернула ошибку доступа. По умолчанию такие записи остаются в БД, чтобы временная проблема с доступом не стёрла полезную историю. Если вы уверены, что такие записи больше не нужны, добавьте --db-drop-inaccessible.

Если же файл или один из каталогов в его пути вообще не виден в файловой системе, precizer считает удалённой обычную запись, не защищённую через --lock-checksum, и при --update удалит её из БД без дополнительных опций. Программа не может сама отличить настоящее удаление от ситуации, когда точка монтирования существует, но нужный том не подключился и поэтому каталог выглядит пустым. Перед обновлением БД для внешних, сетевых или съёмных томов сначала убедитесь, что нужный том действительно смонтирован. Для важных архивных путей используйте --lock-checksum: тогда исчезнувший или недоступный файл будет показан как предупреждение, а запись в БД сохранится.

ОСНОВНЫЕ ПАРАМЕТРЫ КОМАНДНОЙ СТРОКИ

Ниже описаны основные опции для повседневной работы. В режиме сканирования после опций указывают исходные каталоги, а с --compare — два файла баз данных. Полный список опций и подробную справку можно получить командой:

precizer --help

Сканирование и обновление базы

  • --database=FILE, -d FILE — Выбрать файл базы данных. По умолчанию используется имя хоста с расширением .db

  • --update, -u — Разрешить обновление существующей базы по результатам сканирования: добавление новых файлов, обновление изменившихся и удаление записей об исчезнувших файлах. Используйте те же исходные каталоги, что и при создании базы

  • --watch-timestamps, -T — Учитывать изменения метаданных ctime в дополнение к размеру файла при определении необходимости пересчитать контрольную сумму

  • --dry-run, -n — Выполнить пробный обход без записи в базу данных. Вариант --dry-run=with-checksums дополнительно читает файлы и вычисляет контрольные суммы. На --compare эта опция не влияет

--update не означает полный пересчёт всех контрольных сумм. Для обычных файлов с уже сохранённой полной SHA512 пересчёт запускается при изменении размера или mtime. С --watch-timestamps также учитываются изменения ctime и количества занятых блоков на диске. Правила защиты архивных файлов через --lock-checksum описаны в примере 9, а их принудительная проверка — в примере 10

Сравнение баз

  • --compare, -c — Сравнить две базы по относительным путям и контрольным суммам, например precizer --compare first.db second.db

  • --compare-filter=TYPE, -F TYPE — Выбрать категории отчёта: checksum-mismatch — разные контрольные суммы, first-source — файлы только в первой базе, second-source — только во второй. Работает вместе с --compare; опцию можно повторять для объединения категорий

Без --compare-filter выводятся все три категории. Подробный пример приведён в разделе «Фильтрация категорий отчёта сравнения»

Выбор файлов и глубина обхода

  • --ignore=REGEXP, -e REGEXP — Исключить пути, совпадающие с регулярным выражением PCRE2

  • --include=REGEXP, -i REGEXP — Вернуть пути, исключённые через --ignore. Сама по себе эта опция не ограничивает обработку только совпавшими путями

  • --maxdepth=N, -m N — Ограничить глубину обхода. Исходный каталог имеет глубину 0; --maxdepth=0 обрабатывает файлы непосредственно в нём, не заходя в подкаталоги

Шаблоны --ignore и --include задаются для относительных путей от исходного каталога. Обе опции можно повторять. В режиме --compare эти фильтры ограничивают и списки различий, и область, для которой выводятся итоговые сообщения об идентичности. Исключение через --ignore само по себе не удаляет существующие записи из базы; управление таким удалением описано в примере 7

Подробность вывода

  • --progress, -p — Показывать ход обработки и объём данных. Для оценки прогресса программа сначала выполняет дополнительный обход и подсчёт файлов

  • --verbose, -v — Выводить подробные диагностические сообщения для разбора работы программы

  • --silent, -s — Подавить обычный вывод. В режиме --compare результаты сравнения остаются видимыми; заголовки категорий сохраняются, если активна более чем одна категория

Цвет и оформление текста

Параметр --color=auto|always|never управляет цветом и выделением текста, например полужирным шрифтом, в сообщениях программы. Значение обязательно: используйте, например, --color=never или короткую форму -S never

  • auto — режим по умолчанию. Оформление включено при выводе в терминал, в том числе псевдотерминал, и выключено при выводе в файл или pipe. В CI, cron и системной службе без терминала вывод также будет без оформления
  • always — добавлять ANSI-последовательности оформления даже при выводе в файл или pipe
  • never — не добавлять ANSI-последовательности оформления, включая сброс стиля, даже при выводе в терминал

В режиме auto наличие переменной окружения NO_COLOR, даже с пустым значением, или значение TERM=dumb отключает оформление. Это правило действует и при явном --color=auto. Режимы always и never имеют приоритет над этими переменными

Проверяется именно поток, в который выводится сообщение. Например, при перенаправлении stdout в файл сообщения в этом потоке остаются без оформления в режиме auto, даже если stderr всё ещё подключён к терминалу. Режим auto определяет подключение к терминалу, но не проверяет, какие цвета и эффекты он поддерживает

Примеры для двух уже существующих баз данных first.db и second.db:

# Автоматически включать оформление при выводе в интерактивный терминал
precizer --compare --color=auto first.db second.db

# Сохранить отчёт сравнения без оформления в режиме auto по умолчанию
precizer --compare first.db second.db > comparison.txt

# Сохранить оформление при передаче отчёта другой программе через pipe
precizer --compare --color=always first.db second.db | cat

# Отключить оформление даже при выводе в интерактивный терминал
precizer --compare -S never first.db second.db

# Отключить автоматическое оформление через переменную окружения
NO_COLOR=1 precizer --compare first.db second.db

УСТРАНЕНИЕ НЕПОЛАДОК (ТРАБЛШУТИНГ)

Антивирус замедляет работу под Windows

Антивирусная защита в реальном времени может значительно замедлять обход файлов и расчёт контрольных сумм, в отдельных случаях — на один-два порядка. Причина в том, что антивирус проверяет каждый файл при обращении. Для ускорения работы обрабатываемые каталоги рекомендуется добавить в исключения проверки в реальном времени.

precizer считывает каждый байт всех файлов в указанной директории для расчёта контрольной суммы, но НЕ запускает файлы и НЕ исполняет их содержимого. Для самого расчёта контрольных сумм антивирус не требуется.

Медленный проход по файлам, медленный расчёт контрольных сумм, медленная запись в БД. Или решение проблемы под названием «ВСЁ МЕДЛЕННО»

Чтобы выяснить причину, попробуйте запустить precizer в режиме --dry-run или --dry-run=with-checksums.

--dry-run рекурсивно проходит по Файловой Системе. В этом режиме, кроме обхода дерева файлов, больше ничего не выполняется. Можно добавить --progress — тогда добавится подсчёт занимаемого файлами места и количества файлов, но записи в БД не будет. В этом режиме можно проверить доступность ФС и частично — аппаратные возможности. Если медленно даже с --dry-run, то маловероятно, что причина в самой программе precizer.

Режим --dry-run=with-checksums отличается от --dry-run только тем, что каждый встреченный файл будет полностью (побайтово) считан с диска, и для него будет рассчитана контрольная сумма. Это значительно более ресурсоёмкий процесс, практически идентичный реальной работе программы. Режим полностью раскрывает аппаратный потенциал, но при этом не делает записей в БД. Если при этом указать --progress, то после прохода по файловой системе будет показан статус: количество байт, которые прошли через хеширование, а так же средняя скорость хеширования в B/s Показатель скорости хеширования можно сравнивать с результатами сторонних бенчмарков для поиска «бутылочного горлышка».

Возможна ситуация, когда даже с --dry-run=with-checksums программа работает очень быстро, но в режиме реальной работы (без Dry-Run) наблюдается заметная деградация производительности, особенно при массовых добавлениях или изменениях в БД. В этой ситуации нужно проверить ФС, на которой расположен файл базы данных. Именно там может скрываться причина.

База данных SQLite открывается программой precizer с такими параметрами, чтобы максимально сохранить уже записанное и всеми силами противостоять повреждению файла БД. Однако это предполагает больше дисковых I/O-операций и больше синхронизаций ФС с блочным устройством. На практике SQLite действительно очень быстрая БД и обычно не является «слабым звеном». Но если ФС с компрессией, сетевая или просто медленная, это может ощутимо отразиться на производительности программы в целом.

Например, при массовых добавлениях precizer ждёт, когда информация о файле будет записана в БД и транзакция будет завершена, и только потом переходит к следующему файлу. В такой ситуации для решения проблем производительности имеет смысл попробовать временно разместить файл .db, например, на tmpfs, — это может значительно увеличить общую производительность и понять где именно кроется проблема.

Если по-прежнему всё медленно в любых режимах, то имеет смысл проверить:

Целостность файловой системы

Сделайте системные проверки ФС, на которой делаются слепки контрольных сумм файлов, а также той ФС, где хранится и обновляется файл базы данных .db. Наблюдаемые просадки производительности могут быть связаны с логическими проблемами на уровне ФС.

Аппаратные возможности:

Скорость диска

Файлы считываются полностью и побайтово. Производительность дисковой подсистемы прямо пропорциональна скорости работы precizer. Программа работает поверх ФС как с более высоким слоем абстракции, а не с блочными устройствами напрямую. Любые логические ошибки ФС имеют значение.

Падение производительности может сильно зависеть от выбранной ФС. Например, скорость обработки файлов из смонтированной точки NFS может упираться в производительность сети и заметно отличаться от скорости доступа к ФС с отключённым atime на локальном диске NVMe (atime — access time, метка «время последнего доступа» к файлу). Используйте сторонние утилиты для проверки производительности файловой подсистемы.

Производительность CPU

Расчёт контрольных сумм — это чистая математика и достаточно трудоёмкий процесс. Современные процессоры справляются с этим незаметно быстро, но имеет смысл убедиться, что производительность не деградирует из-за разделяемых ресурсов виртуальных CPU в случае контейнеризации или виртуализации. Используйте сторонние системы мониторинга и бенчмарки для проверки производительности CPU.

Матрица диагностики узких мест

Шаг Режим/команда Что проверяем Если здесь медленно Что делать дальше
1 precizer --dry-run Доступность ФС, скорость обхода дерева файлов, базовая скорость I/O Вероятнее всего проблема вне precizer: ФС/диск/сеть/нагрузка Проверить ФС и подсистему хранения, состояние монтирования, нагрузку системы
2 precizer --dry-run=with-checksums Реальную скорость чтения файлов + вычисления checksum (без БД) Узкое место: чтение данных (диск/сеть/ФС) или CPU (реже) Проверить скорость диска/сети, параметры ФС, ограничение ресурсов CPU (виртуализация/контейнеры)
3 Реальный режим (без Dry-Run) Влияние записи в БД (SQLite) и транзакций Часто проблема в ФС, где лежит .db (медленная/сетевая/компрессия) Проверить ФС под .db, попробовать временно перенести .db на быстрый носитель или tmpfs

АЛЬТЕРНАТИВЫ

Альтернативы программе precizer с открытыми архитектурами и кодом. Больше альтернатив (актуально): alternativeto.net

  • AIDE — aide.github.io

    • Платформы/архитектуры: Linux/*BSD/macOS (x86_64, arm64 и др.)
    • Написана на: C, поддерживается
      • Можно выбирать/комбинировать разные хэш-алгоритмы и контролировать больше «не-хэш» атрибутов (ACL/xattr/SELinux и т.п.) на уровне правил.
      • База/снимок — текстовый формат (опционально gzip), а не SQLite: хуже подходит для сложных выборок/аналитики по данным БД.
      • Нет «докачки» прерванного хэширования внутри огромного файла: обычно перескан начинается заново.
  • Samhain — www.la-samhna.de/samhain

    • Платформы/архитектуры: Linux/Unix/POSIX, Windows (x86_64, arm64 и др.)
    • Написана на: C, поддерживается
      • Встроенная модель «агент + центральный сервер» (централизованный сбор/контроль), что выходит за рамки «одна локальная БД».
      • Упор на tamper-resistance (подписи/криптозащита части артефактов).
      • Сильно более сложное развёртывание/сопровождение (агенты/сервер/ключи), если нужна просто быстрая сверка двух деревьев через SQLite.
  • OSSEC — www.ossec.net

    • Платформы/архитектуры: Linux, Windows, macOS, *BSD (x86_64, arm64 и др.)
    • Написана на: C, поддерживается
      • Событийная/агентская HIDS-платформа: реально-временные алерты, правила, корреляция, реакция — это другой класс задач, чем «снимок+сверка».
      • Централизованная архитектура из коробки.
      • Не заточен под хранение «снимка файлов» именно в SQLite и под возобновление прерванного вычисления хэша внутри большого файла.
  • Open Source Tripwire — github.com/Tripwire/tripwire-open-source

    • Платформы/архитектуры: POSIX-подобные ОС (Linux/macOS/*BSD/Solaris и т.п.), Windows через Cygwin (x86_64, arm64 и др.)
    • Написана на: C++, последние изменения 8 лет назад
      • Развитый policy-язык и практика подписания policy/конфигов/базы (цепочка доверия вокруг baseline).
      • Нет SQLite-БД как «первичного формата данных» и нет возобновления прерванного хэширования внутри большого файла.
  • integrit — github.com/integrit/integrit

    • Платформы/архитектуры: Linux/*BSD (x86_64, arm64 и др.)
    • Написана на: C, последние изменения 2 года назад
      • Минимализм и малая зависимость от внешних библиотек (если вам важнее «маленькая утилита», чем SQL-модель данных).
      • Не использует SQLite и, как следствие, хуже подходит для «жирных» выборок/сравнений/аналитики по снимкам.
  • mtree (NetBSD mtree) — man.netbsd.org/mtree.8

    • Платформы/архитектуры: *BSD, Linux (x86_64, arm64 и др.)
    • Написана на: C, последние изменения 18 лет назад
      • Спецификация дерева (spec) — удобна в сценариях «эталонная раскладка/права/владельцы», где нужен именно декларативный формат.
      • Очень старые изменения (практически «заморожено»).
      • Формат/workflow «spec-файл», а не SQLite-снимок + быстрые SQL-сверки; нет возобновления прерванного хэширования внутри большого файла.
  • hashdeep (md5deep/sha*deep) — github.com/jessek/hashdeep

    • Платформы/архитектуры: Linux, Windows, macOS (x86_64, arm64 и др.)
    • Написана на: C++/C, последние изменения 9 лет назад
      • Выбор семейства хэшей/форматов вывода. Удобно, когда нужно соответствовать внешним требованиям/стандартам.
      • Нет SQLite-снимка «как продукта»: результаты — это в основном файлы отчётов/листинги, а не БД для быстрых сравнений.
  • hashit — github.com/boyter/hashit

    • Платформы/архитектуры: Linux, Windows, macOS (x86_64, arm64 и др.)
    • Написана на: Go, поддерживается
      • Умеет считать несколько разных хэшей для одного файла за один проход.
      • Нет SQLite-снимка и механизмов «обновления базы».
  • RHash — github.com/rhash/RHash

    • Платформы/архитектуры: Linux, Windows, macOS, *BSD (x86_64, arm64 и др.)
    • Написана на: C, поддерживается
      • Очень широкий набор алгоритмов/выходных форматов (включая магнет-ссылки и т.п.), если требуется совместимость с внешними экосистемами.
      • Не делает SQLite-снимок дерева как первичную сущность (скорее «посчитал/проверил хэши», чем «веду БД снимков»).
  • rsync — rsync.samba.org

    • Платформы/архитектуры: Linux, *BSD, macOS (x86_64, arm64 и др.), Windows через Cygwin/MSYS2
    • Написана на: C, поддерживается
      • Это одновременно и перенос/синхронизация, и проверка: можно сразу «исправлять расхождения», а не только выявлять их.
      • Контрольные суммы не сохраняются между запусками: при обрывах/повторных проверках пересчёт начинается заново
  • rclone — rclone.org

    • Платформы/архитектуры: Linux, Windows, macOS, *BSD (amd64/arm/arm64 и др.)
    • Написана на: Go, поддерживается
      • Ориентирован на удалённые/облачные хранилища: S3/Drive/etc.
      • Не делает локальный SQLite-снимок дерева для быстрых офлайн-сверок A↔B.
      • Проверка целостности часто зависит от возможностей конкретного backend’а (какие хэши/метаданные он вообще отдаёт).
  • QuickHash GUI — www.quickhash-gui.org

    • Платформы/архитектуры: Linux, Windows, macOS (x86_64; macOS arm64)
    • Написана на: FreePascal (Lazarus), последние изменения 2 года назад
      • GUI-only ориентированный инструмент и «комбайн» под разные носители/артефакты (например, сценарии форензики), где CLI-снапшоты не всегда удобны.
      • Не использует SQLite-снимок дерева как ядро workflow.
  • restic — restic.net

    • Платформы/архитектуры: Linux, Windows, macOS, *BSD (x86_64, arm64 и др.)
    • Написана на: Go, поддерживается
      • Репозиторий бэкапов со снапшотами, дедупликацией и шифрованием — если цель «хранить историю и переносить её», это сильнее, чем просто сравнить два дерева.
      • Другой подход: chunk/dedup-модель вместо «SQLite-снимок дерева + сверка»; для задачи чистой сверки A↔B может быть избыточен.
      • Не дает «прямой» модели сравнения двух локальных деревьев через одну SQL-БД

АВТОР

Автор приложения Денис Владимирович Разумовский

COPYING

This program is distributed under the GNU General Public License v3.0 (GPLv3) as provided in the top-level COPYING file. The author is not responsible for any use of the source code or the entire program. Anyone who uses the code or the program uses it at their own risk and responsibility

Ограничение использования на территории рашистского террористического геообразования, захваченного оккупировавшей власть авторитарной диктатурой

  • Разрешено: исключительно личное некоммерческое использование частными лицами.
  • Запрещено: любое использование, прямо или косвенно приводящее к уплате налогов, сборов, взносов или иных обязательных платежей в местные бюджеты на указанной территории (включая НДС, налог на прибыль, НДФЛ при исполнении обязанностей налогового агента, страховые взносы, таможенные пошлины и т.п.).
  • Также запрещено использование структурами, которые по недоразумению именуют себя государственными органами, государственными компаниями, бюджетными учреждениями и аффилированными организациями.
  • Коммерческая эксплуатация, возмездное распространение, платная поддержка и интеграция — запрещены, если осуществляются на указанной территории или для её резидентов и влекут уплату обязательных платежей.
  • Запрет распространяется на использование самой программы, её исходного кода полностью или частично.
  • Цель условия — исключить прямое и косвенное финансирование войны в Украине.