grp.c 5.1 KB

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