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 #define PULSE_ROOTENV "PULSE_ROOT"
155 int pa_set_root(HANDLE handle
) {
156 char library_path
[MAX_PATH
], *sep
;
158 /* FIXME: Needs to set errno */
160 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
163 sep
= strrchr(library_path
, PA_PATH_SEP_CHAR
);
167 if (!SetEnvironmentVariable(PULSE_ROOTENV
, library_path
))
175 /** Make a file descriptor nonblock. Doesn't do any error checking */
176 void pa_make_fd_nonblock(int fd
) {
182 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
184 if (!(v
& O_NONBLOCK
))
185 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
187 #elif defined(OS_IS_WIN32)
189 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
190 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
191 pa_log_warn("Only sockets can be made non-blocking!");
194 pa_log_warn("Non-blocking I/O not supported.!");
199 /* Set the FD_CLOEXEC flag for a fd */
200 void pa_make_fd_cloexec(int fd
) {
206 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
208 if (!(v
& FD_CLOEXEC
))
209 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
214 /** Creates a directory securely */
215 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
217 int r
, saved_errno
, fd
;
226 u
= umask((~m
) & 0777);
232 if (r
< 0 && errno
!= EEXIST
)
235 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
249 if (fstat(fd
, &st
) < 0) {
250 pa_assert_se(pa_close(fd
) >= 0);
254 if (!S_ISDIR(st
.st_mode
)) {
255 pa_assert_se(pa_close(fd
) >= 0);
261 if (uid
== (uid_t
)-1)
263 if (gid
== (gid_t
)-1)
265 (void) fchown(fd
, uid
, gid
);
269 (void) fchmod(fd
, m
);
272 pa_assert_se(pa_close(fd
) >= 0);
276 if (lstat(dir
, &st
) < 0)
278 if (stat(dir
, &st
) < 0)
283 if (!S_ISDIR(st
.st_mode
) ||
284 (st
.st_uid
!= uid
) ||
285 (st
.st_gid
!= gid
) ||
286 ((st
.st_mode
& 0777) != m
)) {
291 pa_log_warn("Secure directory creation not supported on Win32.");
304 /* Return a newly allocated sting containing the parent directory of the specified file */
305 char *pa_parent_dir(const char *fn
) {
306 char *slash
, *dir
= pa_xstrdup(fn
);
308 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
318 /* Creates a the parent directory of the specified path securely */
319 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
323 if (!(dir
= pa_parent_dir(fn
)))
326 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
336 /** Platform independent read function. Necessary since not all
337 * systems treat all file descriptors equal. If type is
338 * non-NULL it is used to cache the type of the fd. This is
339 * useful for making sure that only a single syscall is executed per
340 * function call. The variable pointed to should be initialized to 0
342 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
346 if (!type
|| *type
== 0) {
349 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
352 if (WSAGetLastError() != WSAENOTSOCK
) {
353 errno
= WSAGetLastError();
366 if ((r
= read(fd
, buf
, count
)) < 0)
374 /** Similar to pa_read(), but handles writes */
375 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
377 if (!type
|| *type
== 0) {
381 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
393 if (WSAGetLastError() != WSAENOTSOCK
) {
394 errno
= WSAGetLastError();
398 if (errno
!= ENOTSOCK
)
409 if ((r
= write(fd
, buf
, count
)) < 0)
417 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
418 * unless EOF is reached or an error occurred */
419 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
435 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
442 data
= (uint8_t*) data
+ r
;
449 /** Similar to pa_loop_read(), but wraps write() */
450 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
466 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
473 data
= (const uint8_t*) data
+ r
;
480 /** Platform independent read function. Necessary since not all
481 * systems treat all file descriptors equal. */
482 int pa_close(int fd
) {
487 if ((ret
= closesocket(fd
)) == 0)
490 if (WSAGetLastError() != WSAENOTSOCK
) {
491 errno
= WSAGetLastError();
499 if ((r
= close(fd
)) < 0)
507 /* Print a warning messages in case that the given signal is not
508 * blocked or trapped */
509 void pa_check_signal_is_blocked(int sig
) {
510 #ifdef HAVE_SIGACTION
514 /* If POSIX threads are supported use thread-aware
515 * pthread_sigmask() function, to check if the signal is
516 * blocked. Otherwise fall back to sigprocmask() */
519 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
521 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
522 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
529 if (sigismember(&set
, sig
))
532 /* Check whether the signal is trapped */
534 if (sigaction(sig
, NULL
, &sa
) < 0) {
535 pa_log("sigaction(): %s", pa_cstrerror(errno
));
539 if (sa
.sa_handler
!= SIG_DFL
)
542 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
543 #else /* HAVE_SIGACTION */
544 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
548 /* The following function is based on an example from the GNU libc
549 * documentation. This function is similar to GNU's asprintf(). */
550 char *pa_sprintf_malloc(const char *format
, ...) {
560 c
= pa_xrealloc(c
, size
);
562 va_start(ap
, format
);
563 r
= vsnprintf(c
, size
, format
, ap
);
568 if (r
> -1 && (size_t) r
< size
)
571 if (r
> -1) /* glibc 2.1 */
578 /* Same as the previous function, but use a va_list instead of an
580 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
590 c
= pa_xrealloc(c
, size
);
593 r
= vsnprintf(c
, size
, format
, aq
);
598 if (r
> -1 && (size_t) r
< size
)
601 if (r
> -1) /* glibc 2.1 */
608 /* Similar to OpenBSD's strlcpy() function */
609 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
627 #ifdef _POSIX_PRIORITY_SCHEDULING
628 static int set_scheduler(int rtprio
) {
630 struct sched_param sp
;
636 dbus_error_init(&error
);
640 sp
.sched_priority
= rtprio
;
642 #ifdef SCHED_RESET_ON_FORK
643 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
644 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
649 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
650 pa_log_debug("SCHED_RR worked.");
653 #endif /* HAVE_SCHED_H */
656 /* Try to talk to RealtimeKit */
658 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
659 pa_log("Failed to connect to system bus: %s\n", error
.message
);
660 dbus_error_free(&error
);
665 /* We need to disable exit on disconnect because otherwise
666 * dbus_shutdown will kill us. See
667 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
668 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
670 r
= rtkit_make_realtime(bus
, 0, rtprio
);
671 dbus_connection_unref(bus
);
674 pa_log_debug("RealtimeKit worked.");
687 /* Make the current thread a realtime thread, and acquire the highest
688 * rtprio we can get that is less or equal the specified parameter. If
689 * the thread is already realtime, don't do anything. */
690 int pa_make_realtime(int rtprio
) {
692 #if defined(OS_IS_DARWIN)
693 struct thread_time_constraint_policy ttcpolicy
;
695 size_t size
= sizeof(freq
);
698 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
700 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
704 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
706 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
707 ttcpolicy
.period
= freq
/ 160;
708 ttcpolicy
.computation
= freq
/ 3300;
709 ttcpolicy
.constraint
= freq
/ 2200;
710 ttcpolicy
.preemptible
= 1;
712 ret
= thread_policy_set(mach_thread_self(),
713 THREAD_TIME_CONSTRAINT_POLICY
,
714 (thread_policy_t
) &ttcpolicy
,
715 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
717 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
721 pa_log_info("Successfully acquired real-time thread priority.");
724 #elif _POSIX_PRIORITY_SCHEDULING
727 if (set_scheduler(rtprio
) >= 0) {
728 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
732 for (p
= rtprio
-1; p
>= 1; p
--)
733 if (set_scheduler(p
) >= 0) {
734 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
737 #elif defined(OS_IS_WIN32)
738 /* Windows only allows realtime scheduling to be set on a per process basis.
739 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
740 if(SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
741 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
745 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
750 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
754 #ifdef HAVE_SYS_RESOURCE_H
755 static int set_nice(int nice_level
) {
761 dbus_error_init(&error
);
764 #ifdef HAVE_SYS_RESOURCE_H
765 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
766 pa_log_debug("setpriority() worked.");
772 /* Try to talk to RealtimeKit */
774 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
775 pa_log("Failed to connect to system bus: %s\n", error
.message
);
776 dbus_error_free(&error
);
781 /* We need to disable exit on disconnect because otherwise
782 * dbus_shutdown will kill us. See
783 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
784 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
786 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
787 dbus_connection_unref(bus
);
790 pa_log_debug("RealtimeKit worked.");
801 /* Raise the priority of the current process as much as possible that
802 * is <= the specified nice level..*/
803 int pa_raise_priority(int nice_level
) {
805 #ifdef HAVE_SYS_RESOURCE_H
808 if (set_nice(nice_level
) >= 0) {
809 pa_log_info("Successfully gained nice level %i.", nice_level
);
813 for (n
= nice_level
+1; n
< 0; n
++)
814 if (set_nice(n
) >= 0) {
815 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
819 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
824 if (nice_level
< 0) {
825 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
826 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
831 pa_log_info("Successfully gained high priority class.");
838 /* Reset the priority to normal, inverting the changes made by
839 * pa_raise_priority() and pa_make_realtime()*/
840 void pa_reset_priority(void) {
841 #ifdef HAVE_SYS_RESOURCE_H
842 struct sched_param sp
;
844 setpriority(PRIO_PROCESS
, 0, 0);
847 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
851 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
855 int pa_match(const char *expr
, const char *v
) {
860 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
865 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
867 else if (k
== REG_NOMATCH
)
880 /* Try to parse a boolean string value.*/
881 int pa_parse_boolean(const char *v
) {
885 /* First we check language independant */
886 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
888 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
891 #ifdef HAVE_LANGINFO_H
892 /* And then we check language dependant */
893 if ((expr
= nl_langinfo(YESEXPR
)))
895 if (pa_match(expr
, v
) > 0)
898 if ((expr
= nl_langinfo(NOEXPR
)))
900 if (pa_match(expr
, v
) > 0)
908 /* Split the specified string wherever one of the strings in delimiter
909 * occurs. Each time it is called returns a newly allocated string
910 * with pa_xmalloc(). The variable state points to, should be
911 * initiallized to NULL before the first call. */
912 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
913 const char *current
= *state
? *state
: c
;
919 l
= strcspn(current
, delimiter
);
925 return pa_xstrndup(current
, l
);
928 /* Split a string into words. Otherwise similar to pa_split(). */
929 char *pa_split_spaces(const char *c
, const char **state
) {
930 const char *current
= *state
? *state
: c
;
933 if (!*current
|| *c
== 0)
936 current
+= strspn(current
, WHITESPACE
);
937 l
= strcspn(current
, WHITESPACE
);
941 return pa_xstrndup(current
, l
);
944 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
946 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
947 const char *pa_sig2str(int sig
) {
960 char buf
[SIG2STR_MAX
];
962 if (sig2str(sig
, buf
) == 0) {
963 pa_xfree(PA_STATIC_TLS_GET(signame
));
964 t
= pa_sprintf_malloc("SIG%s", buf
);
965 PA_STATIC_TLS_SET(signame
, t
);
973 case SIGHUP
: return "SIGHUP";
975 case SIGINT
: return "SIGINT";
977 case SIGQUIT
: return "SIGQUIT";
979 case SIGILL
: return "SIGULL";
981 case SIGTRAP
: return "SIGTRAP";
983 case SIGABRT
: return "SIGABRT";
985 case SIGBUS
: return "SIGBUS";
987 case SIGFPE
: return "SIGFPE";
989 case SIGKILL
: return "SIGKILL";
992 case SIGUSR1
: return "SIGUSR1";
994 case SIGSEGV
: return "SIGSEGV";
996 case SIGUSR2
: return "SIGUSR2";
999 case SIGPIPE
: return "SIGPIPE";
1002 case SIGALRM
: return "SIGALRM";
1004 case SIGTERM
: return "SIGTERM";
1006 case SIGSTKFLT
: return "SIGSTKFLT";
1009 case SIGCHLD
: return "SIGCHLD";
1012 case SIGCONT
: return "SIGCONT";
1015 case SIGSTOP
: return "SIGSTOP";
1018 case SIGTSTP
: return "SIGTSTP";
1021 case SIGTTIN
: return "SIGTTIN";
1024 case SIGTTOU
: return "SIGTTOU";
1027 case SIGURG
: return "SIGURG";
1030 case SIGXCPU
: return "SIGXCPU";
1033 case SIGXFSZ
: return "SIGXFSZ";
1036 case SIGVTALRM
: return "SIGVTALRM";
1039 case SIGPROF
: return "SIGPROF";
1042 case SIGWINCH
: return "SIGWINCH";
1045 case SIGIO
: return "SIGIO";
1048 case SIGPWR
: return "SIGPWR";
1051 case SIGSYS
: return "SIGSYS";
1056 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1057 pa_xfree(PA_STATIC_TLS_GET(signame
));
1058 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1059 PA_STATIC_TLS_SET(signame
, t
);
1068 pa_xfree(PA_STATIC_TLS_GET(signame
));
1069 t
= pa_sprintf_malloc("SIG%i", sig
);
1070 PA_STATIC_TLS_SET(signame
, t
);
1076 /* Check whether the specified GID and the group name match */
1077 static int is_group(gid_t gid
, const char *name
) {
1078 struct group
*group
= NULL
;
1082 if (!(group
= pa_getgrgid_malloc(gid
))) {
1086 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1091 r
= strcmp(name
, group
->gr_name
) == 0;
1094 pa_getgrgid_free(group
);
1099 /* Check the current user is member of the specified group */
1100 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1101 GETGROUPS_T
*gids
, tgid
;
1102 long n
= sysconf(_SC_NGROUPS_MAX
);
1107 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1109 if ((n
= getgroups((int) n
, gids
)) < 0) {
1110 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1114 for (i
= 0; i
< n
; i
++) {
1116 if ((k
= is_group(gids
[i
], name
)) < 0)
1125 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1141 /* Check whether the specifc user id is a member of the specified group */
1142 int pa_uid_in_group(uid_t uid
, const char *name
) {
1143 struct group
*group
= NULL
;
1148 if (!(group
= pa_getgrnam_malloc(name
))) {
1155 for (i
= group
->gr_mem
; *i
; i
++) {
1156 struct passwd
*pw
= NULL
;
1159 if (!(pw
= pa_getpwnam_malloc(*i
)))
1162 if (pw
->pw_uid
== uid
)
1165 pa_getpwnam_free(pw
);
1172 pa_getgrnam_free(group
);
1177 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1178 gid_t
pa_get_gid_of_group(const char *name
) {
1179 gid_t ret
= (gid_t
) -1;
1180 struct group
*gr
= NULL
;
1183 if (!(gr
= pa_getgrnam_malloc(name
))) {
1192 pa_getgrnam_free(gr
);
1196 int pa_check_in_group(gid_t g
) {
1197 gid_t gids
[NGROUPS_MAX
];
1200 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1210 #else /* HAVE_GRP_H */
1212 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1218 int pa_uid_in_group(uid_t uid
, const char *name
) {
1223 gid_t
pa_get_gid_of_group(const char *name
) {
1228 int pa_check_in_group(gid_t g
) {
1235 /* Lock or unlock a file entirely.
1236 (advisory on UNIX, mandatory on Windows) */
1237 int pa_lock_fd(int fd
, int b
) {
1239 struct flock f_lock
;
1241 /* Try a R/W lock first */
1243 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1244 f_lock
.l_whence
= SEEK_SET
;
1248 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1251 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1252 if (b
&& errno
== EBADF
) {
1253 f_lock
.l_type
= F_RDLCK
;
1254 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1258 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1262 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
1264 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1266 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1269 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1271 /* FIXME: Needs to set errno! */
1277 /* Remove trailing newlines from a string */
1278 char* pa_strip_nl(char *s
) {
1281 s
[strcspn(s
, NEWLINE
)] = 0;
1285 char *pa_strip(char *s
) {
1288 /* Drops trailing whitespace. Modifies the string in
1289 * place. Returns pointer to first non-space character */
1291 s
+= strspn(s
, WHITESPACE
);
1293 for (e
= s
; *e
; e
++)
1294 if (!strchr(WHITESPACE
, *e
))
1305 /* Create a temporary lock file and lock it. */
1306 int pa_lock_lockfile(const char *fn
) {
1313 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1317 , S_IRUSR
|S_IWUSR
)) < 0) {
1318 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1322 if (pa_lock_fd(fd
, 1) < 0) {
1323 pa_log_warn("Failed to lock file '%s'.", fn
);
1327 if (fstat(fd
, &st
) < 0) {
1328 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1332 /* Check whether the file has been removed meanwhile. When yes,
1333 * restart this loop, otherwise, we're done */
1334 if (st
.st_nlink
>= 1)
1337 if (pa_lock_fd(fd
, 0) < 0) {
1338 pa_log_warn("Failed to unlock file '%s'.", fn
);
1342 if (pa_close(fd
) < 0) {
1343 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1354 int saved_errno
= errno
;
1356 errno
= saved_errno
;
1362 /* Unlock a temporary lcok file */
1363 int pa_unlock_lockfile(const char *fn
, int fd
) {
1368 if (unlink(fn
) < 0) {
1369 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1374 if (pa_lock_fd(fd
, 0) < 0) {
1375 pa_log_warn("Failed to unlock file '%s'.", fn
);
1379 if (pa_close(fd
) < 0) {
1380 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1387 static char *get_pulse_home(void) {
1392 if (!(h
= pa_get_home_dir_malloc())) {
1393 pa_log_error("Failed to get home directory.");
1397 if (stat(h
, &st
) < 0) {
1398 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1403 if (st
.st_uid
!= getuid()) {
1404 pa_log_error("Home directory %s not ours.", h
);
1410 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1418 char *pa_get_state_dir(void) {
1421 /* The state directory shall contain dynamic data that should be
1422 * kept across reboots, and is private to this user */
1424 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1425 if (!(d
= get_pulse_home()))
1428 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1429 * dir then this will break. */
1431 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1432 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1440 char *pa_get_home_dir_malloc(void) {
1442 size_t allocated
= 128;
1445 homedir
= pa_xmalloc(allocated
);
1447 if (!pa_get_home_dir(homedir
, allocated
)) {
1452 if (strlen(homedir
) < allocated
- 1)
1462 char *pa_get_binary_name_malloc(void) {
1464 size_t allocated
= 128;
1467 t
= pa_xmalloc(allocated
);
1469 if (!pa_get_binary_name(t
, allocated
)) {
1474 if (strlen(t
) < allocated
- 1)
1484 static char* make_random_dir(mode_t m
) {
1485 static const char table
[] =
1486 "abcdefghijklmnopqrstuvwxyz"
1487 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1493 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1494 pathlen
= strlen(fn
);
1502 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1503 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1505 u
= umask((~m
) & 0777);
1512 saved_errno
= errno
;
1514 errno
= saved_errno
;
1519 if (errno
!= EEXIST
) {
1520 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1527 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1530 if (!(p
= make_random_dir(m
)))
1534 if (symlink(p
, k
) < 0) {
1535 int saved_errno
= errno
;
1537 if (errno
!= EEXIST
)
1538 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1543 errno
= saved_errno
;
1555 char *pa_get_runtime_dir(void) {
1556 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1560 /* The runtime directory shall contain dynamic data that needs NOT
1561 * to be kept accross reboots and is usuallly private to the user,
1562 * except in system mode, where it might be accessible by other
1563 * users, too. Since we need POSIX locking and UNIX sockets in
1564 * this directory, we link it to a random subdir in /tmp, if it
1565 * was not explicitly configured. */
1567 m
= pa_in_system_mode() ? 0755U : 0700U;
1569 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1571 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1572 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1576 return pa_xstrdup(d
);
1579 if (!(d
= get_pulse_home()))
1582 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1583 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1588 if (!(mid
= pa_machine_id())) {
1593 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1598 /* OK, first let's check if the "runtime" symlink is already
1601 if (!(p
= pa_readlink(k
))) {
1603 if (errno
!= ENOENT
) {
1604 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1609 /* Hmm, so the runtime directory didn't exist yet, so let's
1610 * create one in /tmp and symlink that to it */
1612 if (make_random_dir_and_link(0700, k
) < 0) {
1614 /* Mhmm, maybe another process was quicker than us,
1615 * let's check if that was valid */
1616 if (errno
== EEXIST
)
1622 /* No symlink possible, so let's just create the runtime directly */
1630 /* Make sure that this actually makes sense */
1631 if (!pa_is_path_absolute(p
)) {
1632 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1637 /* Hmm, so this symlink is still around, make sure nobody fools
1641 if (lstat(p
, &st
) < 0) {
1643 if (errno
!= ENOENT
) {
1644 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1650 if (S_ISDIR(st
.st_mode
) &&
1651 (st
.st_uid
== getuid()) &&
1652 ((st
.st_mode
& 0777) == 0700)) {
1658 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1665 /* Hmm, so the link points to some nonexisting or invalid
1666 * dir. Let's replace it by a new link. We first create a
1667 * temporary link and then rename that to allow concurrent
1668 * execution of this function. */
1670 t
= pa_sprintf_malloc("%s.tmp", k
);
1672 if (make_random_dir_and_link(0700, t
) < 0) {
1674 if (errno
!= EEXIST
) {
1675 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1682 /* Hmm, someone lese was quicker then us. Let's give
1683 * him some time to finish, and retry. */
1688 /* OK, we succeeded in creating the temporary symlink, so
1689 * let's rename it */
1690 if (rename(t
, k
) < 0) {
1691 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1707 /* Try to open a configuration file. If "env" is specified, open the
1708 * value of the specified environment variable. Otherwise look for a
1709 * file "local" in the home directory or a file "global" in global
1710 * file system. If "result" is non-NULL, a pointer to a newly
1711 * allocated buffer containing the used configuration file is
1713 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1718 if (!getenv(PULSE_ROOTENV
))
1722 if (env
&& (fn
= getenv(env
))) {
1726 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1727 /* FIXME: Needs to set errno! */
1732 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1734 *result
= pa_xstrdup(fn
);
1739 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1749 if ((e
= getenv("PULSE_CONFIG_PATH")))
1750 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1751 else if ((h
= pa_get_home_dir_malloc())) {
1752 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1758 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1759 /* FIXME: Needs to set errno! */
1766 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1768 *result
= pa_xstrdup(fn
);
1774 if (errno
!= ENOENT
) {
1775 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1787 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1788 /* FIXME: Needs to set errno! */
1793 if ((f
= pa_fopen_cloexec(global
, "r"))) {
1796 *result
= pa_xstrdup(global
);
1806 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1811 if (!getenv(PULSE_ROOTENV
))
1815 if (env
&& (fn
= getenv(env
))) {
1818 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1819 /* FIXME: Needs to set errno! */
1824 if (access(fn
, R_OK
) == 0)
1825 return pa_xstrdup(fn
);
1827 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1836 if ((e
= getenv("PULSE_CONFIG_PATH")))
1837 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1838 else if ((h
= pa_get_home_dir_malloc())) {
1839 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1845 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1846 /* FIXME: Needs to set errno! */
1853 if (access(fn
, R_OK
) == 0) {
1854 char *r
= pa_xstrdup(fn
);
1859 if (errno
!= ENOENT
) {
1860 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1870 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1871 /* FIXME: Needs to set errno! */
1876 if (access(global
, R_OK
) == 0)
1877 return pa_xstrdup(global
);
1885 /* Format the specified data as a hexademical string */
1886 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1887 size_t i
= 0, j
= 0;
1888 const char hex
[] = "0123456789abcdef";
1892 pa_assert(slength
> 0);
1894 while (i
< dlength
&& j
+3 <= slength
) {
1895 s
[j
++] = hex
[*d
>> 4];
1896 s
[j
++] = hex
[*d
& 0xF];
1902 s
[j
< slength
? j
: slength
] = 0;
1906 /* Convert a hexadecimal digit to a number or -1 if invalid */
1907 static int hexc(char c
) {
1908 if (c
>= '0' && c
<= '9')
1911 if (c
>= 'A' && c
<= 'F')
1912 return c
- 'A' + 10;
1914 if (c
>= 'a' && c
<= 'f')
1915 return c
- 'a' + 10;
1921 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1922 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1928 while (j
< dlength
&& *p
) {
1931 if ((b
= hexc(*(p
++))) < 0)
1934 d
[j
] = (uint8_t) (b
<< 4);
1939 if ((b
= hexc(*(p
++))) < 0)
1942 d
[j
] |= (uint8_t) b
;
1949 /* Returns nonzero when *s starts with *pfx */
1950 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1958 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1961 /* Returns nonzero when *s ends with *sfx */
1962 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1971 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1974 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1980 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1984 char *pa_make_path_absolute(const char *p
) {
1990 if (pa_is_path_absolute(p
))
1991 return pa_xstrdup(p
);
1993 if (!(cwd
= pa_getcwd()))
1994 return pa_xstrdup(p
);
1996 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2001 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
2002 * if fn is non-null and starts with / return fn
2003 * otherwise append fn to the run time path and return it */
2004 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
2007 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2012 if (pa_is_path_absolute(fn
))
2013 return pa_xstrdup(fn
);
2021 if (!(mid
= pa_machine_id())) {
2026 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
2029 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
2037 char *pa_runtime_path(const char *fn
) {
2038 return get_path(fn
, FALSE
, TRUE
);
2041 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2042 return get_path(fn
, appendmid
, FALSE
);
2045 /* Convert the string s to a signed integer in *ret_i */
2046 int pa_atoi(const char *s
, int32_t *ret_i
) {
2054 l
= strtol(s
, &x
, 0);
2056 if (!x
|| *x
|| errno
) {
2062 if ((int32_t) l
!= l
) {
2067 *ret_i
= (int32_t) l
;
2072 /* Convert the string s to an unsigned integer in *ret_u */
2073 int pa_atou(const char *s
, uint32_t *ret_u
) {
2081 l
= strtoul(s
, &x
, 0);
2083 if (!x
|| *x
|| errno
) {
2089 if ((uint32_t) l
!= l
) {
2094 *ret_u
= (uint32_t) l
;
2099 #ifdef HAVE_STRTOF_L
2100 static locale_t c_locale
= NULL
;
2102 static void c_locale_destroy(void) {
2103 freelocale(c_locale
);
2107 int pa_atod(const char *s
, double *ret_d
) {
2114 /* This should be locale independent */
2116 #ifdef HAVE_STRTOF_L
2120 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2121 atexit(c_locale_destroy
);
2127 f
= strtod_l(s
, &x
, c_locale
);
2135 if (!x
|| *x
|| errno
) {
2146 /* Same as snprintf, but guarantees NUL-termination on every platform */
2147 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2152 pa_assert(size
> 0);
2155 va_start(ap
, format
);
2156 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2162 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2163 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2167 pa_assert(size
> 0);
2170 ret
= vsnprintf(str
, size
, format
, ap
);
2177 if ((size_t) ret
> size
-1)
2180 return (size_t) ret
;
2183 /* Truncate the specified string, but guarantee that the string
2184 * returned still validates as UTF8 */
2185 char *pa_truncate_utf8(char *c
, size_t l
) {
2187 pa_assert(pa_utf8_valid(c
));
2194 while (l
> 0 && !pa_utf8_valid(c
))
2200 char *pa_getcwd(void) {
2204 char *p
= pa_xmalloc(l
);
2208 if (errno
!= ERANGE
)
2216 void *pa_will_need(const void *p
, size_t l
) {
2217 #ifdef RLIMIT_MEMLOCK
2228 a
= PA_PAGE_ALIGN_PTR(p
);
2229 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2231 #ifdef HAVE_POSIX_MADVISE
2232 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2233 pa_log_debug("posix_madvise() worked fine!");
2238 /* Most likely the memory was not mmap()ed from a file and thus
2239 * madvise() didn't work, so let's misuse mlock() do page this
2240 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2241 * inviting, the man page of mlock() tells us: "All pages that
2242 * contain a part of the specified address range are guaranteed to
2243 * be resident in RAM when the call returns successfully." */
2245 #ifdef RLIMIT_MEMLOCK
2246 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2248 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2249 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
));
2254 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2256 bs
= PA_PAGE_SIZE
*4;
2259 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2262 while (size
> 0 && bs
> 0) {
2267 if (mlock(a
, bs
) < 0) {
2268 bs
= PA_PAGE_ALIGN(bs
/ 2);
2272 pa_assert_se(munlock(a
, bs
) == 0);
2274 a
= (const uint8_t*) a
+ bs
;
2280 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2282 pa_log_debug("mlock() worked fine!");
2287 void pa_close_pipe(int fds
[2]) {
2291 pa_assert_se(pa_close(fds
[0]) == 0);
2294 pa_assert_se(pa_close(fds
[1]) == 0);
2296 fds
[0] = fds
[1] = -1;
2299 char *pa_readlink(const char *p
) {
2300 #ifdef HAVE_READLINK
2309 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2314 if ((size_t) n
< l
-1) {
2327 int pa_close_all(int except_fd
, ...) {
2332 va_start(ap
, except_fd
);
2335 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2340 p
= pa_xnew(int, n
+1);
2342 va_start(ap
, except_fd
);
2345 if (except_fd
>= 0) {
2349 while ((fd
= va_arg(ap
, int)) >= 0)
2356 r
= pa_close_allv(p
);
2362 int pa_close_allv(const int except_fds
[]) {
2371 if ((d
= opendir("/proc/self/fd"))) {
2375 while ((de
= readdir(d
))) {
2381 if (de
->d_name
[0] == '.')
2385 l
= strtol(de
->d_name
, &e
, 10);
2386 if (errno
!= 0 || !e
|| *e
) {
2394 if ((long) fd
!= l
) {
2407 for (i
= 0; except_fds
[i
] >= 0; i
++)
2408 if (except_fds
[i
] == fd
) {
2416 if (pa_close(fd
) < 0) {
2417 saved_errno
= errno
;
2419 errno
= saved_errno
;
2431 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2432 maxfd
= (int) rl
.rlim_max
;
2434 maxfd
= sysconf(_SC_OPEN_MAX
);
2436 for (fd
= 3; fd
< maxfd
; fd
++) {
2441 for (i
= 0; except_fds
[i
] >= 0; i
++)
2442 if (except_fds
[i
] == fd
) {
2450 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2453 #endif /* !OS_IS_WIN32 */
2458 int pa_unblock_sigs(int except
, ...) {
2463 va_start(ap
, except
);
2466 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2471 p
= pa_xnew(int, n
+1);
2473 va_start(ap
, except
);
2480 while ((sig
= va_arg(ap
, int)) >= 0)
2487 r
= pa_unblock_sigsv(p
);
2493 int pa_unblock_sigsv(const int except
[]) {
2498 if (sigemptyset(&ss
) < 0)
2501 for (i
= 0; except
[i
] > 0; i
++)
2502 if (sigaddset(&ss
, except
[i
]) < 0)
2505 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2511 int pa_reset_sigs(int except
, ...) {
2516 va_start(ap
, except
);
2519 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2524 p
= pa_xnew(int, n
+1);
2526 va_start(ap
, except
);
2533 while ((sig
= va_arg(ap
, int)) >= 0)
2540 r
= pa_reset_sigsv(p
);
2546 int pa_reset_sigsv(const int except
[]) {
2550 for (sig
= 1; sig
< NSIG
; sig
++) {
2551 pa_bool_t reset
= TRUE
;
2562 for (i
= 0; except
[i
] > 0; i
++) {
2563 if (sig
== except
[i
]) {
2572 struct sigaction sa
;
2574 memset(&sa
, 0, sizeof(sa
));
2575 sa
.sa_handler
= SIG_DFL
;
2577 /* On Linux the first two RT signals are reserved by
2578 * glibc, and sigaction() will return EINVAL for them. */
2579 if ((sigaction(sig
, &sa
, NULL
) < 0))
2580 if (errno
!= EINVAL
)
2589 void pa_set_env(const char *key
, const char *value
) {
2593 /* This is not thread-safe */
2596 SetEnvironmentVariable(key
, value
);
2598 setenv(key
, value
, 1);
2602 void pa_set_env_and_record(const char *key
, const char *value
) {
2606 /* This is not thread-safe */
2608 pa_set_env(key
, value
);
2609 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2612 void pa_unset_env_recorded(void) {
2614 /* This is not thread-safe */
2619 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2625 SetEnvironmentVariable(s
, NULL
);
2633 pa_bool_t
pa_in_system_mode(void) {
2636 if (!(e
= getenv("PULSE_SYSTEM")))
2642 char *pa_get_user_name_malloc(void) {
2646 #ifdef _SC_LOGIN_NAME_MAX
2647 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2653 u
= pa_xnew(char, k
+1);
2655 if (!(pa_get_user_name(u
, k
))) {
2663 char *pa_get_host_name_malloc(void) {
2672 if (!pa_get_host_name(c
, l
)) {
2674 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2677 } else if (strlen(c
) < l
-1) {
2685 u
= pa_utf8_filter(c
);
2690 /* Hmm, the hostname is as long the space we offered the
2691 * function, we cannot know if it fully fit in, so let's play
2692 * safe and retry. */
2701 char *pa_machine_id(void) {
2705 /* The returned value is supposed be some kind of ascii identifier
2706 * that is unique and stable across reboots. */
2708 /* First we try the D-Bus UUID, which is the best option we have,
2709 * since it fits perfectly our needs and is not as volatile as the
2710 * hostname which might be set from dhcp. */
2712 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2713 char ln
[34] = "", *r
;
2715 r
= fgets(ln
, sizeof(ln
)-1, f
);
2721 return pa_utf8_filter(ln
);
2724 if ((h
= pa_get_host_name_malloc()))
2728 /* If no hostname was set we use the POSIX hostid. It's usually
2729 * the IPv4 address. Might not be that stable. */
2730 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2736 char *pa_session_id(void) {
2739 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2742 return pa_utf8_filter(e
);
2745 char *pa_uname_string(void) {
2749 pa_assert_se(uname(&u
) >= 0);
2751 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2757 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2758 pa_assert_se(GetVersionEx(&i
));
2760 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2764 #ifdef HAVE_VALGRIND_MEMCHECK_H
2765 pa_bool_t
pa_in_valgrind(void) {
2768 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2769 * here instead of really checking whether we run in valgrind or
2773 b
= getenv("VALGRIND") ? 2 : 1;
2779 unsigned pa_gcd(unsigned a
, unsigned b
) {
2790 void pa_reduce(unsigned *num
, unsigned *den
) {
2792 unsigned gcd
= pa_gcd(*num
, *den
);
2800 pa_assert(pa_gcd(*num
, *den
) == 1);
2803 unsigned pa_ncpus(void) {
2806 #ifdef _SC_NPROCESSORS_CONF
2807 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2812 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2815 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2824 sb
= pa_strbuf_new();
2829 if (!(p
= strstr(s
, a
)))
2832 pa_strbuf_putsn(sb
, s
, p
-s
);
2833 pa_strbuf_puts(sb
, b
);
2837 pa_strbuf_puts(sb
, s
);
2839 return pa_strbuf_tostring_free(sb
);
2842 char *pa_escape(const char *p
, const char *chars
) {
2845 pa_strbuf
*buf
= pa_strbuf_new();
2847 for (s
= p
; *s
; ++s
) {
2849 pa_strbuf_putc(buf
, '\\');
2851 for (c
= chars
; *c
; ++c
) {
2853 pa_strbuf_putc(buf
, '\\');
2858 pa_strbuf_putc(buf
, *s
);
2861 return pa_strbuf_tostring_free(buf
);
2864 char *pa_unescape(char *p
) {
2866 pa_bool_t escaped
= FALSE
;
2868 for (s
= p
, d
= p
; *s
; s
++) {
2869 if (!escaped
&& *s
== '\\') {
2883 char *pa_realpath(const char *path
) {
2887 /* We want only abolsute paths */
2888 if (path
[0] != '/') {
2893 #if defined(__GLIBC__) || defined(__APPLE__)
2897 if (!(r
= realpath(path
, NULL
)))
2900 /* We copy this here in case our pa_xmalloc() is not
2901 * implemented on top of libc malloc() */
2905 #elif defined(PATH_MAX)
2908 path_buf
= pa_xmalloc(PATH_MAX
);
2910 #if defined(OS_IS_WIN32)
2911 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2916 if (!(t
= realpath(path
, path_buf
))) {
2923 #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."
2929 void pa_disable_sigpipe(void) {
2932 struct sigaction sa
;
2936 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2937 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2941 sa
.sa_handler
= SIG_IGN
;
2943 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2944 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2950 void pa_xfreev(void**a
) {
2956 for (p
= a
; *p
; p
++)
2962 char **pa_split_spaces_strv(const char *s
) {
2964 unsigned i
= 0, n
= 8;
2965 const char *state
= NULL
;
2967 t
= pa_xnew(char*, n
);
2968 while ((e
= pa_split_spaces(s
, &state
))) {
2973 t
= pa_xrenew(char*, t
, n
);
2986 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2989 if (pa_is_path_absolute(path
))
2990 return pa_xstrdup(path
);
2992 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2995 size_t pa_pipe_buf(int fd
) {
3000 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3011 void pa_reset_personality(void) {
3014 if (personality(PER_LINUX
) < 0)
3015 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3020 #if defined(__linux__) && !defined(__OPTIMIZE__)
3022 pa_bool_t
pa_run_from_build_tree(void) {
3024 pa_bool_t b
= FALSE
;
3026 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
3029 if ((rp
= pa_readlink("/proc/self/exe"))) {
3030 b
= pa_startswith(rp
, PA_BUILDDIR
);
3039 const char *pa_get_temp_dir(void) {
3042 if ((t
= getenv("TMPDIR")) &&
3043 pa_is_path_absolute(t
))
3046 if ((t
= getenv("TMP")) &&
3047 pa_is_path_absolute(t
))
3050 if ((t
= getenv("TEMP")) &&
3051 pa_is_path_absolute(t
))
3054 if ((t
= getenv("TEMPDIR")) &&
3055 pa_is_path_absolute(t
))
3061 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3069 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3072 if (errno
!= EINVAL
)
3076 if ((fd
= open(fn
, flags
, mode
)) < 0)
3080 /* Some implementations might simply ignore O_CLOEXEC if it is not
3081 * understood, make sure FD_CLOEXEC is enabled anyway */
3083 pa_make_fd_cloexec(fd
);
3087 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3091 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3094 if (errno
!= EINVAL
)
3098 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3102 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3103 * not understood, make sure FD_CLOEXEC is enabled anyway */
3105 pa_make_fd_cloexec(fd
);
3109 int pa_pipe_cloexec(int pipefd
[2]) {
3113 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3116 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3121 if ((r
= pipe(pipefd
)) < 0)
3125 pa_make_fd_cloexec(pipefd
[0]);
3126 pa_make_fd_cloexec(pipefd
[1]);
3131 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3135 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3138 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3143 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3147 pa_make_fd_cloexec(fd
);
3151 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3155 m
= pa_sprintf_malloc("%se", mode
);
3158 if ((f
= fopen(path
, m
))) {
3165 if (errno
!= EINVAL
)
3168 if (!(f
= fopen(path
, mode
)))
3172 pa_make_fd_cloexec(fileno(f
));
3176 void pa_nullify_stdfds(void) {
3179 pa_close(STDIN_FILENO
);
3180 pa_close(STDOUT_FILENO
);
3181 pa_close(STDERR_FILENO
);
3183 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3184 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3185 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3192 char *pa_read_line_from_file(const char *fn
) {
3194 char ln
[256] = "", *r
;
3196 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3199 r
= fgets(ln
, sizeof(ln
)-1, f
);
3208 return pa_xstrdup(ln
);
3211 pa_bool_t
pa_running_in_vm(void) {
3213 #if defined(__i386__) || defined(__x86_64__)
3215 /* Both CPUID and DMI are x86 specific interfaces... */
3217 uint32_t eax
= 0x40000000;
3224 const char *const dmi_vendors
[] = {
3225 "/sys/class/dmi/id/sys_vendor",
3226 "/sys/class/dmi/id/board_vendor",
3227 "/sys/class/dmi/id/bios_vendor"
3232 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3235 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3237 if (pa_startswith(s
, "QEMU") ||
3238 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3239 pa_startswith(s
, "VMware") ||
3240 pa_startswith(s
, "VMW") ||
3241 pa_startswith(s
, "Microsoft Corporation") ||
3242 pa_startswith(s
, "innotek GmbH") ||
3243 pa_startswith(s
, "Xen")) {
3255 /* http://lwn.net/Articles/301888/ */
3258 __asm__
__volatile__ (
3259 /* ebx/rbx is being used for PIC! */
3260 " push %%"PA_REG_b
" \n\t"
3262 " mov %%ebx, %1 \n\t"
3263 " pop %%"PA_REG_b
" \n\t"
3265 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3269 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3270 pa_streq(sig
.text
, "KVMKVMKVM") ||
3271 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3272 pa_streq(sig
.text
, "VMwareVMware") ||
3273 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3274 pa_streq(sig
.text
, "Microsoft Hv"))