rpm/python/rpmarchive-py.c

276 lines
7.0 KiB
C

#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;
}