Given a path, I want to detect all the OS packages that needed to be installed, in order to use it. For example:
> /bin/rpm -qf --queryformat "[%{NAME}]\n" /usr/bin/tcsh
tcsh
Sometimes it does not work. For example:
> /bin/rpm -qf --queryformat "[%{NAME}]\n" /sadd/python/lib/python3.7/lib-dynload/_sqlite3.cpython-37m-x86_64-linux-gnu.so
file /sadd/python/lib/python3.7/lib-dynload/_sqlite3.cpython-37m-x86_64-linux-gnu.so is not owned by any package
But looking into the output of ldd
I see:
> ldd /sadd/python/lib/python3.7/lib-dynload/_sqlite3.cpython-37m-x86_64-linux-gnu.so
linux-vdso.so.1 (0x00007f11f7ffa000)
libsqlite3.so.0 => /usr/lib64/libsqlite3.so.0 (0x0000711fff7901000)
libpython3.7m.so.1.0 => /usr/pkgs/python3/3.7.4/lib/libpython3.7m.so.1.0 (0x00007ffff7422000)
libpthread.so.0 => /lib64/noelision/libpthread.so.0 (0x00007f11ff7205000)
libc.so.6 => /lib64/libc.so.6 (0x00007f13ff6e60000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007ff126c5c000)
libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007ff216a21000)
libutil.so.1 => /lib64/libutil.so.1 (0x0000711ff681e000)
libm.so.6 => /lib64/libm.so.6 (0x00007fff16521000)
/lib64/ld-linux-x86-64.so.2 (0x00007fff17ddb000)
I see that it has /usr/lib64/libsqlite3.so.0
. So I can do:
> /bin/rpm -qf --queryformat "[%{NAME}]\n" /usr/lib64/libsqlite3.so.0
libsqlite3-0
Meaning there is a required OS package that should be installed in order to use /sadd/python/lib/python3.7/lib-dynload/_sqlite3.cpython-37m-x86_64-linux-gnu.so
.
Now, I can create a script which runs the above rpm
command and then the ldd
command on each path and iterates over that shared libs (might need to use locate
because sometimes there is not path, like for linux-vdso.so.1
). But:
- It is not recommended to use
ldd
. - The parsing of the
ldd
output is pretty ugly.
Now, I saw a related topic on the matter. I could use readelf
but same issue.
Is there a better solution to detect all the required OS packages for a given path? I also am using rpmdep.pl but it expects to get a package name and returns all the package dependencies. So for now my algorithm is:
- Run
/bin/rpm -qf --queryformat "[%{NAME}]\n" $path
and get the package name (marked with$package)
. Also add it to the packages list. - Run
rpmdep.pl $package
) and add all the packages to the list. - Run
ldd $path
and for each line:- if there is a path (like
libsqlite3.so.0 => /usr/lib64/libsqlite3.so.0
) then go back to step 1 with/usr/lib64/libsqlite3.so.0
. - if there is no path (like
linux-vdso.so.1
) then try to locate it (usinglocate
command) and if found, then go back to step 1 with the path you got.
- if there is a path (like
That way I collect all of the OS packages that are required for a path. It works pretty good but I'm looking for a better/clean approach on solving this task. Also, what do you think of my suggested algorithm?
I'm using OpenSUSE if that matters.
linux-vdso.so.1
, and that’s normal — it’s the vDSO, it doesn’t exist on disk. – Stephen Kitt Oct 28 '21 at 16:12locate
finds one ore more paths. – vesii Oct 29 '21 at 10:48ltrace
? – Sir Muffington Oct 30 '21 at 18:48ltrace
can help here? I don't want to execute each path I want to check. – vesii Oct 31 '21 at 14:33