drm: implement syncobj and fence for VIRGL/VirtIO driver
Extract protocol-agnostic FenceTimeline from Intel to shared src/drivers/fence.rs — atomic-based fence tracking suitable for Intel, VIRGL, and AMD drivers. Extract protocol-agnostic SyncobjManager from Intel to shared src/drivers/syncobj.rs — syncobj create/destroy/signal/reset/ wait/query and sync_file fd export/import. Wire both into VirtioDriver: - Add FenceTimeline + SyncobjManager fields - Implement all 5 GpuDriver syncobj trait methods (create, destroy, wait, export_fd, import_fd) - Track fence seqnos in virgl_submit_3d (allocate before submit, signal after completion) Intel fence.rs and syncobj.rs converted to thin re-export modules pointing at shared sources — no behavioral change for Intel driver. This gives Mesa VIRGL userspace the standard DRM syncobj API for GPU/compositor synchronization.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# Python `file-magic` Log of Changes
|
||||
|
||||
## `0.4.1`
|
||||
|
||||
- Create threadlocal objects so that the `detect_from_*` methods work properly
|
||||
|
||||
|
||||
## `0.4.0`
|
||||
|
||||
- Sync with current version of file:
|
||||
* Retain python 2 compatibility, factoring out the conversion functions.
|
||||
* Avoid double encoding with python3
|
||||
* Restore python-2 compatibility.
|
||||
|
||||
|
||||
## `0.3.0`
|
||||
|
||||
- Fix `setup.py` so we can upload to PyPI
|
||||
- Add function `detect_from_filename`
|
||||
- Add function `detect_from_fobj`
|
||||
- Add function `detect_from_content`
|
||||
@@ -0,0 +1,25 @@
|
||||
Copyright (c) Ian F. Darwin 1986-1995.
|
||||
Software written by Ian F. Darwin and others;
|
||||
maintained 1995-present by Christos Zoulas and others.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice immediately at the beginning of the file, without modification,
|
||||
this list of conditions, and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
EXTRA_DIST = LICENSE CHANGELOG.md README.md example.py magic.py setup.py \
|
||||
tests.py file_magic/__init__.py
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
# Makefile.in generated by automake 1.16.5 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = python
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/visibility.m4 $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in README.md
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
pkgdatadir = @pkgdatadir@
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CSCOPE = @CSCOPE@
|
||||
CTAGS = @CTAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
ETAGS = @ETAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
FILECMD = @FILECMD@
|
||||
GREP = @GREP@
|
||||
HAVE_VISIBILITY = @HAVE_VISIBILITY@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MINGW = @MINGW@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
WARNINGS = @WARNINGS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
fsect = @fsect@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
EXTRA_DIST = LICENSE CHANGELOG.md README.md example.py magic.py setup.py \
|
||||
tests.py file_magic/__init__.py
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign python/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign python/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
tags TAGS:
|
||||
|
||||
ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||
cscopelist-am ctags-am distclean distclean-generic \
|
||||
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags-am uninstall uninstall-am
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,31 @@
|
||||
# `file-magic`: Python Bindings
|
||||
|
||||
This library is a Python ctypes interface to `libmagic`.
|
||||
|
||||
|
||||
## Installing
|
||||
|
||||
You can install `file-magic` either with:
|
||||
|
||||
python setup.py install
|
||||
# or
|
||||
easy_install .
|
||||
# or
|
||||
pip install file-magic
|
||||
|
||||
|
||||
## Using
|
||||
|
||||
import magic
|
||||
|
||||
detected = magic.detect_from_filename('magic.py')
|
||||
print 'Detected MIME type: {}'.format(detected.mime_type)
|
||||
print 'Detected encoding: {}'.format(detected.encoding)
|
||||
print 'Detected file type name: {}'.format(detected.name)
|
||||
|
||||
|
||||
## Developing/Contributing
|
||||
|
||||
To run the tests:
|
||||
|
||||
python setup.py test
|
||||
@@ -0,0 +1,17 @@
|
||||
#! /usr/bin/python
|
||||
|
||||
import magic
|
||||
|
||||
ms = magic.open(magic.NONE)
|
||||
ms.load()
|
||||
tp = ms.file("/bin/ls")
|
||||
print (tp)
|
||||
|
||||
f = open("/bin/ls", "rb")
|
||||
buf = f.read(4096)
|
||||
f.close()
|
||||
|
||||
tp = ms.buffer(buf)
|
||||
print (tp)
|
||||
|
||||
ms.close()
|
||||
@@ -0,0 +1 @@
|
||||
name = 'file_magic'
|
||||
@@ -0,0 +1,361 @@
|
||||
# coding: utf-8
|
||||
|
||||
'''
|
||||
Python bindings for libmagic
|
||||
'''
|
||||
|
||||
import ctypes
|
||||
import threading
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
from ctypes import *
|
||||
from ctypes.util import find_library
|
||||
|
||||
|
||||
def _init():
|
||||
"""
|
||||
Loads the shared library through ctypes and returns a library
|
||||
L{ctypes.CDLL} instance
|
||||
"""
|
||||
return ctypes.cdll.LoadLibrary(find_library('magic'))
|
||||
|
||||
_libraries = {}
|
||||
_libraries['magic'] = _init()
|
||||
|
||||
# Flag constants for open and setflags
|
||||
MAGIC_NONE = NONE = 0
|
||||
MAGIC_DEBUG = DEBUG = 1
|
||||
MAGIC_SYMLINK = SYMLINK = 2
|
||||
MAGIC_COMPRESS = COMPRESS = 4
|
||||
MAGIC_DEVICES = DEVICES = 8
|
||||
MAGIC_MIME_TYPE = MIME_TYPE = 16
|
||||
MAGIC_CONTINUE = CONTINUE = 32
|
||||
MAGIC_CHECK = CHECK = 64
|
||||
MAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128
|
||||
MAGIC_RAW = RAW = 256
|
||||
MAGIC_ERROR = ERROR = 512
|
||||
MAGIC_MIME_ENCODING = MIME_ENCODING = 1024
|
||||
MAGIC_MIME = MIME = 1040 # MIME_TYPE + MIME_ENCODING
|
||||
MAGIC_APPLE = APPLE = 2048
|
||||
|
||||
MAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096
|
||||
MAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192
|
||||
MAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384
|
||||
MAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768
|
||||
MAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536
|
||||
MAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072
|
||||
MAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144
|
||||
MAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576
|
||||
MAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152
|
||||
|
||||
MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
|
||||
|
||||
MAGIC_PARAM_INDIR_MAX = PARAM_INDIR_MAX = 0
|
||||
MAGIC_PARAM_NAME_MAX = PARAM_NAME_MAX = 1
|
||||
MAGIC_PARAM_ELF_PHNUM_MAX = PARAM_ELF_PHNUM_MAX = 2
|
||||
MAGIC_PARAM_ELF_SHNUM_MAX = PARAM_ELF_SHNUM_MAX = 3
|
||||
MAGIC_PARAM_ELF_NOTES_MAX = PARAM_ELF_NOTES_MAX = 4
|
||||
MAGIC_PARAM_REGEX_MAX = PARAM_REGEX_MAX = 5
|
||||
MAGIC_PARAM_BYTES_MAX = PARAM_BYTES_MAX = 6
|
||||
|
||||
FileMagic = namedtuple('FileMagic', ('mime_type', 'encoding', 'name'))
|
||||
|
||||
|
||||
class magic_set(Structure):
|
||||
pass
|
||||
magic_set._fields_ = []
|
||||
magic_t = POINTER(magic_set)
|
||||
|
||||
_open = _libraries['magic'].magic_open
|
||||
_open.restype = magic_t
|
||||
_open.argtypes = [c_int]
|
||||
|
||||
_close = _libraries['magic'].magic_close
|
||||
_close.restype = None
|
||||
_close.argtypes = [magic_t]
|
||||
|
||||
_file = _libraries['magic'].magic_file
|
||||
_file.restype = c_char_p
|
||||
_file.argtypes = [magic_t, c_char_p]
|
||||
|
||||
_descriptor = _libraries['magic'].magic_descriptor
|
||||
_descriptor.restype = c_char_p
|
||||
_descriptor.argtypes = [magic_t, c_int]
|
||||
|
||||
_buffer = _libraries['magic'].magic_buffer
|
||||
_buffer.restype = c_char_p
|
||||
_buffer.argtypes = [magic_t, c_void_p, c_size_t]
|
||||
|
||||
_error = _libraries['magic'].magic_error
|
||||
_error.restype = c_char_p
|
||||
_error.argtypes = [magic_t]
|
||||
|
||||
_setflags = _libraries['magic'].magic_setflags
|
||||
_setflags.restype = c_int
|
||||
_setflags.argtypes = [magic_t, c_int]
|
||||
|
||||
_load = _libraries['magic'].magic_load
|
||||
_load.restype = c_int
|
||||
_load.argtypes = [magic_t, c_char_p]
|
||||
|
||||
_compile = _libraries['magic'].magic_compile
|
||||
_compile.restype = c_int
|
||||
_compile.argtypes = [magic_t, c_char_p]
|
||||
|
||||
_check = _libraries['magic'].magic_check
|
||||
_check.restype = c_int
|
||||
_check.argtypes = [magic_t, c_char_p]
|
||||
|
||||
_list = _libraries['magic'].magic_list
|
||||
_list.restype = c_int
|
||||
_list.argtypes = [magic_t, c_char_p]
|
||||
|
||||
_errno = _libraries['magic'].magic_errno
|
||||
_errno.restype = c_int
|
||||
_errno.argtypes = [magic_t]
|
||||
|
||||
_getparam = _libraries['magic'].magic_getparam
|
||||
_getparam.restype = c_int
|
||||
_getparam.argtypes = [magic_t, c_int, c_void_p]
|
||||
|
||||
_setparam = _libraries['magic'].magic_setparam
|
||||
_setparam.restype = c_int
|
||||
_setparam.argtypes = [magic_t, c_int, c_void_p]
|
||||
|
||||
|
||||
class Magic(object):
|
||||
def __init__(self, ms):
|
||||
self._magic_t = ms
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes the magic database and deallocates any resources used.
|
||||
"""
|
||||
_close(self._magic_t)
|
||||
|
||||
@staticmethod
|
||||
def __tostr(s):
|
||||
if s is None:
|
||||
return None
|
||||
if isinstance(s, str):
|
||||
return s
|
||||
try: # keep Python 2 compatibility
|
||||
return str(s, 'utf-8')
|
||||
except TypeError:
|
||||
return str(s)
|
||||
|
||||
@staticmethod
|
||||
def __tobytes(b):
|
||||
if b is None:
|
||||
return None
|
||||
if isinstance(b, bytes):
|
||||
return b
|
||||
try: # keep Python 2 compatibility
|
||||
return bytes(b, 'utf-8')
|
||||
except TypeError:
|
||||
return bytes(b)
|
||||
|
||||
def file(self, filename):
|
||||
"""
|
||||
Returns a textual description of the contents of the argument passed
|
||||
as a filename or None if an error occurred and the MAGIC_ERROR flag
|
||||
is set. A call to errno() will return the numeric error code.
|
||||
"""
|
||||
return Magic.__tostr(_file(self._magic_t, Magic.__tobytes(filename)))
|
||||
|
||||
def descriptor(self, fd):
|
||||
"""
|
||||
Returns a textual description of the contents of the argument passed
|
||||
as a file descriptor or None if an error occurred and the MAGIC_ERROR
|
||||
flag is set. A call to errno() will return the numeric error code.
|
||||
"""
|
||||
return Magic.__tostr(_descriptor(self._magic_t, fd))
|
||||
|
||||
def buffer(self, buf):
|
||||
"""
|
||||
Returns a textual description of the contents of the argument passed
|
||||
as a buffer or None if an error occurred and the MAGIC_ERROR flag
|
||||
is set. A call to errno() will return the numeric error code.
|
||||
"""
|
||||
return Magic.__tostr(_buffer(self._magic_t, buf, len(buf)))
|
||||
|
||||
def error(self):
|
||||
"""
|
||||
Returns a textual explanation of the last error or None
|
||||
if there was no error.
|
||||
"""
|
||||
return Magic.__tostr(_error(self._magic_t))
|
||||
|
||||
def setflags(self, flags):
|
||||
"""
|
||||
Set flags on the magic object which determine how magic checking
|
||||
behaves; a bitwise OR of the flags described in libmagic(3), but
|
||||
without the MAGIC_ prefix.
|
||||
|
||||
Returns -1 on systems that don't support utime(2) or utimes(2)
|
||||
when PRESERVE_ATIME is set.
|
||||
"""
|
||||
return _setflags(self._magic_t, flags)
|
||||
|
||||
def load(self, filename=None):
|
||||
"""
|
||||
Must be called to load entries in the colon separated list of database
|
||||
files passed as argument or the default database file if no argument
|
||||
before any magic queries can be performed.
|
||||
|
||||
Returns 0 on success and -1 on failure.
|
||||
"""
|
||||
return _load(self._magic_t, Magic.__tobytes(filename))
|
||||
|
||||
def compile(self, dbs):
|
||||
"""
|
||||
Compile entries in the colon separated list of database files
|
||||
passed as argument or the default database file if no argument.
|
||||
The compiled files created are named from the basename(1) of each file
|
||||
argument with ".mgc" appended to it.
|
||||
|
||||
Returns 0 on success and -1 on failure.
|
||||
"""
|
||||
return _compile(self._magic_t, Magic.__tobytes(dbs))
|
||||
|
||||
def check(self, dbs):
|
||||
"""
|
||||
Check the validity of entries in the colon separated list of
|
||||
database files passed as argument or the default database file
|
||||
if no argument.
|
||||
|
||||
Returns 0 on success and -1 on failure.
|
||||
"""
|
||||
return _check(self._magic_t, Magic.__tobytes(dbs))
|
||||
|
||||
def list(self, dbs):
|
||||
"""
|
||||
Check the validity of entries in the colon separated list of
|
||||
database files passed as argument or the default database file
|
||||
if no argument.
|
||||
|
||||
Returns 0 on success and -1 on failure.
|
||||
"""
|
||||
return _list(self._magic_t, Magic.__tobytes(dbs))
|
||||
|
||||
def errno(self):
|
||||
"""
|
||||
Returns a numeric error code. If return value is 0, an internal
|
||||
magic error occurred. If return value is non-zero, the value is
|
||||
an OS error code. Use the errno module or os.strerror() can be used
|
||||
to provide detailed error information.
|
||||
"""
|
||||
return _errno(self._magic_t)
|
||||
|
||||
def getparam(self, param):
|
||||
"""
|
||||
Returns the param value if successful and -1 if the parameter
|
||||
was unknown.
|
||||
"""
|
||||
v = c_int()
|
||||
i = _getparam(self._magic_t, param, byref(v))
|
||||
if i == -1:
|
||||
return -1
|
||||
return v.value
|
||||
|
||||
def setparam(self, param, value):
|
||||
"""
|
||||
Returns 0 if successful and -1 if the parameter was unknown.
|
||||
"""
|
||||
v = c_int(value)
|
||||
return _setparam(self._magic_t, param, byref(v))
|
||||
|
||||
|
||||
def open(flags):
|
||||
"""
|
||||
Returns a magic object on success and None on failure.
|
||||
Flags argument as for setflags.
|
||||
"""
|
||||
magic_t = _open(flags)
|
||||
if magic_t is None:
|
||||
return None
|
||||
return Magic(magic_t)
|
||||
|
||||
|
||||
# Objects used by `detect_from_` functions
|
||||
class error(Exception):
|
||||
pass
|
||||
|
||||
class MagicDetect(object):
|
||||
def __init__(self):
|
||||
self.mime_magic = open(MAGIC_MIME)
|
||||
if self.mime_magic is None:
|
||||
raise error
|
||||
if self.mime_magic.load() == -1:
|
||||
self.mime_magic.close()
|
||||
self.mime_magic = None
|
||||
raise error
|
||||
self.none_magic = open(MAGIC_NONE)
|
||||
if self.none_magic is None:
|
||||
self.mime_magic.close()
|
||||
self.mime_magic = None
|
||||
raise error
|
||||
if self.none_magic.load() == -1:
|
||||
self.none_magic.close()
|
||||
self.none_magic = None
|
||||
self.mime_magic.close()
|
||||
self.mime_magic = None
|
||||
raise error
|
||||
|
||||
def __del__(self):
|
||||
if self.mime_magic is not None:
|
||||
self.mime_magic.close()
|
||||
if self.none_magic is not None:
|
||||
self.none_magic.close()
|
||||
|
||||
threadlocal = threading.local()
|
||||
|
||||
def _detect_make():
|
||||
v = getattr(threadlocal, "magic_instance", None)
|
||||
if v is None:
|
||||
v = MagicDetect()
|
||||
setattr(threadlocal, "magic_instance", v)
|
||||
return v
|
||||
|
||||
def _create_filemagic(mime_detected, type_detected):
|
||||
try:
|
||||
mime_type, mime_encoding = mime_detected.split('; ')
|
||||
except ValueError:
|
||||
raise ValueError(mime_detected)
|
||||
|
||||
return FileMagic(name=type_detected, mime_type=mime_type,
|
||||
encoding=mime_encoding.replace('charset=', ''))
|
||||
|
||||
|
||||
def detect_from_filename(filename):
|
||||
'''Detect mime type, encoding and file type from a filename
|
||||
|
||||
Returns a `FileMagic` namedtuple.
|
||||
'''
|
||||
x = _detect_make()
|
||||
return _create_filemagic(x.mime_magic.file(filename),
|
||||
x.none_magic.file(filename))
|
||||
|
||||
|
||||
def detect_from_fobj(fobj):
|
||||
'''Detect mime type, encoding and file type from file-like object
|
||||
|
||||
Returns a `FileMagic` namedtuple.
|
||||
'''
|
||||
|
||||
file_descriptor = fobj.fileno()
|
||||
x = _detect_make()
|
||||
return _create_filemagic(x.mime_magic.descriptor(file_descriptor),
|
||||
x.none_magic.descriptor(file_descriptor))
|
||||
|
||||
|
||||
def detect_from_content(byte_content):
|
||||
'''Detect mime type, encoding and file type from bytes
|
||||
|
||||
Returns a `FileMagic` namedtuple.
|
||||
'''
|
||||
|
||||
x = _detect_make()
|
||||
return _create_filemagic(x.mime_magic.buffer(byte_content),
|
||||
x.none_magic.buffer(byte_content))
|
||||
@@ -0,0 +1,27 @@
|
||||
# coding: utf-8
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
with open('README.md', 'r') as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
|
||||
setup(name='file-magic',
|
||||
version='0.4.0',
|
||||
author='Reuben Thomas, Álvaro Justen',
|
||||
author_email='rrt@sc3d.org, alvarojusten@gmail.com',
|
||||
url='https://github.com/file/file',
|
||||
license='BSD',
|
||||
description='(official) libmagic Python bindings',
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
py_modules=['magic'],
|
||||
test_suite='tests',
|
||||
classifiers = [
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Natural Language :: English',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
])
|
||||
@@ -0,0 +1,32 @@
|
||||
# coding: utf-8
|
||||
|
||||
import unittest
|
||||
|
||||
import magic
|
||||
|
||||
|
||||
class MagicTestCase(unittest.TestCase):
|
||||
|
||||
filename = 'magic.py'
|
||||
expected_mime_type = 'text/x-script.python'
|
||||
expected_encoding = 'us-ascii'
|
||||
expected_name = 'Python script, ASCII text executable'
|
||||
|
||||
def assert_result(self, result):
|
||||
self.assertEqual(result.mime_type, self.expected_mime_type)
|
||||
self.assertEqual(result.encoding, self.expected_encoding)
|
||||
self.assertEqual(result.name, self.expected_name)
|
||||
|
||||
def test_detect_from_filename(self):
|
||||
result = magic.detect_from_filename(self.filename)
|
||||
self.assert_result(result)
|
||||
|
||||
def test_detect_from_fobj(self):
|
||||
with open(self.filename, "rb") as fobj:
|
||||
result = magic.detect_from_fobj(fobj)
|
||||
self.assert_result(result)
|
||||
|
||||
def test_detect_from_content(self):
|
||||
with open(self.filename, "rb") as fobj:
|
||||
result = magic.detect_from_content(fobj.read(8192))
|
||||
self.assert_result(result)
|
||||
Reference in New Issue
Block a user