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