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
&& (strcmp(p
+ 1, "bin") == 0))
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
) {
222 int r
, saved_errno
, fd
;
231 u
= umask((~m
) & 0777);
237 if (r
< 0 && errno
!= EEXIST
)
240 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
254 if (fstat(fd
, &st
) < 0) {
255 pa_assert_se(pa_close(fd
) >= 0);
259 if (!S_ISDIR(st
.st_mode
)) {
260 pa_assert_se(pa_close(fd
) >= 0);
266 if (uid
== (uid_t
) -1)
268 if (gid
== (gid_t
) -1)
270 if (fchown(fd
, uid
, gid
) < 0)
275 (void) fchmod(fd
, m
);
278 pa_assert_se(pa_close(fd
) >= 0);
282 if (lstat(dir
, &st
) < 0)
284 if (stat(dir
, &st
) < 0)
289 if (!S_ISDIR(st
.st_mode
) ||
290 (st
.st_uid
!= uid
) ||
291 (st
.st_gid
!= gid
) ||
292 ((st
.st_mode
& 0777) != m
)) {
297 pa_log_warn("Secure directory creation not supported on Win32.");
310 /* Return a newly allocated sting containing the parent directory of the specified file */
311 char *pa_parent_dir(const char *fn
) {
312 char *slash
, *dir
= pa_xstrdup(fn
);
314 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
324 /* Creates a the parent directory of the specified path securely */
325 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
329 if (!(dir
= pa_parent_dir(fn
)))
332 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
342 /** Platform independent read function. Necessary since not all
343 * systems treat all file descriptors equal. If type is
344 * non-NULL it is used to cache the type of the fd. This is
345 * useful for making sure that only a single syscall is executed per
346 * function call. The variable pointed to should be initialized to 0
348 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
352 if (!type
|| *type
== 0) {
355 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
358 if (WSAGetLastError() != WSAENOTSOCK
) {
359 errno
= WSAGetLastError();
372 if ((r
= read(fd
, buf
, count
)) < 0)
380 /** Similar to pa_read(), but handles writes */
381 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
383 if (!type
|| *type
== 0) {
387 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
399 if (WSAGetLastError() != WSAENOTSOCK
) {
400 errno
= WSAGetLastError();
404 if (errno
!= ENOTSOCK
)
415 if ((r
= write(fd
, buf
, count
)) < 0)
423 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
424 * unless EOF is reached or an error occurred */
425 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
441 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
448 data
= (uint8_t*) data
+ r
;
455 /** Similar to pa_loop_read(), but wraps write() */
456 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
472 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
479 data
= (const uint8_t*) data
+ r
;
486 /** Platform independent read function. Necessary since not all
487 * systems treat all file descriptors equal. */
488 int pa_close(int fd
) {
493 if ((ret
= closesocket(fd
)) == 0)
496 if (WSAGetLastError() != WSAENOTSOCK
) {
497 errno
= WSAGetLastError();
505 if ((r
= close(fd
)) < 0)
513 /* Print a warning messages in case that the given signal is not
514 * blocked or trapped */
515 void pa_check_signal_is_blocked(int sig
) {
516 #ifdef HAVE_SIGACTION
520 /* If POSIX threads are supported use thread-aware
521 * pthread_sigmask() function, to check if the signal is
522 * blocked. Otherwise fall back to sigprocmask() */
525 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
527 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
528 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
535 if (sigismember(&set
, sig
))
538 /* Check whether the signal is trapped */
540 if (sigaction(sig
, NULL
, &sa
) < 0) {
541 pa_log("sigaction(): %s", pa_cstrerror(errno
));
545 if (sa
.sa_handler
!= SIG_DFL
)
548 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
549 #else /* HAVE_SIGACTION */
550 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
554 /* The following function is based on an example from the GNU libc
555 * documentation. This function is similar to GNU's asprintf(). */
556 char *pa_sprintf_malloc(const char *format
, ...) {
566 c
= pa_xrealloc(c
, size
);
568 va_start(ap
, format
);
569 r
= vsnprintf(c
, size
, format
, ap
);
574 if (r
> -1 && (size_t) r
< size
)
577 if (r
> -1) /* glibc 2.1 */
584 /* Same as the previous function, but use a va_list instead of an
586 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
596 c
= pa_xrealloc(c
, size
);
599 r
= vsnprintf(c
, size
, format
, aq
);
604 if (r
> -1 && (size_t) r
< size
)
607 if (r
> -1) /* glibc 2.1 */
614 /* Similar to OpenBSD's strlcpy() function */
615 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
633 #ifdef _POSIX_PRIORITY_SCHEDULING
634 static int set_scheduler(int rtprio
) {
636 struct sched_param sp
;
642 dbus_error_init(&error
);
646 sp
.sched_priority
= rtprio
;
648 #ifdef SCHED_RESET_ON_FORK
649 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
650 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
655 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
656 pa_log_debug("SCHED_RR worked.");
659 #endif /* HAVE_SCHED_H */
662 /* Try to talk to RealtimeKit */
664 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
665 pa_log("Failed to connect to system bus: %s\n", error
.message
);
666 dbus_error_free(&error
);
671 /* We need to disable exit on disconnect because otherwise
672 * dbus_shutdown will kill us. See
673 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
674 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
676 r
= rtkit_make_realtime(bus
, 0, rtprio
);
677 dbus_connection_close(bus
);
678 dbus_connection_unref(bus
);
681 pa_log_debug("RealtimeKit worked.");
694 /* Make the current thread a realtime thread, and acquire the highest
695 * rtprio we can get that is less or equal the specified parameter. If
696 * the thread is already realtime, don't do anything. */
697 int pa_make_realtime(int rtprio
) {
699 #if defined(OS_IS_DARWIN)
700 struct thread_time_constraint_policy ttcpolicy
;
702 size_t size
= sizeof(freq
);
705 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
707 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
711 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
713 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
714 ttcpolicy
.period
= freq
/ 160;
715 ttcpolicy
.computation
= freq
/ 3300;
716 ttcpolicy
.constraint
= freq
/ 2200;
717 ttcpolicy
.preemptible
= 1;
719 ret
= thread_policy_set(mach_thread_self(),
720 THREAD_TIME_CONSTRAINT_POLICY
,
721 (thread_policy_t
) &ttcpolicy
,
722 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
724 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
728 pa_log_info("Successfully acquired real-time thread priority.");
731 #elif _POSIX_PRIORITY_SCHEDULING
734 if (set_scheduler(rtprio
) >= 0) {
735 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
739 for (p
= rtprio
-1; p
>= 1; p
--)
740 if (set_scheduler(p
) >= 0) {
741 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
744 #elif defined(OS_IS_WIN32)
745 /* Windows only allows realtime scheduling to be set on a per process basis.
746 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
747 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
748 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
752 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
757 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
761 #ifdef HAVE_SYS_RESOURCE_H
762 static int set_nice(int nice_level
) {
768 dbus_error_init(&error
);
771 #ifdef HAVE_SYS_RESOURCE_H
772 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
773 pa_log_debug("setpriority() worked.");
779 /* Try to talk to RealtimeKit */
781 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
782 pa_log("Failed to connect to system bus: %s\n", error
.message
);
783 dbus_error_free(&error
);
788 /* We need to disable exit on disconnect because otherwise
789 * dbus_shutdown will kill us. See
790 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
791 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
793 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
794 dbus_connection_unref(bus
);
797 pa_log_debug("RealtimeKit worked.");
808 /* Raise the priority of the current process as much as possible that
809 * is <= the specified nice level..*/
810 int pa_raise_priority(int nice_level
) {
812 #ifdef HAVE_SYS_RESOURCE_H
815 if (set_nice(nice_level
) >= 0) {
816 pa_log_info("Successfully gained nice level %i.", nice_level
);
820 for (n
= nice_level
+1; n
< 0; n
++)
821 if (set_nice(n
) >= 0) {
822 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
826 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
831 if (nice_level
< 0) {
832 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
833 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
838 pa_log_info("Successfully gained high priority class.");
845 /* Reset the priority to normal, inverting the changes made by
846 * pa_raise_priority() and pa_make_realtime()*/
847 void pa_reset_priority(void) {
848 #ifdef HAVE_SYS_RESOURCE_H
849 struct sched_param sp
;
851 setpriority(PRIO_PROCESS
, 0, 0);
854 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
858 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
862 int pa_match(const char *expr
, const char *v
) {
867 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
872 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
874 else if (k
== REG_NOMATCH
)
887 /* Try to parse a boolean string value.*/
888 int pa_parse_boolean(const char *v
) {
892 /* First we check language independant */
893 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
895 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
898 #ifdef HAVE_LANGINFO_H
899 /* And then we check language dependant */
900 if ((expr
= nl_langinfo(YESEXPR
)))
902 if (pa_match(expr
, v
) > 0)
905 if ((expr
= nl_langinfo(NOEXPR
)))
907 if (pa_match(expr
, v
) > 0)
915 /* Split the specified string wherever one of the strings in delimiter
916 * occurs. Each time it is called returns a newly allocated string
917 * with pa_xmalloc(). The variable state points to, should be
918 * initiallized to NULL before the first call. */
919 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
920 const char *current
= *state
? *state
: c
;
926 l
= strcspn(current
, delimiter
);
932 return pa_xstrndup(current
, l
);
935 /* Split a string into words. Otherwise similar to pa_split(). */
936 char *pa_split_spaces(const char *c
, const char **state
) {
937 const char *current
= *state
? *state
: c
;
940 if (!*current
|| *c
== 0)
943 current
+= strspn(current
, WHITESPACE
);
944 l
= strcspn(current
, WHITESPACE
);
948 return pa_xstrndup(current
, l
);
951 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
953 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
954 const char *pa_sig2str(int sig
) {
967 char buf
[SIG2STR_MAX
];
969 if (sig2str(sig
, buf
) == 0) {
970 pa_xfree(PA_STATIC_TLS_GET(signame
));
971 t
= pa_sprintf_malloc("SIG%s", buf
);
972 PA_STATIC_TLS_SET(signame
, t
);
980 case SIGHUP
: return "SIGHUP";
982 case SIGINT
: return "SIGINT";
984 case SIGQUIT
: return "SIGQUIT";
986 case SIGILL
: return "SIGULL";
988 case SIGTRAP
: return "SIGTRAP";
990 case SIGABRT
: return "SIGABRT";
992 case SIGBUS
: return "SIGBUS";
994 case SIGFPE
: return "SIGFPE";
996 case SIGKILL
: return "SIGKILL";
999 case SIGUSR1
: return "SIGUSR1";
1001 case SIGSEGV
: return "SIGSEGV";
1003 case SIGUSR2
: return "SIGUSR2";
1006 case SIGPIPE
: return "SIGPIPE";
1009 case SIGALRM
: return "SIGALRM";
1011 case SIGTERM
: return "SIGTERM";
1013 case SIGSTKFLT
: return "SIGSTKFLT";
1016 case SIGCHLD
: return "SIGCHLD";
1019 case SIGCONT
: return "SIGCONT";
1022 case SIGSTOP
: return "SIGSTOP";
1025 case SIGTSTP
: return "SIGTSTP";
1028 case SIGTTIN
: return "SIGTTIN";
1031 case SIGTTOU
: return "SIGTTOU";
1034 case SIGURG
: return "SIGURG";
1037 case SIGXCPU
: return "SIGXCPU";
1040 case SIGXFSZ
: return "SIGXFSZ";
1043 case SIGVTALRM
: return "SIGVTALRM";
1046 case SIGPROF
: return "SIGPROF";
1049 case SIGWINCH
: return "SIGWINCH";
1052 case SIGIO
: return "SIGIO";
1055 case SIGPWR
: return "SIGPWR";
1058 case SIGSYS
: return "SIGSYS";
1063 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1064 pa_xfree(PA_STATIC_TLS_GET(signame
));
1065 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1066 PA_STATIC_TLS_SET(signame
, t
);
1075 pa_xfree(PA_STATIC_TLS_GET(signame
));
1076 t
= pa_sprintf_malloc("SIG%i", sig
);
1077 PA_STATIC_TLS_SET(signame
, t
);
1083 /* Check whether the specified GID and the group name match */
1084 static int is_group(gid_t gid
, const char *name
) {
1085 struct group
*group
= NULL
;
1089 if (!(group
= pa_getgrgid_malloc(gid
))) {
1093 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1098 r
= strcmp(name
, group
->gr_name
) == 0;
1101 pa_getgrgid_free(group
);
1106 /* Check the current user is member of the specified group */
1107 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1108 GETGROUPS_T
*gids
, tgid
;
1109 long n
= sysconf(_SC_NGROUPS_MAX
);
1114 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1116 if ((n
= getgroups((int) n
, gids
)) < 0) {
1117 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1121 for (i
= 0; i
< n
; i
++) {
1123 if ((k
= is_group(gids
[i
], name
)) < 0)
1132 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1148 /* Check whether the specifc user id is a member of the specified group */
1149 int pa_uid_in_group(uid_t uid
, const char *name
) {
1150 struct group
*group
= NULL
;
1155 if (!(group
= pa_getgrnam_malloc(name
))) {
1162 for (i
= group
->gr_mem
; *i
; i
++) {
1163 struct passwd
*pw
= NULL
;
1166 if (!(pw
= pa_getpwnam_malloc(*i
)))
1169 if (pw
->pw_uid
== uid
)
1172 pa_getpwnam_free(pw
);
1179 pa_getgrnam_free(group
);
1184 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1185 gid_t
pa_get_gid_of_group(const char *name
) {
1186 gid_t ret
= (gid_t
) -1;
1187 struct group
*gr
= NULL
;
1190 if (!(gr
= pa_getgrnam_malloc(name
))) {
1199 pa_getgrnam_free(gr
);
1203 int pa_check_in_group(gid_t g
) {
1204 gid_t gids
[NGROUPS_MAX
];
1207 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1217 #else /* HAVE_GRP_H */
1219 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1225 int pa_uid_in_group(uid_t uid
, const char *name
) {
1230 gid_t
pa_get_gid_of_group(const char *name
) {
1235 int pa_check_in_group(gid_t g
) {
1242 /* Lock or unlock a file entirely.
1243 (advisory on UNIX, mandatory on Windows) */
1244 int pa_lock_fd(int fd
, int b
) {
1246 struct flock f_lock
;
1248 /* Try a R/W lock first */
1250 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1251 f_lock
.l_whence
= SEEK_SET
;
1255 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1258 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1259 if (b
&& errno
== EBADF
) {
1260 f_lock
.l_type
= F_RDLCK
;
1261 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1265 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1269 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1271 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1273 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1276 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1278 /* FIXME: Needs to set errno! */
1284 /* Remove trailing newlines from a string */
1285 char* pa_strip_nl(char *s
) {
1288 s
[strcspn(s
, NEWLINE
)] = 0;
1292 char *pa_strip(char *s
) {
1295 /* Drops trailing whitespace. Modifies the string in
1296 * place. Returns pointer to first non-space character */
1298 s
+= strspn(s
, WHITESPACE
);
1300 for (e
= s
; *e
; e
++)
1301 if (!strchr(WHITESPACE
, *e
))
1312 /* Create a temporary lock file and lock it. */
1313 int pa_lock_lockfile(const char *fn
) {
1320 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1324 , S_IRUSR
|S_IWUSR
)) < 0) {
1325 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1329 if (pa_lock_fd(fd
, 1) < 0) {
1330 pa_log_warn("Failed to lock file '%s'.", fn
);
1334 if (fstat(fd
, &st
) < 0) {
1335 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1339 /* Check whether the file has been removed meanwhile. When yes,
1340 * restart this loop, otherwise, we're done */
1341 if (st
.st_nlink
>= 1)
1344 if (pa_lock_fd(fd
, 0) < 0) {
1345 pa_log_warn("Failed to unlock file '%s'.", fn
);
1349 if (pa_close(fd
) < 0) {
1350 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1361 int saved_errno
= errno
;
1363 errno
= saved_errno
;
1369 /* Unlock a temporary lcok file */
1370 int pa_unlock_lockfile(const char *fn
, int fd
) {
1375 if (unlink(fn
) < 0) {
1376 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1381 if (pa_lock_fd(fd
, 0) < 0) {
1382 pa_log_warn("Failed to unlock file '%s'.", fn
);
1386 if (pa_close(fd
) < 0) {
1387 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1394 static char *get_pulse_home(void) {
1399 if (!(h
= pa_get_home_dir_malloc())) {
1400 pa_log_error("Failed to get home directory.");
1404 if (stat(h
, &st
) < 0) {
1405 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1410 if (st
.st_uid
!= getuid()) {
1411 pa_log_error("Home directory %s not ours.", h
);
1417 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1425 char *pa_get_state_dir(void) {
1428 /* The state directory shall contain dynamic data that should be
1429 * kept across reboots, and is private to this user */
1431 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1432 if (!(d
= get_pulse_home()))
1435 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1436 * dir then this will break. */
1438 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1439 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1447 char *pa_get_home_dir_malloc(void) {
1449 size_t allocated
= 128;
1452 homedir
= pa_xmalloc(allocated
);
1454 if (!pa_get_home_dir(homedir
, allocated
)) {
1459 if (strlen(homedir
) < allocated
- 1)
1469 char *pa_get_binary_name_malloc(void) {
1471 size_t allocated
= 128;
1474 t
= pa_xmalloc(allocated
);
1476 if (!pa_get_binary_name(t
, allocated
)) {
1481 if (strlen(t
) < allocated
- 1)
1491 static char* make_random_dir(mode_t m
) {
1492 static const char table
[] =
1493 "abcdefghijklmnopqrstuvwxyz"
1494 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1500 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1501 pathlen
= strlen(fn
);
1509 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1510 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1512 u
= umask((~m
) & 0777);
1519 saved_errno
= errno
;
1521 errno
= saved_errno
;
1526 if (errno
!= EEXIST
) {
1527 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1534 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1537 if (!(p
= make_random_dir(m
)))
1541 if (symlink(p
, k
) < 0) {
1542 int saved_errno
= errno
;
1544 if (errno
!= EEXIST
)
1545 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1550 errno
= saved_errno
;
1562 char *pa_get_runtime_dir(void) {
1563 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1567 /* The runtime directory shall contain dynamic data that needs NOT
1568 * to be kept accross reboots and is usuallly private to the user,
1569 * except in system mode, where it might be accessible by other
1570 * users, too. Since we need POSIX locking and UNIX sockets in
1571 * this directory, we link it to a random subdir in /tmp, if it
1572 * was not explicitly configured. */
1574 m
= pa_in_system_mode() ? 0755U : 0700U;
1576 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1578 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1579 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1583 return pa_xstrdup(d
);
1586 if (!(d
= get_pulse_home()))
1589 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1590 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1595 if (!(mid
= pa_machine_id())) {
1600 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1605 /* OK, first let's check if the "runtime" symlink is already
1608 if (!(p
= pa_readlink(k
))) {
1610 if (errno
!= ENOENT
) {
1611 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1616 /* Hmm, so the runtime directory didn't exist yet, so let's
1617 * create one in /tmp and symlink that to it */
1619 if (make_random_dir_and_link(0700, k
) < 0) {
1621 /* Mhmm, maybe another process was quicker than us,
1622 * let's check if that was valid */
1623 if (errno
== EEXIST
)
1629 /* No symlink possible, so let's just create the runtime directly */
1637 /* Make sure that this actually makes sense */
1638 if (!pa_is_path_absolute(p
)) {
1639 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1644 /* Hmm, so this symlink is still around, make sure nobody fools
1648 if (lstat(p
, &st
) < 0) {
1650 if (errno
!= ENOENT
) {
1651 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1657 if (S_ISDIR(st
.st_mode
) &&
1658 (st
.st_uid
== getuid()) &&
1659 ((st
.st_mode
& 0777) == 0700)) {
1665 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1672 /* Hmm, so the link points to some nonexisting or invalid
1673 * dir. Let's replace it by a new link. We first create a
1674 * temporary link and then rename that to allow concurrent
1675 * execution of this function. */
1677 t
= pa_sprintf_malloc("%s.tmp", k
);
1679 if (make_random_dir_and_link(0700, t
) < 0) {
1681 if (errno
!= EEXIST
) {
1682 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1689 /* Hmm, someone lese was quicker then us. Let's give
1690 * him some time to finish, and retry. */
1695 /* OK, we succeeded in creating the temporary symlink, so
1696 * let's rename it */
1697 if (rename(t
, k
) < 0) {
1698 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1714 /* Try to open a configuration file. If "env" is specified, open the
1715 * value of the specified environment variable. Otherwise look for a
1716 * file "local" in the home directory or a file "global" in global
1717 * file system. If "result" is non-NULL, a pointer to a newly
1718 * allocated buffer containing the used configuration file is
1720 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1724 if (env
&& (fn
= getenv(env
))) {
1725 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1727 *result
= pa_xstrdup(fn
);
1732 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1741 if ((e
= getenv("PULSE_CONFIG_PATH")))
1742 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1743 else if ((h
= pa_get_home_dir_malloc())) {
1744 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1749 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1751 *result
= pa_xstrdup(fn
);
1757 if (errno
!= ENOENT
) {
1758 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1770 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1771 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1772 pa_win32_get_toplevel(NULL
),
1773 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1776 gfn
= pa_xstrdup(global
);
1778 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1793 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1796 if (env
&& (fn
= getenv(env
))) {
1797 if (access(fn
, R_OK
) == 0)
1798 return pa_xstrdup(fn
);
1800 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1809 if ((e
= getenv("PULSE_CONFIG_PATH")))
1810 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1811 else if ((h
= pa_get_home_dir_malloc())) {
1812 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1817 if (access(fn
, R_OK
) == 0) {
1818 char *r
= pa_xstrdup(fn
);
1823 if (errno
!= ENOENT
) {
1824 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1836 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1837 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1838 pa_win32_get_toplevel(NULL
),
1839 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1842 gfn
= pa_xstrdup(global
);
1844 if (access(gfn
, R_OK
) == 0)
1854 /* Format the specified data as a hexademical string */
1855 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1856 size_t i
= 0, j
= 0;
1857 const char hex
[] = "0123456789abcdef";
1861 pa_assert(slength
> 0);
1863 while (j
+2 < slength
&& i
< dlength
) {
1864 s
[j
++] = hex
[*d
>> 4];
1865 s
[j
++] = hex
[*d
& 0xF];
1871 s
[j
< slength
? j
: slength
] = 0;
1875 /* Convert a hexadecimal digit to a number or -1 if invalid */
1876 static int hexc(char c
) {
1877 if (c
>= '0' && c
<= '9')
1880 if (c
>= 'A' && c
<= 'F')
1881 return c
- 'A' + 10;
1883 if (c
>= 'a' && c
<= 'f')
1884 return c
- 'a' + 10;
1890 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1891 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1897 while (j
< dlength
&& *p
) {
1900 if ((b
= hexc(*(p
++))) < 0)
1903 d
[j
] = (uint8_t) (b
<< 4);
1908 if ((b
= hexc(*(p
++))) < 0)
1911 d
[j
] |= (uint8_t) b
;
1918 /* Returns nonzero when *s starts with *pfx */
1919 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1927 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1930 /* Returns nonzero when *s ends with *sfx */
1931 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1940 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1943 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1949 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1953 char *pa_make_path_absolute(const char *p
) {
1959 if (pa_is_path_absolute(p
))
1960 return pa_xstrdup(p
);
1962 if (!(cwd
= pa_getcwd()))
1963 return pa_xstrdup(p
);
1965 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1970 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1971 * if fn is non-null and starts with / return fn
1972 * otherwise append fn to the run time path and return it */
1973 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1976 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1981 if (pa_is_path_absolute(fn
))
1982 return pa_xstrdup(fn
);
1990 if (!(mid
= pa_machine_id())) {
1995 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1998 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
2006 char *pa_runtime_path(const char *fn
) {
2007 return get_path(fn
, FALSE
, TRUE
);
2010 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2011 return get_path(fn
, appendmid
, FALSE
);
2014 /* Convert the string s to a signed integer in *ret_i */
2015 int pa_atoi(const char *s
, int32_t *ret_i
) {
2021 if (pa_atol(s
, &l
) < 0)
2024 if ((int32_t) l
!= l
) {
2029 *ret_i
= (int32_t) l
;
2034 /* Convert the string s to an unsigned integer in *ret_u */
2035 int pa_atou(const char *s
, uint32_t *ret_u
) {
2043 l
= strtoul(s
, &x
, 0);
2045 if (!x
|| *x
|| errno
) {
2051 if ((uint32_t) l
!= l
) {
2056 *ret_u
= (uint32_t) l
;
2061 /* Convert the string s to a signed long integer in *ret_l. */
2062 int pa_atol(const char *s
, long *ret_l
) {
2070 l
= strtol(s
, &x
, 0);
2072 if (!x
|| *x
|| errno
) {
2083 #ifdef HAVE_STRTOF_L
2084 static locale_t c_locale
= NULL
;
2086 static void c_locale_destroy(void) {
2087 freelocale(c_locale
);
2091 int pa_atod(const char *s
, double *ret_d
) {
2098 /* This should be locale independent */
2100 #ifdef HAVE_STRTOF_L
2104 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2105 atexit(c_locale_destroy
);
2111 f
= strtod_l(s
, &x
, c_locale
);
2119 if (!x
|| *x
|| errno
) {
2130 /* Same as snprintf, but guarantees NUL-termination on every platform */
2131 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2136 pa_assert(size
> 0);
2139 va_start(ap
, format
);
2140 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2146 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2147 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2151 pa_assert(size
> 0);
2154 ret
= vsnprintf(str
, size
, format
, ap
);
2161 if ((size_t) ret
> size
-1)
2164 return (size_t) ret
;
2167 /* Truncate the specified string, but guarantee that the string
2168 * returned still validates as UTF8 */
2169 char *pa_truncate_utf8(char *c
, size_t l
) {
2171 pa_assert(pa_utf8_valid(c
));
2178 while (l
> 0 && !pa_utf8_valid(c
))
2184 char *pa_getcwd(void) {
2188 char *p
= pa_xmalloc(l
);
2192 if (errno
!= ERANGE
)
2200 void *pa_will_need(const void *p
, size_t l
) {
2201 #ifdef RLIMIT_MEMLOCK
2212 a
= PA_PAGE_ALIGN_PTR(p
);
2213 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2215 #ifdef HAVE_POSIX_MADVISE
2216 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2217 pa_log_debug("posix_madvise() worked fine!");
2222 /* Most likely the memory was not mmap()ed from a file and thus
2223 * madvise() didn't work, so let's misuse mlock() do page this
2224 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2225 * inviting, the man page of mlock() tells us: "All pages that
2226 * contain a part of the specified address range are guaranteed to
2227 * be resident in RAM when the call returns successfully." */
2229 #ifdef RLIMIT_MEMLOCK
2230 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2232 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2233 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
));
2238 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2240 bs
= PA_PAGE_SIZE
*4;
2243 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2246 while (size
> 0 && bs
> 0) {
2251 if (mlock(a
, bs
) < 0) {
2252 bs
= PA_PAGE_ALIGN(bs
/ 2);
2256 pa_assert_se(munlock(a
, bs
) == 0);
2258 a
= (const uint8_t*) a
+ bs
;
2264 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2266 pa_log_debug("mlock() worked fine!");
2271 void pa_close_pipe(int fds
[2]) {
2275 pa_assert_se(pa_close(fds
[0]) == 0);
2278 pa_assert_se(pa_close(fds
[1]) == 0);
2280 fds
[0] = fds
[1] = -1;
2283 char *pa_readlink(const char *p
) {
2284 #ifdef HAVE_READLINK
2293 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2298 if ((size_t) n
< l
-1) {
2311 int pa_close_all(int except_fd
, ...) {
2316 va_start(ap
, except_fd
);
2319 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2324 p
= pa_xnew(int, n
+1);
2326 va_start(ap
, except_fd
);
2329 if (except_fd
>= 0) {
2333 while ((fd
= va_arg(ap
, int)) >= 0)
2340 r
= pa_close_allv(p
);
2346 int pa_close_allv(const int except_fds
[]) {
2355 if ((d
= opendir("/proc/self/fd"))) {
2359 while ((de
= readdir(d
))) {
2365 if (de
->d_name
[0] == '.')
2369 l
= strtol(de
->d_name
, &e
, 10);
2370 if (errno
!= 0 || !e
|| *e
) {
2378 if ((long) fd
!= l
) {
2391 for (i
= 0; except_fds
[i
] >= 0; i
++)
2392 if (except_fds
[i
] == fd
) {
2400 if (pa_close(fd
) < 0) {
2401 saved_errno
= errno
;
2403 errno
= saved_errno
;
2415 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2416 maxfd
= (int) rl
.rlim_max
;
2418 maxfd
= sysconf(_SC_OPEN_MAX
);
2420 for (fd
= 3; fd
< maxfd
; fd
++) {
2425 for (i
= 0; except_fds
[i
] >= 0; i
++)
2426 if (except_fds
[i
] == fd
) {
2434 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2437 #endif /* !OS_IS_WIN32 */
2442 int pa_unblock_sigs(int except
, ...) {
2447 va_start(ap
, except
);
2450 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2455 p
= pa_xnew(int, n
+1);
2457 va_start(ap
, except
);
2464 while ((sig
= va_arg(ap
, int)) >= 0)
2471 r
= pa_unblock_sigsv(p
);
2477 int pa_unblock_sigsv(const int except
[]) {
2482 if (sigemptyset(&ss
) < 0)
2485 for (i
= 0; except
[i
] > 0; i
++)
2486 if (sigaddset(&ss
, except
[i
]) < 0)
2489 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2495 int pa_reset_sigs(int except
, ...) {
2500 va_start(ap
, except
);
2503 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2508 p
= pa_xnew(int, n
+1);
2510 va_start(ap
, except
);
2517 while ((sig
= va_arg(ap
, int)) >= 0)
2524 r
= pa_reset_sigsv(p
);
2530 int pa_reset_sigsv(const int except
[]) {
2534 for (sig
= 1; sig
< NSIG
; sig
++) {
2535 pa_bool_t reset
= TRUE
;
2546 for (i
= 0; except
[i
] > 0; i
++) {
2547 if (sig
== except
[i
]) {
2556 struct sigaction sa
;
2558 memset(&sa
, 0, sizeof(sa
));
2559 sa
.sa_handler
= SIG_DFL
;
2561 /* On Linux the first two RT signals are reserved by
2562 * glibc, and sigaction() will return EINVAL for them. */
2563 if ((sigaction(sig
, &sa
, NULL
) < 0))
2564 if (errno
!= EINVAL
)
2573 void pa_set_env(const char *key
, const char *value
) {
2577 /* This is not thread-safe */
2580 SetEnvironmentVariable(key
, value
);
2582 setenv(key
, value
, 1);
2586 void pa_set_env_and_record(const char *key
, const char *value
) {
2590 /* This is not thread-safe */
2592 pa_set_env(key
, value
);
2593 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2596 void pa_unset_env_recorded(void) {
2598 /* This is not thread-safe */
2603 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2609 SetEnvironmentVariable(s
, NULL
);
2617 pa_bool_t
pa_in_system_mode(void) {
2620 if (!(e
= getenv("PULSE_SYSTEM")))
2626 char *pa_get_user_name_malloc(void) {
2630 #ifdef _SC_LOGIN_NAME_MAX
2631 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2637 u
= pa_xnew(char, k
+1);
2639 if (!(pa_get_user_name(u
, k
))) {
2647 char *pa_get_host_name_malloc(void) {
2656 if (!pa_get_host_name(c
, l
)) {
2658 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2661 } else if (strlen(c
) < l
-1) {
2669 u
= pa_utf8_filter(c
);
2674 /* Hmm, the hostname is as long the space we offered the
2675 * function, we cannot know if it fully fit in, so let's play
2676 * safe and retry. */
2685 char *pa_machine_id(void) {
2689 /* The returned value is supposed be some kind of ascii identifier
2690 * that is unique and stable across reboots. */
2692 /* First we try the D-Bus UUID, which is the best option we have,
2693 * since it fits perfectly our needs and is not as volatile as the
2694 * hostname which might be set from dhcp. */
2696 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2697 char ln
[34] = "", *r
;
2699 r
= fgets(ln
, sizeof(ln
)-1, f
);
2705 return pa_utf8_filter(ln
);
2708 if ((h
= pa_get_host_name_malloc()))
2712 /* If no hostname was set we use the POSIX hostid. It's usually
2713 * the IPv4 address. Might not be that stable. */
2714 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2720 char *pa_session_id(void) {
2723 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2726 return pa_utf8_filter(e
);
2729 char *pa_uname_string(void) {
2733 pa_assert_se(uname(&u
) >= 0);
2735 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2741 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2742 pa_assert_se(GetVersionEx(&i
));
2744 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2748 #ifdef HAVE_VALGRIND_MEMCHECK_H
2749 pa_bool_t
pa_in_valgrind(void) {
2752 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2753 * here instead of really checking whether we run in valgrind or
2757 b
= getenv("VALGRIND") ? 2 : 1;
2763 unsigned pa_gcd(unsigned a
, unsigned b
) {
2774 void pa_reduce(unsigned *num
, unsigned *den
) {
2776 unsigned gcd
= pa_gcd(*num
, *den
);
2784 pa_assert(pa_gcd(*num
, *den
) == 1);
2787 unsigned pa_ncpus(void) {
2790 #ifdef _SC_NPROCESSORS_CONF
2791 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2796 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2799 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2808 sb
= pa_strbuf_new();
2813 if (!(p
= strstr(s
, a
)))
2816 pa_strbuf_putsn(sb
, s
, p
-s
);
2817 pa_strbuf_puts(sb
, b
);
2821 pa_strbuf_puts(sb
, s
);
2823 return pa_strbuf_tostring_free(sb
);
2826 char *pa_escape(const char *p
, const char *chars
) {
2829 pa_strbuf
*buf
= pa_strbuf_new();
2831 for (s
= p
; *s
; ++s
) {
2833 pa_strbuf_putc(buf
, '\\');
2835 for (c
= chars
; *c
; ++c
) {
2837 pa_strbuf_putc(buf
, '\\');
2842 pa_strbuf_putc(buf
, *s
);
2845 return pa_strbuf_tostring_free(buf
);
2848 char *pa_unescape(char *p
) {
2850 pa_bool_t escaped
= FALSE
;
2852 for (s
= p
, d
= p
; *s
; s
++) {
2853 if (!escaped
&& *s
== '\\') {
2867 char *pa_realpath(const char *path
) {
2871 /* We want only abolsute paths */
2872 if (path
[0] != '/') {
2877 #if defined(__GLIBC__) || defined(__APPLE__)
2881 if (!(r
= realpath(path
, NULL
)))
2884 /* We copy this here in case our pa_xmalloc() is not
2885 * implemented on top of libc malloc() */
2889 #elif defined(PATH_MAX)
2892 path_buf
= pa_xmalloc(PATH_MAX
);
2894 #if defined(OS_IS_WIN32)
2895 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2900 if (!(t
= realpath(path
, path_buf
))) {
2907 #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."
2913 void pa_disable_sigpipe(void) {
2916 struct sigaction sa
;
2920 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2921 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2925 sa
.sa_handler
= SIG_IGN
;
2927 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2928 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2934 void pa_xfreev(void**a
) {
2940 for (p
= a
; *p
; p
++)
2946 char **pa_split_spaces_strv(const char *s
) {
2948 unsigned i
= 0, n
= 8;
2949 const char *state
= NULL
;
2951 t
= pa_xnew(char*, n
);
2952 while ((e
= pa_split_spaces(s
, &state
))) {
2957 t
= pa_xrenew(char*, t
, n
);
2970 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2973 if (pa_is_path_absolute(path
))
2974 return pa_xstrdup(path
);
2976 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2979 size_t pa_pipe_buf(int fd
) {
2984 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2995 void pa_reset_personality(void) {
2998 if (personality(PER_LINUX
) < 0)
2999 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3004 #if defined(__linux__) && !defined(__OPTIMIZE__)
3006 pa_bool_t
pa_run_from_build_tree(void) {
3008 pa_bool_t b
= FALSE
;
3010 if ((rp
= pa_readlink("/proc/self/exe"))) {
3011 b
= pa_startswith(rp
, PA_BUILDDIR
);
3020 const char *pa_get_temp_dir(void) {
3023 if ((t
= getenv("TMPDIR")) &&
3024 pa_is_path_absolute(t
))
3027 if ((t
= getenv("TMP")) &&
3028 pa_is_path_absolute(t
))
3031 if ((t
= getenv("TEMP")) &&
3032 pa_is_path_absolute(t
))
3035 if ((t
= getenv("TEMPDIR")) &&
3036 pa_is_path_absolute(t
))
3042 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3050 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3053 if (errno
!= EINVAL
)
3057 if ((fd
= open(fn
, flags
, mode
)) < 0)
3061 /* Some implementations might simply ignore O_CLOEXEC if it is not
3062 * understood, make sure FD_CLOEXEC is enabled anyway */
3064 pa_make_fd_cloexec(fd
);
3068 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3072 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3075 if (errno
!= EINVAL
)
3079 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3083 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3084 * not understood, make sure FD_CLOEXEC is enabled anyway */
3086 pa_make_fd_cloexec(fd
);
3090 int pa_pipe_cloexec(int pipefd
[2]) {
3094 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3097 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3102 if ((r
= pipe(pipefd
)) < 0)
3106 pa_make_fd_cloexec(pipefd
[0]);
3107 pa_make_fd_cloexec(pipefd
[1]);
3112 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3116 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3119 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3124 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3128 pa_make_fd_cloexec(fd
);
3132 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3136 m
= pa_sprintf_malloc("%se", mode
);
3139 if ((f
= fopen(path
, m
))) {
3146 if (errno
!= EINVAL
)
3149 if (!(f
= fopen(path
, mode
)))
3153 pa_make_fd_cloexec(fileno(f
));
3157 void pa_nullify_stdfds(void) {
3160 pa_close(STDIN_FILENO
);
3161 pa_close(STDOUT_FILENO
);
3162 pa_close(STDERR_FILENO
);
3164 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3165 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3166 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3173 char *pa_read_line_from_file(const char *fn
) {
3175 char ln
[256] = "", *r
;
3177 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3180 r
= fgets(ln
, sizeof(ln
)-1, f
);
3189 return pa_xstrdup(ln
);
3192 pa_bool_t
pa_running_in_vm(void) {
3194 #if defined(__i386__) || defined(__x86_64__)
3196 /* Both CPUID and DMI are x86 specific interfaces... */
3198 uint32_t eax
= 0x40000000;
3205 const char *const dmi_vendors
[] = {
3206 "/sys/class/dmi/id/sys_vendor",
3207 "/sys/class/dmi/id/board_vendor",
3208 "/sys/class/dmi/id/bios_vendor"
3213 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3216 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3218 if (pa_startswith(s
, "QEMU") ||
3219 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3220 pa_startswith(s
, "VMware") ||
3221 pa_startswith(s
, "VMW") ||
3222 pa_startswith(s
, "Microsoft Corporation") ||
3223 pa_startswith(s
, "innotek GmbH") ||
3224 pa_startswith(s
, "Xen")) {
3236 /* http://lwn.net/Articles/301888/ */
3239 __asm__
__volatile__ (
3240 /* ebx/rbx is being used for PIC! */
3241 " push %%"PA_REG_b
" \n\t"
3243 " mov %%ebx, %1 \n\t"
3244 " pop %%"PA_REG_b
" \n\t"
3246 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3250 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3251 pa_streq(sig
.text
, "KVMKVMKVM") ||
3252 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3253 pa_streq(sig
.text
, "VMwareVMware") ||
3254 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3255 pa_streq(sig
.text
, "Microsoft Hv"))