示例#1
0
def wait_for_abortRequested(proc, monitor):
    monitor.closing.wait()
    log.info("torrserverd: exiting torrserverd daemon")
    try:
        if proc is not None:
            proc.terminate()
    except OSError:
        pass  # Process already exited, nothing to terminate
    log.info("torrserverd: torrserverd daemon exited")
示例#2
0
def system_information():
    build = xbmc.getInfoLabel("System.BuildVersion")
    log.info("System information: %(os)s_%(arch)s %(version)s" % PLATFORM)
    log.info("Kodi build version: %s" % build)
    log.info("OS type: %s" % platform.system())
    log.info("uname: %s" % repr(platform.uname()))
    return PLATFORM
示例#3
0
def dump_version():
    try:
        p = platform.platform()
    except:
        p = "Could not detect"

    log.info("""Python version: %s
    dist: %s
    linux_distribution: %s
    system: %s
    machine: %s
    platform: %s
    uname: %s
    version: %s
    mac_ver: %s
    """ % (sys.version.split('\n'), str(platform.dist()), linux_distribution(),
           platform.system(), platform.machine(), p, platform.uname(),
           platform.version(), platform.mac_ver()))
示例#4
0
def start_torrserverd(**kwargs):
    torrserver_dir, torrserver_binary = get_torrserver_binary()

    log.info("Binary dir: %s, item: %s " % (torrserver_dir, torrserver_binary))
    if torrserver_dir is False or torrserver_binary is False:
        return False

    SW_HIDE = 0
    STARTF_USESHOWWINDOW = 1
    ADDON_PORT = ADDON.getSetting("torrserver_port")
    database_path = getShortPath(
        os.path.join(
            xbmc.translatePath(ADDON.getAddonInfo("profile")).decode('utf-8')))
    args = [torrserver_binary, "-p", ADDON_PORT, "-d", database_path]
    kwargs["cwd"] = torrserver_dir

    if PLATFORM["os"] == "windows":
        args[0] = getShortPath(torrserver_binary)
        kwargs["cwd"] = getShortPath(torrserver_dir)
        si = subprocess.STARTUPINFO()
        si.dwFlags = STARTF_USESHOWWINDOW
        si.wShowWindow = SW_HIDE
        clear_fd_inherit_flags()
        kwargs["startupinfo"] = si
    else:
        env = os.environ.copy()
        env["LD_LIBRARY_PATH"] = "%s:%s" % (torrserver_dir,
                                            env.get("LD_LIBRARY_PATH", ""))
        kwargs["env"] = env
        kwargs["close_fds"] = True

    wait_counter = 1
    log.debug("Checking for visible")
    while xbmc.getCondVisibility(
            'Window.IsVisible(10140)') or xbmc.getCondVisibility(
                'Window.IsActive(10140)'):
        if wait_counter == 1:
            log.info(
                'Add-on settings currently opened, waiting before starting...')
        if wait_counter > 300:
            break
        time.sleep(1)
        wait_counter += 1
    log.info("torrserverd: start args: %s, kw: %s" % (args, kwargs))

    if hasSubprocess:
        return subprocess.Popen(args, **kwargs)
    else:
        command = ' '.join(args) + ' ' + ' '.join(kwargs)
        log.info("torrserverd: starting without subprocess: %s" % command)
        return os.system(command)
