#!/usr/bin/python3
#
# Copyright 2020 Google, Inc.
#
# Copyright (c) 2020 ARM Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#
# gem5img.py
# Script for managing a gem5 disk image.
#

from argparse import ArgumentParser
import os
from os import environ as env
import string
from subprocess import CalledProcessError, Popen, PIPE, STDOUT
from sys import exit, argv
import re

# Some constants.
MaxLBACylinders = 16383
MaxLBAHeads = 16
MaxLBASectors = 63
MaxLBABlocks = MaxLBACylinders * MaxLBAHeads * MaxLBASectors

BlockSize = 512
MB = 1024 * 1024

# Setup PATH to look in the sbins.
env["PATH"] += ":/sbin:/usr/sbin"

# Whether to print debug output.
debug = False

# Figure out cylinders, heads and sectors from a size in blocks.
def chsFromSize(sizeInBlocks):
    if sizeInBlocks >= MaxLBABlocks:
        sizeInMBs = (sizeInBlocks * BlockSize) / MB
        print("%d MB is too big for LBA, truncating file." % sizeInMBs)
        return (MaxLBACylinders, MaxLBAHeads, MaxLBASectors)

    sectors = sizeInBlocks
    if sizeInBlocks > 63:
        sectors = 63

    headSize = sizeInBlocks / sectors
    heads = 16
    if headSize < 16:
        heads = sizeInBlocks

    cylinders = sizeInBlocks / (sectors * heads)

    return (cylinders, heads, sectors)


# Figure out if we should use sudo.
def needSudo():
    if not hasattr(needSudo, "notRoot"):
        needSudo.notRoot = os.geteuid() != 0
        if needSudo.notRoot:
            print("You are not root. Using sudo.")
    return needSudo.notRoot


# Run an external command.
def runCommand(command, inputVal=""):
    print("%>", " ".join(command))
    proc = Popen(command, stdin=PIPE)
    proc.communicate(inputVal.encode())
    return proc.returncode


# Run an external command and capture its output. This is intended to be
# used with non-interactive commands where the output is for internal use.
def getOutput(command, inputVal=""):
    global debug
    if debug:
        print("%>", " ".join(command))
    proc = Popen(command, stderr=STDOUT, stdin=PIPE, stdout=PIPE)
    (out, err) = proc.communicate(inputVal)
    return (out.decode(), proc.returncode)


# Run a command as root, using sudo if necessary.
def runPriv(command, inputVal=""):
    realCommand = command
    if needSudo():
        realCommand = [findProg("sudo")] + command
    return runCommand(realCommand, inputVal)


def privOutput(command, inputVal=""):
    realCommand = command
    if needSudo():
        realCommand = [findProg("sudo")] + command
    return getOutput(realCommand, inputVal)


# Find the path to a program.
def findProg(program, cleanupDev=None):
    (out, returncode) = getOutput(["which", program])
    if returncode != 0:
        if cleanupDev:
            cleanupDev.destroy()
        exit(f"Unable to find program {program}, check your PATH variable.")
    return out.strip()


class LoopbackDevice(object):
    def __init__(self, devFile=None):
        self.devFile = devFile

    def __str__(self):
        return str(self.devFile)

    def setup(self, fileName, offset=False):
        assert not self.devFile
        (out, returncode) = privOutput([findProg("losetup"), "-f"])
        if returncode != 0:
            print(out)
            return returncode
        self.devFile = out.strip()
        command = [findProg("losetup"), self.devFile, fileName]
        if offset:
            off = findPartOffset(self.devFile, fileName, 0)
            command = command[:1] + ["-o", "%d" % off] + command[1:]
        return runPriv(command)

    def destroy(self):
        assert self.devFile
        returncode = runPriv([findProg("losetup"), "-d", self.devFile])
        self.devFile = None
        return returncode


