OpenCoverage

mgetgroups.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/mgetgroups.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* mgetgroups.c -- return a list of the groups a user or current process is in-
2-
3 Copyright (C) 2007-2018 Free Software Foundation, Inc.-
4-
5 This program is free software: you can redistribute it and/or modify-
6 it under the terms of the GNU General Public License as published by-
7 the Free Software Foundation, either version 3 of the License, or-
8 (at your option) any later version.-
9-
10 This program is distributed in the hope that it will be useful,-
11 but WITHOUT ANY WARRANTY; without even the implied warranty of-
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
13 GNU General Public License for more details.-
14-
15 You should have received a copy of the GNU General Public License-
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */-
17-
18/* Extracted from coreutils' src/id.c. */-
19-
20#include <config.h>-
21-
22#include "mgetgroups.h"-
23-
24#include <stdlib.h>-
25#include <unistd.h>-
26#include <stdint.h>-
27#include <string.h>-
28#include <errno.h>-
29#if HAVE_GETGROUPLIST-
30# include <grp.h>-
31#endif-
32-
33#include "getugroups.h"-
34#include "xalloc-oversized.h"-
35-
36/* Work around an incompatibility of OS X 10.11: getgrouplist-
37 accepts int *, not gid_t *, and int and gid_t differ in sign. */-
38#if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)-
39# pragma GCC diagnostic ignored "-Wpointer-sign"-
40#endif-
41-
42static gid_t *-
43realloc_groupbuf (gid_t *g, size_t num)-
44{-
45 if (xalloc_oversized (num, sizeof *g))
92233720368547...count); }))) {Description
TRUEnever evaluated
FALSEevaluated 115 times by 1 test
Evaluated by:
  • id
223372036854775807L)Description
TRUEnever evaluated
FALSEevaluated 115 times by 1 test
Evaluated by:
  • id
Description
TRUEnever evaluated
FALSEnever evaluated
0-115
46 {-
47 errno = ENOMEM;-
48 return NULL;
never executed: ((void *)0) ; }
0
49 }-
50-
51 return realloc (g, num * sizeof *g);
executed 115 times by 1 test
Executed by:
  • id
115
52}-
53-
54/* Like getugroups, but store the result in malloc'd storage.-
55 Set *GROUPS to the malloc'd list of all group IDs of which USERNAME-
56 is a member. If GID is not -1, store it first. GID should be the-
57 group ID (pw_gid) obtained from getpwuid, in case USERNAME is not-
58 listed in the groups database (e.g., /etc/groups). If USERNAME is-
59 NULL, store the supplementary groups of the current process, and GID-
60 should be -1 or the effective group ID (getegid). Upon failure,-
61 don't modify *GROUPS, set errno, and return -1. Otherwise, return-
62 the number of groups. The resulting list may contain duplicates,-
63 but adjacent members will be distinct. */-
64-
65int-
66mgetgroups (char const *username, gid_t gid, gid_t **groups)-
67{-
68 int max_n_groups;-
69 int ng;-
70 gid_t *g;-
71-
72#if HAVE_GETGROUPLIST-
73 /* We prefer to use getgrouplist if available, because it has better-
74 performance characteristics.-
75-
76 In glibc 2.3.2, getgrouplist is buggy. If you pass a zero as the-
77 length of the output buffer, getgrouplist will still write to the-
78 buffer. Contrary to what some versions of the getgrouplist-
79 manpage say, this doesn't happen with nonzero buffer sizes.-
80 Therefore our usage here just avoids a zero sized buffer. */-
81 if (username)
Description
TRUEevaluated 42 times by 1 test
Evaluated by:
  • id
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
16-42
82 {-
83 enum { N_GROUPS_INIT = 10 };-
84 max_n_groups = N_GROUPS_INIT;-
85-
86 g = realloc_groupbuf (NULL, max_n_groups);-
87 if (g == NULL)
((void *)0) )Description
TRUEnever evaluated
FALSEevaluated 42 times by 1 test
Evaluated by:
  • id
0-42
88 return -1;
never executed
0
89-
90 while (1)-
91 {-
92 gid_t *h;-
93 int last_n_groups = max_n_groups;-
94-
95 /* getgrouplist updates max_n_groups to num required. */-
96 ng = getgrouplist (username, gid, g, &max_n_groups);-
97-
98 /* Some systems (like Darwin) have a bug where they-
99 never increase max_n_groups. */-
100 if (ng < 0 && last_n_groups == max_n_groups)
x_n_grDescription
TRUEevaluated 15 times by 1 test
Evaluated by:
  • id
FALSEevaluated 42 times by 1 test
Evaluated by:
  • id
*= 2;Description
TRUEnever evaluated
FALSEevaluated 15 times by 1 test
Evaluated by:
  • id
0-42
101 max_n_groups *= 2;
never executed
0
102-
103 if ((h = realloc_groupbuf (g, max_n_groups)) == NULL)
((void *)0) )Description
TRUEnever evaluated
FALSEevaluated 57 times by 1 test
Evaluated by:
  • id
0-57
104 {-
105 int saved_errno = errno;-
106 free (g);-
107 errno = saved_errno;-
108 return -1;
never executed
0
109 }-
110 g = h;-
111-
112 if (0 <= ng)
Description
TRUEevaluated 42 times by 1 test
Evaluated by:
  • id
FALSEevaluated 15 times by 1 test
Evaluated by:
  • id
15-42
113 {-
114 *groups = g;-
115 /* On success some systems just return 0 from getgrouplist,-
116 so return max_n_groups rather than ng. */-
117 return max_n_groups;
executed 42 times by 1 test
Executed by:
  • id
42
118 }-
119 }
executed 15 times by 1 test
Executed by:
  • id
