grp.c 5.3 KB

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