* support-test-*.cs: Rename from test-*-p2.cs.
[mono.git] / support / pwd.c
index fc908958905a58c32882676fa636dbd31f5f808c..38859e0d7c61bb3522adf62da87ec0bba2fe3b0c 100644 (file)
@@ -4,7 +4,7 @@
  * Authors:
  *   Jonathan Pryor (jonpryor@vt.edu)
  *
- * Copyright (C) 2004 Jonathan Pryor
+ * Copyright (C) 2004-2005 Jonathan Pryor
  */
 
 #include <pwd.h>
@@ -28,6 +28,24 @@ struct Mono_Posix_Syscall__Passwd {
        /* string */ char      *_pw_buf_;
 };
 
+static const size_t
+passwd_offsets[] = {
+       offsetof (struct passwd, pw_name),
+       offsetof (struct passwd, pw_passwd),
+       offsetof (struct passwd, pw_gecos),
+       offsetof (struct passwd, pw_dir),
+       offsetof (struct passwd, pw_shell)
+};
+
+static const size_t
+mph_passwd_offsets[] = {
+       offsetof (struct Mono_Posix_Syscall__Passwd, pw_name),
+       offsetof (struct Mono_Posix_Syscall__Passwd, pw_passwd),
+       offsetof (struct Mono_Posix_Syscall__Passwd, pw_gecos),
+       offsetof (struct Mono_Posix_Syscall__Passwd, pw_dir),
+       offsetof (struct Mono_Posix_Syscall__Passwd, pw_shell)
+};
+
 /*
  * Copy the native `passwd' structure to it's managed representation.
  *
@@ -37,59 +55,18 @@ struct Mono_Posix_Syscall__Passwd {
 static int
 copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
 {
-       enum {PW_NAME = 0, PW_PASSWD, PW_GECOS, PW_DIR, PW_SHELL, PW_LAST};
-       size_t buflen, len[PW_LAST];
-       /* bool */ unsigned char copy[PW_LAST] = {0};
-       const char *source[PW_LAST];
-       char **dest[PW_LAST];
-       int i;
-       char *cur;
+       char *buf;
+       buf = _mph_copy_structure_strings (to, mph_passwd_offsets,
+                       from, passwd_offsets, sizeof(passwd_offsets)/sizeof(passwd_offsets[0]));
 
        to->pw_uid    = from->pw_uid;
        to->pw_gid    = from->pw_gid;
 
-       to->pw_name   = NULL;
-       to->pw_passwd = NULL;
-       to->pw_gecos  = NULL;
-       to->pw_dir    = NULL;
-       to->pw_shell  = NULL;
-       to->_pw_buf_  = NULL;
-
-       source[PW_NAME]   = from->pw_name;
-       source[PW_PASSWD] = from->pw_passwd;
-       source[PW_GECOS]  = from->pw_gecos;
-       source[PW_DIR]    = from->pw_dir;
-       source[PW_SHELL]  = from->pw_shell;
-
-       dest[PW_NAME]   = &to->pw_name;
-       dest[PW_PASSWD] = &to->pw_passwd;
-       dest[PW_GECOS]  = &to->pw_gecos;
-       dest[PW_DIR]    = &to->pw_dir;
-       dest[PW_SHELL]  = &to->pw_shell;
-
-       buflen = PW_LAST;
-
-       /* over-rigorous checking for integer overflow */
-       for (i = 0; i != PW_LAST; ++i) {
-               len[i] = strlen (source[i]);
-               if (len[i] < INT_MAX - buflen) {
-                       buflen += len[i];
-                       copy[i] = 1;
-               }
-       }
-
-       cur = to->_pw_buf_ = (char*) malloc (buflen);
-       if (cur == NULL) {
+       to->_pw_buf_ = buf;
+       if (buf == NULL) {
                return -1;
        }
 
-       for (i = 0; i != PW_LAST; ++i) {
-               if (copy[i]) {
-                       *dest[i] = strcpy (cur, source[i]);
-                       cur += (len[i] + 1);
-               }
-       }
-
        return 0;
 }
 
