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);
333 if (uid
== (uid_t
) -1)
335 if (gid
== (gid_t
) -1)
337 if (fchown(fd
, uid
, gid
) < 0)
342 (void) fchmod(fd
, m
);
345 pa_assert_se(pa_close(fd
) >= 0);
350 if (lstat(dir
, &st
) < 0)
352 if (stat(dir
, &st
) < 0)
357 if (!S_ISDIR(st
.st_mode
) ||
358 (st
.st_uid
!= uid
) ||
359 (st
.st_gid
!= gid
) ||
360 ((st
.st_mode
& 0777) != m
)) {
365 pa_log_warn("Secure directory creation not supported on Win32.");
378 /* Return a newly allocated sting containing the parent directory of the specified file */
379 char *pa_parent_dir(const char *fn
) {
380 char *slash
, *dir
= pa_xstrdup(fn
);
382 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
392 /* Creates a the parent directory of the specified path securely */
393 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
, bool update_perms
) {
397 if (!(dir
= pa_parent_dir(fn
)))
400 if (pa_make_secure_dir(dir
, m
, uid
, gid
, update_perms
) < 0)
410 /** Platform independent read function. Necessary since not all
411 * systems treat all file descriptors equal. If type is
412 * non-NULL it is used to cache the type of the fd. This is
413 * useful for making sure that only a single syscall is executed per
414 * function call. The variable pointed to should be initialized to 0
416 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
420 if (!type
|| *type
== 0) {
423 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
426 if (WSAGetLastError() != WSAENOTSOCK
) {
427 errno
= WSAGetLastError();
440 if ((r
= read(fd
, buf
, count
)) < 0)
448 /** Similar to pa_read(), but handles writes */
449 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
451 if (!type
|| *type
== 0) {
455 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
467 if (WSAGetLastError() != WSAENOTSOCK
) {
468 errno
= WSAGetLastError();
472 if (errno
!= ENOTSOCK
)
483 if ((r
= write(fd
, buf
, count
)) < 0)
491 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
492 * unless EOF is reached or an error occurred */
493 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
509 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
516 data
= (uint8_t*) data
+ r
;
523 /** Similar to pa_loop_read(), but wraps write() */
524 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
540 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
547 data
= (const uint8_t*) data
+ r
;
554 /** Platform independent close function. Necessary since not all
555 * systems treat all file descriptors equal. */
556 int pa_close(int fd
) {
561 FD_CLR(fd
, &nonblocking_fds
);
563 if ((ret
= closesocket(fd
)) == 0)
566 if (WSAGetLastError() != WSAENOTSOCK
) {
567 errno
= WSAGetLastError();
575 if ((r
= close(fd
)) < 0)
583 /* Print a warning messages in case that the given signal is not
584 * blocked or trapped */
585 void pa_check_signal_is_blocked(int sig
) {
586 #ifdef HAVE_SIGACTION
590 /* If POSIX threads are supported use thread-aware
591 * pthread_sigmask() function, to check if the signal is
592 * blocked. Otherwise fall back to sigprocmask() */
595 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
597 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
598 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
605 if (sigismember(&set
, sig
))
608 /* Check whether the signal is trapped */
610 if (sigaction(sig
, NULL
, &sa
) < 0) {
611 pa_log("sigaction(): %s", pa_cstrerror(errno
));
615 if (sa
.sa_handler
!= SIG_DFL
)
618 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
619 #else /* HAVE_SIGACTION */
620 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
624 /* The following function is based on an example from the GNU libc
625 * documentation. This function is similar to GNU's asprintf(). */
626 char *pa_sprintf_malloc(const char *format
, ...) {
636 c
= pa_xrealloc(c
, size
);
638 va_start(ap
, format
);
639 r
= vsnprintf(c
, size
, format
, ap
);
644 if (r
> -1 && (size_t) r
< size
)
647 if (r
> -1) /* glibc 2.1 */
654 /* Same as the previous function, but use a va_list instead of an
656 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
666 c
= pa_xrealloc(c
, size
);
669 r
= vsnprintf(c
, size
, format
, aq
);
674 if (r
> -1 && (size_t) r
< size
)
677 if (r
> -1) /* glibc 2.1 */
684 /* Similar to OpenBSD's strlcpy() function */
685 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
703 #ifdef _POSIX_PRIORITY_SCHEDULING
704 static int set_scheduler(int rtprio
) {
706 struct sched_param sp
;
710 #ifdef HAVE_SYS_RESOURCE_H
716 dbus_error_init(&error
);
720 sp
.sched_priority
= rtprio
;
722 #ifdef SCHED_RESET_ON_FORK
723 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
724 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
729 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
730 pa_log_debug("SCHED_RR worked.");
733 #endif /* HAVE_SCHED_H */
736 /* Try to talk to RealtimeKit */
738 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
739 pa_log("Failed to connect to system bus: %s\n", error
.message
);
740 dbus_error_free(&error
);
745 /* We need to disable exit on disconnect because otherwise
746 * dbus_shutdown will kill us. See
747 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
748 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
750 rttime
= rtkit_get_rttime_usec_max(bus
);
752 #ifdef HAVE_SYS_RESOURCE_H
753 r
= getrlimit(RLIMIT_RTTIME
, &rl
);
755 if (r
>= 0 && (long long) rl
.rlim_max
> rttime
) {
756 pa_log_info("Clamping rlimit-rttime to %lld for RealtimeKit\n", rttime
);
757 rl
.rlim_cur
= rl
.rlim_max
= rttime
;
758 r
= setrlimit(RLIMIT_RTTIME
, &rl
);
761 pa_log("setrlimit() failed: %s", pa_cstrerror(errno
));
764 r
= rtkit_make_realtime(bus
, 0, rtprio
);
765 dbus_connection_close(bus
);
766 dbus_connection_unref(bus
);
769 pa_log_debug("RealtimeKit worked.");
775 dbus_connection_close(bus
);
776 dbus_connection_unref(bus
);
788 /* Make the current thread a realtime thread, and acquire the highest
789 * rtprio we can get that is less or equal the specified parameter. If
790 * the thread is already realtime, don't do anything. */
791 int pa_make_realtime(int rtprio
) {
793 #if defined(OS_IS_DARWIN)
794 struct thread_time_constraint_policy ttcpolicy
;
796 size_t size
= sizeof(freq
);
799 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
801 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
805 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
807 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
808 ttcpolicy
.period
= freq
/ 160;
809 ttcpolicy
.computation
= freq
/ 3300;
810 ttcpolicy
.constraint
= freq
/ 2200;
811 ttcpolicy
.preemptible
= 1;
813 ret
= thread_policy_set(mach_thread_self(),
814 THREAD_TIME_CONSTRAINT_POLICY
,
815 (thread_policy_t
) &ttcpolicy
,
816 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
818 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
822 pa_log_info("Successfully acquired real-time thread priority.");
825 #elif defined(_POSIX_PRIORITY_SCHEDULING)
828 if (set_scheduler(rtprio
) >= 0) {
829 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
833 for (p
= rtprio
-1; p
>= 1; p
--)
834 if (set_scheduler(p
) >= 0) {
835 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
838 #elif defined(OS_IS_WIN32)
839 /* Windows only allows realtime scheduling to be set on a per process basis.
840 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
841 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
842 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
846 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
851 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
855 #ifdef HAVE_SYS_RESOURCE_H
856 static int set_nice(int nice_level
) {
862 dbus_error_init(&error
);
865 #ifdef HAVE_SYS_RESOURCE_H
866 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
867 pa_log_debug("setpriority() worked.");
873 /* Try to talk to RealtimeKit */
875 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
876 pa_log("Failed to connect to system bus: %s\n", error
.message
);
877 dbus_error_free(&error
);
882 /* We need to disable exit on disconnect because otherwise
883 * dbus_shutdown will kill us. See
884 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
885 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
887 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
888 dbus_connection_unref(bus
);
891 pa_log_debug("RealtimeKit worked.");
902 /* Raise the priority of the current process as much as possible that
903 * is <= the specified nice level..*/
904 int pa_raise_priority(int nice_level
) {
906 #ifdef HAVE_SYS_RESOURCE_H
909 if (set_nice(nice_level
) >= 0) {
910 pa_log_info("Successfully gained nice level %i.", nice_level
);
914 for (n
= nice_level
+1; n
< 0; n
++)
915 if (set_nice(n
) >= 0) {
916 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
920 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
925 if (nice_level
< 0) {
926 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
927 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
932 pa_log_info("Successfully gained high priority class.");
939 /* Reset the priority to normal, inverting the changes made by
940 * pa_raise_priority() and pa_make_realtime()*/
941 void pa_reset_priority(void) {
942 #ifdef HAVE_SYS_RESOURCE_H
943 struct sched_param sp
;
945 setpriority(PRIO_PROCESS
, 0, 0);
948 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
952 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
956 int pa_match(const char *expr
, const char *v
) {
961 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
966 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
968 else if (k
== REG_NOMATCH
)
981 /* Try to parse a boolean string value.*/
982 int pa_parse_boolean(const char *v
) {
985 /* First we check language independent */
986 if (pa_streq(v
, "1") || !strcasecmp(v
, "y") || !strcasecmp(v
, "t")
987 || !strcasecmp(v
, "yes") || !strcasecmp(v
, "true") || !strcasecmp(v
, "on"))
989 else if (pa_streq(v
, "0") || !strcasecmp(v
, "n") || !strcasecmp(v
, "f")
990 || !strcasecmp(v
, "no") || !strcasecmp(v
, "false") || !strcasecmp(v
, "off"))
993 #ifdef HAVE_LANGINFO_H
996 /* And then we check language dependent */
997 if ((expr
= nl_langinfo(YESEXPR
)))
999 if (pa_match(expr
, v
) > 0)
1002 if ((expr
= nl_langinfo(NOEXPR
)))
1004 if (pa_match(expr
, v
) > 0)
1013 /* Try to parse a volume string to pa_volume_t. The allowed formats are:
1014 * db, % and unsigned integer */
1015 int pa_parse_volume(const char *v
, pa_volume_t
*volume
) {
1029 memcpy(str
, v
, len
+ 1);
1031 if (str
[len
- 1] == '%') {
1032 str
[len
- 1] = '\0';
1033 if (pa_atou(str
, &i
) == 0) {
1034 *volume
= PA_CLAMP_VOLUME((uint64_t) PA_VOLUME_NORM
* i
/ 100);
1037 } else if (len
> 2 && (str
[len
- 1] == 'b' || str
[len
- 1] == 'B') &&
1038 (str
[len
- 2] == 'd' || str
[len
- 2] == 'D')) {
1039 str
[len
- 2] = '\0';
1040 if (pa_atod(str
, &d
) == 0) {
1041 *volume
= pa_sw_volume_from_dB(d
);
1045 if (pa_atou(v
, &i
) == 0) {
1046 *volume
= PA_CLAMP_VOLUME(i
);
1055 /* Split the specified string wherever one of the strings in delimiter
1056 * occurs. Each time it is called returns a newly allocated string
1057 * with pa_xmalloc(). The variable state points to, should be
1058 * initialized to NULL before the first call. */
1059 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
1060 const char *current
= *state
? *state
: c
;
1066 l
= strcspn(current
, delimiter
);
1072 return pa_xstrndup(current
, l
);
1075 /* Split the specified string wherever one of the strings in delimiter
1076 * occurs. Each time it is called returns a pointer to the substring within the
1077 * string and the length in 'n'. Note that the resultant string cannot be used
1078 * as-is without the length parameter, since it is merely pointing to a point
1079 * within the original string. The variable state points to, should be
1080 * initialized to NULL before the first call. */
1081 const char *pa_split_in_place(const char *c
, const char *delimiter
, int *n
, const char**state
) {
1082 const char *current
= *state
? *state
: c
;
1088 l
= strcspn(current
, delimiter
);
1098 /* Split a string into words. Otherwise similar to pa_split(). */
1099 char *pa_split_spaces(const char *c
, const char **state
) {
1100 const char *current
= *state
? *state
: c
;
1103 if (!*current
|| *c
== 0)
1106 current
+= strspn(current
, WHITESPACE
);
1107 l
= strcspn(current
, WHITESPACE
);
1111 return pa_xstrndup(current
, l
);
1114 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
1116 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
1117 const char *pa_sig2str(int sig
) {
1130 char buf
[SIG2STR_MAX
];
1132 if (sig2str(sig
, buf
) == 0) {
1133 pa_xfree(PA_STATIC_TLS_GET(signame
));
1134 t
= pa_sprintf_malloc("SIG%s", buf
);
1135 PA_STATIC_TLS_SET(signame
, t
);
1143 case SIGHUP
: return "SIGHUP";
1145 case SIGINT
: return "SIGINT";
1147 case SIGQUIT
: return "SIGQUIT";
1149 case SIGILL
: return "SIGULL";
1151 case SIGTRAP
: return "SIGTRAP";
1153 case SIGABRT
: return "SIGABRT";
1155 case SIGBUS
: return "SIGBUS";
1157 case SIGFPE
: return "SIGFPE";
1159 case SIGKILL
: return "SIGKILL";
1162 case SIGUSR1
: return "SIGUSR1";
1164 case SIGSEGV
: return "SIGSEGV";
1166 case SIGUSR2
: return "SIGUSR2";
1169 case SIGPIPE
: return "SIGPIPE";
1172 case SIGALRM
: return "SIGALRM";
1174 case SIGTERM
: return "SIGTERM";
1176 case SIGSTKFLT
: return "SIGSTKFLT";
1179 case SIGCHLD
: return "SIGCHLD";
1182 case SIGCONT
: return "SIGCONT";
1185 case SIGSTOP
: return "SIGSTOP";
1188 case SIGTSTP
: return "SIGTSTP";
1191 case SIGTTIN
: return "SIGTTIN";
1194 case SIGTTOU
: return "SIGTTOU";
1197 case SIGURG
: return "SIGURG";
1200 case SIGXCPU
: return "SIGXCPU";
1203 case SIGXFSZ
: return "SIGXFSZ";
1206 case SIGVTALRM
: return "SIGVTALRM";
1209 case SIGPROF
: return "SIGPROF";
1212 case SIGWINCH
: return "SIGWINCH";
1215 case SIGIO
: return "SIGIO";
1218 case SIGPWR
: return "SIGPWR";
1221 case SIGSYS
: return "SIGSYS";
1226 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1227 pa_xfree(PA_STATIC_TLS_GET(signame
));
1228 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1229 PA_STATIC_TLS_SET(signame
, t
);
1238 pa_xfree(PA_STATIC_TLS_GET(signame
));
1239 t
= pa_sprintf_malloc("SIG%i", sig
);
1240 PA_STATIC_TLS_SET(signame
, t
);
1246 /* Check whether the specified GID and the group name match */
1247 static int is_group(gid_t gid
, const char *name
) {
1248 struct group
*group
= NULL
;
1252 if (!(group
= pa_getgrgid_malloc(gid
))) {
1256 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1261 r
= pa_streq(name
, group
->gr_name
);
1264 pa_getgrgid_free(group
);
1269 /* Check the current user is member of the specified group */
1270 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1271 GETGROUPS_T
*gids
, tgid
;
1272 long n
= sysconf(_SC_NGROUPS_MAX
);
1277 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1279 if ((n
= getgroups((int) n
, gids
)) < 0) {
1280 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1284 for (i
= 0; i
< n
; i
++) {
1286 if ((k
= is_group(gids
[i
], name
)) < 0)
1295 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1311 /* Check whether the specific user id is a member of the specified group */
1312 int pa_uid_in_group(uid_t uid
, const char *name
) {
1313 struct group
*group
= NULL
;
1318 if (!(group
= pa_getgrnam_malloc(name
))) {
1325 for (i
= group
->gr_mem
; *i
; i
++) {
1326 struct passwd
*pw
= NULL
;
1329 if (!(pw
= pa_getpwnam_malloc(*i
)))
1332 if (pw
->pw_uid
== uid
)
1335 pa_getpwnam_free(pw
);
1342 pa_getgrnam_free(group
);
1347 /* Get the GID of a given group, return (gid_t) -1 on failure. */
1348 gid_t
pa_get_gid_of_group(const char *name
) {
1349 gid_t ret
= (gid_t
) -1;
1350 struct group
*gr
= NULL
;
1353 if (!(gr
= pa_getgrnam_malloc(name
))) {
1362 pa_getgrnam_free(gr
);
1366 int pa_check_in_group(gid_t g
) {
1367 gid_t gids
[NGROUPS_MAX
];
1370 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1380 #else /* HAVE_GRP_H */
1382 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1388 int pa_uid_in_group(uid_t uid
, const char *name
) {
1393 gid_t
pa_get_gid_of_group(const char *name
) {
1398 int pa_check_in_group(gid_t g
) {
1405 /* Lock or unlock a file entirely.
1406 (advisory on UNIX, mandatory on Windows) */
1407 int pa_lock_fd(int fd
, int b
) {
1409 struct flock f_lock
;
1411 /* Try a R/W lock first */
1413 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1414 f_lock
.l_whence
= SEEK_SET
;
1418 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1421 /* Perhaps the file descriptor was opened for read only, than try again with a read lock. */
1422 if (b
&& errno
== EBADF
) {
1423 f_lock
.l_type
= F_RDLCK
;
1424 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1428 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1432 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1434 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1436 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1439 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1441 /* FIXME: Needs to set errno! */
1447 /* Remove trailing newlines from a string */
1448 char* pa_strip_nl(char *s
) {
1451 s
[strcspn(s
, NEWLINE
)] = 0;
1455 char *pa_strip(char *s
) {
1458 /* Drops trailing whitespace. Modifies the string in
1459 * place. Returns pointer to first non-space character */
1461 s
+= strspn(s
, WHITESPACE
);
1463 for (e
= s
; *e
; e
++)
1464 if (!strchr(WHITESPACE
, *e
))
1475 /* Create a temporary lock file and lock it. */
1476 int pa_lock_lockfile(const char *fn
) {
1483 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1487 , S_IRUSR
|S_IWUSR
)) < 0) {
1488 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1492 if (pa_lock_fd(fd
, 1) < 0) {
1493 pa_log_warn("Failed to lock file '%s'.", fn
);
1497 if (fstat(fd
, &st
) < 0) {
1498 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1502 /* Check whether the file has been removed meanwhile. When yes,
1503 * restart this loop, otherwise, we're done */
1504 if (st
.st_nlink
>= 1)
1507 if (pa_lock_fd(fd
, 0) < 0) {
1508 pa_log_warn("Failed to unlock file '%s'.", fn
);
1512 if (pa_close(fd
) < 0) {
1513 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1524 int saved_errno
= errno
;
1526 errno
= saved_errno
;
1532 /* Unlock a temporary lock file */
1533 int pa_unlock_lockfile(const char *fn
, int fd
) {
1538 if (unlink(fn
) < 0) {
1539 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1544 if (pa_lock_fd(fd
, 0) < 0) {
1545 pa_log_warn("Failed to unlock file '%s'.", fn
);
1549 if (pa_close(fd
) < 0) {
1550 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1557 static char *get_config_home(char *home
) {
1560 t
= getenv("XDG_CONFIG_HOME");
1562 return pa_xstrdup(t
);
1564 return pa_sprintf_malloc("%s" PA_PATH_SEP
".config", home
);
1567 static int check_ours(const char *p
) {
1572 if (stat(p
, &st
) < 0)
1576 if (st
.st_uid
!= getuid())
1583 static char *get_pulse_home(void) {
1584 char *h
, *ret
, *config_home
;
1587 h
= pa_get_home_dir_malloc();
1589 pa_log_error("Failed to get home directory.");
1594 if (t
< 0 && t
!= -ENOENT
) {
1595 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t
));
1600 /* If the old directory exists, use it. */
1601 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1602 if (access(ret
, F_OK
) >= 0) {
1608 /* Otherwise go for the XDG compliant directory. */
1609 config_home
= get_config_home(h
);
1611 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", config_home
);
1617 char *pa_get_state_dir(void) {
1620 /* The state directory shall contain dynamic data that should be
1621 * kept across reboots, and is private to this user */
1623 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1624 if (!(d
= get_pulse_home()))
1627 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1628 * dir then this will break. */
1630 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1631 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1639 char *pa_get_home_dir_malloc(void) {
1641 size_t allocated
= 128;
1644 homedir
= pa_xmalloc(allocated
);
1646 if (!pa_get_home_dir(homedir
, allocated
)) {
1651 if (strlen(homedir
) < allocated
- 1)
1661 char *pa_get_binary_name_malloc(void) {
1663 size_t allocated
= 128;
1666 t
= pa_xmalloc(allocated
);
1668 if (!pa_get_binary_name(t
, allocated
)) {
1673 if (strlen(t
) < allocated
- 1)
1683 static char* make_random_dir(mode_t m
) {
1684 static const char table
[] =
1685 "abcdefghijklmnopqrstuvwxyz"
1686 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1692 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1693 pathlen
= strlen(fn
);
1701 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1702 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1704 u
= umask((~m
) & 0777);
1711 saved_errno
= errno
;
1713 errno
= saved_errno
;
1718 if (errno
!= EEXIST
) {
1719 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1726 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1729 if (!(p
= make_random_dir(m
)))
1733 if (symlink(p
, k
) < 0) {
1734 int saved_errno
= errno
;
1736 if (errno
!= EEXIST
)
1737 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1742 errno
= saved_errno
;
1754 char *pa_get_runtime_dir(void) {
1755 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1758 /* The runtime directory shall contain dynamic data that needs NOT
1759 * to be kept across reboots and is usually private to the user,
1760 * except in system mode, where it might be accessible by other
1761 * users, too. Since we need POSIX locking and UNIX sockets in
1762 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1763 * set create a directory in $HOME and link it to a random subdir
1764 * in /tmp, if it was not explicitly configured. */
1766 m
= pa_in_system_mode() ? 0755U : 0700U;
1768 /* Use the explicitly configured value if it is set */
1769 d
= getenv("PULSE_RUNTIME_PATH");
1772 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1773 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1777 return pa_xstrdup(d
);
1780 /* Use the XDG standard for the runtime directory. */
1781 d
= getenv("XDG_RUNTIME_DIR");
1783 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", d
);
1785 if (pa_make_secure_dir(k
, m
, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1786 pa_log_error("Failed to create secure directory (%s): %s", k
, pa_cstrerror(errno
));
1793 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1794 d
= get_pulse_home();
1798 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, true) < 0) {
1799 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1804 mid
= pa_machine_id();
1810 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1815 /* OK, first let's check if the "runtime" symlink already exists */
1820 if (errno
!= ENOENT
) {
1821 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1826 /* Hmm, so the runtime directory didn't exist yet, so let's
1827 * create one in /tmp and symlink that to it */
1829 if (make_random_dir_and_link(0700, k
) < 0) {
1831 /* Mhmm, maybe another process was quicker than us,
1832 * let's check if that was valid */
1833 if (errno
== EEXIST
)
1839 /* No symlink possible, so let's just create the runtime directly
1840 * Do not check again if it exists since it cannot be a symlink */
1841 if (mkdir(k
) < 0 && errno
!= EEXIST
)
1848 /* Make sure that this actually makes sense */
1849 if (!pa_is_path_absolute(p
)) {
1850 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1855 /* Hmm, so this symlink is still around, make sure nobody fools us */
1859 if (lstat(p
, &st
) < 0) {
1861 if (errno
!= ENOENT
) {
1862 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1868 if (S_ISDIR(st
.st_mode
) &&
1869 (st
.st_uid
== getuid()) &&
1870 ((st
.st_mode
& 0777) == 0700)) {
1876 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1884 /* Hmm, so the link points to some nonexisting or invalid
1885 * dir. Let's replace it by a new link. We first create a
1886 * temporary link and then rename that to allow concurrent
1887 * execution of this function. */
1889 t
= pa_sprintf_malloc("%s.tmp", k
);
1891 if (make_random_dir_and_link(0700, t
) < 0) {
1893 if (errno
!= EEXIST
) {
1894 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1901 /* Hmm, someone else was quicker then us. Let's give
1902 * him some time to finish, and retry. */
1907 /* OK, we succeeded in creating the temporary symlink, so
1908 * let's rename it */
1909 if (rename(t
, k
) < 0) {
1910 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1926 /* Try to open a configuration file. If "env" is specified, open the
1927 * value of the specified environment variable. Otherwise look for a
1928 * file "local" in the home directory or a file "global" in global
1929 * file system. If "result" is non-NULL, a pointer to a newly
1930 * allocated buffer containing the used configuration file is
1932 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1936 if (env
&& (fn
= getenv(env
))) {
1937 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1939 *result
= pa_xstrdup(fn
);
1944 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1953 if ((e
= getenv("PULSE_CONFIG_PATH"))) {
1954 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1955 f
= pa_fopen_cloexec(fn
, "r");
1956 } else if ((h
= pa_get_home_dir_malloc())) {
1957 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1958 f
= pa_fopen_cloexec(fn
, "r");
1961 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".config/pulse" PA_PATH_SEP
"%s", h
, local
);
1962 f
= pa_fopen_cloexec(fn
, "r");
1970 *result
= pa_xstrdup(fn
);
1976 if (errno
!= ENOENT
) {
1977 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1989 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1990 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1991 pa_win32_get_toplevel(NULL
),
1992 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1995 gfn
= pa_xstrdup(global
);
1997 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
2012 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
2015 if (env
&& (fn
= getenv(env
))) {
2016 if (access(fn
, R_OK
) == 0)
2017 return pa_xstrdup(fn
);
2019 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
2028 if ((e
= getenv("PULSE_CONFIG_PATH")))
2029 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
2030 else if ((h
= pa_get_home_dir_malloc())) {
2031 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
2036 if (access(fn
, R_OK
) == 0) {
2037 char *r
= pa_xstrdup(fn
);
2042 if (errno
!= ENOENT
) {
2043 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
2055 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
2056 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
2057 pa_win32_get_toplevel(NULL
),
2058 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
2061 gfn
= pa_xstrdup(global
);
2063 if (access(gfn
, R_OK
) == 0)
2073 /* Format the specified data as a hexademical string */
2074 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
2075 size_t i
= 0, j
= 0;
2076 const char hex
[] = "0123456789abcdef";
2080 pa_assert(slength
> 0);
2082 while (j
+2 < slength
&& i
< dlength
) {
2083 s
[j
++] = hex
[*d
>> 4];
2084 s
[j
++] = hex
[*d
& 0xF];
2090 s
[j
< slength
? j
: slength
] = 0;
2094 /* Convert a hexadecimal digit to a number or -1 if invalid */
2095 static int hexc(char c
) {
2096 if (c
>= '0' && c
<= '9')
2099 if (c
>= 'A' && c
<= 'F')
2100 return c
- 'A' + 10;
2102 if (c
>= 'a' && c
<= 'f')
2103 return c
- 'a' + 10;
2109 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
2110 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
2116 while (j
< dlength
&& *p
) {
2119 if ((b
= hexc(*(p
++))) < 0)
2122 d
[j
] = (uint8_t) (b
<< 4);
2127 if ((b
= hexc(*(p
++))) < 0)
2130 d
[j
] |= (uint8_t) b
;
2137 /* Returns nonzero when *s starts with *pfx */
2138 bool pa_startswith(const char *s
, const char *pfx
) {
2146 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
2149 /* Returns nonzero when *s ends with *sfx */
2150 bool pa_endswith(const char *s
, const char *sfx
) {
2159 return l1
>= l2
&& pa_streq(s
+ l1
- l2
, sfx
);
2162 bool pa_is_path_absolute(const char *fn
) {
2168 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
2172 char *pa_make_path_absolute(const char *p
) {
2178 if (pa_is_path_absolute(p
))
2179 return pa_xstrdup(p
);
2181 if (!(cwd
= pa_getcwd()))
2182 return pa_xstrdup(p
);
2184 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2189 /* If fn is NULL, return the PulseAudio runtime or state dir (depending on the
2190 * rt parameter). If fn is non-NULL and starts with /, return fn. Otherwise,
2191 * append fn to the runtime/state dir and return it. */
2192 static char *get_path(const char *fn
, bool prependmid
, bool rt
) {
2195 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2198 char *r
, *canonical_rtp
;
2200 if (pa_is_path_absolute(fn
)) {
2202 return pa_xstrdup(fn
);
2208 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2209 if ((canonical_rtp
= pa_realpath(rtp
))) {
2210 if (strlen(rtp
) >= strlen(canonical_rtp
))
2213 pa_xfree(canonical_rtp
);
2214 canonical_rtp
= rtp
;
2217 canonical_rtp
= rtp
;
2222 if (!(mid
= pa_machine_id())) {
2223 pa_xfree(canonical_rtp
);
2227 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", canonical_rtp
, mid
, fn
);
2230 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", canonical_rtp
, fn
);
2232 pa_xfree(canonical_rtp
);
2238 char *pa_runtime_path(const char *fn
) {
2239 return get_path(fn
, false, true);
2242 char *pa_state_path(const char *fn
, bool appendmid
) {
2243 return get_path(fn
, appendmid
, false);
2246 /* Convert the string s to a signed integer in *ret_i */
2247 int pa_atoi(const char *s
, int32_t *ret_i
) {
2253 if (pa_atol(s
, &l
) < 0)
2256 if ((int32_t) l
!= l
) {
2261 *ret_i
= (int32_t) l
;
2266 /* Convert the string s to an unsigned integer in *ret_u */
2267 int pa_atou(const char *s
, uint32_t *ret_u
) {
2275 l
= strtoul(s
, &x
, 0);
2277 if (!x
|| *x
|| errno
) {
2283 if ((uint32_t) l
!= l
) {
2288 *ret_u
= (uint32_t) l
;
2293 /* Convert the string s to a signed long integer in *ret_l. */
2294 int pa_atol(const char *s
, long *ret_l
) {
2302 l
= strtol(s
, &x
, 0);
2304 if (!x
|| *x
|| errno
) {
2315 #ifdef HAVE_STRTOF_L
2316 static locale_t c_locale
= NULL
;
2318 static void c_locale_destroy(void) {
2319 freelocale(c_locale
);
2323 int pa_atod(const char *s
, double *ret_d
) {
2330 /* This should be locale independent */
2332 #ifdef HAVE_STRTOF_L
2336 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2337 atexit(c_locale_destroy
);
2343 f
= strtod_l(s
, &x
, c_locale
);
2351 if (!x
|| *x
|| errno
) {
2362 /* Same as snprintf, but guarantees NUL-termination on every platform */
2363 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2368 pa_assert(size
> 0);
2371 va_start(ap
, format
);
2372 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2378 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2379 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2383 pa_assert(size
> 0);
2386 ret
= vsnprintf(str
, size
, format
, ap
);
2393 if ((size_t) ret
> size
-1)
2396 return (size_t) ret
;
2399 /* Truncate the specified string, but guarantee that the string
2400 * returned still validates as UTF8 */
2401 char *pa_truncate_utf8(char *c
, size_t l
) {
2403 pa_assert(pa_utf8_valid(c
));
2410 while (l
> 0 && !pa_utf8_valid(c
))
2416 char *pa_getcwd(void) {
2420 char *p
= pa_xmalloc(l
);
2424 if (errno
!= ERANGE
)
2432 void *pa_will_need(const void *p
, size_t l
) {
2433 #ifdef RLIMIT_MEMLOCK
2444 a
= PA_PAGE_ALIGN_PTR(p
);
2445 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2447 #ifdef HAVE_POSIX_MADVISE
2448 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2449 pa_log_debug("posix_madvise() worked fine!");
2454 /* Most likely the memory was not mmap()ed from a file and thus
2455 * madvise() didn't work, so let's misuse mlock() do page this
2456 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2457 * inviting, the man page of mlock() tells us: "All pages that
2458 * contain a part of the specified address range are guaranteed to
2459 * be resident in RAM when the call returns successfully." */
2461 #ifdef RLIMIT_MEMLOCK
2462 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2464 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2465 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
));
2470 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2472 bs
= PA_PAGE_SIZE
*4;
2475 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2478 while (size
> 0 && bs
> 0) {
2483 if (mlock(a
, bs
) < 0) {
2484 bs
= PA_PAGE_ALIGN(bs
/ 2);
2488 pa_assert_se(munlock(a
, bs
) == 0);
2490 a
= (const uint8_t*) a
+ bs
;
2496 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2498 pa_log_debug("mlock() worked fine!");
2503 void pa_close_pipe(int fds
[2]) {
2507 pa_assert_se(pa_close(fds
[0]) == 0);
2510 pa_assert_se(pa_close(fds
[1]) == 0);
2512 fds
[0] = fds
[1] = -1;
2515 char *pa_readlink(const char *p
) {
2516 #ifdef HAVE_READLINK
2525 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2530 if ((size_t) n
< l
-1) {
2543 int pa_close_all(int except_fd
, ...) {
2548 va_start(ap
, except_fd
);
2551 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2556 p
= pa_xnew(int, n
+1);
2558 va_start(ap
, except_fd
);
2561 if (except_fd
>= 0) {
2565 while ((fd
= va_arg(ap
, int)) >= 0)
2572 r
= pa_close_allv(p
);
2578 int pa_close_allv(const int except_fds
[]) {
2587 if ((d
= opendir("/proc/self/fd"))) {
2591 while ((de
= readdir(d
))) {
2597 if (de
->d_name
[0] == '.')
2601 l
= strtol(de
->d_name
, &e
, 10);
2602 if (errno
!= 0 || !e
|| *e
) {
2610 if ((long) fd
!= l
) {
2623 for (i
= 0; except_fds
[i
] >= 0; i
++)
2624 if (except_fds
[i
] == fd
) {
2632 if (pa_close(fd
) < 0) {
2633 saved_errno
= errno
;
2635 errno
= saved_errno
;
2647 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2648 maxfd
= (int) rl
.rlim_max
;
2650 maxfd
= sysconf(_SC_OPEN_MAX
);
2652 for (fd
= 3; fd
< maxfd
; fd
++) {
2657 for (i
= 0; except_fds
[i
] >= 0; i
++)
2658 if (except_fds
[i
] == fd
) {
2666 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2669 #endif /* !OS_IS_WIN32 */
2674 int pa_unblock_sigs(int except
, ...) {
2679 va_start(ap
, except
);
2682 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2687 p
= pa_xnew(int, n
+1);
2689 va_start(ap
, except
);
2696 while ((sig
= va_arg(ap
, int)) >= 0)
2703 r
= pa_unblock_sigsv(p
);
2709 int pa_unblock_sigsv(const int except
[]) {
2714 if (sigemptyset(&ss
) < 0)
2717 for (i
= 0; except
[i
] > 0; i
++)
2718 if (sigaddset(&ss
, except
[i
]) < 0)
2721 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2727 int pa_reset_sigs(int except
, ...) {
2732 va_start(ap
, except
);
2735 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2740 p
= pa_xnew(int, n
+1);
2742 va_start(ap
, except
);
2749 while ((sig
= va_arg(ap
, int)) >= 0)
2756 r
= pa_reset_sigsv(p
);
2762 int pa_reset_sigsv(const int except
[]) {
2766 for (sig
= 1; sig
< NSIG
; sig
++) {
2778 for (i
= 0; except
[i
] > 0; i
++) {
2779 if (sig
== except
[i
]) {
2788 struct sigaction sa
;
2790 memset(&sa
, 0, sizeof(sa
));
2791 sa
.sa_handler
= SIG_DFL
;
2793 /* On Linux the first two RT signals are reserved by
2794 * glibc, and sigaction() will return EINVAL for them. */
2795 if ((sigaction(sig
, &sa
, NULL
) < 0))
2796 if (errno
!= EINVAL
)
2805 void pa_set_env(const char *key
, const char *value
) {
2809 /* This is not thread-safe */
2812 SetEnvironmentVariable(key
, value
);
2814 setenv(key
, value
, 1);
2818 void pa_set_env_and_record(const char *key
, const char *value
) {
2822 /* This is not thread-safe */
2824 pa_set_env(key
, value
);
2825 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2828 void pa_unset_env_recorded(void) {
2830 /* This is not thread-safe */
2835 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2841 SetEnvironmentVariable(s
, NULL
);
2849 bool pa_in_system_mode(void) {
2852 if (!(e
= getenv("PULSE_SYSTEM")))
2858 /* Checks a whitespace-separated list of words in haystack for needle */
2859 bool pa_str_in_list_spaces(const char *haystack
, const char *needle
) {
2861 const char *state
= NULL
;
2863 if (!haystack
|| !needle
)
2866 while ((s
= pa_split_spaces(haystack
, &state
))) {
2867 if (pa_streq(needle
, s
)) {
2878 char *pa_get_user_name_malloc(void) {
2882 #ifdef _SC_LOGIN_NAME_MAX
2883 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2889 u
= pa_xnew(char, k
+1);
2891 if (!(pa_get_user_name(u
, k
))) {
2899 char *pa_get_host_name_malloc(void) {
2908 if (!pa_get_host_name(c
, l
)) {
2910 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2913 } else if (strlen(c
) < l
-1) {
2921 u
= pa_utf8_filter(c
);
2926 /* Hmm, the hostname is as long the space we offered the
2927 * function, we cannot know if it fully fit in, so let's play
2928 * safe and retry. */
2937 char *pa_machine_id(void) {
2941 /* The returned value is supposed be some kind of ascii identifier
2942 * that is unique and stable across reboots. */
2944 /* First we try the /etc/machine-id, which is the best option we
2945 * have, since it fits perfectly our needs and is not as volatile
2946 * as the hostname which might be set from dhcp. */
2948 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r")) ||
2949 (f
= pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK
, "r"))) {
2950 char ln
[34] = "", *r
;
2952 r
= fgets(ln
, sizeof(ln
)-1, f
);
2958 return pa_utf8_filter(ln
);
2961 if ((h
= pa_get_host_name_malloc()))
2964 #if !defined(OS_IS_WIN32) && !defined(__ANDROID__)
2965 /* If no hostname was set we use the POSIX hostid. It's usually
2966 * the IPv4 address. Might not be that stable. */
2967 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2973 char *pa_session_id(void) {
2976 e
= getenv("XDG_SESSION_ID");
2980 return pa_utf8_filter(e
);
2983 char *pa_uname_string(void) {
2987 pa_assert_se(uname(&u
) >= 0);
2989 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2995 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2996 pa_assert_se(GetVersionEx(&i
));
2998 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
3002 #ifdef HAVE_VALGRIND_MEMCHECK_H
3003 bool pa_in_valgrind(void) {
3006 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
3007 * here instead of really checking whether we run in valgrind or
3011 b
= getenv("VALGRIND") ? 2 : 1;
3017 unsigned pa_gcd(unsigned a
, unsigned b
) {
3028 void pa_reduce(unsigned *num
, unsigned *den
) {
3030 unsigned gcd
= pa_gcd(*num
, *den
);
3038 pa_assert(pa_gcd(*num
, *den
) == 1);
3041 unsigned pa_ncpus(void) {
3044 #ifdef _SC_NPROCESSORS_CONF
3045 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
3050 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
3053 char *pa_replace(const char*s
, const char*a
, const char *b
) {
3062 sb
= pa_strbuf_new();
3067 if (!(p
= strstr(s
, a
)))
3070 pa_strbuf_putsn(sb
, s
, p
-s
);
3071 pa_strbuf_puts(sb
, b
);
3075 pa_strbuf_puts(sb
, s
);
3077 return pa_strbuf_tostring_free(sb
);
3080 char *pa_escape(const char *p
, const char *chars
) {
3083 pa_strbuf
*buf
= pa_strbuf_new();
3085 for (s
= p
; *s
; ++s
) {
3087 pa_strbuf_putc(buf
, '\\');
3089 for (c
= chars
; *c
; ++c
) {
3091 pa_strbuf_putc(buf
, '\\');
3096 pa_strbuf_putc(buf
, *s
);
3099 return pa_strbuf_tostring_free(buf
);
3102 char *pa_unescape(char *p
) {
3104 bool escaped
= false;
3106 for (s
= p
, d
= p
; *s
; s
++) {
3107 if (!escaped
&& *s
== '\\') {
3121 char *pa_realpath(const char *path
) {
3125 /* We want only absolute paths */
3126 if (path
[0] != '/') {
3131 #if defined(__GLIBC__)
3135 if (!(r
= realpath(path
, NULL
)))
3138 /* We copy this here in case our pa_xmalloc() is not
3139 * implemented on top of libc malloc() */
3143 #elif defined(PATH_MAX)
3146 path_buf
= pa_xmalloc(PATH_MAX
);
3148 #if defined(OS_IS_WIN32)
3149 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
3154 if (!(t
= realpath(path
, path_buf
))) {
3161 #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."
3167 void pa_disable_sigpipe(void) {
3170 struct sigaction sa
;
3174 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
3175 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3179 sa
.sa_handler
= SIG_IGN
;
3181 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
3182 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3188 void pa_xfreev(void**a
) {
3194 for (p
= a
; *p
; p
++)
3200 char **pa_split_spaces_strv(const char *s
) {
3202 unsigned i
= 0, n
= 8;
3203 const char *state
= NULL
;
3205 t
= pa_xnew(char*, n
);
3206 while ((e
= pa_split_spaces(s
, &state
))) {
3211 t
= pa_xrenew(char*, t
, n
);
3224 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
3227 if (pa_is_path_absolute(path
))
3228 return pa_xstrdup(path
);
3230 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
3233 size_t pa_pipe_buf(int fd
) {
3238 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3249 void pa_reset_personality(void) {
3251 #if defined(__linux__) && !defined(__ANDROID__)
3252 if (personality(PER_LINUX
) < 0)
3253 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3258 bool pa_run_from_build_tree(void) {
3260 static bool b
= false;
3263 if ((rp
= pa_readlink("/proc/self/exe"))) {
3264 b
= pa_startswith(rp
, PA_BUILDDIR
);
3272 const char *pa_get_temp_dir(void) {
3275 if ((t
= getenv("TMPDIR")) &&
3276 pa_is_path_absolute(t
))
3279 if ((t
= getenv("TMP")) &&
3280 pa_is_path_absolute(t
))
3283 if ((t
= getenv("TEMP")) &&
3284 pa_is_path_absolute(t
))
3287 if ((t
= getenv("TEMPDIR")) &&
3288 pa_is_path_absolute(t
))
3294 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3302 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3305 if (errno
!= EINVAL
)
3309 if ((fd
= open(fn
, flags
, mode
)) < 0)
3313 /* Some implementations might simply ignore O_CLOEXEC if it is not
3314 * understood, make sure FD_CLOEXEC is enabled anyway */
3316 pa_make_fd_cloexec(fd
);
3320 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3324 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3327 if (errno
!= EINVAL
)
3331 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3335 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3336 * not understood, make sure FD_CLOEXEC is enabled anyway */
3338 pa_make_fd_cloexec(fd
);
3342 int pa_pipe_cloexec(int pipefd
[2]) {
3346 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3349 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3354 if ((r
= pipe(pipefd
)) < 0)
3358 pa_make_fd_cloexec(pipefd
[0]);
3359 pa_make_fd_cloexec(pipefd
[1]);
3364 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3368 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3371 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3376 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3380 pa_make_fd_cloexec(fd
);
3384 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3388 m
= pa_sprintf_malloc("%se", mode
);
3391 if ((f
= fopen(path
, m
))) {
3398 if (errno
!= EINVAL
)
3401 if (!(f
= fopen(path
, mode
)))
3405 pa_make_fd_cloexec(fileno(f
));
3409 void pa_nullify_stdfds(void) {
3412 pa_close(STDIN_FILENO
);
3413 pa_close(STDOUT_FILENO
);
3414 pa_close(STDERR_FILENO
);
3416 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3417 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3418 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3425 char *pa_read_line_from_file(const char *fn
) {
3427 char ln
[256] = "", *r
;
3429 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3432 r
= fgets(ln
, sizeof(ln
)-1, f
);
3441 return pa_xstrdup(ln
);
3444 bool pa_running_in_vm(void) {
3446 #if defined(__i386__) || defined(__x86_64__)
3448 /* Both CPUID and DMI are x86 specific interfaces... */
3450 uint32_t eax
= 0x40000000;
3457 const char *const dmi_vendors
[] = {
3458 "/sys/class/dmi/id/sys_vendor",
3459 "/sys/class/dmi/id/board_vendor",
3460 "/sys/class/dmi/id/bios_vendor"
3465 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3468 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3470 if (pa_startswith(s
, "QEMU") ||
3471 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3472 pa_startswith(s
, "VMware") ||
3473 pa_startswith(s
, "VMW") ||
3474 pa_startswith(s
, "Microsoft Corporation") ||
3475 pa_startswith(s
, "innotek GmbH") ||
3476 pa_startswith(s
, "Xen")) {
3488 /* http://lwn.net/Articles/301888/ */
3491 __asm__
__volatile__ (
3492 /* ebx/rbx is being used for PIC! */
3493 " push %%"PA_REG_b
" \n\t"
3495 " mov %%ebx, %1 \n\t"
3496 " pop %%"PA_REG_b
" \n\t"
3498 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3502 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3503 pa_streq(sig
.text
, "KVMKVMKVM") ||
3504 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3505 pa_streq(sig
.text
, "VMwareVMware") ||
3506 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3507 pa_streq(sig
.text
, "Microsoft Hv"))