Imported Upstream version 4.14.1
[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 #include "rpmstrpool-py.h"
9
10 struct rpmfiObject_s {
11     PyObject_HEAD
12     PyObject *md_dict;          /*!< to look like PyModuleObject */
13     int active;
14     rpmfi fi;
15 };
16
17 static PyObject *
18 rpmfi_FC(rpmfiObject * s, PyObject * unused)
19 {
20     return Py_BuildValue("i", rpmfiFC(s->fi));
21 }
22
23 static PyObject *
24 rpmfi_FX(rpmfiObject * s, PyObject * unused)
25 {
26     return Py_BuildValue("i", rpmfiFX(s->fi));
27 }
28
29 static PyObject *
30 rpmfi_DC(rpmfiObject * s, PyObject * unused)
31 {
32     return Py_BuildValue("i", rpmfiDC(s->fi));
33 }
34
35 static PyObject *
36 rpmfi_DX(rpmfiObject * s, PyObject * unused)
37 {
38     return Py_BuildValue("i", rpmfiDX(s->fi));
39 }
40
41 static PyObject *
42 rpmfi_BN(rpmfiObject * s, PyObject * unused)
43 {
44     return Py_BuildValue("s", rpmfiBN(s->fi));
45 }
46
47 static PyObject *
48 rpmfi_DN(rpmfiObject * s, PyObject * unused)
49 {
50     return Py_BuildValue("s", rpmfiDN(s->fi));
51 }
52
53 static PyObject *
54 rpmfi_FN(rpmfiObject * s, PyObject * unused)
55 {
56     return Py_BuildValue("s", rpmfiFN(s->fi));
57 }
58
59 static PyObject *
60 rpmfi_FindFN(rpmfiObject * s, PyObject * args, PyObject * kwds)
61 {
62     char * kwlist[] = {"filename", NULL};
63     PyObject * filename = NULL;
64     if (!PyArg_ParseTupleAndKeywords(args, kwds, "S:FindFN", kwlist,
65                                      &filename))
66         return NULL;
67     return Py_BuildValue("i", rpmfiFindFN(s->fi, PyBytes_AsString(filename)));
68 }
69
70
71 static PyObject *
72 rpmfi_FFlags(rpmfiObject * s, PyObject * unused)
73 {
74     return Py_BuildValue("i", rpmfiFFlags(s->fi));
75 }
76
77 static PyObject *
78 rpmfi_VFlags(rpmfiObject * s, PyObject * unused)
79 {
80     return Py_BuildValue("i", rpmfiVFlags(s->fi));
81 }
82
83 static PyObject *
84 rpmfi_FMode(rpmfiObject * s, PyObject * unused)
85 {
86     return Py_BuildValue("i", rpmfiFMode(s->fi));
87 }
88
89 static PyObject *
90 rpmfi_FState(rpmfiObject * s, PyObject * unused)
91 {
92     return Py_BuildValue("i", rpmfiFState(s->fi));
93 }
94
95 /* XXX rpmfiFDigest */
96 static PyObject *
97 rpmfi_Digest(rpmfiObject * s, PyObject * unused)
98 {
99     char *digest = rpmfiFDigestHex(s->fi, NULL);
100     if (digest) {
101         PyObject *dig = Py_BuildValue("s", digest);
102         free(digest);
103         return dig;
104     } else {
105         Py_RETURN_NONE;
106     }
107 }
108
109 static PyObject *
110 rpmfi_FLink(rpmfiObject * s, PyObject * unused)
111 {
112     return Py_BuildValue("s", rpmfiFLink(s->fi));
113 }
114
115 static PyObject *
116 rpmfi_FSize(rpmfiObject * s, PyObject * unused)
117 {
118     return Py_BuildValue("L", rpmfiFSize(s->fi));
119 }
120
121 static PyObject *
122 rpmfi_FRdev(rpmfiObject * s, PyObject * unused)
123 {
124     return Py_BuildValue("i", rpmfiFRdev(s->fi));
125 }
126
127 static PyObject *
128 rpmfi_FMtime(rpmfiObject * s, PyObject * unused)
129 {
130     return Py_BuildValue("i", rpmfiFMtime(s->fi));
131 }
132
133 static PyObject *
134 rpmfi_FUser(rpmfiObject * s, PyObject * unused)
135 {
136     return Py_BuildValue("s", rpmfiFUser(s->fi));
137 }
138
139 static PyObject *
140 rpmfi_FGroup(rpmfiObject * s, PyObject * unused)
141 {
142     return Py_BuildValue("s", rpmfiFGroup(s->fi));
143 }
144
145 static PyObject *
146 rpmfi_FColor(rpmfiObject * s, PyObject * unused)
147 {
148     return Py_BuildValue("i", rpmfiFColor(s->fi));
149 }
150
151 static PyObject *
152 rpmfi_FClass(rpmfiObject * s, PyObject * unused)
153 {
154     const char * FClass;
155
156     if ((FClass = rpmfiFClass(s->fi)) == NULL)
157         FClass = "";
158     return Py_BuildValue("s", FClass);
159 }
160
161 static PyObject *
162 rpmfi_FLinks(rpmfiObject * s, PyObject * unused)
163 {
164     uint32_t nlinks;
165     const int * files;
166     PyObject * result;
167
168     nlinks = rpmfiFLinks(s->fi, &files);
169     if (nlinks==1) {
170         return Py_BuildValue("(i)", rpmfiFX(s->fi));
171     }
172
173     result = PyTuple_New(nlinks);
174     for (uint32_t i=0; i<nlinks; i++) {
175         PyTuple_SET_ITEM(result,  i, PyInt_FromLong(files[i]));
176     }
177     return result;
178 }
179
180 static PyObject *
181 rpmfi_iternext(rpmfiObject * s)
182 {
183     PyObject * result = NULL;
184
185     /* Reset loop indices on 1st entry. */
186     if (!s->active) {
187         s->fi = rpmfiInit(s->fi, 0);
188         s->active = 1;
189     }
190
191     /* If more to do, return the file tuple. */
192     if (rpmfiNext(s->fi) >= 0) {
193         const char * FN = rpmfiFN(s->fi);
194         rpm_loff_t FSize = rpmfiFSize(s->fi);
195         int FMode = rpmfiFMode(s->fi);
196         int FMtime = rpmfiFMtime(s->fi);
197         int FFlags = rpmfiFFlags(s->fi);
198         int FRdev = rpmfiFRdev(s->fi);
199         int FInode = rpmfiFInode(s->fi);
200         int FNlink = rpmfiFNlink(s->fi);
201         int FState = rpmfiFState(s->fi);
202         int VFlags = rpmfiVFlags(s->fi);
203         const char * FUser = rpmfiFUser(s->fi);
204         const char * FGroup = rpmfiFGroup(s->fi);
205
206         result = PyTuple_New(13);
207         if (FN == NULL) {
208             Py_INCREF(Py_None);
209             PyTuple_SET_ITEM(result, 0, Py_None);
210         } else
211             PyTuple_SET_ITEM(result,  0, Py_BuildValue("s", FN));
212         PyTuple_SET_ITEM(result,  1, PyLong_FromLongLong(FSize));
213         PyTuple_SET_ITEM(result,  2, PyInt_FromLong(FMode));
214         PyTuple_SET_ITEM(result,  3, PyInt_FromLong(FMtime));
215         PyTuple_SET_ITEM(result,  4, PyInt_FromLong(FFlags));
216         PyTuple_SET_ITEM(result,  5, PyInt_FromLong(FRdev));
217         PyTuple_SET_ITEM(result,  6, PyInt_FromLong(FInode));
218         PyTuple_SET_ITEM(result,  7, PyInt_FromLong(FNlink));
219         PyTuple_SET_ITEM(result,  8, PyInt_FromLong(FState));
220         PyTuple_SET_ITEM(result,  9, PyInt_FromLong(VFlags));
221         if (FUser == NULL) {
222             Py_INCREF(Py_None);
223             PyTuple_SET_ITEM(result, 10, Py_None);
224         } else
225             PyTuple_SET_ITEM(result, 10, Py_BuildValue("s", FUser));
226         if (FGroup == NULL) {
227             Py_INCREF(Py_None);
228             PyTuple_SET_ITEM(result, 11, Py_None);
229         } else
230             PyTuple_SET_ITEM(result, 11, Py_BuildValue("s", FGroup));
231         PyTuple_SET_ITEM(result, 12, rpmfi_Digest(s, NULL));
232
233     } else
234         s->active = 0;
235
236     return result;
237 }
238
239 static struct PyMethodDef rpmfi_methods[] = {
240  {"FC",         (PyCFunction)rpmfi_FC,          METH_NOARGS,
241   "fi.FC() -- Return number of files entries."},
242  {"FX",         (PyCFunction)rpmfi_FX,          METH_NOARGS,
243   "fi.FX() -- Return current position of the iterator."},
244  {"DC",         (PyCFunction)rpmfi_DC,          METH_NOARGS,
245   "fi.DC() --Return number of directory entries."},
246  {"DX",         (PyCFunction)rpmfi_DX,          METH_NOARGS,
247   "fi.DX() -- Return number of directory entry matching current file."},
248  {"BN",         (PyCFunction)rpmfi_BN,          METH_NOARGS,
249   "fi.BN() -- Return base name of current file."},
250  {"DN",         (PyCFunction)rpmfi_DN,          METH_NOARGS,
251   "fi.DN() -- Return directory name of the current file."},
252  {"FN",         (PyCFunction)rpmfi_FN,          METH_NOARGS,
253   "fi.FN() -- Return the name/path of the current file."},
254  {"FindFN",     (PyCFunction)rpmfi_FindFN,      METH_VARARGS|METH_KEYWORDS,
255   "fi.FindFN(pathname) -- Return entry number of given pathname.\n\nReturn -1 if file is not found.\nLeading '.' in the given name is stripped before the search."},
256  {"FFlags",     (PyCFunction)rpmfi_FFlags,      METH_NOARGS,
257   "fi.FFlags() -- Return the flags of the current file."},
258  {"VFlags",     (PyCFunction)rpmfi_VFlags,      METH_NOARGS,
259   "fi.VFlags() -- Return the verify flags of the current file.\n\nSee RPMVERIFY_* (in rpmvf.h)"},
260  {"FMode",      (PyCFunction)rpmfi_FMode,       METH_NOARGS,
261   "fi.FMode() -- Return the mode flags of the current file."},
262  {"FState",     (PyCFunction)rpmfi_FState,      METH_NOARGS,
263   "fi.FState() -- Return the file state of the current file."},
264  {"MD5",        (PyCFunction)rpmfi_Digest,      METH_NOARGS,
265   "fi.() -- Return the checksum of the current file.\n\nDEPRECATED! Use fi.Digest instead!"},
266  {"Digest",     (PyCFunction)rpmfi_Digest,      METH_NOARGS,
267   "fi.() -- Return the checksum of the current file."},
268  {"FLink",      (PyCFunction)rpmfi_FLink,       METH_NOARGS,
269   "fi.() -- Return the link target of the current file.\n\nFor soft links only."},
270  {"FSize",      (PyCFunction)rpmfi_FSize,       METH_NOARGS,
271   "fi.() -- Return the size of the current file."},
272  {"FRdev",      (PyCFunction)rpmfi_FRdev,       METH_NOARGS,
273   "fi.() -- Return the device number of the current file.\n\nFor device files only."},
274  {"FMtime",     (PyCFunction)rpmfi_FMtime,      METH_NOARGS,
275   "fi.() -- Return the modification time of the current file."},
276  {"FUser",      (PyCFunction)rpmfi_FUser,       METH_NOARGS,
277   "fi.() -- Return the user name owning the current file."},
278  {"FGroup",     (PyCFunction)rpmfi_FGroup,      METH_NOARGS,
279   "fi.() -- Return the group name of the current file."},
280  {"FColor",     (PyCFunction)rpmfi_FColor,      METH_NOARGS,
281   "fi.() -- Return the color of the current file.\n\n2 for 64 bit binaries\n1 for 32 bit binaries\n0 for everything else"},
282  {"FClass",     (PyCFunction)rpmfi_FClass,      METH_NOARGS,
283   "fi.() -- Return the classification of the current file."},
284  {"FLinks",     (PyCFunction)rpmfi_FLinks,      METH_NOARGS,
285   "fi.() -- Return the number of hardlinks pointing to of the\ncurrent file."},
286  {NULL,         NULL}           /* sentinel */
287 };
288
289 /* ---------- */
290
291 static void
292 rpmfi_dealloc(rpmfiObject * s)
293 {
294     s->fi = rpmfiFree(s->fi);
295     Py_TYPE(s)->tp_free((PyObject *)s);
296 }
297
298 static int
299 rpmfi_length(rpmfiObject * s)
300 {
301     return rpmfiFC(s->fi);
302 }
303
304 static PyObject *
305 rpmfi_subscript(rpmfiObject * s, PyObject * key)
306 {
307     int ix;
308
309     if (!PyInt_Check(key)) {
310         PyErr_SetString(PyExc_TypeError, "integer expected");
311         return NULL;
312     }
313
314     ix = (int) PyInt_AsLong(key);
315     rpmfiSetFX(s->fi, ix);
316     return Py_BuildValue("s", rpmfiFN(s->fi));
317 }
318
319 static PyMappingMethods rpmfi_as_mapping = {
320         (lenfunc) rpmfi_length,         /* mp_length */
321         (binaryfunc) rpmfi_subscript,   /* mp_subscript */
322         (objobjargproc)0,               /* mp_ass_subscript */
323 };
324
325 static int rpmfi_init(rpmfiObject * s, PyObject *args, PyObject *kwds)
326 {
327     s->active = 0;
328     return 0;
329 }
330
331 static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
332 {
333     PyObject * to = NULL;
334     Header h = NULL;
335     rpmfi fi = NULL;
336     rpmTagVal tagN = RPMTAG_BASENAMES;
337     int flags = 0;
338     rpmstrPool pool = NULL;
339     char * kwlist[] = {"header", "tag", "flags", "pool", NULL};
340
341     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|OiO&:rpmfi_init", kwlist,
342                                 hdrFromPyObject, &h, &to, &flags,
343                                 poolFromPyObject, &pool))
344         return NULL;
345
346     fi = rpmfiNewPool(pool, h, tagN, flags);
347
348     if (fi == NULL) {
349         PyErr_SetString(PyExc_ValueError, "invalid file data in header");
350         return NULL;
351     }
352
353     return rpmfi_Wrap(subtype, fi);
354 }
355
356 static char rpmfi_doc[] =
357 "File iterator\n\n"
358 "DEPRECATED! This old API mixes storing and iterating over the meta data\n"
359 "of the files of a package. Use rpm.files and rpm.file data types as a\n"
360 "much cleaner API.\n\n"
361 "Iteration returns a tuple of\n(FN, FSize, FMode, FMtime, FFlags, FRdev, FInode, FNlink, FState,\n VFlags, FUser, FGroup, Digest)";
362
363 PyTypeObject rpmfi_Type = {
364         PyVarObject_HEAD_INIT(&PyType_Type, 0)
365         "rpm.fi",                       /* tp_name */
366         sizeof(rpmfiObject),            /* tp_basicsize */
367         0,                              /* tp_itemsize */
368         /* methods */
369         (destructor) rpmfi_dealloc,     /* tp_dealloc */
370         0,                              /* tp_print */
371         (getattrfunc)0,                 /* tp_getattr */
372         (setattrfunc)0,                 /* tp_setattr */
373         0,                              /* tp_compare */
374         (reprfunc)0,                    /* tp_repr */
375         0,                              /* tp_as_number */
376         0,                              /* tp_as_sequence */
377         &rpmfi_as_mapping,              /* tp_as_mapping */
378         (hashfunc)0,                    /* tp_hash */
379         (ternaryfunc)0,                 /* tp_call */
380         (reprfunc)0,                    /* tp_str */
381         PyObject_GenericGetAttr,        /* tp_getattro */
382         PyObject_GenericSetAttr,        /* tp_setattro */
383         0,                              /* tp_as_buffer */
384         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
385         rpmfi_doc,                      /* tp_doc */
386         0,                              /* tp_traverse */
387         0,                              /* tp_clear */
388         0,                              /* tp_richcompare */
389         0,                              /* tp_weaklistoffset */
390         PyObject_SelfIter,              /* tp_iter */
391         (iternextfunc) rpmfi_iternext,  /* tp_iternext */
392         rpmfi_methods,                  /* tp_methods */
393         0,                              /* tp_members */
394         0,                              /* tp_getset */
395         0,                              /* tp_base */
396         0,                              /* tp_dict */
397         0,                              /* tp_descr_get */
398         0,                              /* tp_descr_set */
399         0,                              /* tp_dictoffset */
400         (initproc) rpmfi_init,          /* tp_init */
401         0,                              /* tp_alloc */
402         (newfunc) rpmfi_new,            /* tp_new */
403         0,                              /* tp_free */
404         0,                              /* tp_is_gc */
405 };
406
407 /* ---------- */
408
409 rpmfi fiFromFi(rpmfiObject * s)
410 {
411     return s->fi;
412 }
413
414 PyObject * rpmfi_Wrap(PyTypeObject *subtype, rpmfi fi)
415 {
416     rpmfiObject *s = (rpmfiObject *)subtype->tp_alloc(subtype, 0);
417     if (s == NULL) return NULL;
418
419     s->fi = fi;
420     s->active = 0;
421     return (PyObject *) s;
422 }
423