@@ -103,6 +80,7 @@ Mono_Posix_Syscall_getpwnam (const char *name, struct Mono_Posix_Syscall__Passwd
                return -1;
        }
 
+       errno = 0;
        pw = getpwnam (name);
        if (pw == NULL)
                return -1;
@@ -137,10 +115,11 @@ Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *p
        return 0;
 }
 
+#ifdef HAVE_GETPWNAM_R
 gint32
 Mono_Posix_Syscall_getpwnam_r (const char *name, 
        struct Mono_Posix_Syscall__Passwd *pwbuf,
-       struct passwd **pwbufp)
+       void **pwbufp)
 {
        char *buf, *buf2;
        size_t buflen;
@@ -163,7 +142,13 @@ Mono_Posix_Syscall_getpwnam_r (const char *name,
                        return -1;
                }
                buf = buf2;
-       } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, pwbufp)) && r == ERANGE);
+               errno = 0;
+       } while ((r = getpwnam_r (name, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) && 
+                       recheck_range (r));
+
+       if (r == 0 && !(*pwbufp))
+               /* On solaris, this function returns 0 even if the entry was not found */
+               r = errno = ENOENT;
 
        if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
                r = errno = ENOMEM;
@@ -171,11 +156,13 @@ Mono_Posix_Syscall_getpwnam_r (const char *name,
 
        return r;
 }
+#endif /* ndef HAVE_GETPWNAM_R */
 
+#ifdef HAVE_GETPWUID_R
 gint32
 Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
        struct Mono_Posix_Syscall__Passwd *pwbuf,
-       struct passwd **pwbufp)
+       void **pwbufp)
 {
        char *buf, *buf2;
        size_t buflen;
@@ -198,7 +185,9 @@ Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
                        return -1;
                }
                buf = buf2;
-       } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, pwbufp)) && r == ERANGE);
+               errno = 0;
+       } while ((r = getpwuid_r (uid, &_pwbuf, buf, buflen, (struct passwd**) pwbufp)) && 
+                       recheck_range (r));
 
        if (r == 0 && copy_passwd (pwbuf, &_pwbuf) == -1)
                r = errno = ENOMEM;
@@ -206,6 +195,7 @@ Mono_Posix_Syscall_getpwuid_r (mph_uid_t uid,
 
        return r;
 }
+#endif /* ndef HAVE_GETPWUID_R */
 
 gint32
 Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
@@ -217,6 +207,7 @@ Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
                return -1;
        }
 
+       errno = 0;
        pw = getpwent ();
        if (pw == NULL)
                return -1;
@@ -230,7 +221,7 @@ Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
 
 #ifdef HAVE_FGETPWENT
 gint32
-Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
+Mono_Posix_Syscall_fgetpwent (void *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
 {
        struct passwd *pw;
 
@@ -239,7 +230,8 @@ Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *p
                return -1;
        }
 
-       pw = fgetpwent (stream);
+       errno = 0;
+       pw = fgetpwent ((FILE*) stream);
        if (pw == NULL)
                return -1;
 
@@ -249,7 +241,23 @@ Mono_Posix_Syscall_fgetpwent (FILE *stream, struct Mono_Posix_Syscall__Passwd *p
        }
        return 0;
 }
-#endif /* ndef FGETPWENT */
+#endif /* ndef HAVE_FGETPWENT */
+
+int
+Mono_Posix_Syscall_setpwent (void)
+{
+       errno = 0;
+       setpwent ();
+       return errno == 0 ? 0 : -1;
+}
+
+int
+Mono_Posix_Syscall_endpwent (void)
+{
+       errno = 0;
+       endpwent ();
+       return errno == 0 ? 0 : -1;
+}
 
 G_END_DECLS