user-util: Add helper functions for gid lists operations
This commit is contained in:
parent
6a6078a585
commit
0c5d667932
|
@ -404,11 +404,16 @@ char* gid_to_name(gid_t gid) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool gid_list_has(const gid_t *list, size_t size, gid_t val) {
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (list[i] == val)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int in_gid(gid_t gid) {
|
||||
_cleanup_free_ gid_t *allocated = NULL;
|
||||
gid_t local[16], *p = local;
|
||||
int ngroups = ELEMENTSOF(local);
|
||||
unsigned attempt = 0;
|
||||
_cleanup_free_ gid_t *gids = NULL;
|
||||
int ngroups;
|
||||
|
||||
if (getgid() == gid)
|
||||
return 1;
|
||||
|
@ -419,6 +424,57 @@ int in_gid(gid_t gid) {
|
|||
if (!gid_is_valid(gid))
|
||||
return -EINVAL;
|
||||
|
||||
ngroups = getgroups_alloc(&gids);
|
||||
if (ngroups < 0)
|
||||
return ngroups;
|
||||
|
||||
return gid_list_has(gids, ngroups, gid);
|
||||
}
|
||||
|
||||
int in_group(const char *name) {
|
||||
int r;
|
||||
gid_t gid;
|
||||
|
||||
r = get_group_creds(&name, &gid, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return in_gid(gid);
|
||||
}
|
||||
|
||||
int merge_gid_lists(const gid_t *list1, size_t size1, const gid_t *list2, size_t size2, gid_t **ret) {
|
||||
size_t nresult = 0;
|
||||
assert(ret);
|
||||
|
||||
if (size2 > INT_MAX - size1)
|
||||
return -ENOBUFS;
|
||||
|
||||
gid_t *buf = new(gid_t, size1 + size2);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Duplicates need to be skipped on merging, otherwise they'll be passed on and stored in the kernel. */
|
||||
for (size_t i = 0; i < size1; i++)
|
||||
if (!gid_list_has(buf, nresult, list1[i]))
|
||||
buf[nresult++] = list1[i];
|
||||
for (size_t i = 0; i < size2; i++)
|
||||
if (!gid_list_has(buf, nresult, list2[i]))
|
||||
buf[nresult++] = list2[i];
|
||||
*ret = buf;
|
||||
return (int)nresult;
|
||||
}
|
||||
|
||||
int getgroups_alloc(gid_t** gids) {
|
||||
gid_t *allocated;
|
||||
_cleanup_free_ gid_t *p = NULL;
|
||||
int ngroups = 8;
|
||||
unsigned attempt = 0;
|
||||
|
||||
allocated = new(gid_t, ngroups);
|
||||
if (!allocated)
|
||||
return -ENOMEM;
|
||||
p = allocated;
|
||||
|
||||
for (;;) {
|
||||
ngroups = getgroups(ngroups, p);
|
||||
if (ngroups >= 0)
|
||||
|
@ -447,22 +503,8 @@ int in_gid(gid_t gid) {
|
|||
p = allocated;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ngroups; i++)
|
||||
if (p[i] == gid)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int in_group(const char *name) {
|
||||
int r;
|
||||
gid_t gid;
|
||||
|
||||
r = get_group_creds(&name, &gid, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return in_gid(gid);
|
||||
*gids = TAKE_PTR(p);
|
||||
return ngroups;
|
||||
}
|
||||
|
||||
int get_home_dir(char **_h) {
|
||||
|
|
|
@ -42,6 +42,9 @@ char* gid_to_name(gid_t gid);
|
|||
int in_gid(gid_t gid);
|
||||
int in_group(const char *name);
|
||||
|
||||
int merge_gid_lists(const gid_t *list1, size_t size1, const gid_t *list2, size_t size2, gid_t **result);
|
||||
int getgroups_alloc(gid_t** gids);
|
||||
|
||||
int get_home_dir(char **ret);
|
||||
int get_shell(char **_ret);
|
||||
|
||||
|
|
Loading…
Reference in a new issue