I have a previous version of a package I maintain, that contained a subdirectory with files in it. The upgrade is happening on RHEL/CentOS 7. For example my version 1.0 RPM contained:
/opt/foo/etc/bar/x/y
/opt/foo/etc/bar/z
etc. In the newer version of this package, I must replace the entire /opt/foo/etc/bar
directory with a file of that same name (unfortunately this is required by the tool, there's nothing I can do about it). So in the new version of the package, it will contain
/opt/foo/etc/bar
which is a file.
If I run normal rpm --upgrade pkg-2.0.rpm
, I get an error before any of my spec scriptlets are even invoked:
file /opt/foo/etc/bar from install of pkg-2.0-1.x86_64 conflicts with file from package pkg-1.0-1.x86_64
In order to avoid this I must add the --replacefiles
option to my rpm
command line, which is gross.
Even if I do that, it still fails, this time after my preinst scriptlet runs, with an error like this:
error: unpacking of archive failed on file /opt/foo/etc/bar: cpio: rename failed - Is a directory
error: pkg-2.0-1.x86_64: install failed
error: pkg-1.0-1.x86_64: erase skipped
The only way I can make this work, as far as I can tell, is to modify my preinst to remove the directory, AND to add the --replacefiles
option to rpm
. Even after I do all that, while the upgrade does succeed it throws a warning for every single file which is "missing" (because I removed the directory):
warning: file /opt/foo/etc/bar/x/y: remove failed: Not a directory
warning: file /opt/foo/etc/bar/z: remove failed: Not a directory
I don't know why it's showing this error since these things are not directories and never were, but anyway.
I've searched all around for info on this particular issue and while I've found lots of sort-of similar errors they are all for different situations, such as people trying to install two packages with overlapping files or similar. Here I'm definitely trying to upgrade one version of a package to a new version of that same package.
There seems to be no possible way to make this work cleanly in RPM; is this just a deficiency of the RPM tool or am I missing something?
This is an outstanding issue of rpm for a long time. It is caused by CPIO, which cannot replace directory by file (and vice versa).
If you cannot change the pathname, then you have two options - both are ugly hacks:
You start with A-1.0.rpm which includes /opt/foo/etc/bar/z
as directory. Then you create A-transition-1.1.rpm which will do not have /opt/foo/etc/bar/z
directory (in fact - it can be empty package) and you will Obsolete: A <= 0:1.0
. The leading zero is epoch. I assume you did not used it in past. Then you will create new A-1.0.rpm with Epoch: 1
and you will Obsolete: A-transition < 0:2.0
and this time it can contain /opt/foo/etc/bar/z
as a file. RPM will do the upgrade 0:A-1.0 -> A-transition -> 1:A-1.0
Because this is a CPIO issue you can:
%pre if [ -d /opt/foo/etc/bar/z ]; then rm -rf /opt/foo/etc/bar/z fi
RPM will shout about missing /opt/foo/etc/bar/z
when removing old package, but it should pass (not tested thou).