#!/usr/bin/python
#
# make-kabi - Red Hat kABI reference module generation tool
#
# We use this script to generate reference Module.kabi files.
# or add reference info to separate kabi files.
#
# Author: Jon Masters <jcm@redhat.com>
# Copyright (C) 2007 Red Hat, Inc.
#
# This software may be freely redistributed under the terms of the GNU
# General Public License (GPL).

# Changelog:
# 
# 2014/10/05 - Update for new kabi structure by Petr Oros.
# 2007/06/13 - Initial rewrite in python by Jon Masters.

__author__ = "Jon Masters <jcm@redhat.com>"
__version__ = "2.0"
__date__ = "2014/10/05"
__copyright__ = "Copyright (C) 2007 Red Hat, Inc"
__license__ = "GPL"

import getopt
import os
import re
import string
import sys

true = 1
false = 0

def load_symvers(symvers, filename):
    """Load a reference Module.symvers file."""

    symvers_file = open(filename, "r")

    while true:
        in_line = symvers_file.readline()
        if in_line == "":
            break
        if in_line == "\n":
            continue
        checksum, symbol, directory, ctype = string.split(in_line)

        symvers[symbol] = in_line[0:-1]

def load_whitelist(whitelist, order, filename):
    if os.path.isfile(filename):
        load_whitelist_file(whitelist, order, filename)
    else:
        load_whitelist_dir(whitelist, order, filename)

def load_whitelist_file(whitelist, order, filename):
    """Load a reference whitelist file."""

    whitelist_file = open(filename, "r")

    while true:
        in_line = whitelist_file.readline()
        if in_line == "":
            break
        if in_line == "\n":
            continue
        string.split(in_line)
        if in_line[0] == "[":
            continue
        symbol = in_line[1:-1]

        whitelist[symbol] = []
        order.append(symbol)

    order.sort()

def load_whitelist_dir(whitelist, order, dirname):
    """Load a reference whitelist directory."""

    for symbol in os.listdir(dirname):
        kabi_file = open(dirname + "/" + symbol, "r")
        line = []
        # store version metadata
        line.append(kabi_file.readline())
        # store content ( no empty line is bad state )
        line.append(kabi_file.readline())
        kabi_file.close()
        if re.match("#[0-9]+-[0-9]+", line[0]):
            print "Symbol " + symbol + " is currently removed, ignoring"
            continue
        whitelist[symbol] = line
        order.append(symbol)

    order.sort()

def make_kabi_file(filename, symvers, order):
    """Munge together whitelist and Module.symvers file."""

    if os.path.isfile(filename):
        print filename + " already exists"
        sys.exit(1)

    kabi_file = open(filename, "w")

    for symbol in order:
        if symvers.has_key(symbol):
            kabi_file.write(symvers[symbol] + "\n")

    kabi_file.close()

def make_kabi_dir(dirname, symvers, whitelist):
    """Munge together whitelist and Module.symvers file."""

    current_dir = os.getcwd()
    os.chdir(dirname)

    for symbol in whitelist:
        if symvers.has_key(symbol):
            kabi_file = open(symbol, "w")
            kabi_file.write(whitelist[symbol][0])
            kabi_file.write(symvers[symbol] + "\n")
            kabi_file.close()

    os.chdir(current_dir)

def usage():
    print """make-kabi: process Module.symvers into reference Module.kabi output file/directory using
           the kabi whitelist provided as a set of symbols to filer on.

    make-kabi [ -k Module.kabi or -d (kabi-module dir) ] [ -s Module.symvers ] [ -w kabi_whitelist ]

    examples:
        add checksums to files into kabi-module/kabi_x86_64/
            make-kabi -s Module.symvers -w kabi-module/kabi_x86_64/ -d

        create Module.kabi ( old style ) witch checksums
            make-kabi -s Module.symvers -w kabi-module/kabi_x86_64/ -k Module.kabi"""

if __name__ == "__main__":

    whitelist_source = ""
    symvers_file = ""
    kabi_output = ""
    kabi_file = true

    opts, args = getopt.getopt(sys.argv[1:], 'hk:s:w:d')

    for o, v in opts:
        if o == "-s":
            symvers_file = v
        if o == "-h":
            usage()
            sys.exit(0)
        if o == "-k":
            kabi_output = v
            kabi_file = true
        if o == "-d":
            kabi_file = false
        if o == "-w":
            whitelist_source = v

    if (whitelist_source == "") or (symvers_file == "") or (kabi_output == "" and kabi_file):
        usage()
        sys.exit(1)

    symvers = {}
    whitelist = {}
    whitelist_order = []

    load_symvers(symvers, symvers_file)
    load_whitelist(whitelist, whitelist_order, whitelist_source)
    if kabi_file:
        make_kabi_file(kabi_output, symvers, whitelist_order)
    else:
        make_kabi_dir(whitelist_source, symvers, whitelist)
