]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/file/python/magic.py
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / file / python / magic.py
1 #!/usr/bin/env python
2 '''
3 Python bindings for libmagic
4 '''
5
6 import ctypes
7
8 from ctypes import *
9 from ctypes.util import find_library
10
11
12 def _init():
13     """
14     Loads the shared library through ctypes and returns a library
15     L{ctypes.CDLL} instance
16     """
17     return ctypes.cdll.LoadLibrary(find_library('magic'))
18
19 _libraries = {}
20 _libraries['magic'] = _init()
21
22 # Flag constants for open and setflags
23 MAGIC_NONE = NONE = 0
24 MAGIC_DEBUG = DEBUG = 1
25 MAGIC_SYMLINK = SYMLINK = 2
26 MAGIC_COMPRESS = COMPRESS = 4
27 MAGIC_DEVICES = DEVICES = 8
28 MAGIC_MIME_TYPE = MIME_TYPE = 16
29 MAGIC_CONTINUE = CONTINUE = 32
30 MAGIC_CHECK = CHECK = 64
31 MAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128
32 MAGIC_RAW = RAW = 256
33 MAGIC_ERROR = ERROR = 512
34 MAGIC_MIME_ENCODING = MIME_ENCODING = 1024
35 MAGIC_MIME = MIME = 1040
36 MAGIC_APPLE = APPLE = 2048
37
38 MAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096
39 MAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192
40 MAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384
41 MAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768
42 MAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536
43 MAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072
44 MAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144
45 MAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576
46 MAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152
47
48 MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
49
50
51 class magic_set(Structure):
52     pass
53 magic_set._fields_ = []
54 magic_t = POINTER(magic_set)
55
56 _open = _libraries['magic'].magic_open
57 _open.restype = magic_t
58 _open.argtypes = [c_int]
59
60 _close = _libraries['magic'].magic_close
61 _close.restype = None
62 _close.argtypes = [magic_t]
63
64 _file = _libraries['magic'].magic_file
65 _file.restype = c_char_p
66 _file.argtypes = [magic_t, c_char_p]
67
68 _descriptor = _libraries['magic'].magic_descriptor
69 _descriptor.restype = c_char_p
70 _descriptor.argtypes = [magic_t, c_int]
71
72 _buffer = _libraries['magic'].magic_buffer
73 _buffer.restype = c_char_p
74 _buffer.argtypes = [magic_t, c_void_p, c_size_t]
75
76 _error = _libraries['magic'].magic_error
77 _error.restype = c_char_p
78 _error.argtypes = [magic_t]
79
80 _setflags = _libraries['magic'].magic_setflags
81 _setflags.restype = c_int
82 _setflags.argtypes = [magic_t, c_int]
83
84 _load = _libraries['magic'].magic_load
85 _load.restype = c_int
86 _load.argtypes = [magic_t, c_char_p]
87
88 _compile = _libraries['magic'].magic_compile
89 _compile.restype = c_int
90 _compile.argtypes = [magic_t, c_char_p]
91
92 _check = _libraries['magic'].magic_check
93 _check.restype = c_int
94 _check.argtypes = [magic_t, c_char_p]
95
96 _list = _libraries['magic'].magic_list
97 _list.restype = c_int
98 _list.argtypes = [magic_t, c_char_p]
99
100 _errno = _libraries['magic'].magic_errno
101 _errno.restype = c_int
102 _errno.argtypes = [magic_t]
103
104
105 class Magic(object):
106     def __init__(self, ms):
107         self._magic_t = ms
108
109     def close(self):
110         """
111         Closes the magic database and deallocates any resources used.
112         """
113         _close(self._magic_t)
114
115     def file(self, filename):
116         """
117         Returns a textual description of the contents of the argument passed
118         as a filename or None if an error occurred and the MAGIC_ERROR flag
119         is set.  A call to errno() will return the numeric error code.
120         """
121         try:  # attempt python3 approach first
122             if isinstance(filename, bytes):
123                 bi = filename
124             else:
125                 bi = bytes(filename, 'utf-8')
126             return str(_file(self._magic_t, bi), 'utf-8')
127         except:
128             return _file(self._magic_t, filename.encode('utf-8'))
129
130     def descriptor(self, fd):
131         """
132         Like the file method, but the argument is a file descriptor.
133         """
134         return _descriptor(self._magic_t, fd)
135
136     def buffer(self, buf):
137         """
138         Returns a textual description of the contents of the argument passed
139         as a buffer or None if an error occurred and the MAGIC_ERROR flag
140         is set. A call to errno() will return the numeric error code.
141         """
142         try:  # attempt python3 approach first
143             return str(_buffer(self._magic_t, buf, len(buf)), 'utf-8')
144         except:
145             return _buffer(self._magic_t, buf, len(buf))
146
147     def error(self):
148         """
149         Returns a textual explanation of the last error or None
150         if there was no error.
151         """
152         try:  # attempt python3 approach first
153             return str(_error(self._magic_t), 'utf-8')
154         except:
155             return _error(self._magic_t)
156
157     def setflags(self, flags):
158         """
159         Set flags on the magic object which determine how magic checking
160         behaves; a bitwise OR of the flags described in libmagic(3), but
161         without the MAGIC_ prefix.
162
163         Returns -1 on systems that don't support utime(2) or utimes(2)
164         when PRESERVE_ATIME is set.
165         """
166         return _setflags(self._magic_t, flags)
167
168     def load(self, filename=None):
169         """
170         Must be called to load entries in the colon separated list of database
171         files passed as argument or the default database file if no argument
172         before any magic queries can be performed.
173
174         Returns 0 on success and -1 on failure.
175         """
176         return _load(self._magic_t, filename)
177
178     def compile(self, dbs):
179         """
180         Compile entries in the colon separated list of database files
181         passed as argument or the default database file if no argument.
182         Returns 0 on success and -1 on failure.
183         The compiled files created are named from the basename(1) of each file
184         argument with ".mgc" appended to it.
185         """
186         return _compile(self._magic_t, dbs)
187
188     def check(self, dbs):
189         """
190         Check the validity of entries in the colon separated list of
191         database files passed as argument or the default database file
192         if no argument.
193         Returns 0 on success and -1 on failure.
194         """
195         return _check(self._magic_t, dbs)
196
197     def list(self, dbs):
198         """
199         Check the validity of entries in the colon separated list of
200         database files passed as argument or the default database file
201         if no argument.
202         Returns 0 on success and -1 on failure.
203         """
204         return _list(self._magic_t, dbs)
205
206     def errno(self):
207         """
208         Returns a numeric error code. If return value is 0, an internal
209         magic error occurred. If return value is non-zero, the value is
210         an OS error code. Use the errno module or os.strerror() can be used
211         to provide detailed error information.
212         """
213         return _errno(self._magic_t)
214
215
216 def open(flags):
217     """
218     Returns a magic object on success and None on failure.
219     Flags argument as for setflags.
220     """
221     return Magic(_open(flags))