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
;
153 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
154 char *pa_win32_get_toplevel(HANDLE handle
) {
155 static char *toplevel
= NULL
;
158 char library_path
[MAX_PATH
];
161 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
164 toplevel
= pa_xstrdup(library_path
);
166 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
170 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
171 if (p
&& pa_streq(p
+ 1, "bin"))
180 /** Make a file descriptor nonblock. Doesn't do any error checking */
181 void pa_make_fd_nonblock(int fd
) {
187 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
189 if (!(v
& O_NONBLOCK
))
190 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
192 #elif defined(OS_IS_WIN32)
194 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
195 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
196 pa_log_warn("Only sockets can be made non-blocking!");
199 pa_log_warn("Non-blocking I/O not supported.!");
204 /* Set the FD_CLOEXEC flag for a fd */
205 void pa_make_fd_cloexec(int fd
) {
211 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
213 if (!(v
& FD_CLOEXEC
))
214 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
219 /** Creates a directory securely */
220 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
231 u
= umask((~m
) & 0777);
237 if (r
< 0 && errno
!= EEXIST
)
240 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
256 if (fstat(fd
, &st
) < 0) {
257 pa_assert_se(pa_close(fd
) >= 0);
261 if (!S_ISDIR(st
.st_mode
)) {
262 pa_assert_se(pa_close(fd
) >= 0);
268 if (uid
== (uid_t
) -1)
270 if (gid
== (gid_t
) -1)
272 if (fchown(fd
, uid
, gid
) < 0)
277 (void) fchmod(fd
, m
);
280 pa_assert_se(pa_close(fd
) >= 0);
285 if (lstat(dir
, &st
) < 0)
287 if (stat(dir
, &st
) < 0)
292 if (!S_ISDIR(st
.st_mode
) ||
293 (st
.st_uid
!= uid
) ||
294 (st
.st_gid
!= gid
) ||
295 ((st
.st_mode
& 0777) != m
)) {
300 pa_log_warn("Secure directory creation not supported on Win32.");
313 /* Return a newly allocated sting containing the parent directory of the specified file */
314 char *pa_parent_dir(const char *fn
) {
315 char *slash
, *dir
= pa_xstrdup(fn
);
317 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
327 /* Creates a the parent directory of the specified path securely */
328 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
332 if (!(dir
= pa_parent_dir(fn
)))
335 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
345 /** Platform independent read function. Necessary since not all
346 * systems treat all file descriptors equal. If type is
347 * non-NULL it is used to cache the type of the fd. This is
348 * useful for making sure that only a single syscall is executed per
349 * function call. The variable pointed to should be initialized to 0
351 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
355 if (!type
|| *type
== 0) {
358 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
361 if (WSAGetLastError() != WSAENOTSOCK
) {
362 errno
= WSAGetLastError();
375 if ((r
= read(fd
, buf
, count
)) < 0)
383 /** Similar to pa_read(), but handles writes */
384 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
386 if (!type
|| *type
== 0) {
390 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
402 if (WSAGetLastError() != WSAENOTSOCK
) {
403 errno
= WSAGetLastError();
407 if (errno
!= ENOTSOCK
)
418 if ((r
= write(fd
, buf
, count
)) < 0)
426 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
427 * unless EOF is reached or an error occurred */
428 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
444 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
451 data
= (uint8_t*) data
+ r
;
458 /** Similar to pa_loop_read(), but wraps write() */
459 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
475 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
482 data
= (const uint8_t*) data
+ r
;
489 /** Platform independent read function. Necessary since not all
490 * systems treat all file descriptors equal. */
491 int pa_close(int fd
) {
496 if ((ret
= closesocket(fd
)) == 0)
499 if (WSAGetLastError() != WSAENOTSOCK
) {
500 errno
= WSAGetLastError();
508 if ((r
= close(fd
)) < 0)
516 /* Print a warning messages in case that the given signal is not
517 * blocked or trapped */
518 void pa_check_signal_is_blocked(int sig
) {
519 #ifdef HAVE_SIGACTION
523 /* If POSIX threads are supported use thread-aware
524 * pthread_sigmask() function, to check if the signal is
525 * blocked. Otherwise fall back to sigprocmask() */
528 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
530 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
531 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
538 if (sigismember(&set
, sig
))
541 /* Check whether the signal is trapped */
543 if (sigaction(sig
, NULL
, &sa
) < 0) {
544 pa_log("sigaction(): %s", pa_cstrerror(errno
));
548 if (sa
.sa_handler
!= SIG_DFL
)
551 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
552 #else /* HAVE_SIGACTION */
553 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
557 /* The following function is based on an example from the GNU libc
558 * documentation. This function is similar to GNU's asprintf(). */
559 char *pa_sprintf_malloc(const char *format
, ...) {
569 c
= pa_xrealloc(c
, size
);
571 va_start(ap
, format
);
572 r
= vsnprintf(c
, size
, format
, ap
);
577 if (r
> -1 && (size_t) r
< size
)
580 if (r
> -1) /* glibc 2.1 */
587 /* Same as the previous function, but use a va_list instead of an
589 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
599 c
= pa_xrealloc(c
, size
);
602 r
= vsnprintf(c
, size
, format
, aq
);
607 if (r
> -1 && (size_t) r
< size
)
610 if (r
> -1) /* glibc 2.1 */
617 /* Similar to OpenBSD's strlcpy() function */
618 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
636 #ifdef _POSIX_PRIORITY_SCHEDULING
637 static int set_scheduler(int rtprio
) {
639 struct sched_param sp
;
645 dbus_error_init(&error
);
649 sp
.sched_priority
= rtprio
;
651 #ifdef SCHED_RESET_ON_FORK
652 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
653 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
658 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
659 pa_log_debug("SCHED_RR worked.");
662 #endif /* HAVE_SCHED_H */
665 /* Try to talk to RealtimeKit */
667 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
668 pa_log("Failed to connect to system bus: %s\n", error
.message
);
669 dbus_error_free(&error
);
674 /* We need to disable exit on disconnect because otherwise
675 * dbus_shutdown will kill us. See
676 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
677 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
679 r
= rtkit_make_realtime(bus
, 0, rtprio
);
680 dbus_connection_close(bus
);
681 dbus_connection_unref(bus
);
684 pa_log_debug("RealtimeKit worked.");
697 /* Make the current thread a realtime thread, and acquire the highest
698 * rtprio we can get that is less or equal the specified parameter. If
699 * the thread is already realtime, don't do anything. */
700 int pa_make_realtime(int rtprio
) {
702 #if defined(OS_IS_DARWIN)
703 struct thread_time_constraint_policy ttcpolicy
;
705 size_t size
= sizeof(freq
);
708 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
710 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
714 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
716 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
717 ttcpolicy
.period
= freq
/ 160;
718 ttcpolicy
.computation
= freq
/ 3300;
719 ttcpolicy
.constraint
= freq
/ 2200;
720 ttcpolicy
.preemptible
= 1;
722 ret
= thread_policy_set(mach_thread_self(),
723 THREAD_TIME_CONSTRAINT_POLICY
,
724 (thread_policy_t
) &ttcpolicy
,
725 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
727 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
731 pa_log_info("Successfully acquired real-time thread priority.");
734 #elif defined(_POSIX_PRIORITY_SCHEDULING)
737 if (set_scheduler(rtprio
) >= 0) {
738 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
742 for (p
= rtprio
-1; p
>= 1; p
--)
743 if (set_scheduler(p
) >= 0) {
744 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
747 #elif defined(OS_IS_WIN32)
748 /* Windows only allows realtime scheduling to be set on a per process basis.
749 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
750 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
751 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
755 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
760 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
764 #ifdef HAVE_SYS_RESOURCE_H
765 static int set_nice(int nice_level
) {
771 dbus_error_init(&error
);
774 #ifdef HAVE_SYS_RESOURCE_H
775 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
776 pa_log_debug("setpriority() worked.");
782 /* Try to talk to RealtimeKit */
784 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
785 pa_log("Failed to connect to system bus: %s\n", error
.message
);
786 dbus_error_free(&error
);
791 /* We need to disable exit on disconnect because otherwise
792 * dbus_shutdown will kill us. See
793 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
794 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
796 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
797 dbus_connection_unref(bus
);
800 pa_log_debug("RealtimeKit worked.");
811 /* Raise the priority of the current process as much as possible that
812 * is <= the specified nice level..*/
813 int pa_raise_priority(int nice_level
) {
815 #ifdef HAVE_SYS_RESOURCE_H
818 if (set_nice(nice_level
) >= 0) {
819 pa_log_info("Successfully gained nice level %i.", nice_level
);
823 for (n
= nice_level
+1; n
< 0; n
++)
824 if (set_nice(n
) >= 0) {
825 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
829 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
834 if (nice_level
< 0) {
835 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
836 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
841 pa_log_info("Successfully gained high priority class.");
848 /* Reset the priority to normal, inverting the changes made by
849 * pa_raise_priority() and pa_make_realtime()*/
850 void pa_reset_priority(void) {
851 #ifdef HAVE_SYS_RESOURCE_H
852 struct sched_param sp
;
854 setpriority(PRIO_PROCESS
, 0, 0);
857 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
861 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
865 int pa_match(const char *expr
, const char *v
) {
870 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
875 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
877 else if (k
== REG_NOMATCH
)
890 /* Try to parse a boolean string value.*/
891 int pa_parse_boolean(const char *v
) {
894 /* First we check language independent */
895 if (pa_streq(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
897 else if (pa_streq(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
900 #ifdef HAVE_LANGINFO_H
903 /* And then we check language dependent */
904 if ((expr
= nl_langinfo(YESEXPR
)))
906 if (pa_match(expr
, v
) > 0)
909 if ((expr
= nl_langinfo(NOEXPR
)))
911 if (pa_match(expr
, v
) > 0)
920 /* Split the specified string wherever one of the strings in delimiter
921 * occurs. Each time it is called returns a newly allocated string
922 * with pa_xmalloc(). The variable state points to, should be
923 * initialized to NULL before the first call. */
924 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
925 const char *current
= *state
? *state
: c
;
931 l
= strcspn(current
, delimiter
);
937 return pa_xstrndup(current
, l
);
940 /* Split a string into words. Otherwise similar to pa_split(). */
941 char *pa_split_spaces(const char *c
, const char **state
) {
942 const char *current
= *state
? *state
: c
;
945 if (!*current
|| *c
== 0)
948 current
+= strspn(current
, WHITESPACE
);
949 l
= strcspn(current
, WHITESPACE
);
953 return pa_xstrndup(current
, l
);
956 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
958 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
959 const char *pa_sig2str(int sig
) {
972 char buf
[SIG2STR_MAX
];
974 if (sig2str(sig
, buf
) == 0) {
975 pa_xfree(PA_STATIC_TLS_GET(signame
));
976 t
= pa_sprintf_malloc("SIG%s", buf
);
977 PA_STATIC_TLS_SET(signame
, t
);
985 case SIGHUP
: return "SIGHUP";
987 case SIGINT
: return "SIGINT";
989 case SIGQUIT
: return "SIGQUIT";
991 case SIGILL
: return "SIGULL";
993 case SIGTRAP
: return "SIGTRAP";
995 case SIGABRT
: return "SIGABRT";
997 case SIGBUS
: return "SIGBUS";
999 case SIGFPE
: return "SIGFPE";
1001 case SIGKILL
: return "SIGKILL";
1004 case SIGUSR1
: return "SIGUSR1";
1006 case SIGSEGV
: return "SIGSEGV";
1008 case SIGUSR2
: return "SIGUSR2";
1011 case SIGPIPE
: return "SIGPIPE";
1014 case SIGALRM
: return "SIGALRM";
1016 case SIGTERM
: return "SIGTERM";
1018 case SIGSTKFLT
: return "SIGSTKFLT";
1021 case SIGCHLD
: return "SIGCHLD";
1024 case SIGCONT
: return "SIGCONT";
1027 case SIGSTOP
: return "SIGSTOP";
1030 case SIGTSTP
: return "SIGTSTP";
1033 case SIGTTIN
: return "SIGTTIN";
1036 case SIGTTOU
: return "SIGTTOU";
1039 case SIGURG
: return "SIGURG";
1042 case SIGXCPU
: return "SIGXCPU";
1045 case SIGXFSZ
: return "SIGXFSZ";
1048 case SIGVTALRM
: return "SIGVTALRM";
1051 case SIGPROF
: return "SIGPROF";
1054 case SIGWINCH
: return "SIGWINCH";
1057 case SIGIO
: return "SIGIO";
1060 case SIGPWR
: return "SIGPWR";
1063 case SIGSYS
: return "SIGSYS";
1068 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1069 pa_xfree(PA_STATIC_TLS_GET(signame
));
1070 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1071 PA_STATIC_TLS_SET(signame
, t
);
1080 pa_xfree(PA_STATIC_TLS_GET(signame
));
1081 t
= pa_sprintf_malloc("SIG%i", sig
);
1082 PA_STATIC_TLS_SET(signame
, t
);
1088 /* Check whether the specified GID and the group name match */
1089 static int is_group(gid_t gid
, const char *name
) {
1090 struct group
*group
= NULL
;
1094 if (!(group
= pa_getgrgid_malloc(gid
))) {
1098 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1103 r
= pa_streq(name
, group
->gr_name
);
1106 pa_getgrgid_free(group
);
1111 /* Check the current user is member of the specified group */
1112 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1113 GETGROUPS_T
*gids
, tgid
;
1114 long n
= sysconf(_SC_NGROUPS_MAX
);
1119 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1121 if ((n
= getgroups((int) n
, gids
)) < 0) {
1122 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1126 for (i
= 0; i
< n
; i
++) {
1128 if ((k
= is_group(gids
[i
], name
)) < 0)
1137 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1153 /* Check whether the specific user id is a member of the specified group */
1154 int pa_uid_in_group(uid_t uid
, const char *name
) {
1155 struct group
*group
= NULL
;
1160 if (!(group
= pa_getgrnam_malloc(name
))) {
1167 for (i
= group
->gr_mem
; *i
; i
++) {
1168 struct passwd
*pw
= NULL
;
1171 if (!(pw
= pa_getpwnam_malloc(*i
)))
1174 if (pw
->pw_uid
== uid
)
1177 pa_getpwnam_free(pw
);
1184 pa_getgrnam_free(group
);
1189 /* Get the GID of a given group, return (gid_t) -1 on failure. */
1190 gid_t
pa_get_gid_of_group(const char *name
) {
1191 gid_t ret
= (gid_t
) -1;
1192 struct group
*gr
= NULL
;
1195 if (!(gr
= pa_getgrnam_malloc(name
))) {
1204 pa_getgrnam_free(gr
);
1208 int pa_check_in_group(gid_t g
) {
1209 gid_t gids
[NGROUPS_MAX
];
1212 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1222 #else /* HAVE_GRP_H */
1224 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1230 int pa_uid_in_group(uid_t uid
, const char *name
) {
1235 gid_t
pa_get_gid_of_group(const char *name
) {
1240 int pa_check_in_group(gid_t g
) {
1247 /* Lock or unlock a file entirely.
1248 (advisory on UNIX, mandatory on Windows) */
1249 int pa_lock_fd(int fd
, int b
) {
1251 struct flock f_lock
;
1253 /* Try a R/W lock first */
1255 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1256 f_lock
.l_whence
= SEEK_SET
;
1260 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1263 /* Perhaps the file descriptor was opened for read only, than try again with a read lock. */
1264 if (b
&& errno
== EBADF
) {
1265 f_lock
.l_type
= F_RDLCK
;
1266 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1270 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1274 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1276 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1278 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1281 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1283 /* FIXME: Needs to set errno! */
1289 /* Remove trailing newlines from a string */
1290 char* pa_strip_nl(char *s
) {
1293 s
[strcspn(s
, NEWLINE
)] = 0;
1297 char *pa_strip(char *s
) {
1300 /* Drops trailing whitespace. Modifies the string in
1301 * place. Returns pointer to first non-space character */
1303 s
+= strspn(s
, WHITESPACE
);
1305 for (e
= s
; *e
; e
++)
1306 if (!strchr(WHITESPACE
, *e
))
1317 /* Create a temporary lock file and lock it. */
1318 int pa_lock_lockfile(const char *fn
) {
1325 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1329 , S_IRUSR
|S_IWUSR
)) < 0) {
1330 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1334 if (pa_lock_fd(fd
, 1) < 0) {
1335 pa_log_warn("Failed to lock file '%s'.", fn
);
1339 if (fstat(fd
, &st
) < 0) {
1340 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1344 /* Check whether the file has been removed meanwhile. When yes,
1345 * restart this loop, otherwise, we're done */
1346 if (st
.st_nlink
>= 1)
1349 if (pa_lock_fd(fd
, 0) < 0) {
1350 pa_log_warn("Failed to unlock file '%s'.", fn
);
1354 if (pa_close(fd
) < 0) {
1355 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1366 int saved_errno
= errno
;
1368 errno
= saved_errno
;
1374 /* Unlock a temporary lock file */
1375 int pa_unlock_lockfile(const char *fn
, int fd
) {
1380 if (unlink(fn
) < 0) {
1381 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1386 if (pa_lock_fd(fd
, 0) < 0) {
1387 pa_log_warn("Failed to unlock file '%s'.", fn
);
1391 if (pa_close(fd
) < 0) {
1392 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1399 static char *get_config_home(char *home
) {
1402 t
= getenv("XDG_CONFIG_HOME");
1404 return pa_xstrdup(t
);
1406 return pa_sprintf_malloc("%s" PA_PATH_SEP
".config", home
);
1409 static int check_ours(const char *p
) {
1414 if (stat(p
, &st
) < 0)
1418 if (st
.st_uid
!= getuid())
1425 static char *get_pulse_home(void) {
1426 char *h
, *ret
, *config_home
;
1429 h
= pa_get_home_dir_malloc();
1431 pa_log_error("Failed to get home directory.");
1436 if (t
< 0 && t
!= -ENOENT
) {
1437 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t
));
1442 /* If the old directory exists, use it. */
1443 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1444 if (access(ret
, F_OK
) >= 0) {
1450 /* Otherwise go for the XDG compliant directory. */
1451 config_home
= get_config_home(h
);
1453 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", config_home
);
1459 char *pa_get_state_dir(void) {
1462 /* The state directory shall contain dynamic data that should be
1463 * kept across reboots, and is private to this user */
1465 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1466 if (!(d
= get_pulse_home()))
1469 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1470 * dir then this will break. */
1472 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1473 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1481 char *pa_get_home_dir_malloc(void) {
1483 size_t allocated
= 128;
1486 homedir
= pa_xmalloc(allocated
);
1488 if (!pa_get_home_dir(homedir
, allocated
)) {
1493 if (strlen(homedir
) < allocated
- 1)
1503 char *pa_get_binary_name_malloc(void) {
1505 size_t allocated
= 128;
1508 t
= pa_xmalloc(allocated
);
1510 if (!pa_get_binary_name(t
, allocated
)) {
1515 if (strlen(t
) < allocated
- 1)
1525 static char* make_random_dir(mode_t m
) {
1526 static const char table
[] =
1527 "abcdefghijklmnopqrstuvwxyz"
1528 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1534 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1535 pathlen
= strlen(fn
);
1543 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1544 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1546 u
= umask((~m
) & 0777);
1553 saved_errno
= errno
;
1555 errno
= saved_errno
;
1560 if (errno
!= EEXIST
) {
1561 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1568 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1571 if (!(p
= make_random_dir(m
)))
1575 if (symlink(p
, k
) < 0) {
1576 int saved_errno
= errno
;
1578 if (errno
!= EEXIST
)
1579 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1584 errno
= saved_errno
;
1596 char *pa_get_runtime_dir(void) {
1597 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1600 /* The runtime directory shall contain dynamic data that needs NOT
1601 * to be kept across reboots and is usually private to the user,
1602 * except in system mode, where it might be accessible by other
1603 * users, too. Since we need POSIX locking and UNIX sockets in
1604 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1605 * set create a directory in $HOME and link it to a random subdir
1606 * in /tmp, if it was not explicitly configured. */
1608 m
= pa_in_system_mode() ? 0755U : 0700U;
1610 /* Use the explicitly configured value if it is set */
1611 d
= getenv("PULSE_RUNTIME_PATH");
1614 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1615 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1619 return pa_xstrdup(d
);
1622 /* Use the XDG standard for the runtime directory. */
1623 d
= getenv("XDG_RUNTIME_DIR");
1625 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", d
);
1627 if (pa_make_secure_dir(k
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1629 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1636 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1637 d
= get_pulse_home();
1641 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1642 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1647 mid
= pa_machine_id();
1653 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1658 /* OK, first let's check if the "runtime" symlink already exists */
1663 if (errno
!= ENOENT
) {
1664 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1669 /* Hmm, so the runtime directory didn't exist yet, so let's
1670 * create one in /tmp and symlink that to it */
1672 if (make_random_dir_and_link(0700, k
) < 0) {
1674 /* Mhmm, maybe another process was quicker than us,
1675 * let's check if that was valid */
1676 if (errno
== EEXIST
)
1682 /* No symlink possible, so let's just create the runtime directly */
1690 /* Make sure that this actually makes sense */
1691 if (!pa_is_path_absolute(p
)) {
1692 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1697 /* Hmm, so this symlink is still around, make sure nobody fools us */
1701 if (lstat(p
, &st
) < 0) {
1703 if (errno
!= ENOENT
) {
1704 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1710 if (S_ISDIR(st
.st_mode
) &&
1711 (st
.st_uid
== getuid()) &&
1712 ((st
.st_mode
& 0777) == 0700)) {
1718 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1726 /* Hmm, so the link points to some nonexisting or invalid
1727 * dir. Let's replace it by a new link. We first create a
1728 * temporary link and then rename that to allow concurrent
1729 * execution of this function. */
1731 t
= pa_sprintf_malloc("%s.tmp", k
);
1733 if (make_random_dir_and_link(0700, t
) < 0) {
1735 if (errno
!= EEXIST
) {
1736 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1743 /* Hmm, someone else was quicker then us. Let's give
1744 * him some time to finish, and retry. */
1749 /* OK, we succeeded in creating the temporary symlink, so
1750 * let's rename it */
1751 if (rename(t
, k
) < 0) {
1752 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1768 /* Try to open a configuration file. If "env" is specified, open the
1769 * value of the specified environment variable. Otherwise look for a
1770 * file "local" in the home directory or a file "global" in global
1771 * file system. If "result" is non-NULL, a pointer to a newly
1772 * allocated buffer containing the used configuration file is
1774 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1778 if (env
&& (fn
= getenv(env
))) {
1779 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1781 *result
= pa_xstrdup(fn
);
1786 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1795 if ((e
= getenv("PULSE_CONFIG_PATH"))) {
1796 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1797 f
= pa_fopen_cloexec(fn
, "r");
1798 } else if ((h
= pa_get_home_dir_malloc())) {
1799 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1800 f
= pa_fopen_cloexec(fn
, "r");
1803 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".config/pulse" PA_PATH_SEP
"%s", h
, local
);
1804 f
= pa_fopen_cloexec(fn
, "r");
1812 *result
= pa_xstrdup(fn
);
1818 if (errno
!= ENOENT
) {
1819 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1831 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1832 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1833 pa_win32_get_toplevel(NULL
),
1834 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1837 gfn
= pa_xstrdup(global
);
1839 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1854 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1857 if (env
&& (fn
= getenv(env
))) {
1858 if (access(fn
, R_OK
) == 0)
1859 return pa_xstrdup(fn
);
1861 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1870 if ((e
= getenv("PULSE_CONFIG_PATH")))
1871 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1872 else if ((h
= pa_get_home_dir_malloc())) {
1873 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1878 if (access(fn
, R_OK
) == 0) {
1879 char *r
= pa_xstrdup(fn
);
1884 if (errno
!= ENOENT
) {
1885 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1897 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1898 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1899 pa_win32_get_toplevel(NULL
),
1900 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1903 gfn
= pa_xstrdup(global
);
1905 if (access(gfn
, R_OK
) == 0)
1915 /* Format the specified data as a hexademical string */
1916 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1917 size_t i
= 0, j
= 0;
1918 const char hex
[] = "0123456789abcdef";
1922 pa_assert(slength
> 0);
1924 while (j
+2 < slength
&& i
< dlength
) {
1925 s
[j
++] = hex
[*d
>> 4];
1926 s
[j
++] = hex
[*d
& 0xF];
1932 s
[j
< slength
? j
: slength
] = 0;
1936 /* Convert a hexadecimal digit to a number or -1 if invalid */
1937 static int hexc(char c
) {
1938 if (c
>= '0' && c
<= '9')
1941 if (c
>= 'A' && c
<= 'F')
1942 return c
- 'A' + 10;
1944 if (c
>= 'a' && c
<= 'f')
1945 return c
- 'a' + 10;
1951 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1952 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1958 while (j
< dlength
&& *p
) {
1961 if ((b
= hexc(*(p
++))) < 0)
1964 d
[j
] = (uint8_t) (b
<< 4);
1969 if ((b
= hexc(*(p
++))) < 0)
1972 d
[j
] |= (uint8_t) b
;
1979 /* Returns nonzero when *s starts with *pfx */
1980 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1988 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1991 /* Returns nonzero when *s ends with *sfx */
1992 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
2001 return l1
>= l2
&& pa_streq(s
+ l1
- l2
, sfx
);
2004 pa_bool_t
pa_is_path_absolute(const char *fn
) {
2010 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
2014 char *pa_make_path_absolute(const char *p
) {
2020 if (pa_is_path_absolute(p
))
2021 return pa_xstrdup(p
);
2023 if (!(cwd
= pa_getcwd()))
2024 return pa_xstrdup(p
);
2026 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2031 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
2032 * if fn is non-null and starts with / return fn
2033 * otherwise append fn to the run time path and return it */
2034 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
2037 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2040 char *r
, *canonical_rtp
;
2042 if (pa_is_path_absolute(fn
)) {
2044 return pa_xstrdup(fn
);
2050 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2051 if ((canonical_rtp
= pa_realpath(rtp
))) {
2052 if (strlen(rtp
) >= strlen(canonical_rtp
))
2055 pa_xfree(canonical_rtp
);
2056 canonical_rtp
= rtp
;
2059 canonical_rtp
= rtp
;
2064 if (!(mid
= pa_machine_id())) {
2065 pa_xfree(canonical_rtp
);
2069 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", canonical_rtp
, mid
, fn
);
2072 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", canonical_rtp
, fn
);
2074 pa_xfree(canonical_rtp
);
2080 char *pa_runtime_path(const char *fn
) {
2081 return get_path(fn
, FALSE
, TRUE
);
2084 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2085 return get_path(fn
, appendmid
, FALSE
);
2088 /* Convert the string s to a signed integer in *ret_i */
2089 int pa_atoi(const char *s
, int32_t *ret_i
) {
2095 if (pa_atol(s
, &l
) < 0)
2098 if ((int32_t) l
!= l
) {
2103 *ret_i
= (int32_t) l
;
2108 /* Convert the string s to an unsigned integer in *ret_u */
2109 int pa_atou(const char *s
, uint32_t *ret_u
) {
2117 l
= strtoul(s
, &x
, 0);
2119 if (!x
|| *x
|| errno
) {
2125 if ((uint32_t) l
!= l
) {
2130 *ret_u
= (uint32_t) l
;
2135 /* Convert the string s to a signed long integer in *ret_l. */
2136 int pa_atol(const char *s
, long *ret_l
) {
2144 l
= strtol(s
, &x
, 0);
2146 if (!x
|| *x
|| errno
) {
2157 #ifdef HAVE_STRTOF_L
2158 static locale_t c_locale
= NULL
;
2160 static void c_locale_destroy(void) {
2161 freelocale(c_locale
);
2165 int pa_atod(const char *s
, double *ret_d
) {
2172 /* This should be locale independent */
2174 #ifdef HAVE_STRTOF_L
2178 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2179 atexit(c_locale_destroy
);
2185 f
= strtod_l(s
, &x
, c_locale
);
2193 if (!x
|| *x
|| errno
) {
2204 /* Same as snprintf, but guarantees NUL-termination on every platform */
2205 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2210 pa_assert(size
> 0);
2213 va_start(ap
, format
);
2214 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2220 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2221 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2225 pa_assert(size
> 0);
2228 ret
= vsnprintf(str
, size
, format
, ap
);
2235 if ((size_t) ret
> size
-1)
2238 return (size_t) ret
;
2241 /* Truncate the specified string, but guarantee that the string
2242 * returned still validates as UTF8 */
2243 char *pa_truncate_utf8(char *c
, size_t l
) {
2245 pa_assert(pa_utf8_valid(c
));
2252 while (l
> 0 && !pa_utf8_valid(c
))
2258 char *pa_getcwd(void) {
2262 char *p
= pa_xmalloc(l
);
2266 if (errno
!= ERANGE
)
2274 void *pa_will_need(const void *p
, size_t l
) {
2275 #ifdef RLIMIT_MEMLOCK
2286 a
= PA_PAGE_ALIGN_PTR(p
);
2287 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2289 #ifdef HAVE_POSIX_MADVISE
2290 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2291 pa_log_debug("posix_madvise() worked fine!");
2296 /* Most likely the memory was not mmap()ed from a file and thus
2297 * madvise() didn't work, so let's misuse mlock() do page this
2298 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2299 * inviting, the man page of mlock() tells us: "All pages that
2300 * contain a part of the specified address range are guaranteed to
2301 * be resident in RAM when the call returns successfully." */
2303 #ifdef RLIMIT_MEMLOCK
2304 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2306 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2307 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
));
2312 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2314 bs
= PA_PAGE_SIZE
*4;
2317 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2320 while (size
> 0 && bs
> 0) {
2325 if (mlock(a
, bs
) < 0) {
2326 bs
= PA_PAGE_ALIGN(bs
/ 2);
2330 pa_assert_se(munlock(a
, bs
) == 0);
2332 a
= (const uint8_t*) a
+ bs
;
2338 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2340 pa_log_debug("mlock() worked fine!");
2345 void pa_close_pipe(int fds
[2]) {
2349 pa_assert_se(pa_close(fds
[0]) == 0);
2352 pa_assert_se(pa_close(fds
[1]) == 0);
2354 fds
[0] = fds
[1] = -1;
2357 char *pa_readlink(const char *p
) {
2358 #ifdef HAVE_READLINK
2367 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2372 if ((size_t) n
< l
-1) {
2385 int pa_close_all(int except_fd
, ...) {
2390 va_start(ap
, except_fd
);
2393 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2398 p
= pa_xnew(int, n
+1);
2400 va_start(ap
, except_fd
);
2403 if (except_fd
>= 0) {
2407 while ((fd
= va_arg(ap
, int)) >= 0)
2414 r
= pa_close_allv(p
);
2420 int pa_close_allv(const int except_fds
[]) {
2429 if ((d
= opendir("/proc/self/fd"))) {
2433 while ((de
= readdir(d
))) {
2439 if (de
->d_name
[0] == '.')
2443 l
= strtol(de
->d_name
, &e
, 10);
2444 if (errno
!= 0 || !e
|| *e
) {
2452 if ((long) fd
!= l
) {
2465 for (i
= 0; except_fds
[i
] >= 0; i
++)
2466 if (except_fds
[i
] == fd
) {
2474 if (pa_close(fd
) < 0) {
2475 saved_errno
= errno
;
2477 errno
= saved_errno
;
2489 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2490 maxfd
= (int) rl
.rlim_max
;
2492 maxfd
= sysconf(_SC_OPEN_MAX
);
2494 for (fd
= 3; fd
< maxfd
; fd
++) {
2499 for (i
= 0; except_fds
[i
] >= 0; i
++)
2500 if (except_fds
[i
] == fd
) {
2508 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2511 #endif /* !OS_IS_WIN32 */
2516 int pa_unblock_sigs(int except
, ...) {
2521 va_start(ap
, except
);
2524 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2529 p
= pa_xnew(int, n
+1);
2531 va_start(ap
, except
);
2538 while ((sig
= va_arg(ap
, int)) >= 0)
2545 r
= pa_unblock_sigsv(p
);
2551 int pa_unblock_sigsv(const int except
[]) {
2556 if (sigemptyset(&ss
) < 0)
2559 for (i
= 0; except
[i
] > 0; i
++)
2560 if (sigaddset(&ss
, except
[i
]) < 0)
2563 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2569 int pa_reset_sigs(int except
, ...) {
2574 va_start(ap
, except
);
2577 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2582 p
= pa_xnew(int, n
+1);
2584 va_start(ap
, except
);
2591 while ((sig
= va_arg(ap
, int)) >= 0)
2598 r
= pa_reset_sigsv(p
);
2604 int pa_reset_sigsv(const int except
[]) {
2608 for (sig
= 1; sig
< NSIG
; sig
++) {
2609 pa_bool_t reset
= TRUE
;
2620 for (i
= 0; except
[i
] > 0; i
++) {
2621 if (sig
== except
[i
]) {
2630 struct sigaction sa
;
2632 memset(&sa
, 0, sizeof(sa
));
2633 sa
.sa_handler
= SIG_DFL
;
2635 /* On Linux the first two RT signals are reserved by
2636 * glibc, and sigaction() will return EINVAL for them. */
2637 if ((sigaction(sig
, &sa
, NULL
) < 0))
2638 if (errno
!= EINVAL
)
2647 void pa_set_env(const char *key
, const char *value
) {
2651 /* This is not thread-safe */
2654 SetEnvironmentVariable(key
, value
);
2656 setenv(key
, value
, 1);
2660 void pa_set_env_and_record(const char *key
, const char *value
) {
2664 /* This is not thread-safe */
2666 pa_set_env(key
, value
);
2667 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2670 void pa_unset_env_recorded(void) {
2672 /* This is not thread-safe */
2677 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2683 SetEnvironmentVariable(s
, NULL
);
2691 pa_bool_t
pa_in_system_mode(void) {
2694 if (!(e
= getenv("PULSE_SYSTEM")))
2700 /* Checks a whitespace-separated list of words in haystack for needle */
2701 pa_bool_t
pa_str_in_list_spaces(const char *haystack
, const char *needle
) {
2703 const char *state
= NULL
;
2705 if (!haystack
|| !needle
)
2708 while ((s
= pa_split_spaces(haystack
, &state
))) {
2709 if (pa_streq(needle
, s
)) {
2720 char *pa_get_user_name_malloc(void) {
2724 #ifdef _SC_LOGIN_NAME_MAX
2725 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2731 u
= pa_xnew(char, k
+1);
2733 if (!(pa_get_user_name(u
, k
))) {
2741 char *pa_get_host_name_malloc(void) {
2750 if (!pa_get_host_name(c
, l
)) {
2752 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2755 } else if (strlen(c
) < l
-1) {
2763 u
= pa_utf8_filter(c
);
2768 /* Hmm, the hostname is as long the space we offered the
2769 * function, we cannot know if it fully fit in, so let's play
2770 * safe and retry. */
2779 char *pa_machine_id(void) {
2783 /* The returned value is supposed be some kind of ascii identifier
2784 * that is unique and stable across reboots. */
2786 /* First we try the /etc/machine-id, which is the best option we
2787 * have, since it fits perfectly our needs and is not as volatile
2788 * as the hostname which might be set from dhcp. */
2790 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r")) ||
2791 (f
= pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK
, "r"))) {
2792 char ln
[34] = "", *r
;
2794 r
= fgets(ln
, sizeof(ln
)-1, f
);
2800 return pa_utf8_filter(ln
);
2803 if ((h
= pa_get_host_name_malloc()))
2807 /* If no hostname was set we use the POSIX hostid. It's usually
2808 * the IPv4 address. Might not be that stable. */
2809 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2815 char *pa_session_id(void) {
2818 e
= getenv("XDG_SESSION_ID");
2822 return pa_utf8_filter(e
);
2825 char *pa_uname_string(void) {
2829 pa_assert_se(uname(&u
) >= 0);
2831 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2837 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2838 pa_assert_se(GetVersionEx(&i
));
2840 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2844 #ifdef HAVE_VALGRIND_MEMCHECK_H
2845 pa_bool_t
pa_in_valgrind(void) {
2848 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2849 * here instead of really checking whether we run in valgrind or
2853 b
= getenv("VALGRIND") ? 2 : 1;
2859 unsigned pa_gcd(unsigned a
, unsigned b
) {
2870 void pa_reduce(unsigned *num
, unsigned *den
) {
2872 unsigned gcd
= pa_gcd(*num
, *den
);
2880 pa_assert(pa_gcd(*num
, *den
) == 1);
2883 unsigned pa_ncpus(void) {
2886 #ifdef _SC_NPROCESSORS_CONF
2887 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2892 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2895 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2904 sb
= pa_strbuf_new();
2909 if (!(p
= strstr(s
, a
)))
2912 pa_strbuf_putsn(sb
, s
, p
-s
);
2913 pa_strbuf_puts(sb
, b
);
2917 pa_strbuf_puts(sb
, s
);
2919 return pa_strbuf_tostring_free(sb
);
2922 char *pa_escape(const char *p
, const char *chars
) {
2925 pa_strbuf
*buf
= pa_strbuf_new();
2927 for (s
= p
; *s
; ++s
) {
2929 pa_strbuf_putc(buf
, '\\');
2931 for (c
= chars
; *c
; ++c
) {
2933 pa_strbuf_putc(buf
, '\\');
2938 pa_strbuf_putc(buf
, *s
);
2941 return pa_strbuf_tostring_free(buf
);
2944 char *pa_unescape(char *p
) {
2946 pa_bool_t escaped
= FALSE
;
2948 for (s
= p
, d
= p
; *s
; s
++) {
2949 if (!escaped
&& *s
== '\\') {
2963 char *pa_realpath(const char *path
) {
2967 /* We want only absolute paths */
2968 if (path
[0] != '/') {
2973 #if defined(__GLIBC__) || defined(__APPLE__)
2977 if (!(r
= realpath(path
, NULL
)))
2980 /* We copy this here in case our pa_xmalloc() is not
2981 * implemented on top of libc malloc() */
2985 #elif defined(PATH_MAX)
2988 path_buf
= pa_xmalloc(PATH_MAX
);
2990 #if defined(OS_IS_WIN32)
2991 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2996 if (!(t
= realpath(path
, path_buf
))) {
3003 #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."
3009 void pa_disable_sigpipe(void) {
3012 struct sigaction sa
;
3016 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
3017 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3021 sa
.sa_handler
= SIG_IGN
;
3023 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
3024 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3030 void pa_xfreev(void**a
) {
3036 for (p
= a
; *p
; p
++)
3042 char **pa_split_spaces_strv(const char *s
) {
3044 unsigned i
= 0, n
= 8;
3045 const char *state
= NULL
;
3047 t
= pa_xnew(char*, n
);
3048 while ((e
= pa_split_spaces(s
, &state
))) {
3053 t
= pa_xrenew(char*, t
, n
);
3066 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
3069 if (pa_is_path_absolute(path
))
3070 return pa_xstrdup(path
);
3072 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
3075 size_t pa_pipe_buf(int fd
) {
3080 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3091 void pa_reset_personality(void) {
3094 if (personality(PER_LINUX
) < 0)
3095 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3100 #if defined(__linux__) && !defined(__OPTIMIZE__)
3102 pa_bool_t
pa_run_from_build_tree(void) {
3104 pa_bool_t b
= FALSE
;
3106 if ((rp
= pa_readlink("/proc/self/exe"))) {
3107 b
= pa_startswith(rp
, PA_BUILDDIR
);
3116 const char *pa_get_temp_dir(void) {
3119 if ((t
= getenv("TMPDIR")) &&
3120 pa_is_path_absolute(t
))
3123 if ((t
= getenv("TMP")) &&
3124 pa_is_path_absolute(t
))
3127 if ((t
= getenv("TEMP")) &&
3128 pa_is_path_absolute(t
))
3131 if ((t
= getenv("TEMPDIR")) &&
3132 pa_is_path_absolute(t
))
3138 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3146 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3149 if (errno
!= EINVAL
)
3153 if ((fd
= open(fn
, flags
, mode
)) < 0)
3157 /* Some implementations might simply ignore O_CLOEXEC if it is not
3158 * understood, make sure FD_CLOEXEC is enabled anyway */
3160 pa_make_fd_cloexec(fd
);
3164 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3168 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3171 if (errno
!= EINVAL
)
3175 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3179 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3180 * not understood, make sure FD_CLOEXEC is enabled anyway */
3182 pa_make_fd_cloexec(fd
);
3186 int pa_pipe_cloexec(int pipefd
[2]) {
3190 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3193 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3198 if ((r
= pipe(pipefd
)) < 0)
3202 pa_make_fd_cloexec(pipefd
[0]);
3203 pa_make_fd_cloexec(pipefd
[1]);
3208 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3212 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3215 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3220 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3224 pa_make_fd_cloexec(fd
);
3228 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3232 m
= pa_sprintf_malloc("%se", mode
);
3235 if ((f
= fopen(path
, m
))) {
3242 if (errno
!= EINVAL
)
3245 if (!(f
= fopen(path
, mode
)))
3249 pa_make_fd_cloexec(fileno(f
));
3253 void pa_nullify_stdfds(void) {
3256 pa_close(STDIN_FILENO
);
3257 pa_close(STDOUT_FILENO
);
3258 pa_close(STDERR_FILENO
);
3260 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3261 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3262 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3269 char *pa_read_line_from_file(const char *fn
) {
3271 char ln
[256] = "", *r
;
3273 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3276 r
= fgets(ln
, sizeof(ln
)-1, f
);
3285 return pa_xstrdup(ln
);
3288 pa_bool_t
pa_running_in_vm(void) {
3290 #if defined(__i386__) || defined(__x86_64__)
3292 /* Both CPUID and DMI are x86 specific interfaces... */
3294 uint32_t eax
= 0x40000000;
3301 const char *const dmi_vendors
[] = {
3302 "/sys/class/dmi/id/sys_vendor",
3303 "/sys/class/dmi/id/board_vendor",
3304 "/sys/class/dmi/id/bios_vendor"
3309 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3312 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3314 if (pa_startswith(s
, "QEMU") ||
3315 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3316 pa_startswith(s
, "VMware") ||
3317 pa_startswith(s
, "VMW") ||
3318 pa_startswith(s
, "Microsoft Corporation") ||
3319 pa_startswith(s
, "innotek GmbH") ||
3320 pa_startswith(s
, "Xen")) {
3332 /* http://lwn.net/Articles/301888/ */
3335 __asm__
__volatile__ (
3336 /* ebx/rbx is being used for PIC! */
3337 " push %%"PA_REG_b
" \n\t"
3339 " mov %%ebx, %1 \n\t"
3340 " pop %%"PA_REG_b
" \n\t"
3342 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3346 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3347 pa_streq(sig
.text
, "KVMKVMKVM") ||
3348 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3349 pa_streq(sig
.text
, "VMwareVMware") ||
3350 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3351 pa_streq(sig
.text
, "Microsoft Hv"))