def findPartOffset(devFile, fileName, partition):
    # Attach a loopback device to the file so we can use sfdisk on it.
    dev = LoopbackDevice()
    dev.setup(fileName)
    # Dump the partition information.
    command = [findProg("sfdisk"), "-d", dev.devFile]
    (out, returncode) = privOutput(command)
    if returncode != 0:
        print(out)
        exit(returncode)

    # Parse each line of the sfdisk output looking for the first
    # partition description.
    SFDISK_PARTITION_INFO_RE = re.compile(
        r"^\s*"  # Start of line
        r"(?P<name>\S+)"  # Name
        r"\s*:\s*"  # Separator
        r"start=\s*(?P<start>\d+),\s*"  # Partition start record
        r"size=\s*(?P<size>\d+),\s*"  # Partition size record
        r"type=(?P<type>\d+)"  # Partition type record
        r"\s*$"  # End of line
    )
    lines = out.splitlines()
    for line in lines:
        match = SFDISK_PARTITION_INFO_RE.match(line)
        if match:
            sectors = int(match.group("start"))
            break
    else:
        # No partition description was found
        print("No partition description was found in sfdisk output:")
        print("\n".join(f"  {line.rstrip()}" for line in lines))
        print("Could not determine size of first partition.")
        exit(1)

    # Free the loopback device and return an answer.
    dev.destroy()
    return sectors * BlockSize


def mountPointToDev(mountPoint):
    (mountTable, returncode) = getOutput([findProg("mount")])
    if returncode != 0:
        print(mountTable)
        exit(returncode)
    mountTable = mountTable.splitlines()
    for line in mountTable:
        chunks = line.split()
        try:
            if os.path.samefile(chunks[2], mountPoint):
                return LoopbackDevice(chunks[0])
        except OSError:
            continue
    return None


# Commands for the gem5img.py script
commands = {}
commandOrder = []


class Command(object):
    def addArgument(self, *args, **kargs):
        self.parser.add_argument(*args, **kargs)

    def __init__(self, name, description, posArgs):
        self.name = name
        self.description = description
        self.func = None
        self.posArgs = posArgs
        commands[self.name] = self
        commandOrder.append(self.name)
        usage = "%(prog)s [options]"
        posUsage = ""
        for posArg in posArgs:
            (argName, argDesc) = posArg
            usage += f" {argName}"
            posUsage += "\n  %s: %s" % posArg
        usage += posUsage
        self.parser = ArgumentParser(usage=usage, description=description)
        self.addArgument(
            "-d",
            "--debug",
            dest="debug",
            action="store_true",
            help="Verbose output.",
        )
        self.addArgument("pos", nargs="*")

    def parseArgs(self, argv):
        self.options = self.parser.parse_args(argv[2:])
        self.args = self.options.pos
        if len(self.args) != len(self.posArgs):
            self.parser.error("Incorrect number of arguments")
        global debug
        if self.options.debug:
            debug = True

    def runCom(self):
        if not self.func:
            exit(f"Unimplemented command {self.name}!")
        self.func(self.options, self.args)


# A command which prepares an image with an partition table and an empty file
# system.
initCom = Command(
    "init",
    "Create an image with an empty file system.",
    [("file", "Name of the image file."), ("mb", "Size of the file in MB.")],
)
initCom.addArgument(
    "-t",
    "--type",
    dest="fstype",
    action="store",
    default="ext2",
    help="Type of file system to use. Appended to mkfs.",
)

# A command to mount the first partition in the image.
mountCom = Command(
    "mount",
    "Mount the first partition in the disk image.",
    [
        ("file", "Name of the image file."),
        ("mount point", "Where to mount the image."),
    ],
)


def mountComFunc(options, args):
    (path, mountPoint) = args
    if not os.path.isdir(mountPoint):
        print(f"Mount point {mountPoint} is not a directory.")

    dev = LoopbackDevice()
    if dev.setup(path, offset=True) != 0:
        exit(1)

    if runPriv([findProg("mount"), str(dev), mountPoint]) != 0:
        dev.destroy()
        exit(1)


mountCom.func = mountComFunc

# A command to unmount the first partition in the image.
umountCom = Command(
    "umount",
    "Unmount the disk image mounted at mount_point.",
    [("mount_point", "What mount point to unmount.")],
)