示例#5
0
def get_platform():
    build = xbmc.getInfoLabel("System.BuildVersion")
    kodi_version = int(build.split()[0][:2])
    ret = {
        "auto_arch": sys.maxsize > 2**32 and "64-bit" or "32-bit",
        "arch": sys.maxsize > 2**32 and "amd64" or "386",
        "os": "",
        "version": platform.release(),
        "kodi": kodi_version,
        "build": build,
        "fork": True,
    }
    if xbmc.getCondVisibility("system.platform.linux"):
        ret["os"] = "linux"
        if "aarch" in platform.machine().lower(
        ) or "arm64" in platform.machine().lower():
            dump_version()

            if xbmc.getCondVisibility("system.platform.linux.raspberrypi"):
                ret["arch"] = "arm7"
            elif ret["auto_arch"] == "32-bit":
                ret["arch"] = "arm7"
            elif ret["auto_arch"] == "64-bit":
                ret["arch"] = "arm64"
            else:
                ret["arch"] = "arm7"
        elif "arm" in platform.machine():
            dump_version()

            cpuarch = ""
            if "aarch" in platform.machine().lower(
            ) or "arm" in platform.machine().lower():
                info = cpuinfo()
                for proc in info.keys():
                    log.info("CPU: %s=%s" % (proc, info[proc]))
                    model = ""
                    if "Processor" in info[proc]:
                        model = info[proc]["Processor"].lower()
                    elif "model name" in info[proc]:
                        model = info[proc]["model name"].lower()

                    if model:
                        log.info("Exploring model: %s" % model)
                        if "aarch" in model or "arm64" in model or "v8l" in model:
                            cpuarch = "arm64"
                        elif "armv7" in model or "v7l" in model:
                            cpuarch = "arm7"
                        break

            if cpuarch:
                log.info("Using CPU info arch: %s" % cpuarch)
                ret["arch"] = cpuarch
            else:
                ret["arch"] = "arm6"
    elif xbmc.getCondVisibility("system.platform.windows"):
        ret["os"] = "windows"
        if platform.machine().endswith('64'):
            ret["arch"] = "amd64"
    return ret
示例#6
0
def get_torrserver_binary():
    binary = "TorrServer-" + "%(os)s-%(arch)s" % PLATFORM + (
        PLATFORM["os"] == "windows" and ".exe" or "")

    binary_dir = os.path.join(ADDON_PATH, "resources", "bin")
    if PLATFORM["os"] == "android":
        log.info("Detected binary folder: %s" % binary_dir)
        binary_dir_legacy = binary_dir.replace("/storage/emulated/0",
                                               "/storage/emulated/legacy")
        if os.path.exists(binary_dir_legacy):
            binary_dir = binary_dir_legacy
            log.info("Using changed binary folder for Android: %s" %
                     binary_dir)
        app_id = android_get_current_appid()
        xbmc_data_path = os.path.join("/data", "data", app_id)
        if not os.path.exists(xbmc_data_path):
            log.info("%s path does not exist, so using %s as xbmc_data_path" %
                     (xbmc_data_path,
                      xbmc.translatePath("special://masterprofile/")))
            xbmc_data_path = xbmc.translatePath("special://masterprofile/")

        dest_binary_dir = os.path.join(xbmc_data_path, "files", ADDON_ID,
                                       "bin")
    else:
        dest_binary_dir = os.path.join(
            xbmc.translatePath(ADDON.getAddonInfo("profile")).decode('utf-8'),
            "bin")

    binary_path = os.path.join(binary_dir, binary)
    dest_binary_path = os.path.join(dest_binary_dir, binary)

    log.info("Binary detection. Source: %s, Destination: %s" %
             (binary_path, dest_binary_path))

    if not os.path.exists(binary_path) or ADDON.getSetting(
            "update_binaries") == "true":
        version = ADDON_VERSION
        if not ADDON.getSetting("git_version") == "":
            version = ADDON.getSetting("git_version")
        download = dialog_yesno(
            "LOCALIZE[30000];;" + "TorrServer-%(os)s-%(arch)s" % PLATFORM +
            " v%s" % version, "LOCALIZE[30007]")
        system_information()
        if download:
            try:
                download_binary(
                    version, binary,
                    os.path.join(os.path.join(ADDON_PATH, "resources", "bin"),
                                 binary))
                notify(getLocalizedString(30001), time=3000)
            except Exception as e:
                import traceback
                map(log.error, traceback.format_exc().split("\n"))
                notify("Binary Not Found", time=2000)
                if dialog_yesno(
                        "Не удалось скачать файл. Тогда возможно попробуем открыть его из папки ??"
                ):
                    bFile = xbmcgui.Dialog().browseSingle(
                        1, 'Выберете файл сервера ' + binary, 'files', binary)
                    if bFile:
                        shutil.copy(bFile, binary_path)
                        notify(getLocalizedString(30001), time=3000)
                else:
                    return False, False
            else:
                ADDON.setSetting("update_binaries", "false")
                database_path = getShortPath(
                    os.path.join(
                        xbmc.translatePath(
                            ADDON.getAddonInfo("profile")).decode('utf-8')))
                if not os.path.exists(database_path):
                    os.mkdir(database_path)
        else:
            try:
                log.info(
                    "Source directory (%s):\n%s" %
                    (binary_dir, os.listdir(os.path.join(binary_dir, ".."))))
                log.info("Destination directory (%s):\n%s" %
                         (dest_binary_dir,
                          os.listdir(os.path.join(dest_binary_dir, ".."))))
            except Exception:
                pass
            return False, False

    if os.path.isdir(dest_binary_path):
        log.warning(
            "Destination path is a directory, expected previous binary file, removing..."
        )
        try:
            shutil.rmtree(dest_binary_path)
        except Exception as e:
            log.error("Unable to remove destination path for update: %s" % e)
            system_information()
            return False, False

    if not os.path.exists(dest_binary_path) or not os.path.exists(
            binary_path) or get_torrserverd_checksum(
                dest_binary_path) != get_torrserverd_checksum(
                    binary_path) or not filecmp.cmp(
                        dest_binary_path, binary_path, shallow=True):
        log.info("Updating torrserver daemon...")
        try:
            os.makedirs(dest_binary_dir)
        except OSError:
            pass
        try:
            shutil.rmtree(dest_binary_dir)
        except Exception as e:
            log.error("Unable to remove destination path for update: %s" % e)
            system_information()
            pass
        try:
            if not os.path.exists(dest_binary_dir):
                os.mkdir(dest_binary_dir)
            shutil.copy(binary_path, dest_binary_path)
        except Exception as e:
            log.error("Unable to copy to destination path for update: %s" % e)
            system_information()
            return False, False

    # Clean stale files in the directory, as this can cause headaches on
    # Android when they are unreachable
    dest_files = set(os.listdir(dest_binary_dir))
    orig_files = set(os.listdir(binary_dir))
    log.info("Deleting stale files %s" % (dest_files - orig_files))
    for file_ in (dest_files - orig_files):
        path = os.path.join(dest_binary_dir, file_)
        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.remove(path)

    log.info("Binary detection: [ Source: %s, Destination: %s ]" %
             (binary_path, dest_binary_path))
    return dest_binary_dir, ensure_exec_perms(dest_binary_path)
