diff options
Diffstat (limited to 'python/rpmarchive-py.c')
-rw-r--r-- | python/rpmarchive-py.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/python/rpmarchive-py.c b/python/rpmarchive-py.c new file mode 100644 index 000000000..53a078a4e --- /dev/null +++ b/python/rpmarchive-py.c @@ -0,0 +1,275 @@ +#include "rpmsystem-py.h" + +#include <rpm/rpmtypes.h> +#include <rpm/rpmpgp.h> + +#include "header-py.h" +#include "rpmfi-py.h" +#include "rpmfd-py.h" +#include "rpmfiles-py.h" +#include "rpmarchive-py.h" +#include "rpmstrpool-py.h" + +struct rpmarchiveObject_s { + PyObject_HEAD + PyObject *md_dict; + rpmfi archive; + rpmfiles files; +}; + +static void rpmarchive_dealloc(rpmarchiveObject * s) +{ + rpmfilesFree(s->files); + rpmfiArchiveClose(s->archive); + rpmfiFree(s->archive); + Py_TYPE(s)->tp_free((PyObject *)s); +} + +static PyObject *rpmarchive_error(int rc) +{ + PyErr_SetObject(PyExc_IOError, + Py_BuildValue("(is)", rc, rpmfileStrerror(rc))); + return NULL; +} + +static PyObject *rpmarchive_closed(void) +{ + PyErr_SetString(PyExc_IOError, "I/O operation on closed archive"); + return NULL; +} + +static PyObject *rpmarchive_tell(rpmarchiveObject *s) +{ + return PyLong_FromLongLong(rpmfiArchiveTell(s->archive)); +} + +static PyObject *rpmarchive_close(rpmarchiveObject *s) +{ + if (s->archive) { + int rc = rpmfiArchiveClose(s->archive); + s->archive = rpmfiFree(s->archive); + if (rc) + return rpmarchive_error(rc); + } + Py_RETURN_NONE; +} + +static PyObject *rpmarchive_has_content(rpmarchiveObject *s) +{ + return PyLong_FromLong(rpmfiArchiveHasContent(s->archive)); +} + +static PyObject *rpmarchive_read(rpmarchiveObject *s, + PyObject *args, PyObject *kwds) +{ + char *kwlist[] = { "size", NULL }; + char buf[BUFSIZ]; + ssize_t chunksize = sizeof(buf); + ssize_t left = -1; + ssize_t nb = 0; + PyObject *res = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &left)) + return NULL; + + if (s->archive == NULL) + return rpmarchive_closed(); + + /* ConcatAndDel() doesn't work on NULL string, meh */ + res = PyBytes_FromStringAndSize(NULL, 0); + do { + if (left >= 0 && left < chunksize) + chunksize = left; + + Py_BEGIN_ALLOW_THREADS + nb = rpmfiArchiveRead(s->archive, buf, chunksize); + Py_END_ALLOW_THREADS + + if (nb > 0) { + PyObject *tmp = PyBytes_FromStringAndSize(buf, nb); + PyBytes_ConcatAndDel(&res, tmp); + left -= nb; + } + } while (nb > 0); + + if (nb < 0) { + Py_XDECREF(res); + return rpmarchive_error(nb); + } else { + return res; + } +} + +static PyObject *rpmarchive_write(rpmarchiveObject *s, + PyObject *args, PyObject *kwds) +{ + const char *buf = NULL; + ssize_t size = 0; + char *kwlist[] = { "buffer", NULL }; + ssize_t rc = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &buf, &size)) { + return NULL; + } + + if (s->archive == NULL) + return rpmarchive_closed(); + + Py_BEGIN_ALLOW_THREADS + rc = rpmfiArchiveWrite(s->archive, buf, size); + Py_END_ALLOW_THREADS + + if (rc < 0) + return rpmarchive_error(rc); + else + return Py_BuildValue("n", rc); +} + +static PyObject *rpmarchive_readto(rpmarchiveObject *s, + PyObject *args, PyObject *kwds) +{ + rpmfdObject *fdo = NULL; + int nodigest = 0; + int rc; + char *kwlist[] = { "fd", "nodigest", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist, + rpmfdFromPyObject, &fdo, &nodigest)) { + return NULL; + } + + if (s->archive == NULL) + return rpmarchive_closed(); + + Py_BEGIN_ALLOW_THREADS + rc = rpmfiArchiveReadToFile(s->archive, rpmfdGetFd(fdo), nodigest); + Py_END_ALLOW_THREADS + + if (rc) + return rpmarchive_error(rc); + + Py_RETURN_NONE; +} + +static PyObject *rpmarchive_writeto(rpmarchiveObject *s, + PyObject *args, PyObject *kwds) +{ + rpmfdObject *fdo = NULL; + int rc; + char *kwlist[] = { "fd", NULL }; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist, + rpmfdFromPyObject, &fdo)) { + return NULL; + } + + if (s->archive == NULL) + return rpmarchive_closed(); + + Py_BEGIN_ALLOW_THREADS + rc = rpmfiArchiveWriteFile(s->archive, rpmfdGetFd(fdo)); + Py_END_ALLOW_THREADS + + if (rc) + return rpmarchive_error(rc); + + Py_RETURN_NONE; +} + +static struct PyMethodDef rpmarchive_methods[] = { + { "tell", (PyCFunction)rpmarchive_tell, METH_NOARGS, + "archive.tell() -- Return current position in archive." }, + { "close", (PyCFunction)rpmarchive_close, METH_NOARGS, + "archive.close() -- Close archive and do final consistency checks."}, + { "read", (PyCFunction)rpmarchive_read, METH_VARARGS|METH_KEYWORDS, + "archive.read(size=None) -- Read next size bytes from current file.\n\n" + "Returns bytes\n"}, + { "write", (PyCFunction)rpmarchive_write, METH_VARARGS|METH_KEYWORDS, + "archive.write(buffer) -- Write buffer to current file." }, + { "readto", (PyCFunction)rpmarchive_readto, METH_VARARGS|METH_KEYWORDS, + "archive.readto(fd, nodigest=None) -- Read content of fd\n" + "and write as content of the current file to archive." }, + { "writeto", (PyCFunction)rpmarchive_writeto,METH_VARARGS|METH_KEYWORDS, + "archive.writeto(fd) -- Write content of current file in archive\n to fd." }, + { "hascontent", (PyCFunction)rpmarchive_has_content, METH_NOARGS, + "archive.hascontent() -- Return if current file has a content.\n\n" + "Returns false for non regular and all but one of hardlinked files."}, + { NULL, NULL, 0, NULL } +}; + +static char rpmarchive_doc[] = +"Gives access to the payload of an rpm package.\n\n" +"Is returned by .archive() method of an rpm.files instance.\n" +"All methods can raise an IOError exception."; + +static PyObject *rpmarchive_iternext(rpmarchiveObject *s) +{ + PyObject *next = NULL; + int fx = rpmfiNext(s->archive); + + if (fx >= 0) { + next = rpmfile_Wrap(s->files, fx); + } else if (fx < -1) { + next = rpmarchive_error(fx); + } else { + /* end of iteration, nothing to do */ + } + + return next; +} + +PyTypeObject rpmarchive_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rpm.archive", /* tp_name */ + sizeof(rpmarchiveObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) rpmarchive_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* 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 */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ + rpmarchive_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc) rpmarchive_iternext, /* tp_iternext */ + rpmarchive_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; + +PyObject * rpmarchive_Wrap(PyTypeObject *subtype, + rpmfiles files, rpmfi archive) +{ + rpmarchiveObject *s = (rpmarchiveObject *)subtype->tp_alloc(subtype, 0); + if (s == NULL) return NULL; + + s->files = rpmfilesLink(files); + s->archive = archive; + + return (PyObject *) s; +} + |