Merge pull request #5675 from mono/glib-debug-symbols
[mono.git] / support / grp.c
index ff49aa1bd2a8ccd7fb9c5a9132a7657e7b35a51a..827bc550d938fa91252db4ca620d739b939cb508 100644 (file)
@@ -4,27 +4,25 @@
  * Authors:
  *   Jonathan Pryor (jonpryor@vt.edu)
  *
- * Copyright (C) 2004 Jonathan Pryor
+ * Copyright (C) 2004-2005 Jonathan Pryor
  */
 
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
 #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
 
-struct Mono_Posix_Syscall__Group {
-       /* string */  char     *gr_name;
-       /* string */  char     *gr_passwd;
-       /* gid_t  */  mph_gid_t gr_gid;
-       /* int    */  int       _gr_nmem_;
-       /* string */  char    **gr_mem;
-       /* string */  char     *_gr_buf_;  /* holds all but gr_mem */
-};
-
 static void
 count_members (char **gr_mem, int *count, size_t *mem)
 {
@@ -52,7 +50,7 @@ copy_group (struct Mono_Posix_Syscall__Group *to, struct group *from)
 {
        size_t nlen, plen, buflen;
        int i, count;
-       char *cur;
+       char *cur, **to_mem;
 
        to->gr_gid    = from->gr_gid;
 
@@ -79,7 +77,7 @@ copy_group (struct Mono_Posix_Syscall__Group *to, struct group *from)
 
        to->_gr_nmem_ = count;
        cur = to->_gr_buf_ = (char*) malloc (buflen);
-       to->gr_mem = (char **) malloc (sizeof(char*)*(count+1));
+       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);
@@ -92,10 +90,10 @@ copy_group (struct Mono_Posix_Syscall__Group *to, struct group *from)
        cur += (plen + 1);
 
        for (i = 0; i != count; ++i) {
-               to->gr_mem[i] = strcpy (cur, from->gr_mem[i]);
+               to_mem [i] = strcpy (cur, from->gr_mem[i]);
                cur += (strlen (from->gr_mem[i])+1);
        }
-       to->gr_mem[i] = NULL;
+       to_mem [i] = NULL;
 
        return 0;
 }
@@ -110,6 +108,7 @@ Mono_Posix_Syscall_getgrnam (const char *name, struct Mono_Posix_Syscall__Group
                return -1;
        }
 
+       errno = 0;
        _gbuf = getgrnam (name);
        if (_gbuf == NULL)
                return -1;
@@ -131,6 +130,7 @@ Mono_Posix_Syscall_getgrgid (mph_gid_t gid, struct Mono_Posix_Syscall__Group *gb
                return -1;
        }
 
+       errno = 0;
        _gbuf = getgrgid (gid);
        if (_gbuf == NULL)
                return -1;
@@ -142,10 +142,11 @@ Mono_Posix_Syscall_getgrgid (mph_gid_t gid, struct Mono_Posix_Syscall__Group *gb
        return 0;
 }
 
+#ifdef HAVE_GETGRNAM_R
 gint32
 Mono_Posix_Syscall_getgrnam_r (const char *name, 
        struct Mono_Posix_Syscall__Group *gbuf,
-       struct group **gbufp)
+       void **gbufp)
 {
        char *buf, *buf2;
        size_t buflen;
@@ -168,7 +169,13 @@ Mono_Posix_Syscall_getgrnam_r (const char *name,
                        return -1;
                }
                buf = buf2;
-       } while ((r = getgrnam_r (name, &_grbuf, buf, buflen, gbufp)) && r == ERANGE);
+               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;
@@ -176,11 +183,13 @@ Mono_Posix_Syscall_getgrnam_r (const char *name,
 
        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,
-       struct group **gbufp)
+       void **gbufp)
 {
        char *buf, *buf2;
        size_t buflen;
@@ -203,7 +212,13 @@ Mono_Posix_Syscall_getgrgid_r (mph_gid_t gid,
                        return -1;
                }
                buf = buf2;
-       } while ((r = getgrgid_r (gid, &_grbuf, buf, buflen, gbufp)) && r == ERANGE);
+               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;
@@ -211,7 +226,9 @@ Mono_Posix_Syscall_getgrgid_r (mph_gid_t gid,
 
        return r;
 }
+#endif /* ndef HAVE_GETGRGID_R */
 
+#if HAVE_GETGRENT
 gint32
 Mono_Posix_Syscall_getgrent (struct Mono_Posix_Syscall__Group *grbuf)
 {
@@ -222,6 +239,7 @@ Mono_Posix_Syscall_getgrent (struct Mono_Posix_Syscall__Group *grbuf)
                return -1;
        }
 
+       errno = 0;
        gr = getgrent ();
        if (gr == NULL)
                return -1;
@@ -232,9 +250,11 @@ Mono_Posix_Syscall_getgrent (struct Mono_Posix_Syscall__Group *grbuf)
        }
        return 0;
 }
+#endif  /* def HAVE_GETGRENT */
 
+#ifdef HAVE_FGETGRENT
 gint32
-Mono_Posix_Syscall_fgetgrent (FILE *stream, struct Mono_Posix_Syscall__Group *grbuf)
+Mono_Posix_Syscall_fgetgrent (void *stream, struct Mono_Posix_Syscall__Group *grbuf)
 {
        struct group *gr;
 
@@ -243,7 +263,8 @@ Mono_Posix_Syscall_fgetgrent (FILE *stream, struct Mono_Posix_Syscall__Group *gr
                return -1;
        }
 
-       gr = fgetgrent (stream);
+       errno = 0;
+       gr = fgetgrent ((FILE*) stream);
        if (gr == NULL)
                return -1;
 
@@ -253,13 +274,39 @@ Mono_Posix_Syscall_fgetgrent (FILE *stream, struct Mono_Posix_Syscall__Group *gr
        }
        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