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