On Sun, Sep 23, 2007 at 02:35:41AM +0400, Alexey Tourbin wrote: > > pam0-config-1.4.3-alt1 Provides pam0(other) > > -pam0-config-1.4.3-alt1 Provides pam0(system-auth) > > pam0-config-1.4.3-alt1 Provides pam0(system-auth-ldap) > > pam0-config-1.4.3-alt1 Provides pam0(system-auth-local) > > -pam0-config-1.4.3-alt1 Provides pam0(system-auth-use_first_pass) > > pam0-config-1.4.3-alt1 Provides pam0(system-auth-use_first_pass-ldap) > > Изменение зависимостей у меня не воспроизводится. :( Я всё понял! Да, у этого пакета слишком специфическим образом формируются зависимости. Requires: %([ -x "%SOURCE1" ] && RPM_LIB=%_lib RPM_LIBDIR=%_libdir PAM_SO_SUFFIX= PAM_NAME_SUFFIX=0 RPM_BUILD_ROOT=%buildroot %SOURCE1 %SOURC Provides: %([ -x "%SOURCE1" ] && PAM_SO_SUFFIX= PAM_NAME_SUFFIX=0 RPM_BUILD_ROOT=%buildroot %SOURCE1 %SOURCE0 prov || echo unknown) Скрипт %SOURCE1 который pam-config-deps.sh вызывает /usr/lib/rpm/pam.{req,prov} с ОТНОСТИТЕЛЬНЫМИ путями: 19 for f in */*; do 20 /usr/lib/rpm/pam."$t" "$f" Во всех стандартных /usr/lib/rpm/* скриптах, если они используют стандарнтую процедуру обработки аргументов ArgvFileAtion, происходит более или менее принудительная каноникализация ОТНОСИТЕЛЬНЫХ путей. /usr/lib/rpm/pam.req: 20 . /usr/lib/rpm/functions 21 [ $# -eq 1 ] && [ -n "$1" -a -z "${1##/*}" ] || 22 { ArgvFileAction "$0" "$@"; exit; } Это просто некоторый "хак", который я добавил в pam.req, чтобы сразу же не переписывать pam.req целиком (со временем он перепишется). Суть здесь в другом. Принудительная каноникализация относительных путей на самом деле происходит в ArgvFileAction из /usr/lib/rpm/functions. Так вот, раньше эта каноникализация была слишком навязчивой. Каноникализировался в том числе и последний компонент пути. Теперь остается только заметить, что убравшиеся зависимости являются симлинками zsh$ ls -l pam-config/*(@) lrwxrwxrwx 1 at at 17 Sep 23 02:00 pam-config/system-auth -> system-auth-local lrwxrwxrwx 1 at at 32 Sep 23 02:00 pam-config/system-auth-use_first_pass -> system-auth-use_first_pass-local zsh$ Полная каноникализация абсолютного пути приводила к тому, что вместо system-auth на самом деле повторно обрабатывался system-auth-local и т.д. Потом в ArgvFileAction я сделал каноникализацию относительных путей МЕНЕЕ НАВЯЗЧИВОЙ, то есть по сути в ряде случаев более предпочтительной. Для этого была реализована довольно простая и даже в некотором смысле сомнительная функция CanonPath. Но, как оказалось, она удачно решает целый ряд довольно тонких проблем сразу в нескольких местах. commit 5a5bd821337d620c8dae75617d5351bdc2061853 Author: Alexey Tourbin Date: Mon Aug 27 20:41:02 2007 +0400 scripts/functions: CanonPath: new function (canonicalize each path component except for the last) This is actually a DWIM-style hack. It does what we want but I cannot think of a better name. The idea is that sometimes we want to clean up path name, possibly following symbolic links, except for the last component, which we want to keep as is. $ sh -c '. scripts/functions; CanonPath /etc/init.d/functions' /etc/rc.d/init.d/functions $ sh -c '. scripts/functions; CanonPath /usr/bin/../bin/perl' /usr/bin/perl $ So actually it does a few different things: 1) prepend $PWD if needed; 2) cleanup dirname; 3) canonicalize dirname with respect to symbolic links. Now the question is how to process symbolic links which targets are directories, e.g. /etc/init.d ? My answer is that both "/etc/init.d" and "/etc/init.d/", as well as "/etc/init.d/." should yield the same result, which is "/etc/rc.d/init.d". diff --git a/scripts/functions b/scripts/functions index ef43b7b..e55e30a 100644 --- a/scripts/functions +++ b/scripts/functions @@ -99,6 +99,23 @@ RunMethods() done } +CanonPath() +{ + local f="$1" f2; shift + if [ -d "$f" ]; then + f2=$(readlink -vm -- "$f") + elif [ -L "$f" ]; then + local d + d=$(dirname -- "$f") + d=$(readlink -vm -- "$d") + f2="$d/${f##*/}" + else + f2=$(readlink -vm -- "$f") + fi + [ "$f" = "$f2" ] || Verbose "CanonPath: $f -> $f2" + echo "$f2" +} + ArgvFileAction() { local av_action="$1"; shift @@ -126,14 +143,14 @@ ArgvFileAction() local av_f if [ $# -gt 0 ]; then for av_f; do - [ -n "$av_f" -a -z "${av_f##/*}" ] || av_f=$(readlink -vm -- "$av_f") + [ -n "$av_f" -a -z "${av_f##/*}" ] || av_f=$(CanonPath "$av_f") Debug "processing $av_f" "$av_action" "$av_f" done else [ -t 0 ] && Info "reading file list from standard input" while IFS= read -r av_f; do - [ -n "$av_f" -a -z "${av_f##/*}" ] || av_f=$(readlink -vm -- "$av_f") + [ -n "$av_f" -a -z "${av_f##/*}" ] || av_f=$(CanonPath "$av_f") Debug "processing $av_f" "$av_action" "$av_f" done