#!/usr/bin/python3
# Этот сценарий вызывается из системного юнита как сценарий обработки подключения/отключения накопителей.
import os
import sys
import re
import json


def usage():
    os.system('echo "Использование: ' + sys.argv[
        0] + ' {add|remove} device_name (например, sdb1)" "path_to_udev_rule" (например /etc/udev/rules.d/80-ubl_udevrules.rules)')
    sys.exit(1)


if len(sys.argv) != 4:
    usage()

ACTION = sys.argv[1]
DEVBASE = sys.argv[2]
UDEV_PATH = sys.argv[3]

udev_name = UDEV_PATH.split(".rules")[0].split("/")[-1].split("-")[-1]

DEVPATH_file = f"/usr/share/ubl-udevrules/devpathes/{udev_name}_{DEVBASE}"
with open(DEVPATH_file, "r") as file:
    buffer = file.readline()
    DEVPATH = buffer.strip()
    DEVPATH = os.popen(f"echo {DEVPATH} | "
                       f"sed 's/.*usb[[:digit:]]//' | sed 's/[a-z].*//'| sed 's/[0-9]-[0-9].//'").readline()


DEVICE = f"/dev/{DEVBASE}"

active_user = []
users = os.popen("who").readlines()
for u in users:
    k = u.split()
    if re.findall("\:\d", k[1]):
        active_user.append(k[0])

# Проверяем, не примонтировано ли уже устройство
MOUNT_POINT = os.popen("echo $(/bin/mount | /bin/grep " + DEVICE + " | /usr/bin/awk '{ print $3 }')").readlines()

