1/* 2 Python wrappers for magic functions. 3 4 Copyright (C) Brett Funderburg, Deepfile Corp. Austin, TX, US 2003 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice immediately at the beginning of the file, without modification, 11 this list of conditions, and the following disclaimer. 12 2. Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 3. The name of the author may not be used to endorse or promote products 16 derived from this software without specific prior written permission. 17 18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 22 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 SUCH DAMAGE. 29*/ 30 31#include <Python.h> 32#include <magic.h> 33#include "py_magic.h" 34 35/* Exceptions raised by this module */ 36 37PyObject* magic_error_obj; 38 39/* Create a new magic_cookie_hnd object */ 40PyObject* new_magic_cookie_handle(magic_t cookie) 41{ 42 magic_cookie_hnd* mch; 43 44 mch = PyObject_New(magic_cookie_hnd, &magic_cookie_type); 45 46 mch->cookie = cookie; 47 48 return (PyObject*)mch; 49} 50 51static char _magic_open__doc__[] = 52"Returns a magic cookie on success and None on failure.\n"; 53static PyObject* py_magic_open(PyObject* self, PyObject* args) 54{ 55 int flags = 0; 56 magic_t cookie; 57 58 if(!PyArg_ParseTuple(args, "i", &flags)) 59 return NULL; 60 61 if(!(cookie = magic_open(flags))) { 62 PyErr_SetString(magic_error_obj, "failure initializing magic cookie"); 63 return NULL; 64 } 65 66 return new_magic_cookie_handle(cookie); 67} 68 69static char _magic_close__doc__[] = 70"Closes the magic database and deallocates any resources used.\n"; 71static PyObject* py_magic_close(PyObject* self, PyObject* args) 72{ 73 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 74 75 magic_close(hnd->cookie); 76 77 Py_INCREF(Py_None); 78 return Py_None; 79} 80 81static char _magic_error__doc__[] = 82"Returns a textual explanation of the last error or None \ 83 if there was no error.\n"; 84static PyObject* py_magic_error(PyObject* self, PyObject* args) 85{ 86 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 87 const char* message = NULL; 88 PyObject* result = Py_None; 89 90 message = magic_error(hnd->cookie); 91 92 if(message != NULL) 93 result = PyString_FromString(message); 94 else 95 Py_INCREF(Py_None); 96 97 return result; 98} 99 100static char _magic_errno__doc__[] = 101"Returns a numeric error code. If return value is 0, an internal \ 102 magic error occurred. If return value is non-zero, the value is \ 103 an OS error code. Use the errno module or os.strerror() can be used \ 104 to provide detailed error information.\n"; 105static PyObject* py_magic_errno(PyObject* self, PyObject* args) 106{ 107 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 108 return PyInt_FromLong(magic_errno(hnd->cookie)); 109} 110 111static char _magic_file__doc__[] = 112"Returns a textual description of the contents of the argument passed \ 113 as a filename or None if an error occurred and the MAGIC_ERROR flag \ 114 is set. A call to errno() will return the numeric error code.\n"; 115static PyObject* py_magic_file(PyObject* self, PyObject* args) 116{ 117 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 118 char* filename = NULL; 119 const char* message = NULL; 120 PyObject* result = Py_None; 121 122 if(!(PyArg_ParseTuple(args, "s", &filename))) 123 return NULL; 124 125 message = magic_file(hnd->cookie, filename); 126 127 if(message != NULL) 128 result = PyString_FromString(message); 129 else 130 Py_INCREF(Py_None); 131 132 return result; 133} 134 135static char _magic_buffer__doc__[] = 136"Returns a textual description of the contents of the argument passed \ 137 as a buffer or None if an error occurred and the MAGIC_ERROR flag \ 138 is set. A call to errno() will return the numeric error code.\n"; 139static PyObject* py_magic_buffer(PyObject* self, PyObject* args) 140{ 141 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 142 void* buffer = NULL; 143 int buffer_length = 0; 144 const char* message = NULL; 145 PyObject* result = Py_None; 146 147 if(!(PyArg_ParseTuple(args, "s#", (char**)&buffer, &buffer_length))) 148 return NULL; 149 150 message = magic_buffer(hnd->cookie, buffer, buffer_length); 151 152 if(message != NULL) 153 result = PyString_FromString(message); 154 else 155 Py_INCREF(Py_None); 156 157 return result; 158} 159 160static char _magic_setflags__doc__[] = 161"Set flags on the cookie object.\n \ 162 Returns -1 on systems that don't support utime(2) or utimes(2) \ 163 when MAGIC_PRESERVE_ATIME is set.\n"; 164static PyObject* py_magic_setflags(PyObject* self, PyObject* args) 165{ 166 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 167 int flags; 168 int result; 169 170 if(!(PyArg_ParseTuple(args, "i", &flags))) 171 return NULL; 172 173 result = magic_setflags(hnd->cookie, flags); 174 175 return PyInt_FromLong(result); 176} 177 178static char _magic_check__doc__[] = 179"Check the validity of entries in the colon separated list of \ 180 database files passed as argument or the default database file \ 181 if no argument.\n Returns 0 on success and -1 on failure.\n"; 182static PyObject* py_magic_check(PyObject* self, PyObject* args) 183{ 184 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 185 char* filename = NULL; 186 int result; 187 188 if(!(PyArg_ParseTuple(args, "|s", &filename))) 189 return NULL; 190 191 result = magic_check(hnd->cookie, filename); 192 193 return PyInt_FromLong(result); 194} 195 196static char _magic_compile__doc__[] = 197"Compile entries in the colon separated list of database files \ 198 passed as argument or the default database file if no argument.\n \ 199 Returns 0 on success and -1 on failure.\n \ 200 The compiled files created are named from the basename(1) of each file \ 201 argument with \".mgc\" appended to it.\n"; 202static PyObject* py_magic_compile(PyObject* self, PyObject* args) 203{ 204 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 205 char* filename = NULL; 206 int result; 207 208 if(!(PyArg_ParseTuple(args, "|s", &filename))) 209 return NULL; 210 211 result = magic_compile(hnd->cookie, filename); 212 213 return PyInt_FromLong(result); 214} 215 216static char _magic_load__doc__[] = 217"Must be called to load entries in the colon separated list of database files \ 218 passed as argument or the default database file if no argument before \ 219 any magic queries can be performed.\n \ 220 Returns 0 on success and -1 on failure.\n"; 221static PyObject* py_magic_load(PyObject* self, PyObject* args) 222{ 223 magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; 224 char* filename = NULL; 225 int result; 226 227 if(!(PyArg_ParseTuple(args, "|s", &filename))) 228 return NULL; 229 230 result = magic_load(hnd->cookie, filename); 231 232 return PyInt_FromLong(result); 233} 234 235/* object methods */ 236 237static PyMethodDef magic_cookie_hnd_methods[] = { 238 { "close", (PyCFunction)py_magic_close, 239 METH_NOARGS, _magic_close__doc__ }, 240 { "error", (PyCFunction)py_magic_error, 241 METH_NOARGS, _magic_error__doc__ }, 242 { "file", (PyCFunction)py_magic_file, 243 METH_VARARGS, _magic_file__doc__ }, 244 { "buffer", (PyCFunction)py_magic_buffer, 245 METH_VARARGS, _magic_buffer__doc__ }, 246 { "setflags", (PyCFunction)py_magic_setflags, 247 METH_VARARGS, _magic_setflags__doc__ }, 248 { "check", (PyCFunction)py_magic_check, 249 METH_VARARGS, _magic_check__doc__ }, 250 { "compile", (PyCFunction)py_magic_compile, 251 METH_VARARGS, _magic_compile__doc__ }, 252 { "load", (PyCFunction)py_magic_load, 253 METH_VARARGS, _magic_load__doc__ }, 254 { "errno", (PyCFunction)py_magic_errno, 255 METH_NOARGS, _magic_errno__doc__ }, 256 { NULL, NULL } 257}; 258 259/* module level methods */ 260 261static PyMethodDef magic_methods[] = { 262 { "open", (PyCFunction)py_magic_open, 263 METH_VARARGS, _magic_open__doc__ }, 264 { NULL, NULL } 265}; 266 267static void py_magic_dealloc(PyObject* self) 268{ 269 PyObject_Del(self); 270} 271 272static PyObject* py_magic_getattr(PyObject* self, char* attrname) 273{ 274 return Py_FindMethod(magic_cookie_hnd_methods, self, attrname); 275} 276 277PyTypeObject magic_cookie_type = { 278 PyObject_HEAD_INIT(NULL) 279 0, 280 "Magic cookie", 281 sizeof(magic_cookie_hnd), 282 0, 283 py_magic_dealloc, /* tp_dealloc */ 284 0, /* tp_print */ 285 py_magic_getattr, /* tp_getattr */ 286 0, /* tp_setattr */ 287 0, /* tp_compare */ 288 0, /* tp_repr */ 289 0, /* tp_as_number */ 290 0, /* tp_as_sequence */ 291 0, /* tp_as_mapping */ 292 0, /* tp_hash */ 293}; 294 295/* Initialize constants */ 296 297static struct const_vals { 298 const char* const name; 299 unsigned int value; 300} module_const_vals[] = { 301 { "MAGIC_NONE", MAGIC_NONE }, 302 { "MAGIC_DEBUG", MAGIC_DEBUG }, 303 { "MAGIC_SYMLINK", MAGIC_SYMLINK }, 304 { "MAGIC_COMPRESS", MAGIC_COMPRESS }, 305 { "MAGIC_DEVICES", MAGIC_DEVICES }, 306 { "MAGIC_MIME", MAGIC_MIME }, 307 { "MAGIC_CONTINUE", MAGIC_CONTINUE }, 308 { "MAGIC_CHECK", MAGIC_CHECK }, 309 { "MAGIC_PRESERVE_ATIME", MAGIC_PRESERVE_ATIME }, 310 { "MAGIC_ERROR", MAGIC_ERROR}, 311 { NULL } 312}; 313 314static void const_init(PyObject* dict) 315{ 316 struct const_vals* tmp; 317 PyObject *obj; 318 319 for(tmp = module_const_vals; tmp->name; ++tmp) { 320 obj = PyInt_FromLong(tmp->value); 321 PyDict_SetItemString(dict, tmp->name, obj); 322 Py_DECREF(obj); 323 } 324} 325 326/* 327 * Module initialization 328 */ 329 330void initmagic(void) 331{ 332 PyObject* module; 333 PyObject* dict; 334 335 /* Initialize module */ 336 337 module = Py_InitModule("magic", magic_methods); 338 dict = PyModule_GetDict(module); 339 340 magic_error_obj = PyErr_NewException("magic.error", NULL, NULL); 341 PyDict_SetItemString(dict, "error", magic_error_obj); 342 343 magic_cookie_type.ob_type = &PyType_Type; 344 345 /* Initialize constants */ 346 347 const_init(dict); 348 349 if(PyErr_Occurred()) 350 Py_FatalError("can't initialize module magic"); 351} 352