import subprocess
import sys
import os
import shutil
import time

from engine.DiskLib import *
from engine.FileSystemLib import *
from engine.FileLib import *
from engine.NetLib import *

# Example usage:
#rsync("-a", "-v", "source/", "destination/")
def rsync(*args):
    RSYNC = subprocess.check_output(["which", "rsync"]).decode().strip()
    if sys.platform == "linux" and sys.maxsize <= 2**32 and RSYNC == "":
        RSYNC = "/opt/opengnsys/bin/rsync"
    subprocess.run([RSYNC] + list(args))

def ogCreateFileImage():
    SIZEREQUIRED = int(sys.argv[4])
    if SIZEREQUIRED < 300000:
        SIZEREQUIRED = 300000
    KERNELVERSION = ".".join([str(int(num)) for num in platform.release().split(".")])

    if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
        IMGDIR = ogGetParentPath(sys.argv[1], "/" + sys.argv[2])
        if sys.argv[3] == "img":
            IMGEXT = "img"
        else:
            IMGEXT = "img.diff"
        IMGFILE = f"{IMGDIR}/{os.path.basename('/' + sys.argv[2])}.{IMGEXT}"
        if not os.path.exists(IMGDIR):
            ogEcho("log session", f"      {MSG_HELP_ogMakeDir} \"{sys.argv[1]} {os.path.dirname('/' + sys.argv[2])}.\"")
            ogMakeDir(sys.argv[1], os.path.dirname('/' + sys.argv[2]))
            IMGDIR = ogGetParentPath(sys.argv[1], "/" + sys.argv[2])
        DIRMOUNT = f"/tmp/{ogGetMountImageDir(sys.argv[2], sys.argv[3])}"
        os.makedirs(DIRMOUNT, exist_ok=True)
        LOOPDEVICE = subprocess.run(["losetup", "-f"], capture_output=True, text=True).stdout.strip()

        if os.path.isfile(IMGFILE):
            if os.path.isfile(f"{IMGFILE}.ant"):
                if BACKUP == "true" or BACKUP == "TRUE":
                    ogEcho("log session", f"     {MSG_SCRIPTS_FILE_RENAME} \"{IMGFILE}\" ->  \"{IMGFILE}.ant\".")
                    shutil.copy2(IMGFILE, f"{IMGFILE}.ant")
                    os.rename(f"{IMGFILE}.torrent", f"{IMGFILE}.torrent.ant")
                    os.remove(f"{IMGFILE}.sum")
            IMGSIZE = os.path.getsize(IMGFILE)
            if IMGSIZE < SIZEREQUIRED:
                ogEcho("log session", f"      {MSG_SYNC_RESIZE}")
                print(f"      truncate --size=>{SIZEREQUIRED}k {IMGFILE}")
                subprocess.run(["truncate", f"--size={SIZEREQUIRED}k", IMGFILE], capture_output=True, text=True)
                if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
                    subprocess.run(["losetup", LOOPDEVICE, IMGFILE])
                    print(f"      resize2fs -f {LOOPDEVICE}")
                    subprocess.run(["resize2fs", "-f", LOOPDEVICE], capture_output=True, text=True)
                else:
                    print(f"      ogMountImage {sys.argv[1]} {sys.argv[2]} {sys.argv[3]}")
                    ogMountImage(sys.argv[1], sys.argv[2], sys.argv[3])
                    print(f"      btrfs filesystem resize max {DIRMOUNT}")
                    subprocess.run(["btrfs", "filesystem", "resize", "max", DIRMOUNT], capture_output=True, text=True)
        else:
            open(IMGFILE, "w").close()
            print(f"      truncate --size=>{SIZEREQUIRED}k {IMGFILE}")
            subprocess.run(["truncate", f"--size={SIZEREQUIRED}k", IMGFILE], capture_output=True, text=True)
            subprocess.run(["losetup", LOOPDEVICE, IMGFILE])
            if KERNELVERSION < "3.07":
                IMGFS = "EXT4"
            else:
                IMGFS = os.environ.get("IMGFS", "BTRFS")
            if IMGFS == "EXT4":
                print(f"      mkfs.ext4 -i 4096  -b 4096 -L {os.path.basename(sys.argv[2])} {LOOPDEVICE}")
                subprocess.run(["mkfs.ext4", "-i", "4096", "-b", "4096", "-L", os.path.basename(sys.argv[2]), LOOPDEVICE], capture_output=True, text=True)
            else:
                print(f"      mkfs.btrfs  -L {os.path.basename(sys.argv[2])} {LOOPDEVICE}")
                subprocess.run(["mkfs.btrfs", "-L", os.path.basename(sys.argv[2]), LOOPDEVICE], capture_output=True, text=True)
        ogMountImage(sys.argv[1], sys.argv[2], sys.argv[3])
        if not os.path.exists(IMGFILE + ".lock"):
            open(IMGFILE + ".lock", "w").write("mounted")
        if LOOPDEVICE:
            subprocess.run(["losetup", "-d", LOOPDEVICE], capture_output=True, text=True)
    else:
        REPOIP = ogGetRepoIp()
        print(f"      hose {REPOIP} 2009 --out sh -c \"echo -ne CREATE_IMAGE {sys.argv[2]} {sys.argv[3]} {SIZEREQUIRED} \"")
        subprocess.run(["hose", REPOIP, "2009", "--out", "sh", "-c", f"echo -ne CREATE_IMAGE \"{sys.argv[2]}\" {sys.argv[3]} {SIZEREQUIRED}\""], capture_output=True, text=True)

