]>
code.delx.au - pulseaudio/blob - src/pulsecore/usergroup.c
2 This file is part of PulseAudio.
4 Copyright 2009 Ted Percival
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include <sys/types.h>
37 #include <pulse/xmalloc.h>
38 #include <pulsecore/macro.h>
40 #include "usergroup.h"
44 /* Returns a suitable starting size for a getgrnam_r() or getgrgid_r() buffer,
45 plus the size of a struct group.
47 static size_t starting_getgr_buflen(void) {
50 #ifdef _SC_GETGR_R_SIZE_MAX
51 n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
58 full_size
= (size_t) n
+ sizeof(struct group
);
60 if (full_size
< (size_t) n
) /* check for integer overflow */
66 /* Returns a suitable starting size for a getpwnam_r() or getpwuid_r() buffer,
67 plus the size of a struct passwd.
69 static size_t starting_getpw_buflen(void) {
73 #ifdef _SC_GETPW_R_SIZE_MAX
74 n
= sysconf(_SC_GETPW_R_SIZE_MAX
);
81 full_size
= (size_t) n
+ sizeof(struct passwd
);
83 if (full_size
< (size_t) n
) /* check for integer overflow */
89 /* Given a memory allocation (*bufptr) and its length (*buflenptr),
90 double the size of the allocation, updating the given buffer and length
91 arguments. This function should be used in conjunction with the pa_*alloc
92 and pa_xfree functions.
94 Unlike realloc(), this function does *not* retain the original buffer's
97 Returns 0 on success, nonzero on error. The error cause is indicated by
100 static int expand_buffer_trashcontents(void **bufptr
, size_t *buflenptr
) {
103 if (!bufptr
|| !*bufptr
|| !buflenptr
) {
108 newlen
= *buflenptr
* 2;
110 if (newlen
< *buflenptr
) {
115 /* Don't bother retaining memory contents; free & alloc anew */
118 *bufptr
= pa_xmalloc(newlen
);
124 #ifdef HAVE_GETGRGID_R
125 /* Thread-safe getgrgid() replacement.
126 Returned value should be freed using pa_getgrgid_free() when the caller is
127 finished with the returned group data.
129 API is the same as getgrgid(), errors are indicated by a NULL return;
130 consult errno for the error cause (zero it before calling).
131 The returned value must be freed using pa_xfree().
133 struct group
*pa_getgrgid_malloc(gid_t gid
) {
134 size_t buflen
, getgr_buflen
;
138 struct group
*result
= NULL
;
140 buflen
= starting_getgr_buflen();
141 buf
= pa_xmalloc(buflen
);
143 getgr_buflen
= buflen
- sizeof(struct group
);
144 getgr_buf
= (char *)buf
+ sizeof(struct group
);
146 while ((err
= getgrgid_r(gid
, (struct group
*)buf
, getgr_buf
,
147 getgr_buflen
, &result
)) == ERANGE
)
149 if (expand_buffer_trashcontents(&buf
, &buflen
))
152 getgr_buflen
= buflen
- sizeof(struct group
);
153 getgr_buf
= (char *)buf
+ sizeof(struct group
);
156 if (err
|| !result
) {
164 pa_assert(result
== buf
|| result
== NULL
);
169 void pa_getgrgid_free(struct group
*grp
) {
173 #else /* !HAVE_GETGRGID_R */
175 struct group
*pa_getgrgid_malloc(gid_t gid
) {
176 return getgrgid(gid
);
179 void pa_getgrgid_free(struct group
*grp
) {
184 #endif /* !HAVE_GETGRGID_R */
186 #ifdef HAVE_GETGRNAM_R
187 /* Thread-safe getgrnam() function.
188 Returned value should be freed using pa_getgrnam_free() when the caller is
189 finished with the returned group data.
191 API is the same as getgrnam(), errors are indicated by a NULL return;
192 consult errno for the error cause (zero it before calling).
193 The returned value must be freed using pa_xfree().
195 struct group
*pa_getgrnam_malloc(const char *name
) {
196 size_t buflen
, getgr_buflen
;
200 struct group
*result
= NULL
;
202 buflen
= starting_getgr_buflen();
203 buf
= pa_xmalloc(buflen
);
205 getgr_buflen
= buflen
- sizeof(struct group
);
206 getgr_buf
= (char *)buf
+ sizeof(struct group
);
208 while ((err
= getgrnam_r(name
, (struct group
*)buf
, getgr_buf
,
209 getgr_buflen
, &result
)) == ERANGE
)
211 if (expand_buffer_trashcontents(&buf
, &buflen
))
214 getgr_buflen
= buflen
- sizeof(struct group
);
215 getgr_buf
= (char *)buf
+ sizeof(struct group
);
218 if (err
|| !result
) {
226 pa_assert(result
== buf
|| result
== NULL
);
231 void pa_getgrnam_free(struct group
*group
) {
235 #else /* !HAVE_GETGRNAM_R */
237 struct group
*pa_getgrnam_malloc(const char *name
) {
238 return getgrnam(name
);
241 void pa_getgrnam_free(struct group
*group
) {
246 #endif /* HAVE_GETGRNAM_R */
248 #endif /* HAVE_GRP_H */
252 #ifdef HAVE_GETPWNAM_R
253 /* Thread-safe getpwnam() function.
254 Returned value should be freed using pa_getpwnam_free() when the caller is
255 finished with the returned passwd data.
257 API is the same as getpwnam(), errors are indicated by a NULL return;
258 consult errno for the error cause (zero it before calling).
259 The returned value must be freed using pa_xfree().
261 struct passwd
*pa_getpwnam_malloc(const char *name
) {
262 size_t buflen
, getpw_buflen
;
266 struct passwd
*result
= NULL
;
268 buflen
= starting_getpw_buflen();
269 buf
= pa_xmalloc(buflen
);
271 getpw_buflen
= buflen
- sizeof(struct passwd
);
272 getpw_buf
= (char *)buf
+ sizeof(struct passwd
);
274 while ((err
= getpwnam_r(name
, (struct passwd
*)buf
, getpw_buf
,
275 getpw_buflen
, &result
)) == ERANGE
)
277 if (expand_buffer_trashcontents(&buf
, &buflen
))
280 getpw_buflen
= buflen
- sizeof(struct passwd
);
281 getpw_buf
= (char *)buf
+ sizeof(struct passwd
);
284 if (err
|| !result
) {
292 pa_assert(result
== buf
|| result
== NULL
);
297 void pa_getpwnam_free(struct passwd
*passwd
) {
301 #else /* !HAVE_GETPWNAM_R */
303 struct passwd
*pa_getpwnam_malloc(const char *name
) {
304 return getpwnam(name
);
307 void pa_getpwnam_free(struct passwd
*passwd
) {
312 #endif /* !HAVE_GETPWNAM_R */
314 #ifdef HAVE_GETPWUID_R
315 /* Thread-safe getpwuid() function.
316 Returned value should be freed using pa_getpwuid_free() when the caller is
317 finished with the returned group data.
319 API is the same as getpwuid(), errors are indicated by a NULL return;
320 consult errno for the error cause (zero it before calling).
321 The returned value must be freed using pa_xfree().
323 struct passwd
*pa_getpwuid_malloc(uid_t uid
) {
324 size_t buflen
, getpw_buflen
;
328 struct passwd
*result
= NULL
;
330 buflen
= starting_getpw_buflen();
331 buf
= pa_xmalloc(buflen
);
333 getpw_buflen
= buflen
- sizeof(struct passwd
);
334 getpw_buf
= (char *)buf
+ sizeof(struct passwd
);
336 while ((err
= getpwuid_r(uid
, (struct passwd
*)buf
, getpw_buf
,
337 getpw_buflen
, &result
)) == ERANGE
)
339 if (expand_buffer_trashcontents(&buf
, &buflen
))
342 getpw_buflen
= buflen
- sizeof(struct passwd
);
343 getpw_buf
= (char *)buf
+ sizeof(struct passwd
);
346 if (err
|| !result
) {
354 pa_assert(result
== buf
|| result
== NULL
);
359 void pa_getpwuid_free(struct passwd
*passwd
) {
363 #else /* !HAVE_GETPWUID_R */
365 struct passwd
*pa_getpwuid_malloc(uid_t uid
) {
366 return getpwuid(uid
);
369 void pa_getpwuid_free(struct passwd
*passwd
) {
374 #endif /* !HAVE_GETPWUID_R */
376 #endif /* HAVE_PWD_H */