mirror of
https://github.com/postgres/postgres.git
synced 2025-05-25 00:04:05 -04:00
Clean up messy API for src/port/thread.c.
The point of this patch is to reduce inclusion spam by not needing to #include <netdb.h> or <pwd.h> in port.h (which is read by every compile in our tree). To do that, we must remove port.h's declarations of pqGetpwuid and pqGethostbyname. pqGethostbyname is only used, and is only ever likely to be used, in src/port/getaddrinfo.c --- which isn't even built on most platforms, making pqGethostbyname dead code for most people. Hence, deal with that by just moving it into getaddrinfo.c. To clean up pqGetpwuid, invent a couple of simple wrapper functions with less-messy APIs. This allows removing some duplicate error-handling code, too. In passing, remove thread.c from the MSVC build, since it contains nothing we use on Windows. Noted while working on 376ce3e40. Discussion: https://postgr.es/m/1634252654444.90107@mit.edu
This commit is contained in:
parent
7fa945b857
commit
98e93a1fc9
@ -18,6 +18,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <unistd.h> /* for write() */
|
#include <unistd.h> /* for write() */
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#define PG_PORT_H
|
#define PG_PORT_H
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windows has enough specialized port stuff that we push most of it off
|
* Windows has enough specialized port stuff that we push most of it off
|
||||||
@ -484,18 +482,12 @@ extern char *dlerror(void);
|
|||||||
#define RTLD_GLOBAL 0
|
#define RTLD_GLOBAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* thread.h */
|
/* thread.c */
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
extern int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
|
extern bool pg_get_user_name(uid_t user_id, char *buffer, size_t buflen);
|
||||||
size_t buflen, struct passwd **result);
|
extern bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int pqGethostbyname(const char *name,
|
|
||||||
struct hostent *resultbuf,
|
|
||||||
char *buffer, size_t buflen,
|
|
||||||
struct hostent **result,
|
|
||||||
int *herrno);
|
|
||||||
|
|
||||||
extern void pg_qsort(void *base, size_t nel, size_t elsize,
|
extern void pg_qsort(void *base, size_t nel, size_t elsize,
|
||||||
int (*cmp) (const void *, const void *));
|
int (*cmp) (const void *, const void *));
|
||||||
extern int pg_qsort_strcmp(const void *a, const void *b);
|
extern int pg_qsort_strcmp(const void *a, const void *b);
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#ifndef MAXHOSTNAMELEN
|
#ifndef MAXHOSTNAMELEN
|
||||||
#include <netdb.h> /* for MAXHOSTNAMELEN on some */
|
#include <netdb.h> /* for MAXHOSTNAMELEN on some */
|
||||||
#endif
|
#endif
|
||||||
#include <pwd.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common/md5.h"
|
#include "common/md5.h"
|
||||||
@ -1099,14 +1098,17 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pg_fe_getauthname
|
* pg_fe_getusername
|
||||||
*
|
*
|
||||||
* Returns a pointer to malloc'd space containing whatever name the user
|
* Returns a pointer to malloc'd space containing the name of the
|
||||||
* has authenticated to the system. If there is an error, return NULL,
|
* specified user_id. If there is an error, return NULL, and append
|
||||||
* and append a suitable error message to *errorMessage if that's not NULL.
|
* a suitable error message to *errorMessage if that's not NULL.
|
||||||
|
*
|
||||||
|
* Caution: on Windows, the user_id argument is ignored, and we always
|
||||||
|
* fetch the current user's name.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
pg_fe_getauthname(PQExpBuffer errorMessage)
|
pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
|
||||||
{
|
{
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
@ -1116,17 +1118,13 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
|
|||||||
char username[256 + 1];
|
char username[256 + 1];
|
||||||
DWORD namesize = sizeof(username);
|
DWORD namesize = sizeof(username);
|
||||||
#else
|
#else
|
||||||
uid_t user_id = geteuid();
|
|
||||||
char pwdbuf[BUFSIZ];
|
char pwdbuf[BUFSIZ];
|
||||||
struct passwd pwdstr;
|
|
||||||
struct passwd *pw = NULL;
|
|
||||||
int pwerr;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some users are using configure --enable-thread-safety-force, so we
|
* Some users are using configure --enable-thread-safety-force, so we
|
||||||
* might as well do the locking within our library to protect
|
* might as well do the locking within our library to protect
|
||||||
* pqGetpwuid(). In fact, application developers can use getpwuid() in
|
* getpwuid(). In fact, application developers can use getpwuid() in
|
||||||
* their application if they use the locking call we provide, or install
|
* their application if they use the locking call we provide, or install
|
||||||
* their own locking function using PQregisterThreadLock().
|
* their own locking function using PQregisterThreadLock().
|
||||||
*/
|
*/
|
||||||
@ -1140,21 +1138,10 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
|
|||||||
libpq_gettext("user name lookup failure: error code %lu\n"),
|
libpq_gettext("user name lookup failure: error code %lu\n"),
|
||||||
GetLastError());
|
GetLastError());
|
||||||
#else
|
#else
|
||||||
pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
|
if (pg_get_user_name(user_id, pwdbuf, sizeof(pwdbuf)))
|
||||||
if (pw != NULL)
|
name = pwdbuf;
|
||||||
name = pw->pw_name;
|
|
||||||
else if (errorMessage)
|
else if (errorMessage)
|
||||||
{
|
appendPQExpBuffer(errorMessage, "%s\n", pwdbuf);
|
||||||
if (pwerr != 0)
|
|
||||||
appendPQExpBuffer(errorMessage,
|
|
||||||
libpq_gettext("could not look up local user ID %d: %s\n"),
|
|
||||||
(int) user_id,
|
|
||||||
strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
|
|
||||||
else
|
|
||||||
appendPQExpBuffer(errorMessage,
|
|
||||||
libpq_gettext("local user with ID %d does not exist\n"),
|
|
||||||
(int) user_id);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
@ -1170,6 +1157,23 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pg_fe_getauthname
|
||||||
|
*
|
||||||
|
* Returns a pointer to malloc'd space containing whatever name the user
|
||||||
|
* has authenticated to the system. If there is an error, return NULL,
|
||||||
|
* and append a suitable error message to *errorMessage if that's not NULL.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
pg_fe_getauthname(PQExpBuffer errorMessage)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return pg_fe_getusername(0, errorMessage);
|
||||||
|
#else
|
||||||
|
return pg_fe_getusername(geteuid(), errorMessage);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PQencryptPassword -- exported routine to encrypt a password with MD5
|
* PQencryptPassword -- exported routine to encrypt a password with MD5
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
/* Prototypes for functions in fe-auth.c */
|
/* Prototypes for functions in fe-auth.c */
|
||||||
extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn);
|
extern int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn);
|
||||||
|
extern char *pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage);
|
||||||
extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
|
extern char *pg_fe_getauthname(PQExpBuffer errorMessage);
|
||||||
|
|
||||||
/* Mechanisms in fe-auth-scram.c */
|
/* Mechanisms in fe-auth-scram.c */
|
||||||
|
@ -2813,10 +2813,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
IS_AF_UNIX(conn->raddr.addr.ss_family))
|
IS_AF_UNIX(conn->raddr.addr.ss_family))
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
char pwdbuf[BUFSIZ];
|
char *remote_username;
|
||||||
struct passwd pass_buf;
|
|
||||||
struct passwd *pass;
|
|
||||||
int passerr;
|
|
||||||
#endif
|
#endif
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
@ -2839,28 +2836,20 @@ keep_going: /* We will come back to here until there is
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
|
remote_username = pg_fe_getusername(uid,
|
||||||
if (pass == NULL)
|
&conn->errorMessage);
|
||||||
{
|
if (remote_username == NULL)
|
||||||
if (passerr != 0)
|
goto error_return; /* message already logged */
|
||||||
appendPQExpBuffer(&conn->errorMessage,
|
|
||||||
libpq_gettext("could not look up local user ID %d: %s\n"),
|
|
||||||
(int) uid,
|
|
||||||
strerror_r(passerr, sebuf, sizeof(sebuf)));
|
|
||||||
else
|
|
||||||
appendPQExpBuffer(&conn->errorMessage,
|
|
||||||
libpq_gettext("local user with ID %d does not exist\n"),
|
|
||||||
(int) uid);
|
|
||||||
goto error_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(pass->pw_name, conn->requirepeer) != 0)
|
if (strcmp(remote_username, conn->requirepeer) != 0)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&conn->errorMessage,
|
appendPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
|
libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
|
||||||
conn->requirepeer, pass->pw_name);
|
conn->requirepeer, remote_username);
|
||||||
|
free(remote_username);
|
||||||
goto error_return;
|
goto error_return;
|
||||||
}
|
}
|
||||||
|
free(remote_username);
|
||||||
#else /* WIN32 */
|
#else /* WIN32 */
|
||||||
/* should have failed with ENOSYS above */
|
/* should have failed with ENOSYS above */
|
||||||
Assert(false);
|
Assert(false);
|
||||||
@ -7271,16 +7260,7 @@ pqGetHomeDirectory(char *buf, int bufsize)
|
|||||||
|
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
if (home == NULL || home[0] == '\0')
|
if (home == NULL || home[0] == '\0')
|
||||||
{
|
return pg_get_user_home_dir(geteuid(), buf, bufsize);
|
||||||
char pwdbuf[BUFSIZ];
|
|
||||||
struct passwd pwdstr;
|
|
||||||
struct passwd *pwd = NULL;
|
|
||||||
|
|
||||||
(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
|
|
||||||
if (pwd == NULL)
|
|
||||||
return false;
|
|
||||||
home = pwd->pw_dir;
|
|
||||||
}
|
|
||||||
strlcpy(buf, home, bufsize);
|
strlcpy(buf, home, bufsize);
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
@ -84,6 +84,10 @@ libpgport.a: $(OBJS)
|
|||||||
rm -f $@
|
rm -f $@
|
||||||
$(AR) $(AROPT) $@ $^
|
$(AR) $(AROPT) $@ $^
|
||||||
|
|
||||||
|
# getaddrinfo.o and getaddrinfo_shlib.o need PTHREAD_CFLAGS (but getaddrinfo_srv.o does not)
|
||||||
|
getaddrinfo.o: CFLAGS+=$(PTHREAD_CFLAGS)
|
||||||
|
getaddrinfo_shlib.o: CFLAGS+=$(PTHREAD_CFLAGS)
|
||||||
|
|
||||||
# thread.o and thread_shlib.o need PTHREAD_CFLAGS (but thread_srv.o does not)
|
# thread.o and thread_shlib.o need PTHREAD_CFLAGS (but thread_srv.o does not)
|
||||||
thread.o: CFLAGS+=$(PTHREAD_CFLAGS)
|
thread.o: CFLAGS+=$(PTHREAD_CFLAGS)
|
||||||
thread_shlib.o: CFLAGS+=$(PTHREAD_CFLAGS)
|
thread_shlib.o: CFLAGS+=$(PTHREAD_CFLAGS)
|
||||||
|
@ -34,6 +34,14 @@
|
|||||||
#include "port/pg_bswap.h"
|
#include "port/pg_bswap.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FRONTEND
|
||||||
|
static int pqGethostbyname(const char *name,
|
||||||
|
struct hostent *resultbuf,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
struct hostent **result,
|
||||||
|
int *herrno);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
/*
|
/*
|
||||||
* The native routines may or may not exist on the Windows platform we are on,
|
* The native routines may or may not exist on the Windows platform we are on,
|
||||||
@ -394,3 +402,39 @@ getnameinfo(const struct sockaddr *sa, int salen,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper around gethostbyname() or gethostbyname_r() to mimic
|
||||||
|
* POSIX gethostbyname_r() behaviour, if it is not available or required.
|
||||||
|
*/
|
||||||
|
#ifdef FRONTEND
|
||||||
|
static int
|
||||||
|
pqGethostbyname(const char *name,
|
||||||
|
struct hostent *resultbuf,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
struct hostent **result,
|
||||||
|
int *herrno)
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* broken (well early POSIX draft) gethostbyname_r() which returns 'struct
|
||||||
|
* hostent *'
|
||||||
|
*/
|
||||||
|
*result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
|
||||||
|
return (*result == NULL) ? -1 : 0;
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* no gethostbyname_r(), just use gethostbyname() */
|
||||||
|
*result = gethostbyname(name);
|
||||||
|
|
||||||
|
if (*result != NULL)
|
||||||
|
*herrno = h_errno;
|
||||||
|
|
||||||
|
if (*result != NULL)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* FRONTEND */
|
||||||
|
@ -815,16 +815,7 @@ get_home_path(char *ret_path)
|
|||||||
|
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
if (home == NULL || home[0] == '\0')
|
if (home == NULL || home[0] == '\0')
|
||||||
{
|
return pg_get_user_home_dir(geteuid(), ret_path, MAXPGPATH);
|
||||||
char pwdbuf[BUFSIZ];
|
|
||||||
struct passwd pwdstr;
|
|
||||||
struct passwd *pwd = NULL;
|
|
||||||
|
|
||||||
(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
|
|
||||||
if (pwd == NULL)
|
|
||||||
return false;
|
|
||||||
home = pwd->pw_dir;
|
|
||||||
}
|
|
||||||
strlcpy(ret_path, home, MAXPGPATH);
|
strlcpy(ret_path, home, MAXPGPATH);
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
@ -45,10 +45,9 @@
|
|||||||
* use *_r function names if they exit
|
* use *_r function names if they exit
|
||||||
* (*_THREADSAFE=yes)
|
* (*_THREADSAFE=yes)
|
||||||
* use non-*_r functions if they are thread-safe
|
* use non-*_r functions if they are thread-safe
|
||||||
*
|
|
||||||
* One thread-safe solution for gethostbyname() might be to use getaddrinfo().
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
|
* Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
|
||||||
@ -60,8 +59,7 @@
|
|||||||
* error during lookup: returns an errno code, *result is NULL
|
* error during lookup: returns an errno code, *result is NULL
|
||||||
* (caller should *not* assume that the errno variable is set)
|
* (caller should *not* assume that the errno variable is set)
|
||||||
*/
|
*/
|
||||||
#ifndef WIN32
|
static int
|
||||||
int
|
|
||||||
pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
|
pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
|
||||||
size_t buflen, struct passwd **result)
|
size_t buflen, struct passwd **result)
|
||||||
{
|
{
|
||||||
@ -75,42 +73,74 @@ pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
|
|||||||
return (*result == NULL) ? errno : 0;
|
return (*result == NULL) ? errno : 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrapper around gethostbyname() or gethostbyname_r() to mimic
|
* pg_get_user_name - get the name of the user with the given ID
|
||||||
* POSIX gethostbyname_r() behaviour, if it is not available or required.
|
*
|
||||||
* This function is called _only_ by our getaddrinfo() portability function.
|
* On success, the user name is returned into the buffer (of size buflen),
|
||||||
|
* and "true" is returned. On failure, a localized error message is
|
||||||
|
* returned into the buffer, and "false" is returned.
|
||||||
*/
|
*/
|
||||||
#ifndef HAVE_GETADDRINFO
|
bool
|
||||||
int
|
pg_get_user_name(uid_t user_id, char *buffer, size_t buflen)
|
||||||
pqGethostbyname(const char *name,
|
|
||||||
struct hostent *resultbuf,
|
|
||||||
char *buffer, size_t buflen,
|
|
||||||
struct hostent **result,
|
|
||||||
int *herrno)
|
|
||||||
{
|
{
|
||||||
#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
|
char pwdbuf[BUFSIZ];
|
||||||
|
struct passwd pwdstr;
|
||||||
|
struct passwd *pw = NULL;
|
||||||
|
int pwerr;
|
||||||
|
|
||||||
/*
|
pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
|
||||||
* broken (well early POSIX draft) gethostbyname_r() which returns 'struct
|
if (pw != NULL)
|
||||||
* hostent *'
|
{
|
||||||
*/
|
strlcpy(buffer, pw->pw_name, buflen);
|
||||||
*result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
|
return true;
|
||||||
return (*result == NULL) ? -1 : 0;
|
}
|
||||||
#else
|
if (pwerr != 0)
|
||||||
|
snprintf(buffer, buflen,
|
||||||
/* no gethostbyname_r(), just use gethostbyname() */
|
_("could not look up local user ID %d: %s"),
|
||||||
*result = gethostbyname(name);
|
(int) user_id,
|
||||||
|
strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
|
||||||
if (*result != NULL)
|
|
||||||
*herrno = h_errno;
|
|
||||||
|
|
||||||
if (*result != NULL)
|
|
||||||
return 0;
|
|
||||||
else
|
else
|
||||||
return -1;
|
snprintf(buffer, buflen,
|
||||||
#endif
|
_("local user with ID %d does not exist"),
|
||||||
|
(int) user_id);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
/*
|
||||||
|
* pg_get_user_home_dir - get the home directory of the user with the given ID
|
||||||
|
*
|
||||||
|
* On success, the directory path is returned into the buffer (of size buflen),
|
||||||
|
* and "true" is returned. On failure, a localized error message is
|
||||||
|
* returned into the buffer, and "false" is returned.
|
||||||
|
*
|
||||||
|
* Note that this does not incorporate the common behavior of checking
|
||||||
|
* $HOME first, since it's independent of which user_id is queried.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
char pwdbuf[BUFSIZ];
|
||||||
|
struct passwd pwdstr;
|
||||||
|
struct passwd *pw = NULL;
|
||||||
|
int pwerr;
|
||||||
|
|
||||||
|
pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
|
||||||
|
if (pw != NULL)
|
||||||
|
{
|
||||||
|
strlcpy(buffer, pw->pw_dir, buflen);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (pwerr != 0)
|
||||||
|
snprintf(buffer, buflen,
|
||||||
|
_("could not look up local user ID %d: %s"),
|
||||||
|
(int) user_id,
|
||||||
|
strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
|
||||||
|
else
|
||||||
|
snprintf(buffer, buflen,
|
||||||
|
_("local user with ID %d does not exist"),
|
||||||
|
(int) user_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !WIN32 */
|
||||||
|
@ -106,7 +106,7 @@ sub mkvcbuild
|
|||||||
pread.c preadv.c pwrite.c pwritev.c pg_bitutils.c
|
pread.c preadv.c pwrite.c pwritev.c pg_bitutils.c
|
||||||
pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
|
pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
|
||||||
pqsignal.c mkdtemp.c qsort.c qsort_arg.c bsearch_arg.c quotes.c system.c
|
pqsignal.c mkdtemp.c qsort.c qsort_arg.c bsearch_arg.c quotes.c system.c
|
||||||
strerror.c tar.c thread.c
|
strerror.c tar.c
|
||||||
win32env.c win32error.c win32ntdll.c
|
win32env.c win32error.c win32ntdll.c
|
||||||
win32security.c win32setlocale.c win32stat.c);
|
win32security.c win32setlocale.c win32stat.c);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user