Rust Coreutils 0.10.0 сократил разрыв с GNU — проваленных тестов стало почти вдвое меньше

Проект uutils выпустил обновлённую версию Rust Coreutils 0.10.0 вечером 5 августа 2026 года. Новая версия значительно повысила совместимость с GNU Coreutils, сократив количество неудачных тестов с 56 до 29. Разработчики укрепили файловые операции против гонок, убрали десятки аварийных завершений и добавили функции mv --exchange, install --reflink, ускоренные контрольные суммы через OpenSSL и поддержку WASI Preview 2.

Rust Coreutils 0.10.0 сократил разрыв с GNU
Rust Coreutils 0.10.0 сократил разрыв с GNU

Rust Coreutils 0.10.0 проходит 645 из 690 тестов GNU

За сухими цифрами релиза скрывается риск для реальных систем. В официальном анонсе версии 0.10.0 команда описывает фокус версии как «совместимость с GNU и устойчивость». Rust Coreutils уже используется как набор базовых команд в реальных системах, поэтому любая мелкая разница с GNU-реализацией способна сломать установочный скрипт, сборку контейнера или обслуживание сервера. В версии 0.10.0 разработчики сократили количество несовместимых тестов почти вдвое за один цикл.

Coreutils — это повседневные команды Unix-подобных систем: ls показывает файлы, cp копирует их, mv перемещает, rm удаляет, chmod меняет права, date работает с датой, а cat, sort, head и tail обрабатывают текст. Пользователь редко думает о них как об отдельном программном пакете, хотя на этих утилитах держатся shell-скрипты, установщики, контейнерные образы и системные задания.

uutils создаёт совместимую реализацию этих команд на Rust. Цель проекта — воспроизводить вывод GNU Coreutils, коды завершения и поведение параметров настолько точно, чтобы существующие сценарии продолжали работать без переделки. Все программы уже реализованы, хотя документация проекта по-прежнему предупреждает о недостающих параметрах и различиях в отдельных ситуациях.

Результаты официального набора тестов GNU выглядят так:

Результат тестовRust Coreutils 0.9.0Rust Coreutils 0.10.0Изменение
Успешно625645+20
Пропущено815+7
Провалено5629−27
Ошибка11без изменений
Всего690690без изменений

Доля успешных тестов выросла с 90,58% до 93,48%. Особенно показательно снижение числа провалов: релиз 0.9.0 перешёл на тестовую базу GNU Coreutils 9.11 и получил 25 новых проверок, из-за чего показатель временно ухудшился. Версия 0.10.0 закрыла большую часть накопившегося разрыва.

Изменения затронули pr, nproc, date, numfmt, ls, du, install, od, truncate, fold, head, tail, sum и stat. У nproc, к примеру, уточнили учёт квот cgroups v2, маски привязки к процессорам, отключённых ядер и переменных окружения OpenMP. Для контейнеров это чувствительная деталь: неверное число доступных процессоров меняет количество рабочих потоков и расход памяти.

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

Защита файловых операций закрывает опасные промежутки между проверкой и действием

Самая содержательная часть Rust Coreutils 0.10.0 связана с TOCTOU — гонками между моментом проверки объекта и фактической операцией над ним. Название расшифровывается как time-of-check to time-of-use. Программа сначала проверяет путь, затем открывает, меняет или удаляет его; в коротком промежутке другой процесс может подменить файл либо символическую ссылку.

Rust защищает память от целого класса ошибок, но файловая система живёт по своим правилам. Типовая модель владения не способна гарантировать, что путь указывает на тот же объект спустя несколько системных вызовов. Именно поэтому разработчики продолжили отдельную кампанию по укреплению операций с файлами, начатую в версии 0.9.0.

В touch убрали использование O_TRUNC при создании файла. head теперь проверяет уже открытый файловый дескриптор, сохраняя связь с конкретным объектом. В mkfifo отказались от последующего изменения прав через путь, а split получил более защищённое открытие выходных файлов.

