rpm/python/rpmfd-py.c

333 lines
6.4 KiB
C

/** \ingroup py_c
* \file python/rpmfd-py.c
*/
#include "system.h"
#include <glob.h> /* XXX rpmio.h */
#include <dirent.h> /* XXX rpmio.h */
#include <rpmio_internal.h>
#include <rpmlib.h> /* XXX _free */
#include "header-py.h" /* XXX pyrpmError */
#include "rpmfd-py.h"
#include "debug.h"
/*@access FD_t @*/
/*@unchecked@*/
static int _rpmfd_debug = 1;
/** \ingroup python
* \name Class: Rpmfd
* \class Rpmfd
* \brief An python rpm.fd object represents an rpm I/O handle.
*/
/*@null@*/
static PyObject *
rpmfd_Debug(/*@unused@*/ rpmfdObject * s, PyObject * args)
/*@globals _Py_NoneStruct @*/
/*@modifies _Py_NoneStruct @*/
{
if (!PyArg_ParseTuple(args, "i", &_rpmfd_debug)) return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/**
*/
typedef struct FDlist_t FDlist;
/**
*/
struct FDlist_t {
FILE * f;
FD_t fd;
const char * note;
FDlist * next;
} ;
/**
*/
static FDlist *fdhead = NULL;
/**
*/
static FDlist *fdtail = NULL;
/**
*/
static int closeCallback(FILE * f)
/*@globals fdhead @*/
/*@modifies fdhead @*/
{
FDlist *node, *last;
node = fdhead;
last = NULL;
while (node) {
if (node->f == f)
break;
last = node;
node = node->next;
}
/*@-branchstate@*/
if (node) {
if (last)
last->next = node->next;
else
fdhead = node->next;
node->note = _free (node->note);
node->fd = fdLink(node->fd, "closeCallback");
(void) Fclose (node->fd);
while (node->fd)
node->fd = fdFree(node->fd, "closeCallback");
node = _free (node);
}
/*@=branchstate@*/
return 0;
}
/**
*/
/*@null@*/
static PyObject *
rpmfd_Fopen(/*@unused@*/ PyObject * s, PyObject * args)
/*@globals fdhead, fdtail @*/
/*@modifies fdhead, fdtail @*/
{
char * path;
char * mode = "r.ufdio";
FDlist *node;
if (!PyArg_ParseTuple(args, "s|s", &path, &mode))
return NULL;
node = xmalloc (sizeof(FDlist));
node->fd = Fopen(path, mode);
node->fd = fdLink(node->fd, "doFopen");
node->note = xstrdup (path);
if (!node->fd) {
(void) PyErr_SetFromErrno(pyrpmError);
node = _free (node);
return NULL;
}
if (Ferror(node->fd)) {
const char *err = Fstrerror(node->fd);
node = _free(node);
if (err)
PyErr_SetString(pyrpmError, err);
return NULL;
}
node->f = fdGetFp(node->fd);
if (!node->f) {
PyErr_SetString(pyrpmError, "FD_t has no FILE*");
free(node);
return NULL;
}
node->next = NULL;
/*@-branchstate@*/
if (!fdhead) {
fdhead = fdtail = node;
} else if (fdtail) {
fdtail->next = node;
} else {
fdhead = node;
}
/*@=branchstate@*/
fdtail = node;
return PyFile_FromFile (node->f, path, mode, closeCallback);
}
/** \ingroup py_c
*/
/*@-fullinitblock@*/
/*@unchecked@*/ /*@observer@*/
static struct PyMethodDef rpmfd_methods[] = {
{"Debug", (PyCFunction)rpmfd_Debug, METH_VARARGS,
NULL},
{"Fopen", (PyCFunction)rpmfd_Fopen, METH_VARARGS,
NULL},
{NULL, NULL} /* sentinel */
};
/*@=fullinitblock@*/
/* ---------- */
/** \ingroup py_c
*/
static void
rpmfd_dealloc(/*@only@*/ /*@null@*/ rpmfdObject * s)
/*@modifies s @*/
{
if (s) {
Fclose(s->fd);
s->fd = NULL;
PyObject_Del(s);
}
}
static PyObject * rpmfd_getattro(PyObject * o, PyObject * n)
/*@*/
{
return PyObject_GenericGetAttr(o, n);
}
static int rpmfd_setattro(PyObject * o, PyObject * n, PyObject * v)
/*@*/
{
return PyObject_GenericSetAttr(o, n, v);
}
/** \ingroup py_c
*/
static int rpmfd_init(rpmfdObject * s, PyObject *args, PyObject *kwds)
/*@modifies s @*/
{
char * path;
char * mode = "r.ufdio";
if (_rpmfd_debug)
fprintf(stderr, "*** rpmfd_init(%p,%p,%p)\n", s, args, kwds);
if (!PyArg_ParseTuple(args, "s|s:rpmfd_init", &path, &mode))
return -1;
s->fd = Fopen(path, mode);
if (s->fd == NULL) {
(void) PyErr_SetFromErrno(pyrpmError);
return -1;
}
if (Ferror(s->fd)) {
const char *err = Fstrerror(s->fd);
if (s->fd)
Fclose(s->fd);
if (err)
PyErr_SetString(pyrpmError, err);
return -1;
}
return 0;
}
/** \ingroup py_c
*/
static void rpmfd_free(/*@only@*/ rpmfdObject * s)
/*@modifies s @*/
{
if (_rpmfd_debug)
fprintf(stderr, "%p -- fd %p\n", s, s->fd);
if (s->fd)
Fclose(s->fd);
PyObject_Del((PyObject *)s);
}
/** \ingroup py_c
*/
static PyObject * rpmfd_alloc(PyTypeObject * subtype, int nitems)
/*@*/
{
PyObject * s = PyType_GenericAlloc(subtype, nitems);
if (_rpmfd_debug)
fprintf(stderr, "*** rpmfd_alloc(%p,%d) ret %p\n", subtype, nitems, s);
return s;
}
/** \ingroup py_c
*/
/*@null@*/
static rpmfdObject * rpmfd_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds)
/*@*/
{
rpmfdObject * s = PyObject_New(rpmfdObject, subtype);
/* Perform additional initialization. */
if (rpmfd_init(s, args, kwds) < 0) {
rpmfd_free(s);
return NULL;
}
if (_rpmfd_debug)
fprintf(stderr, "%p ++ fd %p\n", s, s->fd);
return s;
}
/**
*/
/*@unchecked@*/ /*@observer@*/
static char rpmfd_doc[] =
"";
/** \ingroup py_c
*/
/*@-fullinitblock@*/
PyTypeObject rpmfd_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
"rpm.fd", /* tp_name */
sizeof(rpmfdObject), /* tp_size */
0, /* tp_itemsize */
/* methods */
(destructor) rpmfd_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)0, /* tp_getattr */
(setattrfunc)0, /* tp_setattr */
(cmpfunc)0, /* tp_compare */
(reprfunc)0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
(reprfunc)0, /* tp_str */
(getattrofunc) rpmfd_getattro, /* tp_getattro */
(setattrofunc) rpmfd_setattro, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
rpmfd_doc, /* tp_doc */
#if Py_TPFLAGS_HAVE_ITER
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
rpmfd_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc) rpmfd_init, /* tp_init */
(allocfunc) rpmfd_alloc, /* tp_alloc */
(newfunc) rpmfd_new, /* tp_new */
rpmfd_free, /* tp_free */
0, /* tp_is_gc */
#endif
};
/*@=fullinitblock@*/
rpmfdObject * rpmfd_Wrap(FD_t fd)
{
rpmfdObject *s = PyObject_New(rpmfdObject, &rpmfd_Type);
if (s == NULL)
return NULL;
s->fd = fd;
return s;
}