diff options
author | Zack Weinberg <zackw@panix.com> | 2017-06-08 15:39:03 -0400 |
---|---|---|
committer | Zack Weinberg <zackw@panix.com> | 2017-06-08 15:39:03 -0400 |
commit | 5046dbb4a7eba5eccfd258f92f4735c9ffc8d069 (patch) | |
tree | 4470480d904b65cf14ca524f96f79eca818c3eaf /REORG.TODO/grp/compat-initgroups.c | |
parent | 199fc19d3aaaf57944ef036e15904febe877fc93 (diff) | |
download | glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.tar glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.tar.gz glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.tar.bz2 glibc-5046dbb4a7eba5eccfd258f92f4735c9ffc8d069.zip |
Prepare for radical source tree reorganization.zack/build-layout-experiment
All top-level files and directories are moved into a temporary storage
directory, REORG.TODO, except for files that will certainly still
exist in their current form at top level when we're done (COPYING,
COPYING.LIB, LICENSES, NEWS, README), all old ChangeLog files (which
are moved to the new directory OldChangeLogs, instead), and the
generated file INSTALL (which is just deleted; in the new order, there
will be no generated files checked into version control).
Diffstat (limited to 'REORG.TODO/grp/compat-initgroups.c')
-rw-r--r-- | REORG.TODO/grp/compat-initgroups.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/REORG.TODO/grp/compat-initgroups.c b/REORG.TODO/grp/compat-initgroups.c new file mode 100644 index 0000000000..3dd50d2306 --- /dev/null +++ b/REORG.TODO/grp/compat-initgroups.c @@ -0,0 +1,116 @@ +/* Prototype for the setgrent functions we use here. */ +typedef enum nss_status (*set_function) (void); + +/* Prototype for the endgrent functions we use here. */ +typedef enum nss_status (*end_function) (void); + +/* Prototype for the setgrent functions we use here. */ +typedef enum nss_status (*get_function) (struct group *, char *, + size_t, int *); + + +static enum nss_status +compat_call (service_user *nip, const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, long int limit, int *errnop) +{ + struct group grpbuf; + enum nss_status status; + set_function setgrent_fct; + get_function getgrent_fct; + end_function endgrent_fct; + gid_t *groups = *groupsp; + + getgrent_fct = __nss_lookup_function (nip, "getgrent_r"); + if (getgrent_fct == NULL) + return NSS_STATUS_UNAVAIL; + + setgrent_fct = __nss_lookup_function (nip, "setgrent"); + if (setgrent_fct) + { + status = DL_CALL_FCT (setgrent_fct, ()); + if (status != NSS_STATUS_SUCCESS) + return status; + } + + endgrent_fct = __nss_lookup_function (nip, "endgrent"); + + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + enum nss_status result = NSS_STATUS_SUCCESS; + + do + { + while ((status = DL_CALL_FCT (getgrent_fct, + (&grpbuf, tmpbuf.data, tmpbuf.length, + errnop)), + status == NSS_STATUS_TRYAGAIN) + && *errnop == ERANGE) + { + if (!scratch_buffer_grow (&tmpbuf)) + { + result = NSS_STATUS_TRYAGAIN; + goto done; + } + } + + if (status != NSS_STATUS_SUCCESS) + goto done; + + if (grpbuf.gr_gid != group) + { + char **m; + + for (m = grpbuf.gr_mem; *m != NULL; ++m) + if (strcmp (*m, user) == 0) + { + /* Check whether the group is already on the list. */ + long int cnt; + for (cnt = 0; cnt < *start; ++cnt) + if (groups[cnt] == grpbuf.gr_gid) + break; + + if (cnt == *start) + { + /* Matches user and not yet on the list. Insert + this group. */ + if (__glibc_unlikely (*start == *size)) + { + /* Need a bigger buffer. */ + gid_t *newgroups; + long int newsize; + + if (limit > 0 && *size == limit) + /* We reached the maximum. */ + goto done; + + if (limit <= 0) + newsize = 2 * *size; + else + newsize = MIN (limit, 2 * *size); + + newgroups = realloc (groups, + newsize * sizeof (*groups)); + if (newgroups == NULL) + goto done; + *groupsp = groups = newgroups; + *size = newsize; + } + + groups[*start] = grpbuf.gr_gid; + *start += 1; + } + + break; + } + } + } + while (status == NSS_STATUS_SUCCESS); + + done: + scratch_buffer_free (&tmpbuf); + + if (endgrent_fct) + DL_CALL_FCT (endgrent_fct, ()); + + return result; +} |