Blame python/rpmarchive-py.c

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