From: Christos Zoulas Date: Wed, 15 Oct 2003 02:22:59 +0000 (+0000) Subject: add python bindings X-Git-Tag: FILE4_06~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ff3bfb82017cd80732b72e66d8c420fd650f129f;p=file add python bindings --- diff --git a/python/README b/python/README new file mode 100644 index 00000000..880dfa50 --- /dev/null +++ b/python/README @@ -0,0 +1,24 @@ + +This directory contains Python bindings to allow you to access the +libmagic api. At the moment their status is "experimental" and +they are not built by default. + +In order to be able to compile magic-python you need to have python +and the python-dev packages installed. + +Python libraries are always built for a particular version of Python +(2.2, 2.3, etc), and libraries built for one version will not be seen +by another. + +To build: + +$ python setup.py build + +Now, you can install the modules: + +$ cp build/lib.*/magic.so /usr/lib/python2.3/lib-dynload/ + +(the directory /usr/lib/python2.3 may vary, depending on your installation) + +magic-python should work now! + diff --git a/python/py_magic.c b/python/py_magic.c new file mode 100644 index 00000000..48700c25 --- /dev/null +++ b/python/py_magic.c @@ -0,0 +1,331 @@ +/* + Python wrappers for magic functions. + + Copyright (C) Brett Funderburg, Deepfile Corp. Austin, TX, US 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include "py_magic.h" + +/* Exceptions raised by this module */ + +PyObject* magic_error_obj; + +/* Create a new magic_cookie_hnd object */ +PyObject* new_magic_cookie_handle(magic_t cookie) +{ + magic_cookie_hnd* mch; + + mch = PyObject_New(magic_cookie_hnd, &magic_cookie_type); + + mch->cookie = cookie; + + return (PyObject*)mch; +} + +static char _magic_open__doc__[] = +"Returns a magic cookie on success and None on failure.\n"; +static PyObject* py_magic_open(PyObject* self, PyObject* args) +{ + int flags = 0; + magic_t cookie; + + if(!PyArg_ParseTuple(args, "i", &flags)) + return NULL; + + if(!(cookie = magic_open(flags))) { + PyErr_SetString(magic_error_obj, "failure initializing magic +cookie"); + return NULL; + } + + return new_magic_cookie_handle(cookie); +} + +static char _magic_close__doc__[] = +"Closes the magic database and deallocates any resources used.\n"; +static PyObject* py_magic_close(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + + magic_close(hnd->cookie); + + Py_INCREF(Py_None); + return Py_None; +} + +static char _magic_error__doc__[] = +"Returns a textual explanation of the last error or None \ + if there was no error.\n"; +static PyObject* py_magic_error(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + const char* message = NULL; + PyObject* result = NULL; + + message = magic_error(hnd->cookie); + + if(message != NULL) + result = PyString_FromString(message); + else { + Py_INCREF(Py_None); + result = Py_None; + } + + return result; +} + +static char _magic_file__doc__[] = +"Returns a textual description of the contents of the argument passed \ + as a filename or None if an error occurred.\n"; +static PyObject* py_magic_file(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + char* filename = NULL; + const char* message = NULL; + PyObject* result = NULL; + + if(!(PyArg_ParseTuple(args, "s", &filename))) + return NULL; + + message = magic_file(hnd->cookie, filename); + + if(message != NULL) + result = PyString_FromString(message); + else + PyErr_SetString(PyExc_RuntimeError, + "failure determining file type"); + + return result; +} + +static char _magic_buffer__doc__[] = +"Returns a textual description of the contents of the argument passed \ + as a buffer or None if an error occurred.\n"; +static PyObject* py_magic_buffer(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + void* buffer = NULL; + int buffer_length = 0; + const char* message = NULL; + PyObject* result = NULL; + + if(!(PyArg_ParseTuple(args, "s#", (char**)&buffer, &buffer_length))) + return NULL; + + message = magic_buffer(hnd->cookie, buffer, buffer_length); + + if(message != NULL) + result = PyString_FromString(message); + else + PyErr_SetString(PyExc_RuntimeError, + "failure determining buffer type"); + + return result; +} + +static char _magic_setflags__doc__[] = +"Set flags on the cookie object.\n \ + Returns -1 on systems that don't support utime(2) or utimes(2) \ + when MAGIC_PRESERVE_ATIME is set.\n"; +static PyObject* py_magic_setflags(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + int flags; + int result; + + if(!(PyArg_ParseTuple(args, "i", &flags))) + return NULL; + + result = magic_setflags(hnd->cookie, flags); + + return PyInt_FromLong(result); +} + +static char _magic_check__doc__[] = +"Check the validity of entries in the colon separated list of database +files \ + passed as argument or the default database file if no argument.\n \ + Returns 0 on success and -1 on failure.\n"; +static PyObject* py_magic_check(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + char* filename = NULL; + int result; + + if(!(PyArg_ParseTuple(args, "|s", &filename))) + return NULL; + + result = magic_check(hnd->cookie, filename); + + return PyInt_FromLong(result); +} + +static char _magic_compile__doc__[] = +"Compile entries in the colon separated list of database files \ + passed as argument or the default database file if no argument.\n \ + Returns 0 on success and -1 on failure.\n \ + The compiled files created are named from the basename(1) of each file \ + argument with \".mgc\" appended to it.\n"; +static PyObject* py_magic_compile(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + char* filename = NULL; + int result; + + if(!(PyArg_ParseTuple(args, "|s", &filename))) + return NULL; + + result = magic_compile(hnd->cookie, filename); + + return PyInt_FromLong(result); +} + +static char _magic_load__doc__[] = +"Must be used to load entries in the colon separated list of database files \ + passed as argument or the default database file if no argument before \ + any magic queries can be performed.\n \ + Returns 0 on success and -1 on failure.\n"; +static PyObject* py_magic_load(PyObject* self, PyObject* args) +{ + magic_cookie_hnd* hnd = (magic_cookie_hnd*)self; + char* filename = NULL; + int result; + + if(!(PyArg_ParseTuple(args, "|s", &filename))) + return NULL; + + result = magic_load(hnd->cookie, filename); + + return PyInt_FromLong(result); +} + +/* object methods */ + +static PyMethodDef magic_cookie_hnd_methods[] = { + { "close", (PyCFunction)py_magic_close, + METH_NOARGS, _magic_close__doc__ }, + { "error", (PyCFunction)py_magic_error, + METH_NOARGS, _magic_error__doc__ }, + { "file", (PyCFunction)py_magic_file, + METH_VARARGS, _magic_file__doc__ }, + { "buffer", (PyCFunction)py_magic_buffer, + METH_VARARGS, _magic_buffer__doc__ }, + { "setflags", (PyCFunction)py_magic_setflags, + METH_VARARGS, _magic_setflags__doc__ }, + { "check", (PyCFunction)py_magic_check, + METH_VARARGS, _magic_check__doc__ }, + { "compile", (PyCFunction)py_magic_compile, + METH_VARARGS, _magic_compile__doc__ }, + { "load", (PyCFunction)py_magic_load, + METH_VARARGS, _magic_load__doc__ }, + { NULL, NULL } +}; + +/* module level methods */ + +static PyMethodDef magic_methods[] = { + { "open", (PyCFunction)py_magic_open, + METH_VARARGS, _magic_open__doc__ }, + { NULL, NULL } +}; + +static void py_magic_dealloc(PyObject* self) +{ + PyObject_Del(self); +} + +static PyObject* py_magic_getattr(PyObject* self, char* attrname) +{ + return Py_FindMethod(magic_cookie_hnd_methods, self, attrname); +} + +PyTypeObject magic_cookie_type = { + PyObject_HEAD_INIT(NULL) + 0, + "Magic cookie", + sizeof(magic_cookie_hnd), + 0, + py_magic_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + py_magic_getattr, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ +}; + +/* Initialize constants */ + +static struct const_vals { + const char* const name; + unsigned int value; +} module_const_vals[] = { + { "MAGIC_NONE", MAGIC_NONE }, + { "MAGIC_DEBUG", MAGIC_DEBUG }, + { "MAGIC_SYMLINK", MAGIC_SYMLINK }, + { "MAGIC_COMPRESS", MAGIC_COMPRESS }, + { "MAGIC_DEVICES", MAGIC_DEVICES }, + { "MAGIC_MIME", MAGIC_MIME }, + { "MAGIC_CONTINUE", MAGIC_CONTINUE }, + { "MAGIC_CHECK", MAGIC_CHECK }, + { "MAGIC_PRESERVE_ATIME", MAGIC_PRESERVE_ATIME }, + { NULL } +}; + +static void const_init(PyObject* dict) +{ + struct const_vals* tmp; + PyObject *obj; + + for(tmp = module_const_vals; tmp->name; ++tmp) { + obj = PyInt_FromLong(tmp->value); + PyDict_SetItemString(dict, tmp->name, obj); + Py_DECREF(obj); + } +} + +/* + * Module initialization + */ + +void initmagic(void) +{ + PyObject* module; + PyObject* dict; + + /* Initialize module */ + + module = Py_InitModule("magic", magic_methods); + dict = PyModule_GetDict(module); + + magic_error_obj = PyErr_NewException("magic.error", NULL, NULL); + PyDict_SetItemString(dict, "error", magic_error_obj); + + magic_cookie_type.ob_type = &PyType_Type; + + /* Initialize constants */ + + const_init(dict); + + if(PyErr_Occurred()) + Py_FatalError("can't initialize module magic"); +} diff --git a/python/py_magic.h b/python/py_magic.h new file mode 100644 index 00000000..0129cbb2 --- /dev/null +++ b/python/py_magic.h @@ -0,0 +1,29 @@ +/* + Python wrappers for magic functions. + + Copyright (C) Brett Funderburg, Deepfile Corp. Austin, TX, US 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _PY_MAGIC_H +#define _PY_MAGIC_H + +typedef struct { + PyObject_HEAD + magic_t cookie; +} magic_cookie_hnd; + +#endif /* _PY_MAGIC_H */ diff --git a/python/setup.py b/python/setup.py new file mode 100644 index 00000000..e18c5b03 --- /dev/null +++ b/python/setup.py @@ -0,0 +1,24 @@ +To build, make a directory called 'python' in 'src' and then follow the +instructions in the README. + +Unless something got screwed up in the cut and paste, the code should +compile cleanly and without warnings. + +You may need to tinker with the library and include paths specified in the +distutils build script (setup.py) to make things work on your machine. + +The following python script should give you an idea of how things work. + +-- begin -- +import magic +c = magic.open(magic.MAGIC_NONE) +c.load() +c.file("/path/to/some/file") + +f = file("/path/to/some/file", "r") +buffer = f.read(4096) +f.close() + +c.buffer(buffer) + +c.close()