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
39 #include <sys/types.h>
45 #include <sys/utsname.h>
55 #ifdef HAVE_SYS_RESOURCE_H
56 #include <sys/resource.h>
59 #ifdef HAVE_SYS_CAPABILITY_H
60 #include <sys/capability.h>
63 #ifdef HAVE_SYS_MMAN_H
87 #ifdef HAVE_LIBSAMPLERATE
88 #include <samplerate.h>
95 #include <pulse/xmalloc.h>
96 #include <pulse/util.h>
97 #include <pulse/utf8.h>
99 #include <pulsecore/core-error.h>
100 #include <pulsecore/winsock.h>
101 #include <pulsecore/log.h>
102 #include <pulsecore/macro.h>
103 #include <pulsecore/thread.h>
104 #include <pulsecore/strbuf.h>
106 #include "core-util.h"
108 /* Not all platforms have this */
110 #define MSG_NOSIGNAL 0
115 #define PULSE_ROOTENV "PULSE_ROOT"
117 int pa_set_root(HANDLE handle
) {
118 char library_path
[MAX_PATH
+ sizeof(PULSE_ROOTENV
) + 1], *sep
;
120 strcpy(library_path
, PULSE_ROOTENV
"=");
122 /* FIXME: Needs to set errno */
124 if (!GetModuleFileName(handle
, library_path
+ sizeof(PULSE_ROOTENV
), MAX_PATH
))
127 sep
= strrchr(library_path
, PA_PATH_SEP_CHAR
);
131 if (_putenv(library_path
) < 0)
139 /** Make a file descriptor nonblock. Doesn't do any error checking */
140 void pa_make_fd_nonblock(int fd
) {
146 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
148 if (!(v
& O_NONBLOCK
))
149 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
151 #elif defined(OS_IS_WIN32)
153 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
154 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
155 pa_log_warn("Only sockets can be made non-blocking!");
158 pa_log_warn("Non-blocking I/O not supported.!");
163 /* Set the FD_CLOEXEC flag for a fd */
164 void pa_make_fd_cloexec(int fd
) {
170 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
172 if (!(v
& FD_CLOEXEC
))
173 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
178 /** Creates a directory securely */
179 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
190 u
= umask((~m
) & 0777);
196 if (r
< 0 && errno
!= EEXIST
)
200 if (uid
== (uid_t
)-1)
202 if (gid
== (gid_t
)-1)
204 (void) chown(dir
, uid
, gid
);
212 if (lstat(dir
, &st
) < 0)
214 if (stat(dir
, &st
) < 0)
219 if (!S_ISDIR(st
.st_mode
) ||
220 (st
.st_uid
!= uid
) ||
221 (st
.st_gid
!= gid
) ||
222 ((st
.st_mode
& 0777) != m
)) {
227 pa_log_warn("Secure directory creation not supported on Win32.");
240 /* Return a newly allocated sting containing the parent directory of the specified file */
241 char *pa_parent_dir(const char *fn
) {
242 char *slash
, *dir
= pa_xstrdup(fn
);
244 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
254 /* Creates a the parent directory of the specified path securely */
255 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
259 if (!(dir
= pa_parent_dir(fn
)))
262 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
272 /** Platform independent read function. Necessary since not all
273 * systems treat all file descriptors equal. If type is
274 * non-NULL it is used to cache the type of the fd. This is
275 * useful for making sure that only a single syscall is executed per
276 * function call. The variable pointed to should be initialized to 0
278 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
282 if (!type
|| *type
== 0) {
285 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
288 if (WSAGetLastError() != WSAENOTSOCK
) {
289 errno
= WSAGetLastError();
302 if ((r
= read(fd
, buf
, count
)) < 0)
310 /** Similar to pa_read(), but handles writes */
311 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
313 if (!type
|| *type
== 0) {
317 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
329 if (WSAGetLastError() != WSAENOTSOCK
) {
330 errno
= WSAGetLastError();
334 if (errno
!= ENOTSOCK
)
345 if ((r
= write(fd
, buf
, count
)) < 0)
353 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
354 * unless EOF is reached or an error occurred */
355 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
371 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
378 data
= (uint8_t*) data
+ r
;
385 /** Similar to pa_loop_read(), but wraps write() */
386 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
402 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
409 data
= (const uint8_t*) data
+ r
;
416 /** Platform independent read function. Necessary since not all
417 * systems treat all file descriptors equal. */
418 int pa_close(int fd
) {
423 if ((ret
= closesocket(fd
)) == 0)
426 if (WSAGetLastError() != WSAENOTSOCK
) {
427 errno
= WSAGetLastError();
435 if ((r
= close(fd
)) < 0)
443 /* Print a warning messages in case that the given signal is not
444 * blocked or trapped */
445 void pa_check_signal_is_blocked(int sig
) {
446 #ifdef HAVE_SIGACTION
450 /* If POSIX threads are supported use thread-aware
451 * pthread_sigmask() function, to check if the signal is
452 * blocked. Otherwise fall back to sigprocmask() */
455 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
457 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
458 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
465 if (sigismember(&set
, sig
))
468 /* Check whether the signal is trapped */
470 if (sigaction(sig
, NULL
, &sa
) < 0) {
471 pa_log("sigaction(): %s", pa_cstrerror(errno
));
475 if (sa
.sa_handler
!= SIG_DFL
)
478 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
479 #else /* HAVE_SIGACTION */
480 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
484 /* The following function is based on an example from the GNU libc
485 * documentation. This function is similar to GNU's asprintf(). */
486 char *pa_sprintf_malloc(const char *format
, ...) {
496 c
= pa_xrealloc(c
, size
);
498 va_start(ap
, format
);
499 r
= vsnprintf(c
, size
, format
, ap
);
504 if (r
> -1 && (size_t) r
< size
)
507 if (r
> -1) /* glibc 2.1 */
514 /* Same as the previous function, but use a va_list instead of an
516 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
526 c
= pa_xrealloc(c
, size
);
529 r
= vsnprintf(c
, size
, format
, aq
);
534 if (r
> -1 && (size_t) r
< size
)
537 if (r
> -1) /* glibc 2.1 */
544 /* Similar to OpenBSD's strlcpy() function */
545 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
555 /* Make the current thread a realtime thread, and acquire the highest
556 * rtprio we can get that is less or equal the specified parameter. If
557 * the thread is already realtime, don't do anything. */
558 int pa_make_realtime(int rtprio
) {
560 #ifdef _POSIX_PRIORITY_SCHEDULING
561 struct sched_param sp
;
564 memset(&sp
, 0, sizeof(sp
));
567 if ((r
= pthread_getschedparam(pthread_self(), &policy
, &sp
)) != 0) {
568 pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r
));
572 if (policy
== SCHED_FIFO
&& sp
.sched_priority
>= rtprio
) {
573 pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp
.sched_priority
);
577 sp
.sched_priority
= rtprio
;
578 if ((r
= pthread_setschedparam(pthread_self(), SCHED_FIFO
, &sp
)) != 0) {
580 while (sp
.sched_priority
> 1) {
581 sp
.sched_priority
--;
583 if ((r
= pthread_setschedparam(pthread_self(), SCHED_FIFO
, &sp
)) == 0) {
584 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp
.sched_priority
, rtprio
);
589 pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r
));
593 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp
.sched_priority
);
602 /* This is merely used for giving the user a hint. This is not correct
603 * for anything security related */
604 pa_bool_t
pa_can_realtime(void) {
609 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
613 if (getrlimit(RLIMIT_RTPRIO
, &rl
) >= 0)
614 if (rl
.rlim_cur
> 0 || rl
.rlim_cur
== RLIM_INFINITY
)
619 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
623 if ((cap
= cap_get_proc())) {
624 cap_flag_value_t flag
= CAP_CLEAR
;
626 if (cap_get_flag(cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, &flag
) >= 0)
627 if (flag
== CAP_SET
) {
640 /* This is merely used for giving the user a hint. This is not correct
641 * for anything security related */
642 pa_bool_t
pa_can_high_priority(void) {
647 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
651 if (getrlimit(RLIMIT_NICE
, &rl
) >= 0)
652 if (rl
.rlim_cur
>= 21 || rl
.rlim_cur
== RLIM_INFINITY
)
657 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
661 if ((cap
= cap_get_proc())) {
662 cap_flag_value_t flag
= CAP_CLEAR
;
664 if (cap_get_flag(cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, &flag
) >= 0)
665 if (flag
== CAP_SET
) {
678 /* Raise the priority of the current process as much as possible that
679 * is <= the specified nice level..*/
680 int pa_raise_priority(int nice_level
) {
682 #ifdef HAVE_SYS_RESOURCE_H
683 if (setpriority(PRIO_PROCESS
, 0, nice_level
) < 0) {
686 for (n
= nice_level
+1; n
< 0; n
++) {
688 if (setpriority(PRIO_PROCESS
, 0, n
) == 0) {
689 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
694 pa_log_warn("setpriority(): %s", pa_cstrerror(errno
));
698 pa_log_info("Successfully gained nice level %i.", nice_level
);
702 if (nice_level
< 0) {
703 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
704 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
708 pa_log_info("Successfully gained high priority class.");
715 /* Reset the priority to normal, inverting the changes made by
716 * pa_raise_priority() and pa_make_realtime()*/
717 void pa_reset_priority(void) {
718 #ifdef HAVE_SYS_RESOURCE_H
719 struct sched_param sp
;
721 setpriority(PRIO_PROCESS
, 0, 0);
723 memset(&sp
, 0, sizeof(sp
));
724 pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
) == 0);
728 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
732 int pa_match(const char *expr
, const char *v
) {
737 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
742 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
744 else if (k
== REG_NOMATCH
)
757 /* Try to parse a boolean string value.*/
758 int pa_parse_boolean(const char *v
) {
763 /* First we check language independant */
764 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
766 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
769 /* And then we check language dependant */
770 if ((expr
= nl_langinfo(YESEXPR
)))
772 if ((r
= pa_match(expr
, v
)) > 0)
775 if ((expr
= nl_langinfo(NOEXPR
)))
777 if ((r
= pa_match(expr
, v
)) > 0)
784 /* Split the specified string wherever one of the strings in delimiter
785 * occurs. Each time it is called returns a newly allocated string
786 * with pa_xmalloc(). The variable state points to, should be
787 * initiallized to NULL before the first call. */
788 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
789 const char *current
= *state
? *state
: c
;
795 l
= strcspn(current
, delimiter
);
801 return pa_xstrndup(current
, l
);
804 /* What is interpreted as whitespace? */
805 #define WHITESPACE " \t\n"
807 /* Split a string into words. Otherwise similar to pa_split(). */
808 char *pa_split_spaces(const char *c
, const char **state
) {
809 const char *current
= *state
? *state
: c
;
812 if (!*current
|| *c
== 0)
815 current
+= strspn(current
, WHITESPACE
);
816 l
= strcspn(current
, WHITESPACE
);
820 return pa_xstrndup(current
, l
);
823 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
825 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
826 const char *pa_sig2str(int sig
) {
839 char buf
[SIG2STR_MAX
];
841 if (sig2str(sig
, buf
) == 0) {
842 pa_xfree(PA_STATIC_TLS_GET(signame
));
843 t
= pa_sprintf_malloc("SIG%s", buf
);
844 PA_STATIC_TLS_SET(signame
, t
);
852 case SIGHUP
: return "SIGHUP";
854 case SIGINT
: return "SIGINT";
856 case SIGQUIT
: return "SIGQUIT";
858 case SIGILL
: return "SIGULL";
860 case SIGTRAP
: return "SIGTRAP";
862 case SIGABRT
: return "SIGABRT";
864 case SIGBUS
: return "SIGBUS";
866 case SIGFPE
: return "SIGFPE";
868 case SIGKILL
: return "SIGKILL";
871 case SIGUSR1
: return "SIGUSR1";
873 case SIGSEGV
: return "SIGSEGV";
875 case SIGUSR2
: return "SIGUSR2";
878 case SIGPIPE
: return "SIGPIPE";
881 case SIGALRM
: return "SIGALRM";
883 case SIGTERM
: return "SIGTERM";
885 case SIGSTKFLT
: return "SIGSTKFLT";
888 case SIGCHLD
: return "SIGCHLD";
891 case SIGCONT
: return "SIGCONT";
894 case SIGSTOP
: return "SIGSTOP";
897 case SIGTSTP
: return "SIGTSTP";
900 case SIGTTIN
: return "SIGTTIN";
903 case SIGTTOU
: return "SIGTTOU";
906 case SIGURG
: return "SIGURG";
909 case SIGXCPU
: return "SIGXCPU";
912 case SIGXFSZ
: return "SIGXFSZ";
915 case SIGVTALRM
: return "SIGVTALRM";
918 case SIGPROF
: return "SIGPROF";
921 case SIGWINCH
: return "SIGWINCH";
924 case SIGIO
: return "SIGIO";
927 case SIGPWR
: return "SIGPWR";
930 case SIGSYS
: return "SIGSYS";
935 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
936 pa_xfree(PA_STATIC_TLS_GET(signame
));
937 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
938 PA_STATIC_TLS_SET(signame
, t
);
947 pa_xfree(PA_STATIC_TLS_GET(signame
));
948 t
= pa_sprintf_malloc("SIG%i", sig
);
949 PA_STATIC_TLS_SET(signame
, t
);
955 /* Check whether the specified GID and the group name match */
956 static int is_group(gid_t gid
, const char *name
) {
957 struct group group
, *result
= NULL
;
962 #ifdef HAVE_GETGRGID_R
963 #ifdef _SC_GETGR_R_SIZE_MAX
964 n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
971 data
= pa_xmalloc((size_t) n
);
974 if (getgrgid_r(gid
, &group
, data
, (size_t) n
, &result
) < 0 || !result
) {
975 pa_log("getgrgid_r(%u): %s", (unsigned) gid
, pa_cstrerror(errno
));
983 r
= strcmp(name
, result
->gr_name
) == 0;
988 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
989 * support getgrgid_r. */
992 if (!(result
= getgrgid(gid
))) {
993 pa_log("getgrgid(%u): %s", gid
, pa_cstrerror(errno
));
1001 r
= strcmp(name
, result
->gr_name
) == 0;
1009 /* Check the current user is member of the specified group */
1010 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1011 GETGROUPS_T
*gids
, tgid
;
1012 long n
= sysconf(_SC_NGROUPS_MAX
);
1017 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1019 if ((n
= getgroups((int) n
, gids
)) < 0) {
1020 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1024 for (i
= 0; i
< n
; i
++) {
1026 if ((k
= is_group(gids
[i
], name
)) < 0)
1035 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1051 /* Check whether the specifc user id is a member of the specified group */
1052 int pa_uid_in_group(uid_t uid
, const char *name
) {
1053 char *g_buf
, *p_buf
;
1055 struct group grbuf
, *gr
;
1059 #ifdef _SC_GETGR_R_SIZE_MAX
1060 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
1067 g_buf
= pa_xmalloc((size_t) g_n
);
1069 #ifdef _SC_GETPW_R_SIZE_MAX
1070 p_n
= sysconf(_SC_GETPW_R_SIZE_MAX
);
1077 p_buf
= pa_xmalloc((size_t) p_n
);
1080 #ifdef HAVE_GETGRNAM_R
1081 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
1083 if (!(gr
= getgrnam(name
)))
1092 for (i
= gr
->gr_mem
; *i
; i
++) {
1093 struct passwd pwbuf
, *pw
;
1095 #ifdef HAVE_GETPWNAM_R
1096 if (getpwnam_r(*i
, &pwbuf
, p_buf
, (size_t) p_n
, &pw
) != 0 || !pw
)
1098 if (!(pw
= getpwnam(*i
)))
1102 if (pw
->pw_uid
== uid
) {
1115 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1116 gid_t
pa_get_gid_of_group(const char *name
) {
1117 gid_t ret
= (gid_t
) -1;
1120 struct group grbuf
, *gr
;
1122 #ifdef _SC_GETGR_R_SIZE_MAX
1123 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
1130 g_buf
= pa_xmalloc((size_t) g_n
);
1133 #ifdef HAVE_GETGRNAM_R
1134 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
1136 if (!(gr
= getgrnam(name
)))
1151 int pa_check_in_group(gid_t g
) {
1152 gid_t gids
[NGROUPS_MAX
];
1155 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1165 #else /* HAVE_GRP_H */
1167 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1173 int pa_uid_in_group(uid_t uid
, const char *name
) {
1178 gid_t
pa_get_gid_of_group(const char *name
) {
1183 int pa_check_in_group(gid_t g
) {
1190 /* Lock or unlock a file entirely.
1191 (advisory on UNIX, mandatory on Windows) */
1192 int pa_lock_fd(int fd
, int b
) {
1196 /* Try a R/W lock first */
1198 flock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1199 flock
.l_whence
= SEEK_SET
;
1203 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
1206 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1207 if (b
&& errno
== EBADF
) {
1208 flock
.l_type
= F_RDLCK
;
1209 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
1213 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1217 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
1219 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1221 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1224 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1226 /* FIXME: Needs to set errno! */
1232 /* Remove trailing newlines from a string */
1233 char* pa_strip_nl(char *s
) {
1236 s
[strcspn(s
, "\r\n")] = 0;
1240 /* Create a temporary lock file and lock it. */
1241 int pa_lock_lockfile(const char *fn
) {
1248 if ((fd
= open(fn
, O_CREAT
|O_RDWR
1255 , S_IRUSR
|S_IWUSR
)) < 0) {
1256 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1260 if (pa_lock_fd(fd
, 1) < 0) {
1261 pa_log_warn("Failed to lock file '%s'.", fn
);
1265 if (fstat(fd
, &st
) < 0) {
1266 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1270 /* Check whether the file has been removed meanwhile. When yes,
1271 * restart this loop, otherwise, we're done */
1272 if (st
.st_nlink
>= 1)
1275 if (pa_lock_fd(fd
, 0) < 0) {
1276 pa_log_warn("Failed to unlock file '%s'.", fn
);
1280 if (pa_close(fd
) < 0) {
1281 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1294 int saved_errno
= errno
;
1296 errno
= saved_errno
;
1302 /* Unlock a temporary lcok file */
1303 int pa_unlock_lockfile(const char *fn
, int fd
) {
1308 if (unlink(fn
) < 0) {
1309 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1314 if (pa_lock_fd(fd
, 0) < 0) {
1315 pa_log_warn("Failed to unlock file '%s'.", fn
);
1319 if (pa_close(fd
) < 0) {
1320 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1327 static char *get_pulse_home(void) {
1331 if (!pa_get_home_dir(h
, sizeof(h
))) {
1332 pa_log_error("Failed to get home directory.");
1336 if (stat(h
, &st
) < 0) {
1337 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1341 if (st
.st_uid
!= getuid()) {
1342 pa_log_error("Home directory %s not ours.", h
);
1347 return pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1350 char *pa_get_state_dir(void) {
1353 /* The state directory shall contain dynamic data that should be
1354 * kept across reboots, and is private to this user */
1356 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1357 if (!(d
= get_pulse_home()))
1360 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1361 * dir then this will break. */
1363 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1364 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1372 static char* make_random_dir(mode_t m
) {
1373 static const char table
[] =
1374 "abcdefghijklmnopqrstuvwxyz"
1375 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1382 if (!(tmpdir
= getenv("TMPDIR")))
1383 if (!(tmpdir
= getenv("TMP")))
1384 if (!(tmpdir
= getenv("TEMP")))
1385 tmpdir
= getenv("TEMPDIR");
1387 if (!tmpdir
|| !pa_is_path_absolute(tmpdir
))
1390 fn
= pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir
);
1391 pathlen
= strlen(fn
);
1399 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1400 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1402 u
= umask((~m
) & 0777);
1405 saved_errno
= errno
;
1407 errno
= saved_errno
;
1412 if (errno
!= EEXIST
) {
1413 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1420 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1423 if (!(p
= make_random_dir(m
)))
1426 if (symlink(p
, k
) < 0) {
1427 int saved_errno
= errno
;
1429 if (errno
!= EEXIST
)
1430 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1435 errno
= saved_errno
;
1443 char *pa_get_runtime_dir(void) {
1444 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1448 /* The runtime directory shall contain dynamic data that needs NOT
1449 * to be kept accross reboots and is usuallly private to the user,
1450 * except in system mode, where it might be accessible by other
1451 * users, too. Since we need POSIX locking and UNIX sockets in
1452 * this directory, we link it to a random subdir in /tmp, if it
1453 * was not explicitly configured. */
1455 m
= pa_in_system_mode() ? 0755U : 0700U;
1457 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1459 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1460 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1464 return pa_xstrdup(d
);
1467 if (!(d
= get_pulse_home()))
1470 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1471 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1476 if (!(mid
= pa_machine_id())) {
1481 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s:runtime", d
, mid
);
1486 /* OK, first let's check if the "runtime" symlink is already
1489 if (!(p
= pa_readlink(k
))) {
1491 if (errno
!= ENOENT
) {
1492 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1496 /* Hmm, so the runtime directory didn't exist yet, so let's
1497 * create one in /tmp and symlink that to it */
1499 if (make_random_dir_and_link(0700, k
) < 0) {
1501 /* Mhmm, maybe another process was quicker than us,
1502 * let's check if that was valid */
1503 if (errno
== EEXIST
)
1512 /* Make sure that this actually makes sense */
1513 if (!pa_is_path_absolute(p
)) {
1514 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1519 /* Hmm, so this symlink is still around, make sure nobody fools
1522 if (lstat(p
, &st
) < 0) {
1524 if (errno
!= ENOENT
) {
1525 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1531 if (S_ISDIR(st
.st_mode
) &&
1532 (st
.st_uid
== getuid()) &&
1533 ((st
.st_mode
& 0777) == 0700)) {
1539 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1545 /* Hmm, so the link points to some nonexisting or invalid
1546 * dir. Let's replace it by a new link. We first create a
1547 * temporary link and then rename that to allow concurrent
1548 * execution of this function. */
1550 t
= pa_sprintf_malloc("%s.tmp", k
);
1552 if (make_random_dir_and_link(0700, t
) < 0) {
1554 if (errno
!= EEXIST
) {
1555 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1562 /* Hmm, someone lese was quicker then us. Let's give
1563 * him some time to finish, and retry. */
1568 /* OK, we succeeded in creating the temporary symlink, so
1569 * let's rename it */
1570 if (rename(t
, k
) < 0) {
1571 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1587 /* Try to open a configuration file. If "env" is specified, open the
1588 * value of the specified environment variable. Otherwise look for a
1589 * file "local" in the home directory or a file "global" in global
1590 * file system. If "result" is non-NULL, a pointer to a newly
1591 * allocated buffer containing the used configuration file is
1593 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1598 if (!getenv(PULSE_ROOTENV
))
1602 if (env
&& (fn
= getenv(env
))) {
1606 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1607 /* FIXME: Needs to set errno! */
1612 if ((f
= fopen(fn
, "r"))) {
1614 *result
= pa_xstrdup(fn
);
1619 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1629 if ((e
= getenv("PULSE_CONFIG_PATH")))
1630 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1631 else if (pa_get_home_dir(h
, sizeof(h
)))
1632 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1637 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1638 /* FIXME: Needs to set errno! */
1645 if ((f
= fopen(fn
, "r"))) {
1647 *result
= pa_xstrdup(fn
);
1653 if (errno
!= ENOENT
) {
1654 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1666 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1667 /* FIXME: Needs to set errno! */
1672 if ((f
= fopen(global
, "r"))) {
1675 *result
= pa_xstrdup(global
);
1685 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1690 if (!getenv(PULSE_ROOTENV
))
1694 if (env
&& (fn
= getenv(env
))) {
1697 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1698 /* FIXME: Needs to set errno! */
1703 if (access(fn
, R_OK
) == 0)
1704 return pa_xstrdup(fn
);
1706 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1715 if ((e
= getenv("PULSE_CONFIG_PATH")))
1716 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1717 else if (pa_get_home_dir(h
, sizeof(h
)))
1718 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1723 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1724 /* FIXME: Needs to set errno! */
1731 if (access(fn
, R_OK
) == 0) {
1732 char *r
= pa_xstrdup(fn
);
1737 if (errno
!= ENOENT
) {
1738 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1748 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1749 /* FIXME: Needs to set errno! */
1754 if (access(global
, R_OK
) == 0)
1755 return pa_xstrdup(global
);
1763 /* Format the specified data as a hexademical string */
1764 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1765 size_t i
= 0, j
= 0;
1766 const char hex
[] = "0123456789abcdef";
1770 pa_assert(slength
> 0);
1772 while (i
< dlength
&& j
+3 <= slength
) {
1773 s
[j
++] = hex
[*d
>> 4];
1774 s
[j
++] = hex
[*d
& 0xF];
1780 s
[j
< slength
? j
: slength
] = 0;
1784 /* Convert a hexadecimal digit to a number or -1 if invalid */
1785 static int hexc(char c
) {
1786 if (c
>= '0' && c
<= '9')
1789 if (c
>= 'A' && c
<= 'F')
1790 return c
- 'A' + 10;
1792 if (c
>= 'a' && c
<= 'f')
1793 return c
- 'a' + 10;
1799 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1800 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1806 while (j
< dlength
&& *p
) {
1809 if ((b
= hexc(*(p
++))) < 0)
1812 d
[j
] = (uint8_t) (b
<< 4);
1817 if ((b
= hexc(*(p
++))) < 0)
1820 d
[j
] |= (uint8_t) b
;
1827 /* Returns nonzero when *s starts with *pfx */
1828 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1836 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1839 /* Returns nonzero when *s ends with *sfx */
1840 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1849 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1852 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1858 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1862 char *pa_make_path_absolute(const char *p
) {
1868 if (pa_is_path_absolute(p
))
1869 return pa_xstrdup(p
);
1871 if (!(cwd
= pa_getcwd()))
1872 return pa_xstrdup(p
);
1874 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1879 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1880 * if fn is non-null and starts with / return fn
1881 * otherwise append fn to the run time path and return it */
1882 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1885 if (pa_is_path_absolute(fn
))
1886 return pa_xstrdup(fn
);
1888 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1899 if (!(mid
= pa_machine_id())) {
1904 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s:%s", rtp
, mid
, fn
);
1907 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
1915 char *pa_runtime_path(const char *fn
) {
1916 return get_path(fn
, FALSE
, TRUE
);
1919 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
1920 return get_path(fn
, appendmid
, FALSE
);
1923 /* Convert the string s to a signed integer in *ret_i */
1924 int pa_atoi(const char *s
, int32_t *ret_i
) {
1932 l
= strtol(s
, &x
, 0);
1934 if (!x
|| *x
|| errno
) {
1940 if ((int32_t) l
!= l
) {
1945 *ret_i
= (int32_t) l
;
1950 /* Convert the string s to an unsigned integer in *ret_u */
1951 int pa_atou(const char *s
, uint32_t *ret_u
) {
1959 l
= strtoul(s
, &x
, 0);
1961 if (!x
|| *x
|| errno
) {
1967 if ((uint32_t) l
!= l
) {
1972 *ret_u
= (uint32_t) l
;
1977 #ifdef HAVE_STRTOF_L
1978 static locale_t c_locale
= NULL
;
1980 static void c_locale_destroy(void) {
1981 freelocale(c_locale
);
1985 int pa_atod(const char *s
, double *ret_d
) {
1992 /* This should be locale independent */
1994 #ifdef HAVE_STRTOF_L
1998 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
1999 atexit(c_locale_destroy
);
2005 f
= strtod_l(s
, &x
, c_locale
);
2013 if (!x
|| *x
|| errno
) {
2024 /* Same as snprintf, but guarantees NUL-termination on every platform */
2025 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2030 pa_assert(size
> 0);
2033 va_start(ap
, format
);
2034 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2040 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2041 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2045 pa_assert(size
> 0);
2048 ret
= vsnprintf(str
, size
, format
, ap
);
2055 if ((size_t) ret
> size
-1)
2058 return (size_t) ret
;
2061 /* Truncate the specified string, but guarantee that the string
2062 * returned still validates as UTF8 */
2063 char *pa_truncate_utf8(char *c
, size_t l
) {
2065 pa_assert(pa_utf8_valid(c
));
2072 while (l
> 0 && !pa_utf8_valid(c
))
2078 char *pa_getcwd(void) {
2082 char *p
= pa_xmalloc(l
);
2086 if (errno
!= ERANGE
)
2094 void *pa_will_need(const void *p
, size_t l
) {
2095 #ifdef RLIMIT_MEMLOCK
2106 a
= PA_PAGE_ALIGN_PTR(p
);
2107 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2109 #ifdef HAVE_POSIX_MADVISE
2110 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2111 pa_log_debug("posix_madvise() worked fine!");
2116 /* Most likely the memory was not mmap()ed from a file and thus
2117 * madvise() didn't work, so let's misuse mlock() do page this
2118 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2119 * inviting, the man page of mlock() tells us: "All pages that
2120 * contain a part of the specified address range are guaranteed to
2121 * be resident in RAM when the call returns successfully." */
2123 #ifdef RLIMIT_MEMLOCK
2124 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2126 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2127 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
));
2132 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2134 bs
= PA_PAGE_SIZE
*4;
2137 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2140 while (size
> 0 && bs
> 0) {
2145 if (mlock(a
, bs
) < 0) {
2146 bs
= PA_PAGE_ALIGN(bs
/ 2);
2150 pa_assert_se(munlock(a
, bs
) == 0);
2152 a
= (const uint8_t*) a
+ bs
;
2158 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2160 pa_log_debug("mlock() worked fine!");
2165 void pa_close_pipe(int fds
[2]) {
2169 pa_assert_se(pa_close(fds
[0]) == 0);
2172 pa_assert_se(pa_close(fds
[1]) == 0);
2174 fds
[0] = fds
[1] = -1;
2177 char *pa_readlink(const char *p
) {
2186 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2191 if ((size_t) n
< l
-1) {
2201 int pa_close_all(int except_fd
, ...) {
2206 va_start(ap
, except_fd
);
2209 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2214 p
= pa_xnew(int, n
+1);
2216 va_start(ap
, except_fd
);
2219 if (except_fd
>= 0) {
2223 while ((fd
= va_arg(ap
, int)) >= 0)
2230 r
= pa_close_allv(p
);
2236 int pa_close_allv(const int except_fds
[]) {
2245 if ((d
= opendir("/proc/self/fd"))) {
2249 while ((de
= readdir(d
))) {
2255 if (de
->d_name
[0] == '.')
2259 l
= strtol(de
->d_name
, &e
, 10);
2260 if (errno
!= 0 || !e
|| *e
) {
2268 if ((long) fd
!= l
) {
2281 for (i
= 0; except_fds
[i
] >= 0; i
++)
2282 if (except_fds
[i
] == fd
) {
2290 if (pa_close(fd
) < 0) {
2291 saved_errno
= errno
;
2293 errno
= saved_errno
;
2305 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2306 maxfd
= (int) rl
.rlim_max
;
2308 maxfd
= sysconf(_SC_OPEN_MAX
);
2310 for (fd
= 3; fd
< maxfd
; fd
++) {
2315 for (i
= 0; except_fds
[i
] >= 0; i
++)
2316 if (except_fds
[i
] == fd
) {
2324 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2331 int pa_unblock_sigs(int except
, ...) {
2336 va_start(ap
, except
);
2339 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2344 p
= pa_xnew(int, n
+1);
2346 va_start(ap
, except
);
2353 while ((sig
= va_arg(ap
, int)) >= 0)
2360 r
= pa_unblock_sigsv(p
);
2366 int pa_unblock_sigsv(const int except
[]) {
2370 if (sigemptyset(&ss
) < 0)
2373 for (i
= 0; except
[i
] > 0; i
++)
2374 if (sigaddset(&ss
, except
[i
]) < 0)
2377 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2380 int pa_reset_sigs(int except
, ...) {
2385 va_start(ap
, except
);
2388 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2393 p
= pa_xnew(int, n
+1);
2395 va_start(ap
, except
);
2402 while ((sig
= va_arg(ap
, int)) >= 0)
2409 r
= pa_reset_sigsv(p
);
2415 int pa_reset_sigsv(const int except
[]) {
2418 for (sig
= 1; sig
< NSIG
; sig
++) {
2419 pa_bool_t reset
= TRUE
;
2430 for (i
= 0; except
[i
] > 0; i
++) {
2431 if (sig
== except
[i
]) {
2440 struct sigaction sa
;
2442 memset(&sa
, 0, sizeof(sa
));
2443 sa
.sa_handler
= SIG_DFL
;
2445 /* On Linux the first two RT signals are reserved by
2446 * glibc, and sigaction() will return EINVAL for them. */
2447 if ((sigaction(sig
, &sa
, NULL
) < 0))
2448 if (errno
!= EINVAL
)
2456 void pa_set_env(const char *key
, const char *value
) {
2460 putenv(pa_sprintf_malloc("%s=%s", key
, value
));
2463 pa_bool_t
pa_in_system_mode(void) {
2466 if (!(e
= getenv("PULSE_SYSTEM")))
2472 char *pa_get_user_name_malloc(void) {
2476 #ifdef _SC_LOGIN_NAME_MAX
2477 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2483 u
= pa_xnew(char, k
+1);
2485 if (!(pa_get_user_name(u
, k
))) {
2493 char *pa_get_host_name_malloc(void) {
2502 if (!pa_get_host_name(c
, l
)) {
2504 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2507 } else if (strlen(c
) < l
-1) {
2515 u
= pa_utf8_filter(c
);
2520 /* Hmm, the hostname is as long the space we offered the
2521 * function, we cannot know if it fully fit in, so let's play
2522 * safe and retry. */
2531 char *pa_machine_id(void) {
2535 /* The returned value is supposed be some kind of ascii identifier
2536 * that is unique and stable across reboots. */
2538 /* First we try the D-Bus UUID, which is the best option we have,
2539 * since it fits perfectly our needs and is not as volatile as the
2540 * hostname which might be set from dhcp. */
2542 if ((f
= fopen(PA_MACHINE_ID
, "r"))) {
2543 char ln
[34] = "", *r
;
2545 r
= fgets(ln
, sizeof(ln
)-1, f
);
2551 return pa_utf8_filter(ln
);
2554 if ((h
= pa_get_host_name_malloc()))
2557 /* If no hostname was set we use the POSIX hostid. It's usually
2558 * the IPv4 address. Might not be that stable. */
2559 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2562 char *pa_session_id(void) {
2565 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2568 return pa_utf8_filter(e
);
2571 char *pa_uname_string(void) {
2574 pa_assert_se(uname(&u
) >= 0);
2576 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2579 #ifdef HAVE_VALGRIND_MEMCHECK_H
2580 pa_bool_t
pa_in_valgrind(void) {
2583 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2584 * here instead of really checking whether we run in valgrind or
2588 b
= getenv("VALGRIND") ? 2 : 1;
2594 unsigned pa_gcd(unsigned a
, unsigned b
) {
2605 void pa_reduce(unsigned *num
, unsigned *den
) {
2607 unsigned gcd
= pa_gcd(*num
, *den
);
2615 pa_assert(pa_gcd(*num
, *den
) == 1);
2618 unsigned pa_ncpus(void) {
2621 #ifdef _SC_NPROCESSORS_CONF
2622 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2627 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2630 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2639 sb
= pa_strbuf_new();
2644 if (!(p
= strstr(s
, a
)))
2647 pa_strbuf_putsn(sb
, s
, p
-s
);
2648 pa_strbuf_puts(sb
, b
);
2652 pa_strbuf_puts(sb
, s
);
2654 return pa_strbuf_tostring_free(sb
);
2657 char *pa_unescape(char *p
) {
2659 pa_bool_t escaped
= FALSE
;
2661 for (s
= p
, d
= p
; *s
; s
++) {
2662 if (!escaped
&& *s
== '\\') {
2676 char *pa_realpath(const char *path
) {
2680 /* We want only abolsute paths */
2681 if (path
[0] != '/') {
2686 #if defined(__GLIBC__) || defined(__APPLE__)
2690 if (!(r
= realpath(path
, NULL
)))
2693 /* We copy this here in case our pa_xmalloc() is not
2694 * implemented on top of libc malloc() */
2698 #elif defined(PATH_MAX)
2701 path_buf
= pa_xmalloc(PATH_MAX
);
2703 if (!(t
= realpath(path
, path_buf
))) {
2709 #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."
2715 void pa_disable_sigpipe(void) {
2718 struct sigaction sa
;
2722 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2723 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2727 sa
.sa_handler
= SIG_IGN
;
2729 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2730 pa_log("sigaction(): %s", pa_cstrerror(errno
));