grp.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * <grp.h> wrapper functions.
  3. *
  4. * Authors:
  5. * Jonathan Pryor ([email protected])
  6. *
  7. * Copyright (C) 2004 Jonathan Pryor
  8. */
  9. #include <sys/types.h>
  10. #include <sys/param.h>
  11. #include <grp.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <errno.h>
  15. #include <string.h>
  16. #include <unistd.h> /* for setgroups on Mac OS X */
  17. #include "mph.h"
  18. G_BEGIN_DECLS
  19. struct Mono_Posix_Syscall__Group {
  20. /* string */ char *gr_name;
  21. /* string */ char *gr_passwd;
  22. /* gid_t */ mph_gid_t gr_gid;
  23. /* int */ int _gr_nmem_;
  24. /* string */ char **gr_mem;
  25. /* string */ char *_gr_buf_; /* holds all but gr_mem */
  26. };
  27. static void
  28. count_members (char **gr_mem, int *count, size_t *mem)
  29. {
  30. char *cur;
  31. *count = 0;
  32. // ensure that later (*mem)+1 doesn't result in integer overflow
  33. if (*mem > INT_MAX - 1)
  34. return;
  35. for (cur = *gr_mem; cur != NULL; cur = *++gr_mem) {
  36. size_t len;
  37. len = strlen (cur);
  38. if (!(len < INT_MAX - ((*mem) + 1)))
  39. break;
  40. ++(*count);
  41. *mem += (len + 1);
  42. }
  43. }
  44. static int
  45. copy_group (struct Mono_Posix_Syscall__Group *to, struct group *from)
  46. {
  47. size_t nlen, plen, buflen;
  48. int i, count;
  49. char *cur;
  50. to->gr_gid = from->gr_gid;
  51. to->gr_name = NULL;
  52. to->gr_passwd = NULL;
  53. to->gr_mem = NULL;
  54. to->_gr_buf_ = NULL;
  55. nlen = strlen (from->gr_name);
  56. plen = strlen (from->gr_passwd);
  57. buflen = 2;
  58. if (!(nlen < INT_MAX - buflen))
  59. return -1;
  60. buflen += nlen;
  61. if (!(plen < INT_MAX - buflen))
  62. return -1;
  63. buflen += plen;
  64. count = 0;
  65. count_members (from->gr_mem, &count, &buflen);
  66. to->_gr_nmem_ = count;
  67. cur = to->_gr_buf_ = (char*) malloc (buflen);
  68. to->gr_mem = (char **) malloc (sizeof(char*)*(count+1));
  69. if (to->_gr_buf_ == NULL || to->gr_mem == NULL) {
  70. free (to->_gr_buf_);
  71. free (to->gr_mem);
  72. return -1;
  73. }
  74. to->gr_name = strcpy (cur, from->gr_name);
  75. cur += (nlen + 1);
  76. to->gr_passwd = strcpy (cur, from->gr_passwd);
  77. cur += (plen + 1);
  78. for (i = 0; i != count; ++i) {
  79. to->gr_mem[i] = strcpy (cur, from->gr_mem[i]);
  80. cur += (strlen (from->gr_mem[i])+1);
  81. }
  82. to->gr_mem[i] = NULL;
  83. return 0;
  84. }
  85. gint32
  86. Mono_Posix_Syscall_getgrnam (const char *name, struct Mono_Posix_Syscall__Group *gbuf)
  87. {
  88. struct group *_gbuf;
  89. if (gbuf == NULL) {
  90. errno = EFAULT;
  91. return -1;
  92. }
  93. errno = 0;
  94. _gbuf = getgrnam (name);
  95. if (_gbuf == NULL)
  96. return -1;
  97. if (copy_group (gbuf, _gbuf) == -1) {
  98. errno = ENOMEM;
  99. return -1;
  100. }
  101. return 0;
  102. }
  103. gint32
  104. Mono_Posix_Syscall_getgrgid (mph_gid_t gid, struct Mono_Posix_Syscall__Group *gbuf)
  105. {
  106. struct group *_gbuf;
  107. if (gbuf == NULL) {
  108. errno = EFAULT;
  109. return -1;
  110. }
  111. errno = 0;
  112. _gbuf = getgrgid (gid);
  113. if (_gbuf == NULL)
  114. return -1;
  115. if (copy_group (gbuf, _gbuf) == -1) {
  116. errno = ENOMEM;
  117. return -1;
  118. }
  119. return 0;
  120. }
  121. #ifdef HAVE_GETGRNAM_R
  122. gint32
  123. Mono_Posix_Syscall_getgrnam_r (const char *name,
  124. struct Mono_Posix_Syscall__Group *gbuf,
  125. void **gbufp)
  126. {
  127. char *buf, *buf2;
  128. size_t buflen;
  129. int r;
  130. struct group _grbuf;
  131. if (gbuf == NULL) {
  132. errno = EFAULT;
  133. return -1;
  134. }
  135. buf = buf2 = NULL;
  136. buflen = 2;
  137. do {
  138. buf2 = realloc (buf, buflen *= 2);
  139. if (buf2 == NULL) {
  140. free (buf);
  141. errno = ENOMEM;
  142. return -1;
  143. }
  144. buf = buf2;
  145. errno = 0;
  146. } while ((r = getgrnam_r (name, &_grbuf, buf, buflen, (struct group**) gbufp)) &&
  147. recheck_range (r));
  148. /* On Solaris, this function returns 0 even if the entry was not found */
  149. if (r == 0 && !(*gbufp))
  150. r = errno = ENOENT;
  151. if (r == 0 && copy_group (gbuf, &_grbuf) == -1)
  152. r = errno = ENOMEM;
  153. free (buf);
  154. return r;
  155. }
  156. #endif /* ndef HAVE_GETGRNAM_R */
  157. #ifdef HAVE_GETGRGID_R
  158. gint32
  159. Mono_Posix_Syscall_getgrgid_r (mph_gid_t gid,
  160. struct Mono_Posix_Syscall__Group *gbuf,
  161. void **gbufp)
  162. {
  163. char *buf, *buf2;
  164. size_t buflen;
  165. int r;
  166. struct group _grbuf;
  167. if (gbuf == NULL) {
  168. errno = EFAULT;
  169. return -1;
  170. }
  171. buf = buf2 = NULL;
  172. buflen = 2;
  173. do {
  174. buf2 = realloc (buf, buflen *= 2);
  175. if (buf2 == NULL) {
  176. free (buf);
  177. errno = ENOMEM;
  178. return -1;
  179. }
  180. buf = buf2;
  181. errno = 0;
  182. } while ((r = getgrgid_r (gid, &_grbuf, buf, buflen, (struct group**) gbufp)) &&
  183. recheck_range (r));
  184. /* On Solaris, this function returns 0 even if the entry was not found */
  185. if (r == 0 && !(*gbufp))
  186. r = errno = ENOENT;
  187. if (r == 0 && copy_group (gbuf, &_grbuf) == -1)
  188. r = errno = ENOMEM;
  189. free (buf);
  190. return r;
  191. }
  192. #endif /* ndef HAVE_GETGRGID_R */
  193. gint32
  194. Mono_Posix_Syscall_getgrent (struct Mono_Posix_Syscall__Group *grbuf)
  195. {
  196. struct group *gr;
  197. if (grbuf == NULL) {
  198. errno = EFAULT;
  199. return -1;
  200. }
  201. errno = 0;
  202. gr = getgrent ();
  203. if (gr == NULL)
  204. return -1;
  205. if (copy_group (grbuf, gr) == -1) {
  206. errno = ENOMEM;
  207. return -1;
  208. }
  209. return 0;
  210. }
  211. #ifdef HAVE_FGETGRENT
  212. gint32
  213. Mono_Posix_Syscall_fgetgrent (void *stream, struct Mono_Posix_Syscall__Group *grbuf)
  214. {
  215. struct group *gr;
  216. if (grbuf == NULL) {
  217. errno = EFAULT;
  218. return -1;
  219. }
  220. errno = 0;
  221. gr = fgetgrent ((FILE*) stream);
  222. if (gr == NULL)
  223. return -1;
  224. if (copy_group (grbuf, gr) == -1) {
  225. errno = ENOMEM;
  226. return -1;
  227. }
  228. return 0;
  229. }
  230. #endif /* ndef HAVE_FGETGRENT */
  231. gint32
  232. Mono_Posix_Syscall_setgroups (mph_size_t size, mph_gid_t *list)
  233. {
  234. mph_return_if_size_t_overflow (size);
  235. return setgroups ((size_t) size, list);
  236. }
  237. G_END_DECLS
  238. /*
  239. * vim: noexpandtab
  240. */