#!/usr/bin/env python3
#
# Copyright 2018 - The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Command-line tool to build SEPolicy files."""

import argparse
import os
import subprocess
import sys

import file_utils


# All supported commands in this module.
# For each command, need to add two functions. Take 'build_cil' for example:
#   - setup_build_cil()
#     - Sets up command parsers and sets default function to do_build_cil().
#   - do_build_cil()
_SUPPORTED_COMMANDS = ('build_cil', 'filter_out')


def run_host_command(args, **kwargs):
    """Runs a host command and prints output."""
    if kwargs.get('shell'):
        command_log = args
    else:
        command_log = ' '.join(args)  # For args as a sequence.

    try:
        subprocess.check_call(args, **kwargs)
    except subprocess.CalledProcessError as err:
        sys.stderr.write(
            'build_sepolicy - failed to run command: {!r} (ret:{})\n'.format(
                command_log, err.returncode))
        sys.exit(err.returncode)


def do_build_cil(args):
    """Builds a sepolicy CIL (Common Intermediate Language) file.

    This functions invokes some host utils (e.g., secilc, checkpolicy,
    version_sepolicy) to generate a .cil file.

    Args:
        args: the parsed command arguments.
    """
    # Determines the raw CIL file name.
    input_file_name = os.path.splitext(args.input_policy_conf)[0]
    raw_cil_file = input_file_name + '_raw.cil'
    # Builds the raw CIL.
    file_utils.make_parent_dirs(raw_cil_file)
    checkpolicy_cmd = [args.checkpolicy_env]
    checkpolicy_cmd += [os.path.join(args.android_host_path, 'checkpolicy'),
                        '-C', '-M', '-c', args.policy_vers,
                        '-o', raw_cil_file, args.input_policy_conf]
    # Using shell=True to setup args.checkpolicy_env variables.
    run_host_command(' '.join(checkpolicy_cmd), shell=True)
    file_utils.filter_out([args.reqd_mask], raw_cil_file)

    # Builds the output CIL by versioning the above raw CIL.
    output_file = args.output_cil
    if output_file is None:
        output_file = input_file_name + '.cil'
    file_utils.make_parent_dirs(output_file)

    run_host_command([os.path.join(args.android_host_path, 'version_policy'),
                      '-b', args.base_policy, '-t', raw_cil_file,
                      '-n', args.treble_sepolicy_vers, '-o', output_file])
    if args.filter_out_files:
        file_utils.filter_out(args.filter_out_files, output_file)

    # Tests that the output file can be merged with the given CILs.
    if args.dependent_cils:
        merge_cmd = [os.path.join(args.android_host_path, 'secilc'),
                     '-m', '-M', 'true', '-G', '-N', '-c', args.policy_vers]
        merge_cmd += args.dependent_cils      # the give CILs to merge
        merge_cmd += [output_file, '-o', '/dev/null', '-f', '/dev/null']
        run_host_command(merge_cmd)


def setup_build_cil(subparsers):
    """Sets up command args for 'build_cil' command."""

    # Required arguments.
    parser = subparsers.add_parser('build_cil', help='build CIL files')
    parser.add_argument('-i', '--input_policy_conf', required=True,
                        help='source policy.conf')
    parser.add_argument('-m', '--reqd_mask', required=True,
                        help='the bare minimum policy.conf to use checkpolicy')
    parser.add_argument('-b', '--base_policy', required=True,
                        help='base policy for versioning')
    parser.add_argument('-t', '--treble_sepolicy_vers', required=True,
                        help='the version number to use for Treble-OTA')
    parser.add_argument('-p', '--policy_vers', required=True,
                        help='SELinux policy version')

    # Optional arguments.
    parser.add_argument('-c', '--checkpolicy_env',
                        help='environment variables passed to checkpolicy')
    parser.add_argument('-f', '--filter_out_files', nargs='+',
                        help='the pattern files to filter out the output cil')
    parser.add_argument('-d', '--dependent_cils', nargs='+',
                        help=('check the output file can be merged with '
                              'the dependent cil files'))
    parser.add_argument('-o', '--output_cil', help='the output cil file')

    # The function that performs the actual works.
    parser.set_defaults(func=do_build_cil)


def do_filter_out(args):
    """Removes all lines in one file that match any line in another file.

    Args:
        args: the parsed command arguments.
    """
    file_utils.filter_out(args.filter_out_files, args.target_file)

def setup_filter_out(subparsers):
    """Sets up command args for 'filter_out' command."""
    parser = subparsers.add_parser('filter_out', help='filter CIL files')
    parser.add_argument('-f', '--filter_out_files', required=True, nargs='+',
                        help='the pattern files to filter out the output cil')
    parser.add_argument('-t', '--target_file', required=True,
                        help='target file to filter')
    parser.set_defaults(func=do_filter_out)


def run(argv):
    """Sets up command parser and execuates sub-command."""
    parser = argparse.ArgumentParser()

    # Adds top-level arguments.
    parser.add_argument('-a', '--android_host_path', default='',
                        help='a path to host out executables')

    # Adds subparsers for each COMMAND.
    subparsers = parser.add_subparsers(title='COMMAND')
    for command in _SUPPORTED_COMMANDS:
        globals()['setup_' + command](subparsers)

    args = parser.parse_args(argv[1:])
    args.func(args)


if __name__ == '__main__':
    run(sys.argv)
