rpmbuild: brp-java-repack-jars changes jar permissions - linux

Consider a SPEC file containing:
%install
install -m u=rwx,g=rx,o= -D bin/blah.jar ${RPM_BUILD_ROOT}%{_libexecdir}/foo/blah.jar
Then in the %files section, the permissions are not changed (say, %defattr(-,bubba,users,-)).
Installing the RPM results in blah.jar having permissions 644 instead of 640. Indeed, no matter what permissions are used in the install command, they're reset to the default 640. I've found that the cause is the jar repacking, as permissions are maintained if I disable repacking by adding %define __jar_repack %{nil} to the SPEC file.
This is a nasty bug of the repacker.
How do I get both repacking to work and the permissions to be preserved (and I mean preserved, not setting them instead in the %files section, as then I'd have to mention individual files not only in %install but in %files as well, rather than just whole directories in the latter)?

Related

How to run a bash script that installs rpms from a current rpm spec file?

I have this internal software installer that has a size > 4.9GBs,
it installs a bunch of rpms/libraries and set some configs at the end.
I need to create a RPM using rpmbuild(Im new to this rpm creation) in order to install the RPM and also proceed to install/execute this installer(its a bash file).
My rpm spec is currently doing this at (you can check the code below):
%install
Copy 2 zips files into a specific folder.
This are 2 zip files from the actual software folder, I just splitted its
content in 2 parts and zip them to avoid the max size limitations(4gbs if Im
not wrong).
%post
Unzip those files into a specific folder.
run the bash script installer that was inside those zip files (it will run silently because a -s flag that it has).
Complete the bash and rpm installation successfully.
I had alredy built the rpm, so when I try to:
yum install .rpm,
it does the zip part just fine but it stays forever doing nothing at the bash installation part, maybe because this rpm lock thing, but I'm not sure.
By the way, Im not sure at all if this is a good approach for this at the end, I mean combined this rpm and installation stuff
So because the install.sh part is giving me this issues I tried this different changes:
sudo /root/sotfware/install.sh -silent /root/software/silent_configfile.conf
/root/sotfware/install.sh -silent /root/software/silent_configfile.conf
./root/sotfware/install.sh -silent /root/software/silent_configfile.conf
What do you guys thisnk I'm doing wrong?,
Whats the best way to do this? or
Whats you recommendation for this?
This is the spec file:
Name: software-19
Version: 1.0
Release: 1
Summary: software 2019
License: N/A
URL: https://
AutoReqProv: no
AutoReq: no
%description
Some description
%install
mkdir -p %{buildroot}/root/software2019
cp /root/software/software-1.zip %{buildroot}/root/software2019/software-1.zip
cp /root/software/software-2.zip %{buildroot}/root/software2019/software-2.zip
%post
unzip /root/software/software-1.zip -d /root/software2019/
unzip /root/software/software-2.zip -d /root/software2019/rpm/
sudo /root/software/install.sh -s /root/software2019/silent_configfile.conf
rm -rf /root/software/
%clean
rm -rf %{buildroot}
%files
/root/software/*
%changelog
* Tue Jan 20 2019 1.0
- Initial release
Hopefully Im been clear, thanks in advance!
You have multiple issues here
You are building RPMs as root, which is dangerous and can wipe your machine if you don't write things correctly. Since you're just getting started, this is much more likely.
The source files shouldn't have absolute paths.
You shouldn't use sudo because RPM installation is always run as root.
silent_configfile.conf wasn't included in the RPM, so the target machine might not have it.
The %post deletes the files that you told RPM you would install, likely causing errors.
This would also break rpm -V verification.
You are misusing the RPM system by doing a third-party install in your %post.
This breaks things like rpm -q --whatprovides /root/software19/myfile.
This breaks rpm -V because it cannot verify the files you installed.
This breaks any concept of uninstall / upgrade because you don't provide %preun and related files to "do the right thing."
To do things right and not cause your admins headaches for years to come, you need to have those installers run during RPM creation (again, not as root!) with a target of %{buildroot} and then distributing the resulting file structure as an RPM. If this is not something that can be done, then RPM is probably not going to work for you and you need to look at other distribution options, like custom scripts.

rpmbuild does not preserve permissions of directories

I have an application in /opt/MyApp that I need to pack into an RPM package using FPM as follows:
fpm -e -s dir -t rpm --name 'MyApp' --version '1.0' --iteration "12345" --directories /opt/MyApp --epoch 0 /opt/MyApp
(other options are not relevant here)
All files and directories in MyApp are owned by root (both user and group). Also there is a directory called "help" with different permissions like
drwxrwxrwx.
i.e. all users can write into that directory.
When I inspect the spec file generated by FPM, it has
%defattr(-,root,root,-)
and all directories (%dir) and files are then listed, so I would expect that all original permissions are preserved in this package. However, when I inspect it using
rpm -qlvp MyApp.rpm
the permission on the "help" directory are reset to:
drwxrwxr-x
i.e. other users cannot write there anymore.
My first guess was to add the option
--rpm-use-file-permissions
but it made things even worse, because now all files in RPM are owned by the user that called FPM.
Edited:
I've achieved the result using
--rpm-use-file-permissions --rpm-user root --rpm-group root
but still it doesn't feel elegant and flexible.
Thanks in advance.
The comment about %defattr, and absence of comments about the BUILDROOT tree may indicate some confusion. According to rpm.org:
If a particular attribute does not need to be specified (usually because the file is installed with that attribute set properly), then that attribute may be replaced with a dash
That is, if no explicit permission is given in %defattr, then the permissions from build-time %install when constructing the rpm are satisfactory. There is no guarantee that those match (or are even compatible with) the actual system on which the rpm is later installed.

rpmbuild: common ownership of directories

Suppose packages I'm building for myprog1 and myprog2 are to install in /usr/lib/mysystem/myprog1/ and /usr/lib/mysystem/myprog2/
According to some distros' documentation, such in the case of OpenSUSE, both packages must own the shared directory. But how is that accomplished in the .spec files? Is the following correct?
%files
/usr/lib/mysystem
or do I need to do
%files
%dir /usr/lib/mysystem
/usr/lib/mysystem/myprog<1|2>
Usually only one package owns a given directory. On a typical system, there will be a package such as "filesystem" which may own things such as /bin. In the case of the filesystem package on Red Hat and OpenSUSE, that package owns /usr/bin but none of the files within that directory.
You could do that, by making a wrapper-package which owns things that are shared across your applications, and making it a dependency (Requires) of the applications which install into those directories.
To see what actually owns something with rpm, you can use the -qf options, e.g.,
rpm -qf /usr/lib/mysystem/myprog
The command works for directories as well as files.
The documentation for %dir and %files is the place to start when deciding how to make a package own a directory. In Maximum RPM: Taking the Red Hat Package Manager to the Limit, chapter 13 Directives For the %files list, it says:
As we mentioned in the section called The %files List, if a directory is specified in the %files list, the contents of that directory, and the contents of every directory under it, will automatically be included in the package
The way to get around this, is to use the %dir directive. By adding this directive to the line containing the directory, RPM will package only the directory itself, regardless of what files are in the directory at the time the package is created. Here's an example of %dir in action.
%dir /usr/blather
So the latter of the suggested cases follows the documentation. However, as a check on whether the syntax is correct (even if the rpm happens to build) it is good practice to examine the list of pathnames.
Investigating Fedora 21 to find packages for which rpm -qf shows the same directory finds several. For example, initscripts and chkconfig use the %dir directive to do this:
%dir /etc/rc.d
%dir /etc/rc.d/rc[0-9].d
%dir /etc/rc.d/init.d
in initscripts spec-file, and
/etc/rc.d
/etc/rc.d/init.d
/etc/rc[0-6].d
/etc/rc.d/rc[0-6].d
in chkconfig spec-file. However, the initscripts package requires /sbin/chkconfig, which is provided by the chkconfig package. Because of that dependency, chkconfig is the actual owner of the directory.
That depends, especially if the packages for program1 and program2 are built from one source or form completely different sources.
If they come from one source, you have to differentiate in a more sophisticated way:
%files program1
%dir /usr/lib/mysystem
/usr/lib/mysystem/program1
%files program2
%dir /usr/lib/mysystem
/usr/lib/mysystem/program2
If you build them separately, you can just do
%files programX
/usr/lib/mysystem
if you work with a clean buildroot which nevertheless only contains the files created by your package.
But it doesn't hurt to do
%files programX
%dir /usr/lib/mysystem
/usr/lib/mysystem/programX
as well.
If you have several such packages, you could even create a common package which owns that directory and which as well provides other requirements if you have such. It is then sufficient to require this "parent package", "company package" or how you want to name it.
Then it is enough to do
Requires: mysystemcompanypackage
...
%files
/usr/lib/mysystem/program1

How do I set optional configuration files in an RPM SPEC file?

Is there a way I can flag a configuration file as optional so when verification is invoked (rpm -v), it will ignore a missing configuration file?
I have an RPM package which I include a default configuration file for my application. The configuration file is not required for my application but I'd like to include it for easy configuration purposes. If the file was deleted, the application will work as expected (with some internal defaults). The problem I'm facing is that if I delete my configuration file and then run a verification on my installed RPM, the RPM indicates the package is not in good standing:
rpm -V test-rpm
(outputs)
missing c /etc/test/test.conf
Minimized SPEC definition:
Version: 0.0.1
Name: test-rpm
...
%install
install -m 644 $resource_directory/test.conf %{buildroot}/etc/test/test.conf
...
%files
%defattr(-,root,root)
%config(noreplace) /etc/test/test.conf
...
Is there some option I haven't found yet or am I misunderstanding something about RPMs?
This is what %config(missingok) is for I believe.
The %config(missingok) indicates that the file need not exist on the installed machine. The %config(missingok) is frequently used for files like /etc/rc.d/rc2.d/S55named where the (non-)existence of the symlink is part of the configuration in %post, and the file may need to be removed when this package is removed. This file is not required to exist at either install or uninstall time.

What actually is $RPM_BUILD_ROOT?

In the process of building an RPM package, I have to specify the BuildRoot and later will be used in %install which invovles $RPM_BUILD_ROOT. I always think that $RPM_BUILD_ROOT is the fake installation for RPM to perform packaging. Then, at install time using the RPM package, it will install into actual location. For example:
$RPM_BUILD_ROOT/usr/bin
I thought that $RPM_BUILD_ROOT is for the packaging process only, and in some ways RPM can distinguish the $RPM_BUILD_ROOT and the actual install location when the user performs "rpm -ivh package.rpm" will be /usr/bin.
But recently upon reading some documents, it is suggested that $RPM_BUILD_ROOT is the actual location which will be installed, and the $RPM_BUILD_ROOT is specified by user with the setting of environment variable $RPM_BUILD_ROOT in order to let the users install the package in their desire locations. Otherwise, $RPM_BUILD_ROOT will be null and it will install into the default location. In the above case, it is /usr/bin . Thus, $RPM_BUILD_ROOT is not just for packaging or "fake installation" process, but is a way for user to define install location, similar to select folder location in Windows.
I don't know my thinking is correct or not. Can someone please verify? Thanks in advance.
$RPM_BUILD_ROOT (or the equivalent %{buildroot} SPEC file macro) always holds the directory under which RPM will look for any files to package. The RPM scripts (e.g. the script that compresses the manual pages) will also use that value to know where to look for the files that were just installed. Normally, this value will be non-empty and contain a location away from the system directories - usually somewhere under /tmp or /var/tmp.
The author of the SPEC file is expected to make sure that make install (or whatever installer the software in question is using) will place any files under $RPM_BUILD_ROOT, with the same hierarchy that should be used when the software is finally installed. E.g. to have RPM install ls in /bin/ls, the %install SPEC file section should make sure that ls is placed in $RPM_BUILD_ROOT/bin/ls.
The author of the SPEC file is also expected to use the BuildRoot: tag to specify a proper location. Alternatively, the build system could have an rpmrc RPM configuration file with a proper entry. In any case the build root should be set, so that:
Normal users will be able to build the source package.
Should the superuser ever build the source package, the build process will not clobber any system files, unless the superuser installs the resulting binary package. And yes, there may be a good reason to build some packages as root - for example, running the full glibc testsuite requires root privileges for some tests.
That said, RPM can and will build a package with an empty build root variable. In that case both the build install and the final destination locations will coincide. A potential call to e.g. make install will use the default locations, thus clobbering the system files under e.g. /usr/lib if run with sufficient privileges. Additionally, having /usr/bin/* in your %files section will happily pull the whole contents of the build host /usr/bin/ directory into your binary package.
Bottom line:
Never use an empty build root.
Do not build packages as root unless there is absolutely no other way.
the file ~/.rpmmacros defines the paths per user:
%_topdir %(echo $HOME)/rpmbuild
%_tmppath %{_topdir}/tmp
and one can also define them with rpmbuild command line parameters:
rpmbuild --define '_topdir /home/username/rpmbuild'

Resources