Support relocatable packages in Lua scriptlets too (#1531)

Pass relocatable package prefixes as RPM_INSTALL_PREFIX Lua table
to Lua scriptlets, add a test-case.

In Lua, indexes start at 1 rather than 0, so the numbers appear
off by one which is annoying, but consistent within Lua and our other
similar Lua constructs such as scriptlet arg.

Fixes: #1531
This commit is contained in:
Panu Matilainen 2022-01-20 15:54:46 +02:00 committed by Florian Festi
parent fc8386be36
commit ed61ee28d0
5 changed files with 82 additions and 0 deletions

View File

@ -29,6 +29,10 @@ The point? Remember, Lua is embedded in rpm. This means the Lua scriptlets run i
Scriptlet arguments are accessible from a global 'arg' table. Note: in Lua, indexes customarily start at 1 (one) instead of 0 (zero), and for the better or worse, the rpm implementation follows this practise. Thus the scriptlet arg indexes are off by one from general expectation based on traditional scriptlet arguments. The argument containing number of installed package instances is arg[2] and the similar argument for trigger targets is arg[3], whereas traditionally they are 1 and 2 (eg $1 and $2 in shell scripts).
Scriptlets of relocatable packages additionally carry a global
`RPM_INSTALL_PREFIX` table containing all the possible prefixes of the
package. (rpm >= 4.18.0)
While scriptlets shouldn't be allowed to fail normally, you can signal scriptlet failure status by using Lua's error(msg, [level]) function if you need to. As <lua> scriptlets run within the rpm process itself, care needs to be taken within the scripts - eg os.exit() must not be called (see ticket #167). In newer rpm versions (>= 4.9.0) this is not an issue as rpm protects itself by returning errors on unsafe os.exit() and posix.exec().
## Lua macros

View File

@ -125,6 +125,16 @@ static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
lua_setfield(L, -2, "next_file");
}
if (prefixes) {
lua_newtable(L);
for (ARGV_const_t p = prefixes; p && *p; p++) {
int i = p - prefixes + 1;
lua_pushstring(L, *p);
lua_rawseti(L, -2, i);
}
lua_setglobal(L, "RPM_INSTALL_PREFIX");
}
if (arg1 >= 0)
argvAddNum(argvp, arg1);
if (arg2 >= 0)
@ -165,6 +175,11 @@ static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes,
}
free(scriptbuf);
if (prefixes) {
lua_pushnil(L);
lua_setglobal(L, "RPM_INSTALL_PREFIX");
}
if (nextFileFunc) {
lua_pushnil(L);
lua_setfield(L, -2, "next_file");

View File

@ -75,6 +75,7 @@ EXTRA_DIST += data/SPECS/scriptfile.spec
EXTRA_DIST += data/SPECS/selfconflict.spec
EXTRA_DIST += data/SPECS/shebang.spec
EXTRA_DIST += data/SPECS/suicidal.spec
EXTRA_DIST += data/SPECS/reloc.spec
EXTRA_DIST += data/SPECS/replacetest.spec
EXTRA_DIST += data/SPECS/triggers.spec
EXTRA_DIST += data/SPECS/filetriggers.spec

View File

@ -0,0 +1,31 @@
Name: reloc
Version: 1.0
Release: 1
Summary: Testing relocation behavior
Group: Testing
License: GPL
Prefixes: /opt/bin /opt/etc /opt/lib
BuildArch: noarch
%description
%{summary}
%install
mkdir -p $RPM_BUILD_ROOT/opt/{bin,lib,etc}
touch $RPM_BUILD_ROOT/opt/bin/typo
touch $RPM_BUILD_ROOT/opt/lib/notlib
touch $RPM_BUILD_ROOT/opt/etc/conf
%pre -p <lua>
for i, p in ipairs(RPM_INSTALL_PREFIX) do
print(i..": "..p)
end
%post
echo 0: $RPM_INSTALL_PREFIX0
echo 1: $RPM_INSTALL_PREFIX1
echo 2: $RPM_INSTALL_PREFIX2
%files
%defattr(-,root,root,-)
/opt

View File

@ -690,6 +690,37 @@ runroot rpm -U --test --ignoreos --badreloc --relocate /usr=/opt \
[])
AT_CLEANUP
AT_SETUP([rpm -i relocatable package])
AT_KEYWORDS([install relocate])
AT_CHECK([
RPMDB_INIT
runroot rpmbuild --quiet -bb /data/SPECS/reloc.spec
runroot rpmbuild --quiet -bb /data/SPECS/fakeshell.spec
runroot rpm -U /build/RPMS/noarch/fakeshell-1.0-1.noarch.rpm
runroot rpm -U \
/build/RPMS/noarch/reloc-1.0-1.noarch.rpm
runroot rpm -e reloc
runroot rpm -U --relocate /opt/bin=/bin \
/build/RPMS/noarch/reloc-1.0-1.noarch.rpm
],
[0],
[1: /opt/bin
2: /opt/etc
3: /opt/lib
0: /opt/bin
1: /opt/etc
2: /opt/lib
1: /bin
2: /opt/etc
3: /opt/lib
0: /bin
1: /opt/etc
2: /opt/lib
],
[])
AT_CLEANUP
AT_SETUP([rpm -i with/without --excludedocs])
AT_KEYWORDS([install excludedocs])
AT_CHECK([