2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
38 #include <sys/types.h>
42 #ifdef HAVE_LANGINFO_H
47 #include <sys/utsname.h>
50 #if defined(HAVE_REGEX_H)
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
76 #ifdef HAVE_SYS_MMAN_H
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
110 #include <mach/mach_init.h>
111 #include <mach/thread_act.h>
112 #include <mach/thread_policy.h>
113 #include <sys/sysctl.h>
121 #include <sys/personality.h>
124 #include <pulse/xmalloc.h>
125 #include <pulse/util.h>
126 #include <pulse/utf8.h>
128 #include <pulsecore/core-error.h>
129 #include <pulsecore/socket.h>
130 #include <pulsecore/log.h>
131 #include <pulsecore/macro.h>
132 #include <pulsecore/thread.h>
133 #include <pulsecore/strbuf.h>
134 #include <pulsecore/usergroup.h>
135 #include <pulsecore/strlist.h>
136 #include <pulsecore/cpu-x86.h>
137 #include <pulsecore/pipe.h>
139 #include "core-util.h"
141 /* Not all platforms have this */
143 #define MSG_NOSIGNAL 0
146 #define NEWLINE "\r\n"
147 #define WHITESPACE "\n\r \t"
149 static pa_strlist
*recorded_env
= NULL
;
153 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
154 char *pa_win32_get_toplevel(HANDLE handle
) {
155 static char *toplevel
= NULL
;
158 char library_path
[MAX_PATH
];
161 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
164 toplevel
= pa_xstrdup(library_path
);
166 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
170 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
171 if (p
&& pa_streq(p
+ 1, "bin"))
180 /** Make a file descriptor nonblock. Doesn't do any error checking */
181 void pa_make_fd_nonblock(int fd
) {
187 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
189 if (!(v
& O_NONBLOCK
))
190 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
192 #elif defined(OS_IS_WIN32)
194 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
195 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
196 pa_log_warn("Only sockets can be made non-blocking!");
199 pa_log_warn("Non-blocking I/O not supported.!");
204 /* Set the FD_CLOEXEC flag for a fd */
205 void pa_make_fd_cloexec(int fd
) {
211 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
213 if (!(v
& FD_CLOEXEC
))
214 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
219 /** Creates a directory securely */
220 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
231 u
= umask((~m
) & 0777);
237 if (r
< 0 && errno
!= EEXIST
)
240 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
256 if (fstat(fd
, &st
) < 0) {
257 pa_assert_se(pa_close(fd
) >= 0);
261 if (!S_ISDIR(st
.st_mode
)) {
262 pa_assert_se(pa_close(fd
) >= 0);
268 if (uid
== (uid_t
) -1)
270 if (gid
== (gid_t
) -1)
272 if (fchown(fd
, uid
, gid
) < 0)
277 (void) fchmod(fd
, m
);
280 pa_assert_se(pa_close(fd
) >= 0);
285 if (lstat(dir
, &st
) < 0)
287 if (stat(dir
, &st
) < 0)
292 if (!S_ISDIR(st
.st_mode
) ||
293 (st
.st_uid
!= uid
) ||
294 (st
.st_gid
!= gid
) ||
295 ((st
.st_mode
& 0777) != m
)) {
300 pa_log_warn("Secure directory creation not supported on Win32.");
313 /* Return a newly allocated sting containing the parent directory of the specified file */
314 char *pa_parent_dir(const char *fn
) {
315 char *slash
, *dir
= pa_xstrdup(fn
);
317 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
327 /* Creates a the parent directory of the specified path securely */
328 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
332 if (!(dir
= pa_parent_dir(fn
)))
335 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
345 /** Platform independent read function. Necessary since not all
346 * systems treat all file descriptors equal. If type is
347 * non-NULL it is used to cache the type of the fd. This is
348 * useful for making sure that only a single syscall is executed per
349 * function call. The variable pointed to should be initialized to 0
351 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
355 if (!type
|| *type
== 0) {
358 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
361 if (WSAGetLastError() != WSAENOTSOCK
) {
362 errno
= WSAGetLastError();
375 if ((r
= read(fd
, buf
, count
)) < 0)
383 /** Similar to pa_read(), but handles writes */
384 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
386 if (!type
|| *type
== 0) {
390 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
402 if (WSAGetLastError() != WSAENOTSOCK
) {
403 errno
= WSAGetLastError();
407 if (errno
!= ENOTSOCK
)
418 if ((r
= write(fd
, buf
, count
)) < 0)
426 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
427 * unless EOF is reached or an error occurred */
428 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
444 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
451 data
= (uint8_t*) data
+ r
;
458 /** Similar to pa_loop_read(), but wraps write() */
459 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
475 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
482 data
= (const uint8_t*) data
+ r
;
489 /** Platform independent read function. Necessary since not all
490 * systems treat all file descriptors equal. */
491 int pa_close(int fd
) {
496 if ((ret
= closesocket(fd
)) == 0)
499 if (WSAGetLastError() != WSAENOTSOCK
) {
500 errno
= WSAGetLastError();
508 if ((r
= close(fd
)) < 0)
516 /* Print a warning messages in case that the given signal is not
517 * blocked or trapped */
518 void pa_check_signal_is_blocked(int sig
) {
519 #ifdef HAVE_SIGACTION
523 /* If POSIX threads are supported use thread-aware
524 * pthread_sigmask() function, to check if the signal is
525 * blocked. Otherwise fall back to sigprocmask() */
528 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
530 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
531 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
538 if (sigismember(&set
, sig
))
541 /* Check whether the signal is trapped */
543 if (sigaction(sig
, NULL
, &sa
) < 0) {
544 pa_log("sigaction(): %s", pa_cstrerror(errno
));
548 if (sa
.sa_handler
!= SIG_DFL
)
551 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
552 #else /* HAVE_SIGACTION */
553 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
557 /* The following function is based on an example from the GNU libc
558 * documentation. This function is similar to GNU's asprintf(). */
559 char *pa_sprintf_malloc(const char *format
, ...) {
569 c
= pa_xrealloc(c
, size
);
571 va_start(ap
, format
);
572 r
= vsnprintf(c
, size
, format
, ap
);
577 if (r
> -1 && (size_t) r
< size
)
580 if (r
> -1) /* glibc 2.1 */
587 /* Same as the previous function, but use a va_list instead of an
589 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
599 c
= pa_xrealloc(c
, size
);
602 r
= vsnprintf(c
, size
, format
, aq
);
607 if (r
> -1 && (size_t) r
< size
)
610 if (r
> -1) /* glibc 2.1 */
617 /* Similar to OpenBSD's strlcpy() function */
618 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
636 #ifdef _POSIX_PRIORITY_SCHEDULING
637 static int set_scheduler(int rtprio
) {
639 struct sched_param sp
;
645 dbus_error_init(&error
);
649 sp
.sched_priority
= rtprio
;
651 #ifdef SCHED_RESET_ON_FORK
652 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
653 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
658 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
659 pa_log_debug("SCHED_RR worked.");
662 #endif /* HAVE_SCHED_H */
665 /* Try to talk to RealtimeKit */
667 if (!(bus
= dbus_bus_get_private(DBUS_BUS_SYSTEM
, &error
))) {
668 pa_log("Failed to connect to system bus: %s\n", error
.message
);
669 dbus_error_free(&error
);
674 /* We need to disable exit on disconnect because otherwise
675 * dbus_shutdown will kill us. See
676 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
677 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
679 r
= rtkit_make_realtime(bus
, 0, rtprio
);
680 dbus_connection_close(bus
);
681 dbus_connection_unref(bus
);
684 pa_log_debug("RealtimeKit worked.");
697 /* Make the current thread a realtime thread, and acquire the highest
698 * rtprio we can get that is less or equal the specified parameter. If
699 * the thread is already realtime, don't do anything. */
700 int pa_make_realtime(int rtprio
) {
702 #if defined(OS_IS_DARWIN)
703 struct thread_time_constraint_policy ttcpolicy
;
705 size_t size
= sizeof(freq
);
708 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
710 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
714 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
716 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
717 ttcpolicy
.period
= freq
/ 160;
718 ttcpolicy
.computation
= freq
/ 3300;
719 ttcpolicy
.constraint
= freq
/ 2200;
720 ttcpolicy
.preemptible
= 1;
722 ret
= thread_policy_set(mach_thread_self(),
723 THREAD_TIME_CONSTRAINT_POLICY
,
724 (thread_policy_t
) &ttcpolicy
,
725 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
727 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
731 pa_log_info("Successfully acquired real-time thread priority.");
734 #elif defined(_POSIX_PRIORITY_SCHEDULING)
737 if (set_scheduler(rtprio
) >= 0) {
738 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
742 for (p
= rtprio
-1; p
>= 1; p
--)
743 if (set_scheduler(p
) >= 0) {
744 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
747 #elif defined(OS_IS_WIN32)
748 /* Windows only allows realtime scheduling to be set on a per process basis.
749 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
750 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
751 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
755 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
760 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
764 #ifdef HAVE_SYS_RESOURCE_H
765 static int set_nice(int nice_level
) {
771 dbus_error_init(&error
);
774 #ifdef HAVE_SYS_RESOURCE_H
775 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
776 pa_log_debug("setpriority() worked.");
782 /* Try to talk to RealtimeKit */
784 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
785 pa_log("Failed to connect to system bus: %s\n", error
.message
);
786 dbus_error_free(&error
);
791 /* We need to disable exit on disconnect because otherwise
792 * dbus_shutdown will kill us. See
793 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
794 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
796 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
797 dbus_connection_unref(bus
);
800 pa_log_debug("RealtimeKit worked.");
811 /* Raise the priority of the current process as much as possible that
812 * is <= the specified nice level..*/
813 int pa_raise_priority(int nice_level
) {
815 #ifdef HAVE_SYS_RESOURCE_H
818 if (set_nice(nice_level
) >= 0) {
819 pa_log_info("Successfully gained nice level %i.", nice_level
);
823 for (n
= nice_level
+1; n
< 0; n
++)
824 if (set_nice(n
) >= 0) {
825 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
829 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
834 if (nice_level
< 0) {
835 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
836 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
841 pa_log_info("Successfully gained high priority class.");
848 /* Reset the priority to normal, inverting the changes made by
849 * pa_raise_priority() and pa_make_realtime()*/
850 void pa_reset_priority(void) {
851 #ifdef HAVE_SYS_RESOURCE_H
852 struct sched_param sp
;
854 setpriority(PRIO_PROCESS
, 0, 0);
857 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
861 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
865 int pa_match(const char *expr
, const char *v
) {
870 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
875 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
877 else if (k
== REG_NOMATCH
)
890 /* Try to parse a boolean string value.*/
891 int pa_parse_boolean(const char *v
) {
894 /* First we check language independent */
895 if (pa_streq(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
897 else if (pa_streq(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
900 #ifdef HAVE_LANGINFO_H
903 /* And then we check language dependent */
904 if ((expr
= nl_langinfo(YESEXPR
)))
906 if (pa_match(expr
, v
) > 0)
909 if ((expr
= nl_langinfo(NOEXPR
)))
911 if (pa_match(expr
, v
) > 0)
920 /* Split the specified string wherever one of the strings in delimiter
921 * occurs. Each time it is called returns a newly allocated string
922 * with pa_xmalloc(). The variable state points to, should be
923 * initialized to NULL before the first call. */
924 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
925 const char *current
= *state
? *state
: c
;
931 l
= strcspn(current
, delimiter
);
937 return pa_xstrndup(current
, l
);
940 /* Split the specified string wherever one of the strings in delimiter
941 * occurs. Each time it is called returns a pointer to the substring within the
942 * string and the length in 'n'. Note that the resultant string cannot be used
943 * as-is without the length parameter, since it is merely pointing to a point
944 * within the original string. The variable state points to, should be
945 * initialized to NULL before the first call. */
946 const char *pa_split_in_place(const char *c
, const char *delimiter
, int *n
, const char**state
) {
947 const char *current
= *state
? *state
: c
;
953 l
= strcspn(current
, delimiter
);
963 /* Split a string into words. Otherwise similar to pa_split(). */
964 char *pa_split_spaces(const char *c
, const char **state
) {
965 const char *current
= *state
? *state
: c
;
968 if (!*current
|| *c
== 0)
971 current
+= strspn(current
, WHITESPACE
);
972 l
= strcspn(current
, WHITESPACE
);
976 return pa_xstrndup(current
, l
);
979 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
981 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
982 const char *pa_sig2str(int sig
) {
995 char buf
[SIG2STR_MAX
];
997 if (sig2str(sig
, buf
) == 0) {
998 pa_xfree(PA_STATIC_TLS_GET(signame
));
999 t
= pa_sprintf_malloc("SIG%s", buf
);
1000 PA_STATIC_TLS_SET(signame
, t
);
1008 case SIGHUP
: return "SIGHUP";
1010 case SIGINT
: return "SIGINT";
1012 case SIGQUIT
: return "SIGQUIT";
1014 case SIGILL
: return "SIGULL";
1016 case SIGTRAP
: return "SIGTRAP";
1018 case SIGABRT
: return "SIGABRT";
1020 case SIGBUS
: return "SIGBUS";
1022 case SIGFPE
: return "SIGFPE";
1024 case SIGKILL
: return "SIGKILL";
1027 case SIGUSR1
: return "SIGUSR1";
1029 case SIGSEGV
: return "SIGSEGV";
1031 case SIGUSR2
: return "SIGUSR2";
1034 case SIGPIPE
: return "SIGPIPE";
1037 case SIGALRM
: return "SIGALRM";
1039 case SIGTERM
: return "SIGTERM";
1041 case SIGSTKFLT
: return "SIGSTKFLT";
1044 case SIGCHLD
: return "SIGCHLD";
1047 case SIGCONT
: return "SIGCONT";
1050 case SIGSTOP
: return "SIGSTOP";
1053 case SIGTSTP
: return "SIGTSTP";
1056 case SIGTTIN
: return "SIGTTIN";
1059 case SIGTTOU
: return "SIGTTOU";
1062 case SIGURG
: return "SIGURG";
1065 case SIGXCPU
: return "SIGXCPU";
1068 case SIGXFSZ
: return "SIGXFSZ";
1071 case SIGVTALRM
: return "SIGVTALRM";
1074 case SIGPROF
: return "SIGPROF";
1077 case SIGWINCH
: return "SIGWINCH";
1080 case SIGIO
: return "SIGIO";
1083 case SIGPWR
: return "SIGPWR";
1086 case SIGSYS
: return "SIGSYS";
1091 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1092 pa_xfree(PA_STATIC_TLS_GET(signame
));
1093 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1094 PA_STATIC_TLS_SET(signame
, t
);
1103 pa_xfree(PA_STATIC_TLS_GET(signame
));
1104 t
= pa_sprintf_malloc("SIG%i", sig
);
1105 PA_STATIC_TLS_SET(signame
, t
);
1111 /* Check whether the specified GID and the group name match */
1112 static int is_group(gid_t gid
, const char *name
) {
1113 struct group
*group
= NULL
;
1117 if (!(group
= pa_getgrgid_malloc(gid
))) {
1121 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1126 r
= pa_streq(name
, group
->gr_name
);
1129 pa_getgrgid_free(group
);
1134 /* Check the current user is member of the specified group */
1135 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1136 GETGROUPS_T
*gids
, tgid
;
1137 long n
= sysconf(_SC_NGROUPS_MAX
);
1142 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1144 if ((n
= getgroups((int) n
, gids
)) < 0) {
1145 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1149 for (i
= 0; i
< n
; i
++) {
1151 if ((k
= is_group(gids
[i
], name
)) < 0)
1160 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1176 /* Check whether the specific user id is a member of the specified group */
1177 int pa_uid_in_group(uid_t uid
, const char *name
) {
1178 struct group
*group
= NULL
;
1183 if (!(group
= pa_getgrnam_malloc(name
))) {
1190 for (i
= group
->gr_mem
; *i
; i
++) {
1191 struct passwd
*pw
= NULL
;
1194 if (!(pw
= pa_getpwnam_malloc(*i
)))
1197 if (pw
->pw_uid
== uid
)
1200 pa_getpwnam_free(pw
);
1207 pa_getgrnam_free(group
);
1212 /* Get the GID of a given group, return (gid_t) -1 on failure. */
1213 gid_t
pa_get_gid_of_group(const char *name
) {
1214 gid_t ret
= (gid_t
) -1;
1215 struct group
*gr
= NULL
;
1218 if (!(gr
= pa_getgrnam_malloc(name
))) {
1227 pa_getgrnam_free(gr
);
1231 int pa_check_in_group(gid_t g
) {
1232 gid_t gids
[NGROUPS_MAX
];
1235 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1245 #else /* HAVE_GRP_H */
1247 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1253 int pa_uid_in_group(uid_t uid
, const char *name
) {
1258 gid_t
pa_get_gid_of_group(const char *name
) {
1263 int pa_check_in_group(gid_t g
) {
1270 /* Lock or unlock a file entirely.
1271 (advisory on UNIX, mandatory on Windows) */
1272 int pa_lock_fd(int fd
, int b
) {
1274 struct flock f_lock
;
1276 /* Try a R/W lock first */
1278 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1279 f_lock
.l_whence
= SEEK_SET
;
1283 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1286 /* Perhaps the file descriptor was opened for read only, than try again with a read lock. */
1287 if (b
&& errno
== EBADF
) {
1288 f_lock
.l_type
= F_RDLCK
;
1289 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1293 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1297 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1299 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1301 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1304 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1306 /* FIXME: Needs to set errno! */
1312 /* Remove trailing newlines from a string */
1313 char* pa_strip_nl(char *s
) {
1316 s
[strcspn(s
, NEWLINE
)] = 0;
1320 char *pa_strip(char *s
) {
1323 /* Drops trailing whitespace. Modifies the string in
1324 * place. Returns pointer to first non-space character */
1326 s
+= strspn(s
, WHITESPACE
);
1328 for (e
= s
; *e
; e
++)
1329 if (!strchr(WHITESPACE
, *e
))
1340 /* Create a temporary lock file and lock it. */
1341 int pa_lock_lockfile(const char *fn
) {
1348 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1352 , S_IRUSR
|S_IWUSR
)) < 0) {
1353 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1357 if (pa_lock_fd(fd
, 1) < 0) {
1358 pa_log_warn("Failed to lock file '%s'.", fn
);
1362 if (fstat(fd
, &st
) < 0) {
1363 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1367 /* Check whether the file has been removed meanwhile. When yes,
1368 * restart this loop, otherwise, we're done */
1369 if (st
.st_nlink
>= 1)
1372 if (pa_lock_fd(fd
, 0) < 0) {
1373 pa_log_warn("Failed to unlock file '%s'.", fn
);
1377 if (pa_close(fd
) < 0) {
1378 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1389 int saved_errno
= errno
;
1391 errno
= saved_errno
;
1397 /* Unlock a temporary lock file */
1398 int pa_unlock_lockfile(const char *fn
, int fd
) {
1403 if (unlink(fn
) < 0) {
1404 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1409 if (pa_lock_fd(fd
, 0) < 0) {
1410 pa_log_warn("Failed to unlock file '%s'.", fn
);
1414 if (pa_close(fd
) < 0) {
1415 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1422 static char *get_config_home(char *home
) {
1425 t
= getenv("XDG_CONFIG_HOME");
1427 return pa_xstrdup(t
);
1429 return pa_sprintf_malloc("%s" PA_PATH_SEP
".config", home
);
1432 static int check_ours(const char *p
) {
1437 if (stat(p
, &st
) < 0)
1441 if (st
.st_uid
!= getuid())
1448 static char *get_pulse_home(void) {
1449 char *h
, *ret
, *config_home
;
1452 h
= pa_get_home_dir_malloc();
1454 pa_log_error("Failed to get home directory.");
1459 if (t
< 0 && t
!= -ENOENT
) {
1460 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t
));
1465 /* If the old directory exists, use it. */
1466 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1467 if (access(ret
, F_OK
) >= 0) {
1473 /* Otherwise go for the XDG compliant directory. */
1474 config_home
= get_config_home(h
);
1476 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", config_home
);
1482 char *pa_get_state_dir(void) {
1485 /* The state directory shall contain dynamic data that should be
1486 * kept across reboots, and is private to this user */
1488 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1489 if (!(d
= get_pulse_home()))
1492 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1493 * dir then this will break. */
1495 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1496 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1504 char *pa_get_home_dir_malloc(void) {
1506 size_t allocated
= 128;
1509 homedir
= pa_xmalloc(allocated
);
1511 if (!pa_get_home_dir(homedir
, allocated
)) {
1516 if (strlen(homedir
) < allocated
- 1)
1526 char *pa_get_binary_name_malloc(void) {
1528 size_t allocated
= 128;
1531 t
= pa_xmalloc(allocated
);
1533 if (!pa_get_binary_name(t
, allocated
)) {
1538 if (strlen(t
) < allocated
- 1)
1548 static char* make_random_dir(mode_t m
) {
1549 static const char table
[] =
1550 "abcdefghijklmnopqrstuvwxyz"
1551 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1557 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1558 pathlen
= strlen(fn
);
1566 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1567 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1569 u
= umask((~m
) & 0777);
1576 saved_errno
= errno
;
1578 errno
= saved_errno
;
1583 if (errno
!= EEXIST
) {
1584 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1591 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1594 if (!(p
= make_random_dir(m
)))
1598 if (symlink(p
, k
) < 0) {
1599 int saved_errno
= errno
;
1601 if (errno
!= EEXIST
)
1602 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1607 errno
= saved_errno
;
1619 char *pa_get_runtime_dir(void) {
1620 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1623 /* The runtime directory shall contain dynamic data that needs NOT
1624 * to be kept across reboots and is usually private to the user,
1625 * except in system mode, where it might be accessible by other
1626 * users, too. Since we need POSIX locking and UNIX sockets in
1627 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1628 * set create a directory in $HOME and link it to a random subdir
1629 * in /tmp, if it was not explicitly configured. */
1631 m
= pa_in_system_mode() ? 0755U : 0700U;
1633 /* Use the explicitly configured value if it is set */
1634 d
= getenv("PULSE_RUNTIME_PATH");
1637 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1638 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1642 return pa_xstrdup(d
);
1645 /* Use the XDG standard for the runtime directory. */
1646 d
= getenv("XDG_RUNTIME_DIR");
1648 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse", d
);
1650 if (pa_make_secure_dir(k
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1652 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1659 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1660 d
= get_pulse_home();
1664 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1665 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1670 mid
= pa_machine_id();
1676 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1681 /* OK, first let's check if the "runtime" symlink already exists */
1686 if (errno
!= ENOENT
) {
1687 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1692 /* Hmm, so the runtime directory didn't exist yet, so let's
1693 * create one in /tmp and symlink that to it */
1695 if (make_random_dir_and_link(0700, k
) < 0) {
1697 /* Mhmm, maybe another process was quicker than us,
1698 * let's check if that was valid */
1699 if (errno
== EEXIST
)
1705 /* No symlink possible, so let's just create the runtime directly */
1713 /* Make sure that this actually makes sense */
1714 if (!pa_is_path_absolute(p
)) {
1715 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1720 /* Hmm, so this symlink is still around, make sure nobody fools us */
1724 if (lstat(p
, &st
) < 0) {
1726 if (errno
!= ENOENT
) {
1727 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1733 if (S_ISDIR(st
.st_mode
) &&
1734 (st
.st_uid
== getuid()) &&
1735 ((st
.st_mode
& 0777) == 0700)) {
1741 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1749 /* Hmm, so the link points to some nonexisting or invalid
1750 * dir. Let's replace it by a new link. We first create a
1751 * temporary link and then rename that to allow concurrent
1752 * execution of this function. */
1754 t
= pa_sprintf_malloc("%s.tmp", k
);
1756 if (make_random_dir_and_link(0700, t
) < 0) {
1758 if (errno
!= EEXIST
) {
1759 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1766 /* Hmm, someone else was quicker then us. Let's give
1767 * him some time to finish, and retry. */
1772 /* OK, we succeeded in creating the temporary symlink, so
1773 * let's rename it */
1774 if (rename(t
, k
) < 0) {
1775 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1791 /* Try to open a configuration file. If "env" is specified, open the
1792 * value of the specified environment variable. Otherwise look for a
1793 * file "local" in the home directory or a file "global" in global
1794 * file system. If "result" is non-NULL, a pointer to a newly
1795 * allocated buffer containing the used configuration file is
1797 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1801 if (env
&& (fn
= getenv(env
))) {
1802 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1804 *result
= pa_xstrdup(fn
);
1809 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1818 if ((e
= getenv("PULSE_CONFIG_PATH"))) {
1819 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1820 f
= pa_fopen_cloexec(fn
, "r");
1821 } else if ((h
= pa_get_home_dir_malloc())) {
1822 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1823 f
= pa_fopen_cloexec(fn
, "r");
1826 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".config/pulse" PA_PATH_SEP
"%s", h
, local
);
1827 f
= pa_fopen_cloexec(fn
, "r");
1835 *result
= pa_xstrdup(fn
);
1841 if (errno
!= ENOENT
) {
1842 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1854 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1855 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1856 pa_win32_get_toplevel(NULL
),
1857 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1860 gfn
= pa_xstrdup(global
);
1862 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1877 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1880 if (env
&& (fn
= getenv(env
))) {
1881 if (access(fn
, R_OK
) == 0)
1882 return pa_xstrdup(fn
);
1884 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1893 if ((e
= getenv("PULSE_CONFIG_PATH")))
1894 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1895 else if ((h
= pa_get_home_dir_malloc())) {
1896 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1901 if (access(fn
, R_OK
) == 0) {
1902 char *r
= pa_xstrdup(fn
);
1907 if (errno
!= ENOENT
) {
1908 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1920 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1921 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1922 pa_win32_get_toplevel(NULL
),
1923 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1926 gfn
= pa_xstrdup(global
);
1928 if (access(gfn
, R_OK
) == 0)
1938 /* Format the specified data as a hexademical string */
1939 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1940 size_t i
= 0, j
= 0;
1941 const char hex
[] = "0123456789abcdef";
1945 pa_assert(slength
> 0);
1947 while (j
+2 < slength
&& i
< dlength
) {
1948 s
[j
++] = hex
[*d
>> 4];
1949 s
[j
++] = hex
[*d
& 0xF];
1955 s
[j
< slength
? j
: slength
] = 0;
1959 /* Convert a hexadecimal digit to a number or -1 if invalid */
1960 static int hexc(char c
) {
1961 if (c
>= '0' && c
<= '9')
1964 if (c
>= 'A' && c
<= 'F')
1965 return c
- 'A' + 10;
1967 if (c
>= 'a' && c
<= 'f')
1968 return c
- 'a' + 10;
1974 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1975 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1981 while (j
< dlength
&& *p
) {
1984 if ((b
= hexc(*(p
++))) < 0)
1987 d
[j
] = (uint8_t) (b
<< 4);
1992 if ((b
= hexc(*(p
++))) < 0)
1995 d
[j
] |= (uint8_t) b
;
2002 /* Returns nonzero when *s starts with *pfx */
2003 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
2011 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
2014 /* Returns nonzero when *s ends with *sfx */
2015 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
2024 return l1
>= l2
&& pa_streq(s
+ l1
- l2
, sfx
);
2027 pa_bool_t
pa_is_path_absolute(const char *fn
) {
2033 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
2037 char *pa_make_path_absolute(const char *p
) {
2043 if (pa_is_path_absolute(p
))
2044 return pa_xstrdup(p
);
2046 if (!(cwd
= pa_getcwd()))
2047 return pa_xstrdup(p
);
2049 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
2054 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
2055 * if fn is non-null and starts with / return fn
2056 * otherwise append fn to the run time path and return it */
2057 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
2060 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
2063 char *r
, *canonical_rtp
;
2065 if (pa_is_path_absolute(fn
)) {
2067 return pa_xstrdup(fn
);
2073 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2074 if ((canonical_rtp
= pa_realpath(rtp
))) {
2075 if (strlen(rtp
) >= strlen(canonical_rtp
))
2078 pa_xfree(canonical_rtp
);
2079 canonical_rtp
= rtp
;
2082 canonical_rtp
= rtp
;
2087 if (!(mid
= pa_machine_id())) {
2088 pa_xfree(canonical_rtp
);
2092 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", canonical_rtp
, mid
, fn
);
2095 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", canonical_rtp
, fn
);
2097 pa_xfree(canonical_rtp
);
2103 char *pa_runtime_path(const char *fn
) {
2104 return get_path(fn
, FALSE
, TRUE
);
2107 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2108 return get_path(fn
, appendmid
, FALSE
);
2111 /* Convert the string s to a signed integer in *ret_i */
2112 int pa_atoi(const char *s
, int32_t *ret_i
) {
2118 if (pa_atol(s
, &l
) < 0)
2121 if ((int32_t) l
!= l
) {
2126 *ret_i
= (int32_t) l
;
2131 /* Convert the string s to an unsigned integer in *ret_u */
2132 int pa_atou(const char *s
, uint32_t *ret_u
) {
2140 l
= strtoul(s
, &x
, 0);
2142 if (!x
|| *x
|| errno
) {
2148 if ((uint32_t) l
!= l
) {
2153 *ret_u
= (uint32_t) l
;
2158 /* Convert the string s to a signed long integer in *ret_l. */
2159 int pa_atol(const char *s
, long *ret_l
) {
2167 l
= strtol(s
, &x
, 0);
2169 if (!x
|| *x
|| errno
) {
2180 #ifdef HAVE_STRTOF_L
2181 static locale_t c_locale
= NULL
;
2183 static void c_locale_destroy(void) {
2184 freelocale(c_locale
);
2188 int pa_atod(const char *s
, double *ret_d
) {
2195 /* This should be locale independent */
2197 #ifdef HAVE_STRTOF_L
2201 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2202 atexit(c_locale_destroy
);
2208 f
= strtod_l(s
, &x
, c_locale
);
2216 if (!x
|| *x
|| errno
) {
2227 /* Same as snprintf, but guarantees NUL-termination on every platform */
2228 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2233 pa_assert(size
> 0);
2236 va_start(ap
, format
);
2237 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2243 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2244 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2248 pa_assert(size
> 0);
2251 ret
= vsnprintf(str
, size
, format
, ap
);
2258 if ((size_t) ret
> size
-1)
2261 return (size_t) ret
;
2264 /* Truncate the specified string, but guarantee that the string
2265 * returned still validates as UTF8 */
2266 char *pa_truncate_utf8(char *c
, size_t l
) {
2268 pa_assert(pa_utf8_valid(c
));
2275 while (l
> 0 && !pa_utf8_valid(c
))
2281 char *pa_getcwd(void) {
2285 char *p
= pa_xmalloc(l
);
2289 if (errno
!= ERANGE
)
2297 void *pa_will_need(const void *p
, size_t l
) {
2298 #ifdef RLIMIT_MEMLOCK
2309 a
= PA_PAGE_ALIGN_PTR(p
);
2310 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2312 #ifdef HAVE_POSIX_MADVISE
2313 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2314 pa_log_debug("posix_madvise() worked fine!");
2319 /* Most likely the memory was not mmap()ed from a file and thus
2320 * madvise() didn't work, so let's misuse mlock() do page this
2321 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2322 * inviting, the man page of mlock() tells us: "All pages that
2323 * contain a part of the specified address range are guaranteed to
2324 * be resident in RAM when the call returns successfully." */
2326 #ifdef RLIMIT_MEMLOCK
2327 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2329 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2330 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
));
2335 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2337 bs
= PA_PAGE_SIZE
*4;
2340 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2343 while (size
> 0 && bs
> 0) {
2348 if (mlock(a
, bs
) < 0) {
2349 bs
= PA_PAGE_ALIGN(bs
/ 2);
2353 pa_assert_se(munlock(a
, bs
) == 0);
2355 a
= (const uint8_t*) a
+ bs
;
2361 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2363 pa_log_debug("mlock() worked fine!");
2368 void pa_close_pipe(int fds
[2]) {
2372 pa_assert_se(pa_close(fds
[0]) == 0);
2375 pa_assert_se(pa_close(fds
[1]) == 0);
2377 fds
[0] = fds
[1] = -1;
2380 char *pa_readlink(const char *p
) {
2381 #ifdef HAVE_READLINK
2390 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2395 if ((size_t) n
< l
-1) {
2408 int pa_close_all(int except_fd
, ...) {
2413 va_start(ap
, except_fd
);
2416 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2421 p
= pa_xnew(int, n
+1);
2423 va_start(ap
, except_fd
);
2426 if (except_fd
>= 0) {
2430 while ((fd
= va_arg(ap
, int)) >= 0)
2437 r
= pa_close_allv(p
);
2443 int pa_close_allv(const int except_fds
[]) {
2452 if ((d
= opendir("/proc/self/fd"))) {
2456 while ((de
= readdir(d
))) {
2462 if (de
->d_name
[0] == '.')
2466 l
= strtol(de
->d_name
, &e
, 10);
2467 if (errno
!= 0 || !e
|| *e
) {
2475 if ((long) fd
!= l
) {
2488 for (i
= 0; except_fds
[i
] >= 0; i
++)
2489 if (except_fds
[i
] == fd
) {
2497 if (pa_close(fd
) < 0) {
2498 saved_errno
= errno
;
2500 errno
= saved_errno
;
2512 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2513 maxfd
= (int) rl
.rlim_max
;
2515 maxfd
= sysconf(_SC_OPEN_MAX
);
2517 for (fd
= 3; fd
< maxfd
; fd
++) {
2522 for (i
= 0; except_fds
[i
] >= 0; i
++)
2523 if (except_fds
[i
] == fd
) {
2531 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2534 #endif /* !OS_IS_WIN32 */
2539 int pa_unblock_sigs(int except
, ...) {
2544 va_start(ap
, except
);
2547 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2552 p
= pa_xnew(int, n
+1);
2554 va_start(ap
, except
);
2561 while ((sig
= va_arg(ap
, int)) >= 0)
2568 r
= pa_unblock_sigsv(p
);
2574 int pa_unblock_sigsv(const int except
[]) {
2579 if (sigemptyset(&ss
) < 0)
2582 for (i
= 0; except
[i
] > 0; i
++)
2583 if (sigaddset(&ss
, except
[i
]) < 0)
2586 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2592 int pa_reset_sigs(int except
, ...) {
2597 va_start(ap
, except
);
2600 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2605 p
= pa_xnew(int, n
+1);
2607 va_start(ap
, except
);
2614 while ((sig
= va_arg(ap
, int)) >= 0)
2621 r
= pa_reset_sigsv(p
);
2627 int pa_reset_sigsv(const int except
[]) {
2631 for (sig
= 1; sig
< NSIG
; sig
++) {
2632 pa_bool_t reset
= TRUE
;
2643 for (i
= 0; except
[i
] > 0; i
++) {
2644 if (sig
== except
[i
]) {
2653 struct sigaction sa
;
2655 memset(&sa
, 0, sizeof(sa
));
2656 sa
.sa_handler
= SIG_DFL
;
2658 /* On Linux the first two RT signals are reserved by
2659 * glibc, and sigaction() will return EINVAL for them. */
2660 if ((sigaction(sig
, &sa
, NULL
) < 0))
2661 if (errno
!= EINVAL
)
2670 void pa_set_env(const char *key
, const char *value
) {
2674 /* This is not thread-safe */
2677 SetEnvironmentVariable(key
, value
);
2679 setenv(key
, value
, 1);
2683 void pa_set_env_and_record(const char *key
, const char *value
) {
2687 /* This is not thread-safe */
2689 pa_set_env(key
, value
);
2690 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2693 void pa_unset_env_recorded(void) {
2695 /* This is not thread-safe */
2700 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2706 SetEnvironmentVariable(s
, NULL
);
2714 pa_bool_t
pa_in_system_mode(void) {
2717 if (!(e
= getenv("PULSE_SYSTEM")))
2723 /* Checks a whitespace-separated list of words in haystack for needle */
2724 pa_bool_t
pa_str_in_list_spaces(const char *haystack
, const char *needle
) {
2726 const char *state
= NULL
;
2728 if (!haystack
|| !needle
)
2731 while ((s
= pa_split_spaces(haystack
, &state
))) {
2732 if (pa_streq(needle
, s
)) {
2743 char *pa_get_user_name_malloc(void) {
2747 #ifdef _SC_LOGIN_NAME_MAX
2748 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2754 u
= pa_xnew(char, k
+1);
2756 if (!(pa_get_user_name(u
, k
))) {
2764 char *pa_get_host_name_malloc(void) {
2773 if (!pa_get_host_name(c
, l
)) {
2775 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2778 } else if (strlen(c
) < l
-1) {
2786 u
= pa_utf8_filter(c
);
2791 /* Hmm, the hostname is as long the space we offered the
2792 * function, we cannot know if it fully fit in, so let's play
2793 * safe and retry. */
2802 char *pa_machine_id(void) {
2806 /* The returned value is supposed be some kind of ascii identifier
2807 * that is unique and stable across reboots. */
2809 /* First we try the /etc/machine-id, which is the best option we
2810 * have, since it fits perfectly our needs and is not as volatile
2811 * as the hostname which might be set from dhcp. */
2813 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r")) ||
2814 (f
= pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK
, "r"))) {
2815 char ln
[34] = "", *r
;
2817 r
= fgets(ln
, sizeof(ln
)-1, f
);
2823 return pa_utf8_filter(ln
);
2826 if ((h
= pa_get_host_name_malloc()))
2830 /* If no hostname was set we use the POSIX hostid. It's usually
2831 * the IPv4 address. Might not be that stable. */
2832 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2838 char *pa_session_id(void) {
2841 e
= getenv("XDG_SESSION_ID");
2845 return pa_utf8_filter(e
);
2848 char *pa_uname_string(void) {
2852 pa_assert_se(uname(&u
) >= 0);
2854 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2860 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2861 pa_assert_se(GetVersionEx(&i
));
2863 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2867 #ifdef HAVE_VALGRIND_MEMCHECK_H
2868 pa_bool_t
pa_in_valgrind(void) {
2871 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2872 * here instead of really checking whether we run in valgrind or
2876 b
= getenv("VALGRIND") ? 2 : 1;
2882 unsigned pa_gcd(unsigned a
, unsigned b
) {
2893 void pa_reduce(unsigned *num
, unsigned *den
) {
2895 unsigned gcd
= pa_gcd(*num
, *den
);
2903 pa_assert(pa_gcd(*num
, *den
) == 1);
2906 unsigned pa_ncpus(void) {
2909 #ifdef _SC_NPROCESSORS_CONF
2910 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2915 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2918 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2927 sb
= pa_strbuf_new();
2932 if (!(p
= strstr(s
, a
)))
2935 pa_strbuf_putsn(sb
, s
, p
-s
);
2936 pa_strbuf_puts(sb
, b
);
2940 pa_strbuf_puts(sb
, s
);
2942 return pa_strbuf_tostring_free(sb
);
2945 char *pa_escape(const char *p
, const char *chars
) {
2948 pa_strbuf
*buf
= pa_strbuf_new();
2950 for (s
= p
; *s
; ++s
) {
2952 pa_strbuf_putc(buf
, '\\');
2954 for (c
= chars
; *c
; ++c
) {
2956 pa_strbuf_putc(buf
, '\\');
2961 pa_strbuf_putc(buf
, *s
);
2964 return pa_strbuf_tostring_free(buf
);
2967 char *pa_unescape(char *p
) {
2969 pa_bool_t escaped
= FALSE
;
2971 for (s
= p
, d
= p
; *s
; s
++) {
2972 if (!escaped
&& *s
== '\\') {
2986 char *pa_realpath(const char *path
) {
2990 /* We want only absolute paths */
2991 if (path
[0] != '/') {
2996 #if defined(__GLIBC__) || defined(__APPLE__)
3000 if (!(r
= realpath(path
, NULL
)))
3003 /* We copy this here in case our pa_xmalloc() is not
3004 * implemented on top of libc malloc() */
3008 #elif defined(PATH_MAX)
3011 path_buf
= pa_xmalloc(PATH_MAX
);
3013 #if defined(OS_IS_WIN32)
3014 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
3019 if (!(t
= realpath(path
, path_buf
))) {
3026 #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."
3032 void pa_disable_sigpipe(void) {
3035 struct sigaction sa
;
3039 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
3040 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3044 sa
.sa_handler
= SIG_IGN
;
3046 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
3047 pa_log("sigaction(): %s", pa_cstrerror(errno
));
3053 void pa_xfreev(void**a
) {
3059 for (p
= a
; *p
; p
++)
3065 char **pa_split_spaces_strv(const char *s
) {
3067 unsigned i
= 0, n
= 8;
3068 const char *state
= NULL
;
3070 t
= pa_xnew(char*, n
);
3071 while ((e
= pa_split_spaces(s
, &state
))) {
3076 t
= pa_xrenew(char*, t
, n
);
3089 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
3092 if (pa_is_path_absolute(path
))
3093 return pa_xstrdup(path
);
3095 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
3098 size_t pa_pipe_buf(int fd
) {
3103 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
3114 void pa_reset_personality(void) {
3117 if (personality(PER_LINUX
) < 0)
3118 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
3123 #if defined(__linux__) && !defined(__OPTIMIZE__)
3125 pa_bool_t
pa_run_from_build_tree(void) {
3127 pa_bool_t b
= FALSE
;
3129 if ((rp
= pa_readlink("/proc/self/exe"))) {
3130 b
= pa_startswith(rp
, PA_BUILDDIR
);
3139 const char *pa_get_temp_dir(void) {
3142 if ((t
= getenv("TMPDIR")) &&
3143 pa_is_path_absolute(t
))
3146 if ((t
= getenv("TMP")) &&
3147 pa_is_path_absolute(t
))
3150 if ((t
= getenv("TEMP")) &&
3151 pa_is_path_absolute(t
))
3154 if ((t
= getenv("TEMPDIR")) &&
3155 pa_is_path_absolute(t
))
3161 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3169 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3172 if (errno
!= EINVAL
)
3176 if ((fd
= open(fn
, flags
, mode
)) < 0)
3180 /* Some implementations might simply ignore O_CLOEXEC if it is not
3181 * understood, make sure FD_CLOEXEC is enabled anyway */
3183 pa_make_fd_cloexec(fd
);
3187 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3191 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3194 if (errno
!= EINVAL
)
3198 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3202 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3203 * not understood, make sure FD_CLOEXEC is enabled anyway */
3205 pa_make_fd_cloexec(fd
);
3209 int pa_pipe_cloexec(int pipefd
[2]) {
3213 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3216 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3221 if ((r
= pipe(pipefd
)) < 0)
3225 pa_make_fd_cloexec(pipefd
[0]);
3226 pa_make_fd_cloexec(pipefd
[1]);
3231 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3235 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3238 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3243 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3247 pa_make_fd_cloexec(fd
);
3251 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3255 m
= pa_sprintf_malloc("%se", mode
);
3258 if ((f
= fopen(path
, m
))) {
3265 if (errno
!= EINVAL
)
3268 if (!(f
= fopen(path
, mode
)))
3272 pa_make_fd_cloexec(fileno(f
));
3276 void pa_nullify_stdfds(void) {
3279 pa_close(STDIN_FILENO
);
3280 pa_close(STDOUT_FILENO
);
3281 pa_close(STDERR_FILENO
);
3283 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3284 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3285 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3292 char *pa_read_line_from_file(const char *fn
) {
3294 char ln
[256] = "", *r
;
3296 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3299 r
= fgets(ln
, sizeof(ln
)-1, f
);
3308 return pa_xstrdup(ln
);
3311 pa_bool_t
pa_running_in_vm(void) {
3313 #if defined(__i386__) || defined(__x86_64__)
3315 /* Both CPUID and DMI are x86 specific interfaces... */
3317 uint32_t eax
= 0x40000000;
3324 const char *const dmi_vendors
[] = {
3325 "/sys/class/dmi/id/sys_vendor",
3326 "/sys/class/dmi/id/board_vendor",
3327 "/sys/class/dmi/id/bios_vendor"
3332 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3335 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3337 if (pa_startswith(s
, "QEMU") ||
3338 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3339 pa_startswith(s
, "VMware") ||
3340 pa_startswith(s
, "VMW") ||
3341 pa_startswith(s
, "Microsoft Corporation") ||
3342 pa_startswith(s
, "innotek GmbH") ||
3343 pa_startswith(s
, "Xen")) {
3355 /* http://lwn.net/Articles/301888/ */
3358 __asm__
__volatile__ (
3359 /* ebx/rbx is being used for PIC! */
3360 " push %%"PA_REG_b
" \n\t"
3362 " mov %%ebx, %1 \n\t"
3363 " pop %%"PA_REG_b
" \n\t"
3365 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3369 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3370 pa_streq(sig
.text
, "KVMKVMKVM") ||
3371 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3372 pa_streq(sig
.text
, "VMwareVMware") ||
3373 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3374 pa_streq(sig
.text
, "Microsoft Hv"))