#!/usr/bin/python

# Python library with UBI management related functions

from subprocess import CalledProcessError
import lib_system
import lib_logger
import logging

logger = logging.getLogger()

def ubi_volume_exists(volume_name, partition='0'):
    '''
    Check if a UBI volume is present on the system
    @volume_name: UBI volume name
    @partition: UBI partition index
    '''
    try:
        lib_system.call_shell(["ubinfo","-d", partition, "-N", volume_name])
        return True
    except CalledProcessError as e:
        return False

def update_ubi_volume(ubi_device_node, image_file):
    '''
    Update an UBI volume with a given image
    Warning: sometime an ECC error can occurs. It is neither detected by ubiupdatevol nor by corrupted file
    @ubi_device_node: node of the device to update (e.g.: ubi0_6)
    @image_file: filename of image to use for update
    '''
    try:
        lib_system.call_shell(["ubiupdatevol","/dev/{}".format(ubi_device_node), image_file])
        (_, output) = lib_system.call_shell(["/bin/sh","-c", "cat /sys/class/ubi/{}/corrupted".format(ubi_device_node)])
        if output != "0":
            logger.error("Update of UBI volume {} with file {} has failed. UBI volume is in corrupted state. Output: \"{}\"".format(ubi_device_node, image_file,output))
            return False
    except CalledProcessError as e:
        logger.error("ubiupdatevol of device {} with image {} has failed: {}".format(ubi_device_node,image_file,e.output))
        return False
    return True

def is_volume_using_ubifs(volume_name):
    '''
    Check if the volume is a UBIFS filesystem.
    @volume_name: name of the UBI volume to test
    '''
    try:
        lib_system.call_shell(["/bin/sh","-c", "mkdir -p /tmp/appfs/ && mount -t ubifs ubi0:" + volume_name +" /tmp/appfs 2>&1 > /dev/null"])
        lib_system.call_shell(["/bin/sh","-c", "umount /tmp/appfs > /dev/null && rm -rf /tmp/appfs > /dev/null"])
        return True
    except CalledProcessError as e:
        return False

def get_device_node_from_volume_name(volume_name):
    '''
    Find the device node whose name is volume_name (e.g.: rootfs-0 gives ubi0_6)
    @volume_name: volume to search
    '''
    try:
        # Find folders with name file that contains the volume name and extract the device node name from the folder (e.g: "ubi0_6")
        (_, output) = lib_system.call_shell(["/bin/sh","-c", "grep -l -r {} /sys/class/ubi/ubi*_*/name | grep -o \"ubi[0-9]*_[0-9]*\"".format(volume_name)])
        return output
    except CalledProcessError as e:
        logger.error("Unable to found device node name for volume name {}".format(volume_name))
        raise



