lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.DEB.2.02.1606150806190.2231@localhost6.localdomain6>
Date:	Wed, 15 Jun 2016 08:06:33 +0200 (CEST)
From:	Julia Lawall <julia.lawall@...6.fr>
To:	"Luis R. Rodriguez" <mcgrof@...nel.org>
cc:	Julia.Lawall@...6.fr, Gilles.Muller@...6.fr, nicolas.palix@...g.fr,
	mmarek@...e.com, linux-kernel@...r.kernel.org,
	cocci@...teme.lip6.fr
Subject: Re: [PATCH 2/4] scripts: add reqs python library



On Tue, 14 Jun 2016, Luis R. Rodriguez wrote:

> This library can be used in other python scripts to require
> specific binary version requirements. It will be used first
> with coccinelle's python bindings to enable coccinelle SmPL
> files to specify version requirements per cocci file if it
> has any.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@...nel.org>
> ---
>  MAINTAINERS             |   1 +
>  scripts/lib/__init__.py |   1 +
>  scripts/lib/reqs.py     | 211 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 213 insertions(+)
>  create mode 100644 scripts/lib/__init__.py
>  create mode 100644 scripts/lib/reqs.py
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f83e19a2dd97..fdebbb513c1b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -6521,6 +6521,7 @@ F:	scripts/Makefile.*
>  F:	scripts/basic/
>  F:	scripts/mk*
>  F:	scripts/package/
> +F:	scripts/lib/
>  
>  KERNEL JANITORS
>  L:	kernel-janitors@...r.kernel.org
> diff --git a/scripts/lib/__init__.py b/scripts/lib/__init__.py
> new file mode 100644
> index 000000000000..1bb8bf6d7fd4
> --- /dev/null
> +++ b/scripts/lib/__init__.py
> @@ -0,0 +1 @@
> +# empty
> diff --git a/scripts/lib/reqs.py b/scripts/lib/reqs.py
> new file mode 100644
> index 000000000000..1325fd21a87a
> --- /dev/null
> +++ b/scripts/lib/reqs.py
> @@ -0,0 +1,211 @@
> +import subprocess, os, sys, re
> +"""
> +Often enough Python code can grow to depend on binaries
> +on a system, you may also require only specific versions
> +of these. This small library helps with this. It also has
> +helpers for packages which we know to handle already.
> +"""
> +
> +class ReqError(Exception):
> +    pass
> +class ExecutionError(ReqError):
> +    def __init__(self, errcode):
> +        self.error_code = errcode
> +
> +class Req:
> +    "To be used for verifying binay package dependencies on Python code"

binay -> binary

