a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
314 lines
5.3 KiB
C
314 lines
5.3 KiB
C
/*
|
|
* <grp.h> wrapper functions.
|
|
*
|
|
* Authors:
|
|
* Jonathan Pryor (jonpryor@vt.edu)
|
|
*
|
|
* Copyright (C) 2004-2005 Jonathan Pryor
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/param.h>
|
|
#include <grp.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <unistd.h> /* for setgroups on Mac OS X */
|
|
|
|
#include "map.h"
|
|
#include "mph.h"
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
static void
|
|
count_members (char **gr_mem, int *count, size_t *mem)
|
|
{
|
|
char *cur;
|
|
*count = 0;
|
|
|
|
// ensure that later (*mem)+1 doesn't result in integer overflow
|
|
if (*mem > INT_MAX - 1)
|
|
return;
|
|
|
|
for (cur = *gr_mem; cur != NULL; cur = *++gr_mem) {
|
|
size_t len;
|
|
len = strlen (cur);
|
|
|
|
if (!(len < INT_MAX - ((*mem) + 1)))
|
|
break;
|
|
|
|
++(*count);
|
|
*mem += (len + 1);
|
|
}
|
|
}
|
|
|
|
static int
|
|
copy_group (struct Mono_Posix_Syscall__Group *to, struct group *from)
|
|
{
|
|
size_t nlen, plen, buflen;
|
|
int i, count;
|
|
char *cur, **to_mem;
|
|
|
|
to->gr_gid = from->gr_gid;
|
|
|
|
to->gr_name = NULL;
|
|
to->gr_passwd = NULL;
|
|
to->gr_mem = NULL;
|
|
to->_gr_buf_ = NULL;
|
|
|
|
nlen = strlen (from->gr_name);
|
|
plen = strlen (from->gr_passwd);
|
|
|
|
buflen = 2;
|
|
|
|
if (!(nlen < INT_MAX - buflen))
|
|
return -1;
|
|
buflen += nlen;
|
|
|
|
if (!(plen < INT_MAX - buflen))
|
|
return -1;
|
|
buflen += plen;
|
|
|
|
count = 0;
|
|
count_members (from->gr_mem, &count, &buflen);
|
|
|
|
to->_gr_nmem_ = count;
|
|
cur = to->_gr_buf_ = (char*) malloc (buflen);
|
|
to_mem = to->gr_mem = malloc (sizeof(char*)*(count+1));
|
|
if (to->_gr_buf_ == NULL || to->gr_mem == NULL) {
|
|
free (to->_gr_buf_);
|
|
free (to->gr_mem);
|
|
return -1;
|
|
}
|
|
|
|
to->gr_name = strcpy (cur, from->gr_name);
|
|
cur += (nlen + 1);
|
|
to->gr_passwd = strcpy (cur, from->gr_passwd);
|
|
cur += (plen + 1);
|
|
|
|
for (i = 0; i != count; ++i) {
|
|
to_mem [i] = strcpy (cur, from->gr_mem[i]);
|
|
cur += (strlen (from->gr_mem[i])+1);
|
|
}
|
|
to_mem [i] = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
gint32
|
|
Mono_Posix_Syscall_getgrnam (const char *name, struct Mono_Posix_Syscall__Group *gbuf)
|
|
{
|
|
struct group *_gbuf;
|
|
|
|
if (gbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
_gbuf = getgrnam (name);
|
|
if (_gbuf == NULL)
|
|
return -1;
|
|
|
|
if (copy_group (gbuf, _gbuf) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
gint32
|
|
Mono_Posix_Syscall_getgrgid (mph_gid_t gid, struct Mono_Posix_Syscall__Group *gbuf)
|
|
{
|
|
struct group *_gbuf;
|
|
|
|
if (gbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
_gbuf = getgrgid (gid);
|
|
if (_gbuf == NULL)
|
|
return -1;
|
|
|
|
if (copy_group (gbuf, _gbuf) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HAVE_GETGRNAM_R
|
|
gint32
|
|
Mono_Posix_Syscall_getgrnam_r (const char *name,
|
|
struct Mono_Posix_Syscall__Group *gbuf,
|
|
void **gbufp)
|
|
{
|
|
char *buf, *buf2;
|
|
size_t buflen;
|
|
int r;
|
|
struct group _grbuf;
|
|
|
|
if (gbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
buf = buf2 = NULL;
|
|
buflen = 2;
|
|
|
|
do {
|
|
buf2 = realloc (buf, buflen *= 2);
|
|
if (buf2 == NULL) {
|
|
free (buf);
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
buf = buf2;
|
|
errno = 0;
|
|
} while ((r = getgrnam_r (name, &_grbuf, buf, buflen, (struct group**) gbufp)) &&
|
|
recheck_range (r));
|
|
|
|
/* On Solaris, this function returns 0 even if the entry was not found */
|
|
if (r == 0 && !(*gbufp))
|
|
r = errno = ENOENT;
|
|
|
|
if (r == 0 && copy_group (gbuf, &_grbuf) == -1)
|
|
r = errno = ENOMEM;
|
|
free (buf);
|
|
|
|
return r;
|
|
}
|
|
#endif /* ndef HAVE_GETGRNAM_R */
|
|
|
|
#ifdef HAVE_GETGRGID_R
|
|
gint32
|
|
Mono_Posix_Syscall_getgrgid_r (mph_gid_t gid,
|
|
struct Mono_Posix_Syscall__Group *gbuf,
|
|
void **gbufp)
|
|
{
|
|
char *buf, *buf2;
|
|
size_t buflen;
|
|
int r;
|
|
struct group _grbuf;
|
|
|
|
if (gbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
buf = buf2 = NULL;
|
|
buflen = 2;
|
|
|
|
do {
|
|
buf2 = realloc (buf, buflen *= 2);
|
|
if (buf2 == NULL) {
|
|
free (buf);
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
buf = buf2;
|
|
errno = 0;
|
|
} while ((r = getgrgid_r (gid, &_grbuf, buf, buflen, (struct group**) gbufp)) &&
|
|
recheck_range (r));
|
|
|
|
/* On Solaris, this function returns 0 even if the entry was not found */
|
|
if (r == 0 && !(*gbufp))
|
|
r = errno = ENOENT;
|
|
|
|
if (r == 0 && copy_group (gbuf, &_grbuf) == -1)
|
|
r = errno = ENOMEM;
|
|
free (buf);
|
|
|
|
return r;
|
|
}
|
|
#endif /* ndef HAVE_GETGRGID_R */
|
|
|
|
#if HAVE_GETGRENT
|
|
gint32
|
|
Mono_Posix_Syscall_getgrent (struct Mono_Posix_Syscall__Group *grbuf)
|
|
{
|
|
struct group *gr;
|
|
|
|
if (grbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
gr = getgrent ();
|
|
if (gr == NULL)
|
|
return -1;
|
|
|
|
if (copy_group (grbuf, gr) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* def HAVE_GETGRENT */
|
|
|
|
#ifdef HAVE_FGETGRENT
|
|
gint32
|
|
Mono_Posix_Syscall_fgetgrent (void *stream, struct Mono_Posix_Syscall__Group *grbuf)
|
|
{
|
|
struct group *gr;
|
|
|
|
if (grbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
gr = fgetgrent ((FILE*) stream);
|
|
if (gr == NULL)
|
|
return -1;
|
|
|
|
if (copy_group (grbuf, gr) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* ndef HAVE_FGETGRENT */
|
|
|
|
#if HAVE_SETGROUPS
|
|
gint32
|
|
Mono_Posix_Syscall_setgroups (mph_size_t size, mph_gid_t *list)
|
|
{
|
|
mph_return_if_size_t_overflow (size);
|
|
return setgroups ((size_t) size, list);
|
|
}
|
|
#endif /* def HAVE_SETGROUPS */
|
|
|
|
#if HAVE_SETGRENT
|
|
int
|
|
Mono_Posix_Syscall_setgrent (void)
|
|
{
|
|
errno = 0;
|
|
do {
|
|
setgrent ();
|
|
} while (errno == EINTR);
|
|
mph_return_if_val_in_list5(errno, EIO, EMFILE, ENFILE, ENOMEM, ERANGE);
|
|
return 0;
|
|
}
|
|
#endif /* def HAVE_SETGRENT */
|
|
|
|
#if HAVE_ENDGRENT
|
|
int
|
|
Mono_Posix_Syscall_endgrent (void)
|
|
{
|
|
endgrent();
|
|
return 0;
|
|
}
|
|
#endif /* def HAVE_ENDGRENT */
|
|
|
|
|
|
G_END_DECLS
|
|
|
|
/*
|
|
* vim: noexpandtab
|
|
*/
|