15
120 }
never executed
0
121 /* else no username, so fall through and use getgroups. */-
122#endif-
123-
124 max_n_groups = (username
? getugrDescription
TRUEnever evaluated
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
0-16
125 ? getugroups (0, NULL, username, gid)-
126 : getgroups (0, NULL));-
127-
128 /* If we failed to count groups because there is no supplemental-
129 group support, then return an array containing just GID.-
130 Otherwise, we fail for the same reason. */-
131 if (max_n_groups < 0)
Description
TRUEnever evaluated
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
0-16
132 {-
133 if (errno == ENOSYS && (g = realloc_groupbuf (NULL, 1)))
== 38Description
TRUEnever evaluated
FALSEnever evaluated
((void *)0) , 1))) {Description
TRUEnever evaluated
FALSEnever evaluated
0
134 {-
135 *groups = g;-
136 *g = gid;-
137 return gid != (gid_t) -1;
never executed
0
138 }-
139 return -1;
never executed
0
140 }-
141-
142 if (max_n_groups == 0 || (!username && gid != (gid_t) -1))
x_n_groups++;Description
TRUEnever evaluated
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • id
FALSEnever evaluated
Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • id
FALSEnever evaluated
0-16
143 max_n_groups++;
executed 16 times by 1 test: = realloc_group
Executed by:
  • id
16
144 g = realloc_groupbuf (NULL, max_n_groups);-
145 if (g == NULL)
((void *)0) )Description
TRUEnever evaluated
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
0-16
146 return -1;
never executed
0
147-
148 ng = (username
? getugrDescription
TRUEnever evaluated
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
0-16
149 ? getugroups (max_n_groups, g, username, gid)-
150 : getgroups (max_n_groups - (gid != (gid_t) -1),-
151 g + (gid != (gid_t) -1)));-
152-
153 if (ng < 0)
Description
TRUEnever evaluated
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
0-16
154 {-
155 /* Failure is unexpected, but handle it anyway. */-
156 int saved_errno = errno;-
157 free (g);-
158 errno = saved_errno;-
159 return -1;
never executed
0
160 }-
161-
162 if (!username && gid != (gid_t) -1)
Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • id
FALSEnever evaluated
Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • id
FALSEnever evaluated
0-16
163 {-
164 *g = gid;-
165 ng++;-
166 }
executed 16 times by 1 test: r
Executed by:
  • id
16
167 *groups = g;-
168-
169 /* Reduce the number of duplicates. On some systems, getgroups-
170 returns the effective gid twice: once as the first element, and-
171 once in its position within the supplementary groups. On other-
172 systems, getgroups does not return the effective gid at all,-
173 which is why we provide a GID argument. Meanwhile, the GID-
174 argument, if provided, is typically any member of the-
175 supplementary groups, and not necessarily the effective gid. So,-
176 the most likely duplicates are the first element with an-
177 arbitrary other element, or pair-wise duplication between the-
178 first and second elements returned by getgroups. It is possible-
179 that this O(n) pass will not remove all duplicates, but it is not-
180 worth the effort to slow down to an O(n log n) algorithm that-
181 sorts the array in place, nor the extra memory needed for-
182 duplicate removal via an O(n) hash-table. Hence, this function-
183 is only documented as guaranteeing no pair-wise duplicates,-
184 rather than returning the minimal set. */-
185 if (1 < ng)
Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • id
FALSEnever evaluated
0-16
186 {-
187 gid_t first = *g;-
188 gid_t *next;-
189 gid_t *groups_end = g + ng;-
190-
191 for (next = g + 1; next < groups_end; next++)
Description
TRUEevaluated 176 times by 1 test
Evaluated by:
  • id
FALSEevaluated 16 times by 1 test
Evaluated by:
  • id
16-176
192 {-
193 if (*next == first || *next == *g)
--;Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • id
FALSEevaluated 160 times by 1 test
Evaluated by:
  • id
Description
TRUEnever evaluated
FALSEevaluated 160 times by 1 test
Evaluated by:
  • id
0-160
194 ng--;
executed 16 times by 1 test: se
Executed by:
  • id
16
195 else-
196 *++g = *next;
executed 160 times by 1 test
Executed by:
  • id
160
197 }-
198 }
executed 16 times by 1 test
Executed by:
  • id
16
199-
200 return ng;
executed 16 times by 1 test
Executed by:
  • id
16
201}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2