1 #include "rpmsystem-py.h"
3 #include <rpm/rpmtypes.h>
4 #include <rpm/rpmpgp.h>
9 #include "rpmfiles-py.h"
10 #include "rpmarchive-py.h"
11 #include "rpmstrpool-py.h"
13 struct rpmarchiveObject_s {
20 static void rpmarchive_dealloc(rpmarchiveObject * s)
22 rpmfilesFree(s->files);
23 rpmfiArchiveClose(s->archive);
24 rpmfiFree(s->archive);
25 Py_TYPE(s)->tp_free((PyObject *)s);
28 static PyObject *rpmarchive_error(int rc)
30 PyErr_SetObject(PyExc_IOError,
31 Py_BuildValue("(is)", rc, rpmfileStrerror(rc)));
35 static PyObject *rpmarchive_closed(void)
37 PyErr_SetString(PyExc_IOError, "I/O operation on closed archive");
41 static PyObject *rpmarchive_tell(rpmarchiveObject *s)
43 return PyLong_FromLongLong(rpmfiArchiveTell(s->archive));
46 static PyObject *rpmarchive_close(rpmarchiveObject *s)
49 int rc = rpmfiArchiveClose(s->archive);
50 s->archive = rpmfiFree(s->archive);
52 return rpmarchive_error(rc);
57 static PyObject *rpmarchive_has_content(rpmarchiveObject *s)
59 return PyLong_FromLong(rpmfiArchiveHasContent(s->archive));
62 static PyObject *rpmarchive_read(rpmarchiveObject *s,
63 PyObject *args, PyObject *kwds)
65 char *kwlist[] = { "size", NULL };
67 ssize_t chunksize = sizeof(buf);
72 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &left))
75 if (s->archive == NULL)
76 return rpmarchive_closed();
78 /* ConcatAndDel() doesn't work on NULL string, meh */
79 res = PyBytes_FromStringAndSize(NULL, 0);
81 if (left >= 0 && left < chunksize)
84 Py_BEGIN_ALLOW_THREADS
85 nb = rpmfiArchiveRead(s->archive, buf, chunksize);
89 PyObject *tmp = PyBytes_FromStringAndSize(buf, nb);
90 PyBytes_ConcatAndDel(&res, tmp);
97 return rpmarchive_error(nb);
103 static PyObject *rpmarchive_write(rpmarchiveObject *s,
104 PyObject *args, PyObject *kwds)
106 const char *buf = NULL;
108 char *kwlist[] = { "buffer", NULL };
111 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &buf, &size)) {
115 if (s->archive == NULL)
116 return rpmarchive_closed();
118 Py_BEGIN_ALLOW_THREADS
119 rc = rpmfiArchiveWrite(s->archive, buf, size);
123 return rpmarchive_error(rc);
125 return Py_BuildValue("n", rc);
128 static PyObject *rpmarchive_readto(rpmarchiveObject *s,
129 PyObject *args, PyObject *kwds)
131 rpmfdObject *fdo = NULL;
134 char *kwlist[] = { "fd", "nodigest", NULL };
136 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
137 rpmfdFromPyObject, &fdo, &nodigest)) {
141 if (s->archive == NULL)
142 return rpmarchive_closed();
144 Py_BEGIN_ALLOW_THREADS
145 rc = rpmfiArchiveReadToFile(s->archive, rpmfdGetFd(fdo), nodigest);
149 return rpmarchive_error(rc);
154 static PyObject *rpmarchive_writeto(rpmarchiveObject *s,
155 PyObject *args, PyObject *kwds)
157 rpmfdObject *fdo = NULL;
159 char *kwlist[] = { "fd", NULL };
161 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|i", kwlist,
162 rpmfdFromPyObject, &fdo)) {
166 if (s->archive == NULL)
167 return rpmarchive_closed();
169 Py_BEGIN_ALLOW_THREADS
170 rc = rpmfiArchiveWriteFile(s->archive, rpmfdGetFd(fdo));
174 return rpmarchive_error(rc);
179 static struct PyMethodDef rpmarchive_methods[] = {
180 { "tell", (PyCFunction)rpmarchive_tell, METH_NOARGS,
181 "archive.tell() -- Return current position in archive." },
182 { "close", (PyCFunction)rpmarchive_close, METH_NOARGS,
183 "archive.close() -- Close archive and do final consistency checks."},
184 { "read", (PyCFunction)rpmarchive_read, METH_VARARGS|METH_KEYWORDS,
185 "archive.read(size=None) -- Read next size bytes from current file.\n\n"
187 { "write", (PyCFunction)rpmarchive_write, METH_VARARGS|METH_KEYWORDS,
188 "archive.write(buffer) -- Write buffer to current file." },
189 { "readto", (PyCFunction)rpmarchive_readto, METH_VARARGS|METH_KEYWORDS,
190 "archive.readto(fd, nodigest=None) -- Read content of fd\n"
191 "and write as content of the current file to archive." },
192 { "writeto", (PyCFunction)rpmarchive_writeto,METH_VARARGS|METH_KEYWORDS,
193 "archive.writeto(fd) -- Write content of current file in archive\n to fd." },
194 { "hascontent", (PyCFunction)rpmarchive_has_content, METH_NOARGS,
195 "archive.hascontent() -- Return if current file has a content.\n\n"
196 "Returns false for non regular and all but one of hardlinked files."},
197 { NULL, NULL, 0, NULL }
200 static char rpmarchive_doc[] =
201 "Gives access to the payload of an rpm package.\n\n"
202 "Is returned by .archive() method of an rpm.files instance.\n"
203 "All methods can raise an IOError exception.";
205 static PyObject *rpmarchive_iternext(rpmarchiveObject *s)
207 PyObject *next = NULL;
208 int fx = rpmfiNext(s->archive);
211 next = rpmfile_Wrap(s->files, fx);
212 } else if (fx < -1) {
213 next = rpmarchive_error(fx);
215 /* end of iteration, nothing to do */
221 PyTypeObject rpmarchive_Type = {
222 PyVarObject_HEAD_INIT(&PyType_Type, 0)
223 "rpm.archive", /* tp_name */
224 sizeof(rpmarchiveObject), /* tp_basicsize */
226 (destructor) rpmarchive_dealloc, /* tp_dealloc */
232 0, /* tp_as_number */
233 0, /* tp_as_sequence */
234 0, /* tp_as_mapping */
238 PyObject_GenericGetAttr, /* tp_getattro */
239 PyObject_GenericSetAttr, /* tp_setattro */
240 0, /* tp_as_buffer */
241 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
242 rpmarchive_doc, /* tp_doc */
245 0, /* tp_richcompare */
246 0, /* tp_weaklistoffset */
247 PyObject_SelfIter, /* tp_iter */
248 (iternextfunc) rpmarchive_iternext, /* tp_iternext */
249 rpmarchive_methods, /* tp_methods */
254 0, /* tp_descr_get */
255 0, /* tp_descr_set */
256 0, /* tp_dictoffset */
264 PyObject * rpmarchive_Wrap(PyTypeObject *subtype,
265 rpmfiles files, rpmfi archive)
267 rpmarchiveObject *s = (rpmarchiveObject *)subtype->tp_alloc(subtype, 0);
268 if (s == NULL) return NULL;
270 s->files = rpmfilesLink(files);
271 s->archive = archive;
273 return (PyObject *) s;