def umountComFunc(options, args):
    (mountPoint,) = args
    if not os.path.isdir(mountPoint):
        print(f"Mount point {mountPoint} is not a directory.")
        exit(1)

    dev = mountPointToDev(mountPoint)
    if not dev:
        print(f"Unable to find mount information for {mountPoint}.")

    # Unmount the loopback device.
    if runPriv([findProg("umount"), mountPoint]) != 0:
        exit(1)

    # Destroy the loopback device.
    dev.destroy()


umountCom.func = umountComFunc


# A command to create an empty file to hold the image.
newCom = Command(
    "new",
    'File creation part of "init".',
    [("file", "Name of the image file."), ("mb", "Size of the file in MB.")],
)


def newImage(file, mb):
    (cylinders, heads, sectors) = chsFromSize((mb * MB) / BlockSize)
    size = cylinders * heads * sectors * BlockSize

    # We lseek to the end of the file and only write one byte there. This
    # leaves a "hole" which many file systems are smart enough not to actually
    # store to disk and which is defined to read as zero.
    fd = os.open(file, os.O_WRONLY | os.O_CREAT)
    os.lseek(fd, size - 1, os.SEEK_SET)
    os.write(fd, b"\0")


def newComFunc(options, args):
    (file, mb) = args
    mb = int(mb)
    newImage(file, mb)


newCom.func = newComFunc

# A command to partition the image file like a raw disk device.
partitionCom = Command(
    "partition",
    'Partition part of "init".',
    [("file", "Name of the image file.")],
)


def partition(dev, cylinders, heads, sectors):
    # Use sfdisk to partition the device
    # The specified options are intended to work with both new and old
    # versions of sfdisk (see https://askubuntu.com/a/819614)
    comStr = ";"
    return runPriv(
        [findProg("sfdisk"), "--no-reread", "-u", "S", "-L", str(dev)],
        inputVal=comStr,
    )


def partitionComFunc(options, args):
    (path,) = args

    dev = LoopbackDevice()
    if dev.setup(path) != 0:
        exit(1)

    # Figure out the dimensions of the file.
    size = os.path.getsize(path)
    if partition(dev, *chsFromSize(size / BlockSize)) != 0:
        dev.destroy()
        exit(1)

    dev.destroy()


partitionCom.func = partitionComFunc

# A command to format the first partition in the image.
formatCom = Command(
    "format",
    'Formatting part of "init".',
    [("file", "Name of the image file.")],
)
formatCom.addArgument(
    "-t",
    "--type",
    dest="fstype",
    action="store",
    default="ext2",
    help="Type of file system to use. Appended to mkfs.",
)


def formatImage(dev, fsType):
    return runPriv([findProg(f"mkfs.{fsType}", dev), str(dev)])


def formatComFunc(options, args):
    (path,) = args

    dev = LoopbackDevice()
    if dev.setup(path, offset=True) != 0:
        exit(1)

    # Format the device.
    if formatImage(dev, options.fstype) != 0:
        dev.destroy()
        exit(1)

    dev.destroy()


formatCom.func = formatComFunc


def initComFunc(options, args):
    (path, mb) = args
    mb = int(mb)
    newImage(path, mb)
    dev = LoopbackDevice()
    if dev.setup(path) != 0:
        exit(1)
    size = os.path.getsize(path)
    if partition(dev, *chsFromSize((mb * MB) / BlockSize)) != 0:
        dev.destroy()
        exit(1)
    dev.destroy()
    if dev.setup(path, offset=True) != 0:
        exit(1)
    if formatImage(dev, options.fstype) != 0:
        dev.destroy()
        exit(1)
    dev.destroy()


initCom.func = initComFunc


# Figure out what command was requested and execute it.
if len(argv) < 2 or argv[1] not in commands:
    print("Usage: %s [command] <command arguments>")
    print("where [command] is one of ")
    for name in commandOrder:
        command = commands[name]
        print(f"    {command.name}: {command.description}")
    print("Watch for orphaned loopback devices and delete them with")
    print("losetup -d. Mounted images will belong to root, so you may need")
    print("to use sudo to modify their contents.")
    exit(1)

command = commands[argv[1]]
command.parseArgs(argv)
command.runCom()
