root/lib/getgroups.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getgroups
  2. rpl_getgroups

     1 /* provide consistent interface to getgroups for systems that don't allow N==0
     2 
     3    Copyright (C) 1996, 1999, 2003, 2006-2023 Free Software Foundation,
     4    Inc.
     5 
     6    This file is free software: you can redistribute it and/or modify
     7    it under the terms of the GNU Lesser General Public License as
     8    published by the Free Software Foundation; either version 2.1 of the
     9    License, or (at your option) any later version.
    10 
    11    This file is distributed in the hope that it will be useful,
    12    but WITHOUT ANY WARRANTY; without even the implied warranty of
    13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14    GNU Lesser General Public License for more details.
    15 
    16    You should have received a copy of the GNU Lesser General Public License
    17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 /* written by Jim Meyering */
    20 
    21 #include <config.h>
    22 
    23 #include <unistd.h>
    24 
    25 #include <errno.h>
    26 #include <stdlib.h>
    27 #include <stdint.h>
    28 
    29 #if !HAVE_GETGROUPS
    30 
    31 /* Provide a stub that fails with ENOSYS, since there is no group
    32    information available on mingw.  */
    33 int
    34 getgroups (_GL_UNUSED int n, _GL_UNUSED GETGROUPS_T *groups)
    35 {
    36   errno = ENOSYS;
    37   return -1;
    38 }
    39 
    40 #else /* HAVE_GETGROUPS */
    41 
    42 # undef getgroups
    43 # ifndef GETGROUPS_ZERO_BUG
    44 #  define GETGROUPS_ZERO_BUG 0
    45 # endif
    46 
    47 /* On OS X 10.6 and later, use the usual getgroups, not the one
    48    supplied when _DARWIN_C_SOURCE is defined.  _DARWIN_C_SOURCE is
    49    normally defined, since it means "conform to POSIX, but add
    50    non-POSIX extensions even if that violates the POSIX namespace
    51    rules", which is what we normally want.  But with getgroups there
    52    is an inconsistency, and _DARWIN_C_SOURCE means "change getgroups()
    53    so that it no longer works right".  The BUGS section of compat(5)
    54    says that the behavior is dubious if you compile different sections
    55    of a program with different _DARWIN_C_SOURCE settings, so fix only
    56    the offending symbol.  */
    57 # ifdef __APPLE__
    58 int posix_getgroups (int, gid_t []) __asm ("_getgroups");
    59 #  define getgroups posix_getgroups
    60 # endif
    61 
    62 /* On at least NeXTstep 3.2, getgroups (0, NULL) always fails.
    63    On other systems, it returns the number of supplemental
    64    groups for the process.  This function handles that special case
    65    and lets the system-provided function handle all others.  However,
    66    it can fail with ENOMEM if memory is tight.  It is unspecified
    67    whether the effective group id is included in the list.  */
    68 
    69 int
    70 rpl_getgroups (int n, gid_t *group)
    71 {
    72   int n_groups;
    73   GETGROUPS_T *gbuf;
    74 
    75   if (n < 0)
    76     {
    77       errno = EINVAL;
    78       return -1;
    79     }
    80 
    81   if (n != 0 || !GETGROUPS_ZERO_BUG)
    82     {
    83       int result;
    84       if (sizeof *group == sizeof *gbuf)
    85         return getgroups (n, (GETGROUPS_T *) group);
    86 
    87       if (SIZE_MAX / sizeof *gbuf <= n)
    88         {
    89           errno = ENOMEM;
    90           return -1;
    91         }
    92       gbuf = malloc (n * sizeof *gbuf);
    93       if (!gbuf)
    94         return -1;
    95       result = getgroups (n, gbuf);
    96       if (0 <= result)
    97         {
    98           n = result;
    99           while (n--)
   100             group[n] = gbuf[n];
   101         }
   102       free (gbuf);
   103       return result;
   104     }
   105 
   106   n = 20;
   107   while (1)
   108     {
   109       /* No need to worry about address arithmetic overflow here,
   110          since the ancient systems that we're running on have low
   111          limits on the number of secondary groups.  */
   112       gbuf = malloc (n * sizeof *gbuf);
   113       if (!gbuf)
   114         return -1;
   115       n_groups = getgroups (n, gbuf);
   116       if (n_groups == -1 ? errno != EINVAL : n_groups < n)
   117         break;
   118       free (gbuf);
   119       n *= 2;
   120     }
   121 
   122   free (gbuf);
   123   return n_groups;
   124 }
   125 
   126 #endif /* HAVE_GETGROUPS */

/* [<][>][^][v][top][bottom][index][help] */