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