Рекурсивные режимы chmod и chown научились безопаснее обходить деревья каталогов. Исправления охватывают циклы символических ссылок и повторную проверку --preserve-root во время спуска по каталогам. Такая проверка связана с защитой корневой файловой системы от разрушительной рекурсивной операции.

Команда cp больше не спускается в каталог назначения, если этот каталог оказался символической ссылкой. Для mkdir, mkfifo и mknod метки SELinux назначаются в момент создания объекта. Прежняя последовательность оставляла промежуток, когда файл или каталог уже существовал с временным контекстом безопасности.

mv получил несколько защитных изменений для перемещения между файловыми системами. При таком переносе операция превращается в копирование и удаление исходника, поэтому набор возможных сбоев шире обычного переименования. Версия 0.10.0 жёстче обрабатывает пересоздание каталога назначения, сравнивает идентичность файлов при использовании резервных копий и снимает биты setuid/setgid, когда сохранить владельца не удалось.

В репозитории появился отдельный файл SECURITY.md, описывающий модель угроз, границы ответственности проекта и порядок сообщения об уязвимостях. Для инфраструктурного компонента с десятками команд это формализует правила, по которым разработчики оценивают сообщения о безопасности.

Кампания против паник затронула более тридцати утилит

Надёжность командной утилиты часто проверяется там, где обычный пользователь никогда её не увидит: заполненный диск, повреждённый ввод, огромный числовой параметр или строка с многобайтными символами. Rust Coreutils 0.10.0 устраняет паники и аварийные завершения именно в таких крайних сценариях.

Исправления перечислены для shuf, printf, numfmt, fmt, pr, chroot, dircolors, install, ln, touch, stat, split, expand, more, kill, cp, du, rm, runcon, sort, chown, chgrp, dirname, expr, cksum, dd, truncate и семейства хеширующих команд.

Один из повторяющихся случаев связан с /dev/full — специальным устройством Linux, которое всегда отвечает ошибкой нехватки места при записи. Его часто используют для проверки реакции программы на заполненный диск. Команда должна вернуть понятную ошибку и корректный код завершения; паника превращает контролируемый сбой в аварийное поведение.

Другой класс ошибок возникал на границах многобайтных символов. В UTF-8 один символ может занимать несколько байтов, поэтому попытка разрезать строку по произвольной позиции иногда попадает внутрь символа. Разработчики закрыли такие паники в командах, которые форматируют и режут текст.

Отдельно исправлены целочисленные переполнения при экстремальных значениях ширины, точности и размера, а также попытки выделить чрезмерный объём памяти из-за огромного аргумента. В expr рекурсивный разбор выражений заменили итеративным, благодаря чему глубоко вложенные выражения больше не переполняют стек.

Здесь и проявляется интрига релиза. Rust снижает вероятность ошибок обращения с памятью, но системная утилита остаётся уязвимой для логических просчётов, особенностей файловых систем, кодировок и необычных ответов ядра. Версия 0.10.0 показывает, сколько инженерной работы требуется после переписывания кода на безопасном языке.

mv --exchange меняет местами два пути одной атомарной операцией

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

Представим развёртывание приложения с каталогами current и next. Последовательность из нескольких обычных переименований оставляет короткие промежуточные состояния, которые может увидеть другой процесс. Атомарный обмен путей устраняет это окно на файловых системах и платформах, где операция поддерживается.

install получил параметр --reflink. Reflink создаёт копию файла через механизм copy-on-write: блоки данных сначала остаются общими, а физическое копирование происходит при изменении. На Btrfs, XFS и других совместимых файловых системах это сокращает объём записи и ускоряет операции с крупными файлами.

Команда rm теперь поддерживает --one-file-system, ограничивающий рекурсивное удаление текущей файловой системой. Такая граница имеет значение для деревьев каталогов, внутри которых смонтированы другие разделы, сетевые ресурсы или служебные файловые системы.

У cut появился короткий параметр -O для --output-delimiter. На Windows реализовали timeout, а tail -f и tail -F научились следить за дописываемыми файлами. Последнее связано с привычным просмотром журналов в реальном времени и приближает поведение Windows-сборки к Unix-вариантам.

