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(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_unref(bus
);
680 pa_log_debug("RealtimeKit worked.");
693 /* Make the current thread a realtime thread, and acquire the highest
694 * rtprio we can get that is less or equal the specified parameter. If
695 * the thread is already realtime, don't do anything. */
696 int pa_make_realtime(int rtprio
) {
698 #if defined(OS_IS_DARWIN)
699 struct thread_time_constraint_policy ttcpolicy
;
701 size_t size
= sizeof(freq
);
704 ret
= sysctlbyname("hw.cpufrequency", &freq
, &size
, NULL
, 0);
706 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
710 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq
);
712 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
713 ttcpolicy
.period
= freq
/ 160;
714 ttcpolicy
.computation
= freq
/ 3300;
715 ttcpolicy
.constraint
= freq
/ 2200;
716 ttcpolicy
.preemptible
= 1;
718 ret
= thread_policy_set(mach_thread_self(),
719 THREAD_TIME_CONSTRAINT_POLICY
,
720 (thread_policy_t
) &ttcpolicy
,
721 THREAD_TIME_CONSTRAINT_POLICY_COUNT
);
723 pa_log_info("Unable to set real-time thread priority (%08x).", ret
);
727 pa_log_info("Successfully acquired real-time thread priority.");
730 #elif _POSIX_PRIORITY_SCHEDULING
733 if (set_scheduler(rtprio
) >= 0) {
734 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
738 for (p
= rtprio
-1; p
>= 1; p
--)
739 if (set_scheduler(p
) >= 0) {
740 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
743 #elif defined(OS_IS_WIN32)
744 /* Windows only allows realtime scheduling to be set on a per process basis.
745 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
746 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
747 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
751 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
756 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
760 #ifdef HAVE_SYS_RESOURCE_H
761 static int set_nice(int nice_level
) {
767 dbus_error_init(&error
);
770 #ifdef HAVE_SYS_RESOURCE_H
771 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
772 pa_log_debug("setpriority() worked.");
778 /* Try to talk to RealtimeKit */
780 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
781 pa_log("Failed to connect to system bus: %s\n", error
.message
);
782 dbus_error_free(&error
);
787 /* We need to disable exit on disconnect because otherwise
788 * dbus_shutdown will kill us. See
789 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
790 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
792 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
793 dbus_connection_unref(bus
);
796 pa_log_debug("RealtimeKit worked.");
807 /* Raise the priority of the current process as much as possible that
808 * is <= the specified nice level..*/
809 int pa_raise_priority(int nice_level
) {
811 #ifdef HAVE_SYS_RESOURCE_H
814 if (set_nice(nice_level
) >= 0) {
815 pa_log_info("Successfully gained nice level %i.", nice_level
);
819 for (n
= nice_level
+1; n
< 0; n
++)
820 if (set_nice(n
) >= 0) {
821 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
825 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
830 if (nice_level
< 0) {
831 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
832 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
837 pa_log_info("Successfully gained high priority class.");
844 /* Reset the priority to normal, inverting the changes made by
845 * pa_raise_priority() and pa_make_realtime()*/
846 void pa_reset_priority(void) {
847 #ifdef HAVE_SYS_RESOURCE_H
848 struct sched_param sp
;
850 setpriority(PRIO_PROCESS
, 0, 0);
853 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
857 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
861 int pa_match(const char *expr
, const char *v
) {
866 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
871 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
873 else if (k
== REG_NOMATCH
)
886 /* Try to parse a boolean string value.*/
887 int pa_parse_boolean(const char *v
) {
891 /* First we check language independant */
892 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
894 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
897 #ifdef HAVE_LANGINFO_H
898 /* And then we check language dependant */
899 if ((expr
= nl_langinfo(YESEXPR
)))
901 if (pa_match(expr
, v
) > 0)
904 if ((expr
= nl_langinfo(NOEXPR
)))
906 if (pa_match(expr
, v
) > 0)
914 /* Split the specified string wherever one of the strings in delimiter
915 * occurs. Each time it is called returns a newly allocated string
916 * with pa_xmalloc(). The variable state points to, should be
917 * initiallized to NULL before the first call. */
918 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
919 const char *current
= *state
? *state
: c
;
925 l
= strcspn(current
, delimiter
);
931 return pa_xstrndup(current
, l
);
934 /* Split a string into words. Otherwise similar to pa_split(). */
935 char *pa_split_spaces(const char *c
, const char **state
) {
936 const char *current
= *state
? *state
: c
;
939 if (!*current
|| *c
== 0)
942 current
+= strspn(current
, WHITESPACE
);
943 l
= strcspn(current
, WHITESPACE
);
947 return pa_xstrndup(current
, l
);
950 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
952 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
953 const char *pa_sig2str(int sig
) {
966 char buf
[SIG2STR_MAX
];
968 if (sig2str(sig
, buf
) == 0) {
969 pa_xfree(PA_STATIC_TLS_GET(signame
));
970 t
= pa_sprintf_malloc("SIG%s", buf
);
971 PA_STATIC_TLS_SET(signame
, t
);
979 case SIGHUP
: return "SIGHUP";
981 case SIGINT
: return "SIGINT";
983 case SIGQUIT
: return "SIGQUIT";
985 case SIGILL
: return "SIGULL";
987 case SIGTRAP
: return "SIGTRAP";
989 case SIGABRT
: return "SIGABRT";
991 case SIGBUS
: return "SIGBUS";
993 case SIGFPE
: return "SIGFPE";
995 case SIGKILL
: return "SIGKILL";
998 case SIGUSR1
: return "SIGUSR1";
1000 case SIGSEGV
: return "SIGSEGV";
1002 case SIGUSR2
: return "SIGUSR2";
1005 case SIGPIPE
: return "SIGPIPE";
1008 case SIGALRM
: return "SIGALRM";
1010 case SIGTERM
: return "SIGTERM";
1012 case SIGSTKFLT
: return "SIGSTKFLT";
1015 case SIGCHLD
: return "SIGCHLD";
1018 case SIGCONT
: return "SIGCONT";
1021 case SIGSTOP
: return "SIGSTOP";
1024 case SIGTSTP
: return "SIGTSTP";
1027 case SIGTTIN
: return "SIGTTIN";
1030 case SIGTTOU
: return "SIGTTOU";
1033 case SIGURG
: return "SIGURG";
1036 case SIGXCPU
: return "SIGXCPU";
1039 case SIGXFSZ
: return "SIGXFSZ";
1042 case SIGVTALRM
: return "SIGVTALRM";
1045 case SIGPROF
: return "SIGPROF";
1048 case SIGWINCH
: return "SIGWINCH";
1051 case SIGIO
: return "SIGIO";
1054 case SIGPWR
: return "SIGPWR";
1057 case SIGSYS
: return "SIGSYS";
1062 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1063 pa_xfree(PA_STATIC_TLS_GET(signame
));
1064 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1065 PA_STATIC_TLS_SET(signame
, t
);
1074 pa_xfree(PA_STATIC_TLS_GET(signame
));
1075 t
= pa_sprintf_malloc("SIG%i", sig
);
1076 PA_STATIC_TLS_SET(signame
, t
);
1082 /* Check whether the specified GID and the group name match */
1083 static int is_group(gid_t gid
, const char *name
) {
1084 struct group
*group
= NULL
;
1088 if (!(group
= pa_getgrgid_malloc(gid
))) {
1092 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1097 r
= strcmp(name
, group
->gr_name
) == 0;
1100 pa_getgrgid_free(group
);
1105 /* Check the current user is member of the specified group */
1106 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1107 GETGROUPS_T
*gids
, tgid
;
1108 long n
= sysconf(_SC_NGROUPS_MAX
);
1113 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1115 if ((n
= getgroups((int) n
, gids
)) < 0) {
1116 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1120 for (i
= 0; i
< n
; i
++) {
1122 if ((k
= is_group(gids
[i
], name
)) < 0)
1131 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1147 /* Check whether the specifc user id is a member of the specified group */
1148 int pa_uid_in_group(uid_t uid
, const char *name
) {
1149 struct group
*group
= NULL
;
1154 if (!(group
= pa_getgrnam_malloc(name
))) {
1161 for (i
= group
->gr_mem
; *i
; i
++) {
1162 struct passwd
*pw
= NULL
;
1165 if (!(pw
= pa_getpwnam_malloc(*i
)))
1168 if (pw
->pw_uid
== uid
)
1171 pa_getpwnam_free(pw
);
1178 pa_getgrnam_free(group
);
1183 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1184 gid_t
pa_get_gid_of_group(const char *name
) {
1185 gid_t ret
= (gid_t
) -1;
1186 struct group
*gr
= NULL
;
1189 if (!(gr
= pa_getgrnam_malloc(name
))) {
1198 pa_getgrnam_free(gr
);
1202 int pa_check_in_group(gid_t g
) {
1203 gid_t gids
[NGROUPS_MAX
];
1206 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1216 #else /* HAVE_GRP_H */
1218 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1224 int pa_uid_in_group(uid_t uid
, const char *name
) {
1229 gid_t
pa_get_gid_of_group(const char *name
) {
1234 int pa_check_in_group(gid_t g
) {
1241 /* Lock or unlock a file entirely.
1242 (advisory on UNIX, mandatory on Windows) */
1243 int pa_lock_fd(int fd
, int b
) {
1245 struct flock f_lock
;
1247 /* Try a R/W lock first */
1249 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1250 f_lock
.l_whence
= SEEK_SET
;
1254 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1257 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1258 if (b
&& errno
== EBADF
) {
1259 f_lock
.l_type
= F_RDLCK
;
1260 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1264 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1268 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1270 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1272 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1275 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1277 /* FIXME: Needs to set errno! */
1283 /* Remove trailing newlines from a string */
1284 char* pa_strip_nl(char *s
) {
1287 s
[strcspn(s
, NEWLINE
)] = 0;
1291 char *pa_strip(char *s
) {
1294 /* Drops trailing whitespace. Modifies the string in
1295 * place. Returns pointer to first non-space character */
1297 s
+= strspn(s
, WHITESPACE
);
1299 for (e
= s
; *e
; e
++)
1300 if (!strchr(WHITESPACE
, *e
))
1311 /* Create a temporary lock file and lock it. */
1312 int pa_lock_lockfile(const char *fn
) {
1319 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1323 , S_IRUSR
|S_IWUSR
)) < 0) {
1324 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1328 if (pa_lock_fd(fd
, 1) < 0) {
1329 pa_log_warn("Failed to lock file '%s'.", fn
);
1333 if (fstat(fd
, &st
) < 0) {
1334 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1338 /* Check whether the file has been removed meanwhile. When yes,
1339 * restart this loop, otherwise, we're done */
1340 if (st
.st_nlink
>= 1)
1343 if (pa_lock_fd(fd
, 0) < 0) {
1344 pa_log_warn("Failed to unlock file '%s'.", fn
);
1348 if (pa_close(fd
) < 0) {
1349 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1360 int saved_errno
= errno
;
1362 errno
= saved_errno
;
1368 /* Unlock a temporary lcok file */
1369 int pa_unlock_lockfile(const char *fn
, int fd
) {
1374 if (unlink(fn
) < 0) {
1375 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1380 if (pa_lock_fd(fd
, 0) < 0) {
1381 pa_log_warn("Failed to unlock file '%s'.", fn
);
1385 if (pa_close(fd
) < 0) {
1386 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1393 static char *get_pulse_home(void) {
1398 if (!(h
= pa_get_home_dir_malloc())) {
1399 pa_log_error("Failed to get home directory.");
1403 if (stat(h
, &st
) < 0) {
1404 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1409 if (st
.st_uid
!= getuid()) {
1410 pa_log_error("Home directory %s not ours.", h
);
1416 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1424 char *pa_get_state_dir(void) {
1427 /* The state directory shall contain dynamic data that should be
1428 * kept across reboots, and is private to this user */
1430 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1431 if (!(d
= get_pulse_home()))
1434 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1435 * dir then this will break. */
1437 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1438 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1446 char *pa_get_home_dir_malloc(void) {
1448 size_t allocated
= 128;
1451 homedir
= pa_xmalloc(allocated
);
1453 if (!pa_get_home_dir(homedir
, allocated
)) {
1458 if (strlen(homedir
) < allocated
- 1)
1468 char *pa_get_binary_name_malloc(void) {
1470 size_t allocated
= 128;
1473 t
= pa_xmalloc(allocated
);
1475 if (!pa_get_binary_name(t
, allocated
)) {
1480 if (strlen(t
) < allocated
- 1)
1490 static char* make_random_dir(mode_t m
) {
1491 static const char table
[] =
1492 "abcdefghijklmnopqrstuvwxyz"
1493 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1499 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1500 pathlen
= strlen(fn
);
1508 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1509 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1511 u
= umask((~m
) & 0777);
1518 saved_errno
= errno
;
1520 errno
= saved_errno
;
1525 if (errno
!= EEXIST
) {
1526 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1533 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1536 if (!(p
= make_random_dir(m
)))
1540 if (symlink(p
, k
) < 0) {
1541 int saved_errno
= errno
;
1543 if (errno
!= EEXIST
)
1544 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1549 errno
= saved_errno
;
1561 char *pa_get_runtime_dir(void) {
1562 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1566 /* The runtime directory shall contain dynamic data that needs NOT
1567 * to be kept accross reboots and is usuallly private to the user,
1568 * except in system mode, where it might be accessible by other
1569 * users, too. Since we need POSIX locking and UNIX sockets in
1570 * this directory, we link it to a random subdir in /tmp, if it
1571 * was not explicitly configured. */
1573 m
= pa_in_system_mode() ? 0755U : 0700U;
1575 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1577 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1578 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1582 return pa_xstrdup(d
);
1585 if (!(d
= get_pulse_home()))
1588 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1589 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1594 if (!(mid
= pa_machine_id())) {
1599 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1604 /* OK, first let's check if the "runtime" symlink is already
1607 if (!(p
= pa_readlink(k
))) {
1609 if (errno
!= ENOENT
) {
1610 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1615 /* Hmm, so the runtime directory didn't exist yet, so let's
1616 * create one in /tmp and symlink that to it */
1618 if (make_random_dir_and_link(0700, k
) < 0) {
1620 /* Mhmm, maybe another process was quicker than us,
1621 * let's check if that was valid */
1622 if (errno
== EEXIST
)
1628 /* No symlink possible, so let's just create the runtime directly */
1636 /* Make sure that this actually makes sense */
1637 if (!pa_is_path_absolute(p
)) {
1638 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1643 /* Hmm, so this symlink is still around, make sure nobody fools
1647 if (lstat(p
, &st
) < 0) {
1649 if (errno
!= ENOENT
) {
1650 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1656 if (S_ISDIR(st
.st_mode
) &&
1657 (st
.st_uid
== getuid()) &&
1658 ((st
.st_mode
& 0777) == 0700)) {
1664 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1671 /* Hmm, so the link points to some nonexisting or invalid
1672 * dir. Let's replace it by a new link. We first create a
1673 * temporary link and then rename that to allow concurrent
1674 * execution of this function. */
1676 t
= pa_sprintf_malloc("%s.tmp", k
);
1678 if (make_random_dir_and_link(0700, t
) < 0) {
1680 if (errno
!= EEXIST
) {
1681 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1688 /* Hmm, someone lese was quicker then us. Let's give
1689 * him some time to finish, and retry. */
1694 /* OK, we succeeded in creating the temporary symlink, so
1695 * let's rename it */
1696 if (rename(t
, k
) < 0) {
1697 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1713 /* Try to open a configuration file. If "env" is specified, open the
1714 * value of the specified environment variable. Otherwise look for a
1715 * file "local" in the home directory or a file "global" in global
1716 * file system. If "result" is non-NULL, a pointer to a newly
1717 * allocated buffer containing the used configuration file is
1719 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1723 if (env
&& (fn
= getenv(env
))) {
1724 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1726 *result
= pa_xstrdup(fn
);
1731 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1740 if ((e
= getenv("PULSE_CONFIG_PATH")))
1741 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1742 else if ((h
= pa_get_home_dir_malloc())) {
1743 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1748 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1750 *result
= pa_xstrdup(fn
);
1756 if (errno
!= ENOENT
) {
1757 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1769 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1770 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1771 pa_win32_get_toplevel(NULL
),
1772 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1775 gfn
= pa_xstrdup(global
);
1777 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1792 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1795 if (env
&& (fn
= getenv(env
))) {
1796 if (access(fn
, R_OK
) == 0)
1797 return pa_xstrdup(fn
);
1799 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1808 if ((e
= getenv("PULSE_CONFIG_PATH")))
1809 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1810 else if ((h
= pa_get_home_dir_malloc())) {
1811 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1816 if (access(fn
, R_OK
) == 0) {
1817 char *r
= pa_xstrdup(fn
);
1822 if (errno
!= ENOENT
) {
1823 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1835 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1836 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1837 pa_win32_get_toplevel(NULL
),
1838 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1841 gfn
= pa_xstrdup(global
);
1843 if (access(gfn
, R_OK
) == 0)
1853 /* Format the specified data as a hexademical string */
1854 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1855 size_t i
= 0, j
= 0;
1856 const char hex
[] = "0123456789abcdef";
1860 pa_assert(slength
> 0);
1862 while (j
+2 < slength
&& i
< dlength
) {
1863 s
[j
++] = hex
[*d
>> 4];
1864 s
[j
++] = hex
[*d
& 0xF];
1870 s
[j
< slength
? j
: slength
] = 0;
1874 /* Convert a hexadecimal digit to a number or -1 if invalid */
1875 static int hexc(char c
) {
1876 if (c
>= '0' && c
<= '9')
1879 if (c
>= 'A' && c
<= 'F')
1880 return c
- 'A' + 10;
1882 if (c
>= 'a' && c
<= 'f')
1883 return c
- 'a' + 10;
1889 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1890 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1896 while (j
< dlength
&& *p
) {
1899 if ((b
= hexc(*(p
++))) < 0)
1902 d
[j
] = (uint8_t) (b
<< 4);
1907 if ((b
= hexc(*(p
++))) < 0)
1910 d
[j
] |= (uint8_t) b
;
1917 /* Returns nonzero when *s starts with *pfx */
1918 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1926 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1929 /* Returns nonzero when *s ends with *sfx */
1930 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1939 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1942 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1948 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1952 char *pa_make_path_absolute(const char *p
) {
1958 if (pa_is_path_absolute(p
))
1959 return pa_xstrdup(p
);
1961 if (!(cwd
= pa_getcwd()))
1962 return pa_xstrdup(p
);
1964 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1969 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1970 * if fn is non-null and starts with / return fn
1971 * otherwise append fn to the run time path and return it */
1972 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1975 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1980 if (pa_is_path_absolute(fn
))
1981 return pa_xstrdup(fn
);
1989 if (!(mid
= pa_machine_id())) {
1994 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1997 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
2005 char *pa_runtime_path(const char *fn
) {
2006 return get_path(fn
, FALSE
, TRUE
);
2009 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2010 return get_path(fn
, appendmid
, FALSE
);
2013 /* Convert the string s to a signed integer in *ret_i */
2014 int pa_atoi(const char *s
, int32_t *ret_i
) {
2022 l
= strtol(s
, &x
, 0);
2024 if (!x
|| *x
|| errno
) {
2030 if ((int32_t) l
!= l
) {
2035 *ret_i
= (int32_t) l
;
2040 /* Convert the string s to an unsigned integer in *ret_u */
2041 int pa_atou(const char *s
, uint32_t *ret_u
) {
2049 l
= strtoul(s
, &x
, 0);
2051 if (!x
|| *x
|| errno
) {
2057 if ((uint32_t) l
!= l
) {
2062 *ret_u
= (uint32_t) l
;
2067 #ifdef HAVE_STRTOF_L
2068 static locale_t c_locale
= NULL
;
2070 static void c_locale_destroy(void) {
2071 freelocale(c_locale
);
2075 int pa_atod(const char *s
, double *ret_d
) {
2082 /* This should be locale independent */
2084 #ifdef HAVE_STRTOF_L
2088 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2089 atexit(c_locale_destroy
);
2095 f
= strtod_l(s
, &x
, c_locale
);
2103 if (!x
|| *x
|| errno
) {
2114 /* Same as snprintf, but guarantees NUL-termination on every platform */
2115 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2120 pa_assert(size
> 0);
2123 va_start(ap
, format
);
2124 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2130 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2131 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2135 pa_assert(size
> 0);
2138 ret
= vsnprintf(str
, size
, format
, ap
);
2145 if ((size_t) ret
> size
-1)
2148 return (size_t) ret
;
2151 /* Truncate the specified string, but guarantee that the string
2152 * returned still validates as UTF8 */
2153 char *pa_truncate_utf8(char *c
, size_t l
) {
2155 pa_assert(pa_utf8_valid(c
));
2162 while (l
> 0 && !pa_utf8_valid(c
))
2168 char *pa_getcwd(void) {
2172 char *p
= pa_xmalloc(l
);
2176 if (errno
!= ERANGE
)
2184 void *pa_will_need(const void *p
, size_t l
) {
2185 #ifdef RLIMIT_MEMLOCK
2196 a
= PA_PAGE_ALIGN_PTR(p
);
2197 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2199 #ifdef HAVE_POSIX_MADVISE
2200 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2201 pa_log_debug("posix_madvise() worked fine!");
2206 /* Most likely the memory was not mmap()ed from a file and thus
2207 * madvise() didn't work, so let's misuse mlock() do page this
2208 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2209 * inviting, the man page of mlock() tells us: "All pages that
2210 * contain a part of the specified address range are guaranteed to
2211 * be resident in RAM when the call returns successfully." */
2213 #ifdef RLIMIT_MEMLOCK
2214 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2216 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2217 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
));
2222 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2224 bs
= PA_PAGE_SIZE
*4;
2227 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2230 while (size
> 0 && bs
> 0) {
2235 if (mlock(a
, bs
) < 0) {
2236 bs
= PA_PAGE_ALIGN(bs
/ 2);
2240 pa_assert_se(munlock(a
, bs
) == 0);
2242 a
= (const uint8_t*) a
+ bs
;
2248 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2250 pa_log_debug("mlock() worked fine!");
2255 void pa_close_pipe(int fds
[2]) {
2259 pa_assert_se(pa_close(fds
[0]) == 0);
2262 pa_assert_se(pa_close(fds
[1]) == 0);
2264 fds
[0] = fds
[1] = -1;
2267 char *pa_readlink(const char *p
) {
2268 #ifdef HAVE_READLINK
2277 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2282 if ((size_t) n
< l
-1) {
2295 int pa_close_all(int except_fd
, ...) {
2300 va_start(ap
, except_fd
);
2303 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2308 p
= pa_xnew(int, n
+1);
2310 va_start(ap
, except_fd
);
2313 if (except_fd
>= 0) {
2317 while ((fd
= va_arg(ap
, int)) >= 0)
2324 r
= pa_close_allv(p
);
2330 int pa_close_allv(const int except_fds
[]) {
2339 if ((d
= opendir("/proc/self/fd"))) {
2343 while ((de
= readdir(d
))) {
2349 if (de
->d_name
[0] == '.')
2353 l
= strtol(de
->d_name
, &e
, 10);
2354 if (errno
!= 0 || !e
|| *e
) {
2362 if ((long) fd
!= l
) {
2375 for (i
= 0; except_fds
[i
] >= 0; i
++)
2376 if (except_fds
[i
] == fd
) {
2384 if (pa_close(fd
) < 0) {
2385 saved_errno
= errno
;
2387 errno
= saved_errno
;
2399 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2400 maxfd
= (int) rl
.rlim_max
;
2402 maxfd
= sysconf(_SC_OPEN_MAX
);
2404 for (fd
= 3; fd
< maxfd
; fd
++) {
2409 for (i
= 0; except_fds
[i
] >= 0; i
++)
2410 if (except_fds
[i
] == fd
) {
2418 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2421 #endif /* !OS_IS_WIN32 */
2426 int pa_unblock_sigs(int except
, ...) {
2431 va_start(ap
, except
);
2434 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2439 p
= pa_xnew(int, n
+1);
2441 va_start(ap
, except
);
2448 while ((sig
= va_arg(ap
, int)) >= 0)
2455 r
= pa_unblock_sigsv(p
);
2461 int pa_unblock_sigsv(const int except
[]) {
2466 if (sigemptyset(&ss
) < 0)
2469 for (i
= 0; except
[i
] > 0; i
++)
2470 if (sigaddset(&ss
, except
[i
]) < 0)
2473 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2479 int pa_reset_sigs(int except
, ...) {
2484 va_start(ap
, except
);
2487 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2492 p
= pa_xnew(int, n
+1);
2494 va_start(ap
, except
);
2501 while ((sig
= va_arg(ap
, int)) >= 0)
2508 r
= pa_reset_sigsv(p
);
2514 int pa_reset_sigsv(const int except
[]) {
2518 for (sig
= 1; sig
< NSIG
; sig
++) {
2519 pa_bool_t reset
= TRUE
;
2530 for (i
= 0; except
[i
] > 0; i
++) {
2531 if (sig
== except
[i
]) {
2540 struct sigaction sa
;
2542 memset(&sa
, 0, sizeof(sa
));
2543 sa
.sa_handler
= SIG_DFL
;
2545 /* On Linux the first two RT signals are reserved by
2546 * glibc, and sigaction() will return EINVAL for them. */
2547 if ((sigaction(sig
, &sa
, NULL
) < 0))
2548 if (errno
!= EINVAL
)
2557 void pa_set_env(const char *key
, const char *value
) {
2561 /* This is not thread-safe */
2564 SetEnvironmentVariable(key
, value
);
2566 setenv(key
, value
, 1);
2570 void pa_set_env_and_record(const char *key
, const char *value
) {
2574 /* This is not thread-safe */
2576 pa_set_env(key
, value
);
2577 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2580 void pa_unset_env_recorded(void) {
2582 /* This is not thread-safe */
2587 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2593 SetEnvironmentVariable(s
, NULL
);
2601 pa_bool_t
pa_in_system_mode(void) {
2604 if (!(e
= getenv("PULSE_SYSTEM")))
2610 char *pa_get_user_name_malloc(void) {
2614 #ifdef _SC_LOGIN_NAME_MAX
2615 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2621 u
= pa_xnew(char, k
+1);
2623 if (!(pa_get_user_name(u
, k
))) {
2631 char *pa_get_host_name_malloc(void) {
2640 if (!pa_get_host_name(c
, l
)) {
2642 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2645 } else if (strlen(c
) < l
-1) {
2653 u
= pa_utf8_filter(c
);
2658 /* Hmm, the hostname is as long the space we offered the
2659 * function, we cannot know if it fully fit in, so let's play
2660 * safe and retry. */
2669 char *pa_machine_id(void) {
2673 /* The returned value is supposed be some kind of ascii identifier
2674 * that is unique and stable across reboots. */
2676 /* First we try the D-Bus UUID, which is the best option we have,
2677 * since it fits perfectly our needs and is not as volatile as the
2678 * hostname which might be set from dhcp. */
2680 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2681 char ln
[34] = "", *r
;
2683 r
= fgets(ln
, sizeof(ln
)-1, f
);
2689 return pa_utf8_filter(ln
);
2692 if ((h
= pa_get_host_name_malloc()))
2696 /* If no hostname was set we use the POSIX hostid. It's usually
2697 * the IPv4 address. Might not be that stable. */
2698 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2704 char *pa_session_id(void) {
2707 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2710 return pa_utf8_filter(e
);
2713 char *pa_uname_string(void) {
2717 pa_assert_se(uname(&u
) >= 0);
2719 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2725 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2726 pa_assert_se(GetVersionEx(&i
));
2728 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2732 #ifdef HAVE_VALGRIND_MEMCHECK_H
2733 pa_bool_t
pa_in_valgrind(void) {
2736 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2737 * here instead of really checking whether we run in valgrind or
2741 b
= getenv("VALGRIND") ? 2 : 1;
2747 unsigned pa_gcd(unsigned a
, unsigned b
) {
2758 void pa_reduce(unsigned *num
, unsigned *den
) {
2760 unsigned gcd
= pa_gcd(*num
, *den
);
2768 pa_assert(pa_gcd(*num
, *den
) == 1);
2771 unsigned pa_ncpus(void) {
2774 #ifdef _SC_NPROCESSORS_CONF
2775 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2780 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2783 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2792 sb
= pa_strbuf_new();
2797 if (!(p
= strstr(s
, a
)))
2800 pa_strbuf_putsn(sb
, s
, p
-s
);
2801 pa_strbuf_puts(sb
, b
);
2805 pa_strbuf_puts(sb
, s
);
2807 return pa_strbuf_tostring_free(sb
);
2810 char *pa_escape(const char *p
, const char *chars
) {
2813 pa_strbuf
*buf
= pa_strbuf_new();
2815 for (s
= p
; *s
; ++s
) {
2817 pa_strbuf_putc(buf
, '\\');
2819 for (c
= chars
; *c
; ++c
) {
2821 pa_strbuf_putc(buf
, '\\');
2826 pa_strbuf_putc(buf
, *s
);
2829 return pa_strbuf_tostring_free(buf
);
2832 char *pa_unescape(char *p
) {
2834 pa_bool_t escaped
= FALSE
;
2836 for (s
= p
, d
= p
; *s
; s
++) {
2837 if (!escaped
&& *s
== '\\') {
2851 char *pa_realpath(const char *path
) {
2855 /* We want only abolsute paths */
2856 if (path
[0] != '/') {
2861 #if defined(__GLIBC__) || defined(__APPLE__)
2865 if (!(r
= realpath(path
, NULL
)))
2868 /* We copy this here in case our pa_xmalloc() is not
2869 * implemented on top of libc malloc() */
2873 #elif defined(PATH_MAX)
2876 path_buf
= pa_xmalloc(PATH_MAX
);
2878 #if defined(OS_IS_WIN32)
2879 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2884 if (!(t
= realpath(path
, path_buf
))) {
2891 #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."
2897 void pa_disable_sigpipe(void) {
2900 struct sigaction sa
;
2904 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2905 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2909 sa
.sa_handler
= SIG_IGN
;
2911 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2912 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2918 void pa_xfreev(void**a
) {
2924 for (p
= a
; *p
; p
++)
2930 char **pa_split_spaces_strv(const char *s
) {
2932 unsigned i
= 0, n
= 8;
2933 const char *state
= NULL
;
2935 t
= pa_xnew(char*, n
);
2936 while ((e
= pa_split_spaces(s
, &state
))) {
2941 t
= pa_xrenew(char*, t
, n
);
2954 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2957 if (pa_is_path_absolute(path
))
2958 return pa_xstrdup(path
);
2960 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2963 size_t pa_pipe_buf(int fd
) {
2968 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2979 void pa_reset_personality(void) {
2982 if (personality(PER_LINUX
) < 0)
2983 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2988 #if defined(__linux__) && !defined(__OPTIMIZE__)
2990 pa_bool_t
pa_run_from_build_tree(void) {
2992 pa_bool_t b
= FALSE
;
2994 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2997 if ((rp
= pa_readlink("/proc/self/exe"))) {
2998 b
= pa_startswith(rp
, PA_BUILDDIR
);
3007 const char *pa_get_temp_dir(void) {
3010 if ((t
= getenv("TMPDIR")) &&
3011 pa_is_path_absolute(t
))
3014 if ((t
= getenv("TMP")) &&
3015 pa_is_path_absolute(t
))
3018 if ((t
= getenv("TEMP")) &&
3019 pa_is_path_absolute(t
))
3022 if ((t
= getenv("TEMPDIR")) &&
3023 pa_is_path_absolute(t
))
3029 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3037 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3040 if (errno
!= EINVAL
)
3044 if ((fd
= open(fn
, flags
, mode
)) < 0)
3048 /* Some implementations might simply ignore O_CLOEXEC if it is not
3049 * understood, make sure FD_CLOEXEC is enabled anyway */
3051 pa_make_fd_cloexec(fd
);
3055 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3059 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3062 if (errno
!= EINVAL
)
3066 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3070 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3071 * not understood, make sure FD_CLOEXEC is enabled anyway */
3073 pa_make_fd_cloexec(fd
);
3077 int pa_pipe_cloexec(int pipefd
[2]) {
3081 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3084 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3089 if ((r
= pipe(pipefd
)) < 0)
3093 pa_make_fd_cloexec(pipefd
[0]);
3094 pa_make_fd_cloexec(pipefd
[1]);
3099 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3103 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3106 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3111 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3115 pa_make_fd_cloexec(fd
);
3119 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3123 m
= pa_sprintf_malloc("%se", mode
);
3126 if ((f
= fopen(path
, m
))) {
3133 if (errno
!= EINVAL
)
3136 if (!(f
= fopen(path
, mode
)))
3140 pa_make_fd_cloexec(fileno(f
));
3144 void pa_nullify_stdfds(void) {
3147 pa_close(STDIN_FILENO
);
3148 pa_close(STDOUT_FILENO
);
3149 pa_close(STDERR_FILENO
);
3151 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3152 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3153 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3160 char *pa_read_line_from_file(const char *fn
) {
3162 char ln
[256] = "", *r
;
3164 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3167 r
= fgets(ln
, sizeof(ln
)-1, f
);
3176 return pa_xstrdup(ln
);
3179 pa_bool_t
pa_running_in_vm(void) {
3181 #if defined(__i386__) || defined(__x86_64__)
3183 /* Both CPUID and DMI are x86 specific interfaces... */
3185 uint32_t eax
= 0x40000000;
3192 const char *const dmi_vendors
[] = {
3193 "/sys/class/dmi/id/sys_vendor",
3194 "/sys/class/dmi/id/board_vendor",
3195 "/sys/class/dmi/id/bios_vendor"
3200 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3203 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3205 if (pa_startswith(s
, "QEMU") ||
3206 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3207 pa_startswith(s
, "VMware") ||
3208 pa_startswith(s
, "VMW") ||
3209 pa_startswith(s
, "Microsoft Corporation") ||
3210 pa_startswith(s
, "innotek GmbH") ||
3211 pa_startswith(s
, "Xen")) {
3223 /* http://lwn.net/Articles/301888/ */
3226 __asm__
__volatile__ (
3227 /* ebx/rbx is being used for PIC! */
3228 " push %%"PA_REG_b
" \n\t"
3230 " mov %%ebx, %1 \n\t"
3231 " pop %%"PA_REG_b
" \n\t"
3233 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3237 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3238 pa_streq(sig
.text
, "KVMKVMKVM") ||
3239 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3240 pa_streq(sig
.text
, "VMwareVMware") ||
3241 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3242 pa_streq(sig
.text
, "Microsoft Hv"))