2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
38 #include <sys/types.h>
42 #ifdef HAVE_LANGINFO_H
47 #include <sys/utsname.h>
50 #if defined(HAVE_REGEX_H)
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
76 #ifdef HAVE_SYS_MMAN_H
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
110 #include <mach/mach_init.h>
111 #include <mach/thread_act.h>
112 #include <mach/thread_policy.h>
113 #include <sys/sysctl.h>
121 #include <sys/personality.h>
124 #include <pulse/xmalloc.h>
125 #include <pulse/util.h>
126 #include <pulse/utf8.h>
128 #include <pulsecore/core-error.h>
129 #include <pulsecore/socket.h>
130 #include <pulsecore/log.h>
131 #include <pulsecore/macro.h>
132 #include <pulsecore/thread.h>
133 #include <pulsecore/strbuf.h>
134 #include <pulsecore/usergroup.h>
135 #include <pulsecore/strlist.h>
136 #include <pulsecore/cpu-x86.h>
137 #include <pulsecore/pipe.h>
139 #include "core-util.h"
141 /* Not all platforms have this */
143 #define MSG_NOSIGNAL 0
146 #define NEWLINE "\r\n"
147 #define WHITESPACE "\n\r \t"
149 static pa_strlist
*recorded_env
= NULL
;
155 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
156 char *pa_win32_get_toplevel(HANDLE handle
) {
157 static char *toplevel
= NULL
;
160 char library_path
[MAX_PATH
];
163 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
166 toplevel
= pa_xstrdup(library_path
);
168 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
172 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
173 if (p
&& pa_streq(p
+ 1, "bin"))
182 /** Make a file descriptor nonblock. Doesn't do any error checking */
183 void pa_make_fd_nonblock(int fd
) {
189 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
191 if (!(v
& O_NONBLOCK
))
192 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
194 #elif defined(OS_IS_WIN32)
196 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
197 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
198 pa_log_warn("Only sockets can be made non-blocking!");
201 pa_log_warn("Non-blocking I/O not supported.!");
206 /* Set the FD_CLOEXEC flag for a fd */
207 void pa_make_fd_cloexec(int fd
) {
213 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
215 if (!(v
& FD_CLOEXEC
))
216 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
221 /** Creates a directory securely. Will create parent directories recursively if
222 * required. This will not update permissions on parent directories if they
223 * already exist, however. */
224 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
, pa_bool_t update_perms
) {
227 pa_bool_t retry
= TRUE
;
237 u
= umask((~m
) & 0777);
243 if (r
< 0 && errno
== ENOENT
&& retry
) {
244 /* If a parent directory in the path doesn't exist, try to create that
245 * first, then try again. */
246 pa_make_secure_parent_dir(dir
, m
, uid
, gid
, FALSE
);
251 if (r
< 0 && errno
!= EEXIST
)
254 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
270 if (fstat(fd
, &st
) < 0) {
271 pa_assert_se(pa_close(fd
) >= 0);
275 if (!S_ISDIR(st
.st_mode
)) {
276 pa_assert_se(pa_close(fd
) >= 0);
285 if (uid
== (uid_t
) -1)
287 if (gid
== (gid_t
) -1)
289 if (fchown(fd
, uid
, gid
) < 0)
294 (void) fchmod(fd
, m
);
297 pa_assert_se(pa_close(fd
) >= 0);
302 if (lstat(dir
, &st
) < 0)
304 if (stat(dir
, &st
) < 0)
309 if (!S_ISDIR(st
.st_mode
) ||
310 (st
.st_uid
!= uid
) ||
311 (st
.st_gid
!= gid
) ||
312 ((st
.st_mode
& 0777) != m
)) {
317 pa_log_warn("Secure directory creation not supported on Win32.");
330 /* Return a newly allocated sting containing the parent directory of the specified file */
331 char *pa_parent_dir(const char *fn
) {
332 char *slash
, *dir
= pa_xstrdup(fn
);
334 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
344 /* Creates a the parent directory of the specified path securely */
345 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
, pa_bool_t update_perms
) {
349 if (!(dir
= pa_parent_dir(fn
)))
352 if (pa_make_secure_dir(dir
, m
, uid
, gid
, update_perms
) < 0)
362 /** Platform independent read function. Necessary since not all
363 * systems treat all file descriptors equal. If type is
364 * non-NULL it is used to cache the type of the fd. This is
365 * useful for making sure that only a single syscall is executed per
366 * function call. The variable pointed to should be initialized to 0
368 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
372 if (!type
|| *type
== 0) {
377 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
380 err
= WSAGetLastError();
381 if (err
!= WSAENOTSOCK
) {
382 /* transparently handle non-blocking sockets, by waiting
384 if (err
== WSAEWOULDBLOCK
) {
388 if (pa_poll(&pfd
, 1, -1) >= 0) {
405 if ((r
= read(fd
, buf
, count
)) < 0)
413 /** Similar to pa_read(), but handles writes */
414 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
416 if (!type
|| *type
== 0) {
424 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
436 err
= WSAGetLastError();
437 if (err
!= WSAENOTSOCK
) {
438 /* transparently handle non-blocking sockets, by waiting
440 if (err
== WSAEWOULDBLOCK
) {
443 pfd
.events
= POLLOUT
;
444 if (pa_poll(&pfd
, 1, -1) >= 0) {
452 if (errno
!= ENOTSOCK
)
463 if ((r
= write(fd
, buf
, count
)) < 0)
471 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
472 * unless EOF is reached or an error occurred */
473 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
489 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
496 data
= (uint8_t*) data
+ r
;
503 /** Similar to pa_loop_read(), but wraps write() */
504 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
520 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
527 data
= (const uint8_t*) data
+ r
;
534 /** Platform independent read function. Necessary since not all
535 * systems treat all file descriptors equal. */
536 int pa_close(int fd
) {
541 if ((ret
= closesocket(fd
)) == 0)
544 if (WSAGetLastError() != WSAENOTSOCK
) {
545 errno
= WSAGetLastError();
553 if ((r
= close(fd
)) < 0)
561 /* Print a warning messages in case that the given signal is not
562 * blocked or trapped */
563 void pa_check_signal_is_blocked(int sig
) {
564 #ifdef HAVE_SIGACTION
568 /* If POSIX threads are supported use thread-aware
569 * pthread_sigmask() function, to check if the signal is
570 * blocked. Otherwise fall back to sigprocmask() */
573 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
575 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
576 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
583 if (sigismember(&set
, sig
))
586 /* Check whether the signal is trapped */
588 if (sigaction(sig
, NULL
, &sa
) < 0) {
589 pa_log("sigaction(): %s", pa_cstrerror(errno
));
593 if (sa
.sa_handler
!= SIG_DFL
)
596 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
597 #else /* HAVE_SIGACTION */
598 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
602 /* The following function is based on an example from the GNU libc
603 * documentation. This function is similar to GNU's asprintf(). */
604 char *pa_sprintf_malloc(const char *format
, ...) {
614 c
= pa_xrealloc(c
, size
);
616 va_start(ap
, format
);
617 r
= vsnprintf(c
, size
, format
, ap
);
622 if (r
> -1 && (size_t) r
< size
)
625 if (r
> -1) /* glibc 2.1 */
632 /* Same as the previous function, but use a va_list instead of an
634 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
644 c
= pa_xrealloc(c
, size
);
647 r
= vsnprintf(c
, size
, format
, aq
);
652 if (r
> -1 && (size_t) r
< size
)
655 if (r
> -1) /* glibc 2.1 */
662 /* Similar to OpenBSD's strlcpy() function */
663 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
681 #ifdef _POSIX_PRIORITY_SCHEDULING
682 static int set_scheduler(int rtprio
) {
684 struct sched_param sp
;
688 #ifdef HAVE_SYS_RESOURCE_H
694 dbus_error_init(&error
);
698 sp
.sched_priority
= rtprio
;
700 #ifdef SCHED_RESET_ON_FORK
701 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
702 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
707 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
708 pa_log_debug("SCHED_RR worked.");
711 #endif /* HAVE_SCHED_H */
714 /* Try to talk to RealtimeKit */
716 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
717 pa_log("Failed to connect to system bus: %s\n", error
.message
);
718 dbus_error_free(&error
);
723 /* We need to disable exit on disconnect because otherwise
724 * dbus_shutdown will kill us. See
725 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
726 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
728 rttime
= rtkit_get_rttime_usec_max(bus
);
730 #ifdef HAVE_SYS_RESOURCE_H
731 r
= getrlimit(RLIMIT_RTTIME
, &rl
);
733 if (r
>= 0 && (long long) rl
.rlim_max
> rttime
) {
734 pa_log_info("Clamping rlimit-rttime to %lld for RealtimeKit\n", rttime
);
735 rl
.rlim_cur
= rl
.rlim_max
= rttime
;
736 r
= setrlimit(RLIMIT_RTTIME
, &rl
);
739 pa_log("setrlimit() failed: %s", pa_cstrerror(errno
));
742 r
= rtkit_make_realtime(bus
, 0, rtprio
);
743 dbus_connection_close(bus
);
744 dbus_connection_unref(bus
);
747 pa_log_debug("RealtimeKit worked.");
753 dbus_connection_close(bus
);
754 dbus_connection_unref(bus
);
766 /* Make the current thread a realtime thread, and acquire the highest
767 * rtprio we can get that is less or equal the specified parameter. If
768 * the thread is already realtime, don't do anything. */
769 int pa_make_realtime(int rtprio
) {
771 #if defined(OS_IS_DARWIN)
772 struct thread_time_constraint_policy ttcpolicy
;
774 size_t size
= sizeof(freq
);
777 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
779 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
783 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
785 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
786 ttcpolicy
.period
= freq
/ 160;
787 ttcpolicy
.computation
= freq
/ 3300;
788 ttcpolicy
.constraint
= freq
/ 2200;
789 ttcpolicy
.preemptible
= 1;
791 ret
= thread_policy_set(mach_thread_self(),
792 THREAD_TIME_CONSTRAINT_POLICY
,
793 (thread_policy_t
) &ttcpolicy
,
794 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
796 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
800 pa_log_info("Successfully acquired real-time thread priority.");
803 #elif defined(_POSIX_PRIORITY_SCHEDULING)
806 if (set_scheduler(rtprio
) >= 0) {
807 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
811 for (p
= rtprio
-1; p
>= 1; p
--)
812 if (set_scheduler(p
) >= 0) {
813 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
816 #elif defined(OS_IS_WIN32)
817 /* Windows only allows realtime scheduling to be set on a per process basis.
818 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
819 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
820 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
824 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
829 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
833 #ifdef HAVE_SYS_RESOURCE_H
834 static int set_nice(int nice_level
) {
840 dbus_error_init(&error
);
843 #ifdef HAVE_SYS_RESOURCE_H
844 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
845 pa_log_debug("setpriority() worked.");
851 /* Try to talk to RealtimeKit */
853 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
854 pa_log("Failed to connect to system bus: %s\n", error
.message
);
855 dbus_error_free(&error
);
860 /* We need to disable exit on disconnect because otherwise
861 * dbus_shutdown will kill us. See
862 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
863 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
865 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
866 dbus_connection_unref(bus
);
869 pa_log_debug("RealtimeKit worked.");
880 /* Raise the priority of the current process as much as possible that
881 * is <= the specified nice level..*/
882 int pa_raise_priority(int nice_level
) {
884 #ifdef HAVE_SYS_RESOURCE_H
887 if (set_nice(nice_level
) >= 0) {
888 pa_log_info("Successfully gained nice level %i.", nice_level
);
892 for (n
= nice_level
+1; n
< 0; n
++)
893 if (set_nice(n
) >= 0) {
894 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
898 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
903 if (nice_level
< 0) {
904 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
905 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
910 pa_log_info("Successfully gained high priority class.");
917 /* Reset the priority to normal, inverting the changes made by
918 * pa_raise_priority() and pa_make_realtime()*/
919 void pa_reset_priority(void) {
920 #ifdef HAVE_SYS_RESOURCE_H
921 struct sched_param sp
;
923 setpriority(PRIO_PROCESS
, 0, 0);
926 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
930 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
934 int pa_match(const char *expr
, const char *v
) {
939 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
944 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
946 else if (k
== REG_NOMATCH
)
959 /* Try to parse a boolean string value.*/
960 int pa_parse_boolean(const char *v
) {
963 /* First we check language independent */
964 if (pa_streq(v
, "1") || !strcasecmp(v
, "y") || !strcasecmp(v
, "t")
965 || !strcasecmp(v
, "yes") || !strcasecmp(v
, "true") || !strcasecmp(v
, "on"))
967 else if (pa_streq(v
, "0") || !strcasecmp(v
, "n") || !strcasecmp(v
, "f")
968 || !strcasecmp(v
, "no") || !strcasecmp(v
, "false") || !strcasecmp(v
, "off"))
971 #ifdef HAVE_LANGINFO_H
974 /* And then we check language dependent */
975 if ((expr
= nl_langinfo(YESEXPR
)))
977 if (pa_match(expr
, v
) > 0)
980 if ((expr
= nl_langinfo(NOEXPR
)))
982 if (pa_match(expr
, v
) > 0)
991 /* Try to parse a volume string to pa_volume_t. The allowed formats are:
992 * db, % and unsigned integer */
993 int pa_parse_volume(const char *v
, pa_volume_t
*volume
) {
1007 memcpy(str
, v
, len
+ 1);
1009 if (str
[len
- 1] == '%') {
1010 str
[len
- 1] = '\0';
1011 if (pa_atou(str
, &i
) == 0) {
1012 *volume
= PA_CLAMP_VOLUME((uint64_t) PA_VOLUME_NORM
* i
/ 100);
1015 } else if (len
> 2 && (str
[len
- 1] == 'b' || str
[len
- 1] == 'B') &&
1016 (str
[len
- 2] == 'd' || str
[len
- 2] == 'D')) {
1017 str
[len
- 2] = '\0';
1018 if (pa_atod(str
, &d
) == 0) {
1019 *volume
= pa_sw_volume_from_dB(d
);
1023 if (pa_atou(v
, &i
) == 0) {
1024 *volume
= PA_CLAMP_VOLUME(i
);
1033 /* Split the specified string wherever one of the strings in delimiter
1034 * occurs. Each time it is called returns a newly allocated string
1035 * with pa_xmalloc(). The variable state points to, should be
1036 * initialized to NULL before the first call. */
1037 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
1038 const char *current
= *state
? *state
: c
;
1044 l
= strcspn(current
, delimiter
);
1050 return pa_xstrndup(current
, l
);
1053 /* Split the specified string wherever one of the strings in delimiter
1054 * occurs. Each time it is called returns a pointer to the substring within the
1055 * string and the length in 'n'. Note that the resultant string cannot be used
1056 * as-is without the length parameter, since it is merely pointing to a point
1057 * within the original string. The variable state points to, should be
1058 * initialized to NULL before the first call. */
1059 const char *pa_split_in_place(const char *c
, const char *delimiter
, int *n
, const char**state
) {
1060 const char *current
= *state
? *state
: c
;
1066 l
= strcspn(current
, delimiter
);
1076 /* Split a string into words. Otherwise similar to pa_split(). */
1077 char *pa_split_spaces(const char *c
, const char **state
) {
1078 const char *current
= *state
? *state
: c
;
1081 if (!*current
|| *c
== 0)
1084 current
+= strspn(current
, WHITESPACE
);
1085 l
= strcspn(current
, WHITESPACE
);
1089 return pa_xstrndup(current
, l
);
1092 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
1094 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
1095 const char *pa_sig2str(int sig
) {
1108 char buf
[SIG2STR_MAX
];
1110 if (sig2str(sig
, buf
) == 0) {
1111 pa_xfree(PA_STATIC_TLS_GET(signame
));
1112 t
= pa_sprintf_malloc("SIG%s", buf
);
1113 PA_STATIC_TLS_SET(signame
, t
);
1121 case SIGHUP
: return "SIGHUP";
1123 case SIGINT
: return "SIGINT";
1125 case SIGQUIT
: return "SIGQUIT";
1127 case SIGILL
: return "SIGULL";
1129 case SIGTRAP
: return "SIGTRAP";
1131 case SIGABRT
: return "SIGABRT";
1133 case SIGBUS
: return "SIGBUS";
1135 case SIGFPE
: return "SIGFPE";
1137 case SIGKILL
: return "SIGKILL";
1140 case SIGUSR1
: return "SIGUSR1";
1142 case SIGSEGV
: return "SIGSEGV";
1144 case SIGUSR2
: return "SIGUSR2";
1147 case SIGPIPE
: return "SIGPIPE";
1150 case SIGALRM
: return "SIGALRM";
1152 case SIGTERM
: return "SIGTERM";
1154 case SIGSTKFLT
: return "SIGSTKFLT";
1157 case SIGCHLD
: return "SIGCHLD";
1160 case SIGCONT
: return "SIGCONT";
1163 case SIGSTOP
: return "SIGSTOP";
1166 case SIGTSTP
: return "SIGTSTP";
1169 case SIGTTIN
: return "SIGTTIN";
1172 case SIGTTOU
: return "SIGTTOU";
1175 case SIGURG
: return "SIGURG";
1178 case SIGXCPU
: return "SIGXCPU";
1181 case SIGXFSZ
: return "SIGXFSZ";
1184 case SIGVTALRM
: return "SIGVTALRM";
1187 case SIGPROF
: return "SIGPROF";
1190 case SIGWINCH
: return "SIGWINCH";
1193 case SIGIO
: return "SIGIO";
1196 case SIGPWR
: return "SIGPWR";
1199 case SIGSYS
: return "SIGSYS";
1204 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1205 pa_xfree(PA_STATIC_TLS_GET(signame
));
1206 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1207 PA_STATIC_TLS_SET(signame
, t
);
1216 pa_xfree(PA_STATIC_TLS_GET(signame
));
1217 t
= pa_sprintf_malloc("SIG%i", sig
);
1218 PA_STATIC_TLS_SET(signame
, t
);
1224 /* Check whether the specified GID and the group name match */
1225 static int is_group(gid_t gid
, const char *name
) {
1226 struct group
*group
= NULL
;
1230 if (!(group
= pa_getgrgid_malloc(gid
))) {
1234 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1239 r
= pa_streq(name
, group
->gr_name
);
1242 pa_getgrgid_free(group
);
1247 /* Check the current user is member of the specified group */
1248 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1249 GETGROUPS_T
*gids
, tgid
;
1250 long n
= sysconf(_SC_NGROUPS_MAX
);
1255 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1257 if ((n
= getgroups((int) n
, gids
)) < 0) {
1258 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1262 for (i
= 0; i
< n
; i
++) {
1264 if ((k
= is_group(gids
[i
], name
)) < 0)
1273 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1289 /* Check whether the specific user id is a member of the specified group */
1290 int pa_uid_in_group(uid_t uid
, const char *name
) {
1291 struct group
*group
= NULL
;
1296 if (!(group
= pa_getgrnam_malloc(name
))) {
1303 for (i
= group
->gr_mem
; *i
; i
++) {
1304 struct passwd
*pw
= NULL
;
1307 if (!(pw
= pa_getpwnam_malloc(*i
)))
1310 if (pw
->pw_uid
== uid
)
1313 pa_getpwnam_free(pw
);
1320 pa_getgrnam_free(group
);
1325 /* Get the GID of a given group, return (gid_t) -1 on failure. */
1326 gid_t
pa_get_gid_of_group(const char *name
) {
1327 gid_t ret
= (gid_t
) -1;
1328 struct group
*gr
= NULL
;
1331 if (!(gr
= pa_getgrnam_malloc(name
))) {
1340 pa_getgrnam_free(gr
);
1344 int pa_check_in_group(gid_t g
) {
1345 gid_t gids
[NGROUPS_MAX
];
1348 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1358 #else /* HAVE_GRP_H */
1360 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1366 int pa_uid_in_group(uid_t uid
, const char *name
) {
1371 gid_t
pa_get_gid_of_group(const char *name
) {
1376 int pa_check_in_group(gid_t g
) {
1383 /* Lock or unlock a file entirely.
1384 (advisory on UNIX, mandatory on Windows) */
1385 int pa_lock_fd(int fd
, int b
) {
1387 struct flock f_lock
;
1389 /* Try a R/W lock first */
1391 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1392 f_lock
.l_whence
= SEEK_SET
;
1396 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1399 /* Perhaps the file descriptor was opened for read only, than try again with a read lock. */
1400 if (b
&& errno
== EBADF
) {
1401 f_lock
.l_type
= F_RDLCK
;
1402 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1406 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1410 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1412 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1414 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1417 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1419 /* FIXME: Needs to set errno! */
1425 /* Remove trailing newlines from a string */
1426 char* pa_strip_nl(char *s
) {
1429 s
[strcspn(s
, NEWLINE
)] = 0;
1433 char *pa_strip(char *s
) {
1436 /* Drops trailing whitespace. Modifies the string in
1437 * place. Returns pointer to first non-space character */
1439 s
+= strspn(s
, WHITESPACE
);
1441 for (e
= s
; *e
; e
++)
1442 if (!strchr(WHITESPACE
, *e
))
1453 /* Create a temporary lock file and lock it. */
1454 int pa_lock_lockfile(const char *fn
) {
1461 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1465 , S_IRUSR
|S_IWUSR
)) < 0) {
1466 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1470 if (pa_lock_fd(fd
, 1) < 0) {
1471 pa_log_warn("Failed to lock file '%s'.", fn
);
1475 if (fstat(fd
, &st
) < 0) {
1476 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1480 /* Check whether the file has been removed meanwhile. When yes,
1481 * restart this loop, otherwise, we're done */
1482 if (st
.st_nlink
>= 1)
1485 if (pa_lock_fd(fd
, 0) < 0) {
1486 pa_log_warn("Failed to unlock file '%s'.", fn
);
1490 if (pa_close(fd
) < 0) {
1491 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1502 int saved_errno
= errno
;
1504 errno
= saved_errno
;
1510 /* Unlock a temporary lock file */
1511 int pa_unlock_lockfile(const char *fn
, int fd
) {
1516 if (unlink(fn
) < 0) {
1517 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1522 if (pa_lock_fd(fd
, 0) < 0) {
1523 pa_log_warn("Failed to unlock file '%s'.", fn
);
1527 if (pa_close(fd
) < 0) {
1528 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1535 static char *get_config_home(char *home
) {
1538 t
= getenv("XDG_CONFIG_HOME");
1540 return pa_xstrdup(t
);
1542 return pa_sprintf_malloc("%s" PA_PATH_SEP
".config", home
);
1545 static int check_ours(const char *p
) {
1550 if (stat(p
, &st
) < 0)
1554 if (st
.st_uid
!= getuid())
1561 static char *get_pulse_home(void) {
1562 char *h
, *ret
, *config_home
;
1565 h
= pa_get_home_dir_malloc();
1567 pa_log_error("Failed to get home directory.");
1572 if (t
< 0 && t
!= -ENOENT
) {
1573 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t
));
1578 /* If the old directory exists, use it. */
1579 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1580 if (access(ret
, F_OK
) >= 0) {
1586 /* Otherwise go for the XDG compliant directory. */
1587 config_home
= get_config_home(h
);
1589 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", config_home
);
1595 char *pa_get_state_dir(void) {
1598 /* The state directory shall contain dynamic data that should be
1599 * kept across reboots, and is private to this user */
1601 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1602 if (!(d
= get_pulse_home()))
1605 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1606 * dir then this will break. */
1608 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1609 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1617 char *pa_get_home_dir_malloc(void) {
1619 size_t allocated
= 128;
1622 homedir
= pa_xmalloc(allocated
);
1624 if (!pa_get_home_dir(homedir
, allocated
)) {
1629 if (strlen(homedir
) < allocated
- 1)
1639 char *pa_get_binary_name_malloc(void) {
1641 size_t allocated
= 128;
1644 t
= pa_xmalloc(allocated
);
1646 if (!pa_get_binary_name(t
, allocated
)) {
1651 if (strlen(t
) < allocated
- 1)
1661 static char* make_random_dir(mode_t m
) {
1662 static const char table
[] =
1663 "abcdefghijklmnopqrstuvwxyz"
1664 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1670 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1671 pathlen
= strlen(fn
);
1679 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1680 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1682 u
= umask((~m
) & 0777);
1689 saved_errno
= errno
;
1691 errno
= saved_errno
;
1696 if (errno
!= EEXIST
) {
1697 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1704 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1707 if (!(p
= make_random_dir(m
)))
1711 if (symlink(p
, k
) < 0) {
1712 int saved_errno
= errno
;
1714 if (errno
!= EEXIST
)
1715 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1720 errno
= saved_errno
;
1732 char *pa_get_runtime_dir(void) {
1733 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1736 /* The runtime directory shall contain dynamic data that needs NOT
1737 * to be kept across reboots and is usually private to the user,
1738 * except in system mode, where it might be accessible by other
1739 * users, too. Since we need POSIX locking and UNIX sockets in
1740 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1741 * set create a directory in $HOME and link it to a random subdir
1742 * in /tmp, if it was not explicitly configured. */
1744 m
= pa_in_system_mode() ? 0755U : 0700U;
1746 /* Use the explicitly configured value if it is set */
1747 d
= getenv("PULSE_RUNTIME_PATH");
1750 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1751 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1755 return pa_xstrdup(d
);
1758 /* Use the XDG standard for the runtime directory. */
1759 d
= getenv("XDG_RUNTIME_DIR");
1761 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", d
);
1763 if (pa_make_secure_dir(k
, m
, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1764 pa_log_error("Failed to create secure directory (%s): %s", k
, pa_cstrerror(errno
));
1771 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1772 d
= get_pulse_home();
1776 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1, TRUE
) < 0) {
1777 pa_log_error("Failed to create secure directory (%s): %s", d
, pa_cstrerror(errno
));
1782 mid
= pa_machine_id();
1788 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1793 /* OK, first let's check if the "runtime" symlink already exists */
1798 if (errno
!= ENOENT
) {
1799 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1804 /* Hmm, so the runtime directory didn't exist yet, so let's
1805 * create one in /tmp and symlink that to it */
1807 if (make_random_dir_and_link(0700, k
) < 0) {
1809 /* Mhmm, maybe another process was quicker than us,
1810 * let's check if that was valid */
1811 if (errno
== EEXIST
)
1817 /* No symlink possible, so let's just create the runtime directly
1818 * Do not check again if it exists since it cannot be a symlink */
1819 if (mkdir(k
) < 0 && errno
!= EEXIST
)
1826 /* Make sure that this actually makes sense */
1827 if (!pa_is_path_absolute(p
)) {
1828 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1833 /* Hmm, so this symlink is still around, make sure nobody fools us */
1837 if (lstat(p
, &st
) < 0) {
1839 if (errno
!= ENOENT
) {
1840 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1846 if (S_ISDIR(st
.st_mode
) &&
1847 (st
.st_uid
== getuid()) &&
1848 ((st
.st_mode
& 0777) == 0700)) {
1854 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1862 /* Hmm, so the link points to some nonexisting or invalid
1863 * dir. Let's replace it by a new link. We first create a
1864 * temporary link and then rename that to allow concurrent
1865 * execution of this function. */
1867 t
= pa_sprintf_malloc("%s.tmp", k
);
1869 if (make_random_dir_and_link(0700, t
) < 0) {
1871 if (errno
!= EEXIST
) {
1872 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1879 /* Hmm, someone else was quicker then us. Let's give
1880 * him some time to finish, and retry. */
1885 /* OK, we succeeded in creating the temporary symlink, so
1886 * let's rename it */
1887 if (rename(t
, k
) < 0) {
1888 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1904 /* Try to open a configuration file. If "env" is specified, open the
1905 * value of the specified environment variable. Otherwise look for a
1906 * file "local" in the home directory or a file "global" in global
1907 * file system. If "result" is non-NULL, a pointer to a newly
1908 * allocated buffer containing the used configuration file is
1910 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1914 if (env
&& (fn
= getenv(env
))) {
1915 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1917 *result
= pa_xstrdup(fn
);
1922 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1931 if ((e
= getenv("PULSE_CONFIG_PATH"))) {
1932 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1933 f
= pa_fopen_cloexec(fn
, "r");
1934 } else if ((h
= pa_get_home_dir_malloc())) {
1935 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1936 f
= pa_fopen_cloexec(fn
, "r");
1939 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".config/pulse" PA_PATH_SEP
"%s", h
, local
);
1940 f
= pa_fopen_cloexec(fn
, "r");
1948 *result
= pa_xstrdup(fn
);
1954 if (errno
!= ENOENT
) {
1955 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1967 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1968 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1969 pa_win32_get_toplevel(NULL
),
1970 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1973 gfn
= pa_xstrdup(global
);
1975 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1990 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1993 if (env
&& (fn
= getenv(env
))) {
1994 if (access(fn
, R_OK
) == 0)
1995 return pa_xstrdup(fn
);
1997 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
2006 if ((e
= getenv("PULSE_CONFIG_PATH")))
2007 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
2008 else if ((h
= pa_get_home_dir_malloc())) {
2009 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
2014 if (access(fn
, R_OK
) == 0) {
2015 char *r
= pa_xstrdup(fn
);
2020 if (errno
!= ENOENT
) {
2021 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
2033 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
2034 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
2035 pa_win32_get_toplevel(NULL
),
2036 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
2039 gfn
= pa_xstrdup(global
);
2041 if (access(gfn
, R_OK
) == 0)
2051 /* Format the specified data as a hexademical string */
2052 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
2053 size_t i
= 0, j
= 0;
2054 const char hex
[] = "0123456789abcdef";
2058 pa_assert(slength
> 0);
2060 while (j
+2 < slength
&& i
< dlength
) {
2061 s
[j
++] = hex
[*d
>> 4];
2062 s
[j
++] = hex
[*d
& 0xF];
2068 s
[j
< slength
? j
: slength
] = 0;
2072 /* Convert a hexadecimal digit to a number or -1 if invalid */
2073 static int hexc(char c
) {
2074 if (c
>= '0' && c
<= '9')
2077 if (c
>= 'A' && c
<= 'F')
2078 return c
- 'A' + 10;
2080 if (c
>= 'a' && c
<= 'f')
2081 return c
- 'a' + 10;
2087 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
2088 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
2094 while (j
< dlength
&& *p
) {
2097 if ((b
= hexc(*(p
++))) < 0)
2100 d
[j
] = (uint8_t) (b
<< 4);
2105 if ((b
= hexc(*(p
++))) < 0)
2108 d
[j
] |= (uint8_t) b
;
2115 /* Returns nonzero when *s starts with *pfx */
2116 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
2124 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
2127 /* Returns nonzero when *s ends with *sfx */
2128 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
2137 return l1
>= l2
&& pa_streq(s
+ l1
- l2
, sfx
);
2140 pa_bool_t
pa_is_path_absolute(const char *fn
) {
2146 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
2150 char *pa_make_path_absolute(const char *p
) {
2156 if (pa_is_path_absolute(p
))
2157 return pa_xstrdup(p
);
2159 if (!(cwd
= pa_getcwd()))
2160 return pa_xstrdup(p
);
2162 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2167 /* If fn is NULL, return the PulseAudio runtime or state dir (depending on the
2168 * rt parameter). If fn is non-NULL and starts with /, return fn. Otherwise,
2169 * append fn to the runtime/state dir and return it. */
2170 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
2173 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2176 char *r
, *canonical_rtp
;
2178 if (pa_is_path_absolute(fn
)) {
2180 return pa_xstrdup(fn
);
2186 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2187 if ((canonical_rtp
= pa_realpath(rtp
))) {
2188 if (strlen(rtp
) >= strlen(canonical_rtp
))
2191 pa_xfree(canonical_rtp
);
2192 canonical_rtp
= rtp
;
2195 canonical_rtp
= rtp
;
2200 if (!(mid
= pa_machine_id())) {
2201 pa_xfree(canonical_rtp
);
2205 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", canonical_rtp
, mid
, fn
);
2208 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", canonical_rtp
, fn
);
2210 pa_xfree(canonical_rtp
);
2216 char *pa_runtime_path(const char *fn
) {
2217 return get_path(fn
, FALSE
, TRUE
);
2220 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2221 return get_path(fn
, appendmid
, FALSE
);
2224 /* Convert the string s to a signed integer in *ret_i */
2225 int pa_atoi(const char *s
, int32_t *ret_i
) {
2231 if (pa_atol(s
, &l
) < 0)
2234 if ((int32_t) l
!= l
) {
2239 *ret_i
= (int32_t) l
;
2244 /* Convert the string s to an unsigned integer in *ret_u */
2245 int pa_atou(const char *s
, uint32_t *ret_u
) {
2253 l
= strtoul(s
, &x
, 0);
2255 if (!x
|| *x
|| errno
) {
2261 if ((uint32_t) l
!= l
) {
2266 *ret_u
= (uint32_t) l
;
2271 /* Convert the string s to a signed long integer in *ret_l. */
2272 int pa_atol(const char *s
, long *ret_l
) {
2280 l
= strtol(s
, &x
, 0);
2282 if (!x
|| *x
|| errno
) {
2293 #ifdef HAVE_STRTOF_L
2294 static locale_t c_locale
= NULL
;
2296 static void c_locale_destroy(void) {
2297 freelocale(c_locale
);
2301 int pa_atod(const char *s
, double *ret_d
) {
2308 /* This should be locale independent */
2310 #ifdef HAVE_STRTOF_L
2314 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2315 atexit(c_locale_destroy
);
2321 f
= strtod_l(s
, &x
, c_locale
);
2329 if (!x
|| *x
|| errno
) {
2340 /* Same as snprintf, but guarantees NUL-termination on every platform */
2341 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2346 pa_assert(size
> 0);
2349 va_start(ap
, format
);
2350 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2356 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2357 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2361 pa_assert(size
> 0);
2364 ret
= vsnprintf(str
, size
, format
, ap
);
2371 if ((size_t) ret
> size
-1)
2374 return (size_t) ret
;
2377 /* Truncate the specified string, but guarantee that the string
2378 * returned still validates as UTF8 */
2379 char *pa_truncate_utf8(char *c
, size_t l
) {
2381 pa_assert(pa_utf8_valid(c
));
2388 while (l
> 0 && !pa_utf8_valid(c
))
2394 char *pa_getcwd(void) {
2398 char *p
= pa_xmalloc(l
);
2402 if (errno
!= ERANGE
)
2410 void *pa_will_need(const void *p
, size_t l
) {
2411 #ifdef RLIMIT_MEMLOCK
2422 a
= PA_PAGE_ALIGN_PTR(p
);
2423 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2425 #ifdef HAVE_POSIX_MADVISE
2426 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2427 pa_log_debug("posix_madvise() worked fine!");
2432 /* Most likely the memory was not mmap()ed from a file and thus
2433 * madvise() didn't work, so let's misuse mlock() do page this
2434 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2435 * inviting, the man page of mlock() tells us: "All pages that
2436 * contain a part of the specified address range are guaranteed to
2437 * be resident in RAM when the call returns successfully." */
2439 #ifdef RLIMIT_MEMLOCK
2440 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2442 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2443 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
));
2448 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2450 bs
= PA_PAGE_SIZE
*4;
2453 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2456 while (size
> 0 && bs
> 0) {
2461 if (mlock(a
, bs
) < 0) {
2462 bs
= PA_PAGE_ALIGN(bs
/ 2);
2466 pa_assert_se(munlock(a
, bs
) == 0);
2468 a
= (const uint8_t*) a
+ bs
;
2474 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2476 pa_log_debug("mlock() worked fine!");
2481 void pa_close_pipe(int fds
[2]) {
2485 pa_assert_se(pa_close(fds
[0]) == 0);
2488 pa_assert_se(pa_close(fds
[1]) == 0);
2490 fds
[0] = fds
[1] = -1;
2493 char *pa_readlink(const char *p
) {
2494 #ifdef HAVE_READLINK
2503 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2508 if ((size_t) n
< l
-1) {
2521 int pa_close_all(int except_fd
, ...) {
2526 va_start(ap
, except_fd
);
2529 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2534 p
= pa_xnew(int, n
+1);
2536 va_start(ap
, except_fd
);
2539 if (except_fd
>= 0) {
2543 while ((fd
= va_arg(ap
, int)) >= 0)
2550 r
= pa_close_allv(p
);
2556 int pa_close_allv(const int except_fds
[]) {
2565 if ((d
= opendir("/proc/self/fd"))) {
2569 while ((de
= readdir(d
))) {
2575 if (de
->d_name
[0] == '.')
2579 l
= strtol(de
->d_name
, &e
, 10);
2580 if (errno
!= 0 || !e
|| *e
) {
2588 if ((long) fd
!= l
) {
2601 for (i
= 0; except_fds
[i
] >= 0; i
++)
2602 if (except_fds
[i
] == fd
) {
2610 if (pa_close(fd
) < 0) {
2611 saved_errno
= errno
;
2613 errno
= saved_errno
;
2625 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2626 maxfd
= (int) rl
.rlim_max
;
2628 maxfd
= sysconf(_SC_OPEN_MAX
);
2630 for (fd
= 3; fd
< maxfd
; fd
++) {
2635 for (i
= 0; except_fds
[i
] >= 0; i
++)
2636 if (except_fds
[i
] == fd
) {
2644 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2647 #endif /* !OS_IS_WIN32 */
2652 int pa_unblock_sigs(int except
, ...) {
2657 va_start(ap
, except
);
2660 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2665 p
= pa_xnew(int, n
+1);
2667 va_start(ap
, except
);
2674 while ((sig
= va_arg(ap
, int)) >= 0)
2681 r
= pa_unblock_sigsv(p
);
2687 int pa_unblock_sigsv(const int except
[]) {
2692 if (sigemptyset(&ss
) < 0)
2695 for (i
= 0; except
[i
] > 0; i
++)
2696 if (sigaddset(&ss
, except
[i
]) < 0)
2699 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2705 int pa_reset_sigs(int except
, ...) {
2710 va_start(ap
, except
);
2713 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2718 p
= pa_xnew(int, n
+1);
2720 va_start(ap
, except
);
2727 while ((sig
= va_arg(ap
, int)) >= 0)
2734 r
= pa_reset_sigsv(p
);
2740 int pa_reset_sigsv(const int except
[]) {
2744 for (sig
= 1; sig
< NSIG
; sig
++) {
2745 pa_bool_t reset
= TRUE
;
2756 for (i
= 0; except
[i
] > 0; i
++) {
2757 if (sig
== except
[i
]) {
2766 struct sigaction sa
;
2768 memset(&sa
, 0, sizeof(sa
));
2769 sa
.sa_handler
= SIG_DFL
;
2771 /* On Linux the first two RT signals are reserved by
2772 * glibc, and sigaction() will return EINVAL for them. */
2773 if ((sigaction(sig
, &sa
, NULL
) < 0))
2774 if (errno
!= EINVAL
)
2783 void pa_set_env(const char *key
, const char *value
) {
2787 /* This is not thread-safe */
2790 SetEnvironmentVariable(key
, value
);
2792 setenv(key
, value
, 1);
2796 void pa_set_env_and_record(const char *key
, const char *value
) {
2800 /* This is not thread-safe */
2802 pa_set_env(key
, value
);
2803 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2806 void pa_unset_env_recorded(void) {
2808 /* This is not thread-safe */
2813 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2819 SetEnvironmentVariable(s
, NULL
);
2827 pa_bool_t
pa_in_system_mode(void) {
2830 if (!(e
= getenv("PULSE_SYSTEM")))
2836 /* Checks a whitespace-separated list of words in haystack for needle */
2837 pa_bool_t
pa_str_in_list_spaces(const char *haystack
, const char *needle
) {
2839 const char *state
= NULL
;
2841 if (!haystack
|| !needle
)
2844 while ((s
= pa_split_spaces(haystack
, &state
))) {
2845 if (pa_streq(needle
, s
)) {
2856 char *pa_get_user_name_malloc(void) {
2860 #ifdef _SC_LOGIN_NAME_MAX
2861 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2867 u
= pa_xnew(char, k
+1);
2869 if (!(pa_get_user_name(u
, k
))) {
2877 char *pa_get_host_name_malloc(void) {
2886 if (!pa_get_host_name(c
, l
)) {
2888 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2891 } else if (strlen(c
) < l
-1) {
2899 u
= pa_utf8_filter(c
);
2904 /* Hmm, the hostname is as long the space we offered the
2905 * function, we cannot know if it fully fit in, so let's play
2906 * safe and retry. */
2915 char *pa_machine_id(void) {
2919 /* The returned value is supposed be some kind of ascii identifier
2920 * that is unique and stable across reboots. */
2922 /* First we try the /etc/machine-id, which is the best option we
2923 * have, since it fits perfectly our needs and is not as volatile
2924 * as the hostname which might be set from dhcp. */
2926 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r")) ||
2927 (f
= pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK
, "r"))) {
2928 char ln
[34] = "", *r
;
2930 r
= fgets(ln
, sizeof(ln
)-1, f
);
2936 return pa_utf8_filter(ln
);
2939 if ((h
= pa_get_host_name_malloc()))
2943 /* If no hostname was set we use the POSIX hostid. It's usually
2944 * the IPv4 address. Might not be that stable. */
2945 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2951 char *pa_session_id(void) {
2954 e
= getenv("XDG_SESSION_ID");
2958 return pa_utf8_filter(e
);
2961 char *pa_uname_string(void) {
2965 pa_assert_se(uname(&u
) >= 0);
2967 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2973 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2974 pa_assert_se(GetVersionEx(&i
));
2976 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2980 #ifdef HAVE_VALGRIND_MEMCHECK_H
2981 pa_bool_t
pa_in_valgrind(void) {
2984 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2985 * here instead of really checking whether we run in valgrind or
2989 b
= getenv("VALGRIND") ? 2 : 1;
2995 unsigned pa_gcd(unsigned a
, unsigned b
) {
3006 void pa_reduce(unsigned *num
, unsigned *den
) {
3008 unsigned gcd
= pa_gcd(*num
, *den
);
3016 pa_assert(pa_gcd(*num
, *den
) == 1);
3019 unsigned pa_ncpus(void) {
3022 #ifdef _SC_NPROCESSORS_CONF
3023 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
3028 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
3031 char *pa_replace(const char*s
, const char*a
, const char *b
) {
3040 sb
= pa_strbuf_new();
3045 if (!(p
= strstr(s
, a
)))
3048 pa_strbuf_putsn(sb
, s
, p
-s
);
3049 pa_strbuf_puts(sb
, b
);
3053 pa_strbuf_puts(sb
, s
);
3055 return pa_strbuf_tostring_free(sb
);
3058 char *pa_escape(const char *p
, const char *chars
) {
3061 pa_strbuf
*buf
= pa_strbuf_new();
3063 for (s
= p
; *s
; ++s
) {
3065 pa_strbuf_putc(buf
, '\\');
3067 for (c
= chars
; *c
; ++c
) {
3069 pa_strbuf_putc(buf
, '\\');
3074 pa_strbuf_putc(buf
, *s
);
3077 return pa_strbuf_tostring_free(buf
);
3080 char *pa_unescape(char *p
) {
3082 pa_bool_t escaped
= FALSE
;
3084 for (s
= p
, d
= p
; *s
; s
++) {
3085 if (!escaped
&& *s
== '\\') {
3099 char *pa_realpath(const char *path
) {
3103 /* We want only absolute paths */
3104 if (path
[0] != '/') {
3109 #if defined(__GLIBC__)
3113 if (!(r
= realpath(path
, NULL
)))
3116 /* We copy this here in case our pa_xmalloc() is not
3117 * implemented on top of libc malloc() */
3121 #elif defined(PATH_MAX)
3124 path_buf
= pa_xmalloc(PATH_MAX
);
3126 #if defined(OS_IS_WIN32)
3127 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
3132 if (!(t
= realpath(path
, path_buf
))) {
3139 #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."
3145 void pa_disable_sigpipe(void) {
3148 struct sigaction sa
;
3152 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
3153 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3157 sa
.sa_handler
= SIG_IGN
;
3159 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
3160 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3166 void pa_xfreev(void**a
) {
3172 for (p
= a
; *p
; p
++)
3178 char **pa_split_spaces_strv(const char *s
) {
3180 unsigned i
= 0, n
= 8;
3181 const char *state
= NULL
;
3183 t
= pa_xnew(char*, n
);
3184 while ((e
= pa_split_spaces(s
, &state
))) {
3189 t
= pa_xrenew(char*, t
, n
);
3202 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
3205 if (pa_is_path_absolute(path
))
3206 return pa_xstrdup(path
);
3208 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
3211 size_t pa_pipe_buf(int fd
) {
3216 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3227 void pa_reset_personality(void) {
3230 if (personality(PER_LINUX
) < 0)
3231 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3236 pa_bool_t
pa_run_from_build_tree(void) {
3238 static pa_bool_t b
= FALSE
;
3241 if ((rp
= pa_readlink("/proc/self/exe"))) {
3242 b
= pa_startswith(rp
, PA_BUILDDIR
);
3250 const char *pa_get_temp_dir(void) {
3253 if ((t
= getenv("TMPDIR")) &&
3254 pa_is_path_absolute(t
))
3257 if ((t
= getenv("TMP")) &&
3258 pa_is_path_absolute(t
))
3261 if ((t
= getenv("TEMP")) &&
3262 pa_is_path_absolute(t
))
3265 if ((t
= getenv("TEMPDIR")) &&
3266 pa_is_path_absolute(t
))
3272 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3280 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3283 if (errno
!= EINVAL
)
3287 if ((fd
= open(fn
, flags
, mode
)) < 0)
3291 /* Some implementations might simply ignore O_CLOEXEC if it is not
3292 * understood, make sure FD_CLOEXEC is enabled anyway */
3294 pa_make_fd_cloexec(fd
);
3298 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3302 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3305 if (errno
!= EINVAL
)
3309 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3313 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3314 * not understood, make sure FD_CLOEXEC is enabled anyway */
3316 pa_make_fd_cloexec(fd
);
3320 int pa_pipe_cloexec(int pipefd
[2]) {
3324 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3327 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3332 if ((r
= pipe(pipefd
)) < 0)
3336 pa_make_fd_cloexec(pipefd
[0]);
3337 pa_make_fd_cloexec(pipefd
[1]);
3342 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3346 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3349 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3354 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3358 pa_make_fd_cloexec(fd
);
3362 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3366 m
= pa_sprintf_malloc("%se", mode
);
3369 if ((f
= fopen(path
, m
))) {
3376 if (errno
!= EINVAL
)
3379 if (!(f
= fopen(path
, mode
)))
3383 pa_make_fd_cloexec(fileno(f
));
3387 void pa_nullify_stdfds(void) {
3390 pa_close(STDIN_FILENO
);
3391 pa_close(STDOUT_FILENO
);
3392 pa_close(STDERR_FILENO
);
3394 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3395 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3396 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3403 char *pa_read_line_from_file(const char *fn
) {
3405 char ln
[256] = "", *r
;
3407 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3410 r
= fgets(ln
, sizeof(ln
)-1, f
);
3419 return pa_xstrdup(ln
);
3422 pa_bool_t
pa_running_in_vm(void) {
3424 #if defined(__i386__) || defined(__x86_64__)
3426 /* Both CPUID and DMI are x86 specific interfaces... */
3428 uint32_t eax
= 0x40000000;
3435 const char *const dmi_vendors
[] = {
3436 "/sys/class/dmi/id/sys_vendor",
3437 "/sys/class/dmi/id/board_vendor",
3438 "/sys/class/dmi/id/bios_vendor"
3443 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3446 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3448 if (pa_startswith(s
, "QEMU") ||
3449 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3450 pa_startswith(s
, "VMware") ||
3451 pa_startswith(s
, "VMW") ||
3452 pa_startswith(s
, "Microsoft Corporation") ||
3453 pa_startswith(s
, "innotek GmbH") ||
3454 pa_startswith(s
, "Xen")) {
3466 /* http://lwn.net/Articles/301888/ */
3469 __asm__
__volatile__ (
3470 /* ebx/rbx is being used for PIC! */
3471 " push %%"PA_REG_b
" \n\t"
3473 " mov %%ebx, %1 \n\t"
3474 " pop %%"PA_REG_b
" \n\t"
3476 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3480 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3481 pa_streq(sig
.text
, "KVMKVMKVM") ||
3482 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3483 pa_streq(sig
.text
, "VMwareVMware") ||
3484 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3485 pa_streq(sig
.text
, "Microsoft Hv"))