"Fossies" - the Fresh Open Source Software Archive

Member "rpm-4.15.0/python/rpmfd-py.c" (26 Sep 2019, 9266 Bytes) of package /linux/misc/rpm-4.15.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rpmfd-py.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.14.2.1_vs_4.15.0.

    1 
    2 #include "rpmsystem-py.h"
    3 #include <rpm/rpmstring.h>
    4 #include "header-py.h"  /* XXX for utf8FromPyObject() only */
    5 #include "rpmfd-py.h"
    6 
    7 struct rpmfdObject_s {
    8     PyObject_HEAD
    9     PyObject *md_dict;
   10     FD_t fd;
   11     char *mode;
   12     char *flags;
   13 };
   14 
   15 FD_t rpmfdGetFd(rpmfdObject *fdo)
   16 {
   17     return fdo->fd;
   18 }
   19 
   20 int rpmfdFromPyObject(PyObject *obj, rpmfdObject **fdop)
   21 {
   22     rpmfdObject *fdo = NULL;
   23 
   24     if (rpmfdObject_Check(obj)) {
   25     Py_INCREF(obj);
   26     fdo = (rpmfdObject *) obj;
   27     } else {
   28     fdo = (rpmfdObject *) PyObject_CallFunctionObjArgs((PyObject *)&rpmfd_Type,
   29                                                            obj, NULL);
   30     }
   31     if (fdo == NULL) return 0;
   32 
   33     if (Ferror(fdo->fd)) {
   34     PyErr_SetString(PyExc_IOError, Fstrerror(fdo->fd));
   35     Py_DECREF(fdo);
   36     return 0;
   37     }
   38     *fdop = fdo;
   39     return 1;
   40 }
   41 
   42 static PyObject *err_closed(void)
   43 {
   44     PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
   45     return NULL;
   46 }
   47 
   48 static FD_t openPath(const char *path, const char *mode)
   49 {
   50     FD_t fd;
   51     Py_BEGIN_ALLOW_THREADS
   52     fd = Fopen(path, mode);
   53     Py_END_ALLOW_THREADS;
   54     return fd;
   55 }
   56 
   57 static FD_t openFd(FD_t ofd, const char *mode)
   58 {
   59     FD_t fd;
   60     Py_BEGIN_ALLOW_THREADS
   61     fd = Fdopen(ofd, mode);
   62     Py_END_ALLOW_THREADS;
   63     return fd;
   64 }
   65 
   66 static int rpmfd_init(rpmfdObject *s, PyObject *args, PyObject *kwds)
   67 {
   68     char *kwlist[] = { "obj", "mode", "flags", NULL };
   69     const char *mode = "r";
   70     const char *flags = "ufdio";
   71     char *rpmio_mode = NULL;
   72     PyObject *fo = NULL;
   73     FD_t fd = NULL;
   74     int fdno;
   75 
   76     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ss", kwlist, 
   77                      &fo, &mode, &flags))
   78     return -1;
   79 
   80     rpmio_mode = rstrscat(NULL, mode, ".", flags, NULL);
   81 
   82     if (PyBytes_Check(fo)) {
   83     fd = openPath(PyBytes_AsString(fo), rpmio_mode);
   84     } else if (PyUnicode_Check(fo)) {
   85     PyObject *enc = NULL;
   86     int rc;
   87 #if PY_MAJOR_VERSION >= 3
   88     rc = PyUnicode_FSConverter(fo, &enc);
   89 #else
   90     rc = utf8FromPyObject(fo, &enc);
   91 #endif
   92     if (rc) {
   93         fd = openPath(PyBytes_AsString(enc), rpmio_mode);
   94         Py_DECREF(enc);
   95     }
   96     } else if (rpmfdObject_Check(fo)) {
   97     rpmfdObject *fdo = (rpmfdObject *)fo;
   98     fd = openFd(fdDup(Fileno(fdo->fd)), rpmio_mode);
   99     } else if ((fdno = PyObject_AsFileDescriptor(fo)) >= 0) {
  100     fd = openFd(fdDup(fdno), rpmio_mode);
  101     } else {
  102     PyErr_SetString(PyExc_TypeError, "path or file object expected");
  103     }
  104 
  105     if (fd != NULL) {
  106     Fclose(s->fd); /* in case __init__ was called again */
  107     free(s->mode);
  108     free(s->flags);
  109     s->fd = fd;
  110     s->mode = rstrdup(mode);
  111     s->flags = rstrdup(flags);
  112     } else {
  113     PyErr_SetString(PyExc_IOError, Fstrerror(fd));
  114     }
  115 
  116     free(rpmio_mode);
  117     return (fd == NULL) ? -1 : 0;
  118 }
  119 
  120 static PyObject *rpmfd_open(PyObject *cls, PyObject *args, PyObject *kwds)
  121 {
  122     return PyObject_Call(cls, args, kwds);
  123 }
  124 
  125 static PyObject *do_close(rpmfdObject *s)
  126 {
  127     /* mimic python fileobject: close on closed file is not an error */
  128     if (s->fd) {
  129     Py_BEGIN_ALLOW_THREADS
  130     Fclose(s->fd);
  131     Py_END_ALLOW_THREADS
  132     s->fd = NULL;
  133     }
  134     Py_RETURN_NONE;
  135 }
  136 
  137 static PyObject *rpmfd_close(rpmfdObject *s)
  138 {
  139     return do_close(s);
  140 }
  141 
  142 static void rpmfd_dealloc(rpmfdObject *s)
  143 {
  144     PyObject *res = do_close(s);
  145     Py_XDECREF(res);
  146     free(s->mode);
  147     free(s->flags);
  148     Py_TYPE(s)->tp_free((PyObject *)s);
  149 }
  150 
  151 static PyObject *rpmfd_fileno(rpmfdObject *s)
  152 {
  153     int fno;
  154     if (s->fd == NULL) return err_closed();
  155 
  156     Py_BEGIN_ALLOW_THREADS
  157     fno = Fileno(s->fd);
  158     Py_END_ALLOW_THREADS
  159 
  160     if (Ferror(s->fd)) {
  161     PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
  162     return NULL;
  163     }
  164     return Py_BuildValue("i", fno);
  165 }
  166 
  167 static PyObject *rpmfd_flush(rpmfdObject *s)
  168 {
  169     int rc;
  170 
  171     if (s->fd == NULL) return err_closed();
  172 
  173     Py_BEGIN_ALLOW_THREADS
  174     rc = Fflush(s->fd);
  175     Py_END_ALLOW_THREADS
  176 
  177     if (rc || Ferror(s->fd)) {
  178     PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
  179     return NULL;
  180     }
  181     Py_RETURN_NONE;
  182 }
  183 
  184 static PyObject *rpmfd_isatty(rpmfdObject *s)
  185 {
  186     int fileno;
  187     if (s->fd == NULL) return err_closed();
  188 
  189     Py_BEGIN_ALLOW_THREADS
  190     fileno = Fileno(s->fd);
  191     Py_END_ALLOW_THREADS
  192 
  193     if (Ferror(s->fd)) {
  194     PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
  195     return NULL;
  196     }
  197     return PyBool_FromLong(isatty(fileno));
  198 }
  199 
  200 static PyObject *rpmfd_seek(rpmfdObject *s, PyObject *args, PyObject *kwds)
  201 {
  202     char *kwlist[] = { "offset", "whence", NULL };
  203     off_t offset;
  204     int whence = SEEK_SET;
  205     int rc = 0;
  206 
  207     if (!PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwlist, 
  208                      &offset, &whence)) 
  209     return NULL;
  210 
  211     if (s->fd == NULL) return err_closed();
  212 
  213     Py_BEGIN_ALLOW_THREADS
  214     rc = Fseek(s->fd, offset, whence);
  215     Py_END_ALLOW_THREADS
  216     if (rc < 0 || Ferror(s->fd)) {
  217     PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
  218     return NULL;
  219     }
  220     Py_RETURN_NONE;
  221 }
  222 
  223 static PyObject *rpmfd_tell(rpmfdObject *s)
  224 {
  225     off_t offset;
  226     Py_BEGIN_ALLOW_THREADS
  227     offset = Ftell(s->fd);
  228     Py_END_ALLOW_THREADS
  229     return Py_BuildValue("L", offset);
  230     
  231 }
  232 
  233 static PyObject *rpmfd_read(rpmfdObject *s, PyObject *args, PyObject *kwds)
  234 {
  235     char *kwlist[] = { "size", NULL };
  236     char buf[BUFSIZ];
  237     ssize_t chunksize = sizeof(buf);
  238     ssize_t left = -1;
  239     ssize_t nb = 0;
  240     PyObject *res = NULL;
  241     
  242     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &left))
  243     return NULL;
  244 
  245     if (s->fd == NULL) return err_closed();
  246 
  247     /* ConcatAndDel() doesn't work on NULL string, meh */
  248     res = PyBytes_FromStringAndSize(NULL, 0);
  249     do {
  250     if (left >= 0 && left < chunksize)
  251         chunksize = left;
  252 
  253     Py_BEGIN_ALLOW_THREADS 
  254     nb = Fread(buf, 1, chunksize, s->fd);
  255     Py_END_ALLOW_THREADS 
  256 
  257     if (nb > 0) {
  258         PyObject *tmp = PyBytes_FromStringAndSize(buf, nb);
  259         PyBytes_ConcatAndDel(&res, tmp);
  260         left -= nb;
  261     }
  262     } while (nb > 0);
  263 
  264     if (Ferror(s->fd)) {
  265     PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
  266     Py_XDECREF(res);
  267     return NULL;
  268     } else {
  269     return res;
  270     }
  271 }
  272 
  273 static PyObject *rpmfd_write(rpmfdObject *s, PyObject *args, PyObject *kwds)
  274 {
  275 
  276     const char *buf = NULL;
  277     ssize_t size = 0;
  278     char *kwlist[] = { "buffer", NULL };
  279     ssize_t rc = 0;
  280 
  281     if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwlist, &buf, &size)) {
  282     return NULL;
  283     }
  284 
  285     if (s->fd == NULL) return err_closed();
  286 
  287     Py_BEGIN_ALLOW_THREADS 
  288     rc = Fwrite(buf, 1, size, s->fd);
  289     Py_END_ALLOW_THREADS 
  290 
  291     if (Ferror(s->fd)) {
  292     PyErr_SetString(PyExc_IOError, Fstrerror(s->fd));
  293     return NULL;
  294     }
  295     return Py_BuildValue("n", rc);
  296 }
  297 
  298 static char rpmfd_doc[] = "";
  299 
  300 static struct PyMethodDef rpmfd_methods[] = {
  301     { "open",   (PyCFunction) rpmfd_open,   METH_VARARGS|METH_KEYWORDS|METH_CLASS,
  302     NULL },
  303     { "close",  (PyCFunction) rpmfd_close,  METH_NOARGS,
  304     NULL },
  305     { "fileno", (PyCFunction) rpmfd_fileno, METH_NOARGS,
  306     NULL },
  307     { "flush",  (PyCFunction) rpmfd_flush,  METH_NOARGS,
  308     NULL },
  309     { "isatty", (PyCFunction) rpmfd_isatty, METH_NOARGS,
  310     NULL },
  311     { "read",   (PyCFunction) rpmfd_read,   METH_VARARGS|METH_KEYWORDS,
  312     NULL },
  313     { "seek",   (PyCFunction) rpmfd_seek,   METH_VARARGS|METH_KEYWORDS,
  314     NULL },
  315     { "tell",   (PyCFunction) rpmfd_tell,   METH_NOARGS,
  316     NULL },
  317     { "write",  (PyCFunction) rpmfd_write,  METH_VARARGS|METH_KEYWORDS,
  318     NULL },
  319     { NULL, NULL }
  320 };
  321 
  322 static PyObject *rpmfd_get_closed(rpmfdObject *s)
  323 {
  324     return PyBool_FromLong((s->fd == NULL));
  325 }
  326 
  327 static PyObject *rpmfd_get_name(rpmfdObject *s)
  328 {
  329     /* XXX: rpm returns non-paths with [mumble], python files use <mumble> */
  330     return utf8FromString(Fdescr(s->fd));
  331 }
  332 
  333 static PyObject *rpmfd_get_mode(rpmfdObject *s)
  334 {
  335     return utf8FromString(s->mode);
  336 }
  337 
  338 static PyObject *rpmfd_get_flags(rpmfdObject *s)
  339 {
  340     return utf8FromString(s->flags);
  341 }
  342 
  343 static PyGetSetDef rpmfd_getseters[] = {
  344     { "closed", (getter)rpmfd_get_closed, NULL, NULL },
  345     { "name", (getter)rpmfd_get_name, NULL, NULL },
  346     { "mode", (getter)rpmfd_get_mode, NULL, NULL },
  347     { "flags", (getter)rpmfd_get_flags, NULL, NULL },
  348     { NULL },
  349 };
  350 
  351 PyTypeObject rpmfd_Type = {
  352     PyVarObject_HEAD_INIT(&PyType_Type, 0)
  353     "rpm.fd",           /* tp_name */
  354     sizeof(rpmfdObject),        /* tp_size */
  355     0,              /* tp_itemsize */
  356     /* methods */
  357     (destructor) rpmfd_dealloc,     /* tp_dealloc */
  358     0,              /* tp_print */
  359     (getattrfunc)0,         /* tp_getattr */
  360     (setattrfunc)0,         /* tp_setattr */
  361     0,              /* tp_compare */
  362     (reprfunc)0,            /* tp_repr */
  363     0,              /* tp_as_number */
  364     0,              /* tp_as_sequence */
  365     0,              /* tp_as_mapping */
  366     (hashfunc)0,            /* tp_hash */
  367     (ternaryfunc)0,         /* tp_call */
  368     (reprfunc)0,            /* tp_str */
  369     PyObject_GenericGetAttr,    /* tp_getattro */
  370     PyObject_GenericSetAttr,    /* tp_setattro */
  371     0,              /* tp_as_buffer */
  372     Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
  373     rpmfd_doc,          /* tp_doc */
  374     0,              /* tp_traverse */
  375     0,              /* tp_clear */
  376     0,              /* tp_richcompare */
  377     0,              /* tp_weaklistoffset */
  378     0,              /* tp_iter */
  379     0,              /* tp_iternext */
  380     rpmfd_methods,          /* tp_methods */
  381     0,              /* tp_members */
  382     rpmfd_getseters,        /* tp_getset */
  383     0,              /* tp_base */
  384     0,              /* tp_dict */
  385     0,              /* tp_descr_get */
  386     0,              /* tp_descr_set */
  387     0,              /* tp_dictoffset */
  388     (initproc)rpmfd_init,       /* tp_init */
  389     (allocfunc)0,           /* tp_alloc */
  390     PyType_GenericNew,      /* tp_new */
  391     (freefunc)0,            /* tp_free */
  392     0,              /* tp_is_gc */
  393 };