4 Python bindings for libmagic
9 from collections import namedtuple
12 from ctypes.util import find_library
17 Loads the shared library through ctypes and returns a library
18 L{ctypes.CDLL} instance
20 return ctypes.cdll.LoadLibrary(find_library('magic'))
23 _libraries['magic'] = _init()
25 # Flag constants for open and setflags
27 MAGIC_DEBUG = DEBUG = 1
28 MAGIC_SYMLINK = SYMLINK = 2
29 MAGIC_COMPRESS = COMPRESS = 4
30 MAGIC_DEVICES = DEVICES = 8
31 MAGIC_MIME_TYPE = MIME_TYPE = 16
32 MAGIC_CONTINUE = CONTINUE = 32
33 MAGIC_CHECK = CHECK = 64
34 MAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128
36 MAGIC_ERROR = ERROR = 512
37 MAGIC_MIME_ENCODING = MIME_ENCODING = 1024
38 MAGIC_MIME = MIME = 1040 # MIME_TYPE + MIME_ENCODING
39 MAGIC_APPLE = APPLE = 2048
41 MAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096
42 MAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192
43 MAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384
44 MAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768
45 MAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536
46 MAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072
47 MAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144
48 MAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576
49 MAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152
51 MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
53 FileMagic = namedtuple('FileMagic', ('mime_type', 'encoding', 'name'))
56 class magic_set(Structure):
58 magic_set._fields_ = []
59 magic_t = POINTER(magic_set)
61 _open = _libraries['magic'].magic_open
62 _open.restype = magic_t
63 _open.argtypes = [c_int]
65 _close = _libraries['magic'].magic_close
67 _close.argtypes = [magic_t]
69 _file = _libraries['magic'].magic_file
70 _file.restype = c_char_p
71 _file.argtypes = [magic_t, c_char_p]
73 _descriptor = _libraries['magic'].magic_descriptor
74 _descriptor.restype = c_char_p
75 _descriptor.argtypes = [magic_t, c_int]
77 _buffer = _libraries['magic'].magic_buffer
78 _buffer.restype = c_char_p
79 _buffer.argtypes = [magic_t, c_void_p, c_size_t]
81 _error = _libraries['magic'].magic_error
82 _error.restype = c_char_p
83 _error.argtypes = [magic_t]
85 _setflags = _libraries['magic'].magic_setflags
86 _setflags.restype = c_int
87 _setflags.argtypes = [magic_t, c_int]
89 _load = _libraries['magic'].magic_load
91 _load.argtypes = [magic_t, c_char_p]
93 _compile = _libraries['magic'].magic_compile
94 _compile.restype = c_int
95 _compile.argtypes = [magic_t, c_char_p]
97 _check = _libraries['magic'].magic_check
98 _check.restype = c_int
99 _check.argtypes = [magic_t, c_char_p]
101 _list = _libraries['magic'].magic_list
102 _list.restype = c_int
103 _list.argtypes = [magic_t, c_char_p]
105 _errno = _libraries['magic'].magic_errno
106 _errno.restype = c_int
107 _errno.argtypes = [magic_t]
111 def __init__(self, ms):
116 Closes the magic database and deallocates any resources used.
118 _close(self._magic_t)
120 def file(self, filename):
122 Returns a textual description of the contents of the argument passed
123 as a filename or None if an error occurred and the MAGIC_ERROR flag
124 is set. A call to errno() will return the numeric error code.
126 if isinstance(filename, bytes):
129 try: # keep Python 2 compatibility
130 bi = bytes(filename, 'utf-8')
133 r = _file(self._magic_t, bi)
134 if isinstance(r, str):
137 return str(r).encode('utf-8')
139 def descriptor(self, fd):
141 Like the file method, but the argument is a file descriptor.
143 return _descriptor(self._magic_t, fd)
145 def buffer(self, buf):
147 Returns a textual description of the contents of the argument passed
148 as a buffer or None if an error occurred and the MAGIC_ERROR flag
149 is set. A call to errno() will return the numeric error code.
151 r = _buffer(self._magic_t, buf, len(buf))
152 if isinstance(r, str):
155 return str(r).encode('utf-8')
159 Returns a textual explanation of the last error or None
160 if there was no error.
162 e = _error(self._magic_t)
163 if isinstance(e, str):
166 return str(e).encode('utf-8')
168 def setflags(self, flags):
170 Set flags on the magic object which determine how magic checking
171 behaves; a bitwise OR of the flags described in libmagic(3), but
172 without the MAGIC_ prefix.
174 Returns -1 on systems that don't support utime(2) or utimes(2)
175 when PRESERVE_ATIME is set.
177 return _setflags(self._magic_t, flags)
179 def load(self, filename=None):
181 Must be called to load entries in the colon separated list of database
182 files passed as argument or the default database file if no argument
183 before any magic queries can be performed.
185 Returns 0 on success and -1 on failure.
187 return _load(self._magic_t, filename)
189 def compile(self, dbs):
191 Compile entries in the colon separated list of database files
192 passed as argument or the default database file if no argument.
193 Returns 0 on success and -1 on failure.
194 The compiled files created are named from the basename(1) of each file
195 argument with ".mgc" appended to it.
197 return _compile(self._magic_t, dbs)
199 def check(self, dbs):
201 Check the validity of entries in the colon separated list of
202 database files passed as argument or the default database file
204 Returns 0 on success and -1 on failure.
206 return _check(self._magic_t, dbs)
210 Check the validity of entries in the colon separated list of
211 database files passed as argument or the default database file
213 Returns 0 on success and -1 on failure.
215 return _list(self._magic_t, dbs)
219 Returns a numeric error code. If return value is 0, an internal
220 magic error occurred. If return value is non-zero, the value is
221 an OS error code. Use the errno module or os.strerror() can be used
222 to provide detailed error information.
224 return _errno(self._magic_t)
229 Returns a magic object on success and None on failure.
230 Flags argument as for setflags.
232 return Magic(_open(flags))
235 # Objects used by `detect_from_` functions
236 mime_magic = Magic(_open(MAGIC_MIME))
238 none_magic = Magic(_open(MAGIC_NONE))
242 def _create_filemagic(mime_detected, type_detected):
243 mime_type, mime_encoding = mime_detected.split('; ')
245 return FileMagic(name=type_detected, mime_type=mime_type,
246 encoding=mime_encoding.replace('charset=', ''))
249 def detect_from_filename(filename):
250 '''Detect mime type, encoding and file type from a filename
252 Returns a `FileMagic` namedtuple.
255 return _create_filemagic(mime_magic.file(filename),
256 none_magic.file(filename))
259 def detect_from_fobj(fobj):
260 '''Detect mime type, encoding and file type from file-like object
262 Returns a `FileMagic` namedtuple.
265 file_descriptor = fobj.fileno()
266 return _create_filemagic(mime_magic.descriptor(file_descriptor),
267 none_magic.descriptor(file_descriptor))
270 def detect_from_content(byte_content):
271 '''Detect mime type, encoding and file type from bytes
273 Returns a `FileMagic` namedtuple.
276 return _create_filemagic(mime_magic.buffer(byte_content),
277 none_magic.buffer(byte_content))