-
-
Notifications
You must be signed in to change notification settings - Fork 13
failover to python-magic detection if vendored library not present #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,7 @@ | |
|
|
||
| import ctypes | ||
| import os | ||
| import warnings | ||
|
|
||
| from commoncode import command | ||
| from plugincode.location_provider import get_location | ||
|
|
@@ -79,18 +80,59 @@ | |
| TYPECODE_LIBMAGIC_DATABASE = 'typecode.libmagic.db' | ||
|
|
||
|
|
||
| def load_lib_failover(): | ||
| # loader from python-magic | ||
| libmagic = None | ||
| # Let's try to find magic or magic1 | ||
| dll = (ctypes.util.find_library('magic') | ||
| or ctypes.util.find_library('magic1') | ||
| or ctypes.util.find_library('cygmagic-1') | ||
| or ctypes.util.find_library('libmagic-1') | ||
| or ctypes.util.find_library('msys-magic-1') # for MSYS2 | ||
| ) | ||
| # necessary because find_library returns None if it doesn't find the library | ||
| if dll: | ||
| libmagic = ctypes.CDLL(dll) | ||
|
|
||
| if not libmagic or not libmagic._name: | ||
| windows_dlls = ['magic1.dll', 'cygmagic-1.dll', 'libmagic-1.dll', 'msys-magic-1.dll'] | ||
| platform_to_lib = {'darwin': ['/opt/local/lib/libmagic.dylib', | ||
| '/usr/local/lib/libmagic.dylib'] + | ||
| # Assumes there will only be one version installed | ||
| glob.glob('/usr/local/Cellar/libmagic/*/lib/libmagic.dylib'), # flake8:noqa | ||
| 'win32': windows_dlls, | ||
| 'cygwin': windows_dlls, | ||
| 'linux': ['libmagic.so.1'], | ||
| # fallback for some Linuxes (e.g. Alpine) where library search does not work # flake8:noqa | ||
| } | ||
| platform = 'linux' if sys.platform.startswith('linux') else sys.platform | ||
| for dll in platform_to_lib.get(platform, []): | ||
| try: | ||
| libmagic = ctypes.CDLL(dll) | ||
| break | ||
| except OSError: | ||
| pass | ||
|
|
||
| if not libmagic or not libmagic._name: | ||
| return None | ||
| return libmagic | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know if there could be a way to test/check the version of this libmagic? Because unless this is close enough to the one provided as a plugin, there could be some magic database inconsistencies.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do a check, but we don't really know what threshold we should really put there. How would you define close enough? We could have a TAINTED flag like linux does which could be put in the typecode dependent reports
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well in hindsight, let's leave it this way.... after all in https://github.com/nexB/scancode-plugins/blob/main/builtins/typecode_libmagic_system_provided/src/typecode_libmagic/__init__.py I do not even check for version |
||
|
|
||
| def load_lib(): | ||
| """ | ||
| Return the loaded libmagic shared library object from plugin-provided path. | ||
| """ | ||
| dll = get_location(TYPECODE_LIBMAGIC_DLL) | ||
| libdir = get_location(TYPECODE_LIBMAGIC_LIBDIR) | ||
| if not (dll and libdir) or not os.path.isfile(dll) or not os.path.isdir(libdir): | ||
| raise Exception( | ||
| 'CRITICAL: libmagic DLL and is magic database are not installed. ' | ||
| 'Unable to continue: you need to install a valid typecode-libmagic ' | ||
| 'plugin with a valid and proper libmagic and magic DB available.' | ||
| ) | ||
| ret = load_lib_failover() | ||
| if ret is None: | ||
| raise ImportError( | ||
| 'CRITICAL: libmagic DLL and is magic database are not installed. ' | ||
| 'Unable to continue: you need to install a valid typecode-libmagic ' | ||
| 'plugin with a valid and proper libmagic and magic DB available.' | ||
| ) | ||
| warnings.warn("System libmagic is used. Install typecode-libmagic for best consitency") | ||
| return ret | ||
| return command.load_shared_library(dll, libdir) | ||
|
|
||
|
|
||
|
|
@@ -164,6 +206,7 @@ def __init__(self, flags, magic_db_location=None): | |
| self.flags = flags | ||
| self.cookie = _magic_open(self.flags) | ||
| if not magic_db_location: | ||
| # if no plugin, None is returned, and libmagic will load the default db | ||
| magic_db_location = get_location(TYPECODE_LIBMAGIC_DATABASE) | ||
|
|
||
| # Note: this location must always be bytes on Python2 and 3, all OSes | ||
|
|
@@ -257,3 +300,9 @@ def check_error(result, func, args): # NOQA | |
| _magic_load.restype = ctypes.c_int | ||
| _magic_load.argtypes = [ctypes.c_void_p, ctypes.c_char_p] | ||
| _magic_load.errcheck = check_error | ||
|
|
||
| _magic_version = libmagic.magic_version | ||
| _magic_version.restype = ctypes.c_int | ||
| _magic_version.argtypes = [] | ||
|
|
||
| libmagic_version = _magic_version() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # | ||
| # Copyright (c) nexB Inc. and others. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Visit https://aboutcode.org and https://github.com/nexB/ for support and download. | ||
| # ScanCode is a trademark of nexB Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
|
|
||
| import os | ||
|
|
||
| from typecode.magic2 import libmagic_version | ||
|
|
||
|
|
||
| def test_load_lib(): | ||
| assert libmagic_version > 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's nice extra credits but not needed IMHO since Adam is already credited at the top for the whole file.