7d05485754
Former-commit-id: df344e34b07851d296efb3e6604c8db42b6f7aa3
276 lines
5.4 KiB
C
276 lines
5.4 KiB
C
/*
|
|
* <pwd.h> wrapper functions.
|
|
*
|
|
* Authors:
|
|
* Jonathan Pryor (jonpryor@vt.edu)
|
|
*
|
|
* Copyright (C) 2004-2005 Jonathan Pryor
|
|
*/
|
|
|
|
#include <pwd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "mph.h" /* Don't remove or move after map.h! Works around issues with Android SDK unified headers */
|
|
#include "map.h"
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
static const mph_string_offset_t
|
|
passwd_offsets[] = {
|
|
MPH_STRING_OFFSET (struct passwd, pw_name, MPH_STRING_OFFSET_PTR),
|
|
MPH_STRING_OFFSET (struct passwd, pw_passwd, MPH_STRING_OFFSET_PTR),
|
|
#if HAVE_STRUCT_PASSWD_PW_GECOS
|
|
MPH_STRING_OFFSET (struct passwd, pw_gecos, MPH_STRING_OFFSET_PTR),
|
|
#endif /* def HAVE_STRUCT_PASSWD_PW_GECOS */
|
|
MPH_STRING_OFFSET (struct passwd, pw_dir, MPH_STRING_OFFSET_PTR),
|
|
MPH_STRING_OFFSET (struct passwd, pw_shell, MPH_STRING_OFFSET_PTR)
|
|
};
|
|
|
|
static const mph_string_offset_t
|
|
mph_passwd_offsets[] = {
|
|
MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_name, MPH_STRING_OFFSET_PTR),
|
|
MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_passwd, MPH_STRING_OFFSET_PTR),
|
|
#if HAVE_STRUCT_PASSWD_PW_GECOS
|
|
MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_gecos, MPH_STRING_OFFSET_PTR),
|
|
#endif /* def HAVE_STRUCT_PASSWD_PW_GECOS */
|
|
MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_dir, MPH_STRING_OFFSET_PTR),
|
|
MPH_STRING_OFFSET (struct Mono_Posix_Syscall__Passwd, pw_shell, MPH_STRING_OFFSET_PTR)
|
|
};
|
|
|
|
/*
|
|
* Copy the native `passwd' structure to it's managed representation.
|
|
*
|
|
* To minimize separate mallocs, all the strings are allocated within the same
|
|
* memory block (stored in _pw_buf_).
|
|
*/
|
|
static int
|
|
copy_passwd (struct Mono_Posix_Syscall__Passwd *to, struct passwd *from)
|
|
{
|
|
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_buf_ = buf;
|
|
if (buf == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
gint32
|
|
Mono_Posix_Syscall_getpwnam (const char *name, struct Mono_Posix_Syscall__Passwd *pwbuf)
|
|
{
|
|
struct passwd *pw;
|
|
|
|
if (pwbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
pw = getpwnam (name);
|
|
if (pw == NULL)
|
|
return -1;
|
|
|
|
if (copy_passwd (pwbuf, pw) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
gint32
|
|
Mono_Posix_Syscall_getpwuid (mph_uid_t uid, struct Mono_Posix_Syscall__Passwd *pwbuf)
|
|
{
|
|
struct passwd *pw;
|
|
|
|
if (pwbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
pw = getpwuid (uid);
|
|
if (pw == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (copy_passwd (pwbuf, pw) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HAVE_GETPWNAM_R
|
|
gint32
|
|
Mono_Posix_Syscall_getpwnam_r (const char *name,
|
|
struct Mono_Posix_Syscall__Passwd *pwbuf,
|
|
void **pwbufp)
|
|
{
|
|
char *buf, *buf2;
|
|
size_t buflen;
|
|
int r;
|
|
struct passwd _pwbuf;
|
|
|
|
if (pwbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
buf = buf2 = NULL;
|
|
buflen = 2;
|
|
|
|
do {
|
|
buf2 = realloc (buf, buflen *= 2);
|
|
if (buf2 == NULL) {
|
|
free (buf);
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
buf = buf2;
|
|
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;
|
|
free (buf);
|
|
|
|
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,
|
|
void **pwbufp)
|
|
{
|
|
char *buf, *buf2;
|
|
size_t buflen;
|
|
int r;
|
|
struct passwd _pwbuf;
|
|
|
|
if (pwbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
buf = buf2 = NULL;
|
|
buflen = 2;
|
|
|
|
do {
|
|
buf2 = realloc (buf, buflen *= 2);
|
|
if (buf2 == NULL) {
|
|
free (buf);
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
buf = buf2;
|
|
errno = 0;
|
|
} while ((r = getpwuid_r (uid, &_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;
|
|
free (buf);
|
|
|
|
return r;
|
|
}
|
|
#endif /* ndef HAVE_GETPWUID_R */
|
|
|
|
#if HAVE_GETPWENT
|
|
gint32
|
|
Mono_Posix_Syscall_getpwent (struct Mono_Posix_Syscall__Passwd *pwbuf)
|
|
{
|
|
struct passwd *pw;
|
|
|
|
if (pwbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
pw = getpwent ();
|
|
if (pw == NULL)
|
|
return -1;
|
|
|
|
if (copy_passwd (pwbuf, pw) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* def HAVE_GETPWENT */
|
|
|
|
#ifdef HAVE_FGETPWENT
|
|
gint32
|
|
Mono_Posix_Syscall_fgetpwent (void *stream, struct Mono_Posix_Syscall__Passwd *pwbuf)
|
|
{
|
|
struct passwd *pw;
|
|
|
|
if (pwbuf == NULL) {
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
pw = fgetpwent ((FILE*) stream);
|
|
if (pw == NULL)
|
|
return -1;
|
|
|
|
if (copy_passwd (pwbuf, pw) == -1) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif /* ndef HAVE_FGETPWENT */
|
|
|
|
#if HAVE_SETPWENT
|
|
int
|
|
Mono_Posix_Syscall_setpwent (void)
|
|
{
|
|
errno = 0;
|
|
do {
|
|
setpwent ();
|
|
} while (errno == EINTR);
|
|
mph_return_if_val_in_list5(errno, EIO, EMFILE, ENFILE, ENOMEM, ERANGE);
|
|
return 0;
|
|
}
|
|
#endif /* def HAVE_SETPWENT */
|
|
|
|
#if HAVE_ENDPWENT
|
|
int
|
|
Mono_Posix_Syscall_endpwent (void)
|
|
{
|
|
errno = 0;
|
|
endpwent ();
|
|
if (errno == EIO)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
#endif /* def HAVE_ENDPWENT */
|
|
|
|
G_END_DECLS
|
|
|
|
/*
|
|
* vim: noexpandtab
|
|
*/
|