setup.py 4.81 KB
#!/usr/bin/env python
from __future__ import print_function
import os
import sys
import tempfile
import subprocess
from distutils.core import setup, Command
from distutils.dir_util import remove_tree

MODULE_NAME = "binwalk"

# Python2/3 compliance
try:
    raw_input
except NameError:
    raw_input = input

# This is super hacky.
if "--yes" in sys.argv:
    sys.argv.pop(sys.argv.index("--yes"))
    IGNORE_WARNINGS = True
else:
    IGNORE_WARNINGS = False

# cd into the src directory, no matter where setup.py was invoked from
os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), "src"))

def which(command):
    # /usr/local/bin is usually the default install path, though it may not be in $PATH
    usr_local_bin = os.path.sep.join([os.path.sep, 'usr', 'local', 'bin', command])

    try:
        location = subprocess.Popen(["which", command], shell=False, stdout=subprocess.PIPE).communicate()[0].strip()
    except KeyboardInterrupt as e:
        raise e
    except Exception as e:
        pass

    if not location and os.path.exists(usr_local_bin):
        location = usr_local_bin

    return location

def warning(lines, terminate=True, prompt=True):
    WIDTH = 115

    if not IGNORE_WARNINGS:
        print("\n" + "*" * WIDTH)
        for line in lines:
            print(line)
        print("*" * WIDTH, "\n")

        if prompt:
            if raw_input('Continue installation anyway (Y/n)? ').lower().startswith('n'):
                terminate = True
            else:
                terminate = False

        if terminate:
            sys.exit(1)

def find_binwalk_module_paths():
    paths = []

    try:
        import binwalk
        paths = binwalk.__path__
    except KeyboardInterrupt as e:
        raise e
    except Exception:
        pass

    return paths

def remove_binwalk_module():
    for path in find_binwalk_module_paths():
        try:
            remove_tree(path)
        except OSError as e:
            pass
        
    script_path = which(MODULE_NAME)
    if script_path:
        try:
            print("removing '%s'" % script_path)
            os.unlink(script_path)
        except KeyboardInterrupt as e:
            pass
        except Exception as e:
            pass

class UninstallCommand(Command):
    description = "Uninstalls the Python module"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        remove_binwalk_module()

class CleanCommand(Command):
    description = "Clean Python build directories"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        try:
            remove_tree("build")
        except KeyboardInterrupt as e:
            raise e
        except Exception:
            pass

        try:
            remove_tree("dist")
        except KeyboardInterrupt as e:
            raise e
        except Exception:
            pass

# Check pre-requisite Python modules during a build
if "build" in sys.argv:
    print("checking pre-requisites")
    try:
        import pyqtgraph
        from pyqtgraph.Qt import QtCore, QtGui, QtOpenGL
    except ImportError as e:
        msg = ["Pre-requisite warning: " + str(e),
               "To take advantage of %s's graphing capabilities, please install this module." % MODULE_NAME,
        ]
   
        warning(msg, prompt=True)

if "install" in sys.argv:
    # If an older version of binwalk is currently installed, completely remove it to prevent conflicts
    existing_binwalk_modules = find_binwalk_module_paths()
    if existing_binwalk_modules and not os.path.exists(os.path.join(existing_binwalk_modules[0], "core")):
        remove_binwalk_module()

# Re-build the magic file during a build/install
if "install" in sys.argv or "build" in sys.argv:
    # Generate a new magic file from the files in the magic directory
    print("creating %s magic file" % MODULE_NAME)
    magic_files = os.listdir("magic")
    magic_files.sort()
    fd = open("%s/magic/%s" % (MODULE_NAME, MODULE_NAME), "wb")
    for magic in magic_files:
        fpath = os.path.join("magic", magic)
        if os.path.isfile(fpath):
            fd.write(open(fpath, "rb").read())
    fd.close()

# The data files to install along with the module
install_data_files = ["magic/*", "config/*", "plugins/*", "modules/*", "core/*"]

# Install the module, script, and support files
setup(name = MODULE_NAME,
      version = "2.0.0 beta",
      description = "Firmware analysis tool",
      author = "Craig Heffner",
      url = "https://github.com/devttys0/%s" % MODULE_NAME,

      requires = ["magic", "pyqtgraph"],
      packages = [MODULE_NAME],
      package_data = {MODULE_NAME : install_data_files},
      scripts = [os.path.join("scripts", MODULE_NAME)],

      cmdclass = {'clean' : CleanCommand, 'uninstall' : UninstallCommand}
)