/* * wrapper functions. * * Authors: * Jonathan Pryor (jonpryor@vt.edu) * * Copyright (C) 2004-2005 Jonathan Pryor */ #include #ifdef HAVE_SYS_PARAM_H #include #endif #include #include #include #include #include #include /* 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 */