#
def do_mount():
    """
    логика монтирования следующая:
    есть 3 списка - юзеры, группы, остальные
    1 идет проверка на наличие юзера в списке допустимых юзеров
    2 идет проверка юзера на наличие юзера в списке групп
    3 идет просто назначение прав остальным, если остальные не пустые
    в конечном итоге, если umask сформировался происходит монтирование, иначе break
    """

    global MOUNT_POINT
    if MOUNT_POINT[0] != "\n":
        os.system(f'echo "Предупреждение: {DEVICE} уже смонтировано в {MOUNT_POINT}" ')
        sys.exit(1)
    this_user = ""
    flag = False

    for user in active_user:
        string = os.popen(f"loginctl user-status {user}").readlines()
        # проверяем на активность владельца usb носителя
        for s in string:
            if "State: active" in s:  # проверка на наличие сессии пользователя
                flag = True
                this_user = user
                break

    UID = ""
    umask_u = "7"
    rwx_g = "7"
    rwx_any = "7"
    flag = False

    with open("/usr/share/ubl-udevrules/userlists/list-udev.json") as main_userlist_file:
        data = json.load(main_userlist_file)
        if UDEV_PATH in data.keys():
            with open(data[UDEV_PATH]) as userlist_file:
                vars = json.load(userlist_file)
                for var in vars.keys():
                    if this_user in var:
                        umask_u = vars[var]
                        UID = os.popen(f"id -u {this_user}").readlines()[0].strip()
                        flag = True
                        break
    other_flag = False
    group_flag = False
    if not flag:
        with open("/usr/share/ubl-udevrules/grouplists/list-udev.json") as main_grouplist_file:
            data = json.load(main_grouplist_file)
            if UDEV_PATH in data.keys():
                with open(data[UDEV_PATH]) as grouplist_file:
                    vars = json.load(grouplist_file)
                    groups = os.popen(f"groups {this_user}").readlines()
                    if groups:
                        groups = groups[0].split(":")[1].strip()
                        for var in vars.keys():
                            if var in groups:
                                group_flag = True
                                rwx_g = vars[var]
                                break
        with open("/usr/share/ubl-udevrules/otherlists/list-udev.json") as otherlist_file:
            data = json.load(otherlist_file)
            if UDEV_PATH in data.keys():
                with open(data[UDEV_PATH]) as otherlist_file:
                    vars = json.load(otherlist_file)
                    rwx_any = vars["others"]
                    other_flag = False if rwx_any == 7 else True
        if not group_flag and not other_flag:
            os.system(
                f'echo "Пользователь {this_user} не включен в список пользователей, имеющих доступ к монтированию."')
            os.system(f"echo 0 > '/sys/bus/usb/devices{DEVPATH.strip()}/authorized'")
            sys.exit(0)
        umask = f"{rwx_g}7{rwx_any}" if group_flag else f"{rwx_any}7{rwx_any}"
        UID = os.popen(f"id -u {this_user}").readlines()[0].strip()
    else:
        with open("/usr/share/ubl-udevrules/otherlists/list-udev.json") as main_otherlist_file:
            data = json.load(main_otherlist_file)
            if UDEV_PATH in data.keys():
                    with open(data[UDEV_PATH]) as otherlist_file:
                        vars = json.load(otherlist_file)
                        rwx_any = vars["others"]
                        UID = os.popen(f"id -u {this_user}").readlines()[0].strip()
        umask = f"{umask_u}7{rwx_any}"
    # Получаем информацию об устройстве : метка $ID_FS_LABEL, идентификатор $ID_FS_UUID, и тип файловой системы $ID_FS_TYPE
    flag = False
    other_flag = False
    group_flag = False
    vars = os.popen(f"echo $(/sbin/blkid -o udev {DEVICE})").readlines()[0]
    vars_ = vars.split(" ")
    ID_FS_TYPE = ID_FS_LABEL = ""
    for i in range(len(vars_)):
        if "ID_FS_TYPE=" in vars_[i]:
            ID_FS_TYPE = re.sub("ID_FS_TYPE=", "", vars_[i].strip())
        elif "ID_FS_LABEL=" in vars_[i]:
            ID_FS_LABEL = re.sub("ID_FS_LABEL=", "", vars_[i].strip())

    # Создаём точку монтирования:
    LABEL = ID_FS_LABEL
    if LABEL == "":
        LABEL = DEVBASE
    elif os.popen(f'/bin/grep -q " /media/{LABEL} " /etc/mtab').readlines():
        # Если точка монтирования уже существует изменяем имя:
        LABEL += f"-{DEVBASE}"

    MOUNT_POINT = f"/media/{LABEL}"
    os.system(f'echo "Точка монтирования: {MOUNT_POINT}"')
    os.system(f"/bin/mkdir -p {MOUNT_POINT}")

    # Глобальные опции монтирования
    OPTS = f"rw,relatime"

    # Специфические опции монтирования:
    if ID_FS_TYPE == "vfat":
        OPTS += f",uid={UID},umask={umask},shortname=mixed,utf8=1,flush"
    elif ID_FS_TYPE == "ntfs":
        OPTS += f",uid={UID},umask=0{umask},shortname=mixed,utf8=1,flush"
    else:
        OPTS += f",umask=0{umask}"
    os.system(f'echo umask={umask}')
    #
    if umask == "777":
        os.system(f"echo 0 > '/sys/bus/usb/devices{DEVPATH.strip()}/authorized'")
        sys.exit(0)

    os.system(f'echo "/bin/mount -o {OPTS} {DEVICE} {MOUNT_POINT}"')
    status = os.WEXITSTATUS(os.system(f"/bin/mount -o {OPTS} {DEVICE} {MOUNT_POINT}"))
    if status != 0:
        os.system(f"echo Ошибка монтирования {DEVICE} (статус = {status})")
        os.system(f"/bin/rmdir {MOUNT_POINT}")
        sys.exit(1)
    os.system(f'echo "**** Устройство {DEVICE} смонтировано в {MOUNT_POINT} ****"')


def do_unmount():
    if MOUNT_POINT == "":
        os.system(f'echo "Предупреждение: {DEVICE} не смонтировано"')
    else:
        os.system(f"/bin/umount -l {DEVICE}")
        os.system(f'echo "**** Отмонтировано {DEVICE}"')
    # Удаление пустых каталогов
    for fl in os.popen("ls /media/").readlines():
        os.system(f'echo "/media/{fl}"')
        if len(os.popen(f'/bin/grep -q " /media/{fl} " /etc/mtab').readlines()) == 0:
            os.system(f'echo "Удаление точки монтирования /media/{fl}"')
            os.system(f'/bin/rmdir /media/{fl}')


if "add" in ACTION:
    do_mount()
elif "remove" in ACTION:
    do_unmount()
else:
    usage()
