mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-07 13:30:03 -05:00
FSF addresses used in PA sources are no longer valid and rpmlint generates numerous warnings during packaging because of this. This patch changes all FSF addresses to FSF web page according to the GPL how-to: https://www.gnu.org/licenses/gpl-howto.en.html Done automatically by sed-ing through sources.
362 lines
8.6 KiB
C
362 lines
8.6 KiB
C
/***
|
|
This file is part of PulseAudio.
|
|
|
|
Copyright 2009 Ted Percival
|
|
|
|
PulseAudio is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as
|
|
published by the Free Software Foundation; either version 2.1 of the
|
|
License, or (at your option) any later version.
|
|
|
|
PulseAudio is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
|
***/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
|
|
#ifdef HAVE_PWD_H
|
|
#include <pwd.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_GRP_H
|
|
#include <grp.h>
|
|
#endif
|
|
|
|
#include <pulse/xmalloc.h>
|
|
#include <pulsecore/macro.h>
|
|
|
|
#include "usergroup.h"
|
|
|
|
#ifdef HAVE_GRP_H
|
|
|
|
/* Returns a suitable starting size for a getgrnam_r() or getgrgid_r() buffer,
|
|
plus the size of a struct group.
|
|
*/
|
|
static size_t starting_getgr_buflen(void) {
|
|
size_t full_size;
|
|
long n;
|
|
#ifdef _SC_GETGR_R_SIZE_MAX
|
|
n = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
#else
|
|
n = -1;
|
|
#endif
|
|
if (n <= 0)
|
|
n = 512;
|
|
|
|
full_size = (size_t) n + sizeof(struct group);
|
|
|
|
if (full_size < (size_t) n) /* check for integer overflow */
|
|
return (size_t) n;
|
|
|
|
return full_size;
|
|
}
|
|
|
|
/* Returns a suitable starting size for a getpwnam_r() or getpwuid_r() buffer,
|
|
plus the size of a struct passwd.
|
|
*/
|
|
static size_t starting_getpw_buflen(void) {
|
|
long n;
|
|
size_t full_size;
|
|
|
|
#ifdef _SC_GETPW_R_SIZE_MAX
|
|
n = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
#else
|
|
n = -1;
|
|
#endif
|
|
if (n <= 0)
|
|
n = 512;
|
|
|
|
full_size = (size_t) n + sizeof(struct passwd);
|
|
|
|
if (full_size < (size_t) n) /* check for integer overflow */
|
|
return (size_t) n;
|
|
|
|
return full_size;
|
|
}
|
|
|
|
/* Given a memory allocation (*bufptr) and its length (*buflenptr),
|
|
double the size of the allocation, updating the given buffer and length
|
|
arguments. This function should be used in conjunction with the pa_*alloc
|
|
and pa_xfree functions.
|
|
|
|
Unlike realloc(), this function does *not* retain the original buffer's
|
|
contents.
|
|
|
|
Returns 0 on success, nonzero on error. The error cause is indicated by
|
|
errno.
|
|
*/
|
|
static int expand_buffer_trashcontents(void **bufptr, size_t *buflenptr) {
|
|
size_t newlen;
|
|
|
|
if (!bufptr || !*bufptr || !buflenptr) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
newlen = *buflenptr * 2;
|
|
|
|
if (newlen < *buflenptr) {
|
|
errno = EOVERFLOW;
|
|
return -1;
|
|
}
|
|
|
|
/* Don't bother retaining memory contents; free & alloc anew */
|
|
pa_xfree(*bufptr);
|
|
|
|
*bufptr = pa_xmalloc(newlen);
|
|
*buflenptr = newlen;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HAVE_GETGRGID_R
|
|
/* Thread-safe getgrgid() replacement.
|
|
Returned value should be freed using pa_getgrgid_free() when the caller is
|
|
finished with the returned group data.
|
|
|
|
API is the same as getgrgid(), errors are indicated by a NULL return;
|
|
consult errno for the error cause (zero it before calling).
|
|
*/
|
|
struct group *pa_getgrgid_malloc(gid_t gid) {
|
|
size_t buflen, getgr_buflen;
|
|
int err;
|
|
void *buf;
|
|
void *getgr_buf;
|
|
struct group *result = NULL;
|
|
|
|
buflen = starting_getgr_buflen();
|
|
buf = pa_xmalloc(buflen);
|
|
|
|
getgr_buflen = buflen - sizeof(struct group);
|
|
getgr_buf = (char *)buf + sizeof(struct group);
|
|
|
|
while ((err = getgrgid_r(gid, (struct group *)buf, getgr_buf, getgr_buflen, &result)) == ERANGE) {
|
|
if (expand_buffer_trashcontents(&buf, &buflen))
|
|
break;
|
|
|
|
getgr_buflen = buflen - sizeof(struct group);
|
|
getgr_buf = (char *)buf + sizeof(struct group);
|
|
}
|
|
|
|
if (err || !result) {
|
|
result = NULL;
|
|
if (buf) {
|
|
pa_xfree(buf);
|
|
buf = NULL;
|
|
}
|
|
}
|
|
|
|
pa_assert(result == buf || result == NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
void pa_getgrgid_free(struct group *grp) {
|
|
pa_xfree(grp);
|
|
}
|
|
|
|
#else /* !HAVE_GETGRGID_R */
|
|
|
|
struct group *pa_getgrgid_malloc(gid_t gid) {
|
|
return getgrgid(gid);
|
|
}
|
|
|
|
void pa_getgrgid_free(struct group *grp) {
|
|
/* nothing */
|
|
return;
|
|
}
|
|
|
|
#endif /* !HAVE_GETGRGID_R */
|
|
|
|
#ifdef HAVE_GETGRNAM_R
|
|
/* Thread-safe getgrnam() function.
|
|
Returned value should be freed using pa_getgrnam_free() when the caller is
|
|
finished with the returned group data.
|
|
|
|
API is the same as getgrnam(), errors are indicated by a NULL return;
|
|
consult errno for the error cause (zero it before calling).
|
|
*/
|
|
struct group *pa_getgrnam_malloc(const char *name) {
|
|
size_t buflen, getgr_buflen;
|
|
int err;
|
|
void *buf;
|
|
void *getgr_buf;
|
|
struct group *result = NULL;
|
|
|
|
buflen = starting_getgr_buflen();
|
|
buf = pa_xmalloc(buflen);
|
|
|
|
getgr_buflen = buflen - sizeof(struct group);
|
|
getgr_buf = (char *)buf + sizeof(struct group);
|
|
|
|
while ((err = getgrnam_r(name, (struct group *)buf, getgr_buf, getgr_buflen, &result)) == ERANGE) {
|
|
if (expand_buffer_trashcontents(&buf, &buflen))
|
|
break;
|
|
|
|
getgr_buflen = buflen - sizeof(struct group);
|
|
getgr_buf = (char *)buf + sizeof(struct group);
|
|
}
|
|
|
|
if (err || !result) {
|
|
result = NULL;
|
|
if (buf) {
|
|
pa_xfree(buf);
|
|
buf = NULL;
|
|
}
|
|
}
|
|
|
|
pa_assert(result == buf || result == NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
void pa_getgrnam_free(struct group *group) {
|
|
pa_xfree(group);
|
|
}
|
|
|
|
#else /* !HAVE_GETGRNAM_R */
|
|
|
|
struct group *pa_getgrnam_malloc(const char *name) {
|
|
return getgrnam(name);
|
|
}
|
|
|
|
void pa_getgrnam_free(struct group *group) {
|
|
/* nothing */
|
|
return;
|
|
}
|
|
|
|
#endif /* HAVE_GETGRNAM_R */
|
|
|
|
#endif /* HAVE_GRP_H */
|
|
|
|
#ifdef HAVE_PWD_H
|
|
|
|
#ifdef HAVE_GETPWNAM_R
|
|
/* Thread-safe getpwnam() function.
|
|
Returned value should be freed using pa_getpwnam_free() when the caller is
|
|
finished with the returned passwd data.
|
|
|
|
API is the same as getpwnam(), errors are indicated by a NULL return;
|
|
consult errno for the error cause (zero it before calling).
|
|
*/
|
|
struct passwd *pa_getpwnam_malloc(const char *name) {
|
|
size_t buflen, getpw_buflen;
|
|
int err;
|
|
void *buf;
|
|
void *getpw_buf;
|
|
struct passwd *result = NULL;
|
|
|
|
buflen = starting_getpw_buflen();
|
|
buf = pa_xmalloc(buflen);
|
|
|
|
getpw_buflen = buflen - sizeof(struct passwd);
|
|
getpw_buf = (char *)buf + sizeof(struct passwd);
|
|
|
|
while ((err = getpwnam_r(name, (struct passwd *)buf, getpw_buf, getpw_buflen, &result)) == ERANGE) {
|
|
if (expand_buffer_trashcontents(&buf, &buflen))
|
|
break;
|
|
|
|
getpw_buflen = buflen - sizeof(struct passwd);
|
|
getpw_buf = (char *)buf + sizeof(struct passwd);
|
|
}
|
|
|
|
if (err || !result) {
|
|
result = NULL;
|
|
if (buf) {
|
|
pa_xfree(buf);
|
|
buf = NULL;
|
|
}
|
|
}
|
|
|
|
pa_assert(result == buf || result == NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
void pa_getpwnam_free(struct passwd *passwd) {
|
|
pa_xfree(passwd);
|
|
}
|
|
|
|
#else /* !HAVE_GETPWNAM_R */
|
|
|
|
struct passwd *pa_getpwnam_malloc(const char *name) {
|
|
return getpwnam(name);
|
|
}
|
|
|
|
void pa_getpwnam_free(struct passwd *passwd) {
|
|
/* nothing */
|
|
return;
|
|
}
|
|
|
|
#endif /* !HAVE_GETPWNAM_R */
|
|
|
|
#ifdef HAVE_GETPWUID_R
|
|
/* Thread-safe getpwuid() function.
|
|
Returned value should be freed using pa_getpwuid_free() when the caller is
|
|
finished with the returned group data.
|
|
|
|
API is the same as getpwuid(), errors are indicated by a NULL return;
|
|
consult errno for the error cause (zero it before calling).
|
|
*/
|
|
struct passwd *pa_getpwuid_malloc(uid_t uid) {
|
|
size_t buflen, getpw_buflen;
|
|
int err;
|
|
void *buf;
|
|
void *getpw_buf;
|
|
struct passwd *result = NULL;
|
|
|
|
buflen = starting_getpw_buflen();
|
|
buf = pa_xmalloc(buflen);
|
|
|
|
getpw_buflen = buflen - sizeof(struct passwd);
|
|
getpw_buf = (char *)buf + sizeof(struct passwd);
|
|
|
|
while ((err = getpwuid_r(uid, (struct passwd *)buf, getpw_buf, getpw_buflen, &result)) == ERANGE) {
|
|
if (expand_buffer_trashcontents(&buf, &buflen))
|
|
break;
|
|
|
|
getpw_buflen = buflen - sizeof(struct passwd);
|
|
getpw_buf = (char *)buf + sizeof(struct passwd);
|
|
}
|
|
|
|
if (err || !result) {
|
|
result = NULL;
|
|
if (buf) {
|
|
pa_xfree(buf);
|
|
buf = NULL;
|
|
}
|
|
}
|
|
|
|
pa_assert(result == buf || result == NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
void pa_getpwuid_free(struct passwd *passwd) {
|
|
pa_xfree(passwd);
|
|
}
|
|
|
|
#else /* !HAVE_GETPWUID_R */
|
|
|
|
struct passwd *pa_getpwuid_malloc(uid_t uid) {
|
|
return getpwuid(uid);
|
|
}
|
|
|
|
void pa_getpwuid_free(struct passwd *passwd) {
|
|
/* nothing */
|
|
return;
|
|
}
|
|
|
|
#endif /* !HAVE_GETPWUID_R */
|
|
|
|
#endif /* HAVE_PWD_H */
|