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