#!/usr/bin/env python3


######
#
# Example Usage :
#
# This is commonly used to retrieve .symvers files that the RTS build is dependent on
# 
# MBUF_SYM := $(shell $(srcdir)/find_module_symvers -q mbuf) 
#
# The other less common use is passing multiple modules and expecting only one to be installed. For the
# below to be valid, only one of the required modules should be found.
#
# DOLPHIN_SYM := $(shell /usr/bin/find_module_symvers -q ligo-dolphin-ix ligo-dolphin-px ligo-dolphin-mx) 
# 
# It is NOT a valid use to call the script with multiple independent modules:
# python3 find_module_symvers -q mbuf rts-logger 
######

import os
import sys
import subprocess
import re
import argparse



def get_first_symver_in_dir(modsymDir):
    for (dirpath, dirnames, filenames) in os.walk(modsymDir):
        for filename in filenames:
            if filename.endswith(".symvers"):
                return str(dirpath + "/" + filename)
    return None



if __name__ == "__main__":

    parser = argparse.ArgumentParser(description='A utility to search for symvers files for dkms kernel modules')
    parser.add_argument('modname', help='Name of the module to search for a symvers file for.', nargs='+')
    parser.add_argument('-q', '--quiet', default=False, action='store_true', help='Request no output on errors')

    args = parser.parse_args()
    modnames = args.modname
    quiet_err = args.quiet

    uname = os.uname()
    for modname in modnames:
        modstat = subprocess.run(
            ['/usr/sbin/dkms', '-k', uname.release, 'status', modname],
            capture_output=True, text=True,
        )
        if modstat.returncode == 0 and modstat.stdout:
            #Newer versions of dkms display "<modname>/<version>..." instead of the old "<modname>, <version> ..."
            temp =  modstat.stdout.split(':')[0]
            modstat = re.split(', |/', temp) 
            if len(modstat) >= 4:
                modvers = modstat[1]
                mkvers = modstat[2]
                march = modstat[3]
                modsymDir = os.path.join(
                    '/var/lib/dkms',
                    modname,
                    modvers,
                    mkvers,
                    march
                )

                mod_path = get_first_symver_in_dir(modsymDir)
                if mod_path != None:
                    print(mod_path)
                    exit(0) #Exit on first found symvers

    # If we get here we didn't find a symvers for any of the requested modules
    # Time to look in the manual install location

    for modname in modnames:
        modsymDir = os.path.join('/var/cache', modname)
        mod_path = get_first_symver_in_dir(modsymDir)
        if mod_path != None:
            print(mod_path)
            exit(0)

    #We only get here if we did not find the symvers above
    if quiet_err:
        exit(1)
    exit(f"No symvers could be found for any of the '{modnames}' modules.")
