Dont leak memory from rpm.fi() methods
[platform/upstream/rpm.git] / python / rpmfi-py.c
1 #include "rpmsystem-py.h"
2
3 #include <rpm/rpmtypes.h>
4 #include <rpm/rpmpgp.h>
5
6 #include "header-py.h"
7 #include "rpmfi-py.h"
8
9 #include "debug.h"
10
11 struct rpmfiObject_s {
12     PyObject_HEAD
13     PyObject *md_dict;          /*!< to look like PyModuleObject */
14     int active;
15     rpmfi fi;
16 };
17
18 static PyObject *
19 rpmfi_FC(rpmfiObject * s)
20 {
21     return Py_BuildValue("i", rpmfiFC(s->fi));
22 }
23
24 static PyObject *
25 rpmfi_FX(rpmfiObject * s)
26 {
27     return Py_BuildValue("i", rpmfiFX(s->fi));
28 }
29
30 static PyObject *
31 rpmfi_DC(rpmfiObject * s)
32 {
33     return Py_BuildValue("i", rpmfiDC(s->fi));
34 }
35
36 static PyObject *
37 rpmfi_DX(rpmfiObject * s)
38 {
39     return Py_BuildValue("i", rpmfiDX(s->fi));
40 }
41
42 static PyObject *
43 rpmfi_BN(rpmfiObject * s)
44 {
45     return Py_BuildValue("s", rpmfiBN(s->fi));
46 }
47
48 static PyObject *
49 rpmfi_DN(rpmfiObject * s)
50 {
51     return Py_BuildValue("s", rpmfiDN(s->fi));
52 }
53
54 static PyObject *
55 rpmfi_FN(rpmfiObject * s)
56 {
57     return Py_BuildValue("s", rpmfiFN(s->fi));
58 }
59
60 static PyObject *
61 rpmfi_FFlags(rpmfiObject * s)
62 {
63     return Py_BuildValue("i", rpmfiFFlags(s->fi));
64 }
65
66 static PyObject *
67 rpmfi_VFlags(rpmfiObject * s)
68 {
69     return Py_BuildValue("i", rpmfiVFlags(s->fi));
70 }
71
72 static PyObject *
73 rpmfi_FMode(rpmfiObject * s)
74 {
75     return Py_BuildValue("i", rpmfiFMode(s->fi));
76 }
77
78 static PyObject *
79 rpmfi_FState(rpmfiObject * s)
80 {
81     return Py_BuildValue("i", rpmfiFState(s->fi));
82 }
83
84 /* XXX rpmfiFDigest */
85 static PyObject *
86 rpmfi_Digest(rpmfiObject * s)
87 {
88     char *digest = rpmfiFDigestHex(s->fi, NULL);
89     if (digest) {
90         PyObject *dig = Py_BuildValue("s", digest);
91         free(digest);
92         return dig;
93     } else {
94         Py_RETURN_NONE;
95     }
96 }
97
98 static PyObject *
99 rpmfi_FLink(rpmfiObject * s)
100 {
101     return Py_BuildValue("s", rpmfiFLink(s->fi));
102 }
103
104 static PyObject *
105 rpmfi_FSize(rpmfiObject * s)
106 {
107     return Py_BuildValue("L", rpmfiFSize(s->fi));
108 }
109
110 static PyObject *
111 rpmfi_FRdev(rpmfiObject * s)
112 {
113     return Py_BuildValue("i", rpmfiFRdev(s->fi));
114 }
115
116 static PyObject *
117 rpmfi_FMtime(rpmfiObject * s)
118 {
119     return Py_BuildValue("i", rpmfiFMtime(s->fi));
120 }
121
122 static PyObject *
123 rpmfi_FUser(rpmfiObject * s)
124 {
125     return Py_BuildValue("s", rpmfiFUser(s->fi));
126 }
127
128 static PyObject *
129 rpmfi_FGroup(rpmfiObject * s)
130 {
131     return Py_BuildValue("s", rpmfiFGroup(s->fi));
132 }
133
134 static PyObject *
135 rpmfi_FColor(rpmfiObject * s)
136 {
137     return Py_BuildValue("i", rpmfiFColor(s->fi));
138 }
139
140 static PyObject *
141 rpmfi_FClass(rpmfiObject * s)
142 {
143     const char * FClass;
144
145     if ((FClass = rpmfiFClass(s->fi)) == NULL)
146         FClass = "";
147     return Py_BuildValue("s", FClass);
148 }
149
150 static PyObject *
151 rpmfi_iternext(rpmfiObject * s)
152 {
153     PyObject * result = NULL;
154
155     /* Reset loop indices on 1st entry. */
156     if (!s->active) {
157         s->fi = rpmfiInit(s->fi, 0);
158         s->active = 1;
159     }
160
161     /* If more to do, return the file tuple. */
162     if (rpmfiNext(s->fi) >= 0) {
163         const char * FN = rpmfiFN(s->fi);
164         rpm_loff_t FSize = rpmfiFSize(s->fi);
165         int FMode = rpmfiFMode(s->fi);
166         int FMtime = rpmfiFMtime(s->fi);
167         int FFlags = rpmfiFFlags(s->fi);
168         int FRdev = rpmfiFRdev(s->fi);
169         int FInode = rpmfiFInode(s->fi);
170         int FNlink = rpmfiFNlink(s->fi);
171         int FState = rpmfiFState(s->fi);
172         int VFlags = rpmfiVFlags(s->fi);
173         const char * FUser = rpmfiFUser(s->fi);
174         const char * FGroup = rpmfiFGroup(s->fi);
175
176         result = PyTuple_New(13);
177         if (FN == NULL) {
178             Py_INCREF(Py_None);
179             PyTuple_SET_ITEM(result, 0, Py_None);
180         } else
181             PyTuple_SET_ITEM(result,  0, Py_BuildValue("s", FN));
182         PyTuple_SET_ITEM(result,  1, PyLong_FromLongLong(FSize));
183         PyTuple_SET_ITEM(result,  2, PyInt_FromLong(FMode));
184         PyTuple_SET_ITEM(result,  3, PyInt_FromLong(FMtime));
185         PyTuple_SET_ITEM(result,  4, PyInt_FromLong(FFlags));
186         PyTuple_SET_ITEM(result,  5, PyInt_FromLong(FRdev));
187         PyTuple_SET_ITEM(result,  6, PyInt_FromLong(FInode));
188         PyTuple_SET_ITEM(result,  7, PyInt_FromLong(FNlink));
189         PyTuple_SET_ITEM(result,  8, PyInt_FromLong(FState));
190         PyTuple_SET_ITEM(result,  9, PyInt_FromLong(VFlags));
191         if (FUser == NULL) {
192             Py_INCREF(Py_None);
193             PyTuple_SET_ITEM(result, 10, Py_None);
194         } else
195             PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser));
196         if (FGroup == NULL) {
197             Py_INCREF(Py_None);
198             PyTuple_SET_ITEM(result, 11, Py_None);
199         } else
200             PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup));
201         PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s));
202
203     } else
204         s->active = 0;
205
206     return result;
207 }
208
209 static struct PyMethodDef rpmfi_methods[] = {
210  {"FC",         (PyCFunction)rpmfi_FC,          METH_NOARGS,
211         NULL},
212  {"FX",         (PyCFunction)rpmfi_FX,          METH_NOARGS,
213         NULL},
214  {"DC",         (PyCFunction)rpmfi_DC,          METH_NOARGS,
215         NULL},
216  {"DX",         (PyCFunction)rpmfi_DX,          METH_NOARGS,
217         NULL},
218  {"BN",         (PyCFunction)rpmfi_BN,          METH_NOARGS,
219         NULL},
220  {"DN",         (PyCFunction)rpmfi_DN,          METH_NOARGS,
221         NULL},
222  {"FN",         (PyCFunction)rpmfi_FN,          METH_NOARGS,
223         NULL},
224  {"FFlags",     (PyCFunction)rpmfi_FFlags,      METH_NOARGS,
225         NULL},
226  {"VFlags",     (PyCFunction)rpmfi_VFlags,      METH_NOARGS,
227         NULL},
228  {"FMode",      (PyCFunction)rpmfi_FMode,       METH_NOARGS,
229         NULL},
230  {"FState",     (PyCFunction)rpmfi_FState,      METH_NOARGS,
231         NULL},
232  {"MD5",        (PyCFunction)rpmfi_Digest,      METH_NOARGS,
233         NULL},
234  {"Digest",     (PyCFunction)rpmfi_Digest,      METH_NOARGS,
235         NULL},
236  {"FLink",      (PyCFunction)rpmfi_FLink,       METH_NOARGS,
237         NULL},
238  {"FSize",      (PyCFunction)rpmfi_FSize,       METH_NOARGS,
239         NULL},
240  {"FRdev",      (PyCFunction)rpmfi_FRdev,       METH_NOARGS,
241         NULL},
242  {"FMtime",     (PyCFunction)rpmfi_FMtime,      METH_NOARGS,
243         NULL},
244  {"FUser",      (PyCFunction)rpmfi_FUser,       METH_NOARGS,
245         NULL},
246  {"FGroup",     (PyCFunction)rpmfi_FGroup,      METH_NOARGS,
247         NULL},
248  {"FColor",     (PyCFunction)rpmfi_FColor,      METH_NOARGS,
249         NULL},
250  {"FClass",     (PyCFunction)rpmfi_FClass,      METH_NOARGS,
251         NULL},
252  {NULL,         NULL}           /* sentinel */
253 };
254
255 /* ---------- */
256
257 static void
258 rpmfi_dealloc(rpmfiObject * s)
259 {
260     s->fi = rpmfiFree(s->fi);
261     s->ob_type->tp_free((PyObject *)s);
262 }
263
264 static int
265 rpmfi_length(rpmfiObject * s)
266 {
267     return rpmfiFC(s->fi);
268 }
269
270 static PyObject *
271 rpmfi_subscript(rpmfiObject * s, PyObject * key)
272 {
273     int ix;
274
275     if (!PyInt_Check(key)) {
276         PyErr_SetString(PyExc_TypeError, "integer expected");
277         return NULL;
278     }
279
280     ix = (int) PyInt_AsLong(key);
281     rpmfiSetFX(s->fi, ix);
282     return Py_BuildValue("s", rpmfiFN(s->fi));
283 }
284
285 static PyMappingMethods rpmfi_as_mapping = {
286         (lenfunc) rpmfi_length,         /* mp_length */
287         (binaryfunc) rpmfi_subscript,   /* mp_subscript */
288         (objobjargproc)0,               /* mp_ass_subscript */
289 };
290
291 static int rpmfi_init(rpmfiObject * s, PyObject *args, PyObject *kwds)
292 {
293     s->active = 0;
294     return 0;
295 }
296
297 static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
298 {
299     PyObject * to = NULL;
300     Header h = NULL;
301     rpmfi fi = NULL;
302     rpmTag tagN = RPMTAG_BASENAMES;
303     int flags = 0;
304     char * kwlist[] = {"header", "tag", "flags", NULL};
305
306     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|Oi:rpmfi_init", kwlist,
307                                 hdrFromPyObject, &h, &to, &flags))
308         return NULL;
309
310     fi = rpmfiNew(NULL, h, tagN, flags);
311
312     return rpmfi_Wrap(subtype, fi);
313 }
314
315 static char rpmfi_doc[] =
316 "";
317
318 PyTypeObject rpmfi_Type = {
319         PyObject_HEAD_INIT(&PyType_Type)
320         0,                              /* ob_size */
321         "rpm.fi",                       /* tp_name */
322         sizeof(rpmfiObject),            /* tp_basicsize */
323         0,                              /* tp_itemsize */
324         /* methods */
325         (destructor) rpmfi_dealloc,     /* tp_dealloc */
326         0,                              /* tp_print */
327         (getattrfunc)0,                 /* tp_getattr */
328         (setattrfunc)0,                 /* tp_setattr */
329         (cmpfunc)0,                     /* tp_compare */
330         (reprfunc)0,                    /* tp_repr */
331         0,                              /* tp_as_number */
332         0,                              /* tp_as_sequence */
333         &rpmfi_as_mapping,              /* tp_as_mapping */
334         (hashfunc)0,                    /* tp_hash */
335         (ternaryfunc)0,                 /* tp_call */
336         (reprfunc)0,                    /* tp_str */
337         PyObject_GenericGetAttr,        /* tp_getattro */
338         PyObject_GenericSetAttr,        /* tp_setattro */
339         0,                              /* tp_as_buffer */
340         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
341         rpmfi_doc,                      /* tp_doc */
342         0,                              /* tp_traverse */
343         0,                              /* tp_clear */
344         0,                              /* tp_richcompare */
345         0,                              /* tp_weaklistoffset */
346         PyObject_SelfIter,              /* tp_iter */
347         (iternextfunc) rpmfi_iternext,  /* tp_iternext */
348         rpmfi_methods,                  /* tp_methods */
349         0,                              /* tp_members */
350         0,                              /* tp_getset */
351         0,                              /* tp_base */
352         0,                              /* tp_dict */
353         0,                              /* tp_descr_get */
354         0,                              /* tp_descr_set */
355         0,                              /* tp_dictoffset */
356         (initproc) rpmfi_init,          /* tp_init */
357         0,                              /* tp_alloc */
358         (newfunc) rpmfi_new,            /* tp_new */
359         0,                              /* tp_free */
360         0,                              /* tp_is_gc */
361 };
362
363 /* ---------- */
364
365 rpmfi fiFromFi(rpmfiObject * s)
366 {
367     return s->fi;
368 }
369
370 PyObject * rpmfi_Wrap(PyTypeObject *subtype, rpmfi fi)
371 {
372     rpmfiObject *s = (rpmfiObject *)subtype->tp_alloc(subtype, 0);
373     if (s == NULL) return PyErr_NoMemory();
374
375     s->fi = fi;
376     s->active = 0;
377     return (PyObject *) s;
378 }
379