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
38 #include <sys/types.h>
42 #ifdef HAVE_LANGINFO_H
47 #include <sys/utsname.h>
50 #if defined(HAVE_REGEX_H)
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
76 #ifdef HAVE_SYS_MMAN_H
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
110 #include <mach/mach_init.h>
111 #include <mach/thread_act.h>
112 #include <mach/thread_policy.h>
113 #include <sys/sysctl.h>
121 #include <sys/personality.h>
124 #include <pulse/xmalloc.h>
125 #include <pulse/util.h>
126 #include <pulse/utf8.h>
128 #include <pulsecore/core-error.h>
129 #include <pulsecore/socket.h>
130 #include <pulsecore/log.h>
131 #include <pulsecore/macro.h>
132 #include <pulsecore/thread.h>
133 #include <pulsecore/strbuf.h>
134 #include <pulsecore/usergroup.h>
135 #include <pulsecore/strlist.h>
136 #include <pulsecore/cpu-x86.h>
137 #include <pulsecore/pipe.h>
139 #include "core-util.h"
141 /* Not all platforms have this */
143 #define MSG_NOSIGNAL 0
146 #define NEWLINE "\r\n"
147 #define WHITESPACE "\n\r \t"
149 static pa_strlist
*recorded_env
= NULL
;
155 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
156 char *pa_win32_get_toplevel(HANDLE handle
) {
157 static char *toplevel
= NULL
;
160 char library_path
[MAX_PATH
];
163 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
166 toplevel
= pa_xstrdup(library_path
);
168 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
172 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
173 if (p
&& pa_streq(p
+ 1, "bin"))
182 /** Make a file descriptor nonblock. Doesn't do any error checking */
183 void pa_make_fd_nonblock(int fd
) {
189 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
191 if (!(v
& O_NONBLOCK
))
192 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
194 #elif defined(OS_IS_WIN32)
196 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
197 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
198 pa_log_warn("Only sockets can be made non-blocking!");
201 pa_log_warn("Non-blocking I/O not supported.!");
206 /* Set the FD_CLOEXEC flag for a fd */
207 void pa_make_fd_cloexec(int fd
) {
213 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
215 if (!(v
& FD_CLOEXEC
))
216 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
221 /** Creates a directory securely. Will create parent directories recursively if
222 * required. This will not update permissions on parent directories if they
223 * already exist, however. */
224 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
, pa_bool_t update_perms
) {
227 pa_bool_t retry
= TRUE
;
237 u
= umask((~m
) & 0777);
243 if (r
< 0 && errno
== ENOENT
&& retry
) {
244 /* If a parent directory in the path doesn't exist, try to create that
245 * first, then try again. */
246 pa_make_secure_parent_dir(dir
, m
, uid
, gid
, FALSE
);
251 if (r
< 0 && errno
!= EEXIST
)
254 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
270 if (fstat(fd
, &st
) < 0) {
271 pa_assert_se(pa_close(fd
) >= 0);
275 if (!S_ISDIR(st
.st_mode
)) {
276 pa_assert_se(pa_close(fd
) >= 0);
285 if (uid
== (uid_t
) -1)
287 if (gid
== (gid_t
) -1)
289 if (fchown(fd
, uid
, gid
) < 0)
294 (void) fchmod(fd
, m
);
297 pa_assert_se(pa_close(fd
) >= 0);
302 if (lstat(dir
, &st
) < 0)
304 if (stat(dir
, &st
) < 0)
309 if (!S_ISDIR(st
.st_mode
) ||
310 (st
.st_uid
!= uid
) ||
311 (st
.st_gid
!= gid
) ||
312 ((st
.st_mode
& 0777) != m
)) {
317 pa_log_warn("Secure directory creation not supported on Win32.");
330 /* Return a newly allocated sting containing the parent directory of the specified file */
331 char *pa_parent_dir(const char *fn
) {
332 char *slash
, *dir
= pa_xstrdup(fn
);
334 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
344 /* Creates a the parent directory of the specified path securely */
345 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
, pa_bool_t update_perms
) {
349 if (!(dir
= pa_parent_dir(fn
)))
352 if (pa_make_secure_dir(dir
, m
, uid
, gid
, update_perms
) < 0)
362 /** Platform independent read function. Necessary since not all
363 * systems treat all file descriptors equal. If type is
364 * non-NULL it is used to cache the type of the fd. This is
365 * useful for making sure that only a single syscall is executed per
366 * function call. The variable pointed to should be initialized to 0
368 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
372 if (!type
|| *type
== 0) {
377 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
380 err
= WSAGetLastError();
381 if (err
!= WSAENOTSOCK
) {
382 /* transparently handle non-blocking sockets, by waiting
384 if (err
== WSAEWOULDBLOCK
) {
388 if (pa_poll(&pfd
, 1, -1) >= 0) {
405 if ((r
= read(fd
, buf
, count
)) < 0)
413 /** Similar to pa_read(), but handles writes */
414 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
416 if (!type
|| *type
== 0) {
422 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
434 err
= WSAGetLastError();
435 if (err
!= WSAENOTSOCK
) {
436 /* transparently handle non-blocking sockets, by waiting
438 if (err
== WSAEWOULDBLOCK
) {
441 pfd
.events
= POLLOUT
;
442 if (pa_poll(&pfd
, 1, -1) >= 0) {
450 if (errno
!= ENOTSOCK
)
461 if ((r
= write(fd
, buf
, count
)) < 0)
469 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
470 * unless EOF is reached or an error occurred */
471 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
487 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
494 data
= (uint8_t*) data
+ r
;
501 /** Similar to pa_loop_read(), but wraps write() */
502 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
518 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
525 data
= (const uint8_t*) data
+ r
;
532 /** Platform independent read function. Necessary since not all
533 * systems treat all file descriptors equal. */
534 int pa_close(int fd
) {
539 if ((ret
= closesocket(fd
)) == 0)
542 if (WSAGetLastError() != WSAENOTSOCK
) {
543 errno
= WSAGetLastError();
551 if ((r
= close(fd
)) < 0)
559 /* Print a warning messages in case that the given signal is not
560 * blocked or trapped */
561 void pa_check_signal_is_blocked(int sig
) {
562 #ifdef HAVE_SIGACTION
566 /* If POSIX threads are supported use thread-aware
567 * pthread_sigmask() function, to check if the signal is
568 * blocked. Otherwise fall back to sigprocmask() */
571 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
573 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
574 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
581 if (sigismember(&set
, sig
))
584 /* Check whether the signal is trapped */
586 if (sigaction(sig
, NULL
, &sa
) < 0) {
587 pa_log("sigaction(): %s", pa_cstrerror(errno
));
591 if (sa
.sa_handler
!= SIG_DFL
)
594 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
595 #else /* HAVE_SIGACTION */
596 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
600 /* The following function is based on an example from the GNU libc
601 * documentation. This function is similar to GNU's asprintf(). */
602 char *pa_sprintf_malloc(const char *format
, ...) {
612 c
= pa_xrealloc(c
, size
);
614 va_start(ap
, format
);
615 r
= vsnprintf(c
, size
, format
, ap
);
620 if (r
> -1 && (size_t) r
< size
)
623 if (r
> -1) /* glibc 2.1 */
630 /* Same as the previous function, but use a va_list instead of an
632 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
642 c
= pa_xrealloc(c
, size
);
645 r
= vsnprintf(c
, size
, format
, aq
);
650 if (r
> -1 && (size_t) r
< size
)
653 if (r
> -1) /* glibc 2.1 */
660 /* Similar to OpenBSD's strlcpy() function */
661 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
679 #ifdef _POSIX_PRIORITY_SCHEDULING
680 static int set_scheduler(int rtprio
) {
682 struct sched_param sp
;
688 dbus_error_init(&error
);
692 sp
.sched_priority
= rtprio
;
694 #ifdef SCHED_RESET_ON_FORK
695 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
696 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
701 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
702 pa_log_debug("SCHED_RR worked.");
705 #endif /* HAVE_SCHED_H */
708 /* Try to talk to RealtimeKit */
710 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
711 pa_log("Failed to connect to system bus: %s\n", error
.message
);
712 dbus_error_free(&error
);
717 /* We need to disable exit on disconnect because otherwise
718 * dbus_shutdown will kill us. See
719 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
720 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
722 r
= rtkit_make_realtime(bus
, 0, rtprio
);
723 dbus_connection_close(bus
);
724 dbus_connection_unref(bus
);
727 pa_log_debug("RealtimeKit worked.");
740 /* Make the current thread a realtime thread, and acquire the highest
741 * rtprio we can get that is less or equal the specified parameter. If
742 * the thread is already realtime, don't do anything. */
743 int pa_make_realtime(int rtprio
) {
745 #if defined(OS_IS_DARWIN)
746 struct thread_time_constraint_policy ttcpolicy
;
748 size_t size
= sizeof(freq
);
751 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
753 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
757 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
759 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
760 ttcpolicy
.period
= freq
/ 160;
761 ttcpolicy
.computation
= freq
/ 3300;
762 ttcpolicy
.constraint
= freq
/ 2200;
763 ttcpolicy
.preemptible
= 1;
765 ret
= thread_policy_set(mach_thread_self(),
766 THREAD_TIME_CONSTRAINT_POLICY
,
767 (thread_policy_t
) &ttcpolicy
,
768 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
770 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
774 pa_log_info("Successfully acquired real-time thread priority.");
777 #elif defined(_POSIX_PRIORITY_SCHEDULING)
780 if (set_scheduler(rtprio
) >= 0) {
781 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
785 for (p
= rtprio
-1; p
>= 1; p
--)
786 if (set_scheduler(p
) >= 0) {
787 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
790 #elif defined(OS_IS_WIN32)
791 /* Windows only allows realtime scheduling to be set on a per process basis.
792 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
793 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
794 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
798 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
803 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
807 #ifdef HAVE_SYS_RESOURCE_H
808 static int set_nice(int nice_level
) {
814 dbus_error_init(&error
);
817 #ifdef HAVE_SYS_RESOURCE_H
818 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
819 pa_log_debug("setpriority() worked.");
825 /* Try to talk to RealtimeKit */
827 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
828 pa_log("Failed to connect to system bus: %s\n", error
.message
);
829 dbus_error_free(&error
);
834 /* We need to disable exit on disconnect because otherwise
835 * dbus_shutdown will kill us. See
836 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
837 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
839 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
840 dbus_connection_unref(bus
);
843 pa_log_debug("RealtimeKit worked.");
854 /* Raise the priority of the current process as much as possible that
855 * is <= the specified nice level..*/
856 int pa_raise_priority(int nice_level
) {
858 #ifdef HAVE_SYS_RESOURCE_H
861 if (set_nice(nice_level
) >= 0) {
862 pa_log_info("Successfully gained nice level %i.", nice_level
);
866 for (n
= nice_level
+1; n
< 0; n
++)
867 if (set_nice(n
) >= 0) {
868 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
872 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
877 if (nice_level
< 0) {
878 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
879 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
884 pa_log_info("Successfully gained high priority class.");
891 /* Reset the priority to normal, inverting the changes made by
892 * pa_raise_priority() and pa_make_realtime()*/
893 void pa_reset_priority(void) {
894 #ifdef HAVE_SYS_RESOURCE_H
895 struct sched_param sp
;
897 setpriority(PRIO_PROCESS
, 0, 0);
900 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
904 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
908 int pa_match(const char *expr
, const char *v
) {
913 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
918 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
920 else if (k
== REG_NOMATCH
)
933 /* Try to parse a boolean string value.*/
934 int pa_parse_boolean(const char *v
) {
937 /* First we check language independent */
938 if (pa_streq(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
940 else if (pa_streq(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
943 #ifdef HAVE_LANGINFO_H
946 /* And then we check language dependent */
947 if ((expr
= nl_langinfo(YESEXPR
)))
949 if (pa_match(expr
, v
) > 0)
952 if ((expr
= nl_langinfo(NOEXPR
)))
954 if (pa_match(expr
, v
) > 0)
963 /* Split the specified string wherever one of the strings in delimiter
964 * occurs. Each time it is called returns a newly allocated string
965 * with pa_xmalloc(). The variable state points to, should be
966 * initialized to NULL before the first call. */
967 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
968 const char *current
= *state
? *state
: c
;
974 l
= strcspn(current
, delimiter
);
980 return pa_xstrndup(current
, l
);
983 /* Split the specified string wherever one of the strings in delimiter
984 * occurs. Each time it is called returns a pointer to the substring within the
985 * string and the length in 'n'. Note that the resultant string cannot be used
986 * as-is without the length parameter, since it is merely pointing to a point
987 * within the original string. The variable state points to, should be
988 * initialized to NULL before the first call. */
989 const char *pa_split_in_place(const char *c
, const char *delimiter
, int *n
, const char**state
) {
990 const char *current
= *state
? *state
: c
;
996 l
= strcspn(current
, delimiter
);
1006 /* Split a string into words. Otherwise similar to pa_split(). */
1007 char *pa_split_spaces(const char *c
, const char **state
) {
1008 const char *current
= *state
? *state
: c
;
1011 if (!*current
|| *c
== 0)
1014 current
+= strspn(current
, WHITESPACE
);
1015 l
= strcspn(current
, WHITESPACE
);
1019 return pa_xstrndup(current
, l
);
1022 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
1024 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
1025 const char *pa_sig2str(int sig
) {
1038 char buf
[SIG2STR_MAX
];
1040 if (sig2str(sig
, buf
) == 0) {
1041 pa_xfree(PA_STATIC_TLS_GET(signame
));
1042 t
= pa_sprintf_malloc("SIG%s", buf
);
1043 PA_STATIC_TLS_SET(signame
, t
);
1051 case SIGHUP
: return "SIGHUP";
1053 case SIGINT
: return "SIGINT";
1055 case SIGQUIT
: return "SIGQUIT";
1057 case SIGILL
: return "SIGULL";
1059 case SIGTRAP
: return "SIGTRAP";
1061 case SIGABRT
: return "SIGABRT";
1063 case SIGBUS
: return "SIGBUS";
1065 case SIGFPE
: return "SIGFPE";
1067 case SIGKILL
: return "SIGKILL";
1070 case SIGUSR1
: return "SIGUSR1";
1072 case SIGSEGV
: return "SIGSEGV";
1074 case SIGUSR2
: return "SIGUSR2";
1077 case SIGPIPE
: return "SIGPIPE";
1080 case SIGALRM
: return "SIGALRM";
1082 case SIGTERM
: return "SIGTERM";
1084 case SIGSTKFLT
: return "SIGSTKFLT";
1087 case SIGCHLD
: return "SIGCHLD";
1090 case SIGCONT
: return "SIGCONT";
1093 case SIGSTOP
: return "SIGSTOP";
1096 case SIGTSTP
: return "SIGTSTP";
1099 case SIGTTIN
: return "SIGTTIN";
1102 case SIGTTOU
: return "SIGTTOU";
1105 case SIGURG
: return "SIGURG";
1108 case SIGXCPU
: return "SIGXCPU";
1111 case SIGXFSZ
: return "SIGXFSZ";
1114 case SIGVTALRM
: return "SIGVTALRM";
1117 case SIGPROF
: return "SIGPROF";
1120 case SIGWINCH
: return "SIGWINCH";
1123 case SIGIO
: return "SIGIO";
1126 case SIGPWR
: return "SIGPWR";
1129 case SIGSYS
: return "SIGSYS";
1134 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1135 pa_xfree(PA_STATIC_TLS_GET(signame
));
1136 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1137 PA_STATIC_TLS_SET(signame
, t
);
1146 pa_xfree(PA_STATIC_TLS_GET(signame
));
1147 t
= pa_sprintf_malloc("SIG%i", sig
);
1148 PA_STATIC_TLS_SET(signame
, t
);
1154 /* Check whether the specified GID and the group name match */
1155 static int is_group(gid_t gid
, const char *name
) {
1156 struct group
*group
= NULL
;
1160 if (!(group
= pa_getgrgid_malloc(gid
))) {
1164 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1169 r
= pa_streq(name
, group
->gr_name
);
1172 pa_getgrgid_free(group
);
1177 /* Check the current user is member of the specified group */
1178 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1179 GETGROUPS_T
*gids
, tgid
;
1180 long n
= sysconf(_SC_NGROUPS_MAX
);
1185 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1187 if ((n
= getgroups((int) n
, gids
)) < 0) {
1188 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1192 for (i
= 0; i
< n
; i
++) {
1194 if ((k
= is_group(gids
[i
], name
)) < 0)
1203 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1219 /* Check whether the specific user id is a member of the specified group */
1220 int pa_uid_in_group(uid_t uid
, const char *name
) {
1221 struct group
*group
= NULL
;
1226 if (!(group
= pa_getgrnam_malloc(name
))) {
1233 for (i
= group
->gr_mem
; *i
; i
++) {
1234 struct passwd
*pw
= NULL
;
1237 if (!(pw
= pa_getpwnam_malloc(*i
)))
1240 if (pw
->pw_uid
== uid
)
1243 pa_getpwnam_free(pw
);
1250 pa_getgrnam_free(group
);
1255 /* Get the GID of a given group, return (gid_t) -1 on failure. */
1256 gid_t
pa_get_gid_of_group(const char *name
) {
1257 gid_t ret
= (gid_t
) -1;
1258 struct group
*gr
= NULL
;
1261 if (!(gr
= pa_getgrnam_malloc(name
))) {
1270 pa_getgrnam_free(gr
);
1274 int pa_check_in_group(gid_t g
) {
1275 gid_t gids
[NGROUPS_MAX
];
1278 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1288 #else /* HAVE_GRP_H */
1290 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1296 int pa_uid_in_group(uid_t uid
, const char *name
) {
1301 gid_t
pa_get_gid_of_group(const char *name
) {
1306 int pa_check_in_group(gid_t g
) {
1313 /* Lock or unlock a file entirely.
1314 (advisory on UNIX, mandatory on Windows) */
1315 int pa_lock_fd(int fd
, int b
) {
1317 struct flock f_lock
;
1319 /* Try a R/W lock first */
1321 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1322 f_lock
.l_whence
= SEEK_SET
;
1326 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1329 /* Perhaps the file descriptor was opened for read only, than try again with a read lock. */
1330 if (b
&& errno
== EBADF
) {
1331 f_lock
.l_type
= F_RDLCK
;
1332 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1336 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1340 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1342 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1344 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1347 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1349 /* FIXME: Needs to set errno! */
1355 /* Remove trailing newlines from a string */
1356 char* pa_strip_nl(char *s
) {
1359 s
[strcspn(s
, NEWLINE
)] = 0;
1363 char *pa_strip(char *s
) {
1366 /* Drops trailing whitespace. Modifies the string in
1367 * place. Returns pointer to first non-space character */
1369 s
+= strspn(s
, WHITESPACE
);
1371 for (e
= s
; *e
; e
++)
1372 if (!strchr(WHITESPACE
, *e
))
1383 /* Create a temporary lock file and lock it. */
1384 int pa_lock_lockfile(const char *fn
) {
1391 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1395 , S_IRUSR
|S_IWUSR
)) < 0) {
1396 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1400 if (pa_lock_fd(fd
, 1) < 0) {
1401 pa_log_warn("Failed to lock file '%s'.", fn
);
1405 if (fstat(fd
, &st
) < 0) {
1406 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1410 /* Check whether the file has been removed meanwhile. When yes,
1411 * restart this loop, otherwise, we're done */
1412 if (st
.st_nlink
>= 1)
1415 if (pa_lock_fd(fd
, 0) < 0) {
1416 pa_log_warn("Failed to unlock file '%s'.", fn
);
1420 if (pa_close(fd
) < 0) {
1421 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1432 int saved_errno
= errno
;
1434 errno
= saved_errno
;
1440 /* Unlock a temporary lock file */
1441 int pa_unlock_lockfile(const char *fn
, int fd
) {
1446 if (unlink(fn
) < 0) {
1447 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1452 if (pa_lock_fd(fd
, 0) < 0) {
1453 pa_log_warn("Failed to unlock file '%s'.", fn
);
1457 if (pa_close(fd
) < 0) {
1458 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1465 static char *get_config_home(char *home
) {
1468 t
= getenv("XDG_CONFIG_HOME");
1470 return pa_xstrdup(t
);
1472 return pa_sprintf_malloc("%s" PA_PATH_SEP
".config", home
);
1475 static int check_ours(const char *p
) {
1480 if (stat(p
, &st
) < 0)
1484 if (st
.st_uid
!= getuid())
1491 static char *get_pulse_home(void) {
1492 char *h
, *ret
, *config_home
;
1495 h
= pa_get_home_dir_malloc();
1497 pa_log_error("Failed to get home directory.");
1502 if (t
< 0 && t
!= -ENOENT
) {
1503 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t
));
1508 /* If the old directory exists, use it. */
1509 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1510 if (access(ret
, F_OK
) >= 0) {
1516 /* Otherwise go for the XDG compliant directory. */
1517 config_home
= get_config_home(h
);
1519 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", config_home
);
1525 char *pa_get_state_dir(void) {
1528 /* The state directory shall contain dynamic data that should be
1529 * kept across reboots, and is private to this user */
1531 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1532 if (!(d
= get_pulse_home()))
1535 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1536 * dir then this will break. */
1538 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1539 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1547 char *pa_get_home_dir_malloc(void) {
1549 size_t allocated
= 128;
1552 homedir
= pa_xmalloc(allocated
);
1554 if (!pa_get_home_dir(homedir
, allocated
)) {
1559 if (strlen(homedir
) < allocated
- 1)
1569 char *pa_get_binary_name_malloc(void) {
1571 size_t allocated
= 128;
1574 t
= pa_xmalloc(allocated
);
1576 if (!pa_get_binary_name(t
, allocated
)) {
1581 if (strlen(t
) < allocated
- 1)
1591 static char* make_random_dir(mode_t m
) {
1592 static const char table
[] =
1593 "abcdefghijklmnopqrstuvwxyz"
1594 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1600 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1601 pathlen
= strlen(fn
);
1609 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1610 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1612 u
= umask((~m
) & 0777);
1619 saved_errno
= errno
;
1621 errno
= saved_errno
;
1626 if (errno
!= EEXIST
) {
1627 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1634 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1637 if (!(p
= make_random_dir(m
)))
1641 if (symlink(p
, k
) < 0) {
1642 int saved_errno
= errno
;
1644 if (errno
!= EEXIST
)
1645 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1650 errno
= saved_errno
;
1662 char *pa_get_runtime_dir(void) {
1663 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1666 /* The runtime directory shall contain dynamic data that needs NOT
1667 * to be kept across reboots and is usually private to the user,
1668 * except in system mode, where it might be accessible by other
1669 * users, too. Since we need POSIX locking and UNIX sockets in
1670 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1671 * set create a directory in $HOME and link it to a random subdir
1672 * in /tmp, if it was not explicitly configured. */
1674 m
= pa_in_system_mode() ? 0755U : 0700U;
1676 /* Use the explicitly configured value if it is set */
1677 d
= getenv("PULSE_RUNTIME_PATH");
1680 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1681 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1685 return pa_xstrdup(d
);
1688 /* Use the XDG standard for the runtime directory. */
1689 d
= getenv("XDG_RUNTIME_DIR");
1691 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", d
);
1693 if (pa_make_secure_dir(k
, m
, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1695 pa_log_error("Failed to create secure directory (%s): %s", k
, pa_cstrerror(errno
));
1702 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1703 d
= get_pulse_home();
1707 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1708 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1713 mid
= pa_machine_id();
1719 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1724 /* OK, first let's check if the "runtime" symlink already exists */
1729 if (errno
!= ENOENT
) {
1730 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1735 /* Hmm, so the runtime directory didn't exist yet, so let's
1736 * create one in /tmp and symlink that to it */
1738 if (make_random_dir_and_link(0700, k
) < 0) {
1740 /* Mhmm, maybe another process was quicker than us,
1741 * let's check if that was valid */
1742 if (errno
== EEXIST
)
1748 /* No symlink possible, so let's just create the runtime directly */
1756 /* Make sure that this actually makes sense */
1757 if (!pa_is_path_absolute(p
)) {
1758 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1763 /* Hmm, so this symlink is still around, make sure nobody fools us */
1767 if (lstat(p
, &st
) < 0) {
1769 if (errno
!= ENOENT
) {
1770 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1776 if (S_ISDIR(st
.st_mode
) &&
1777 (st
.st_uid
== getuid()) &&
1778 ((st
.st_mode
& 0777) == 0700)) {
1784 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1792 /* Hmm, so the link points to some nonexisting or invalid
1793 * dir. Let's replace it by a new link. We first create a
1794 * temporary link and then rename that to allow concurrent
1795 * execution of this function. */
1797 t
= pa_sprintf_malloc("%s.tmp", k
);
1799 if (make_random_dir_and_link(0700, t
) < 0) {
1801 if (errno
!= EEXIST
) {
1802 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1809 /* Hmm, someone else was quicker then us. Let's give
1810 * him some time to finish, and retry. */
1815 /* OK, we succeeded in creating the temporary symlink, so
1816 * let's rename it */
1817 if (rename(t
, k
) < 0) {
1818 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1834 /* Try to open a configuration file. If "env" is specified, open the
1835 * value of the specified environment variable. Otherwise look for a
1836 * file "local" in the home directory or a file "global" in global
1837 * file system. If "result" is non-NULL, a pointer to a newly
1838 * allocated buffer containing the used configuration file is
1840 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1844 if (env
&& (fn
= getenv(env
))) {
1845 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1847 *result
= pa_xstrdup(fn
);
1852 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1861 if ((e
= getenv("PULSE_CONFIG_PATH"))) {
1862 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1863 f
= pa_fopen_cloexec(fn
, "r");
1864 } else if ((h
= pa_get_home_dir_malloc())) {
1865 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1866 f
= pa_fopen_cloexec(fn
, "r");
1869 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".config/pulse" PA_PATH_SEP
"%s", h
, local
);
1870 f
= pa_fopen_cloexec(fn
, "r");
1878 *result
= pa_xstrdup(fn
);
1884 if (errno
!= ENOENT
) {
1885 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1897 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1898 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1899 pa_win32_get_toplevel(NULL
),
1900 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1903 gfn
= pa_xstrdup(global
);
1905 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1920 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1923 if (env
&& (fn
= getenv(env
))) {
1924 if (access(fn
, R_OK
) == 0)
1925 return pa_xstrdup(fn
);
1927 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1936 if ((e
= getenv("PULSE_CONFIG_PATH")))
1937 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1938 else if ((h
= pa_get_home_dir_malloc())) {
1939 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1944 if (access(fn
, R_OK
) == 0) {
1945 char *r
= pa_xstrdup(fn
);
1950 if (errno
!= ENOENT
) {
1951 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1963 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1964 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1965 pa_win32_get_toplevel(NULL
),
1966 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1969 gfn
= pa_xstrdup(global
);
1971 if (access(gfn
, R_OK
) == 0)
1981 /* Format the specified data as a hexademical string */
1982 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1983 size_t i
= 0, j
= 0;
1984 const char hex
[] = "0123456789abcdef";
1988 pa_assert(slength
> 0);
1990 while (j
+2 < slength
&& i
< dlength
) {
1991 s
[j
++] = hex
[*d
>> 4];
1992 s
[j
++] = hex
[*d
& 0xF];
1998 s
[j
< slength
? j
: slength
] = 0;
2002 /* Convert a hexadecimal digit to a number or -1 if invalid */
2003 static int hexc(char c
) {
2004 if (c
>= '0' && c
<= '9')
2007 if (c
>= 'A' && c
<= 'F')
2008 return c
- 'A' + 10;
2010 if (c
>= 'a' && c
<= 'f')
2011 return c
- 'a' + 10;
2017 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
2018 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
2024 while (j
< dlength
&& *p
) {
2027 if ((b
= hexc(*(p
++))) < 0)
2030 d
[j
] = (uint8_t) (b
<< 4);
2035 if ((b
= hexc(*(p
++))) < 0)
2038 d
[j
] |= (uint8_t) b
;
2045 /* Returns nonzero when *s starts with *pfx */
2046 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
2054 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
2057 /* Returns nonzero when *s ends with *sfx */
2058 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
2067 return l1
>= l2
&& pa_streq(s
+ l1
- l2
, sfx
);
2070 pa_bool_t
pa_is_path_absolute(const char *fn
) {
2076 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
2080 char *pa_make_path_absolute(const char *p
) {
2086 if (pa_is_path_absolute(p
))
2087 return pa_xstrdup(p
);
2089 if (!(cwd
= pa_getcwd()))
2090 return pa_xstrdup(p
);
2092 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2097 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
2098 * if fn is non-null and starts with / return fn
2099 * otherwise append fn to the run time path and return it */
2100 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
2103 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2106 char *r
, *canonical_rtp
;
2108 if (pa_is_path_absolute(fn
)) {
2110 return pa_xstrdup(fn
);
2116 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2117 if ((canonical_rtp
= pa_realpath(rtp
))) {
2118 if (strlen(rtp
) >= strlen(canonical_rtp
))
2121 pa_xfree(canonical_rtp
);
2122 canonical_rtp
= rtp
;
2125 canonical_rtp
= rtp
;
2130 if (!(mid
= pa_machine_id())) {
2131 pa_xfree(canonical_rtp
);
2135 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", canonical_rtp
, mid
, fn
);
2138 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", canonical_rtp
, fn
);
2140 pa_xfree(canonical_rtp
);
2146 char *pa_runtime_path(const char *fn
) {
2147 return get_path(fn
, FALSE
, TRUE
);
2150 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2151 return get_path(fn
, appendmid
, FALSE
);
2154 /* Convert the string s to a signed integer in *ret_i */
2155 int pa_atoi(const char *s
, int32_t *ret_i
) {
2161 if (pa_atol(s
, &l
) < 0)
2164 if ((int32_t) l
!= l
) {
2169 *ret_i
= (int32_t) l
;
2174 /* Convert the string s to an unsigned integer in *ret_u */
2175 int pa_atou(const char *s
, uint32_t *ret_u
) {
2183 l
= strtoul(s
, &x
, 0);
2185 if (!x
|| *x
|| errno
) {
2191 if ((uint32_t) l
!= l
) {
2196 *ret_u
= (uint32_t) l
;
2201 /* Convert the string s to a signed long integer in *ret_l. */
2202 int pa_atol(const char *s
, long *ret_l
) {
2210 l
= strtol(s
, &x
, 0);
2212 if (!x
|| *x
|| errno
) {
2223 #ifdef HAVE_STRTOF_L
2224 static locale_t c_locale
= NULL
;
2226 static void c_locale_destroy(void) {
2227 freelocale(c_locale
);
2231 int pa_atod(const char *s
, double *ret_d
) {
2238 /* This should be locale independent */
2240 #ifdef HAVE_STRTOF_L
2244 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2245 atexit(c_locale_destroy
);
2251 f
= strtod_l(s
, &x
, c_locale
);
2259 if (!x
|| *x
|| errno
) {
2270 /* Same as snprintf, but guarantees NUL-termination on every platform */
2271 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2276 pa_assert(size
> 0);
2279 va_start(ap
, format
);
2280 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2286 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2287 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2291 pa_assert(size
> 0);
2294 ret
= vsnprintf(str
, size
, format
, ap
);
2301 if ((size_t) ret
> size
-1)
2304 return (size_t) ret
;
2307 /* Truncate the specified string, but guarantee that the string
2308 * returned still validates as UTF8 */
2309 char *pa_truncate_utf8(char *c
, size_t l
) {
2311 pa_assert(pa_utf8_valid(c
));
2318 while (l
> 0 && !pa_utf8_valid(c
))
2324 char *pa_getcwd(void) {
2328 char *p
= pa_xmalloc(l
);
2332 if (errno
!= ERANGE
)
2340 void *pa_will_need(const void *p
, size_t l
) {
2341 #ifdef RLIMIT_MEMLOCK
2352 a
= PA_PAGE_ALIGN_PTR(p
);
2353 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2355 #ifdef HAVE_POSIX_MADVISE
2356 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2357 pa_log_debug("posix_madvise() worked fine!");
2362 /* Most likely the memory was not mmap()ed from a file and thus
2363 * madvise() didn't work, so let's misuse mlock() do page this
2364 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2365 * inviting, the man page of mlock() tells us: "All pages that
2366 * contain a part of the specified address range are guaranteed to
2367 * be resident in RAM when the call returns successfully." */
2369 #ifdef RLIMIT_MEMLOCK
2370 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2372 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2373 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
));
2378 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2380 bs
= PA_PAGE_SIZE
*4;
2383 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2386 while (size
> 0 && bs
> 0) {
2391 if (mlock(a
, bs
) < 0) {
2392 bs
= PA_PAGE_ALIGN(bs
/ 2);
2396 pa_assert_se(munlock(a
, bs
) == 0);
2398 a
= (const uint8_t*) a
+ bs
;
2404 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2406 pa_log_debug("mlock() worked fine!");
2411 void pa_close_pipe(int fds
[2]) {
2415 pa_assert_se(pa_close(fds
[0]) == 0);
2418 pa_assert_se(pa_close(fds
[1]) == 0);
2420 fds
[0] = fds
[1] = -1;
2423 char *pa_readlink(const char *p
) {
2424 #ifdef HAVE_READLINK
2433 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2438 if ((size_t) n
< l
-1) {
2451 int pa_close_all(int except_fd
, ...) {
2456 va_start(ap
, except_fd
);
2459 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2464 p
= pa_xnew(int, n
+1);
2466 va_start(ap
, except_fd
);
2469 if (except_fd
>= 0) {
2473 while ((fd
= va_arg(ap
, int)) >= 0)
2480 r
= pa_close_allv(p
);
2486 int pa_close_allv(const int except_fds
[]) {
2495 if ((d
= opendir("/proc/self/fd"))) {
2499 while ((de
= readdir(d
))) {
2505 if (de
->d_name
[0] == '.')
2509 l
= strtol(de
->d_name
, &e
, 10);
2510 if (errno
!= 0 || !e
|| *e
) {
2518 if ((long) fd
!= l
) {
2531 for (i
= 0; except_fds
[i
] >= 0; i
++)
2532 if (except_fds
[i
] == fd
) {
2540 if (pa_close(fd
) < 0) {
2541 saved_errno
= errno
;
2543 errno
= saved_errno
;
2555 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2556 maxfd
= (int) rl
.rlim_max
;
2558 maxfd
= sysconf(_SC_OPEN_MAX
);
2560 for (fd
= 3; fd
< maxfd
; fd
++) {
2565 for (i
= 0; except_fds
[i
] >= 0; i
++)
2566 if (except_fds
[i
] == fd
) {
2574 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2577 #endif /* !OS_IS_WIN32 */
2582 int pa_unblock_sigs(int except
, ...) {
2587 va_start(ap
, except
);
2590 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2595 p
= pa_xnew(int, n
+1);
2597 va_start(ap
, except
);
2604 while ((sig
= va_arg(ap
, int)) >= 0)
2611 r
= pa_unblock_sigsv(p
);
2617 int pa_unblock_sigsv(const int except
[]) {
2622 if (sigemptyset(&ss
) < 0)
2625 for (i
= 0; except
[i
] > 0; i
++)
2626 if (sigaddset(&ss
, except
[i
]) < 0)
2629 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2635 int pa_reset_sigs(int except
, ...) {
2640 va_start(ap
, except
);
2643 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2648 p
= pa_xnew(int, n
+1);
2650 va_start(ap
, except
);
2657 while ((sig
= va_arg(ap
, int)) >= 0)
2664 r
= pa_reset_sigsv(p
);
2670 int pa_reset_sigsv(const int except
[]) {
2674 for (sig
= 1; sig
< NSIG
; sig
++) {
2675 pa_bool_t reset
= TRUE
;
2686 for (i
= 0; except
[i
] > 0; i
++) {
2687 if (sig
== except
[i
]) {
2696 struct sigaction sa
;
2698 memset(&sa
, 0, sizeof(sa
));
2699 sa
.sa_handler
= SIG_DFL
;
2701 /* On Linux the first two RT signals are reserved by
2702 * glibc, and sigaction() will return EINVAL for them. */
2703 if ((sigaction(sig
, &sa
, NULL
) < 0))
2704 if (errno
!= EINVAL
)
2713 void pa_set_env(const char *key
, const char *value
) {
2717 /* This is not thread-safe */
2720 SetEnvironmentVariable(key
, value
);
2722 setenv(key
, value
, 1);
2726 void pa_set_env_and_record(const char *key
, const char *value
) {
2730 /* This is not thread-safe */
2732 pa_set_env(key
, value
);
2733 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2736 void pa_unset_env_recorded(void) {
2738 /* This is not thread-safe */
2743 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2749 SetEnvironmentVariable(s
, NULL
);
2757 pa_bool_t
pa_in_system_mode(void) {
2760 if (!(e
= getenv("PULSE_SYSTEM")))
2766 /* Checks a whitespace-separated list of words in haystack for needle */
2767 pa_bool_t
pa_str_in_list_spaces(const char *haystack
, const char *needle
) {
2769 const char *state
= NULL
;
2771 if (!haystack
|| !needle
)
2774 while ((s
= pa_split_spaces(haystack
, &state
))) {
2775 if (pa_streq(needle
, s
)) {
2786 char *pa_get_user_name_malloc(void) {
2790 #ifdef _SC_LOGIN_NAME_MAX
2791 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2797 u
= pa_xnew(char, k
+1);
2799 if (!(pa_get_user_name(u
, k
))) {
2807 char *pa_get_host_name_malloc(void) {
2816 if (!pa_get_host_name(c
, l
)) {
2818 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2821 } else if (strlen(c
) < l
-1) {
2829 u
= pa_utf8_filter(c
);
2834 /* Hmm, the hostname is as long the space we offered the
2835 * function, we cannot know if it fully fit in, so let's play
2836 * safe and retry. */
2845 char *pa_machine_id(void) {
2849 /* The returned value is supposed be some kind of ascii identifier
2850 * that is unique and stable across reboots. */
2852 /* First we try the /etc/machine-id, which is the best option we
2853 * have, since it fits perfectly our needs and is not as volatile
2854 * as the hostname which might be set from dhcp. */
2856 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r")) ||
2857 (f
= pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK
, "r"))) {
2858 char ln
[34] = "", *r
;
2860 r
= fgets(ln
, sizeof(ln
)-1, f
);
2866 return pa_utf8_filter(ln
);
2869 if ((h
= pa_get_host_name_malloc()))
2873 /* If no hostname was set we use the POSIX hostid. It's usually
2874 * the IPv4 address. Might not be that stable. */
2875 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2881 char *pa_session_id(void) {
2884 e
= getenv("XDG_SESSION_ID");
2888 return pa_utf8_filter(e
);
2891 char *pa_uname_string(void) {
2895 pa_assert_se(uname(&u
) >= 0);
2897 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2903 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2904 pa_assert_se(GetVersionEx(&i
));
2906 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2910 #ifdef HAVE_VALGRIND_MEMCHECK_H
2911 pa_bool_t
pa_in_valgrind(void) {
2914 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2915 * here instead of really checking whether we run in valgrind or
2919 b
= getenv("VALGRIND") ? 2 : 1;
2925 unsigned pa_gcd(unsigned a
, unsigned b
) {
2936 void pa_reduce(unsigned *num
, unsigned *den
) {
2938 unsigned gcd
= pa_gcd(*num
, *den
);
2946 pa_assert(pa_gcd(*num
, *den
) == 1);
2949 unsigned pa_ncpus(void) {
2952 #ifdef _SC_NPROCESSORS_CONF
2953 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2958 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2961 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2970 sb
= pa_strbuf_new();
2975 if (!(p
= strstr(s
, a
)))
2978 pa_strbuf_putsn(sb
, s
, p
-s
);
2979 pa_strbuf_puts(sb
, b
);
2983 pa_strbuf_puts(sb
, s
);
2985 return pa_strbuf_tostring_free(sb
);
2988 char *pa_escape(const char *p
, const char *chars
) {
2991 pa_strbuf
*buf
= pa_strbuf_new();
2993 for (s
= p
; *s
; ++s
) {
2995 pa_strbuf_putc(buf
, '\\');
2997 for (c
= chars
; *c
; ++c
) {
2999 pa_strbuf_putc(buf
, '\\');
3004 pa_strbuf_putc(buf
, *s
);
3007 return pa_strbuf_tostring_free(buf
);
3010 char *pa_unescape(char *p
) {
3012 pa_bool_t escaped
= FALSE
;
3014 for (s
= p
, d
= p
; *s
; s
++) {
3015 if (!escaped
&& *s
== '\\') {
3029 char *pa_realpath(const char *path
) {
3033 /* We want only absolute paths */
3034 if (path
[0] != '/') {
3039 #if defined(__GLIBC__)
3043 if (!(r
= realpath(path
, NULL
)))
3046 /* We copy this here in case our pa_xmalloc() is not
3047 * implemented on top of libc malloc() */
3051 #elif defined(PATH_MAX)
3054 path_buf
= pa_xmalloc(PATH_MAX
);
3056 #if defined(OS_IS_WIN32)
3057 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
3062 if (!(t
= realpath(path
, path_buf
))) {
3069 #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."
3075 void pa_disable_sigpipe(void) {
3078 struct sigaction sa
;
3082 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
3083 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3087 sa
.sa_handler
= SIG_IGN
;
3089 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
3090 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3096 void pa_xfreev(void**a
) {
3102 for (p
= a
; *p
; p
++)
3108 char **pa_split_spaces_strv(const char *s
) {
3110 unsigned i
= 0, n
= 8;
3111 const char *state
= NULL
;
3113 t
= pa_xnew(char*, n
);
3114 while ((e
= pa_split_spaces(s
, &state
))) {
3119 t
= pa_xrenew(char*, t
, n
);
3132 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
3135 if (pa_is_path_absolute(path
))
3136 return pa_xstrdup(path
);
3138 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
3141 size_t pa_pipe_buf(int fd
) {
3146 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3157 void pa_reset_personality(void) {
3160 if (personality(PER_LINUX
) < 0)
3161 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3166 #if defined(__linux__) && !defined(__OPTIMIZE__)
3168 pa_bool_t
pa_run_from_build_tree(void) {
3170 pa_bool_t b
= FALSE
;
3172 if ((rp
= pa_readlink("/proc/self/exe"))) {
3173 b
= pa_startswith(rp
, PA_BUILDDIR
);
3182 const char *pa_get_temp_dir(void) {
3185 if ((t
= getenv("TMPDIR")) &&
3186 pa_is_path_absolute(t
))
3189 if ((t
= getenv("TMP")) &&
3190 pa_is_path_absolute(t
))
3193 if ((t
= getenv("TEMP")) &&
3194 pa_is_path_absolute(t
))
3197 if ((t
= getenv("TEMPDIR")) &&
3198 pa_is_path_absolute(t
))
3204 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3212 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3215 if (errno
!= EINVAL
)
3219 if ((fd
= open(fn
, flags
, mode
)) < 0)
3223 /* Some implementations might simply ignore O_CLOEXEC if it is not
3224 * understood, make sure FD_CLOEXEC is enabled anyway */
3226 pa_make_fd_cloexec(fd
);
3230 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3234 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3237 if (errno
!= EINVAL
)
3241 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3245 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3246 * not understood, make sure FD_CLOEXEC is enabled anyway */
3248 pa_make_fd_cloexec(fd
);
3252 int pa_pipe_cloexec(int pipefd
[2]) {
3256 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3259 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3264 if ((r
= pipe(pipefd
)) < 0)
3268 pa_make_fd_cloexec(pipefd
[0]);
3269 pa_make_fd_cloexec(pipefd
[1]);
3274 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3278 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3281 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3286 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3290 pa_make_fd_cloexec(fd
);
3294 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3298 m
= pa_sprintf_malloc("%se", mode
);
3301 if ((f
= fopen(path
, m
))) {
3308 if (errno
!= EINVAL
)
3311 if (!(f
= fopen(path
, mode
)))
3315 pa_make_fd_cloexec(fileno(f
));
3319 void pa_nullify_stdfds(void) {
3322 pa_close(STDIN_FILENO
);
3323 pa_close(STDOUT_FILENO
);
3324 pa_close(STDERR_FILENO
);
3326 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3327 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3328 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3335 char *pa_read_line_from_file(const char *fn
) {
3337 char ln
[256] = "", *r
;
3339 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3342 r
= fgets(ln
, sizeof(ln
)-1, f
);
3351 return pa_xstrdup(ln
);
3354 pa_bool_t
pa_running_in_vm(void) {
3356 #if defined(__i386__) || defined(__x86_64__)
3358 /* Both CPUID and DMI are x86 specific interfaces... */
3360 uint32_t eax
= 0x40000000;
3367 const char *const dmi_vendors
[] = {
3368 "/sys/class/dmi/id/sys_vendor",
3369 "/sys/class/dmi/id/board_vendor",
3370 "/sys/class/dmi/id/bios_vendor"
3375 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3378 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3380 if (pa_startswith(s
, "QEMU") ||
3381 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3382 pa_startswith(s
, "VMware") ||
3383 pa_startswith(s
, "VMW") ||
3384 pa_startswith(s
, "Microsoft Corporation") ||
3385 pa_startswith(s
, "innotek GmbH") ||
3386 pa_startswith(s
, "Xen")) {
3398 /* http://lwn.net/Articles/301888/ */
3401 __asm__
__volatile__ (
3402 /* ebx/rbx is being used for PIC! */
3403 " push %%"PA_REG_b
" \n\t"
3405 " mov %%ebx, %1 \n\t"
3406 " pop %%"PA_REG_b
" \n\t"
3408 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3412 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3413 pa_streq(sig
.text
, "KVMKVMKVM") ||
3414 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3415 pa_streq(sig
.text
, "VMwareVMware") ||
3416 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3417 pa_streq(sig
.text
, "Microsoft Hv"))