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
lddoutput 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" $pathand 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 $pathand 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 (usinglocatecommand) 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:12locatefinds one ore more paths. – vesii Oct 29 '21 at 10:48ltrace? – Sir Muffington Oct 30 '21 at 18:48ltracecan help here? I don't want to execute each path I want to check. – vesii Oct 31 '21 at 14:33