rpm  4.5
rpmfd-py.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <glob.h> /* XXX rpmio.h */
8 #include <dirent.h> /* XXX rpmio.h */
9 #include <rpmio_internal.h>
10 
11 #include <rpmlib.h> /* XXX _free */
12 
13 #include "header-py.h" /* XXX pyrpmError */
14 #include "rpmfd-py.h"
15 
16 #include "debug.h"
17 
18 /*@access FD_t @*/
19 
20 /*@unchecked@*/
21 static int _rpmfd_debug = 1;
22 
31 typedef struct FDlist_t FDlist;
32 
35 struct FDlist_t {
36  FILE * f;
38  const char * note;
40 } ;
41 
44 static FDlist *fdhead = NULL;
45 
48 static FDlist *fdtail = NULL;
49 
52 static int closeCallback(FILE * f)
53  /*@globals fdhead @*/
54  /*@modifies fdhead @*/
55 {
56  FDlist *node, *last;
57 
58  node = fdhead;
59  last = NULL;
60  while (node) {
61  if (node->f == f)
62  break;
63  last = node;
64  node = node->next;
65  }
66 /*@-branchstate@*/
67  if (node) {
68  if (last)
69  last->next = node->next;
70  else
71  fdhead = node->next;
72  node->note = _free (node->note);
73  node->fd = fdLink(node->fd, "closeCallback");
74  (void) Fclose (node->fd);
75  while (node->fd)
76  node->fd = fdFree(node->fd, "closeCallback");
77  node = _free (node);
78  }
79 /*@=branchstate@*/
80  return 0;
81 }
82 
89 /*@null@*/
90 static PyObject *
91 rpmfd_Debug(/*@unused@*/ rpmfdObject * s, PyObject * args, PyObject * kwds)
92  /*@globals _Py_NoneStruct @*/
93  /*@modifies _Py_NoneStruct @*/
94 {
95  char * kwlist[] = {"debugLevel", NULL};
96 
97  if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &_rpmfd_debug))
98  return NULL;
99 
100  Py_INCREF(Py_None);
101  return Py_None;
102 }
103 
106 /*@null@*/
107 static PyObject *
108 rpmfd_Fopen(/*@unused@*/ PyObject * s, PyObject * args, PyObject * kwds)
109  /*@globals fdhead, fdtail @*/
110  /*@modifies fdhead, fdtail @*/
111 {
112  char * path;
113  char * mode = "r";
114  FDlist *node;
115  char * kwlist[] = {"path", "mode", NULL};
116 
117  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s", kwlist, &path, &mode))
118  return NULL;
119 
120  node = xmalloc (sizeof(FDlist));
121 
122  node->fd = Fopen(path, mode);
123  node->fd = fdLink(node->fd, "doFopen");
124  node->note = xstrdup (path);
125 
126  if (!node->fd) {
127  (void) PyErr_SetFromErrno(pyrpmError);
128  node = _free (node);
129  return NULL;
130  }
131 
132  if (Ferror(node->fd)) {
133  const char *err = Fstrerror(node->fd);
134  node = _free(node);
135  if (err)
136  PyErr_SetString(pyrpmError, err);
137  return NULL;
138  }
139 
140  node->f = fdGetFp(node->fd);
141  if (!node->f) {
142  PyErr_SetString(pyrpmError, "FD_t has no FILE*");
143  free(node);
144  return NULL;
145  }
146 
147  node->next = NULL;
148 /*@-branchstate@*/
149  if (!fdhead) {
150  fdhead = fdtail = node;
151  } else if (fdtail) {
152  fdtail->next = node;
153  } else {
154  fdhead = node;
155  }
156 /*@=branchstate@*/
157  fdtail = node;
158 
159  return PyFile_FromFile (node->f, path, mode, closeCallback);
160 }
161 
166 /*@-fullinitblock@*/
167 /*@unchecked@*/ /*@observer@*/
168 static struct PyMethodDef rpmfd_methods[] = {
169  {"Debug", (PyCFunction)rpmfd_Debug, METH_VARARGS|METH_KEYWORDS,
170  NULL},
171  {"Fopen", (PyCFunction)rpmfd_Fopen, METH_VARARGS|METH_KEYWORDS,
172  NULL},
173  {NULL, NULL} /* sentinel */
174 };
175 /*@=fullinitblock@*/
176 
177 /* ---------- */
178 
181 static void
182 rpmfd_dealloc(/*@only@*/ /*@null@*/ rpmfdObject * s)
183  /*@modifies s @*/
184 {
185  if (s) {
186  Fclose(s->fd);
187  s->fd = NULL;
188  PyObject_Del(s);
189  }
190 }
191 
192 static PyObject * rpmfd_getattro(PyObject * o, PyObject * n)
193  /*@*/
194 {
195  return PyObject_GenericGetAttr(o, n);
196 }
197 
198 static int rpmfd_setattro(PyObject * o, PyObject * n, PyObject * v)
199  /*@*/
200 {
201  return PyObject_GenericSetAttr(o, n, v);
202 }
203 
206 static int rpmfd_init(rpmfdObject * s, PyObject *args, PyObject *kwds)
207  /*@modifies s @*/
208 {
209  char * path;
210  char * mode = "r";
211  char * kwlist[] = {"path", "mode", NULL};
212 
213 if (_rpmfd_debug)
214 fprintf(stderr, "*** rpmfd_init(%p,%p,%p)\n", s, args, kwds);
215 
216  if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:rpmfd_init", kwlist,
217  &path, &mode))
218  return -1;
219 
220  s->fd = Fopen(path, mode);
221 
222  if (s->fd == NULL) {
223  (void) PyErr_SetFromErrno(pyrpmError);
224  return -1;
225  }
226 
227  if (Ferror(s->fd)) {
228  const char *err = Fstrerror(s->fd);
229  if (s->fd)
230  Fclose(s->fd);
231  if (err)
232  PyErr_SetString(pyrpmError, err);
233  return -1;
234  }
235  return 0;
236 }
237 
240 static void rpmfd_free(/*@only@*/ rpmfdObject * s)
241  /*@modifies s @*/
242 {
243 if (_rpmfd_debug)
244 fprintf(stderr, "%p -- fd %p\n", s, s->fd);
245  if (s->fd)
246  Fclose(s->fd);
247 
248  PyObject_Del((PyObject *)s);
249 }
250 
253 static PyObject * rpmfd_alloc(PyTypeObject * subtype, int nitems)
254  /*@*/
255 {
256  PyObject * s = PyType_GenericAlloc(subtype, nitems);
257 
258 if (_rpmfd_debug)
259 fprintf(stderr, "*** rpmfd_alloc(%p,%d) ret %p\n", subtype, nitems, s);
260  return s;
261 }
262 
265 /*@null@*/
266 static rpmfdObject * rpmfd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
267  /*@*/
268 {
269  rpmfdObject * s = PyObject_New(rpmfdObject, subtype);
270 
271  /* Perform additional initialization. */
272  if (rpmfd_init(s, args, kwds) < 0) {
273  rpmfd_free(s);
274  return NULL;
275  }
276 
277 if (_rpmfd_debug)
278 fprintf(stderr, "%p ++ fd %p\n", s, s->fd);
279 
280  return s;
281 }
282 
285 /*@unchecked@*/ /*@observer@*/
286 static char rpmfd_doc[] =
287 "";
288 
291 /*@-fullinitblock@*/
292 PyTypeObject rpmfd_Type = {
293  PyObject_HEAD_INIT(&PyType_Type)
294  0, /* ob_size */
295  "rpm.fd", /* tp_name */
296  sizeof(rpmfdObject), /* tp_size */
297  0, /* tp_itemsize */
298  /* methods */
299  (destructor) rpmfd_dealloc, /* tp_dealloc */
300  0, /* tp_print */
301  (getattrfunc)0, /* tp_getattr */
302  (setattrfunc)0, /* tp_setattr */
303  (cmpfunc)0, /* tp_compare */
304  (reprfunc)0, /* tp_repr */
305  0, /* tp_as_number */
306  0, /* tp_as_sequence */
307  0, /* tp_as_mapping */
308  (hashfunc)0, /* tp_hash */
309  (ternaryfunc)0, /* tp_call */
310  (reprfunc)0, /* tp_str */
311  (getattrofunc) rpmfd_getattro, /* tp_getattro */
312  (setattrofunc) rpmfd_setattro, /* tp_setattro */
313  0, /* tp_as_buffer */
314  Py_TPFLAGS_DEFAULT, /* tp_flags */
315  rpmfd_doc, /* tp_doc */
316 #if Py_TPFLAGS_HAVE_ITER
317  0, /* tp_traverse */
318  0, /* tp_clear */
319  0, /* tp_richcompare */
320  0, /* tp_weaklistoffset */
321  0, /* tp_iter */
322  0, /* tp_iternext */
323  rpmfd_methods, /* tp_methods */
324  0, /* tp_members */
325  0, /* tp_getset */
326  0, /* tp_base */
327  0, /* tp_dict */
328  0, /* tp_descr_get */
329  0, /* tp_descr_set */
330  0, /* tp_dictoffset */
331  (initproc) rpmfd_init, /* tp_init */
332  (allocfunc) rpmfd_alloc, /* tp_alloc */
333  (newfunc) rpmfd_new, /* tp_new */
334  rpmfd_free, /* tp_free */
335  0, /* tp_is_gc */
336 #endif
337 };
338 /*@=fullinitblock@*/
339 
341 {
342  rpmfdObject *s = PyObject_New(rpmfdObject, &rpmfd_Type);
343  if (s == NULL)
344  return NULL;
345  s->fd = fd;
346  return s;
347 }