core: relex validity checks when destructing half-set up source outputs/sink inputs
[pulseaudio-mirror.git] / src / pulsecore / core-util.c
blob0eb32cc48d12a77ccbe51710c7aa904a16daf459
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 USA.
22 ***/
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <limits.h>
37 #include <time.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <dirent.h>
43 #include <regex.h>
44 #include <langinfo.h>
45 #include <sys/utsname.h>
46 #include <sys/socket.h>
48 #ifdef HAVE_STRTOF_L
49 #include <locale.h>
50 #endif
52 #ifdef HAVE_SCHED_H
53 #include <sched.h>
55 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
56 #define SCHED_RESET_ON_FORK 0x40000000
57 #endif
58 #endif
60 #ifdef HAVE_SYS_RESOURCE_H
61 #include <sys/resource.h>
62 #endif
64 #ifdef HAVE_SYS_CAPABILITY_H
65 #include <sys/capability.h>
66 #endif
68 #ifdef HAVE_SYS_MMAN_H
69 #include <sys/mman.h>
70 #endif
72 #ifdef HAVE_PTHREAD
73 #include <pthread.h>
74 #endif
76 #ifdef HAVE_NETDB_H
77 #include <netdb.h>
78 #endif
80 #ifdef HAVE_WINDOWS_H
81 #include <windows.h>
82 #endif
84 #ifdef HAVE_PWD_H
85 #include <pwd.h>
86 #endif
88 #ifdef HAVE_GRP_H
89 #include <grp.h>
90 #endif
92 #ifdef HAVE_LIBSAMPLERATE
93 #include <samplerate.h>
94 #endif
96 #ifdef __APPLE__
97 #include <xlocale.h>
98 #endif
100 #ifdef HAVE_DBUS
101 #include "rtkit.h"
102 #endif
104 #ifdef __linux__
105 #include <sys/personality.h>
106 #endif
108 #include <pulse/xmalloc.h>
109 #include <pulse/util.h>
110 #include <pulse/utf8.h>
112 #include <pulsecore/core-error.h>
113 #include <pulsecore/winsock.h>
114 #include <pulsecore/log.h>
115 #include <pulsecore/macro.h>
116 #include <pulsecore/thread.h>
117 #include <pulsecore/strbuf.h>
118 #include <pulsecore/usergroup.h>
120 #include "core-util.h"
122 /* Not all platforms have this */
123 #ifndef MSG_NOSIGNAL
124 #define MSG_NOSIGNAL 0
125 #endif
127 #ifdef OS_IS_WIN32
129 #define PULSE_ROOTENV "PULSE_ROOT"
131 int pa_set_root(HANDLE handle) {
132 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
134 strcpy(library_path, PULSE_ROOTENV "=");
136 /* FIXME: Needs to set errno */
138 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
139 return 0;
141 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
142 if (sep)
143 *sep = '\0';
145 if (_putenv(library_path) < 0)
146 return 0;
148 return 1;
151 #endif
153 /** Make a file descriptor nonblock. Doesn't do any error checking */
154 void pa_make_fd_nonblock(int fd) {
156 #ifdef O_NONBLOCK
157 int v;
158 pa_assert(fd >= 0);
160 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
162 if (!(v & O_NONBLOCK))
163 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
165 #elif defined(OS_IS_WIN32)
166 u_long arg = 1;
167 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
168 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
169 pa_log_warn("Only sockets can be made non-blocking!");
171 #else
172 pa_log_warn("Non-blocking I/O not supported.!");
173 #endif
177 /* Set the FD_CLOEXEC flag for a fd */
178 void pa_make_fd_cloexec(int fd) {
180 #ifdef FD_CLOEXEC
181 int v;
182 pa_assert(fd >= 0);
184 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
186 if (!(v & FD_CLOEXEC))
187 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
188 #endif
192 /** Creates a directory securely */
193 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
194 struct stat st;
195 int r, saved_errno;
197 pa_assert(dir);
199 #ifdef OS_IS_WIN32
200 r = mkdir(dir);
201 #else
203 mode_t u;
204 u = umask((~m) & 0777);
205 r = mkdir(dir, m);
206 umask(u);
208 #endif
210 if (r < 0 && errno != EEXIST)
211 return -1;
213 #ifdef HAVE_CHOWN
214 if (uid == (uid_t)-1)
215 uid = getuid();
216 if (gid == (gid_t)-1)
217 gid = getgid();
218 (void) chown(dir, uid, gid);
219 #endif
221 #ifdef HAVE_CHMOD
222 chmod(dir, m);
223 #endif
225 #ifdef HAVE_LSTAT
226 if (lstat(dir, &st) < 0)
227 #else
228 if (stat(dir, &st) < 0)
229 #endif
230 goto fail;
232 #ifndef OS_IS_WIN32
233 if (!S_ISDIR(st.st_mode) ||
234 (st.st_uid != uid) ||
235 (st.st_gid != gid) ||
236 ((st.st_mode & 0777) != m)) {
237 errno = EACCES;
238 goto fail;
240 #else
241 pa_log_warn("Secure directory creation not supported on Win32.");
242 #endif
244 return 0;
246 fail:
247 saved_errno = errno;
248 rmdir(dir);
249 errno = saved_errno;
251 return -1;
254 /* Return a newly allocated sting containing the parent directory of the specified file */
255 char *pa_parent_dir(const char *fn) {
256 char *slash, *dir = pa_xstrdup(fn);
258 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
259 pa_xfree(dir);
260 errno = ENOENT;
261 return NULL;
264 *(slash-1) = 0;
265 return dir;
268 /* Creates a the parent directory of the specified path securely */
269 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
270 int ret = -1;
271 char *dir;
273 if (!(dir = pa_parent_dir(fn)))
274 goto finish;
276 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
277 goto finish;
279 ret = 0;
281 finish:
282 pa_xfree(dir);
283 return ret;
286 /** Platform independent read function. Necessary since not all
287 * systems treat all file descriptors equal. If type is
288 * non-NULL it is used to cache the type of the fd. This is
289 * useful for making sure that only a single syscall is executed per
290 * function call. The variable pointed to should be initialized to 0
291 * by the caller. */
292 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
294 #ifdef OS_IS_WIN32
296 if (!type || *type == 0) {
297 ssize_t r;
299 if ((r = recv(fd, buf, count, 0)) >= 0)
300 return r;
302 if (WSAGetLastError() != WSAENOTSOCK) {
303 errno = WSAGetLastError();
304 return r;
307 if (type)
308 *type = 1;
311 #endif
313 for (;;) {
314 ssize_t r;
316 if ((r = read(fd, buf, count)) < 0)
317 if (errno == EINTR)
318 continue;
320 return r;
324 /** Similar to pa_read(), but handles writes */
325 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
327 if (!type || *type == 0) {
328 ssize_t r;
330 for (;;) {
331 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
333 if (errno == EINTR)
334 continue;
336 break;
339 return r;
342 #ifdef OS_IS_WIN32
343 if (WSAGetLastError() != WSAENOTSOCK) {
344 errno = WSAGetLastError();
345 return r;
347 #else
348 if (errno != ENOTSOCK)
349 return r;
350 #endif
352 if (type)
353 *type = 1;
356 for (;;) {
357 ssize_t r;
359 if ((r = write(fd, buf, count)) < 0)
360 if (errno == EINTR)
361 continue;
363 return r;
367 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
368 * unless EOF is reached or an error occurred */
369 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
370 ssize_t ret = 0;
371 int _type;
373 pa_assert(fd >= 0);
374 pa_assert(data);
375 pa_assert(size);
377 if (!type) {
378 _type = 0;
379 type = &_type;
382 while (size > 0) {
383 ssize_t r;
385 if ((r = pa_read(fd, data, size, type)) < 0)
386 return r;
388 if (r == 0)
389 break;
391 ret += r;
392 data = (uint8_t*) data + r;
393 size -= (size_t) r;
396 return ret;
399 /** Similar to pa_loop_read(), but wraps write() */
400 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
401 ssize_t ret = 0;
402 int _type;
404 pa_assert(fd >= 0);
405 pa_assert(data);
406 pa_assert(size);
408 if (!type) {
409 _type = 0;
410 type = &_type;
413 while (size > 0) {
414 ssize_t r;
416 if ((r = pa_write(fd, data, size, type)) < 0)
417 return r;
419 if (r == 0)
420 break;
422 ret += r;
423 data = (const uint8_t*) data + r;
424 size -= (size_t) r;
427 return ret;
430 /** Platform independent read function. Necessary since not all
431 * systems treat all file descriptors equal. */
432 int pa_close(int fd) {
434 #ifdef OS_IS_WIN32
435 int ret;
437 if ((ret = closesocket(fd)) == 0)
438 return 0;
440 if (WSAGetLastError() != WSAENOTSOCK) {
441 errno = WSAGetLastError();
442 return ret;
444 #endif
446 for (;;) {
447 int r;
449 if ((r = close(fd)) < 0)
450 if (errno == EINTR)
451 continue;
453 return r;
457 /* Print a warning messages in case that the given signal is not
458 * blocked or trapped */
459 void pa_check_signal_is_blocked(int sig) {
460 #ifdef HAVE_SIGACTION
461 struct sigaction sa;
462 sigset_t set;
464 /* If POSIX threads are supported use thread-aware
465 * pthread_sigmask() function, to check if the signal is
466 * blocked. Otherwise fall back to sigprocmask() */
468 #ifdef HAVE_PTHREAD
469 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
470 #endif
471 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
472 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
473 return;
475 #ifdef HAVE_PTHREAD
477 #endif
479 if (sigismember(&set, sig))
480 return;
482 /* Check whether the signal is trapped */
484 if (sigaction(sig, NULL, &sa) < 0) {
485 pa_log("sigaction(): %s", pa_cstrerror(errno));
486 return;
489 if (sa.sa_handler != SIG_DFL)
490 return;
492 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
493 #else /* HAVE_SIGACTION */
494 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
495 #endif
498 /* The following function is based on an example from the GNU libc
499 * documentation. This function is similar to GNU's asprintf(). */
500 char *pa_sprintf_malloc(const char *format, ...) {
501 size_t size = 100;
502 char *c = NULL;
504 pa_assert(format);
506 for(;;) {
507 int r;
508 va_list ap;
510 c = pa_xrealloc(c, size);
512 va_start(ap, format);
513 r = vsnprintf(c, size, format, ap);
514 va_end(ap);
516 c[size-1] = 0;
518 if (r > -1 && (size_t) r < size)
519 return c;
521 if (r > -1) /* glibc 2.1 */
522 size = (size_t) r+1;
523 else /* glibc 2.0 */
524 size *= 2;
528 /* Same as the previous function, but use a va_list instead of an
529 * ellipsis */
530 char *pa_vsprintf_malloc(const char *format, va_list ap) {
531 size_t size = 100;
532 char *c = NULL;
534 pa_assert(format);
536 for(;;) {
537 int r;
538 va_list aq;
540 c = pa_xrealloc(c, size);
542 va_copy(aq, ap);
543 r = vsnprintf(c, size, format, aq);
544 va_end(aq);
546 c[size-1] = 0;
548 if (r > -1 && (size_t) r < size)
549 return c;
551 if (r > -1) /* glibc 2.1 */
552 size = (size_t) r+1;
553 else /* glibc 2.0 */
554 size *= 2;
558 /* Similar to OpenBSD's strlcpy() function */
559 char *pa_strlcpy(char *b, const char *s, size_t l) {
560 size_t k;
562 pa_assert(b);
563 pa_assert(s);
564 pa_assert(l > 0);
566 k = strlen(s);
568 if (k > l-1)
569 k = l-1;
571 memcpy(b, s, k);
572 b[k] = 0;
574 return b;
577 static int set_scheduler(int rtprio) {
578 struct sched_param sp;
579 int r;
580 #ifdef HAVE_DBUS
581 DBusError error;
582 DBusConnection *bus;
584 dbus_error_init(&error);
585 #endif
587 pa_zero(sp);
588 sp.sched_priority = rtprio;
590 #ifdef SCHED_RESET_ON_FORK
591 if ((r = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp)) == 0) {
592 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
593 return 0;
595 #endif
597 if ((r = pthread_setschedparam(pthread_self(), SCHED_RR, &sp)) == 0) {
598 pa_log_debug("SCHED_RR worked.");
599 return 0;
602 #ifdef HAVE_DBUS
603 /* Try to talk to RealtimeKit */
605 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
606 pa_log("Failed to connect to system bus: %s\n", error.message);
607 dbus_error_free(&error);
608 errno = -EIO;
609 return -1;
612 r = rtkit_make_realtime(bus, 0, rtprio);
613 dbus_connection_unref(bus);
615 if (r >= 0) {
616 pa_log_debug("RealtimeKit worked.");
617 return 0;
620 errno = -r;
621 #else
622 errno = r;
623 #endif
625 return -1;
628 /* Make the current thread a realtime thread, and acquire the highest
629 * rtprio we can get that is less or equal the specified parameter. If
630 * the thread is already realtime, don't do anything. */
631 int pa_make_realtime(int rtprio) {
633 #ifdef _POSIX_PRIORITY_SCHEDULING
634 int p;
636 if (set_scheduler(rtprio) >= 0) {
637 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
638 return 0;
641 for (p = rtprio-1; p >= 1; p--)
642 if (set_scheduler(p)) {
643 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
644 return 0;
647 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
648 return -1;
649 #else
651 errno = ENOTSUP;
652 return -1;
653 #endif
656 static int set_nice(int nice_level) {
657 #ifdef HAVE_DBUS
658 DBusError error;
659 DBusConnection *bus;
660 int r;
662 dbus_error_init(&error);
663 #endif
665 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
666 pa_log_debug("setpriority() worked.");
667 return 0;
670 #ifdef HAVE_DBUS
671 /* Try to talk to RealtimeKit */
673 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
674 pa_log("Failed to connect to system bus: %s\n", error.message);
675 dbus_error_free(&error);
676 errno = -EIO;
677 return -1;
680 r = rtkit_make_high_priority(bus, 0, nice_level);
681 dbus_connection_unref(bus);
683 if (r >= 0) {
684 pa_log_debug("RealtimeKit worked.");
685 return 0;
688 errno = -r;
689 #endif
691 return -1;
694 /* Raise the priority of the current process as much as possible that
695 * is <= the specified nice level..*/
696 int pa_raise_priority(int nice_level) {
698 #ifdef HAVE_SYS_RESOURCE_H
699 int n;
701 if (set_nice(nice_level) >= 0) {
702 pa_log_info("Successfully gained nice level %i.", nice_level);
703 return 0;
706 for (n = nice_level+1; n < 0; n++)
707 if (set_nice(n) > 0) {
708 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
709 return 0;
712 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
713 return -1;
714 #endif
716 #ifdef OS_IS_WIN32
717 if (nice_level < 0) {
718 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
719 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
720 errno = EPERM;
721 return -1;
724 pa_log_info("Successfully gained high priority class.");
726 #endif
728 return 0;
731 /* Reset the priority to normal, inverting the changes made by
732 * pa_raise_priority() and pa_make_realtime()*/
733 void pa_reset_priority(void) {
734 #ifdef HAVE_SYS_RESOURCE_H
735 struct sched_param sp;
737 setpriority(PRIO_PROCESS, 0, 0);
739 pa_zero(sp);
740 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
741 #endif
743 #ifdef OS_IS_WIN32
744 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
745 #endif
748 int pa_match(const char *expr, const char *v) {
749 int k;
750 regex_t re;
751 int r;
753 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
754 errno = EINVAL;
755 return -1;
758 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
759 r = 1;
760 else if (k == REG_NOMATCH)
761 r = 0;
762 else
763 r = -1;
765 regfree(&re);
767 if (r < 0)
768 errno = EINVAL;
770 return r;
773 /* Try to parse a boolean string value.*/
774 int pa_parse_boolean(const char *v) {
775 const char *expr;
776 int r;
777 pa_assert(v);
779 /* First we check language independant */
780 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
781 return 1;
782 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
783 return 0;
785 /* And then we check language dependant */
786 if ((expr = nl_langinfo(YESEXPR)))
787 if (expr[0])
788 if ((r = pa_match(expr, v)) > 0)
789 return 1;
791 if ((expr = nl_langinfo(NOEXPR)))
792 if (expr[0])
793 if ((r = pa_match(expr, v)) > 0)
794 return 0;
796 errno = EINVAL;
797 return -1;
800 /* Split the specified string wherever one of the strings in delimiter
801 * occurs. Each time it is called returns a newly allocated string
802 * with pa_xmalloc(). The variable state points to, should be
803 * initiallized to NULL before the first call. */
804 char *pa_split(const char *c, const char *delimiter, const char**state) {
805 const char *current = *state ? *state : c;
806 size_t l;
808 if (!*current)
809 return NULL;
811 l = strcspn(current, delimiter);
812 *state = current+l;
814 if (**state)
815 (*state)++;
817 return pa_xstrndup(current, l);
820 /* What is interpreted as whitespace? */
821 #define WHITESPACE " \t\n"
823 /* Split a string into words. Otherwise similar to pa_split(). */
824 char *pa_split_spaces(const char *c, const char **state) {
825 const char *current = *state ? *state : c;
826 size_t l;
828 if (!*current || *c == 0)
829 return NULL;
831 current += strspn(current, WHITESPACE);
832 l = strcspn(current, WHITESPACE);
834 *state = current+l;
836 return pa_xstrndup(current, l);
839 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
841 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
842 const char *pa_sig2str(int sig) {
843 char *t;
845 if (sig <= 0)
846 goto fail;
848 #ifdef NSIG
849 if (sig >= NSIG)
850 goto fail;
851 #endif
853 #ifdef HAVE_SIG2STR
855 char buf[SIG2STR_MAX];
857 if (sig2str(sig, buf) == 0) {
858 pa_xfree(PA_STATIC_TLS_GET(signame));
859 t = pa_sprintf_malloc("SIG%s", buf);
860 PA_STATIC_TLS_SET(signame, t);
861 return t;
864 #else
866 switch(sig) {
867 #ifdef SIGHUP
868 case SIGHUP: return "SIGHUP";
869 #endif
870 case SIGINT: return "SIGINT";
871 #ifdef SIGQUIT
872 case SIGQUIT: return "SIGQUIT";
873 #endif
874 case SIGILL: return "SIGULL";
875 #ifdef SIGTRAP
876 case SIGTRAP: return "SIGTRAP";
877 #endif
878 case SIGABRT: return "SIGABRT";
879 #ifdef SIGBUS
880 case SIGBUS: return "SIGBUS";
881 #endif
882 case SIGFPE: return "SIGFPE";
883 #ifdef SIGKILL
884 case SIGKILL: return "SIGKILL";
885 #endif
886 #ifdef SIGUSR1
887 case SIGUSR1: return "SIGUSR1";
888 #endif
889 case SIGSEGV: return "SIGSEGV";
890 #ifdef SIGUSR2
891 case SIGUSR2: return "SIGUSR2";
892 #endif
893 #ifdef SIGPIPE
894 case SIGPIPE: return "SIGPIPE";
895 #endif
896 #ifdef SIGALRM
897 case SIGALRM: return "SIGALRM";
898 #endif
899 case SIGTERM: return "SIGTERM";
900 #ifdef SIGSTKFLT
901 case SIGSTKFLT: return "SIGSTKFLT";
902 #endif
903 #ifdef SIGCHLD
904 case SIGCHLD: return "SIGCHLD";
905 #endif
906 #ifdef SIGCONT
907 case SIGCONT: return "SIGCONT";
908 #endif
909 #ifdef SIGSTOP
910 case SIGSTOP: return "SIGSTOP";
911 #endif
912 #ifdef SIGTSTP
913 case SIGTSTP: return "SIGTSTP";
914 #endif
915 #ifdef SIGTTIN
916 case SIGTTIN: return "SIGTTIN";
917 #endif
918 #ifdef SIGTTOU
919 case SIGTTOU: return "SIGTTOU";
920 #endif
921 #ifdef SIGURG
922 case SIGURG: return "SIGURG";
923 #endif
924 #ifdef SIGXCPU
925 case SIGXCPU: return "SIGXCPU";
926 #endif
927 #ifdef SIGXFSZ
928 case SIGXFSZ: return "SIGXFSZ";
929 #endif
930 #ifdef SIGVTALRM
931 case SIGVTALRM: return "SIGVTALRM";
932 #endif
933 #ifdef SIGPROF
934 case SIGPROF: return "SIGPROF";
935 #endif
936 #ifdef SIGWINCH
937 case SIGWINCH: return "SIGWINCH";
938 #endif
939 #ifdef SIGIO
940 case SIGIO: return "SIGIO";
941 #endif
942 #ifdef SIGPWR
943 case SIGPWR: return "SIGPWR";
944 #endif
945 #ifdef SIGSYS
946 case SIGSYS: return "SIGSYS";
947 #endif
950 #ifdef SIGRTMIN
951 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
952 pa_xfree(PA_STATIC_TLS_GET(signame));
953 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
954 PA_STATIC_TLS_SET(signame, t);
955 return t;
957 #endif
959 #endif
961 fail:
963 pa_xfree(PA_STATIC_TLS_GET(signame));
964 t = pa_sprintf_malloc("SIG%i", sig);
965 PA_STATIC_TLS_SET(signame, t);
966 return t;
969 #ifdef HAVE_GRP_H
971 /* Check whether the specified GID and the group name match */
972 static int is_group(gid_t gid, const char *name) {
973 struct group *group = NULL;
974 int r = -1;
976 errno = 0;
977 if (!(group = pa_getgrgid_malloc(gid)))
979 if (!errno)
980 errno = ENOENT;
982 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
984 goto finish;
987 r = strcmp(name, group->gr_name) == 0;
989 finish:
990 pa_getgrgid_free(group);
992 return r;
995 /* Check the current user is member of the specified group */
996 int pa_own_uid_in_group(const char *name, gid_t *gid) {
997 GETGROUPS_T *gids, tgid;
998 long n = sysconf(_SC_NGROUPS_MAX);
999 int r = -1, i, k;
1001 pa_assert(n > 0);
1003 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1005 if ((n = getgroups((int) n, gids)) < 0) {
1006 pa_log("getgroups(): %s", pa_cstrerror(errno));
1007 goto finish;
1010 for (i = 0; i < n; i++) {
1012 if ((k = is_group(gids[i], name)) < 0)
1013 goto finish;
1014 else if (k > 0) {
1015 *gid = gids[i];
1016 r = 1;
1017 goto finish;
1021 if ((k = is_group(tgid = getgid(), name)) < 0)
1022 goto finish;
1023 else if (k > 0) {
1024 *gid = tgid;
1025 r = 1;
1026 goto finish;
1029 r = 0;
1031 finish:
1033 pa_xfree(gids);
1034 return r;
1037 /* Check whether the specifc user id is a member of the specified group */
1038 int pa_uid_in_group(uid_t uid, const char *name) {
1039 struct group *group = NULL;
1040 char **i;
1041 int r = -1;
1043 errno = 0;
1044 if (!(group = pa_getgrnam_malloc(name)))
1046 if (!errno)
1047 errno = ENOENT;
1048 goto finish;
1051 r = 0;
1052 for (i = group->gr_mem; *i; i++) {
1053 struct passwd *pw = NULL;
1055 errno = 0;
1056 if (!(pw = pa_getpwnam_malloc(*i)))
1057 continue;
1059 if (pw->pw_uid == uid)
1060 r = 1;
1062 pa_getpwnam_free(pw);
1064 if (r == 1)
1065 break;
1068 finish:
1069 pa_getgrnam_free(group);
1071 return r;
1074 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1075 gid_t pa_get_gid_of_group(const char *name) {
1076 gid_t ret = (gid_t) -1;
1077 struct group *gr = NULL;
1079 errno = 0;
1080 if (!(gr = pa_getgrnam_malloc(name)))
1082 if (!errno)
1083 errno = ENOENT;
1084 goto finish;
1087 ret = gr->gr_gid;
1089 finish:
1090 pa_getgrnam_free(gr);
1091 return ret;
1094 int pa_check_in_group(gid_t g) {
1095 gid_t gids[NGROUPS_MAX];
1096 int r;
1098 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1099 return -1;
1101 for (; r > 0; r--)
1102 if (gids[r-1] == g)
1103 return 1;
1105 return 0;
1108 #else /* HAVE_GRP_H */
1110 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1111 errno = ENOSUP;
1112 return -1;
1116 int pa_uid_in_group(uid_t uid, const char *name) {
1117 errno = ENOSUP;
1118 return -1;
1121 gid_t pa_get_gid_of_group(const char *name) {
1122 errno = ENOSUP;
1123 return (gid_t) -1;
1126 int pa_check_in_group(gid_t g) {
1127 errno = ENOSUP;
1128 return -1;
1131 #endif
1133 /* Lock or unlock a file entirely.
1134 (advisory on UNIX, mandatory on Windows) */
1135 int pa_lock_fd(int fd, int b) {
1136 #ifdef F_SETLKW
1137 struct flock f_lock;
1139 /* Try a R/W lock first */
1141 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1142 f_lock.l_whence = SEEK_SET;
1143 f_lock.l_start = 0;
1144 f_lock.l_len = 0;
1146 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1147 return 0;
1149 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1150 if (b && errno == EBADF) {
1151 f_lock.l_type = F_RDLCK;
1152 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1153 return 0;
1156 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1157 #endif
1159 #ifdef OS_IS_WIN32
1160 HANDLE h = (HANDLE)_get_osfhandle(fd);
1162 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1163 return 0;
1164 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1165 return 0;
1167 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1169 /* FIXME: Needs to set errno! */
1170 #endif
1172 return -1;
1175 /* Remove trailing newlines from a string */
1176 char* pa_strip_nl(char *s) {
1177 pa_assert(s);
1179 s[strcspn(s, "\r\n")] = 0;
1180 return s;
1183 /* Create a temporary lock file and lock it. */
1184 int pa_lock_lockfile(const char *fn) {
1185 int fd = -1;
1186 pa_assert(fn);
1188 for (;;) {
1189 struct stat st;
1191 if ((fd = open(fn, O_CREAT|O_RDWR
1192 #ifdef O_NOCTTY
1193 |O_NOCTTY
1194 #endif
1195 #ifdef O_NOFOLLOW
1196 |O_NOFOLLOW
1197 #endif
1198 , S_IRUSR|S_IWUSR)) < 0) {
1199 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1200 goto fail;
1203 if (pa_lock_fd(fd, 1) < 0) {
1204 pa_log_warn("Failed to lock file '%s'.", fn);
1205 goto fail;
1208 if (fstat(fd, &st) < 0) {
1209 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1210 goto fail;
1213 /* Check whether the file has been removed meanwhile. When yes,
1214 * restart this loop, otherwise, we're done */
1215 if (st.st_nlink >= 1)
1216 break;
1218 if (pa_lock_fd(fd, 0) < 0) {
1219 pa_log_warn("Failed to unlock file '%s'.", fn);
1220 goto fail;
1223 if (pa_close(fd) < 0) {
1224 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1225 fd = -1;
1226 goto fail;
1229 fd = -1;
1232 return fd;
1234 fail:
1236 if (fd >= 0) {
1237 int saved_errno = errno;
1238 pa_close(fd);
1239 errno = saved_errno;
1242 return -1;
1245 /* Unlock a temporary lcok file */
1246 int pa_unlock_lockfile(const char *fn, int fd) {
1247 int r = 0;
1248 pa_assert(fd >= 0);
1250 if (fn) {
1251 if (unlink(fn) < 0) {
1252 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1253 r = -1;
1257 if (pa_lock_fd(fd, 0) < 0) {
1258 pa_log_warn("Failed to unlock file '%s'.", fn);
1259 r = -1;
1262 if (pa_close(fd) < 0) {
1263 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1264 r = -1;
1267 return r;
1270 static char *get_pulse_home(void) {
1271 char *h;
1272 struct stat st;
1273 char *ret = NULL;
1275 if (!(h = pa_get_home_dir_malloc())) {
1276 pa_log_error("Failed to get home directory.");
1277 return NULL;
1280 if (stat(h, &st) < 0) {
1281 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1282 goto finish;
1285 if (st.st_uid != getuid()) {
1286 pa_log_error("Home directory %s not ours.", h);
1287 errno = EACCES;
1288 goto finish;
1291 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1293 finish:
1294 pa_xfree(h);
1296 return ret;
1299 char *pa_get_state_dir(void) {
1300 char *d;
1302 /* The state directory shall contain dynamic data that should be
1303 * kept across reboots, and is private to this user */
1305 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1306 if (!(d = get_pulse_home()))
1307 return NULL;
1309 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1310 * dir then this will break. */
1312 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1313 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1314 pa_xfree(d);
1315 return NULL;
1318 return d;
1321 char *pa_get_home_dir_malloc(void) {
1322 char *homedir;
1323 size_t allocated = 128;
1325 for (;;) {
1326 homedir = pa_xmalloc(allocated);
1328 if (!pa_get_home_dir(homedir, allocated)) {
1329 pa_xfree(homedir);
1330 return NULL;
1333 if (strlen(homedir) < allocated - 1)
1334 break;
1336 pa_xfree(homedir);
1337 allocated *= 2;
1340 return homedir;
1343 char *pa_get_binary_name_malloc(void) {
1344 char *t;
1345 size_t allocated = 128;
1347 for (;;) {
1348 t = pa_xmalloc(allocated);
1350 if (!pa_get_binary_name(t, allocated)) {
1351 pa_xfree(t);
1352 return NULL;
1355 if (strlen(t) < allocated - 1)
1356 break;
1358 pa_xfree(t);
1359 allocated *= 2;
1362 return t;
1365 static char* make_random_dir(mode_t m) {
1366 static const char table[] =
1367 "abcdefghijklmnopqrstuvwxyz"
1368 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1369 "0123456789";
1371 const char *tmpdir;
1372 char *fn;
1373 size_t pathlen;
1375 if (!(tmpdir = getenv("TMPDIR")))
1376 if (!(tmpdir = getenv("TMP")))
1377 if (!(tmpdir = getenv("TEMP")))
1378 tmpdir = getenv("TEMPDIR");
1380 if (!tmpdir || !pa_is_path_absolute(tmpdir))
1381 tmpdir = "/tmp";
1383 fn = pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir);
1384 pathlen = strlen(fn);
1386 for (;;) {
1387 size_t i;
1388 int r;
1389 mode_t u;
1390 int saved_errno;
1392 for (i = pathlen - 12; i < pathlen; i++)
1393 fn[i] = table[rand() % (sizeof(table)-1)];
1395 u = umask((~m) & 0777);
1396 r = mkdir(fn, m);
1398 saved_errno = errno;
1399 umask(u);
1400 errno = saved_errno;
1402 if (r >= 0)
1403 return fn;
1405 if (errno != EEXIST) {
1406 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1407 pa_xfree(fn);
1408 return NULL;
1413 static int make_random_dir_and_link(mode_t m, const char *k) {
1414 char *p;
1416 if (!(p = make_random_dir(m)))
1417 return -1;
1419 if (symlink(p, k) < 0) {
1420 int saved_errno = errno;
1422 if (errno != EEXIST)
1423 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1425 rmdir(p);
1426 pa_xfree(p);
1428 errno = saved_errno;
1429 return -1;
1432 pa_xfree(p);
1433 return 0;
1436 char *pa_get_runtime_dir(void) {
1437 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1438 struct stat st;
1439 mode_t m;
1441 /* The runtime directory shall contain dynamic data that needs NOT
1442 * to be kept accross reboots and is usuallly private to the user,
1443 * except in system mode, where it might be accessible by other
1444 * users, too. Since we need POSIX locking and UNIX sockets in
1445 * this directory, we link it to a random subdir in /tmp, if it
1446 * was not explicitly configured. */
1448 m = pa_in_system_mode() ? 0755U : 0700U;
1450 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1452 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1453 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1454 goto fail;
1457 return pa_xstrdup(d);
1460 if (!(d = get_pulse_home()))
1461 goto fail;
1463 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1464 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1465 pa_xfree(d);
1466 goto fail;
1469 if (!(mid = pa_machine_id())) {
1470 pa_xfree(d);
1471 goto fail;
1474 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1475 pa_xfree(d);
1476 pa_xfree(mid);
1478 for (;;) {
1479 /* OK, first let's check if the "runtime" symlink is already
1480 * existant */
1482 if (!(p = pa_readlink(k))) {
1484 if (errno != ENOENT) {
1485 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1486 goto fail;
1489 /* Hmm, so the runtime directory didn't exist yet, so let's
1490 * create one in /tmp and symlink that to it */
1492 if (make_random_dir_and_link(0700, k) < 0) {
1494 /* Mhmm, maybe another process was quicker than us,
1495 * let's check if that was valid */
1496 if (errno == EEXIST)
1497 continue;
1499 goto fail;
1502 return k;
1505 /* Make sure that this actually makes sense */
1506 if (!pa_is_path_absolute(p)) {
1507 pa_log_error("Path %s in link %s is not absolute.", p, k);
1508 errno = ENOENT;
1509 goto fail;
1512 /* Hmm, so this symlink is still around, make sure nobody fools
1513 * us */
1515 if (lstat(p, &st) < 0) {
1517 if (errno != ENOENT) {
1518 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1519 goto fail;
1522 } else {
1524 if (S_ISDIR(st.st_mode) &&
1525 (st.st_uid == getuid()) &&
1526 ((st.st_mode & 0777) == 0700)) {
1528 pa_xfree(p);
1529 return k;
1532 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1535 pa_xfree(p);
1536 p = NULL;
1538 /* Hmm, so the link points to some nonexisting or invalid
1539 * dir. Let's replace it by a new link. We first create a
1540 * temporary link and then rename that to allow concurrent
1541 * execution of this function. */
1543 t = pa_sprintf_malloc("%s.tmp", k);
1545 if (make_random_dir_and_link(0700, t) < 0) {
1547 if (errno != EEXIST) {
1548 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1549 goto fail;
1552 pa_xfree(t);
1553 t = NULL;
1555 /* Hmm, someone lese was quicker then us. Let's give
1556 * him some time to finish, and retry. */
1557 pa_msleep(10);
1558 continue;
1561 /* OK, we succeeded in creating the temporary symlink, so
1562 * let's rename it */
1563 if (rename(t, k) < 0) {
1564 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1565 goto fail;
1568 pa_xfree(t);
1569 return k;
1572 fail:
1573 pa_xfree(p);
1574 pa_xfree(k);
1575 pa_xfree(t);
1577 return NULL;
1580 /* Try to open a configuration file. If "env" is specified, open the
1581 * value of the specified environment variable. Otherwise look for a
1582 * file "local" in the home directory or a file "global" in global
1583 * file system. If "result" is non-NULL, a pointer to a newly
1584 * allocated buffer containing the used configuration file is
1585 * stored there.*/
1586 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1587 const char *fn;
1588 #ifdef OS_IS_WIN32
1589 char buf[PATH_MAX];
1591 if (!getenv(PULSE_ROOTENV))
1592 pa_set_root(NULL);
1593 #endif
1595 if (env && (fn = getenv(env))) {
1596 FILE *f;
1598 #ifdef OS_IS_WIN32
1599 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1600 /* FIXME: Needs to set errno! */
1601 return NULL;
1602 fn = buf;
1603 #endif
1605 if ((f = fopen(fn, "r"))) {
1606 if (result)
1607 *result = pa_xstrdup(fn);
1609 return f;
1612 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1613 return NULL;
1616 if (local) {
1617 const char *e;
1618 char *lfn;
1619 char *h;
1620 FILE *f;
1622 if ((e = getenv("PULSE_CONFIG_PATH")))
1623 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1624 else if ((h = pa_get_home_dir_malloc())) {
1625 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1626 pa_xfree(h);
1627 } else
1628 return NULL;
1630 #ifdef OS_IS_WIN32
1631 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1632 /* FIXME: Needs to set errno! */
1633 pa_xfree(lfn);
1634 return NULL;
1636 fn = buf;
1637 #endif
1639 if ((f = fopen(fn, "r"))) {
1640 if (result)
1641 *result = pa_xstrdup(fn);
1643 pa_xfree(lfn);
1644 return f;
1647 if (errno != ENOENT) {
1648 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1649 pa_xfree(lfn);
1650 return NULL;
1653 pa_xfree(lfn);
1656 if (global) {
1657 FILE *f;
1659 #ifdef OS_IS_WIN32
1660 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1661 /* FIXME: Needs to set errno! */
1662 return NULL;
1663 global = buf;
1664 #endif
1666 if ((f = fopen(global, "r"))) {
1668 if (result)
1669 *result = pa_xstrdup(global);
1671 return f;
1675 errno = ENOENT;
1676 return NULL;
1679 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1680 const char *fn;
1681 #ifdef OS_IS_WIN32
1682 char buf[PATH_MAX];
1684 if (!getenv(PULSE_ROOTENV))
1685 pa_set_root(NULL);
1686 #endif
1688 if (env && (fn = getenv(env))) {
1690 #ifdef OS_IS_WIN32
1691 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1692 /* FIXME: Needs to set errno! */
1693 return NULL;
1694 fn = buf;
1695 #endif
1697 if (access(fn, R_OK) == 0)
1698 return pa_xstrdup(fn);
1700 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1701 return NULL;
1704 if (local) {
1705 const char *e;
1706 char *lfn;
1707 char *h;
1709 if ((e = getenv("PULSE_CONFIG_PATH")))
1710 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1711 else if ((h = pa_get_home_dir_malloc())) {
1712 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1713 pa_xfree(h);
1714 } else
1715 return NULL;
1717 #ifdef OS_IS_WIN32
1718 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1719 /* FIXME: Needs to set errno! */
1720 pa_xfree(lfn);
1721 return NULL;
1723 fn = buf;
1724 #endif
1726 if (access(fn, R_OK) == 0) {
1727 char *r = pa_xstrdup(fn);
1728 pa_xfree(lfn);
1729 return r;
1732 if (errno != ENOENT) {
1733 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1734 pa_xfree(lfn);
1735 return NULL;
1738 pa_xfree(lfn);
1741 if (global) {
1742 #ifdef OS_IS_WIN32
1743 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1744 /* FIXME: Needs to set errno! */
1745 return NULL;
1746 global = buf;
1747 #endif
1749 if (access(global, R_OK) == 0)
1750 return pa_xstrdup(global);
1753 errno = ENOENT;
1755 return NULL;
1758 /* Format the specified data as a hexademical string */
1759 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1760 size_t i = 0, j = 0;
1761 const char hex[] = "0123456789abcdef";
1763 pa_assert(d);
1764 pa_assert(s);
1765 pa_assert(slength > 0);
1767 while (i < dlength && j+3 <= slength) {
1768 s[j++] = hex[*d >> 4];
1769 s[j++] = hex[*d & 0xF];
1771 d++;
1772 i++;
1775 s[j < slength ? j : slength] = 0;
1776 return s;
1779 /* Convert a hexadecimal digit to a number or -1 if invalid */
1780 static int hexc(char c) {
1781 if (c >= '0' && c <= '9')
1782 return c - '0';
1784 if (c >= 'A' && c <= 'F')
1785 return c - 'A' + 10;
1787 if (c >= 'a' && c <= 'f')
1788 return c - 'a' + 10;
1790 errno = EINVAL;
1791 return -1;
1794 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1795 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1796 size_t j = 0;
1798 pa_assert(p);
1799 pa_assert(d);
1801 while (j < dlength && *p) {
1802 int b;
1804 if ((b = hexc(*(p++))) < 0)
1805 return (size_t) -1;
1807 d[j] = (uint8_t) (b << 4);
1809 if (!*p)
1810 return (size_t) -1;
1812 if ((b = hexc(*(p++))) < 0)
1813 return (size_t) -1;
1815 d[j] |= (uint8_t) b;
1816 j++;
1819 return j;
1822 /* Returns nonzero when *s starts with *pfx */
1823 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1824 size_t l;
1826 pa_assert(s);
1827 pa_assert(pfx);
1829 l = strlen(pfx);
1831 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1834 /* Returns nonzero when *s ends with *sfx */
1835 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1836 size_t l1, l2;
1838 pa_assert(s);
1839 pa_assert(sfx);
1841 l1 = strlen(s);
1842 l2 = strlen(sfx);
1844 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1847 pa_bool_t pa_is_path_absolute(const char *fn) {
1848 pa_assert(fn);
1850 #ifndef OS_IS_WIN32
1851 return *fn == '/';
1852 #else
1853 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1854 #endif
1857 char *pa_make_path_absolute(const char *p) {
1858 char *r;
1859 char *cwd;
1861 pa_assert(p);
1863 if (pa_is_path_absolute(p))
1864 return pa_xstrdup(p);
1866 if (!(cwd = pa_getcwd()))
1867 return pa_xstrdup(p);
1869 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1870 pa_xfree(cwd);
1871 return r;
1874 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1875 * if fn is non-null and starts with / return fn
1876 * otherwise append fn to the run time path and return it */
1877 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1878 char *rtp;
1880 if (pa_is_path_absolute(fn))
1881 return pa_xstrdup(fn);
1883 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1885 if (!rtp)
1886 return NULL;
1888 if (fn) {
1889 char *r;
1891 if (prependmid) {
1892 char *mid;
1894 if (!(mid = pa_machine_id())) {
1895 pa_xfree(rtp);
1896 return NULL;
1899 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1900 pa_xfree(mid);
1901 } else
1902 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1904 pa_xfree(rtp);
1905 return r;
1906 } else
1907 return rtp;
1910 char *pa_runtime_path(const char *fn) {
1911 return get_path(fn, FALSE, TRUE);
1914 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1915 return get_path(fn, appendmid, FALSE);
1918 /* Convert the string s to a signed integer in *ret_i */
1919 int pa_atoi(const char *s, int32_t *ret_i) {
1920 char *x = NULL;
1921 long l;
1923 pa_assert(s);
1924 pa_assert(ret_i);
1926 errno = 0;
1927 l = strtol(s, &x, 0);
1929 if (!x || *x || errno) {
1930 if (!errno)
1931 errno = EINVAL;
1932 return -1;
1935 if ((int32_t) l != l) {
1936 errno = ERANGE;
1937 return -1;
1940 *ret_i = (int32_t) l;
1942 return 0;
1945 /* Convert the string s to an unsigned integer in *ret_u */
1946 int pa_atou(const char *s, uint32_t *ret_u) {
1947 char *x = NULL;
1948 unsigned long l;
1950 pa_assert(s);
1951 pa_assert(ret_u);
1953 errno = 0;
1954 l = strtoul(s, &x, 0);
1956 if (!x || *x || errno) {
1957 if (!errno)
1958 errno = EINVAL;
1959 return -1;
1962 if ((uint32_t) l != l) {
1963 errno = ERANGE;
1964 return -1;
1967 *ret_u = (uint32_t) l;
1969 return 0;
1972 #ifdef HAVE_STRTOF_L
1973 static locale_t c_locale = NULL;
1975 static void c_locale_destroy(void) {
1976 freelocale(c_locale);
1978 #endif
1980 int pa_atod(const char *s, double *ret_d) {
1981 char *x = NULL;
1982 double f;
1984 pa_assert(s);
1985 pa_assert(ret_d);
1987 /* This should be locale independent */
1989 #ifdef HAVE_STRTOF_L
1991 PA_ONCE_BEGIN {
1993 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1994 atexit(c_locale_destroy);
1996 } PA_ONCE_END;
1998 if (c_locale) {
1999 errno = 0;
2000 f = strtod_l(s, &x, c_locale);
2001 } else
2002 #endif
2004 errno = 0;
2005 f = strtod(s, &x);
2008 if (!x || *x || errno) {
2009 if (!errno)
2010 errno = EINVAL;
2011 return -1;
2014 *ret_d = f;
2016 return 0;
2019 /* Same as snprintf, but guarantees NUL-termination on every platform */
2020 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2021 size_t ret;
2022 va_list ap;
2024 pa_assert(str);
2025 pa_assert(size > 0);
2026 pa_assert(format);
2028 va_start(ap, format);
2029 ret = pa_vsnprintf(str, size, format, ap);
2030 va_end(ap);
2032 return ret;
2035 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2036 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2037 int ret;
2039 pa_assert(str);
2040 pa_assert(size > 0);
2041 pa_assert(format);
2043 ret = vsnprintf(str, size, format, ap);
2045 str[size-1] = 0;
2047 if (ret < 0)
2048 return strlen(str);
2050 if ((size_t) ret > size-1)
2051 return size-1;
2053 return (size_t) ret;
2056 /* Truncate the specified string, but guarantee that the string
2057 * returned still validates as UTF8 */
2058 char *pa_truncate_utf8(char *c, size_t l) {
2059 pa_assert(c);
2060 pa_assert(pa_utf8_valid(c));
2062 if (strlen(c) <= l)
2063 return c;
2065 c[l] = 0;
2067 while (l > 0 && !pa_utf8_valid(c))
2068 c[--l] = 0;
2070 return c;
2073 char *pa_getcwd(void) {
2074 size_t l = 128;
2076 for (;;) {
2077 char *p = pa_xmalloc(l);
2078 if (getcwd(p, l))
2079 return p;
2081 if (errno != ERANGE)
2082 return NULL;
2084 pa_xfree(p);
2085 l *= 2;
2089 void *pa_will_need(const void *p, size_t l) {
2090 #ifdef RLIMIT_MEMLOCK
2091 struct rlimit rlim;
2092 #endif
2093 const void *a;
2094 size_t size;
2095 int r;
2096 size_t bs;
2098 pa_assert(p);
2099 pa_assert(l > 0);
2101 a = PA_PAGE_ALIGN_PTR(p);
2102 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2104 #ifdef HAVE_POSIX_MADVISE
2105 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2106 pa_log_debug("posix_madvise() worked fine!");
2107 return (void*) p;
2109 #endif
2111 /* Most likely the memory was not mmap()ed from a file and thus
2112 * madvise() didn't work, so let's misuse mlock() do page this
2113 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2114 * inviting, the man page of mlock() tells us: "All pages that
2115 * contain a part of the specified address range are guaranteed to
2116 * be resident in RAM when the call returns successfully." */
2118 #ifdef RLIMIT_MEMLOCK
2119 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2121 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2122 pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
2123 errno = EPERM;
2124 return (void*) p;
2127 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2128 #else
2129 bs = PA_PAGE_SIZE*4;
2130 #endif
2132 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2134 #ifdef HAVE_MLOCK
2135 while (size > 0 && bs > 0) {
2137 if (bs > size)
2138 bs = size;
2140 if (mlock(a, bs) < 0) {
2141 bs = PA_PAGE_ALIGN(bs / 2);
2142 continue;
2145 pa_assert_se(munlock(a, bs) == 0);
2147 a = (const uint8_t*) a + bs;
2148 size -= bs;
2150 #endif
2152 if (bs <= 0)
2153 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2154 else
2155 pa_log_debug("mlock() worked fine!");
2157 return (void*) p;
2160 void pa_close_pipe(int fds[2]) {
2161 pa_assert(fds);
2163 if (fds[0] >= 0)
2164 pa_assert_se(pa_close(fds[0]) == 0);
2166 if (fds[1] >= 0)
2167 pa_assert_se(pa_close(fds[1]) == 0);
2169 fds[0] = fds[1] = -1;
2172 char *pa_readlink(const char *p) {
2173 size_t l = 100;
2175 for (;;) {
2176 char *c;
2177 ssize_t n;
2179 c = pa_xmalloc(l);
2181 if ((n = readlink(p, c, l-1)) < 0) {
2182 pa_xfree(c);
2183 return NULL;
2186 if ((size_t) n < l-1) {
2187 c[n] = 0;
2188 return c;
2191 pa_xfree(c);
2192 l *= 2;
2196 int pa_close_all(int except_fd, ...) {
2197 va_list ap;
2198 unsigned n = 0, i;
2199 int r, *p;
2201 va_start(ap, except_fd);
2203 if (except_fd >= 0)
2204 for (n = 1; va_arg(ap, int) >= 0; n++)
2207 va_end(ap);
2209 p = pa_xnew(int, n+1);
2211 va_start(ap, except_fd);
2213 i = 0;
2214 if (except_fd >= 0) {
2215 int fd;
2216 p[i++] = except_fd;
2218 while ((fd = va_arg(ap, int)) >= 0)
2219 p[i++] = fd;
2221 p[i] = -1;
2223 va_end(ap);
2225 r = pa_close_allv(p);
2226 free(p);
2228 return r;
2231 int pa_close_allv(const int except_fds[]) {
2232 struct rlimit rl;
2233 int maxfd, fd;
2235 #ifdef __linux__
2236 int saved_errno;
2237 DIR *d;
2239 if ((d = opendir("/proc/self/fd"))) {
2241 struct dirent *de;
2243 while ((de = readdir(d))) {
2244 pa_bool_t found;
2245 long l;
2246 char *e = NULL;
2247 int i;
2249 if (de->d_name[0] == '.')
2250 continue;
2252 errno = 0;
2253 l = strtol(de->d_name, &e, 10);
2254 if (errno != 0 || !e || *e) {
2255 closedir(d);
2256 errno = EINVAL;
2257 return -1;
2260 fd = (int) l;
2262 if ((long) fd != l) {
2263 closedir(d);
2264 errno = EINVAL;
2265 return -1;
2268 if (fd < 3)
2269 continue;
2271 if (fd == dirfd(d))
2272 continue;
2274 found = FALSE;
2275 for (i = 0; except_fds[i] >= 0; i++)
2276 if (except_fds[i] == fd) {
2277 found = TRUE;
2278 break;
2281 if (found)
2282 continue;
2284 if (pa_close(fd) < 0) {
2285 saved_errno = errno;
2286 closedir(d);
2287 errno = saved_errno;
2289 return -1;
2293 closedir(d);
2294 return 0;
2297 #endif
2299 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2300 maxfd = (int) rl.rlim_max;
2301 else
2302 maxfd = sysconf(_SC_OPEN_MAX);
2304 for (fd = 3; fd < maxfd; fd++) {
2305 int i;
2306 pa_bool_t found;
2308 found = FALSE;
2309 for (i = 0; except_fds[i] >= 0; i++)
2310 if (except_fds[i] == fd) {
2311 found = TRUE;
2312 break;
2315 if (found)
2316 continue;
2318 if (pa_close(fd) < 0 && errno != EBADF)
2319 return -1;
2322 return 0;
2325 int pa_unblock_sigs(int except, ...) {
2326 va_list ap;
2327 unsigned n = 0, i;
2328 int r, *p;
2330 va_start(ap, except);
2332 if (except >= 1)
2333 for (n = 1; va_arg(ap, int) >= 0; n++)
2336 va_end(ap);
2338 p = pa_xnew(int, n+1);
2340 va_start(ap, except);
2342 i = 0;
2343 if (except >= 1) {
2344 int sig;
2345 p[i++] = except;
2347 while ((sig = va_arg(ap, int)) >= 0)
2348 p[i++] = sig;
2350 p[i] = -1;
2352 va_end(ap);
2354 r = pa_unblock_sigsv(p);
2355 pa_xfree(p);
2357 return r;
2360 int pa_unblock_sigsv(const int except[]) {
2361 int i;
2362 sigset_t ss;
2364 if (sigemptyset(&ss) < 0)
2365 return -1;
2367 for (i = 0; except[i] > 0; i++)
2368 if (sigaddset(&ss, except[i]) < 0)
2369 return -1;
2371 return sigprocmask(SIG_SETMASK, &ss, NULL);
2374 int pa_reset_sigs(int except, ...) {
2375 va_list ap;
2376 unsigned n = 0, i;
2377 int *p, r;
2379 va_start(ap, except);
2381 if (except >= 1)
2382 for (n = 1; va_arg(ap, int) >= 0; n++)
2385 va_end(ap);
2387 p = pa_xnew(int, n+1);
2389 va_start(ap, except);
2391 i = 0;
2392 if (except >= 1) {
2393 int sig;
2394 p[i++] = except;
2396 while ((sig = va_arg(ap, int)) >= 0)
2397 sig = p[i++];
2399 p[i] = -1;
2401 va_end(ap);
2403 r = pa_reset_sigsv(p);
2404 pa_xfree(p);
2406 return r;
2409 int pa_reset_sigsv(const int except[]) {
2410 int sig;
2412 for (sig = 1; sig < NSIG; sig++) {
2413 pa_bool_t reset = TRUE;
2415 switch (sig) {
2416 case SIGKILL:
2417 case SIGSTOP:
2418 reset = FALSE;
2419 break;
2421 default: {
2422 int i;
2424 for (i = 0; except[i] > 0; i++) {
2425 if (sig == except[i]) {
2426 reset = FALSE;
2427 break;
2433 if (reset) {
2434 struct sigaction sa;
2436 memset(&sa, 0, sizeof(sa));
2437 sa.sa_handler = SIG_DFL;
2439 /* On Linux the first two RT signals are reserved by
2440 * glibc, and sigaction() will return EINVAL for them. */
2441 if ((sigaction(sig, &sa, NULL) < 0))
2442 if (errno != EINVAL)
2443 return -1;
2447 return 0;
2450 void pa_set_env(const char *key, const char *value) {
2451 pa_assert(key);
2452 pa_assert(value);
2454 putenv(pa_sprintf_malloc("%s=%s", key, value));
2457 pa_bool_t pa_in_system_mode(void) {
2458 const char *e;
2460 if (!(e = getenv("PULSE_SYSTEM")))
2461 return FALSE;
2463 return !!atoi(e);
2466 char *pa_get_user_name_malloc(void) {
2467 ssize_t k;
2468 char *u;
2470 #ifdef _SC_LOGIN_NAME_MAX
2471 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2473 if (k <= 0)
2474 #endif
2475 k = 32;
2477 u = pa_xnew(char, k+1);
2479 if (!(pa_get_user_name(u, k))) {
2480 pa_xfree(u);
2481 return NULL;
2484 return u;
2487 char *pa_get_host_name_malloc(void) {
2488 size_t l;
2490 l = 100;
2491 for (;;) {
2492 char *c;
2494 c = pa_xmalloc(l);
2496 if (!pa_get_host_name(c, l)) {
2498 if (errno != EINVAL && errno != ENAMETOOLONG)
2499 break;
2501 } else if (strlen(c) < l-1) {
2502 char *u;
2504 if (*c == 0) {
2505 pa_xfree(c);
2506 break;
2509 u = pa_utf8_filter(c);
2510 pa_xfree(c);
2511 return u;
2514 /* Hmm, the hostname is as long the space we offered the
2515 * function, we cannot know if it fully fit in, so let's play
2516 * safe and retry. */
2518 pa_xfree(c);
2519 l *= 2;
2522 return NULL;
2525 char *pa_machine_id(void) {
2526 FILE *f;
2527 char *h;
2529 /* The returned value is supposed be some kind of ascii identifier
2530 * that is unique and stable across reboots. */
2532 /* First we try the D-Bus UUID, which is the best option we have,
2533 * since it fits perfectly our needs and is not as volatile as the
2534 * hostname which might be set from dhcp. */
2536 if ((f = fopen(PA_MACHINE_ID, "r"))) {
2537 char ln[34] = "", *r;
2539 r = fgets(ln, sizeof(ln)-1, f);
2540 fclose(f);
2542 pa_strip_nl(ln);
2544 if (r && ln[0])
2545 return pa_utf8_filter(ln);
2548 if ((h = pa_get_host_name_malloc()))
2549 return h;
2551 /* If no hostname was set we use the POSIX hostid. It's usually
2552 * the IPv4 address. Might not be that stable. */
2553 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2556 char *pa_session_id(void) {
2557 const char *e;
2559 if (!(e = getenv("XDG_SESSION_COOKIE")))
2560 return NULL;
2562 return pa_utf8_filter(e);
2565 char *pa_uname_string(void) {
2566 struct utsname u;
2568 pa_assert_se(uname(&u) >= 0);
2570 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2573 #ifdef HAVE_VALGRIND_MEMCHECK_H
2574 pa_bool_t pa_in_valgrind(void) {
2575 static int b = 0;
2577 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2578 * here instead of really checking whether we run in valgrind or
2579 * not. */
2581 if (b < 1)
2582 b = getenv("VALGRIND") ? 2 : 1;
2584 return b > 1;
2586 #endif
2588 unsigned pa_gcd(unsigned a, unsigned b) {
2590 while (b > 0) {
2591 unsigned t = b;
2592 b = a % b;
2593 a = t;
2596 return a;
2599 void pa_reduce(unsigned *num, unsigned *den) {
2601 unsigned gcd = pa_gcd(*num, *den);
2603 if (gcd <= 0)
2604 return;
2606 *num /= gcd;
2607 *den /= gcd;
2609 pa_assert(pa_gcd(*num, *den) == 1);
2612 unsigned pa_ncpus(void) {
2613 long ncpus;
2615 #ifdef _SC_NPROCESSORS_CONF
2616 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2617 #else
2618 ncpus = 1;
2619 #endif
2621 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2624 char *pa_replace(const char*s, const char*a, const char *b) {
2625 pa_strbuf *sb;
2626 size_t an;
2628 pa_assert(s);
2629 pa_assert(a);
2630 pa_assert(b);
2632 an = strlen(a);
2633 sb = pa_strbuf_new();
2635 for (;;) {
2636 const char *p;
2638 if (!(p = strstr(s, a)))
2639 break;
2641 pa_strbuf_putsn(sb, s, p-s);
2642 pa_strbuf_puts(sb, b);
2643 s = p + an;
2646 pa_strbuf_puts(sb, s);
2648 return pa_strbuf_tostring_free(sb);
2651 char *pa_unescape(char *p) {
2652 char *s, *d;
2653 pa_bool_t escaped = FALSE;
2655 for (s = p, d = p; *s; s++) {
2656 if (!escaped && *s == '\\') {
2657 escaped = TRUE;
2658 continue;
2661 *(d++) = *s;
2662 escaped = FALSE;
2665 *d = 0;
2667 return p;
2670 char *pa_realpath(const char *path) {
2671 char *t;
2672 pa_assert(path);
2674 /* We want only abolsute paths */
2675 if (path[0] != '/') {
2676 errno = EINVAL;
2677 return NULL;
2680 #if defined(__GLIBC__) || defined(__APPLE__)
2682 char *r;
2684 if (!(r = realpath(path, NULL)))
2685 return NULL;
2687 /* We copy this here in case our pa_xmalloc() is not
2688 * implemented on top of libc malloc() */
2689 t = pa_xstrdup(r);
2690 pa_xfree(r);
2692 #elif defined(PATH_MAX)
2694 char *path_buf;
2695 path_buf = pa_xmalloc(PATH_MAX);
2697 if (!(t = realpath(path, path_buf))) {
2698 pa_xfree(path_buf);
2699 return NULL;
2702 #else
2703 #error "It's not clear whether this system supports realpath(..., NULL) like GNU libc does. If it doesn't we need a private version of realpath() here."
2704 #endif
2706 return t;
2709 void pa_disable_sigpipe(void) {
2711 #ifdef SIGPIPE
2712 struct sigaction sa;
2714 pa_zero(sa);
2716 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2717 pa_log("sigaction(): %s", pa_cstrerror(errno));
2718 return;
2721 sa.sa_handler = SIG_IGN;
2723 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2724 pa_log("sigaction(): %s", pa_cstrerror(errno));
2725 return;
2727 #endif
2730 void pa_xfreev(void**a) {
2731 void **p;
2733 if (!a)
2734 return;
2736 for (p = a; *p; p++)
2737 pa_xfree(*p);
2739 pa_xfree(a);
2742 char **pa_split_spaces_strv(const char *s) {
2743 char **t, *e;
2744 unsigned i = 0, n = 8;
2745 const char *state = NULL;
2747 t = pa_xnew(char*, n);
2748 while ((e = pa_split_spaces(s, &state))) {
2749 t[i++] = e;
2751 if (i >= n) {
2752 n *= 2;
2753 t = pa_xrenew(char*, t, n);
2757 if (i <= 0) {
2758 pa_xfree(t);
2759 return NULL;
2762 t[i] = NULL;
2763 return t;
2766 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2767 pa_assert(path);
2769 if (pa_is_path_absolute(path))
2770 return pa_xstrdup(path);
2772 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2775 size_t pa_pipe_buf(int fd) {
2777 #ifdef _PC_PIPE_BUF
2778 long n;
2780 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2781 return (size_t) n;
2782 #endif
2784 #ifdef PIPE_BUF
2785 return PIPE_BUF;
2786 #else
2787 return 4096;
2788 #endif
2791 void pa_reset_personality(void) {
2793 #ifdef __linux__
2794 if (personality(PER_LINUX) < 0)
2795 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2796 #endif
2800 #if defined(__linux__) && !defined(__OPTIMIZE__)
2802 pa_bool_t pa_run_from_build_tree(void) {
2803 char *rp;
2804 pa_bool_t b = FALSE;
2806 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2807 * or not. */
2809 if ((rp = pa_readlink("/proc/self/exe"))) {
2810 b = pa_startswith(rp, PA_BUILDDIR);
2811 pa_xfree(rp);
2814 return b;
2817 #endif