github.com/afumu/libc@v0.0.6/musl/src/passwd/getgrouplist.c (about)

     1  #define _GNU_SOURCE
     2  #include "pwf.h"
     3  #include <grp.h>
     4  #include <string.h>
     5  #include <limits.h>
     6  #include <stdio.h>
     7  #include <stdlib.h>
     8  #include <byteswap.h>
     9  #include <errno.h>
    10  #include "nscd.h"
    11  
    12  int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
    13  {
    14  	int rv, nlim, ret = -1;
    15  	ssize_t i, n = 1;
    16  	struct group gr;
    17  	struct group *res;
    18  	FILE *f;
    19  	int swap = 0;
    20  	int32_t resp[INITGR_LEN];
    21  	uint32_t *nscdbuf = 0;
    22  	char *buf = 0;
    23  	char **mem = 0;
    24  	size_t nmem = 0;
    25  	size_t size;
    26  	nlim = *ngroups;
    27  	if (nlim >= 1) *groups++ = gid;
    28  
    29  	f = __nscd_query(GETINITGR, user, resp, sizeof resp, &swap);
    30  	if (!f) goto cleanup;
    31  	if (resp[INITGRFOUND]) {
    32  		nscdbuf = calloc(resp[INITGRNGRPS], sizeof(uint32_t));
    33  		if (!nscdbuf) goto cleanup;
    34  		if (!fread(nscdbuf, sizeof(*nscdbuf)*resp[INITGRNGRPS], 1, f)) {
    35  			if (!ferror(f)) errno = EIO;
    36  			goto cleanup;
    37  		}
    38  		if (swap) {
    39  			for (i = 0; i < resp[INITGRNGRPS]; i++)
    40  				nscdbuf[i] = bswap_32(nscdbuf[i]);
    41  		}
    42  	}
    43  	fclose(f);
    44  
    45  	f = fopen("/etc/group", "rbe");
    46  	if (!f && errno != ENOENT && errno != ENOTDIR)
    47  		goto cleanup;
    48  
    49  	if (f) {
    50  		while (!(rv = __getgrent_a(f, &gr, &buf, &size, &mem, &nmem, &res)) && res) {
    51  			if (nscdbuf)
    52  				for (i=0; i < resp[INITGRNGRPS]; i++) {
    53  					if (nscdbuf[i] == gr.gr_gid) nscdbuf[i] = gid;
    54  				}
    55  			for (i=0; gr.gr_mem[i] && strcmp(user, gr.gr_mem[i]); i++);
    56  			if (!gr.gr_mem[i]) continue;
    57  			if (++n <= nlim) *groups++ = gr.gr_gid;
    58  		}
    59  		if (rv) {
    60  			errno = rv;
    61  			goto cleanup;
    62  		}
    63  	}
    64  	if (nscdbuf) {
    65  		for(i=0; i < resp[INITGRNGRPS]; i++) {
    66  			if (nscdbuf[i] != gid)
    67  				if(++n <= nlim) *groups++ = nscdbuf[i];
    68  		}
    69  	}
    70  
    71  	ret = n > nlim ? -1 : n;
    72  	*ngroups = n;
    73  
    74  cleanup:
    75  	if (f) fclose(f);
    76  	free(nscdbuf);
    77  	free(buf);
    78  	free(mem);
    79  	return ret;
    80  }