Posix-style regeх now in kernel
Коллеги! Не бейте больно! :)
Мне для моего основного проекта понадобились в ядре регулярные выражения. Я понял, что писать автомат ala apparmor — дело долгое, а у меня времени не очень много. Я попробовал портировать в ядро хоть какую-то библиотеку для сопоставления строки регексу. И у меня получилось.
После недолгого копания в альтернативах, выбор пал на старую библиотеку TRE, которую использует библиотека musl и какой-то из *BSD (Net- или Open-, кто-то из них) в качестве реализации того, что написано в regex(3) и далее по тексту.
Портануть это дело получилось буквально за несколько часов и оно заработало с первой загрузки. Я фшоке и Респект автору!
Свое творение я выложил на гитхаб, если кому надо, то буду благодарен за отзывы. Модулю пока два дня, он толком не оттестирован в условиях ядра, прошло несколько примитивных тестов. В общем, это, наверное, что-то типа «публичная альфа». В апстрим я еще свое поделие не слил, буду договариваться с автором, как это все лучше сделать. Пока основная пользовательская библиотека отдельно, ядерный код - отдельно. Не хочу ничего ломать в существующем коде.
Лежит здесь — https://github.com/gns48/tre/tree/linux-kernel
Как этим пользоваться:
1. Сливаем репу с гитхаба
2. cd tre; git checkout linux-kernel
3. cd linux_kernel; make
4. В Makefile своего модуля прописываем
KBUILD_EXTRA_SYMBOLS = <tre module source>/Module.symvers
5. Добавляем в свои исходники #include <tre.h> из дерева исходников
<tre module source>
6. Пользуем в своем модуле tre_regcomp/rtre_regexec/tre_regfree, как
описано в regex(3). Да, для пользовательского пространства
библиотека объявляет имена regcomp, regexec, regfree для
совместимости, но я не стал этого делать.
Ограничения:
1. нет поддержки "широких символов" и прочего юникода.
2. нет поддержки "приблизительного" сравнения (Approximate pattern matching), уж больно много соответствующие функции отжирают стека статическими массивами. Да и незачем оно в ядре. Основное назнчение -- это сравниватиь пути с "точным" образцом.
Что дальше в планах:
1. Сопроводить каждый регекс некоторым «контекстом использования» для того, что бы кучу регексов можно было объединить в один по '|' и скомпилировать их вместе. Далее regexec кроме «да/нет» должен возвратить, допустим, «да, и вот контекст того индивидуального регекса, которому соответствует строка».
2. Поправить распределение памяти при компиляции регекса с тем, что бы, во-первых, был известен объем выделенной памяти функцией regcomp и, во-вторых, выделенный объём памяти был скомпонован в единый непрерывный бандл. Сейчас regex_t внутри — это развесистая структура, из которой во все стороны торчат указатели, и память для них выделяется не единовременно.