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>
120 #if defined(__linux__) && !defined(__ANDROID__)
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
;
152 static fd_set nonblocking_fds
;
157 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
158 char *pa_win32_get_toplevel(HANDLE handle
) {
159 static char *toplevel
= NULL
;
162 char library_path
[MAX_PATH
];
165 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
168 toplevel
= pa_xstrdup(library_path
);
170 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
174 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
175 if (p
&& pa_streq(p
+ 1, "bin"))
184 static void set_nonblock(int fd
, bool nonblock
) {
190 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
195 nv
= v
& ~O_NONBLOCK
;
198 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
200 #elif defined(OS_IS_WIN32)
208 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
209 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
210 pa_log_warn("Only sockets can be made non-blocking!");
214 /* There is no method to query status, so we remember all fds */
216 FD_SET(fd
, &nonblocking_fds
);
218 FD_CLR(fd
, &nonblocking_fds
);
220 pa_log_warn("Non-blocking I/O not supported.!");
225 /** Make a file descriptor nonblock. Doesn't do any error checking */
226 void pa_make_fd_nonblock(int fd
) {
227 set_nonblock(fd
, true);
230 /** Make a file descriptor blocking. Doesn't do any error checking */
231 void pa_make_fd_block(int fd
) {
232 set_nonblock(fd
, false);
235 /** Query if a file descriptor is non-blocking */
236 bool pa_is_fd_nonblock(int fd
) {
242 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
244 return !!(v
& O_NONBLOCK
);
246 #elif defined(OS_IS_WIN32)
247 return !!FD_ISSET(fd
, &nonblocking_fds
);
254 /* Set the FD_CLOEXEC flag for a fd */
255 void pa_make_fd_cloexec(int fd
) {
261 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
263 if (!(v
& FD_CLOEXEC
))
264 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
269 /** Creates a directory securely. Will create parent directories recursively if
270 * required. This will not update permissions on parent directories if they
271 * already exist, however. */
272 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
, bool update_perms
) {
285 u
= umask((~m
) & 0777);
291 if (r
< 0 && errno
== ENOENT
&& retry
) {
292 /* If a parent directory in the path doesn't exist, try to create that
293 * first, then try again. */
294 pa_make_secure_parent_dir(dir
, m
, uid
, gid
, false);
299 if (r
< 0 && errno
!= EEXIST
)
302 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
318 if (fstat(fd
, &st
) < 0) {
319 pa_assert_se(pa_close(fd
) >= 0);
323 if (!S_ISDIR(st
.st_mode
)) {
324 pa_assert_se(pa_close(fd
) >= 0);
330 pa_assert_se(pa_close(fd
) >= 0);
335 if (uid
== (uid_t
) -1)
337 if (gid
== (gid_t
) -1)
339 if (((st
.st_uid
!= uid
) || (st
.st_gid
!= gid
)) && fchown(fd
, uid
, gid
) < 0) {
340 pa_assert_se(pa_close(fd
) >= 0);
346 (void) fchmod(fd
, m
);
349 pa_assert_se(pa_close(fd
) >= 0);
354 if (lstat(dir
, &st
) < 0)
356 if (stat(dir
, &st
) < 0)
361 if (!S_ISDIR(st
.st_mode
) ||
362 (st
.st_uid
!= uid
) ||
363 (st
.st_gid
!= gid
) ||
364 ((st
.st_mode
& 0777) != m
)) {
369 pa_log_warn("Secure directory creation not supported on Win32.");
382 /* Return a newly allocated sting containing the parent directory of the specified file */
383 char *pa_parent_dir(const char *fn
) {
384 char *slash
, *dir
= pa_xstrdup(fn
);
386 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
396 /* Creates a the parent directory of the specified path securely */
397 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
, bool update_perms
) {
401 if (!(dir
= pa_parent_dir(fn
)))
404 if (pa_make_secure_dir(dir
, m
, uid
, gid
, update_perms
) < 0)
414 /** Platform independent read function. Necessary since not all
415 * systems treat all file descriptors equal. If type is
416 * non-NULL it is used to cache the type of the fd. This is
417 * useful for making sure that only a single syscall is executed per
418 * function call. The variable pointed to should be initialized to 0
420 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
424 if (!type
|| *type
== 0) {
427 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
430 if (WSAGetLastError() != WSAENOTSOCK
) {
431 errno
= WSAGetLastError();
444 if ((r
= read(fd
, buf
, count
)) < 0)
452 /** Similar to pa_read(), but handles writes */
453 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
455 if (!type
|| *type
== 0) {
459 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
471 if (WSAGetLastError() != WSAENOTSOCK
) {
472 errno
= WSAGetLastError();
476 if (errno
!= ENOTSOCK
)
487 if ((r
= write(fd
, buf
, count
)) < 0)
495 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
496 * unless EOF is reached or an error occurred */
497 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
513 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
520 data
= (uint8_t*) data
+ r
;
527 /** Similar to pa_loop_read(), but wraps write() */
528 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
544 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
551 data
= (const uint8_t*) data
+ r
;
558 /** Platform independent close function. Necessary since not all
559 * systems treat all file descriptors equal. */
560 int pa_close(int fd
) {
565 FD_CLR(fd
, &nonblocking_fds
);
567 if ((ret
= closesocket(fd
)) == 0)
570 if (WSAGetLastError() != WSAENOTSOCK
) {
571 errno
= WSAGetLastError();
579 if ((r
= close(fd
)) < 0)
587 /* Print a warning messages in case that the given signal is not
588 * blocked or trapped */
589 void pa_check_signal_is_blocked(int sig
) {
590 #ifdef HAVE_SIGACTION
594 /* If POSIX threads are supported use thread-aware
595 * pthread_sigmask() function, to check if the signal is
596 * blocked. Otherwise fall back to sigprocmask() */
599 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
601 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
602 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
609 if (sigismember(&set
, sig
))
612 /* Check whether the signal is trapped */
614 if (sigaction(sig
, NULL
, &sa
) < 0) {
615 pa_log("sigaction(): %s", pa_cstrerror(errno
));
619 if (sa
.sa_handler
!= SIG_DFL
)
622 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
623 #else /* HAVE_SIGACTION */
624 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
628 /* The following function is based on an example from the GNU libc
629 * documentation. This function is similar to GNU's asprintf(). */
630 char *pa_sprintf_malloc(const char *format
, ...) {
640 c
= pa_xrealloc(c
, size
);
642 va_start(ap
, format
);
643 r
= vsnprintf(c
, size
, format
, ap
);
648 if (r
> -1 && (size_t) r
< size
)
651 if (r
> -1) /* glibc 2.1 */
658 /* Same as the previous function, but use a va_list instead of an
660 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
670 c
= pa_xrealloc(c
, size
);
673 r
= vsnprintf(c
, size
, format
, aq
);
678 if (r
> -1 && (size_t) r
< size
)
681 if (r
> -1) /* glibc 2.1 */
688 /* Similar to OpenBSD's strlcpy() function */
689 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
707 #ifdef _POSIX_PRIORITY_SCHEDULING
708 static int set_scheduler(int rtprio
) {
710 struct sched_param sp
;
720 dbus_error_init(&error
);
724 sp
.sched_priority
= rtprio
;
726 #ifdef SCHED_RESET_ON_FORK
727 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
728 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
733 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
734 pa_log_debug("SCHED_RR worked.");
737 #endif /* HAVE_SCHED_H */
740 /* Try to talk to RealtimeKit */
742 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
743 pa_log("Failed to connect to system bus: %s\n", error
.message
);
744 dbus_error_free(&error
);
749 /* We need to disable exit on disconnect because otherwise
750 * dbus_shutdown will kill us. See
751 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
752 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
754 rttime
= rtkit_get_rttime_usec_max(bus
);
757 r
= getrlimit(RLIMIT_RTTIME
, &rl
);
759 if (r
>= 0 && (long long) rl
.rlim_max
> rttime
) {
760 pa_log_info("Clamping rlimit-rttime to %lld for RealtimeKit\n", rttime
);
761 rl
.rlim_cur
= rl
.rlim_max
= rttime
;
762 r
= setrlimit(RLIMIT_RTTIME
, &rl
);
765 pa_log("setrlimit() failed: %s", pa_cstrerror(errno
));
768 r
= rtkit_make_realtime(bus
, 0, rtprio
);
769 dbus_connection_close(bus
);
770 dbus_connection_unref(bus
);
773 pa_log_debug("RealtimeKit worked.");
779 dbus_connection_close(bus
);
780 dbus_connection_unref(bus
);
792 /* Make the current thread a realtime thread, and acquire the highest
793 * rtprio we can get that is less or equal the specified parameter. If
794 * the thread is already realtime, don't do anything. */
795 int pa_make_realtime(int rtprio
) {
797 #if defined(OS_IS_DARWIN)
798 struct thread_time_constraint_policy ttcpolicy
;
800 size_t size
= sizeof(freq
);
803 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
805 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
809 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
811 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
812 ttcpolicy
.period
= freq
/ 160;
813 ttcpolicy
.computation
= freq
/ 3300;
814 ttcpolicy
.constraint
= freq
/ 2200;
815 ttcpolicy
.preemptible
= 1;
817 ret
= thread_policy_set(mach_thread_self(),
818 THREAD_TIME_CONSTRAINT_POLICY
,
819 (thread_policy_t
) &ttcpolicy
,
820 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
822 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
826 pa_log_info("Successfully acquired real-time thread priority.");
829 #elif defined(_POSIX_PRIORITY_SCHEDULING)
832 if (set_scheduler(rtprio
) >= 0) {
833 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
837 for (p
= rtprio
-1; p
>= 1; p
--)
838 if (set_scheduler(p
) >= 0) {
839 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
842 #elif defined(OS_IS_WIN32)
843 /* Windows only allows realtime scheduling to be set on a per process basis.
844 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
845 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
846 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
850 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
855 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
859 #ifdef HAVE_SYS_RESOURCE_H
860 static int set_nice(int nice_level
) {
866 dbus_error_init(&error
);
869 #ifdef HAVE_SYS_RESOURCE_H
870 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
871 pa_log_debug("setpriority() worked.");
877 /* Try to talk to RealtimeKit */
879 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
880 pa_log("Failed to connect to system bus: %s\n", error
.message
);
881 dbus_error_free(&error
);
886 /* We need to disable exit on disconnect because otherwise
887 * dbus_shutdown will kill us. See
888 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
889 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
891 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
892 dbus_connection_unref(bus
);
895 pa_log_debug("RealtimeKit worked.");
906 /* Raise the priority of the current process as much as possible that
907 * is <= the specified nice level..*/
908 int pa_raise_priority(int nice_level
) {
910 #ifdef HAVE_SYS_RESOURCE_H
913 if (set_nice(nice_level
) >= 0) {
914 pa_log_info("Successfully gained nice level %i.", nice_level
);
918 for (n
= nice_level
+1; n
< 0; n
++)
919 if (set_nice(n
) >= 0) {
920 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
924 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
929 if (nice_level
< 0) {
930 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
931 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
936 pa_log_info("Successfully gained high priority class.");
943 /* Reset the priority to normal, inverting the changes made by
944 * pa_raise_priority() and pa_make_realtime()*/
945 void pa_reset_priority(void) {
946 #ifdef HAVE_SYS_RESOURCE_H
947 struct sched_param sp
;
949 setpriority(PRIO_PROCESS
, 0, 0);
952 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
956 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
960 int pa_match(const char *expr
, const char *v
) {
961 #if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
966 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
971 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
973 else if (k
== REG_NOMATCH
)
990 /* Try to parse a boolean string value.*/
991 int pa_parse_boolean(const char *v
) {
994 /* First we check language independent */
995 if (pa_streq(v
, "1") || !strcasecmp(v
, "y") || !strcasecmp(v
, "t")
996 || !strcasecmp(v
, "yes") || !strcasecmp(v
, "true") || !strcasecmp(v
, "on"))
998 else if (pa_streq(v
, "0") || !strcasecmp(v
, "n") || !strcasecmp(v
, "f")
999 || !strcasecmp(v
, "no") || !strcasecmp(v
, "false") || !strcasecmp(v
, "off"))
1002 #ifdef HAVE_LANGINFO_H
1005 /* And then we check language dependent */
1006 if ((expr
= nl_langinfo(YESEXPR
)))
1008 if (pa_match(expr
, v
) > 0)
1011 if ((expr
= nl_langinfo(NOEXPR
)))
1013 if (pa_match(expr
, v
) > 0)
1022 /* Try to parse a volume string to pa_volume_t. The allowed formats are:
1023 * db, % and unsigned integer */
1024 int pa_parse_volume(const char *v
, pa_volume_t
*volume
) {
1038 memcpy(str
, v
, len
+ 1);
1040 if (str
[len
- 1] == '%') {
1041 str
[len
- 1] = '\0';
1042 if (pa_atou(str
, &i
) == 0) {
1043 *volume
= PA_CLAMP_VOLUME((uint64_t) PA_VOLUME_NORM
* i
/ 100);
1046 } else if (len
> 2 && (str
[len
- 1] == 'b' || str
[len
- 1] == 'B') &&
1047 (str
[len
- 2] == 'd' || str
[len
- 2] == 'D')) {
1048 str
[len
- 2] = '\0';
1049 if (pa_atod(str
, &d
) == 0) {
1050 *volume
= pa_sw_volume_from_dB(d
);
1054 if (pa_atou(v
, &i
) == 0) {
1055 *volume
= PA_CLAMP_VOLUME(i
);
1064 /* Split the specified string wherever one of the strings in delimiter
1065 * occurs. Each time it is called returns a newly allocated string
1066 * with pa_xmalloc(). The variable state points to, should be
1067 * initialized to NULL before the first call. */
1068 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
1069 const char *current
= *state
? *state
: c
;
1075 l
= strcspn(current
, delimiter
);
1081 return pa_xstrndup(current
, l
);
1084 /* Split the specified string wherever one of the strings in delimiter
1085 * occurs. Each time it is called returns a pointer to the substring within the
1086 * string and the length in 'n'. Note that the resultant string cannot be used
1087 * as-is without the length parameter, since it is merely pointing to a point
1088 * within the original string. The variable state points to, should be
1089 * initialized to NULL before the first call. */
1090 const char *pa_split_in_place(const char *c
, const char *delimiter
, int *n
, const char**state
) {
1091 const char *current
= *state
? *state
: c
;
1097 l
= strcspn(current
, delimiter
);
1107 /* Split a string into words. Otherwise similar to pa_split(). */
1108 char *pa_split_spaces(const char *c
, const char **state
) {
1109 const char *current
= *state
? *state
: c
;
1112 if (!*current
|| *c
== 0)
1115 current
+= strspn(current
, WHITESPACE
);
1116 l
= strcspn(current
, WHITESPACE
);
1120 return pa_xstrndup(current
, l
);
1123 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
1125 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
1126 const char *pa_sig2str(int sig
) {
1139 char buf
[SIG2STR_MAX
];
1141 if (sig2str(sig
, buf
) == 0) {
1142 pa_xfree(PA_STATIC_TLS_GET(signame
));
1143 t
= pa_sprintf_malloc("SIG%s", buf
);
1144 PA_STATIC_TLS_SET(signame
, t
);
1152 case SIGHUP
: return "SIGHUP";
1154 case SIGINT
: return "SIGINT";
1156 case SIGQUIT
: return "SIGQUIT";
1158 case SIGILL
: return "SIGULL";
1160 case SIGTRAP
: return "SIGTRAP";
1162 case SIGABRT
: return "SIGABRT";
1164 case SIGBUS
: return "SIGBUS";
1166 case SIGFPE
: return "SIGFPE";
1168 case SIGKILL
: return "SIGKILL";
1171 case SIGUSR1
: return "SIGUSR1";
1173 case SIGSEGV
: return "SIGSEGV";
1175 case SIGUSR2
: return "SIGUSR2";
1178 case SIGPIPE
: return "SIGPIPE";
1181 case SIGALRM
: return "SIGALRM";
1183 case SIGTERM
: return "SIGTERM";
1185 case SIGSTKFLT
: return "SIGSTKFLT";
1188 case SIGCHLD
: return "SIGCHLD";
1191 case SIGCONT
: return "SIGCONT";
1194 case SIGSTOP
: return "SIGSTOP";
1197 case SIGTSTP
: return "SIGTSTP";
1200 case SIGTTIN
: return "SIGTTIN";
1203 case SIGTTOU
: return "SIGTTOU";
1206 case SIGURG
: return "SIGURG";
1209 case SIGXCPU
: return "SIGXCPU";
1212 case SIGXFSZ
: return "SIGXFSZ";
1215 case SIGVTALRM
: return "SIGVTALRM";
1218 case SIGPROF
: return "SIGPROF";
1221 case SIGWINCH
: return "SIGWINCH";
1224 case SIGIO
: return "SIGIO";
1227 case SIGPWR
: return "SIGPWR";
1230 case SIGSYS
: return "SIGSYS";
1235 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1236 pa_xfree(PA_STATIC_TLS_GET(signame
));
1237 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1238 PA_STATIC_TLS_SET(signame
, t
);
1247 pa_xfree(PA_STATIC_TLS_GET(signame
));
1248 t
= pa_sprintf_malloc("SIG%i", sig
);
1249 PA_STATIC_TLS_SET(signame
, t
);
1255 /* Check whether the specified GID and the group name match */
1256 static int is_group(gid_t gid
, const char *name
) {
1257 struct group
*group
= NULL
;
1261 if (!(group
= pa_getgrgid_malloc(gid
))) {
1265 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1270 r
= pa_streq(name
, group
->gr_name
);
1273 pa_getgrgid_free(group
);
1278 /* Check the current user is member of the specified group */
1279 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1280 GETGROUPS_T
*gids
, tgid
;
1281 long n
= sysconf(_SC_NGROUPS_MAX
);
1286 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1288 if ((n
= getgroups((int) n
, gids
)) < 0) {
1289 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1293 for (i
= 0; i
< n
; i
++) {
1295 if ((k
= is_group(gids
[i
], name
)) < 0)
1304 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1320 /* Check whether the specific user id is a member of the specified group */
1321 int pa_uid_in_group(uid_t uid
, const char *name
) {
1322 struct group
*group
= NULL
;
1327 if (!(group
= pa_getgrnam_malloc(name
))) {
1334 for (i
= group
->gr_mem
; *i
; i
++) {
1335 struct passwd
*pw
= NULL
;
1338 if (!(pw
= pa_getpwnam_malloc(*i
)))
1341 if (pw
->pw_uid
== uid
)
1344 pa_getpwnam_free(pw
);
1351 pa_getgrnam_free(group
);
1356 /* Get the GID of a given group, return (gid_t) -1 on failure. */
1357 gid_t
pa_get_gid_of_group(const char *name
) {
1358 gid_t ret
= (gid_t
) -1;
1359 struct group
*gr
= NULL
;
1362 if (!(gr
= pa_getgrnam_malloc(name
))) {
1371 pa_getgrnam_free(gr
);
1375 int pa_check_in_group(gid_t g
) {
1376 gid_t gids
[NGROUPS_MAX
];
1379 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1389 #else /* HAVE_GRP_H */
1391 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1397 int pa_uid_in_group(uid_t uid
, const char *name
) {
1402 gid_t
pa_get_gid_of_group(const char *name
) {
1407 int pa_check_in_group(gid_t g
) {
1414 /* Lock or unlock a file entirely.
1415 (advisory on UNIX, mandatory on Windows) */
1416 int pa_lock_fd(int fd
, int b
) {
1418 struct flock f_lock
;
1420 /* Try a R/W lock first */
1422 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1423 f_lock
.l_whence
= SEEK_SET
;
1427 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1430 /* Perhaps the file descriptor was opened for read only, than try again with a read lock. */
1431 if (b
&& errno
== EBADF
) {
1432 f_lock
.l_type
= F_RDLCK
;
1433 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1437 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1441 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1443 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1445 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1448 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1450 /* FIXME: Needs to set errno! */
1456 /* Remove trailing newlines from a string */
1457 char* pa_strip_nl(char *s
) {
1460 s
[strcspn(s
, NEWLINE
)] = 0;
1464 char *pa_strip(char *s
) {
1467 /* Drops trailing whitespace. Modifies the string in
1468 * place. Returns pointer to first non-space character */
1470 s
+= strspn(s
, WHITESPACE
);
1472 for (e
= s
; *e
; e
++)
1473 if (!strchr(WHITESPACE
, *e
))
1484 /* Create a temporary lock file and lock it. */
1485 int pa_lock_lockfile(const char *fn
) {
1492 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1496 , S_IRUSR
|S_IWUSR
)) < 0) {
1497 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1501 if (pa_lock_fd(fd
, 1) < 0) {
1502 pa_log_warn("Failed to lock file '%s'.", fn
);
1506 if (fstat(fd
, &st
) < 0) {
1507 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1511 /* Check whether the file has been removed meanwhile. When yes,
1512 * restart this loop, otherwise, we're done */
1513 if (st
.st_nlink
>= 1)
1516 if (pa_lock_fd(fd
, 0) < 0) {
1517 pa_log_warn("Failed to unlock file '%s'.", fn
);
1521 if (pa_close(fd
) < 0) {
1522 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1533 int saved_errno
= errno
;
1535 errno
= saved_errno
;
1541 /* Unlock a temporary lock file */
1542 int pa_unlock_lockfile(const char *fn
, int fd
) {
1547 if (unlink(fn
) < 0) {
1548 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1553 if (pa_lock_fd(fd
, 0) < 0) {
1554 pa_log_warn("Failed to unlock file '%s'.", fn
);
1558 if (pa_close(fd
) < 0) {
1559 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1566 static char *get_config_home(char *home
) {
1569 t
= getenv("XDG_CONFIG_HOME");
1571 return pa_xstrdup(t
);
1573 return pa_sprintf_malloc("%s" PA_PATH_SEP
".config", home
);
1576 static int check_ours(const char *p
) {
1581 if (stat(p
, &st
) < 0)
1585 if (st
.st_uid
!= getuid())
1592 static char *get_pulse_home(void) {
1593 char *h
, *ret
, *config_home
;
1596 h
= pa_get_home_dir_malloc();
1598 pa_log_error("Failed to get home directory.");
1603 if (t
< 0 && t
!= -ENOENT
) {
1604 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t
));
1609 /* If the old directory exists, use it. */
1610 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1611 if (access(ret
, F_OK
) >= 0) {
1617 /* Otherwise go for the XDG compliant directory. */
1618 config_home
= get_config_home(h
);
1620 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", config_home
);
1626 char *pa_get_state_dir(void) {
1629 /* The state directory shall contain dynamic data that should be
1630 * kept across reboots, and is private to this user */
1632 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1633 if (!(d
= get_pulse_home()))
1636 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1637 * dir then this will break. */
1639 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1640 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1648 char *pa_get_home_dir_malloc(void) {
1650 size_t allocated
= 128;
1653 homedir
= pa_xmalloc(allocated
);
1655 if (!pa_get_home_dir(homedir
, allocated
)) {
1660 if (strlen(homedir
) < allocated
- 1)
1670 char *pa_get_binary_name_malloc(void) {
1672 size_t allocated
= 128;
1675 t
= pa_xmalloc(allocated
);
1677 if (!pa_get_binary_name(t
, allocated
)) {
1682 if (strlen(t
) < allocated
- 1)
1692 static char* make_random_dir(mode_t m
) {
1693 static const char table
[] =
1694 "abcdefghijklmnopqrstuvwxyz"
1695 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1701 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1702 pathlen
= strlen(fn
);
1710 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1711 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1713 u
= umask((~m
) & 0777);
1720 saved_errno
= errno
;
1722 errno
= saved_errno
;
1727 if (errno
!= EEXIST
) {
1728 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1735 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1738 if (!(p
= make_random_dir(m
)))
1742 if (symlink(p
, k
) < 0) {
1743 int saved_errno
= errno
;
1745 if (errno
!= EEXIST
)
1746 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1751 errno
= saved_errno
;
1763 char *pa_get_runtime_dir(void) {
1764 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1767 /* The runtime directory shall contain dynamic data that needs NOT
1768 * to be kept across reboots and is usually private to the user,
1769 * except in system mode, where it might be accessible by other
1770 * users, too. Since we need POSIX locking and UNIX sockets in
1771 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1772 * set create a directory in $HOME and link it to a random subdir
1773 * in /tmp, if it was not explicitly configured. */
1775 m
= pa_in_system_mode() ? 0755U : 0700U;
1777 /* Use the explicitly configured value if it is set */
1778 d
= getenv("PULSE_RUNTIME_PATH");
1781 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1782 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1786 return pa_xstrdup(d
);
1789 /* Use the XDG standard for the runtime directory. */
1790 d
= getenv("XDG_RUNTIME_DIR");
1792 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", d
);
1794 if (pa_make_secure_dir(k
, m
, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1795 pa_log_error("Failed to create secure directory (%s): %s", k
, pa_cstrerror(errno
));
1802 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1803 d
= get_pulse_home();
1807 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1808 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1813 mid
= pa_machine_id();
1819 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1824 /* OK, first let's check if the "runtime" symlink already exists */
1829 if (errno
!= ENOENT
) {
1830 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1835 /* Hmm, so the runtime directory didn't exist yet, so let's
1836 * create one in /tmp and symlink that to it */
1838 if (make_random_dir_and_link(0700, k
) < 0) {
1840 /* Mhmm, maybe another process was quicker than us,
1841 * let's check if that was valid */
1842 if (errno
== EEXIST
)
1848 /* No symlink possible, so let's just create the runtime directly
1849 * Do not check again if it exists since it cannot be a symlink */
1850 if (mkdir(k
) < 0 && errno
!= EEXIST
)
1857 /* Make sure that this actually makes sense */
1858 if (!pa_is_path_absolute(p
)) {
1859 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1864 /* Hmm, so this symlink is still around, make sure nobody fools us */
1868 if (lstat(p
, &st
) < 0) {
1870 if (errno
!= ENOENT
) {
1871 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1877 if (S_ISDIR(st
.st_mode
) &&
1878 (st
.st_uid
== getuid()) &&
1879 ((st
.st_mode
& 0777) == 0700)) {
1885 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1893 /* Hmm, so the link points to some nonexisting or invalid
1894 * dir. Let's replace it by a new link. We first create a
1895 * temporary link and then rename that to allow concurrent
1896 * execution of this function. */
1898 t
= pa_sprintf_malloc("%s.tmp", k
);
1900 if (make_random_dir_and_link(0700, t
) < 0) {
1902 if (errno
!= EEXIST
) {
1903 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1910 /* Hmm, someone else was quicker then us. Let's give
1911 * him some time to finish, and retry. */
1916 /* OK, we succeeded in creating the temporary symlink, so
1917 * let's rename it */
1918 if (rename(t
, k
) < 0) {
1919 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1935 /* Try to open a configuration file. If "env" is specified, open the
1936 * value of the specified environment variable. Otherwise look for a
1937 * file "local" in the home directory or a file "global" in global
1938 * file system. If "result" is non-NULL, a pointer to a newly
1939 * allocated buffer containing the used configuration file is
1941 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1945 if (env
&& (fn
= getenv(env
))) {
1946 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1948 *result
= pa_xstrdup(fn
);
1953 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1962 if ((e
= getenv("PULSE_CONFIG_PATH"))) {
1963 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1964 f
= pa_fopen_cloexec(fn
, "r");
1965 } else if ((h
= pa_get_home_dir_malloc())) {
1966 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1967 f
= pa_fopen_cloexec(fn
, "r");
1970 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".config/pulse" PA_PATH_SEP
"%s", h
, local
);
1971 f
= pa_fopen_cloexec(fn
, "r");
1979 *result
= pa_xstrdup(fn
);
1985 if (errno
!= ENOENT
) {
1986 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1998 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1999 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
2000 pa_win32_get_toplevel(NULL
),
2001 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
2004 gfn
= pa_xstrdup(global
);
2006 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
2021 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
2024 if (env
&& (fn
= getenv(env
))) {
2025 if (access(fn
, R_OK
) == 0)
2026 return pa_xstrdup(fn
);
2028 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
2037 if ((e
= getenv("PULSE_CONFIG_PATH")))
2038 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
2039 else if ((h
= pa_get_home_dir_malloc())) {
2040 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
2045 if (access(fn
, R_OK
) == 0) {
2046 char *r
= pa_xstrdup(fn
);
2051 if (errno
!= ENOENT
) {
2052 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
2064 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
2065 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
2066 pa_win32_get_toplevel(NULL
),
2067 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
2070 gfn
= pa_xstrdup(global
);
2072 if (access(gfn
, R_OK
) == 0)
2082 /* Format the specified data as a hexademical string */
2083 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
2084 size_t i
= 0, j
= 0;
2085 const char hex
[] = "0123456789abcdef";
2089 pa_assert(slength
> 0);
2091 while (j
+2 < slength
&& i
< dlength
) {
2092 s
[j
++] = hex
[*d
>> 4];
2093 s
[j
++] = hex
[*d
& 0xF];
2099 s
[j
< slength
? j
: slength
] = 0;
2103 /* Convert a hexadecimal digit to a number or -1 if invalid */
2104 static int hexc(char c
) {
2105 if (c
>= '0' && c
<= '9')
2108 if (c
>= 'A' && c
<= 'F')
2109 return c
- 'A' + 10;
2111 if (c
>= 'a' && c
<= 'f')
2112 return c
- 'a' + 10;
2118 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
2119 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
2125 while (j
< dlength
&& *p
) {
2128 if ((b
= hexc(*(p
++))) < 0)
2131 d
[j
] = (uint8_t) (b
<< 4);
2136 if ((b
= hexc(*(p
++))) < 0)
2139 d
[j
] |= (uint8_t) b
;
2146 /* Returns nonzero when *s starts with *pfx */
2147 bool pa_startswith(const char *s
, const char *pfx
) {
2155 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
2158 /* Returns nonzero when *s ends with *sfx */
2159 bool pa_endswith(const char *s
, const char *sfx
) {
2168 return l1
>= l2
&& pa_streq(s
+ l1
- l2
, sfx
);
2171 bool pa_is_path_absolute(const char *fn
) {
2177 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
2181 char *pa_make_path_absolute(const char *p
) {
2187 if (pa_is_path_absolute(p
))
2188 return pa_xstrdup(p
);
2190 if (!(cwd
= pa_getcwd()))
2191 return pa_xstrdup(p
);
2193 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2198 /* If fn is NULL, return the PulseAudio runtime or state dir (depending on the
2199 * rt parameter). If fn is non-NULL and starts with /, return fn. Otherwise,
2200 * append fn to the runtime/state dir and return it. */
2201 static char *get_path(const char *fn
, bool prependmid
, bool rt
) {
2204 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2207 char *r
, *canonical_rtp
;
2209 if (pa_is_path_absolute(fn
)) {
2211 return pa_xstrdup(fn
);
2217 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2218 if ((canonical_rtp
= pa_realpath(rtp
))) {
2219 if (strlen(rtp
) >= strlen(canonical_rtp
))
2222 pa_xfree(canonical_rtp
);
2223 canonical_rtp
= rtp
;
2226 canonical_rtp
= rtp
;
2231 if (!(mid
= pa_machine_id())) {
2232 pa_xfree(canonical_rtp
);
2236 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", canonical_rtp
, mid
, fn
);
2239 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", canonical_rtp
, fn
);
2241 pa_xfree(canonical_rtp
);
2247 char *pa_runtime_path(const char *fn
) {
2248 return get_path(fn
, false, true);
2251 char *pa_state_path(const char *fn
, bool appendmid
) {
2252 return get_path(fn
, appendmid
, false);
2255 /* Convert the string s to a signed integer in *ret_i */
2256 int pa_atoi(const char *s
, int32_t *ret_i
) {
2262 if (pa_atol(s
, &l
) < 0)
2265 if ((int32_t) l
!= l
) {
2270 *ret_i
= (int32_t) l
;
2275 /* Convert the string s to an unsigned integer in *ret_u */
2276 int pa_atou(const char *s
, uint32_t *ret_u
) {
2284 l
= strtoul(s
, &x
, 0);
2286 if (!x
|| *x
|| errno
) {
2292 if ((uint32_t) l
!= l
) {
2297 *ret_u
= (uint32_t) l
;
2302 /* Convert the string s to a signed long integer in *ret_l. */
2303 int pa_atol(const char *s
, long *ret_l
) {
2311 l
= strtol(s
, &x
, 0);
2313 if (!x
|| *x
|| errno
) {
2324 #ifdef HAVE_STRTOF_L
2325 static locale_t c_locale
= NULL
;
2327 static void c_locale_destroy(void) {
2328 freelocale(c_locale
);
2332 int pa_atod(const char *s
, double *ret_d
) {
2339 /* This should be locale independent */
2341 #ifdef HAVE_STRTOF_L
2345 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2346 atexit(c_locale_destroy
);
2352 f
= strtod_l(s
, &x
, c_locale
);
2360 if (!x
|| *x
|| errno
) {
2371 /* Same as snprintf, but guarantees NUL-termination on every platform */
2372 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2377 pa_assert(size
> 0);
2380 va_start(ap
, format
);
2381 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2387 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2388 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2392 pa_assert(size
> 0);
2395 ret
= vsnprintf(str
, size
, format
, ap
);
2402 if ((size_t) ret
> size
-1)
2405 return (size_t) ret
;
2408 /* Truncate the specified string, but guarantee that the string
2409 * returned still validates as UTF8 */
2410 char *pa_truncate_utf8(char *c
, size_t l
) {
2412 pa_assert(pa_utf8_valid(c
));
2419 while (l
> 0 && !pa_utf8_valid(c
))
2425 char *pa_getcwd(void) {
2429 char *p
= pa_xmalloc(l
);
2433 if (errno
!= ERANGE
)
2441 void *pa_will_need(const void *p
, size_t l
) {
2442 #ifdef RLIMIT_MEMLOCK
2453 a
= PA_PAGE_ALIGN_PTR(p
);
2454 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2456 #ifdef HAVE_POSIX_MADVISE
2457 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2458 pa_log_debug("posix_madvise() worked fine!");
2463 /* Most likely the memory was not mmap()ed from a file and thus
2464 * madvise() didn't work, so let's misuse mlock() do page this
2465 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2466 * inviting, the man page of mlock() tells us: "All pages that
2467 * contain a part of the specified address range are guaranteed to
2468 * be resident in RAM when the call returns successfully." */
2470 #ifdef RLIMIT_MEMLOCK
2471 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2473 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2474 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
));
2479 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2481 bs
= PA_PAGE_SIZE
*4;
2484 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2487 while (size
> 0 && bs
> 0) {
2492 if (mlock(a
, bs
) < 0) {
2493 bs
= PA_PAGE_ALIGN(bs
/ 2);
2497 pa_assert_se(munlock(a
, bs
) == 0);
2499 a
= (const uint8_t*) a
+ bs
;
2505 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2507 pa_log_debug("mlock() worked fine!");
2512 void pa_close_pipe(int fds
[2]) {
2516 pa_assert_se(pa_close(fds
[0]) == 0);
2519 pa_assert_se(pa_close(fds
[1]) == 0);
2521 fds
[0] = fds
[1] = -1;
2524 char *pa_readlink(const char *p
) {
2525 #ifdef HAVE_READLINK
2534 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2539 if ((size_t) n
< l
-1) {
2552 int pa_close_all(int except_fd
, ...) {
2557 va_start(ap
, except_fd
);
2560 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2565 p
= pa_xnew(int, n
+1);
2567 va_start(ap
, except_fd
);
2570 if (except_fd
>= 0) {
2574 while ((fd
= va_arg(ap
, int)) >= 0)
2581 r
= pa_close_allv(p
);
2587 int pa_close_allv(const int except_fds
[]) {
2596 if ((d
= opendir("/proc/self/fd"))) {
2600 while ((de
= readdir(d
))) {
2606 if (de
->d_name
[0] == '.')
2610 l
= strtol(de
->d_name
, &e
, 10);
2611 if (errno
!= 0 || !e
|| *e
) {
2619 if ((long) fd
!= l
) {
2632 for (i
= 0; except_fds
[i
] >= 0; i
++)
2633 if (except_fds
[i
] == fd
) {
2641 if (pa_close(fd
) < 0) {
2642 saved_errno
= errno
;
2644 errno
= saved_errno
;
2656 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2657 maxfd
= (int) rl
.rlim_max
;
2659 maxfd
= sysconf(_SC_OPEN_MAX
);
2661 for (fd
= 3; fd
< maxfd
; fd
++) {
2666 for (i
= 0; except_fds
[i
] >= 0; i
++)
2667 if (except_fds
[i
] == fd
) {
2675 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2678 #endif /* !OS_IS_WIN32 */
2683 int pa_unblock_sigs(int except
, ...) {
2688 va_start(ap
, except
);
2691 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2696 p
= pa_xnew(int, n
+1);
2698 va_start(ap
, except
);
2705 while ((sig
= va_arg(ap
, int)) >= 0)
2712 r
= pa_unblock_sigsv(p
);
2718 int pa_unblock_sigsv(const int except
[]) {
2723 if (sigemptyset(&ss
) < 0)
2726 for (i
= 0; except
[i
] > 0; i
++)
2727 if (sigaddset(&ss
, except
[i
]) < 0)
2730 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2736 int pa_reset_sigs(int except
, ...) {
2741 va_start(ap
, except
);
2744 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2749 p
= pa_xnew(int, n
+1);
2751 va_start(ap
, except
);
2758 while ((sig
= va_arg(ap
, int)) >= 0)
2765 r
= pa_reset_sigsv(p
);
2771 int pa_reset_sigsv(const int except
[]) {
2775 for (sig
= 1; sig
< NSIG
; sig
++) {
2787 for (i
= 0; except
[i
] > 0; i
++) {
2788 if (sig
== except
[i
]) {
2797 struct sigaction sa
;
2799 memset(&sa
, 0, sizeof(sa
));
2800 sa
.sa_handler
= SIG_DFL
;
2802 /* On Linux the first two RT signals are reserved by
2803 * glibc, and sigaction() will return EINVAL for them. */
2804 if ((sigaction(sig
, &sa
, NULL
) < 0))
2805 if (errno
!= EINVAL
)
2814 void pa_set_env(const char *key
, const char *value
) {
2818 /* This is not thread-safe */
2821 SetEnvironmentVariable(key
, value
);
2823 setenv(key
, value
, 1);
2827 void pa_set_env_and_record(const char *key
, const char *value
) {
2831 /* This is not thread-safe */
2833 pa_set_env(key
, value
);
2834 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2837 void pa_unset_env_recorded(void) {
2839 /* This is not thread-safe */
2844 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2850 SetEnvironmentVariable(s
, NULL
);
2858 bool pa_in_system_mode(void) {
2861 if (!(e
= getenv("PULSE_SYSTEM")))
2867 /* Checks a whitespace-separated list of words in haystack for needle */
2868 bool pa_str_in_list_spaces(const char *haystack
, const char *needle
) {
2870 const char *state
= NULL
;
2872 if (!haystack
|| !needle
)
2875 while ((s
= pa_split_spaces(haystack
, &state
))) {
2876 if (pa_streq(needle
, s
)) {
2887 char *pa_get_user_name_malloc(void) {
2891 #ifdef _SC_LOGIN_NAME_MAX
2892 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2898 u
= pa_xnew(char, k
+1);
2900 if (!(pa_get_user_name(u
, k
))) {
2908 char *pa_get_host_name_malloc(void) {
2917 if (!pa_get_host_name(c
, l
)) {
2919 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2922 } else if (strlen(c
) < l
-1) {
2930 u
= pa_utf8_filter(c
);
2935 /* Hmm, the hostname is as long the space we offered the
2936 * function, we cannot know if it fully fit in, so let's play
2937 * safe and retry. */
2946 char *pa_machine_id(void) {
2950 /* The returned value is supposed be some kind of ascii identifier
2951 * that is unique and stable across reboots. */
2953 /* First we try the /etc/machine-id, which is the best option we
2954 * have, since it fits perfectly our needs and is not as volatile
2955 * as the hostname which might be set from dhcp. */
2957 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r")) ||
2958 (f
= pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK
, "r"))) {
2959 char ln
[34] = "", *r
;
2961 r
= fgets(ln
, sizeof(ln
)-1, f
);
2967 return pa_utf8_filter(ln
);
2970 if ((h
= pa_get_host_name_malloc()))
2973 #if !defined(OS_IS_WIN32) && !defined(__ANDROID__)
2974 /* If no hostname was set we use the POSIX hostid. It's usually
2975 * the IPv4 address. Might not be that stable. */
2976 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2982 char *pa_session_id(void) {
2985 e
= getenv("XDG_SESSION_ID");
2989 return pa_utf8_filter(e
);
2992 char *pa_uname_string(void) {
2996 pa_assert_se(uname(&u
) >= 0);
2998 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
3004 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
3005 pa_assert_se(GetVersionEx(&i
));
3007 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
3011 #ifdef HAVE_VALGRIND_MEMCHECK_H
3012 bool pa_in_valgrind(void) {
3015 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
3016 * here instead of really checking whether we run in valgrind or
3020 b
= getenv("VALGRIND") ? 2 : 1;
3026 unsigned pa_gcd(unsigned a
, unsigned b
) {
3037 void pa_reduce(unsigned *num
, unsigned *den
) {
3039 unsigned gcd
= pa_gcd(*num
, *den
);
3047 pa_assert(pa_gcd(*num
, *den
) == 1);
3050 unsigned pa_ncpus(void) {
3053 #ifdef _SC_NPROCESSORS_CONF
3054 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
3059 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
3062 char *pa_replace(const char*s
, const char*a
, const char *b
) {
3071 sb
= pa_strbuf_new();
3076 if (!(p
= strstr(s
, a
)))
3079 pa_strbuf_putsn(sb
, s
, p
-s
);
3080 pa_strbuf_puts(sb
, b
);
3084 pa_strbuf_puts(sb
, s
);
3086 return pa_strbuf_tostring_free(sb
);
3089 char *pa_escape(const char *p
, const char *chars
) {
3092 pa_strbuf
*buf
= pa_strbuf_new();
3094 for (s
= p
; *s
; ++s
) {
3096 pa_strbuf_putc(buf
, '\\');
3098 for (c
= chars
; *c
; ++c
) {
3100 pa_strbuf_putc(buf
, '\\');
3105 pa_strbuf_putc(buf
, *s
);
3108 return pa_strbuf_tostring_free(buf
);
3111 char *pa_unescape(char *p
) {
3113 bool escaped
= false;
3115 for (s
= p
, d
= p
; *s
; s
++) {
3116 if (!escaped
&& *s
== '\\') {
3130 char *pa_realpath(const char *path
) {
3134 /* We want only absolute paths */
3135 if (path
[0] != '/') {
3140 #if defined(__GLIBC__)
3144 if (!(r
= realpath(path
, NULL
)))
3147 /* We copy this here in case our pa_xmalloc() is not
3148 * implemented on top of libc malloc() */
3152 #elif defined(PATH_MAX)
3155 path_buf
= pa_xmalloc(PATH_MAX
);
3157 #if defined(OS_IS_WIN32)
3158 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
3163 if (!(t
= realpath(path
, path_buf
))) {
3170 #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."
3176 void pa_disable_sigpipe(void) {
3179 struct sigaction sa
;
3183 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
3184 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3188 sa
.sa_handler
= SIG_IGN
;
3190 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
3191 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3197 void pa_xfreev(void**a
) {
3203 for (p
= a
; *p
; p
++)
3209 char **pa_split_spaces_strv(const char *s
) {
3211 unsigned i
= 0, n
= 8;
3212 const char *state
= NULL
;
3214 t
= pa_xnew(char*, n
);
3215 while ((e
= pa_split_spaces(s
, &state
))) {
3220 t
= pa_xrenew(char*, t
, n
);
3233 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
3236 if (pa_is_path_absolute(path
))
3237 return pa_xstrdup(path
);
3239 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
3242 size_t pa_pipe_buf(int fd
) {
3247 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3258 void pa_reset_personality(void) {
3260 #if defined(__linux__) && !defined(__ANDROID__)
3261 if (personality(PER_LINUX
) < 0)
3262 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3267 bool pa_run_from_build_tree(void) {
3269 static bool b
= false;
3272 if ((rp
= pa_readlink("/proc/self/exe"))) {
3273 b
= pa_startswith(rp
, PA_BUILDDIR
);
3281 const char *pa_get_temp_dir(void) {
3284 if ((t
= getenv("TMPDIR")) &&
3285 pa_is_path_absolute(t
))
3288 if ((t
= getenv("TMP")) &&
3289 pa_is_path_absolute(t
))
3292 if ((t
= getenv("TEMP")) &&
3293 pa_is_path_absolute(t
))
3296 if ((t
= getenv("TEMPDIR")) &&
3297 pa_is_path_absolute(t
))
3303 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3311 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3314 if (errno
!= EINVAL
)
3318 if ((fd
= open(fn
, flags
, mode
)) < 0)
3322 /* Some implementations might simply ignore O_CLOEXEC if it is not
3323 * understood, make sure FD_CLOEXEC is enabled anyway */
3325 pa_make_fd_cloexec(fd
);
3329 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3333 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3336 if (errno
!= EINVAL
)
3340 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3344 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3345 * not understood, make sure FD_CLOEXEC is enabled anyway */
3347 pa_make_fd_cloexec(fd
);
3351 int pa_pipe_cloexec(int pipefd
[2]) {
3355 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3358 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3363 if ((r
= pipe(pipefd
)) < 0)
3367 pa_make_fd_cloexec(pipefd
[0]);
3368 pa_make_fd_cloexec(pipefd
[1]);
3373 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3377 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3380 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3385 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3389 pa_make_fd_cloexec(fd
);
3393 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3397 m
= pa_sprintf_malloc("%se", mode
);
3400 if ((f
= fopen(path
, m
))) {
3407 if (errno
!= EINVAL
)
3410 if (!(f
= fopen(path
, mode
)))
3414 pa_make_fd_cloexec(fileno(f
));
3418 void pa_nullify_stdfds(void) {
3421 pa_close(STDIN_FILENO
);
3422 pa_close(STDOUT_FILENO
);
3423 pa_close(STDERR_FILENO
);
3425 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3426 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3427 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3434 char *pa_read_line_from_file(const char *fn
) {
3436 char ln
[256] = "", *r
;
3438 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3441 r
= fgets(ln
, sizeof(ln
)-1, f
);
3450 return pa_xstrdup(ln
);
3453 bool pa_running_in_vm(void) {
3455 #if defined(__i386__) || defined(__x86_64__)
3457 /* Both CPUID and DMI are x86 specific interfaces... */
3459 uint32_t eax
= 0x40000000;
3466 const char *const dmi_vendors
[] = {
3467 "/sys/class/dmi/id/sys_vendor",
3468 "/sys/class/dmi/id/board_vendor",
3469 "/sys/class/dmi/id/bios_vendor"
3474 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3477 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3479 if (pa_startswith(s
, "QEMU") ||
3480 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3481 pa_startswith(s
, "VMware") ||
3482 pa_startswith(s
, "VMW") ||
3483 pa_startswith(s
, "Microsoft Corporation") ||
3484 pa_startswith(s
, "innotek GmbH") ||
3485 pa_startswith(s
, "Xen")) {
3497 /* http://lwn.net/Articles/301888/ */
3500 __asm__
__volatile__ (
3501 /* ebx/rbx is being used for PIC! */
3502 " push %%"PA_REG_b
" \n\t"
3504 " mov %%ebx, %1 \n\t"
3505 " pop %%"PA_REG_b
" \n\t"
3507 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3511 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3512 pa_streq(sig
.text
, "KVMKVMKVM") ||
3513 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3514 pa_streq(sig
.text
, "VMwareVMware") ||
3515 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3516 pa_streq(sig
.text
, "Microsoft Hv"))