> +    def __init__(self):
> +        self.all_reqs_ok = True
> +        self.debug = False
> +    def enable_debug(self):
> +        self.debug = True
> +    def reqs_match(self):
> +        if self.all_reqs_ok:
> +            return True
> +        sys.stdout.write("You have unfulfilled binary requirements\n")
> +        return False
> +    def req_missing(self, program):
> +        self.all_reqs_ok = False
> +        sys.stdout.write("You need to have installed: %s\n" % program)
> +    def req_old_program(self, program, version_req):
> +        self.all_reqs_ok = False
> +        sys.stdout.write("You need to have installed: %s >= %s\n" % (program, version_req))
> +    def which(self, program):
> +        cmd = ['which', program]
> +        process = subprocess.Popen(cmd,
> +                                   stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
> +                                   close_fds=True, universal_newlines=True)
> +        stdout = process.communicate()[0]
> +        process.wait()
> +        if process.returncode != 0:
> +            raise ExecutionError(process.returncode)
> +        return stdout
> +    def req_exists(self, program):
> +        cmd = ['which', program]
> +        process = subprocess.Popen(cmd,
> +                                   stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
> +                                   close_fds=True, universal_newlines=True)
> +        stdout = process.communicate()[0]
> +        process.wait()
> +        if process.returncode == 0:
> +            return True
> +        return False
> +    def req_get_prog_version(self, program, version_query, version_pos):
> +        '''
> +        Suppose you have a binary that outputs:
> +        $ spatch --version
> +        spatch version 1.0.0-rc21 with Python support and with PCRE support
> +
> +        Every program veries what it wants you to query it for a version string,
> +        prog_version() is designed so that you pass what the program expects for
> +        its version query, and the position you expect the version string to be
> +        on using python list.
> +        '''
> +        cmd = [program, version_query]
> +        process = subprocess.Popen(cmd,
> +                                   stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
> +                                   close_fds=True, universal_newlines=True)
> +        stdout = process.communicate()[0]
> +        process.wait()
> +        if process.returncode != 0:
> +            raise ExecutionError(process.returncode)
> +        if self.debug:
> +            sys.stdout.write("Running '%s' got us this break down:\n%s\n" %
> +                             (
> +                             ' '.join(cmd),
> +                             "\n".join(map(str, [[i, x] for i, x in enumerate(stdout.split())])),
> +                             ))
> +            sys.stdout.write("You are using for version: %s\n" % stdout.split()[version_pos])
> +            sys.stdout.write("Specifically your idx, element: %s\n" % ([[i, x] for i, x in enumerate(stdout.split())][version_pos]))
> +        return stdout.split()[version_pos]
> +
> +    MAX_RC = 25
> +    def __compute_rel_weight(self, rel_specs):
> +        weight = 0
> +        extra = 0
> +        sublevel = 0
> +        relmod = 0
> +
> +        if self.debug:
> +            sys.stdout.write("VERSION       = %s\n" % rel_specs['VERSION'])
> +            sys.stdout.write("PATCHLEVEL    = %s\n" % rel_specs['PATCHLEVEL'])
> +            sys.stdout.write("SUBLEVEL      = %s\n" % rel_specs['SUBLEVEL'])
> +            sys.stdout.write("EXTRAVERSION  = %s\n" % rel_specs['EXTRAVERSION'])
> +            sys.stdout.write("RELMOD_UPDATE = %s\n" % rel_specs['RELMOD_UPDATE'])
> +
> +        if rel_specs['EXTRAVERSION'] != '':
> +            if ("." in rel_specs['EXTRAVERSION'] or
> +                    "rc" in rel_specs['EXTRAVERSION']):
> +                rc = rel_specs['EXTRAVERSION'].lstrip("-rc")
> +                if (rc == ""):
> +                    rc = 0
> +                else:
> +                    rc = int(rc) - (Req.MAX_RC + 1)
> +                extra = int(rc)
> +            else:
> +                extra = int(rel_specs['EXTRAVERSION']) + 10
> +
> +        if rel_specs['SUBLEVEL'] != '':
> +            sublevel = int(rel_specs['SUBLEVEL'].lstrip(".")) * 20
> +        else:
> +            sublevel = 5
> +
> +        if rel_specs['RELMOD_UPDATE'] != '':
> +            mod = rel_specs['RELMOD_UPDATE']
> +            if (mod == ""):
> +                mod = 0
> +            else:
> +                mod = int(mod)
> +            relmod = int(mod)
> +
> +        weight = (int(rel_specs['VERSION'])    << 32) + \
> +                 (int(rel_specs['PATCHLEVEL']) << 16) + \
> +                 (sublevel   		       << 8 ) + \
> +                 (extra * 60) + (relmod * 2)
> +
> +        return weight
> +    def req_get_rel_spec(self, rel):
> +        if "rc" in rel:
> +            m = re.match(r"v*(?P<VERSION>\d+)\.+"
> +                         "(?P<PATCHLEVEL>\d+)[.]*"
> +                         "(?P<SUBLEVEL>\d*)"
> +                         "(?P<EXTRAVERSION>[-rc]+\w*)\-*"
> +                         "(?P<RELMOD_UPDATE>\d*)[-]*",
> +                         rel)
> +        else:
> +            m = re.match(r"v*(?P<VERSION>\d+)\.+"
> +                         "(?P<PATCHLEVEL>\d+)[.]*"
> +                         "(?P<SUBLEVEL>\d*)[.]*"
> +                         "(?P<EXTRAVERSION>\w*)\-*"
> +                         "(?P<RELMOD_UPDATE>\d*)[-]*",
> +                         rel)
> +        if not m:
> +            return m
> +        rel_specs = m.groupdict()
> +        return rel_specs
> +    def compute_rel_weight(self, rel):
> +        rel_specs = self.req_get_rel_spec(rel)
> +        if not rel_specs:
> +            return 0
> +        return self.__compute_rel_weight(rel_specs)
> +    def linux_version_cmp(self, version_req, version):
> +        '''
> +        If the program follows the linux version style scheme you can
> +        use this to compare versions.
> +        '''
> +        weight_has = self.compute_rel_weight(version)
> +        weight_req = self.compute_rel_weight(version_req)
> +
> +        if self.debug:
> +            sys.stdout.write("You have program weight: %s\n" % weight_has)
> +            sys.stdout.write("Required program weight: %s\n" % weight_req)
> +
> +        if weight_has < weight_req:
> +            return -1
> +        return 0
> +    def require_version(self, program, version_query, version_req, version_pos, version_cmp):
> +        '''
> +        If you have a program version requirement you can specify it here,
> +        as for the other flags refer to prog_version.
> +        '''
> +        if not self.require(program):
> +            return False
> +        version = self.req_get_prog_version(program, version_query, version_pos)
> +        if self.debug:
> +            sys.stdout.write("Checking release specs and weight: for: %s\n" % program)
> +            sys.stdout.write("You have version: %s\n" % version)
> +            sys.stdout.write("Required version: %s\n" % version_req)
> +        if version_cmp(version_req, version) != 0:
> +            self.req_old_program(program, version_req)
> +            return False
> +        return True
> +    def require(self, program):
> +        if self.req_exists(program):
> +            return True
> +        self.req_missing(program)
> +        return False
> +    def require_hint(self, program, package_hint):
> +        if self.require(program):
> +            return True
> +        sys.stdout.write("Try installing the package: %s\n" % package_hint)
> +        return False
> +    def coccinelle(self, version):
> +        if self.require_version('spatch', '--version', version, 2, self.linux_version_cmp):
> +            return True
> +        sys.stdout.write("Try installing the package: coccinelle\n")
> +        sys.stdout.write("If that is too old go grab the code from source:\n\n")
> +        sys.stdout.write("git clone https://github.com/coccinelle/coccinelle.git\n\n")
> +        sys.stdout.write("To build you will need: ocaml ncurses-devel\n\n")
> +        sys.stdout.write("If on SUSE / OpenSUSE you will also need: ocaml-ocamldoc\n\n")
> +        return False
> +    def kup(self):
> +        if self.require('kup'):
> +            return True
> +        sys.stdout.write("Try installing the package: kup\n")
> +        sys.stdout.write("If your distribution lacks that go get from source:\n\n")
> +        sys.stdout.write("git clone git://git.kernel.org/pub/scm/utils/kup/kup.git\n\n")
> +        return False
> +    def make(self, version):
> +        return self.require_version('make', '--version', version, 2, self.linux_version_cmp)
> +    def gcc(self, version):
> +        return self.require_version('gcc', '--version', version, 3, self.linux_version_cmp)
> -- 
> 2.8.2
> 
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