#!/usr/bin/python

import sys
import os
import string
import re

# Additional modules to pull in for different types
extramods = {
    "scsi":  [ "sr_mod", "ide-scsi" ],
    "net":   [ "af_packet" ],
    "other": [ "unix", "fat", "msdos", "isofs" ]
    }

# Globals.
modpath = "/lib/modules"
kernelversion = ""
kerneldir = ""
pcilist = "/usr/share/discover/pci.lst"

# Read the command-line arguments.
modlist = []
modtypes = []
for arg in sys.argv[1:]:
    # Kernel version - not preceded by two dashes
    if arg[:2] != "--":
        kernelversion = arg
        continue
    # Path to the module list files
    elif arg[2:9] == "confdir":
        confdir = arg[string.index(arg, "=") + 1:]
        for listfn in ("%s/scsip1.lst" % confdir, \
                       "%s/scsimod.lst" % confdir, \
                       "%s/netmod.lst" % confdir):
            if os.path.exists(listfn):
                listfile = open(listfn)
                for line in listfile.readlines():
                    line = string.strip(line)
                    modlist.append(line)
                listfile.close()
        continue
    # Path to the kernel files
    elif arg[2:11] == "kerneldir":
        kerneldir = arg[string.index(arg, "=") + 1:]
        continue

    # Everything else is a type of module to include
    modtypes.append(arg[2:])

# If an alternate kernel dir was specified, make sure we use it.
if kerneldir:
    modpath = "%s/lib/modules" % kerneldir
    if not os.path.isdir(modpath):
        sys.stderr.write("%s: kernel not found in %s\n" % kerneldir)
        sys.exit(1)

    # If a kernel dir was specified but not a kernel version, look for a
    # single kernel in the kernel dir.
    if not kernelversion:
        kernelversions = os.listdir("%s/lib/modules" % kerneldir)
        if len(kernelversions) != 1:
            sys.stderr.write("%s: cannot determine proper kernel in %s\n"
                             % (sys.argv[0], kerneldir))
            sys.exit(1)

        kernelversion = kernelversions[0]

# Check that the kernel version exists.
if not kernelversion or not os.path.exists("%s/%s" % (modpath, kernelversion)):
    sys.stderr.write("%s: kernel version %s does not exist\n" %
                     (sys.argv[0], kernelversion))
    sys.exit(1)

# If no module list files were specified, look for modules to add.
if len(modlist) == 0:
    modlistfile = open(pcilist)
    for modlistline in modlistfile.readlines():
        if modlistline[0] not in string.whitespace:
            continue

        modfields = string.split(modlistline)
        if len(modfields) < 3:
            continue
        if modfields[2] == "unknown" or modfields[2] == "ignore":
            continue

        if modfields[1] in modtypes and modfields[2] not in modlist:
            modlist.append(modfields[2])

    modlistfile.close()

for modtype in modtypes + ["other"]:
    if extramods.has_key(modtype):
        modlist = modlist + extramods[modtype]

# Module dependencies.
modpaths = []
depstanza = ""
depfile = open("%s/%s/modules.dep" % (modpath, kernelversion))
for depline in depfile.readlines():
    if depline[-1] == "\n":
        depline = depline[:-1]

    if re.search("\S+", depline) is not None:
        if depline[-1] == '\\':
            depline = depline[:-1]
        depstanza = depstanza + " " + depline
    else:
        depfields = string.split(depstanza)
        depmodpath = depfields[0][:-1]
        depmodname = os.path.basename(depmodpath)[:-2]

        if depmodname in modlist and depmodpath not in modpaths:
            modpaths.append(depmodpath)
            if len(depfields) > 1:
                for depmodpath in depfields[1:]:
                    if depmodpath not in modpaths:
                        depmodname = os.path.basename(depmodpath)[:-2]
                        modlist.append(depmodname)
                        modpaths.append(depmodpath)

        depstanza = ""

depfile.close()

# Copy the modules in.
os.mkdir("modules")
modroot = "modules/%s" % kernelversion
os.mkdir(modroot)
os.system("cp %s/%s/modules.dep %s" % (modpath, kernelversion, modroot))
for depmodpath in modpaths:
    depmodrealpath = "%s%s" % (kerneldir, depmodpath)
    if not os.path.exists(depmodrealpath):
        continue

    moddir = "%s/%s" % (modroot, os.path.basename(os.path.dirname(depmodpath)))
    if not os.path.isdir(moddir):
        os.mkdir(moddir)
    os.system("cp %s %s" % (depmodrealpath, moddir))