def ogCreateInfoImage():
    FUNCNAME = ogCreateInfoImage.__name__
    IMGTYPE = None
    IMGDIRAUX = None
    DIRMOUNT = None
    DESTRSYNC = None
    PASSWORD = None
    USERRSYNC = None
    ORIG = None
    FSTYPE = None
    PART = None
    DIREMPTY = None
    IMGLIST = None
    IMGINFO = None
    IMGACL = None
    KERNELVERSION = None

    if len(sys.argv) < 5 or (len(sys.argv) < 6 and sys.argv[3] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part [ REPO|CACHE ] [ base_image_name ] extension", f"base image -> {FUNCNAME} 1 2 img", f"diff image -> {FUNCNAME} 1 1 CACHE Windows7 diff")
        return

    if len(sys.argv) < 3:
        ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {FUNCNAME}  num_disk num_part [ REPO|CACHE ] [ base_image_name]  extension")
        return

    PART = ogDiskToDev(sys.argv[1], sys.argv[2])
    if not PART:
        return

    ORIG = ogMount(sys.argv[1], sys.argv[2])
    if not ORIG:
        return

    if sys.argv[3] == "img":
        IMGTYPE = "img"
    else:
        if not ogCheckStringInGroup(sys.argv[5], "img diff"):
            ogRaiseError(OG_ERR_FORMAT, MSG_SYNC_EXTENSION)
            return
        IMGTYPE = sys.argv[5]
        if IMGTYPE == "diff":
            IMGDIRAUX = ogGetMountImageDir(sys.argv[4], "img")
            if sys.argv[3] == "CACHE" or sys.argv[3] == "cache":
                DIRMOUNT = f"/tmp/{IMGDIRAUX}"
                DESTRSYNC = DIRMOUNT
            else:
                if not REPOIP:
                    REPOIP = ogGetRepoIp()
                DIRMOUNT = f"{OGIMG}/{IMGDIRAUX}"
                USERRSYNC = "opengnsys"
                PASSWORD = "--password-file=/scripts/passrsync"
                DESTRSYNC = f"{USERRSYNC}@{REPOIP}::ogimages/{IMGDIRAUX}"

    FSTYPE = ogGetFsType(sys.argv[1], sys.argv[2])

    DIREMPTY = "/tmp/empty$$"
    IMGLIST = "/tmp/ogimg.list"
    IMGINFO = "/tmp/ogimg.info"
    IMGACL = "/tmp/ogimg.acl"

    os.system(f"rm -f /tmp/ogimg.* 2>/dev/null")
    os.system(f"rm -f {ORIG}/ogimg.* 2>/dev/null")

    SIZEDATA = os.environ.get("SIZEDATA", "SIZEDATA")

    KERNELVERSION = ".".join([str(int(num)) for num in platform.release().split(".")])
    if KERNELVERSION < "3.07":
        IMGFS = "EXT4"
    else:
        IMGFS = os.environ.get("IMGFS", "BTRFS")
    with open(IMGINFO, "w") as f:
        f.write(f"#{IMGFS}:NO:{FSTYPE}:{SIZEDATA}\n")

    if IMGTYPE == "img":
        print(f"      rsync -aHAXWvn --delete {ORIG}/ {DIREMPTY} >> {IMGINFO}")
        subprocess.run(["rsync", "-aHAXWvn", "--delete", f"{ORIG}/", DIREMPTY], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        os.system(f"sed -i -e s/\"^sent.*.bytes\\/sec\"//g -e s/^total.*.speedup.*.$//g -e s/\"sending.*.list\"//g {IMGINFO}")
        os.system(f"sed -i '/^\\.\\//d' {IMGINFO}")
    else:
        print(f"      rsync -aHAXWvn --delete {ORIG}/ {DESTRSYNC} a {IMGLIST}")
        subprocess.run(["rsync", "-aHAXWvn", "--delete", f"{ORIG}/", DESTRSYNC], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        os.system(f"sed -i -e s/\"^sent.*.bytes\\/sec\"//g -e s/^total.*.speedup.*.$//g -e s/\"sending.*.list\"//g {IMGLIST}")
        os.system(f"sed -i '/^\\.\\//d' {IMGLIST}")

        with open(IMGINFO, "a") as f:
            subprocess.run(["grep", "-e", "\\->", "-e", "\\=>", IMGLIST], stdout=f)
            subprocess.run(["grep", "-e", "^deleting", IMGLIST], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode().replace("deleting ", "").split("\n")
            subprocess.run(["grep", "-v", "-e", "\\->", "-e", "\\=>", "-e", "^deleting", "-e", "^created", IMGLIST], stdout=f)

        os.system(f"rm -f {IMGLIST}")

        if subprocess.run(["grep", "-v", "-e", "^$", "-e", "^#", IMGINFO, "/tmp/ogimg.ln", "/tmp/ogimg.rm"], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode().count("\n") == 0:
            ogRaiseError(OG_ERR_NOTDIFFERENT, " ".join(sys.argv[1:]))
            return

    if FSTYPE == "NTFS":
        print(f"      ntfs-3g.secaudit -b {PART} /")
        subprocess.run(["ntfs-3g.secaudit", "-b", PART, "/"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def ogAclFilter():
    FUNCNAME = ogAclFilter.__name__
    IMGACL = "/tmp/ogimg.acl"
    IMGINFO = "/tmp/ogimg.info"
    FILES = "/tmp/files$$"
    ACLTMP = "/tmp/acl$$.tmp"
    ACLFILES = "/tmp/aclfiles$$"

    # Ayuda
    if len(sys.argv) == 2 and sys.argv[1] == "help":
        ogHelp(FUNCNAME, FUNCNAME)
        return

    # comprobamos que existan los archivos de origen. Si no salimos sin error.
    if not (os.path.isfile(IMGACL) and os.path.isfile(IMGINFO)):
        return

    with open(ACLTMP, "w") as f:
        with open(IMGINFO, "r") as info_file:
            for line in info_file:
                line = line.strip()
                if line.startswith("#") or line == "":
                    continue
                line_number = line.split(":")[0]
                acl_lines = []
                with open(ACLFILES, "r") as acl_file:
                    acl_lines = acl_file.readlines()
                end_line, start_line = None, None
                for i, acl_line in enumerate(acl_lines):
                    acl_line = acl_line.strip()
                    if acl_line == "File" or acl_line == "Directory":
                        if acl_lines[i-1].startswith(line_number):
                            start_line = i
                        if acl_lines[i+1].startswith(line_number):
                            end_line = i
                            break
                if start_line is not None and end_line is not None:
                    acl_lines = acl_lines[start_line+1:end_line]
                    f.writelines(acl_lines)
                    ogEcho("aclfilter", line)

    shutil.copy2(ACLTMP, IMGACL)
    os.remove(FILES)
    os.remove(ACLTMP)
    os.remove(ACLFILES)

def ogRestoreInfoImage():
    FUNCNAME = ogRestoreInfoImage.__name__
    DEST = None
    PART = None
    IMGACL = "ogimg.acl"
    IMGLN = "ogimg.ln"
    IMGINFO = "ogimg.info"

    # Ayuda o menos de 5 parametros y la imagen no es basica
    if len(sys.argv) < 3 or (len(sys.argv) < 4 and sys.argv[3] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part", f"base image -> {FUNCNAME} 1 2", f"diff image -> {FUNCNAME} 1 1")
        return

    PART = ogDiskToDev(sys.argv[1], sys.argv[2])
    if not PART:
        return

    DEST = ogMount(sys.argv[1], sys.argv[2])
    if not DEST:
        return

    # Copiamos informacion de la imagen a /tmp (para basicas)
    if os.path.isfile(f"{DEST}/{IMGINFO}"):
        shutil.copy2(f"{DEST}/ogimg.*", "/tmp")

    # Creamos o modificamos los enlaces.
    # La imagen diferencial tiene ogimg.ln
    # para la completa lo generamos con los enlaces que contengan /mnt/
    if not os.path.isfile(f"/tmp/{IMGLN}"):
        with open(f"/tmp/{IMGINFO}", "r") as info_file:
            for line in info_file:
                line = line.strip()
                if "->" in line or "=>" in line:
                    if "/mnt/" in line:
                        with open(f"/tmp/{IMGLN}", "a") as ln_file:
                            ln_file.write(line.split(">")[0] + "\n")

    if os.path.isfile(f"/tmp/{IMGLN}"):
        with open(f"/tmp/{IMGLN}", "r") as ln_file:
            for line in ln_file:
                line = line.strip()
                ORIGLN = line.split("> ")[1]
                if "/mnt/" in ORIGLN:
                    ORIGLN = f"{DEST}/{ORIGLN.replace('/mnt/*/', '')}"
                TYPELN = line.split(" ")[-1]
                DESTLN = line.split(" ")[0]

                if TYPELN == "-":
                    OPTLN = "-s"
                else:
                    OPTLN = ""

                os.chdir(f"{DEST}/{os.path.dirname(DESTLN)}")
                os.remove(os.path.basename(DESTLN))
                os.symlink(ORIGLN, os.path.basename(DESTLN))
                print(".", end="")
        print("")

    os.chdir("/")

def ogRestoreAclImage():
    PART = None
    IMGACL = "ogimg.acl"

    if len(sys.argv) < 3 or (len(sys.argv) < 4 and sys.argv[3] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} num_disk num_part", f"base image -> {FUNCNAME} 1 2", f"diff image -> {FUNCNAME} 1 1")
        return

    PART = ogDiskToDev(sys.argv[1], sys.argv[2])
    if not PART:
        return

    # Restauramos acl
    if ogGetFsType(sys.argv[1], sys.argv[2]) == "NTFS" and os.path.isfile(f"/tmp/{IMGACL}"):
        os.chdir("/")
        ogUnmount(sys.argv[1], sys.argv[2])
        print(f"      ntfs-3g.secaudit -se {PART} /tmp/{IMGACL}")
        subprocess.run(["ntfs-3g.secaudit", "-se", PART, f"/tmp/{IMGACL}"], capture_output=True, text=True)
        # Para evitar que de falso error
        print("")

def ogSyncCreate():
    ORIG = ogMount(sys.argv[1], sys.argv[2])
    DIRAUX = ogGetMountImageDir(sys.argv[4], sys.argv[5])
    DIRMOUNT = f"/tmp/{DIRAUX}"
    DESTRSYNC = None
    USERRSYNC = None
    PASSWORD = None
    OPTRSYNC = None
    RETVAL = None

    if sys.argv[3] == "CACHE" or sys.argv[3] == "cache":
        DESTRSYNC = DIRMOUNT
    else:
        if not REPOIP:
            REPOIP = ogGetRepoIp()
        PASSWORD = "--password-file=/scripts/passrsync"
        if ogrsyncz == "true":
            OPTRSYNC = "z "
        if ogrsyncw == "true":
            OPTRSYNC = f"W{OPTRSYNC}"
        USERRSYNC = "opengnsys"
        DESTRSYNC = f"{USERRSYNC}@{REPOIP}::ogimages/{DIRMOUNT}"

    print(f"      rsync -aHAX{OPTRSYNC} --progress --inplace --delete {ORIG}/ {DESTRSYNC}")
    subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--progress", "--inplace", "--delete", f"{ORIG}/", DESTRSYNC], stderr=subprocess.PIPE, shell=True)

    print(f"      rsync -aHAX{OPTRSYNC} --inplace /tmp/ogimg* {DESTRSYNC}")
    subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--inplace", "/tmp/ogimg*", DESTRSYNC], stderr=subprocess.PIPE, shell=True)

    return RETVAL

def ogSyncRestore():
    DIRMOUNT = ogGetMountImageDir(sys.argv[2], sys.argv[3])
    DESTRSYNC = ogGetMountPoint(sys.argv[4], sys.argv[5])

    # Borramos ficheros de informacion de restauraciones antiguas
    os.system(f"rm -rf {DESTRSYNC}/ogimg.*")
    os.system("rm -rf /tmp/ogimg.*")

    # Origen y destino de la sincronizacion y en REPO opciones rsync
    if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
        ORIG = f"/tmp/{DIRMOUNT}"
    else:
        REPOIP = ogGetRepoIp()
        PASSWORD = "--password-file=/scripts/passrsync"
        OPTRSYNC = ""
        if ogrsyncz == "true":
            OPTRSYNC += "z "
        if ogrsyncw == "true":
            OPTRSYNC += "W" + OPTRSYNC
        USERRSYNC = "opengnsys"
        ORIG = f"{USERRSYNC}@{REPOIP}::ogimages/{DIRMOUNT}"

    # Opciones rsync en cache y repo
    # Para la imagen basica, opcion de borrar archivos de la particion que no existen en la imagen
    if sys.argv[3] == "img" and ogrsyncdel != "false":
        OPTRSYNC += "--delete"

    # Nos traemos listado ficheros y bajamos la imagen
    ogEcho("log session", f"      {MSG_SYNC_RESTORE}")

    # Si la imagen es diferencial nos traemos los archivos de informacion de la imagen.
    if sys.argv[3] == "diff":
        # Lista de archivos a copiar:
        IMGINFO = "ogimg.info"
        FILESFROM = f"--files-from=/tmp/{IMGINFO}"

        print(f"      rsync -aHAX{OPTRSYNC} --progress {ORIG}/ogimg* /tmp")
        subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--progress", f"{ORIG}/ogimg*", "/tmp"])

        # Borramos linea de información de la imagen, sino busca un fichero con ese nombre
        os.system("sed -i '/^#/d' /tmp/{IMGINFO}")

        os.chdir(DESTRSYNC)
        # Diferencial: Borramos archivos sobrantes.
        ogEcho("log session", f"      {MSG_SYNC_DELETE}")
        os.system(f"sed -e s/^/\"/g -e s/$/\"/g \"/tmp/ogimg.rm\" 2>/dev/null | xargs rm -rf")

    print(f"      rsync -aHAX{OPTRSYNC} --progress {FILESFROM} {ORIG}/ {DESTRSYNC}")
    subprocess.run(["rsync", "-aHAX" + OPTRSYNC, "--progress", FILESROM, f"{ORIG}/", DESTRSYNC], stderr=subprocess.PIPE, shell=True)
    RETVAL = subprocess.PIPESTATUS[0]
    os.chdir("/")

def ogMountImage(repo_cache, image_name, extension=None):
    FUNCNAME = ogMountImage.__name__
    if repo_cache == "help":
        ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
        return

    if len(sys.argv) < 2:
        ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {FUNCNAME} [ REPO|CACHE ]  image_name [ extension ]")
        return

    if not extension or extension == "img":
        IMGEXT = "img"
    else:
        IMGEXT = "img.diff"

    DIRMOUNT = ogGetMountImageDir(image_name, IMGEXT.split(".")[1])

    if repo_cache == "REPO" or repo_cache == "repo":
        REPOIP = ogGetRepoIp()
        print(f"      hose {REPOIP} 2009 --out sh -c \"echo -ne MOUNT_IMAGE {image_name} {IMGEXT.split('.')[1]}\"")
        return f"{OGIMG}/{DIRMOUNT}"
    else:
        # Check if already mounted
        if subprocess.run(["df"], capture_output=True, text=True).stdout.count(f"{DIRMOUNT}\n") > 0:
            return f"/tmp/{DIRMOUNT}"

        IMGFILE = ogGetPath(repo_cache, f"/{image_name}.{IMGEXT}")
        if not IMGFILE:
            ogRaiseError(OG_ERR_NOTFOUND, f"{repo_cache} {image_name}.{IMGEXT}")
            return

        os.makedirs(f"/tmp/{DIRMOUNT}", exist_ok=True)

        if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
            print(f"      mount -t ext4 -o loop {IMGFILE} /tmp/{DIRMOUNT}")
            subprocess.run(["mount", "-t", "ext4", "-o", "loop", IMGFILE, f"/tmp/{DIRMOUNT}"], capture_output=True, text=True)
        else:
            print(f"      mount -o compress=lzo {IMGFILE} /tmp/{DIRMOUNT}")
            subprocess.run(["mount", "-o", "compress=lzo", IMGFILE, f"/tmp/{DIRMOUNT}"], capture_output=True, text=True)

        if subprocess.run(["mount"], capture_output=True, text=True).stdout.count(f"/tmp/{DIRMOUNT}\n") == 0:
            ogRaiseError(OG_ERR_DONTMOUNT_IMAGE, f"{repo_cache} {image_name} {extension}")
            return

        return f"/tmp/{DIRMOUNT}"
    
def ogUnmountImage():
    FUNCNAME = ogUnmountImage.__name__
    IMGTYPE = None
    DIRMOUNT = None

    if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[2] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
        return

    if not sys.argv[3] or sys.argv[3] == "img":
        IMGTYPE = "img"
    else:
        IMGTYPE = sys.argv[3]

    if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
        DIRMOUNT = f"/tmp/{ogGetMountImageDir(sys.argv[2], IMGTYPE)}"
        subprocess.run(["umount", DIRMOUNT], capture_output=True, text=True)
        subprocess.run(["rmdir", DIRMOUNT], capture_output=True, text=True)
        if os.path.exists(f"{IMGFILE}.lock"):
            os.system(f"sed -i s/\"mounted\"//g {IMGFILE}.lock")
    else:
        if not REPOIP:
            REPOIP = ogGetRepoIp()
        print(f"      hose {REPOIP} 2009 --out sh -c \"echo -ne UMOUNT_IMAGE {sys.argv[2]} {IMGTYPE}\"")
        subprocess.run(["hose", REPOIP, "2009", "--out", "sh", "-c", f"echo -ne UMOUNT_IMAGE \"{sys.argv[2]}\" {IMGTYPE}\""], capture_output=True, text=True)

def ogGetMountImageDir(image_name, extension=None):
    FUNCNAME = ogGetMountImageDir.__name__
    if image_name == "help":
        ogHelp(FUNCNAME, f"{FUNCNAME} image_name [ extension ]", f"{FUNCNAME} Ubuntu12", f"{FUNCNAME} Windows7 diff")
        return

    if len(sys.argv) < 2:
        ogRaiseError(OG_ERR_FORMAT, f"{MSG_FORMAT}: {FUNCNAME} image_name [ extension ]")
        return

    DIRMOUNT = f"mount/{image_name}"
    if extension == "diff":
        DIRMOUNT = f"{DIRMOUNT}.diff"

    return DIRMOUNT

def ogWaitSyncImage():
    SIZE = int(sys.argv[5]) if len(sys.argv) >= 6 else 300000
    STATE = sys.argv[4]
    ogCheckStringInGroup(STATE, "mounted reduced") or return ogRaiseError(OG_ERR_FORMAT, "STATE = [ mounted | reduced ]")

    IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
    IMGEXT = "img" if sys.argv[3] == "img" else "img.diff"
    LOCKFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}.lock"

    if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
        DIRMOUNT = f"/tmp/{ogGetMountImageDir(sys.argv[2], sys.argv[3])}"
    else:
        DIRMOUNT = f"{OGIMG}/{ogGetMountImageDir(sys.argv[2], sys.argv[3])}"

    print(f"      {MSG_SYNC_SLEEP}: {DIRMOUNT}")
    print("      #")

    TIMEOUT = SIZE // CREATESPEED
    if TIMEOUT < 60:
        TIMEOUT = 60

    while True:
        if STATE == "mounted" and os.path.isfile(f"{DIRMOUNT}/ogimg.info"):
            ogEcho("log session", "")
            return 0

        TIMEAUX = SECONDS - TIME
        if TIMEAUX >= TIMEOUT:
            return ogRaiseError(OG_ERR_DONTMOUNT_IMAGE, f"{sys.argv[3]} {sys.argv[4]} {IMGEXT}: time_out.")

        print("#")
        time.sleep(5)

    print("")

def ogReduceImage():
    FUNCNAME = ogReduceImage.__name__
    IMGEXT = None
    DIRMOUNT = None
    AVAILABLE = None
    USED = None
    IMGDIR = None
    IMGFILE = None
    ENDSIZE = None
    LOOPDEVICE = None

    if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[3] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
        return

    if not sys.argv[3] or sys.argv[3] == "img":
        IMGEXT = "img"
    else:
        IMGEXT = sys.argv[3]

    IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
    IMGFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}"

    if sys.argv[1] == "CACHE" or sys.argv[1] == "cache":
        if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
            DIRMOUNT = ogMountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
            AVAILABLE = int(subprocess.run(["df", "-k"], capture_output=True, text=True).stdout.split(f"{DIRMOUNT}\n")[1].split()[3])
            if AVAILABLE < 200000:
                ogUnmountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
                os.system(f"echo \"reduced\" > \"{IMGFILE}.lock\"")
                return 0

            EXTSIZE = int(subprocess.run(["ls", "-l", "--block-size=1024", IMGFILE], capture_output=True, text=True).stdout.split()[4])
            INTSIZE = int(subprocess.run(["df", "-k"], capture_output=True, text=True).stdout.split(f"{DIRMOUNT}\n")[1].split()[1])
            EDGESIZE = EXTSIZE - INTSIZE
            ogUnmountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
            LOOPDEVICE = subprocess.run(["losetup", "-f"], capture_output=True, text=True).stdout.strip()
            os.system(f"losetup {LOOPDEVICE} \"{IMGFILE}\"")
            os.system(f"resize2fs -fpM {LOOPDEVICE}")
            ogMountImage(sys.argv[1], sys.argv[2], IMGEXT.split(".")[1])
            INTSIZE = int(subprocess.run(["df", "-k"], capture_output=True, text=True).stdout.split(f"{DIRMOUNT}\n")[1].split()[1])
            EXTSIZE = INTSIZE + EDGESIZE
            os.system(f"umount \"{DIRMOUNT}\"")
            if LOOPDEVICE:
                os.system(f"losetup -d {LOOPDEVICE}")
            os.system(f"truncate --size=\"{EXTSIZE}\"k \"{IMGFILE}\"")
        else:
            os.system(f"umount \"{DIRMOUNT}\"")
    
    os.system(f"echo \"reduced\" > \"{IMGFILE}.lock\"")
    os.system(f"rmdir \"{DIRMOUNT}\"")

def ogIsSyncImage():
    FUNCNAME = ogIsSyncImage.__name__
    IMGEXT = None
    IMGDIR = None
    IMGFILE = None

    if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[3] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
        return

    if not sys.argv[3] or sys.argv[3] == "img":
        IMGEXT = "img"
    else:
        IMGEXT = sys.argv[3]

    IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
    IMGFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}"

    if "BTRFS Filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower() or "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
        return 0
    else:
        return OG_ERR_DONTSYNC_IMAGE
    
def ogCheckSyncImage():
    FUNCNAME = ogCheckSyncImage.__name__
    IMGEXT = None
    IMGDIR = None
    IMGFILE = None
    DIRMOUNT = None
    ISMOUNT = None
    RETVAL = None

    if len(sys.argv) < 2 or (len(sys.argv) < 3 and sys.argv[3] != "img"):
        ogHelp(FUNCNAME, f"{FUNCNAME} [ REPO|CACHE ] image_name [ extension ]", f"{FUNCNAME} REPO Ubuntu12", f"{FUNCNAME} CACHE Windows7 diff")
        return

    if not sys.argv[3] or sys.argv[3] == "img":
        IMGEXT = "img"
    else:
        IMGEXT = sys.argv[3]

    IMGDIR = ogGetParentPath(sys.argv[1], f"/{sys.argv[2]}")
    IMGFILE = f"{IMGDIR}/{os.path.basename(f'/{sys.argv[2]}')}.{IMGEXT}"

    if "ext4 filesystem" in subprocess.run(["file", IMGFILE], capture_output=True, text=True).stdout.lower():
        DIRMOUNT = f"/tmp/ogCheckImage$$"
        os.makedirs(DIRMOUNT, exist_ok=True)
        subprocess.run(["mount", "-t", "ext4", "-o", "loop", IMGFILE, DIRMOUNT], capture_output=True, text=True)
        RETVAL = subprocess.PIPESTATUS[0]
    else:
        DIRMOUNT = f"/tmp/ogCheckImage$$"
        os.makedirs(DIRMOUNT, exist_ok=True)
        subprocess.run(["mount", "-o", "compress=lzo", IMGFILE, DIRMOUNT], capture_output=True, text=True)
        RETVAL = subprocess.PIPESTATUS[0]

    print("\n".join(os.listdir(DIRMOUNT)))

    subprocess.run(["umount", DIRMOUNT], capture_output=True, text=True)
    os.rmdir(DIRMOUNT)

    return RETVAL