On linux can we repackage a installed rpm if so how.I remember that the a rpm can be generated from the installed binaries
rpm -??? > my.rpm
Also the later i.e, the newer rpm should work on a different machine
There is also rpmrebuild
http://rpmrebuild.sourceforge.net
Actually there is a simple but "tricky" way; it is just : rpm -e --repackage package-name
It will output the RPM in /var/spool/repackage/.
Example:
# rpm -e --repackage samba3x-client
# file /var/spool/repackage/samba3x-client-3.5.4-0.83.el5_7.2.i386.rpm
/var/spool/repackage/samba3x-client-3.5.4-0.83.el5_7.2.i386.rpm: RPM v3 bin i386 samba3x-client-3.5.4-0.83.el5_7
Why tricky? Because it actually remove the program prior packaging it, just so you know.
This is possible, but not with the rpm command. I wrote a perl script that does this; it crafts a spec file based on the outputs of rpm -q and does a "build" which just copies the installed files from the system.
You can find it here: https://github.com/cormander/rogue-beret-tools/blob/master/scripts/rpm-repack
Usage example, re-packaging the mailx rpm:
Query it:
$ rpm -ql mailx
/bin/mail
/etc/mail.rc
/usr/bin/Mail
/usr/lib/mail.help
/usr/lib/mail.tildehelp
/usr/share/man/man1/Mail.1.gz
/usr/share/man/man1/mail.1.gz
Repack it:
$ ./rpm-repack -p mailx
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.9773
+ umask 022
+ cd /usr/src/redhat/BUILD
+ /usr/lib/rpm/brp-compress
+ /usr/lib/rpm/brp-strip
+ /usr/lib/rpm/brp-strip-static-archive
+ /usr/lib/rpm/brp-strip-comment-note
Processing files: mailx-8.1.1-44.2.2
Provides: mailx
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: libc.so.6 libc.so.6(GLIBC_2.0) libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.3) libc.so.6(GLIBC_2.3.4) libc.so.6(GLIBC_2.4) rtld(GNU_HASH)
Checking for unpackaged file(s): /usr/lib/rpm/check-files /tmp/tlkN4yrYEi
Wrote: ~/rpmbuild/RPMS/i386/mailx-8.1.1-44.2.2.i386.rpm
Query the newly built package:
$ rpm -qpl ~/rpmbuild/RPMS/i386/mailx-8.1.1-44.2.2.i386.rpm
/bin/mail
/etc/mail.rc
/usr/bin/Mail
/usr/lib/mail.help
/usr/lib/mail.tildehelp
/usr/share/man/man1/Mail.1.gz
/usr/share/man/man1/mail.1.gz
The code isn't at all elegant, but functional. It does copy a lot of the rpm info (everything from rpm -qi and most of the scripts), but it isn't by any means comprehensive. Also, it can't copy the GPG signature, nor will it have the same checksums as the original RPM file.
NOTE: This is not a "proper" way to build and distribute RPM packages, and was mainly written for troubleshooting and educational purposes.
I think that most rpm based distributions how have official package rpmrebuild (or in the almost official 3'rd party repos like epel, rpmfusion ... etc). I think nowadays this would be your best option for repackaging installed packages.
Related
Here is written that curlftpfs is terribly slow because of bug in newest libcurl3-gnutls. Downgrading is not recommended due to large reverse dependencies that this package has (can be verified via apt-cache showpkg libcurl3-gnutls:amd64 or apt-cache rdepends libcurl3-gnutls:amd64). So I've decided to downgrade it different way. I've checked available versions in repository:
$ apt-cache policy libcurl3-gnutls:amd64
libcurl3-gnutls:
Installed: 7.43.0-1ubuntu2.1
Candidate: 7.43.0-1ubuntu2.1
Version table:
*** 7.43.0-1ubuntu2.1 0
500 http://sk.archive.ubuntu.com/ubuntu/ wily-updates/main amd64 Packages
500 http://security.ubuntu.com/ubuntu/ wily-security/main amd64 Packages
100 /var/lib/dpkg/status
7.43.0-1ubuntu2 0
500 http://sk.archive.ubuntu.com/ubuntu/ wily/main amd64 Packages
Then I've downloaded and extracted older version than installed one:
$ apt-get install -d libcurl3-gnutls=7.43.0-1ubuntu2
$ sudo mv /var/cache/apt/archives/libcurl3-gnutls_7.43.0-1ubuntu2_amd64.deb .
$ dpkg -x libcurl3-gnutls_7.43.0-1ubuntu2_amd64.deb extracted_deb
Then I've backed up original binary and searched for some common name in shared libraries:
$ cp $(which curlftpfs) .
$ ldd ./curlftpfs | grep curl
libcurl-gnutls.so.4 => /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 (0x00007fcac4443000)
$ readelf -d ./curlftpfs | grep -i curl
0x0000000000000001 (NEEDED) Shared library: [libcurl-gnutls.so.4]
Following step was just the proof that linked file belongs exactly to libcurl3-gnutls package and that curlftpfs depends on libcurl3-gnutls:
$ dpkg -S /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
libcurl3-gnutls:amd64: /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
$ apt-cache depends curlftpfs
curlftpfs
Depends: libc6
Depends: libcurl3-gnutls
Depends: libfuse2
Depends: libglib2.0-0
Depends: fuse
Conflicts: curlftpfs:i386
Also the content of extracted and installed libcurl3-gnutls package seems exactly the same:
$ dpkg -L libcurl3-gnutls:amd64 | sort
/.
/usr
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0
/usr/share
/usr/share/doc
/usr/share/doc/libcurl3-gnutls
/usr/share/doc/libcurl3-gnutls/changelog.Debian.gz
/usr/share/doc/libcurl3-gnutls/copyright
/usr/share/doc/libcurl3-gnutls/NEWS.Debian.gz
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/libcurl3-gnutls
$ find extracted_deb/ | sort
extracted/
extracted/usr
extracted/usr/lib
extracted/usr/lib/x86_64-linux-gnu
extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3
extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4
extracted/usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4.3.0
extracted/usr/share
extracted/usr/share/doc
extracted/usr/share/doc/libcurl3-gnutls
extracted/usr/share/doc/libcurl3-gnutls/changelog.Debian.gz
extracted/usr/share/doc/libcurl3-gnutls/copyright
extracted/usr/share/doc/libcurl3-gnutls/NEWS.Debian.gz
extracted/usr/share/lintian
extracted/usr/share/lintian/overrides
extracted/usr/share/lintian/overrides/libcurl3-gnutls
My question is how can I rewrite the path that is contained in ldd output and point it to file that I've extracted? I've read about rpath and patchelf and chrpath here and here but I guess this is not my case because following commands returns nothing useful:
$ readelf -d ./curlftpfs | grep -i rpath
$
$ chrpath -l ./curlftpfs
./curlftpfs: no rpath or runpath tag found.
$
$ patchelf --print-rpath ./curlftpfs
$
So it seems that rpath is not used. I've also read about $LD_LIBRARY_PRELOAD but I guess that it will change path for all shared libraries for given binary not just one particular (in my case /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4) so I would need to have whole tree of libraries. There is also solutions which suggest changing loader (in my example /lib64/ld-linux-x86-64.so.2 I guess):
$ patchelf --print-interpreter ./curlftpfs
/lib64/ld-linux-x86-64.so.2
$
$ ldd ./curlftpfs | grep ld-linux
/lib64/ld-linux-x86-64.so.2 (0x0000564966b64000)
$
$ ls -laL /lib/x86_64-linux-gnu/ld-2.21.so
-rwxr-xr-x 1 root root 154376 Mar 26 2015 /lib/x86_64-linux-gnu/ld-2.21.so
but to be honest I didn't get the point of this. Can you please assists?
My question is how can I rewrite the path that is contained in ldd
output and point it to file that I've extracted?
It seems like what you want is to override the functionality for just the libcurl-gnutls.so library with an older version. As hinted to in the last link you provided, you can use the LD_PRELOAD environment variable to override the standard library functions.
Say your manually installed (downgraded) version of libcurl-gnutls has the dynamic library file /usr/local/lib/libcurl-gnutls.so.4.4.0.
You could then do something like the following:
LD_PRELOAD=/usr/local/lib/libcurl-gnutls.so.4.4.0 curlftpfs [some_arguments...]
Don't forget that /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 and /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.3 are just symbolic links to the master library file for libcurl-gnutls. Copying these symbolic links may not have the desired effect. You need the long named SO file, like libcurl-gnutls.so.4.4.0 .
Extra Notes
You can test that this override worked by doing something like the following:
LD_PRELOAD=/usr/local/lib/libcurl-gnutls.so.4.4.0 ldd $(which curlftpfs)
For a manual installation, /usr/local/lib may not be a good place to put a dynamic library that you don't want interfering with other binaries. This is because /etc/ld.so.conf.d/libc.conf may point to /usr/local/lib for automatic libraries. (My Debian machine does)
To see the definitions of the LD_ environment variable, check out the ld.so(8) man page (man ld.so).
We are building rpm for openssl 1.0.1g for Redhat5.9 and Redhat 6.4
Steps followed:-
1-Download the openssl 1.0.1 g tar file
2-Created the following dir structure
/myrpm/BUILD
/rpm/SOURCES
/rpm/SPECS/
/rpm/RPMS
3-./config
4-make
5-make install
Our goals:-
-We need to change the soname and realname of the library and link it properly
-We also need fips enabled with openssl.
-Include these changed sonames to our rpm while rpmbuild
Currently the
soname creates as libbssl.so and libcrypto.so
real name as libssl.so.1.0.0 and libcrypto.so.1.0.0
But we required in following formats :-
soname ->libbssl.so.10 and libcrypto.so.10
realname ->libssl.so.1.0.1g and libcrypto.so.1.0.1g
It was not properly linking the sonames with realnames and not including these libraries in the rpm while building through rpmbuild command.
We have changed the Makefile and Makefile.shared but we need some options in openssl.spec file which create and link the soname and realname and also include these libraries in our rpm as mentioned above.
Any help on this will be appreciated.
Thanks,
#PP
How can i determine the Linux version (distribution) for which was compiled rpm packet?
I believe this is what you are after.
$ rpm -q gnome-speech --queryformat '%10{NAME} %20{VENDOR} %20{RELEASE} %20{ARCH}\n'
gnome-speech Red Hat, Inc. 1.fc6 i386
$ rpm -q hwdata --queryformat '%10{NAME} %20{VENDOR} %20{RELEASE} %20{ARCH}\n'
hwdata Red Hat, Inc. 1.el5 noarch
There are lots of nifty bits you can go after with queryformat, see this guide for a reference.
General reference on rpm-philosophy-multi-architecture.
There is no such ways to determine the OS name and version from the content of the file.
Normally a RPM file name contains all these details. According to the RPM file naming convention the file name must be like :
name-version-release.architecture.rpm
Please check this link for details.
You can use rpm -q to get the OS data from the OS tag in the RPM, but you need to specify a queryformat as it is not in the normal -i output. You can use -p to refer to a specific RPM file for the testing.
$ rpm -q -p myfiletotest.rpm --queryformat '%10{NAME} %10{OS} %10{VERSION} %10{RELEASE} %10{ARCH}\n'
mypackage linux 2.2.10 1_14.el6 x86_64
The OS name is the second field in this output. The RPM does not distinguish between releases of the OS though; you will only see 'linux', 'aix', 'darwin', and so on - not 'centos-6'.
I googled for this, but couldn't find how to query a non-installed RPM file for its information:
# rpm -qa blackfin-jtag-tools-09r1.1-2.i386.rpm
#
# rpm -qi blackfin-jtag-tools-09r1.1-2.i386.rpm
package blackfin-jtag-tools-09r1.1-2.i386.rpm is not installed
#
# rpm -q blackfin-jtag-tools-09r1.1-2.i386.rpm
package blackfin-jtag-tools-09r1.1-2.i386.rpm is not installed
#
# rpm --info blackfin-jtag-tools-09r1.1-2.i386.rpm
RPM version 4.8.0
Copyright (C) 1998-2002 - Red Hat, Inc.
This program may be freely redistributed under the terms of the GNU GPL
Usage: rpm [-aKfgpWHqVcdilsKiv?] [-a|--all] [-f|--file] [-g|--group] [-p|--package] [-W|--ftswalk] [--pkgid] [--hdrid] [--fileid]
[--specfile] [--triggeredby] [--whatrequires] [--whatprovides] [--nomanifest] [-c|--configfiles] [-d|--docfiles]
[--dump] [-l|--list] [--queryformat=QUERYFORMAT] [-s|--state] [--nofiledigest] [--nomd5] [--nofiles] [--nodeps]
[...]
Is there a command to read information out of non-installed RPM file?
rpm -qip foo.rpm
#crazyscot did answer the question. Thanks.
Additionally, I found that specific querytags can also be leveraged this way, which wasn't obvious from reading the man page.
So, for example, I found I can do the following:
rpm -qp --queryformat '%{ARCH}\n' foo.rpm
or, even:
xyz="ARCH"; rpm -qp --qf %{${xyz}} foo.rpm; echo ""
This works nicely for RPM's that are not installed, and leveraging the available querytags in the installed rpm
Here is more information about tags
When rpm is not-installed then (this will list the complete info, plus the list of contents in the package);
rpm -qipl <rpm_name.rpm>
When rpm is installed then;
rpm -qi <rpm_name.rpm>
For more on rpm-queries.
For more on handy-queries.
Use rpm -qip:
rpm -qip package_path1 [package_path2 ...]
-q - query the package
-p - get the package name from arguments
It shows the following info:
Name
Version
Release
Architecture
Install Date
Group
Size
License
Signature
Source RPM
Build Date
Build Host
Relocations
Packager
Vendor
URL
Summary
Description
The man page doesn't talk about the -i option in -q context. However, rpm -qp file doesn't produce the right output.
less <rpm_name.rpm>
Displays all that I need, same as 'rpm -qlpv'.
Very good resource: https://blog.packagecloud.io/eng/2015/10/13/inspect-extract-contents-rpm-packages/ .
Related - Display Infos For Installed Package :
rpm -qi InstalledPackageName
there are lot of -i option used in above answers , best way to check :
For one rpms,
rpm -qlp <rpm-name>.rpm
For all rpms , search for your file with grep :
rpm -qpl *.rpm|grep <string or file name>
rpmbuild generates RPM under which directory?
I checked the RPMS directory:-
[root#tom adil]# ls /usr/src/redhat/
BUILD RPMS SOURCES SPECS SRPMS
[root#tom adil]# ls /usr/src/redhat/RPMS/
athlon i386 i486 i586 i686 noarch
[root#tom adil]#
How to decide rpmbuild outputs in which of the above sub-directories?
Is it controlled by spec file? What is the default option?
I thought uname -p but its not the case probable uname -i is used.
Linked to my last question Difference between "machine hardware" and "hardware platform"
The binary package is named according to the %_build_name_fmt macro. By default this macro contains %{ARCH}/ at the beginning, so that is where the binary package is placed.
Following on from your last comment, by default the RPM will go into the subdirectory that matches the platform you're building on. You can override this by passing the --target parameter to rpmbuild, but this only applies where valid; for example, you can use --target i386 on an x86_64 system to build a 32-bit RPM, but you can't build a 64-bit RPM on a 32-bit platform.
The RPM goes to the RPMS folder and the source RPM to the SRPMS. This is not controlled by the spec file - this is convention. What exactly are you trying to do?