示例#7
0
def torrserverd_thread(monitor):
    crash_count = 0
    try:
        while not xbmc.abortRequested:
            xbmc.log("torrserverd: starting torrserverd", level=xbmc.LOGNOTICE)
            proc = None
            if hasSubprocess:
                proc = start_torrserverd(stdout=subprocess.PIPE,
                                         stderr=subprocess.STDOUT)
                if not proc:
                    break
            else:
                start_torrserverd()

            threading.Thread(target=wait_for_abortRequested,
                             args=[proc, monitor]).start()

            if not hasSubprocess:
                break

            if PLATFORM["os"] == "windows":
                while proc.poll() is None:
                    log.info(proc.stdout.readline())
            else:
                # Kodi hangs on some Android (sigh...) systems when doing a blocking
                # read. We count on the fact that torrserver daemon flushes its log
                # output on \n, creating a pretty clean output
                import fcntl
                import select
                fd = proc.stdout.fileno()
                fl = fcntl.fcntl(fd, fcntl.F_GETFL)
                fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
                while proc.poll() is None:
                    try:
                        to_read, _, _ = select.select([proc.stdout], [], [])
                        for ro in to_read:
                            line = ro.readline()
                            if line == "":  # write end is closed
                                break
                            log.info(line)
                    except IOError:
                        time.sleep(1)  # nothing to read, sleep

            if xbmc.abortRequested:
                break

            if proc.returncode == 0:
                notify(getLocalizedString(30001), time=3000)
            else:
                crash_count += 1
                notify(getLocalizedString(30002), time=3000)

            xbmc.executebuiltin("Dialog.Close(all, true)")
            system_information()
            time.sleep(5)
            if crash_count >= 3:
                notify(getLocalizedString(30003), time=3000)
                break

    except Exception as e:
        import traceback
        map(log.error, traceback.format_exc().split("\n"))
        notify("%s: %s" % (getLocalizedString(30004), repr(e).encode('utf-8')))
        raise