OpenSSL ускоряет контрольные суммы, а tee получил путь без копирования данных

Производительность в этом выпуске улучшали точечно, рядом с конкретными узкими местами. Семейство cksum, команды sum, split, expand, unexpand, а также утилиты Base32 и Base64 получили подсказки упреждающего чтения. Операционная система может заранее подгружать следующие блоки файла, пока программа обрабатывает текущие.

Для вычисления MD5, SHA-1, SHA-2 и других контрольных сумм появился опциональный backend OpenSSL. Сборка с этой возможностью передаёт вычисления библиотеке libcrypto; стандартный вариант сохраняет реализации хеширования на чистом Rust. По данным проекта, наибольшая разница ожидается на процессорах без аппаратных инструкций SHA-NI. В строгом режиме FIPS алгоритмы, запрещённые библиотекой, автоматически обходят этот backend.

tee получил быстрый путь с нулевым копированием. При такой схеме данные передаются между файловыми дескрипторами средствами ядра без обычного маршрута через пользовательский буфер программы. cat ускорили при потоковом чтении, cp — при копировании без reflink, а mv использует быстрый путь копирования при переносе между файловыми системами.

Алгоритм expr index изменился с сложности O(N×M) на O(N+M). Проще говоря, время работы теперь растёт примерно вместе с суммарной длиной входных строк, а прежняя схема могла сравнивать множество сочетаний символов. Разница становится заметнее на длинных данных и в циклически вызываемых shell-сценариях.

Разработчики добавили отдельные бенчмарки для expr, tr, cut, uniq и слияния результатов sort с учётом локали. Наличие таких измерений помогает отличать реальное ускорение от изменений, которые выглядят быстрее только на одном искусственном примере.

WASI Preview 2 расширяет работу Rust Coreutils за пределами обычной ОС

Rust Coreutils 0.10.0 добавил целевую платформу wasm32-wasip2. WASI — системный интерфейс для WebAssembly, который даёт программам доступ к файлам, потокам ввода-вывода и другим возможностям в контролируемой среде. Preview 2 использует компонентную модель WebAssembly и более структурированные интерфейсы.

Для проекта Coreutils это расширяет сценарии, где привычные команды запускаются внутри песочницы, браузерного окружения, облачной функции или встраиваемой платформы. У uutils уже есть интерактивная WebAssembly-площадка, где команды можно выполнять в браузере без локальной установки.

Кроссплатформенность остаётся одним из центральных отличий проекта. Один набор утилит на Rust развивается для Linux, macOS, BSD, Windows и WASI. Скрипты всё равно зависят от возможностей конкретной платформы, но единая кодовая база уменьшает количество самостоятельных реализаций с расходящимся поведением.

В Windows-сборках релиз исправляет преобразование CRLF при проверке контрольных сумм, добавляет разреженное копирование в cp, слежение за файлами в tail и реализацию timeout. На других платформах ls --numeric-uid-gid теперь доступен шире, а uptime использует CLOCK_BOOTTIME там, где этот источник времени поддерживается.

После крупного рывка 29 тестов GNU всё ещё не проходят

Rust Coreutils 0.10.0 фиксирует самый крупный за один цикл спад числа проваленных GNU-тестов: с 56 до 29. Одновременно проект укрепил операции с путями и символическими ссылками, устранил паники в десятках команд и расширил набор платформ.

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

Проект по-прежнему рассматривает любое отклонение от GNU Coreutils как ошибку. Именно этот критерий придаёт цифрам совместимости большую информативность: Rust Coreutils сравнивает себя с поведением давно существующего пакета, включая сложные и малоизвестные ситуации. В версии 0.10.0 наблюдается значительное улучшение совместимости, однако полная взаимозаменяемость по всей тестовой матрице пока ещё не достигнута.

При использовании материалов сайта необходимо указывать ссылку на TGLand.ru. Если вы копируете фрагменты текста в интернете, прямая гиперссылка, доступная для индексации поисковыми системами, должна быть размещена в начале материала.