LCOV - code coverage report
Current view: | top level - Modules - grpmodule.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 20 | 138 | 14.5 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 6 | 10 | 60.0 %
|  |  | Branches: | 6 | 72 | 8.3 %

               Branch data     Line data    Source code
           1                 :            :
           2                 :            : /* UNIX group file access module */
           3                 :            :
           4                 :            : #include "Python.h"
           5                 :            : #include "posixmodule.h"
           6                 :            :
           7                 :            : #include <grp.h>
           8                 :            :
           9                 :            : #include "clinic/grpmodule.c.h"
          10                 :            : /*[clinic input]
          11                 :            : module grp
          12                 :            : [clinic start generated code]*/
          13                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=cade63f2ed1bd9f8]*/
          14                 :            :
          15                 :            : static PyStructSequence_Field struct_group_type_fields[] = {
          16                 :            :    {"gr_name", "group name"},
          17                 :            :    {"gr_passwd", "password"},
          18                 :            :    {"gr_gid", "group id"},
          19                 :            :    {"gr_mem", "group members"},
          20                 :            :    {0}
          21                 :            : };
          22                 :            :
          23                 :            : PyDoc_STRVAR(struct_group__doc__,
          24                 :            : "grp.struct_group: Results from getgr*() routines.\n\n\
          25                 :            : This object may be accessed either as a tuple of\n\
          26                 :            :   (gr_name,gr_passwd,gr_gid,gr_mem)\n\
          27                 :            : or via the object attributes as named in the above tuple.\n");
          28                 :            :
          29                 :            : static PyStructSequence_Desc struct_group_type_desc = {
          30                 :            :    "grp.struct_group",
          31                 :            :    struct_group__doc__,
          32                 :            :    struct_group_type_fields,
          33                 :            :    4,
          34                 :            : };
          35                 :            :
          36                 :            :
          37                 :            : typedef struct {
          38                 :            :   PyTypeObject *StructGrpType;
          39                 :            : } grpmodulestate;
          40                 :            :
          41                 :            : static inline grpmodulestate*
          42                 :         15 : get_grp_state(PyObject *module)
          43                 :            : {
          44                 :         15 :     void *state = PyModule_GetState(module);
          45                 :            :     assert(state != NULL);
          46                 :         15 :     return (grpmodulestate *)state;
          47                 :            : }
          48                 :            :
          49                 :            : static struct PyModuleDef grpmodule;
          50                 :            :
          51                 :            : #define DEFAULT_BUFFER_SIZE 1024
          52                 :            :
          53                 :            : static PyObject *
          54                 :          0 : mkgrent(PyObject *module, struct group *p)
          55                 :            : {
          56                 :          0 :     int setIndex = 0;
          57                 :            :     PyObject *v, *w;
          58                 :            :     char **member;
          59                 :            :
          60                 :          0 :     v = PyStructSequence_New(get_grp_state(module)->StructGrpType);
          61         [ #  # ]:          0 :     if (v == NULL)
          62                 :          0 :         return NULL;
          63                 :            :
          64         [ #  # ]:          0 :     if ((w = PyList_New(0)) == NULL) {
          65                 :          0 :         Py_DECREF(v);
          66                 :          0 :         return NULL;
          67                 :            :     }
          68         [ #  # ]:          0 :     for (member = p->gr_mem; *member != NULL; member++) {
          69                 :          0 :         PyObject *x = PyUnicode_DecodeFSDefault(*member);
          70   [ #  #  #  # ]:          0 :         if (x == NULL || PyList_Append(w, x) != 0) {
          71                 :          0 :             Py_XDECREF(x);
          72                 :          0 :             Py_DECREF(w);
          73                 :          0 :             Py_DECREF(v);
          74                 :          0 :             return NULL;
          75                 :            :         }
          76                 :          0 :         Py_DECREF(x);
          77                 :            :     }
          78                 :            :
          79                 :            : #define SET(i,val) PyStructSequence_SET_ITEM(v, i, val)
          80                 :          0 :     SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_name));
          81         [ #  # ]:          0 :     if (p->gr_passwd)
          82                 :          0 :             SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_passwd));
          83                 :            :     else {
          84                 :          0 :             SET(setIndex++, Py_None);
          85                 :          0 :             Py_INCREF(Py_None);
          86                 :            :     }
          87                 :          0 :     SET(setIndex++, _PyLong_FromGid(p->gr_gid));
          88                 :          0 :     SET(setIndex++, w);
          89                 :            : #undef SET
          90                 :            :
          91         [ #  # ]:          0 :     if (PyErr_Occurred()) {
          92                 :          0 :         Py_DECREF(v);
          93                 :          0 :         return NULL;
          94                 :            :     }
          95                 :            :
          96                 :          0 :     return v;
          97                 :            : }
          98                 :            :
          99                 :            : /*[clinic input]
         100                 :            : grp.getgrgid
         101                 :            :
         102                 :            :     id: object
         103                 :            :
         104                 :            : Return the group database entry for the given numeric group ID.
         105                 :            :
         106                 :            : If id is not valid, raise KeyError.
         107                 :            : [clinic start generated code]*/
         108                 :            :
         109                 :            : static PyObject *
         110                 :          0 : grp_getgrgid_impl(PyObject *module, PyObject *id)
         111                 :            : /*[clinic end generated code: output=30797c289504a1ba input=15fa0e2ccf5cda25]*/
         112                 :            : {
         113                 :          0 :     PyObject *retval = NULL;
         114                 :          0 :     int nomem = 0;
         115                 :          0 :     char *buf = NULL, *buf2 = NULL;
         116                 :            :     gid_t gid;
         117                 :            :     struct group *p;
         118                 :            :
         119         [ #  # ]:          0 :     if (!_Py_Gid_Converter(id, &gid)) {
         120                 :          0 :         return NULL;
         121                 :            :     }
         122                 :            : #ifdef HAVE_GETGRGID_R
         123                 :            :     int status;
         124                 :            :     Py_ssize_t bufsize;
         125                 :            :     /* Note: 'grp' will be used via pointer 'p' on getgrgid_r success. */
         126                 :            :     struct group grp;
         127                 :            :
         128                 :          0 :     Py_BEGIN_ALLOW_THREADS
         129                 :          0 :     bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
         130         [ #  # ]:          0 :     if (bufsize == -1) {
         131                 :          0 :         bufsize = DEFAULT_BUFFER_SIZE;
         132                 :            :     }
         133                 :            :
         134                 :            :     while (1) {
         135                 :          0 :         buf2 = PyMem_RawRealloc(buf, bufsize);
         136         [ #  # ]:          0 :         if (buf2 == NULL) {
         137                 :          0 :             p = NULL;
         138                 :          0 :             nomem = 1;
         139                 :          0 :             break;
         140                 :            :         }
         141                 :          0 :         buf = buf2;
         142                 :          0 :         status = getgrgid_r(gid, &grp, buf, bufsize, &p);
         143         [ #  # ]:          0 :         if (status != 0) {
         144                 :          0 :             p = NULL;
         145                 :            :         }
         146   [ #  #  #  # ]:          0 :         if (p != NULL || status != ERANGE) {
         147                 :            :             break;
         148                 :            :         }
         149         [ #  # ]:          0 :         if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
         150                 :          0 :             nomem = 1;
         151                 :          0 :             break;
         152                 :            :         }
         153                 :          0 :         bufsize <<= 1;
         154                 :            :     }
         155                 :            :
         156                 :          0 :     Py_END_ALLOW_THREADS
         157                 :            : #else
         158                 :            :     p = getgrgid(gid);
         159                 :            : #endif
         160         [ #  # ]:          0 :     if (p == NULL) {
         161                 :          0 :         PyMem_RawFree(buf);
         162         [ #  # ]:          0 :         if (nomem == 1) {
         163                 :          0 :             return PyErr_NoMemory();
         164                 :            :         }
         165                 :          0 :         PyObject *gid_obj = _PyLong_FromGid(gid);
         166         [ #  # ]:          0 :         if (gid_obj == NULL)
         167                 :          0 :             return NULL;
         168                 :          0 :         PyErr_Format(PyExc_KeyError, "getgrgid(): gid not found: %S", gid_obj);
         169                 :          0 :         Py_DECREF(gid_obj);
         170                 :          0 :         return NULL;
         171                 :            :     }
         172                 :          0 :     retval = mkgrent(module, p);
         173                 :            : #ifdef HAVE_GETGRGID_R
         174                 :          0 :     PyMem_RawFree(buf);
         175                 :            : #endif
         176                 :          0 :     return retval;
         177                 :            : }
         178                 :            :
         179                 :            : /*[clinic input]
         180                 :            : grp.getgrnam
         181                 :            :
         182                 :            :     name: unicode
         183                 :            :
         184                 :            : Return the group database entry for the given group name.
         185                 :            :
         186                 :            : If name is not valid, raise KeyError.
         187                 :            : [clinic start generated code]*/
         188                 :            :
         189                 :            : static PyObject *
         190                 :          0 : grp_getgrnam_impl(PyObject *module, PyObject *name)
         191                 :            : /*[clinic end generated code: output=67905086f403c21c input=08ded29affa3c863]*/
         192                 :            : {
         193                 :          0 :     char *buf = NULL, *buf2 = NULL, *name_chars;
         194                 :          0 :     int nomem = 0;
         195                 :            :     struct group *p;
         196                 :          0 :     PyObject *bytes, *retval = NULL;
         197                 :            :
         198         [ #  # ]:          0 :     if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL)
         199                 :          0 :         return NULL;
         200                 :            :     /* check for embedded null bytes */
         201         [ #  # ]:          0 :     if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1)
         202                 :          0 :         goto out;
         203                 :            : #ifdef HAVE_GETGRNAM_R
         204                 :            :     int status;
         205                 :            :     Py_ssize_t bufsize;
         206                 :            :     /* Note: 'grp' will be used via pointer 'p' on getgrnam_r success. */
         207                 :            :     struct group grp;
         208                 :            :
         209                 :          0 :     Py_BEGIN_ALLOW_THREADS
         210                 :          0 :     bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
         211         [ #  # ]:          0 :     if (bufsize == -1) {
         212                 :          0 :         bufsize = DEFAULT_BUFFER_SIZE;
         213                 :            :     }
         214                 :            :
         215                 :            :     while(1) {
         216                 :          0 :         buf2 = PyMem_RawRealloc(buf, bufsize);
         217         [ #  # ]:          0 :         if (buf2 == NULL) {
         218                 :          0 :             p = NULL;
         219                 :          0 :             nomem = 1;
         220                 :          0 :             break;
         221                 :            :         }
         222                 :          0 :         buf = buf2;
         223                 :          0 :         status = getgrnam_r(name_chars, &grp, buf, bufsize, &p);
         224         [ #  # ]:          0 :         if (status != 0) {
         225                 :          0 :             p = NULL;
         226                 :            :         }
         227   [ #  #  #  # ]:          0 :         if (p != NULL || status != ERANGE) {
         228                 :            :             break;
         229                 :            :         }
         230         [ #  # ]:          0 :         if (bufsize > (PY_SSIZE_T_MAX >> 1)) {
         231                 :          0 :             nomem = 1;
         232                 :          0 :             break;
         233                 :            :         }
         234                 :          0 :         bufsize <<= 1;
         235                 :            :     }
         236                 :            :
         237                 :          0 :     Py_END_ALLOW_THREADS
         238                 :            : #else
         239                 :            :     p = getgrnam(name_chars);
         240                 :            : #endif
         241         [ #  # ]:          0 :     if (p == NULL) {
         242         [ #  # ]:          0 :         if (nomem == 1) {
         243                 :          0 :             PyErr_NoMemory();
         244                 :            :         }
         245                 :            :         else {
         246                 :          0 :             PyErr_Format(PyExc_KeyError, "getgrnam(): name not found: %R", name);
         247                 :            :         }
         248                 :          0 :         goto out;
         249                 :            :     }
         250                 :          0 :     retval = mkgrent(module, p);
         251                 :          0 : out:
         252                 :          0 :     PyMem_RawFree(buf);
         253                 :          0 :     Py_DECREF(bytes);
         254                 :          0 :     return retval;
         255                 :            : }
         256                 :            :
         257                 :            : /*[clinic input]
         258                 :            : grp.getgrall
         259                 :            :
         260                 :            : Return a list of all available group entries, in arbitrary order.
         261                 :            :
         262                 :            : An entry whose name starts with '+' or '-' represents an instruction
         263                 :            : to use YP/NIS and may not be accessible via getgrnam or getgrgid.
         264                 :            : [clinic start generated code]*/
         265                 :            :
         266                 :            : static PyObject *
         267                 :          0 : grp_getgrall_impl(PyObject *module)
         268                 :            : /*[clinic end generated code: output=585dad35e2e763d7 input=d7df76c825c367df]*/
         269                 :            : {
         270                 :            :     PyObject *d;
         271                 :            :     struct group *p;
         272                 :            :
         273         [ #  # ]:          0 :     if ((d = PyList_New(0)) == NULL)
         274                 :          0 :         return NULL;
         275                 :          0 :     setgrent();
         276         [ #  # ]:          0 :     while ((p = getgrent()) != NULL) {
         277                 :          0 :         PyObject *v = mkgrent(module, p);
         278   [ #  #  #  # ]:          0 :         if (v == NULL || PyList_Append(d, v) != 0) {
         279                 :          0 :             Py_XDECREF(v);
         280                 :          0 :             Py_DECREF(d);
         281                 :          0 :             endgrent();
         282                 :          0 :             return NULL;
         283                 :            :         }
         284                 :          0 :         Py_DECREF(v);
         285                 :            :     }
         286                 :          0 :     endgrent();
         287                 :          0 :     return d;
         288                 :            : }
         289                 :            :
         290                 :            : static PyMethodDef grp_methods[] = {
         291                 :            :     GRP_GETGRGID_METHODDEF
         292                 :            :     GRP_GETGRNAM_METHODDEF
         293                 :            :     GRP_GETGRALL_METHODDEF
         294                 :            :     {NULL, NULL}
         295                 :            : };
         296                 :            :
         297                 :            : PyDoc_STRVAR(grp__doc__,
         298                 :            : "Access to the Unix group database.\n\
         299                 :            : \n\
         300                 :            : Group entries are reported as 4-tuples containing the following fields\n\
         301                 :            : from the group database, in order:\n\
         302                 :            : \n\
         303                 :            :   gr_name   - name of the group\n\
         304                 :            :   gr_passwd - group password (encrypted); often empty\n\
         305                 :            :   gr_gid    - numeric ID of the group\n\
         306                 :            :   gr_mem    - list of members\n\
         307                 :            : \n\
         308                 :            : The gid is an integer, name and password are strings.  (Note that most\n\
         309                 :            : users are not explicitly listed as members of the groups they are in\n\
         310                 :            : according to the password database.  Check both databases to get\n\
         311                 :            : complete membership information.)");
         312                 :            :
         313                 :            : static int
         314                 :          1 : grpmodule_exec(PyObject *module)
         315                 :            : {
         316                 :          1 :     grpmodulestate *state = get_grp_state(module);
         317                 :            :
         318                 :          1 :     state->StructGrpType = PyStructSequence_NewType(&struct_group_type_desc);
         319         [ -  + ]:          1 :     if (state->StructGrpType == NULL) {
         320                 :          0 :         return -1;
         321                 :            :     }
         322         [ -  + ]:          1 :     if (PyModule_AddType(module, state->StructGrpType) < 0) {
         323                 :          0 :         return -1;
         324                 :            :     }
         325                 :          1 :     return 0;
         326                 :            : }
         327                 :            :
         328                 :            : static PyModuleDef_Slot grpmodule_slots[] = {
         329                 :            :     {Py_mod_exec, grpmodule_exec},
         330                 :            :     {0, NULL}
         331                 :            : };
         332                 :            :
         333                 :          6 : static int grpmodule_traverse(PyObject *m, visitproc visit, void *arg) {
         334   [ +  -  -  + ]:          6 :     Py_VISIT(get_grp_state(m)->StructGrpType);
         335                 :          6 :     return 0;
         336                 :            : }
         337                 :            :
         338                 :          2 : static int grpmodule_clear(PyObject *m) {
         339         [ +  + ]:          2 :     Py_CLEAR(get_grp_state(m)->StructGrpType);
         340                 :          2 :     return 0;
         341                 :            : }
         342                 :            :
         343                 :          1 : static void grpmodule_free(void *m) {
         344                 :          1 :     grpmodule_clear((PyObject *)m);
         345                 :          1 : }
         346                 :            :
         347                 :            : static struct PyModuleDef grpmodule = {
         348                 :            :     PyModuleDef_HEAD_INIT,
         349                 :            :     .m_name = "grp",
         350                 :            :     .m_doc = grp__doc__,
         351                 :            :     .m_size = sizeof(grpmodulestate),
         352                 :            :     .m_methods = grp_methods,
         353                 :            :     .m_slots = grpmodule_slots,
         354                 :            :     .m_traverse = grpmodule_traverse,
         355                 :            :     .m_clear = grpmodule_clear,
         356                 :            :     .m_free = grpmodule_free,
         357                 :            : };
         358                 :            :
         359                 :            : PyMODINIT_FUNC
         360                 :          1 : PyInit_grp(void)
         361                 :            : {
         362                 :          1 :    return PyModuleDef_Init(&grpmodule);
         363                 :            : }

Generated by: LCOV version 1.14