153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci  This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci  Copyright 2009 Ted Percival
553a5a1b3Sopenharmony_ci
653a5a1b3Sopenharmony_ci  PulseAudio is free software; you can redistribute it and/or modify
753a5a1b3Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as
853a5a1b3Sopenharmony_ci  published by the Free Software Foundation; either version 2.1 of the
953a5a1b3Sopenharmony_ci  License, or (at your option) any later version.
1053a5a1b3Sopenharmony_ci
1153a5a1b3Sopenharmony_ci  PulseAudio is distributed in the hope that it will be useful, but
1253a5a1b3Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1353a5a1b3Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1453a5a1b3Sopenharmony_ci  Lesser General Public License for more details.
1553a5a1b3Sopenharmony_ci
1653a5a1b3Sopenharmony_ci  You should have received a copy of the GNU Lesser General Public
1753a5a1b3Sopenharmony_ci  License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1853a5a1b3Sopenharmony_ci***/
1953a5a1b3Sopenharmony_ci
2053a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
2153a5a1b3Sopenharmony_ci#include <config.h>
2253a5a1b3Sopenharmony_ci#endif
2353a5a1b3Sopenharmony_ci
2453a5a1b3Sopenharmony_ci#include <sys/types.h>
2553a5a1b3Sopenharmony_ci#include <errno.h>
2653a5a1b3Sopenharmony_ci
2753a5a1b3Sopenharmony_ci#ifdef HAVE_PWD_H
2853a5a1b3Sopenharmony_ci#include <pwd.h>
2953a5a1b3Sopenharmony_ci#endif
3053a5a1b3Sopenharmony_ci
3153a5a1b3Sopenharmony_ci#ifdef HAVE_GRP_H
3253a5a1b3Sopenharmony_ci#include <grp.h>
3353a5a1b3Sopenharmony_ci#endif
3453a5a1b3Sopenharmony_ci
3553a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h>
3653a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
3753a5a1b3Sopenharmony_ci
3853a5a1b3Sopenharmony_ci#include "usergroup.h"
3953a5a1b3Sopenharmony_ci
4053a5a1b3Sopenharmony_ci#ifdef HAVE_GRP_H
4153a5a1b3Sopenharmony_ci
4253a5a1b3Sopenharmony_ci/* Returns a suitable starting size for a getgrnam_r() or getgrgid_r() buffer,
4353a5a1b3Sopenharmony_ci   plus the size of a struct group.
4453a5a1b3Sopenharmony_ci */
4553a5a1b3Sopenharmony_cistatic size_t starting_getgr_buflen(void) {
4653a5a1b3Sopenharmony_ci    size_t full_size;
4753a5a1b3Sopenharmony_ci    long n;
4853a5a1b3Sopenharmony_ci#ifdef _SC_GETGR_R_SIZE_MAX
4953a5a1b3Sopenharmony_ci    n = sysconf(_SC_GETGR_R_SIZE_MAX);
5053a5a1b3Sopenharmony_ci#else
5153a5a1b3Sopenharmony_ci    n = -1;
5253a5a1b3Sopenharmony_ci#endif
5353a5a1b3Sopenharmony_ci    if (n <= 0)
5453a5a1b3Sopenharmony_ci        n = 512;
5553a5a1b3Sopenharmony_ci
5653a5a1b3Sopenharmony_ci    full_size = (size_t) n + sizeof(struct group);
5753a5a1b3Sopenharmony_ci
5853a5a1b3Sopenharmony_ci    if (full_size < (size_t) n) /* check for integer overflow */
5953a5a1b3Sopenharmony_ci        return (size_t) n;
6053a5a1b3Sopenharmony_ci
6153a5a1b3Sopenharmony_ci    return full_size;
6253a5a1b3Sopenharmony_ci}
6353a5a1b3Sopenharmony_ci
6453a5a1b3Sopenharmony_ci/* Returns a suitable starting size for a getpwnam_r() or getpwuid_r() buffer,
6553a5a1b3Sopenharmony_ci   plus the size of a struct passwd.
6653a5a1b3Sopenharmony_ci */
6753a5a1b3Sopenharmony_cistatic size_t starting_getpw_buflen(void) {
6853a5a1b3Sopenharmony_ci    long n;
6953a5a1b3Sopenharmony_ci    size_t full_size;
7053a5a1b3Sopenharmony_ci
7153a5a1b3Sopenharmony_ci#ifdef _SC_GETPW_R_SIZE_MAX
7253a5a1b3Sopenharmony_ci    n = sysconf(_SC_GETPW_R_SIZE_MAX);
7353a5a1b3Sopenharmony_ci#else
7453a5a1b3Sopenharmony_ci    n = -1;
7553a5a1b3Sopenharmony_ci#endif
7653a5a1b3Sopenharmony_ci    if (n <= 0)
7753a5a1b3Sopenharmony_ci        n = 512;
7853a5a1b3Sopenharmony_ci
7953a5a1b3Sopenharmony_ci    full_size = (size_t) n + sizeof(struct passwd);
8053a5a1b3Sopenharmony_ci
8153a5a1b3Sopenharmony_ci    if (full_size < (size_t) n) /* check for integer overflow */
8253a5a1b3Sopenharmony_ci        return (size_t) n;
8353a5a1b3Sopenharmony_ci
8453a5a1b3Sopenharmony_ci    return full_size;
8553a5a1b3Sopenharmony_ci}
8653a5a1b3Sopenharmony_ci
8753a5a1b3Sopenharmony_ci/* Given a memory allocation (*bufptr) and its length (*buflenptr),
8853a5a1b3Sopenharmony_ci   double the size of the allocation, updating the given buffer and length
8953a5a1b3Sopenharmony_ci   arguments. This function should be used in conjunction with the pa_*alloc
9053a5a1b3Sopenharmony_ci   and pa_xfree functions.
9153a5a1b3Sopenharmony_ci
9253a5a1b3Sopenharmony_ci   Unlike realloc(), this function does *not* retain the original buffer's
9353a5a1b3Sopenharmony_ci   contents.
9453a5a1b3Sopenharmony_ci
9553a5a1b3Sopenharmony_ci   Returns 0 on success, nonzero on error. The error cause is indicated by
9653a5a1b3Sopenharmony_ci   errno.
9753a5a1b3Sopenharmony_ci */
9853a5a1b3Sopenharmony_cistatic int expand_buffer_trashcontents(void **bufptr, size_t *buflenptr) {
9953a5a1b3Sopenharmony_ci    size_t newlen;
10053a5a1b3Sopenharmony_ci
10153a5a1b3Sopenharmony_ci    if (!bufptr || !*bufptr || !buflenptr) {
10253a5a1b3Sopenharmony_ci        errno = EINVAL;
10353a5a1b3Sopenharmony_ci        return -1;
10453a5a1b3Sopenharmony_ci    }
10553a5a1b3Sopenharmony_ci
10653a5a1b3Sopenharmony_ci    newlen = *buflenptr * 2;
10753a5a1b3Sopenharmony_ci
10853a5a1b3Sopenharmony_ci    if (newlen < *buflenptr) {
10953a5a1b3Sopenharmony_ci        errno = EOVERFLOW;
11053a5a1b3Sopenharmony_ci        return -1;
11153a5a1b3Sopenharmony_ci    }
11253a5a1b3Sopenharmony_ci
11353a5a1b3Sopenharmony_ci    /* Don't bother retaining memory contents; free & alloc anew */
11453a5a1b3Sopenharmony_ci    pa_xfree(*bufptr);
11553a5a1b3Sopenharmony_ci
11653a5a1b3Sopenharmony_ci    *bufptr = pa_xmalloc(newlen);
11753a5a1b3Sopenharmony_ci    *buflenptr = newlen;
11853a5a1b3Sopenharmony_ci
11953a5a1b3Sopenharmony_ci    return 0;
12053a5a1b3Sopenharmony_ci}
12153a5a1b3Sopenharmony_ci
12253a5a1b3Sopenharmony_ci#ifdef HAVE_GETGRGID_R
12353a5a1b3Sopenharmony_ci/* Thread-safe getgrgid() replacement.
12453a5a1b3Sopenharmony_ci   Returned value should be freed using pa_getgrgid_free() when the caller is
12553a5a1b3Sopenharmony_ci   finished with the returned group data.
12653a5a1b3Sopenharmony_ci
12753a5a1b3Sopenharmony_ci   API is the same as getgrgid(), errors are indicated by a NULL return;
12853a5a1b3Sopenharmony_ci   consult errno for the error cause (zero it before calling).
12953a5a1b3Sopenharmony_ci */
13053a5a1b3Sopenharmony_cistruct group *pa_getgrgid_malloc(gid_t gid) {
13153a5a1b3Sopenharmony_ci    size_t buflen, getgr_buflen;
13253a5a1b3Sopenharmony_ci    int err;
13353a5a1b3Sopenharmony_ci    void *buf;
13453a5a1b3Sopenharmony_ci    void *getgr_buf;
13553a5a1b3Sopenharmony_ci    struct group *result = NULL;
13653a5a1b3Sopenharmony_ci
13753a5a1b3Sopenharmony_ci    buflen = starting_getgr_buflen();
13853a5a1b3Sopenharmony_ci    buf = pa_xmalloc(buflen);
13953a5a1b3Sopenharmony_ci
14053a5a1b3Sopenharmony_ci    getgr_buflen = buflen - sizeof(struct group);
14153a5a1b3Sopenharmony_ci    getgr_buf = (char *)buf + sizeof(struct group);
14253a5a1b3Sopenharmony_ci
14353a5a1b3Sopenharmony_ci    while ((err = getgrgid_r(gid, (struct group *)buf, getgr_buf, getgr_buflen, &result)) == ERANGE) {
14453a5a1b3Sopenharmony_ci        if (expand_buffer_trashcontents(&buf, &buflen))
14553a5a1b3Sopenharmony_ci            break;
14653a5a1b3Sopenharmony_ci
14753a5a1b3Sopenharmony_ci        getgr_buflen = buflen - sizeof(struct group);
14853a5a1b3Sopenharmony_ci        getgr_buf = (char *)buf + sizeof(struct group);
14953a5a1b3Sopenharmony_ci    }
15053a5a1b3Sopenharmony_ci
15153a5a1b3Sopenharmony_ci    if (err || !result) {
15253a5a1b3Sopenharmony_ci        result = NULL;
15353a5a1b3Sopenharmony_ci        if (buf) {
15453a5a1b3Sopenharmony_ci            pa_xfree(buf);
15553a5a1b3Sopenharmony_ci            buf = NULL;
15653a5a1b3Sopenharmony_ci        }
15753a5a1b3Sopenharmony_ci    }
15853a5a1b3Sopenharmony_ci
15953a5a1b3Sopenharmony_ci    pa_assert(result == buf || result == NULL);
16053a5a1b3Sopenharmony_ci
16153a5a1b3Sopenharmony_ci    return result;
16253a5a1b3Sopenharmony_ci}
16353a5a1b3Sopenharmony_ci
16453a5a1b3Sopenharmony_civoid pa_getgrgid_free(struct group *grp) {
16553a5a1b3Sopenharmony_ci    pa_xfree(grp);
16653a5a1b3Sopenharmony_ci}
16753a5a1b3Sopenharmony_ci
16853a5a1b3Sopenharmony_ci#else /* !HAVE_GETGRGID_R */
16953a5a1b3Sopenharmony_ci
17053a5a1b3Sopenharmony_cistruct group *pa_getgrgid_malloc(gid_t gid) {
17153a5a1b3Sopenharmony_ci    return getgrgid(gid);
17253a5a1b3Sopenharmony_ci}
17353a5a1b3Sopenharmony_ci
17453a5a1b3Sopenharmony_civoid pa_getgrgid_free(struct group *grp) {
17553a5a1b3Sopenharmony_ci    /* nothing */
17653a5a1b3Sopenharmony_ci    return;
17753a5a1b3Sopenharmony_ci}
17853a5a1b3Sopenharmony_ci
17953a5a1b3Sopenharmony_ci#endif /* !HAVE_GETGRGID_R */
18053a5a1b3Sopenharmony_ci
18153a5a1b3Sopenharmony_ci#ifdef HAVE_GETGRNAM_R
18253a5a1b3Sopenharmony_ci/* Thread-safe getgrnam() function.
18353a5a1b3Sopenharmony_ci   Returned value should be freed using pa_getgrnam_free() when the caller is
18453a5a1b3Sopenharmony_ci   finished with the returned group data.
18553a5a1b3Sopenharmony_ci
18653a5a1b3Sopenharmony_ci   API is the same as getgrnam(), errors are indicated by a NULL return;
18753a5a1b3Sopenharmony_ci   consult errno for the error cause (zero it before calling).
18853a5a1b3Sopenharmony_ci */
18953a5a1b3Sopenharmony_cistruct group *pa_getgrnam_malloc(const char *name) {
19053a5a1b3Sopenharmony_ci    size_t buflen, getgr_buflen;
19153a5a1b3Sopenharmony_ci    int err;
19253a5a1b3Sopenharmony_ci    void *buf;
19353a5a1b3Sopenharmony_ci    void *getgr_buf;
19453a5a1b3Sopenharmony_ci    struct group *result = NULL;
19553a5a1b3Sopenharmony_ci
19653a5a1b3Sopenharmony_ci    buflen = starting_getgr_buflen();
19753a5a1b3Sopenharmony_ci    buf = pa_xmalloc(buflen);
19853a5a1b3Sopenharmony_ci
19953a5a1b3Sopenharmony_ci    getgr_buflen = buflen - sizeof(struct group);
20053a5a1b3Sopenharmony_ci    getgr_buf = (char *)buf + sizeof(struct group);
20153a5a1b3Sopenharmony_ci
20253a5a1b3Sopenharmony_ci    while ((err = getgrnam_r(name, (struct group *)buf, getgr_buf, getgr_buflen, &result)) == ERANGE) {
20353a5a1b3Sopenharmony_ci        if (expand_buffer_trashcontents(&buf, &buflen))
20453a5a1b3Sopenharmony_ci            break;
20553a5a1b3Sopenharmony_ci
20653a5a1b3Sopenharmony_ci        getgr_buflen = buflen - sizeof(struct group);
20753a5a1b3Sopenharmony_ci        getgr_buf = (char *)buf + sizeof(struct group);
20853a5a1b3Sopenharmony_ci    }
20953a5a1b3Sopenharmony_ci
21053a5a1b3Sopenharmony_ci    if (err || !result) {
21153a5a1b3Sopenharmony_ci        result = NULL;
21253a5a1b3Sopenharmony_ci        if (buf) {
21353a5a1b3Sopenharmony_ci            pa_xfree(buf);
21453a5a1b3Sopenharmony_ci            buf = NULL;
21553a5a1b3Sopenharmony_ci        }
21653a5a1b3Sopenharmony_ci    }
21753a5a1b3Sopenharmony_ci
21853a5a1b3Sopenharmony_ci    pa_assert(result == buf || result == NULL);
21953a5a1b3Sopenharmony_ci
22053a5a1b3Sopenharmony_ci    return result;
22153a5a1b3Sopenharmony_ci}
22253a5a1b3Sopenharmony_ci
22353a5a1b3Sopenharmony_civoid pa_getgrnam_free(struct group *group) {
22453a5a1b3Sopenharmony_ci    pa_xfree(group);
22553a5a1b3Sopenharmony_ci}
22653a5a1b3Sopenharmony_ci
22753a5a1b3Sopenharmony_ci#else /* !HAVE_GETGRNAM_R */
22853a5a1b3Sopenharmony_ci
22953a5a1b3Sopenharmony_cistruct group *pa_getgrnam_malloc(const char *name) {
23053a5a1b3Sopenharmony_ci    return getgrnam(name);
23153a5a1b3Sopenharmony_ci}
23253a5a1b3Sopenharmony_ci
23353a5a1b3Sopenharmony_civoid pa_getgrnam_free(struct group *group) {
23453a5a1b3Sopenharmony_ci    /* nothing */
23553a5a1b3Sopenharmony_ci    return;
23653a5a1b3Sopenharmony_ci}
23753a5a1b3Sopenharmony_ci
23853a5a1b3Sopenharmony_ci#endif /* HAVE_GETGRNAM_R */
23953a5a1b3Sopenharmony_ci
24053a5a1b3Sopenharmony_ci#endif /* HAVE_GRP_H */
24153a5a1b3Sopenharmony_ci
24253a5a1b3Sopenharmony_ci#ifdef HAVE_PWD_H
24353a5a1b3Sopenharmony_ci
24453a5a1b3Sopenharmony_ci#ifdef HAVE_GETPWNAM_R
24553a5a1b3Sopenharmony_ci/* Thread-safe getpwnam() function.
24653a5a1b3Sopenharmony_ci   Returned value should be freed using pa_getpwnam_free() when the caller is
24753a5a1b3Sopenharmony_ci   finished with the returned passwd data.
24853a5a1b3Sopenharmony_ci
24953a5a1b3Sopenharmony_ci   API is the same as getpwnam(), errors are indicated by a NULL return;
25053a5a1b3Sopenharmony_ci   consult errno for the error cause (zero it before calling).
25153a5a1b3Sopenharmony_ci */
25253a5a1b3Sopenharmony_cistruct passwd *pa_getpwnam_malloc(const char *name) {
25353a5a1b3Sopenharmony_ci    size_t buflen, getpw_buflen;
25453a5a1b3Sopenharmony_ci    int err;
25553a5a1b3Sopenharmony_ci    void *buf;
25653a5a1b3Sopenharmony_ci    void *getpw_buf;
25753a5a1b3Sopenharmony_ci    struct passwd *result = NULL;
25853a5a1b3Sopenharmony_ci
25953a5a1b3Sopenharmony_ci    buflen = starting_getpw_buflen();
26053a5a1b3Sopenharmony_ci    buf = pa_xmalloc(buflen);
26153a5a1b3Sopenharmony_ci
26253a5a1b3Sopenharmony_ci    getpw_buflen = buflen - sizeof(struct passwd);
26353a5a1b3Sopenharmony_ci    getpw_buf = (char *)buf + sizeof(struct passwd);
26453a5a1b3Sopenharmony_ci
26553a5a1b3Sopenharmony_ci    while ((err = getpwnam_r(name, (struct passwd *)buf, getpw_buf, getpw_buflen, &result)) == ERANGE) {
26653a5a1b3Sopenharmony_ci        if (expand_buffer_trashcontents(&buf, &buflen))
26753a5a1b3Sopenharmony_ci            break;
26853a5a1b3Sopenharmony_ci
26953a5a1b3Sopenharmony_ci        getpw_buflen = buflen - sizeof(struct passwd);
27053a5a1b3Sopenharmony_ci        getpw_buf = (char *)buf + sizeof(struct passwd);
27153a5a1b3Sopenharmony_ci    }
27253a5a1b3Sopenharmony_ci
27353a5a1b3Sopenharmony_ci    if (err || !result) {
27453a5a1b3Sopenharmony_ci        result = NULL;
27553a5a1b3Sopenharmony_ci        if (buf) {
27653a5a1b3Sopenharmony_ci            pa_xfree(buf);
27753a5a1b3Sopenharmony_ci            buf = NULL;
27853a5a1b3Sopenharmony_ci        }
27953a5a1b3Sopenharmony_ci    }
28053a5a1b3Sopenharmony_ci
28153a5a1b3Sopenharmony_ci    pa_assert(result == buf || result == NULL);
28253a5a1b3Sopenharmony_ci
28353a5a1b3Sopenharmony_ci    return result;
28453a5a1b3Sopenharmony_ci}
28553a5a1b3Sopenharmony_ci
28653a5a1b3Sopenharmony_civoid pa_getpwnam_free(struct passwd *passwd) {
28753a5a1b3Sopenharmony_ci    pa_xfree(passwd);
28853a5a1b3Sopenharmony_ci}
28953a5a1b3Sopenharmony_ci
29053a5a1b3Sopenharmony_ci#else /* !HAVE_GETPWNAM_R */
29153a5a1b3Sopenharmony_ci
29253a5a1b3Sopenharmony_cistruct passwd *pa_getpwnam_malloc(const char *name) {
29353a5a1b3Sopenharmony_ci    return getpwnam(name);
29453a5a1b3Sopenharmony_ci}
29553a5a1b3Sopenharmony_ci
29653a5a1b3Sopenharmony_civoid pa_getpwnam_free(struct passwd *passwd) {
29753a5a1b3Sopenharmony_ci    /* nothing */
29853a5a1b3Sopenharmony_ci    return;
29953a5a1b3Sopenharmony_ci}
30053a5a1b3Sopenharmony_ci
30153a5a1b3Sopenharmony_ci#endif /* !HAVE_GETPWNAM_R */
30253a5a1b3Sopenharmony_ci
30353a5a1b3Sopenharmony_ci#ifdef HAVE_GETPWUID_R
30453a5a1b3Sopenharmony_ci/* Thread-safe getpwuid() function.
30553a5a1b3Sopenharmony_ci   Returned value should be freed using pa_getpwuid_free() when the caller is
30653a5a1b3Sopenharmony_ci   finished with the returned group data.
30753a5a1b3Sopenharmony_ci
30853a5a1b3Sopenharmony_ci   API is the same as getpwuid(), errors are indicated by a NULL return;
30953a5a1b3Sopenharmony_ci   consult errno for the error cause (zero it before calling).
31053a5a1b3Sopenharmony_ci */
31153a5a1b3Sopenharmony_cistruct passwd *pa_getpwuid_malloc(uid_t uid) {
31253a5a1b3Sopenharmony_ci    size_t buflen, getpw_buflen;
31353a5a1b3Sopenharmony_ci    int err;
31453a5a1b3Sopenharmony_ci    void *buf;
31553a5a1b3Sopenharmony_ci    void *getpw_buf;
31653a5a1b3Sopenharmony_ci    struct passwd *result = NULL;
31753a5a1b3Sopenharmony_ci
31853a5a1b3Sopenharmony_ci    buflen = starting_getpw_buflen();
31953a5a1b3Sopenharmony_ci    buf = pa_xmalloc(buflen);
32053a5a1b3Sopenharmony_ci
32153a5a1b3Sopenharmony_ci    getpw_buflen = buflen - sizeof(struct passwd);
32253a5a1b3Sopenharmony_ci    getpw_buf = (char *)buf + sizeof(struct passwd);
32353a5a1b3Sopenharmony_ci
32453a5a1b3Sopenharmony_ci    while ((err = getpwuid_r(uid, (struct passwd *)buf, getpw_buf, getpw_buflen, &result)) == ERANGE) {
32553a5a1b3Sopenharmony_ci        if (expand_buffer_trashcontents(&buf, &buflen))
32653a5a1b3Sopenharmony_ci            break;
32753a5a1b3Sopenharmony_ci
32853a5a1b3Sopenharmony_ci        getpw_buflen = buflen - sizeof(struct passwd);
32953a5a1b3Sopenharmony_ci        getpw_buf = (char *)buf + sizeof(struct passwd);
33053a5a1b3Sopenharmony_ci    }
33153a5a1b3Sopenharmony_ci
33253a5a1b3Sopenharmony_ci    if (err || !result) {
33353a5a1b3Sopenharmony_ci        result = NULL;
33453a5a1b3Sopenharmony_ci        if (buf) {
33553a5a1b3Sopenharmony_ci            pa_xfree(buf);
33653a5a1b3Sopenharmony_ci            buf = NULL;
33753a5a1b3Sopenharmony_ci        }
33853a5a1b3Sopenharmony_ci    }
33953a5a1b3Sopenharmony_ci
34053a5a1b3Sopenharmony_ci    pa_assert(result == buf || result == NULL);
34153a5a1b3Sopenharmony_ci
34253a5a1b3Sopenharmony_ci    return result;
34353a5a1b3Sopenharmony_ci}
34453a5a1b3Sopenharmony_ci
34553a5a1b3Sopenharmony_civoid pa_getpwuid_free(struct passwd *passwd) {
34653a5a1b3Sopenharmony_ci    pa_xfree(passwd);
34753a5a1b3Sopenharmony_ci}
34853a5a1b3Sopenharmony_ci
34953a5a1b3Sopenharmony_ci#else /* !HAVE_GETPWUID_R */
35053a5a1b3Sopenharmony_ci
35153a5a1b3Sopenharmony_cistruct passwd *pa_getpwuid_malloc(uid_t uid) {
35253a5a1b3Sopenharmony_ci    return getpwuid(uid);
35353a5a1b3Sopenharmony_ci}
35453a5a1b3Sopenharmony_ci
35553a5a1b3Sopenharmony_civoid pa_getpwuid_free(struct passwd *passwd) {
35653a5a1b3Sopenharmony_ci    /* nothing */
35753a5a1b3Sopenharmony_ci    return;
35853a5a1b3Sopenharmony_ci}
35953a5a1b3Sopenharmony_ci
36053a5a1b3Sopenharmony_ci#endif /* !HAVE_GETPWUID_R */
36153a5a1b3Sopenharmony_ci
36253a5a1b3Sopenharmony_ci#endif /* HAVE_PWD_H */
363