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
39 #include <sys/types.h>
44 #ifdef HAVE_LANGINFO_H
49 #include <sys/utsname.h>
52 #if defined(HAVE_REGEX_H)
54 #elif defined(HAVE_PCREPOSIX_H)
55 #include <pcreposix.h>
65 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
66 #define SCHED_RESET_ON_FORK 0x40000000
70 #ifdef HAVE_SYS_RESOURCE_H
71 #include <sys/resource.h>
74 #ifdef HAVE_SYS_CAPABILITY_H
75 #include <sys/capability.h>
78 #ifdef HAVE_SYS_MMAN_H
106 #ifdef HAVE_LIBSAMPLERATE
107 #include <samplerate.h>
119 #include <sys/personality.h>
122 #include <pulse/xmalloc.h>
123 #include <pulse/util.h>
124 #include <pulse/utf8.h>
126 #include <pulsecore/core-error.h>
127 #include <pulsecore/socket.h>
128 #include <pulsecore/log.h>
129 #include <pulsecore/macro.h>
130 #include <pulsecore/thread.h>
131 #include <pulsecore/strbuf.h>
132 #include <pulsecore/usergroup.h>
133 #include <pulsecore/strlist.h>
134 #include <pulsecore/cpu-x86.h>
135 #include <pulsecore/pipe.h>
137 #include "core-util.h"
139 /* Not all platforms have this */
141 #define MSG_NOSIGNAL 0
144 #define NEWLINE "\r\n"
145 #define WHITESPACE "\n\r \t"
147 static pa_strlist
*recorded_env
= NULL
;
151 #define PULSE_ROOTENV "PULSE_ROOT"
153 int pa_set_root(HANDLE handle
) {
154 char library_path
[MAX_PATH
], *sep
;
156 /* FIXME: Needs to set errno */
158 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
161 sep
= strrchr(library_path
, PA_PATH_SEP_CHAR
);
165 if (!SetEnvironmentVariable(PULSE_ROOTENV
, library_path
))
173 /** Make a file descriptor nonblock. Doesn't do any error checking */
174 void pa_make_fd_nonblock(int fd
) {
180 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
182 if (!(v
& O_NONBLOCK
))
183 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
185 #elif defined(OS_IS_WIN32)
187 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
188 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
189 pa_log_warn("Only sockets can be made non-blocking!");
192 pa_log_warn("Non-blocking I/O not supported.!");
197 /* Set the FD_CLOEXEC flag for a fd */
198 void pa_make_fd_cloexec(int fd
) {
204 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
206 if (!(v
& FD_CLOEXEC
))
207 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
212 /** Creates a directory securely */
213 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
215 int r
, saved_errno
, fd
;
224 u
= umask((~m
) & 0777);
230 if (r
< 0 && errno
!= EEXIST
)
233 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
247 if (fstat(fd
, &st
) < 0) {
248 pa_assert_se(pa_close(fd
) >= 0);
252 if (!S_ISDIR(st
.st_mode
)) {
253 pa_assert_se(pa_close(fd
) >= 0);
259 if (uid
== (uid_t
)-1)
261 if (gid
== (gid_t
)-1)
263 (void) fchown(fd
, uid
, gid
);
267 (void) fchmod(fd
, m
);
270 pa_assert_se(pa_close(fd
) >= 0);
274 if (lstat(dir
, &st
) < 0)
276 if (stat(dir
, &st
) < 0)
281 if (!S_ISDIR(st
.st_mode
) ||
282 (st
.st_uid
!= uid
) ||
283 (st
.st_gid
!= gid
) ||
284 ((st
.st_mode
& 0777) != m
)) {
289 pa_log_warn("Secure directory creation not supported on Win32.");
302 /* Return a newly allocated sting containing the parent directory of the specified file */
303 char *pa_parent_dir(const char *fn
) {
304 char *slash
, *dir
= pa_xstrdup(fn
);
306 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
316 /* Creates a the parent directory of the specified path securely */
317 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
321 if (!(dir
= pa_parent_dir(fn
)))
324 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
334 /** Platform independent read function. Necessary since not all
335 * systems treat all file descriptors equal. If type is
336 * non-NULL it is used to cache the type of the fd. This is
337 * useful for making sure that only a single syscall is executed per
338 * function call. The variable pointed to should be initialized to 0
340 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
344 if (!type
|| *type
== 0) {
347 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
350 if (WSAGetLastError() != WSAENOTSOCK
) {
351 errno
= WSAGetLastError();
364 if ((r
= read(fd
, buf
, count
)) < 0)
372 /** Similar to pa_read(), but handles writes */
373 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
375 if (!type
|| *type
== 0) {
379 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
391 if (WSAGetLastError() != WSAENOTSOCK
) {
392 errno
= WSAGetLastError();
396 if (errno
!= ENOTSOCK
)
407 if ((r
= write(fd
, buf
, count
)) < 0)
415 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
416 * unless EOF is reached or an error occurred */
417 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
433 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
440 data
= (uint8_t*) data
+ r
;
447 /** Similar to pa_loop_read(), but wraps write() */
448 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
464 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
471 data
= (const uint8_t*) data
+ r
;
478 /** Platform independent read function. Necessary since not all
479 * systems treat all file descriptors equal. */
480 int pa_close(int fd
) {
485 if ((ret
= closesocket(fd
)) == 0)
488 if (WSAGetLastError() != WSAENOTSOCK
) {
489 errno
= WSAGetLastError();
497 if ((r
= close(fd
)) < 0)
505 /* Print a warning messages in case that the given signal is not
506 * blocked or trapped */
507 void pa_check_signal_is_blocked(int sig
) {
508 #ifdef HAVE_SIGACTION
512 /* If POSIX threads are supported use thread-aware
513 * pthread_sigmask() function, to check if the signal is
514 * blocked. Otherwise fall back to sigprocmask() */
517 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
519 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
520 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
527 if (sigismember(&set
, sig
))
530 /* Check whether the signal is trapped */
532 if (sigaction(sig
, NULL
, &sa
) < 0) {
533 pa_log("sigaction(): %s", pa_cstrerror(errno
));
537 if (sa
.sa_handler
!= SIG_DFL
)
540 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
541 #else /* HAVE_SIGACTION */
542 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
546 /* The following function is based on an example from the GNU libc
547 * documentation. This function is similar to GNU's asprintf(). */
548 char *pa_sprintf_malloc(const char *format
, ...) {
558 c
= pa_xrealloc(c
, size
);
560 va_start(ap
, format
);
561 r
= vsnprintf(c
, size
, format
, ap
);
566 if (r
> -1 && (size_t) r
< size
)
569 if (r
> -1) /* glibc 2.1 */
576 /* Same as the previous function, but use a va_list instead of an
578 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
588 c
= pa_xrealloc(c
, size
);
591 r
= vsnprintf(c
, size
, format
, aq
);
596 if (r
> -1 && (size_t) r
< size
)
599 if (r
> -1) /* glibc 2.1 */
606 /* Similar to OpenBSD's strlcpy() function */
607 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
625 static int set_scheduler(int rtprio
) {
627 struct sched_param sp
;
633 dbus_error_init(&error
);
637 sp
.sched_priority
= rtprio
;
639 #ifdef SCHED_RESET_ON_FORK
640 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
641 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
646 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
647 pa_log_debug("SCHED_RR worked.");
650 #endif /* HAVE_SCHED_H */
653 /* Try to talk to RealtimeKit */
655 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
656 pa_log("Failed to connect to system bus: %s\n", error
.message
);
657 dbus_error_free(&error
);
662 /* We need to disable exit on disconnect because otherwise
663 * dbus_shutdown will kill us. See
664 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
665 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
667 r
= rtkit_make_realtime(bus
, 0, rtprio
);
668 dbus_connection_unref(bus
);
671 pa_log_debug("RealtimeKit worked.");
683 /* Make the current thread a realtime thread, and acquire the highest
684 * rtprio we can get that is less or equal the specified parameter. If
685 * the thread is already realtime, don't do anything. */
686 int pa_make_realtime(int rtprio
) {
688 #ifdef _POSIX_PRIORITY_SCHEDULING
691 if (set_scheduler(rtprio
) >= 0) {
692 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
696 for (p
= rtprio
-1; p
>= 1; p
--)
697 if (set_scheduler(p
) >= 0) {
698 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
701 #elif defined(OS_IS_WIN32)
702 /* Windows only allows realtime scheduling to be set on a per process basis.
703 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
704 if(SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
705 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
709 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
714 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
718 static int set_nice(int nice_level
) {
724 dbus_error_init(&error
);
727 #ifdef HAVE_SYS_RESOURCE_H
728 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
729 pa_log_debug("setpriority() worked.");
735 /* Try to talk to RealtimeKit */
737 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
738 pa_log("Failed to connect to system bus: %s\n", error
.message
);
739 dbus_error_free(&error
);
744 /* We need to disable exit on disconnect because otherwise
745 * dbus_shutdown will kill us. See
746 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
747 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
749 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
750 dbus_connection_unref(bus
);
753 pa_log_debug("RealtimeKit worked.");
763 /* Raise the priority of the current process as much as possible that
764 * is <= the specified nice level..*/
765 int pa_raise_priority(int nice_level
) {
767 #ifdef HAVE_SYS_RESOURCE_H
770 if (set_nice(nice_level
) >= 0) {
771 pa_log_info("Successfully gained nice level %i.", nice_level
);
775 for (n
= nice_level
+1; n
< 0; n
++)
776 if (set_nice(n
) >= 0) {
777 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
781 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
786 if (nice_level
< 0) {
787 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
788 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
793 pa_log_info("Successfully gained high priority class.");
800 /* Reset the priority to normal, inverting the changes made by
801 * pa_raise_priority() and pa_make_realtime()*/
802 void pa_reset_priority(void) {
803 #ifdef HAVE_SYS_RESOURCE_H
804 struct sched_param sp
;
806 setpriority(PRIO_PROCESS
, 0, 0);
809 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
813 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
817 int pa_match(const char *expr
, const char *v
) {
822 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
827 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
829 else if (k
== REG_NOMATCH
)
842 /* Try to parse a boolean string value.*/
843 int pa_parse_boolean(const char *v
) {
847 /* First we check language independant */
848 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
850 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
853 #ifdef HAVE_LANGINFO_H
854 /* And then we check language dependant */
855 if ((expr
= nl_langinfo(YESEXPR
)))
857 if (pa_match(expr
, v
) > 0)
860 if ((expr
= nl_langinfo(NOEXPR
)))
862 if (pa_match(expr
, v
) > 0)
870 /* Split the specified string wherever one of the strings in delimiter
871 * occurs. Each time it is called returns a newly allocated string
872 * with pa_xmalloc(). The variable state points to, should be
873 * initiallized to NULL before the first call. */
874 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
875 const char *current
= *state
? *state
: c
;
881 l
= strcspn(current
, delimiter
);
887 return pa_xstrndup(current
, l
);
890 /* Split a string into words. Otherwise similar to pa_split(). */
891 char *pa_split_spaces(const char *c
, const char **state
) {
892 const char *current
= *state
? *state
: c
;
895 if (!*current
|| *c
== 0)
898 current
+= strspn(current
, WHITESPACE
);
899 l
= strcspn(current
, WHITESPACE
);
903 return pa_xstrndup(current
, l
);
906 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
908 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
909 const char *pa_sig2str(int sig
) {
922 char buf
[SIG2STR_MAX
];
924 if (sig2str(sig
, buf
) == 0) {
925 pa_xfree(PA_STATIC_TLS_GET(signame
));
926 t
= pa_sprintf_malloc("SIG%s", buf
);
927 PA_STATIC_TLS_SET(signame
, t
);
935 case SIGHUP
: return "SIGHUP";
937 case SIGINT
: return "SIGINT";
939 case SIGQUIT
: return "SIGQUIT";
941 case SIGILL
: return "SIGULL";
943 case SIGTRAP
: return "SIGTRAP";
945 case SIGABRT
: return "SIGABRT";
947 case SIGBUS
: return "SIGBUS";
949 case SIGFPE
: return "SIGFPE";
951 case SIGKILL
: return "SIGKILL";
954 case SIGUSR1
: return "SIGUSR1";
956 case SIGSEGV
: return "SIGSEGV";
958 case SIGUSR2
: return "SIGUSR2";
961 case SIGPIPE
: return "SIGPIPE";
964 case SIGALRM
: return "SIGALRM";
966 case SIGTERM
: return "SIGTERM";
968 case SIGSTKFLT
: return "SIGSTKFLT";
971 case SIGCHLD
: return "SIGCHLD";
974 case SIGCONT
: return "SIGCONT";
977 case SIGSTOP
: return "SIGSTOP";
980 case SIGTSTP
: return "SIGTSTP";
983 case SIGTTIN
: return "SIGTTIN";
986 case SIGTTOU
: return "SIGTTOU";
989 case SIGURG
: return "SIGURG";
992 case SIGXCPU
: return "SIGXCPU";
995 case SIGXFSZ
: return "SIGXFSZ";
998 case SIGVTALRM
: return "SIGVTALRM";
1001 case SIGPROF
: return "SIGPROF";
1004 case SIGWINCH
: return "SIGWINCH";
1007 case SIGIO
: return "SIGIO";
1010 case SIGPWR
: return "SIGPWR";
1013 case SIGSYS
: return "SIGSYS";
1018 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1019 pa_xfree(PA_STATIC_TLS_GET(signame
));
1020 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1021 PA_STATIC_TLS_SET(signame
, t
);
1030 pa_xfree(PA_STATIC_TLS_GET(signame
));
1031 t
= pa_sprintf_malloc("SIG%i", sig
);
1032 PA_STATIC_TLS_SET(signame
, t
);
1038 /* Check whether the specified GID and the group name match */
1039 static int is_group(gid_t gid
, const char *name
) {
1040 struct group
*group
= NULL
;
1044 if (!(group
= pa_getgrgid_malloc(gid
)))
1049 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1054 r
= strcmp(name
, group
->gr_name
) == 0;
1057 pa_getgrgid_free(group
);
1062 /* Check the current user is member of the specified group */
1063 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1064 GETGROUPS_T
*gids
, tgid
;
1065 long n
= sysconf(_SC_NGROUPS_MAX
);
1070 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1072 if ((n
= getgroups((int) n
, gids
)) < 0) {
1073 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1077 for (i
= 0; i
< n
; i
++) {
1079 if ((k
= is_group(gids
[i
], name
)) < 0)
1088 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1104 /* Check whether the specifc user id is a member of the specified group */
1105 int pa_uid_in_group(uid_t uid
, const char *name
) {
1106 struct group
*group
= NULL
;
1111 if (!(group
= pa_getgrnam_malloc(name
)))
1119 for (i
= group
->gr_mem
; *i
; i
++) {
1120 struct passwd
*pw
= NULL
;
1123 if (!(pw
= pa_getpwnam_malloc(*i
)))
1126 if (pw
->pw_uid
== uid
)
1129 pa_getpwnam_free(pw
);
1136 pa_getgrnam_free(group
);
1141 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1142 gid_t
pa_get_gid_of_group(const char *name
) {
1143 gid_t ret
= (gid_t
) -1;
1144 struct group
*gr
= NULL
;
1147 if (!(gr
= pa_getgrnam_malloc(name
)))
1157 pa_getgrnam_free(gr
);
1161 int pa_check_in_group(gid_t g
) {
1162 gid_t gids
[NGROUPS_MAX
];
1165 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1175 #else /* HAVE_GRP_H */
1177 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1183 int pa_uid_in_group(uid_t uid
, const char *name
) {
1188 gid_t
pa_get_gid_of_group(const char *name
) {
1193 int pa_check_in_group(gid_t g
) {
1200 /* Lock or unlock a file entirely.
1201 (advisory on UNIX, mandatory on Windows) */
1202 int pa_lock_fd(int fd
, int b
) {
1204 struct flock f_lock
;
1206 /* Try a R/W lock first */
1208 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1209 f_lock
.l_whence
= SEEK_SET
;
1213 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1216 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1217 if (b
&& errno
== EBADF
) {
1218 f_lock
.l_type
= F_RDLCK
;
1219 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1223 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1227 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
1229 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1231 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1234 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1236 /* FIXME: Needs to set errno! */
1242 /* Remove trailing newlines from a string */
1243 char* pa_strip_nl(char *s
) {
1246 s
[strcspn(s
, NEWLINE
)] = 0;
1250 char *pa_strip(char *s
) {
1253 /* Drops trailing whitespace. Modifies the string in
1254 * place. Returns pointer to first non-space character */
1256 s
+= strspn(s
, WHITESPACE
);
1258 for (e
= s
; *e
; e
++)
1259 if (!strchr(WHITESPACE
, *e
))
1270 /* Create a temporary lock file and lock it. */
1271 int pa_lock_lockfile(const char *fn
) {
1278 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1282 , S_IRUSR
|S_IWUSR
)) < 0) {
1283 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1287 if (pa_lock_fd(fd
, 1) < 0) {
1288 pa_log_warn("Failed to lock file '%s'.", fn
);
1292 if (fstat(fd
, &st
) < 0) {
1293 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1297 /* Check whether the file has been removed meanwhile. When yes,
1298 * restart this loop, otherwise, we're done */
1299 if (st
.st_nlink
>= 1)
1302 if (pa_lock_fd(fd
, 0) < 0) {
1303 pa_log_warn("Failed to unlock file '%s'.", fn
);
1307 if (pa_close(fd
) < 0) {
1308 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1319 int saved_errno
= errno
;
1321 errno
= saved_errno
;
1327 /* Unlock a temporary lcok file */
1328 int pa_unlock_lockfile(const char *fn
, int fd
) {
1333 if (unlink(fn
) < 0) {
1334 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1339 if (pa_lock_fd(fd
, 0) < 0) {
1340 pa_log_warn("Failed to unlock file '%s'.", fn
);
1344 if (pa_close(fd
) < 0) {
1345 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1352 static char *get_pulse_home(void) {
1357 if (!(h
= pa_get_home_dir_malloc())) {
1358 pa_log_error("Failed to get home directory.");
1362 if (stat(h
, &st
) < 0) {
1363 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1368 if (st
.st_uid
!= getuid()) {
1369 pa_log_error("Home directory %s not ours.", h
);
1375 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1383 char *pa_get_state_dir(void) {
1386 /* The state directory shall contain dynamic data that should be
1387 * kept across reboots, and is private to this user */
1389 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1390 if (!(d
= get_pulse_home()))
1393 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1394 * dir then this will break. */
1396 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1397 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1405 char *pa_get_home_dir_malloc(void) {
1407 size_t allocated
= 128;
1410 homedir
= pa_xmalloc(allocated
);
1412 if (!pa_get_home_dir(homedir
, allocated
)) {
1417 if (strlen(homedir
) < allocated
- 1)
1427 char *pa_get_binary_name_malloc(void) {
1429 size_t allocated
= 128;
1432 t
= pa_xmalloc(allocated
);
1434 if (!pa_get_binary_name(t
, allocated
)) {
1439 if (strlen(t
) < allocated
- 1)
1449 static char* make_random_dir(mode_t m
) {
1450 static const char table
[] =
1451 "abcdefghijklmnopqrstuvwxyz"
1452 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1458 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1459 pathlen
= strlen(fn
);
1467 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1468 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1470 u
= umask((~m
) & 0777);
1477 saved_errno
= errno
;
1479 errno
= saved_errno
;
1484 if (errno
!= EEXIST
) {
1485 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1492 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1495 if (!(p
= make_random_dir(m
)))
1499 if (symlink(p
, k
) < 0) {
1500 int saved_errno
= errno
;
1502 if (errno
!= EEXIST
)
1503 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1508 errno
= saved_errno
;
1520 char *pa_get_runtime_dir(void) {
1521 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1525 /* The runtime directory shall contain dynamic data that needs NOT
1526 * to be kept accross reboots and is usuallly private to the user,
1527 * except in system mode, where it might be accessible by other
1528 * users, too. Since we need POSIX locking and UNIX sockets in
1529 * this directory, we link it to a random subdir in /tmp, if it
1530 * was not explicitly configured. */
1532 m
= pa_in_system_mode() ? 0755U : 0700U;
1534 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1536 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1537 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1541 return pa_xstrdup(d
);
1544 if (!(d
= get_pulse_home()))
1547 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1548 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1553 if (!(mid
= pa_machine_id())) {
1558 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1563 /* OK, first let's check if the "runtime" symlink is already
1566 if (!(p
= pa_readlink(k
))) {
1568 if (errno
!= ENOENT
) {
1569 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1574 /* Hmm, so the runtime directory didn't exist yet, so let's
1575 * create one in /tmp and symlink that to it */
1577 if (make_random_dir_and_link(0700, k
) < 0) {
1579 /* Mhmm, maybe another process was quicker than us,
1580 * let's check if that was valid */
1581 if (errno
== EEXIST
)
1587 /* No symlink possible, so let's just create the runtime directly */
1595 /* Make sure that this actually makes sense */
1596 if (!pa_is_path_absolute(p
)) {
1597 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1602 /* Hmm, so this symlink is still around, make sure nobody fools
1606 if (lstat(p
, &st
) < 0) {
1608 if (errno
!= ENOENT
) {
1609 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1615 if (S_ISDIR(st
.st_mode
) &&
1616 (st
.st_uid
== getuid()) &&
1617 ((st
.st_mode
& 0777) == 0700)) {
1623 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1630 /* Hmm, so the link points to some nonexisting or invalid
1631 * dir. Let's replace it by a new link. We first create a
1632 * temporary link and then rename that to allow concurrent
1633 * execution of this function. */
1635 t
= pa_sprintf_malloc("%s.tmp", k
);
1637 if (make_random_dir_and_link(0700, t
) < 0) {
1639 if (errno
!= EEXIST
) {
1640 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1647 /* Hmm, someone lese was quicker then us. Let's give
1648 * him some time to finish, and retry. */
1653 /* OK, we succeeded in creating the temporary symlink, so
1654 * let's rename it */
1655 if (rename(t
, k
) < 0) {
1656 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1672 /* Try to open a configuration file. If "env" is specified, open the
1673 * value of the specified environment variable. Otherwise look for a
1674 * file "local" in the home directory or a file "global" in global
1675 * file system. If "result" is non-NULL, a pointer to a newly
1676 * allocated buffer containing the used configuration file is
1678 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1683 if (!getenv(PULSE_ROOTENV
))
1687 if (env
&& (fn
= getenv(env
))) {
1691 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1692 /* FIXME: Needs to set errno! */
1697 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1699 *result
= pa_xstrdup(fn
);
1704 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1714 if ((e
= getenv("PULSE_CONFIG_PATH")))
1715 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1716 else if ((h
= pa_get_home_dir_malloc())) {
1717 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1723 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1724 /* FIXME: Needs to set errno! */
1731 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1733 *result
= pa_xstrdup(fn
);
1739 if (errno
!= ENOENT
) {
1740 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1752 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1753 /* FIXME: Needs to set errno! */
1758 if ((f
= pa_fopen_cloexec(global
, "r"))) {
1761 *result
= pa_xstrdup(global
);
1771 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1776 if (!getenv(PULSE_ROOTENV
))
1780 if (env
&& (fn
= getenv(env
))) {
1783 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1784 /* FIXME: Needs to set errno! */
1789 if (access(fn
, R_OK
) == 0)
1790 return pa_xstrdup(fn
);
1792 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1801 if ((e
= getenv("PULSE_CONFIG_PATH")))
1802 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1803 else if ((h
= pa_get_home_dir_malloc())) {
1804 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1810 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1811 /* FIXME: Needs to set errno! */
1818 if (access(fn
, R_OK
) == 0) {
1819 char *r
= pa_xstrdup(fn
);
1824 if (errno
!= ENOENT
) {
1825 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1835 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1836 /* FIXME: Needs to set errno! */
1841 if (access(global
, R_OK
) == 0)
1842 return pa_xstrdup(global
);
1850 /* Format the specified data as a hexademical string */
1851 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1852 size_t i
= 0, j
= 0;
1853 const char hex
[] = "0123456789abcdef";
1857 pa_assert(slength
> 0);
1859 while (i
< dlength
&& j
+3 <= slength
) {
1860 s
[j
++] = hex
[*d
>> 4];
1861 s
[j
++] = hex
[*d
& 0xF];
1867 s
[j
< slength
? j
: slength
] = 0;
1871 /* Convert a hexadecimal digit to a number or -1 if invalid */
1872 static int hexc(char c
) {
1873 if (c
>= '0' && c
<= '9')
1876 if (c
>= 'A' && c
<= 'F')
1877 return c
- 'A' + 10;
1879 if (c
>= 'a' && c
<= 'f')
1880 return c
- 'a' + 10;
1886 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1887 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1893 while (j
< dlength
&& *p
) {
1896 if ((b
= hexc(*(p
++))) < 0)
1899 d
[j
] = (uint8_t) (b
<< 4);
1904 if ((b
= hexc(*(p
++))) < 0)
1907 d
[j
] |= (uint8_t) b
;
1914 /* Returns nonzero when *s starts with *pfx */
1915 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1923 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1926 /* Returns nonzero when *s ends with *sfx */
1927 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1936 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1939 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1945 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1949 char *pa_make_path_absolute(const char *p
) {
1955 if (pa_is_path_absolute(p
))
1956 return pa_xstrdup(p
);
1958 if (!(cwd
= pa_getcwd()))
1959 return pa_xstrdup(p
);
1961 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1966 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1967 * if fn is non-null and starts with / return fn
1968 * otherwise append fn to the run time path and return it */
1969 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1972 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1977 if (pa_is_path_absolute(fn
))
1978 return pa_xstrdup(fn
);
1986 if (!(mid
= pa_machine_id())) {
1991 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1994 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
2002 char *pa_runtime_path(const char *fn
) {
2003 return get_path(fn
, FALSE
, TRUE
);
2006 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2007 return get_path(fn
, appendmid
, FALSE
);
2010 /* Convert the string s to a signed integer in *ret_i */
2011 int pa_atoi(const char *s
, int32_t *ret_i
) {
2019 l
= strtol(s
, &x
, 0);
2021 if (!x
|| *x
|| errno
) {
2027 if ((int32_t) l
!= l
) {
2032 *ret_i
= (int32_t) l
;
2037 /* Convert the string s to an unsigned integer in *ret_u */
2038 int pa_atou(const char *s
, uint32_t *ret_u
) {
2046 l
= strtoul(s
, &x
, 0);
2048 if (!x
|| *x
|| errno
) {
2054 if ((uint32_t) l
!= l
) {
2059 *ret_u
= (uint32_t) l
;
2064 #ifdef HAVE_STRTOF_L
2065 static locale_t c_locale
= NULL
;
2067 static void c_locale_destroy(void) {
2068 freelocale(c_locale
);
2072 int pa_atod(const char *s
, double *ret_d
) {
2079 /* This should be locale independent */
2081 #ifdef HAVE_STRTOF_L
2085 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2086 atexit(c_locale_destroy
);
2092 f
= strtod_l(s
, &x
, c_locale
);
2100 if (!x
|| *x
|| errno
) {
2111 /* Same as snprintf, but guarantees NUL-termination on every platform */
2112 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2117 pa_assert(size
> 0);
2120 va_start(ap
, format
);
2121 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2127 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2128 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2132 pa_assert(size
> 0);
2135 ret
= vsnprintf(str
, size
, format
, ap
);
2142 if ((size_t) ret
> size
-1)
2145 return (size_t) ret
;
2148 /* Truncate the specified string, but guarantee that the string
2149 * returned still validates as UTF8 */
2150 char *pa_truncate_utf8(char *c
, size_t l
) {
2152 pa_assert(pa_utf8_valid(c
));
2159 while (l
> 0 && !pa_utf8_valid(c
))
2165 char *pa_getcwd(void) {
2169 char *p
= pa_xmalloc(l
);
2173 if (errno
!= ERANGE
)
2181 void *pa_will_need(const void *p
, size_t l
) {
2182 #ifdef RLIMIT_MEMLOCK
2193 a
= PA_PAGE_ALIGN_PTR(p
);
2194 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2196 #ifdef HAVE_POSIX_MADVISE
2197 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2198 pa_log_debug("posix_madvise() worked fine!");
2203 /* Most likely the memory was not mmap()ed from a file and thus
2204 * madvise() didn't work, so let's misuse mlock() do page this
2205 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2206 * inviting, the man page of mlock() tells us: "All pages that
2207 * contain a part of the specified address range are guaranteed to
2208 * be resident in RAM when the call returns successfully." */
2210 #ifdef RLIMIT_MEMLOCK
2211 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2213 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2214 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
));
2219 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2221 bs
= PA_PAGE_SIZE
*4;
2224 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2227 while (size
> 0 && bs
> 0) {
2232 if (mlock(a
, bs
) < 0) {
2233 bs
= PA_PAGE_ALIGN(bs
/ 2);
2237 pa_assert_se(munlock(a
, bs
) == 0);
2239 a
= (const uint8_t*) a
+ bs
;
2245 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2247 pa_log_debug("mlock() worked fine!");
2252 void pa_close_pipe(int fds
[2]) {
2256 pa_assert_se(pa_close(fds
[0]) == 0);
2259 pa_assert_se(pa_close(fds
[1]) == 0);
2261 fds
[0] = fds
[1] = -1;
2264 char *pa_readlink(const char *p
) {
2265 #ifdef HAVE_READLINK
2274 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2279 if ((size_t) n
< l
-1) {
2292 int pa_close_all(int except_fd
, ...) {
2297 va_start(ap
, except_fd
);
2300 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2305 p
= pa_xnew(int, n
+1);
2307 va_start(ap
, except_fd
);
2310 if (except_fd
>= 0) {
2314 while ((fd
= va_arg(ap
, int)) >= 0)
2321 r
= pa_close_allv(p
);
2327 int pa_close_allv(const int except_fds
[]) {
2336 if ((d
= opendir("/proc/self/fd"))) {
2340 while ((de
= readdir(d
))) {
2346 if (de
->d_name
[0] == '.')
2350 l
= strtol(de
->d_name
, &e
, 10);
2351 if (errno
!= 0 || !e
|| *e
) {
2359 if ((long) fd
!= l
) {
2372 for (i
= 0; except_fds
[i
] >= 0; i
++)
2373 if (except_fds
[i
] == fd
) {
2381 if (pa_close(fd
) < 0) {
2382 saved_errno
= errno
;
2384 errno
= saved_errno
;
2396 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2397 maxfd
= (int) rl
.rlim_max
;
2399 maxfd
= sysconf(_SC_OPEN_MAX
);
2401 for (fd
= 3; fd
< maxfd
; fd
++) {
2406 for (i
= 0; except_fds
[i
] >= 0; i
++)
2407 if (except_fds
[i
] == fd
) {
2415 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2418 #endif /* !OS_IS_WIN32 */
2423 int pa_unblock_sigs(int except
, ...) {
2428 va_start(ap
, except
);
2431 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2436 p
= pa_xnew(int, n
+1);
2438 va_start(ap
, except
);
2445 while ((sig
= va_arg(ap
, int)) >= 0)
2452 r
= pa_unblock_sigsv(p
);
2458 int pa_unblock_sigsv(const int except
[]) {
2463 if (sigemptyset(&ss
) < 0)
2466 for (i
= 0; except
[i
] > 0; i
++)
2467 if (sigaddset(&ss
, except
[i
]) < 0)
2470 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2476 int pa_reset_sigs(int except
, ...) {
2481 va_start(ap
, except
);
2484 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2489 p
= pa_xnew(int, n
+1);
2491 va_start(ap
, except
);
2498 while ((sig
= va_arg(ap
, int)) >= 0)
2505 r
= pa_reset_sigsv(p
);
2511 int pa_reset_sigsv(const int except
[]) {
2515 for (sig
= 1; sig
< NSIG
; sig
++) {
2516 pa_bool_t reset
= TRUE
;
2527 for (i
= 0; except
[i
] > 0; i
++) {
2528 if (sig
== except
[i
]) {
2537 struct sigaction sa
;
2539 memset(&sa
, 0, sizeof(sa
));
2540 sa
.sa_handler
= SIG_DFL
;
2542 /* On Linux the first two RT signals are reserved by
2543 * glibc, and sigaction() will return EINVAL for them. */
2544 if ((sigaction(sig
, &sa
, NULL
) < 0))
2545 if (errno
!= EINVAL
)
2554 void pa_set_env(const char *key
, const char *value
) {
2558 /* This is not thread-safe */
2561 SetEnvironmentVariable(key
, value
);
2563 setenv(key
, value
, 1);
2567 void pa_set_env_and_record(const char *key
, const char *value
) {
2571 /* This is not thread-safe */
2573 pa_set_env(key
, value
);
2574 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2577 void pa_unset_env_recorded(void) {
2579 /* This is not thread-safe */
2584 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2590 SetEnvironmentVariable(s
, NULL
);
2598 pa_bool_t
pa_in_system_mode(void) {
2601 if (!(e
= getenv("PULSE_SYSTEM")))
2607 char *pa_get_user_name_malloc(void) {
2611 #ifdef _SC_LOGIN_NAME_MAX
2612 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2618 u
= pa_xnew(char, k
+1);
2620 if (!(pa_get_user_name(u
, k
))) {
2628 char *pa_get_host_name_malloc(void) {
2637 if (!pa_get_host_name(c
, l
)) {
2639 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2642 } else if (strlen(c
) < l
-1) {
2650 u
= pa_utf8_filter(c
);
2655 /* Hmm, the hostname is as long the space we offered the
2656 * function, we cannot know if it fully fit in, so let's play
2657 * safe and retry. */
2666 char *pa_machine_id(void) {
2670 /* The returned value is supposed be some kind of ascii identifier
2671 * that is unique and stable across reboots. */
2673 /* First we try the D-Bus UUID, which is the best option we have,
2674 * since it fits perfectly our needs and is not as volatile as the
2675 * hostname which might be set from dhcp. */
2677 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2678 char ln
[34] = "", *r
;
2680 r
= fgets(ln
, sizeof(ln
)-1, f
);
2686 return pa_utf8_filter(ln
);
2689 if ((h
= pa_get_host_name_malloc()))
2693 /* If no hostname was set we use the POSIX hostid. It's usually
2694 * the IPv4 address. Might not be that stable. */
2695 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2701 char *pa_session_id(void) {
2704 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2707 return pa_utf8_filter(e
);
2710 char *pa_uname_string(void) {
2714 pa_assert_se(uname(&u
) >= 0);
2716 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2722 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2723 pa_assert_se(GetVersionEx(&i
));
2725 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2729 #ifdef HAVE_VALGRIND_MEMCHECK_H
2730 pa_bool_t
pa_in_valgrind(void) {
2733 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2734 * here instead of really checking whether we run in valgrind or
2738 b
= getenv("VALGRIND") ? 2 : 1;
2744 unsigned pa_gcd(unsigned a
, unsigned b
) {
2755 void pa_reduce(unsigned *num
, unsigned *den
) {
2757 unsigned gcd
= pa_gcd(*num
, *den
);
2765 pa_assert(pa_gcd(*num
, *den
) == 1);
2768 unsigned pa_ncpus(void) {
2771 #ifdef _SC_NPROCESSORS_CONF
2772 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2777 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2780 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2789 sb
= pa_strbuf_new();
2794 if (!(p
= strstr(s
, a
)))
2797 pa_strbuf_putsn(sb
, s
, p
-s
);
2798 pa_strbuf_puts(sb
, b
);
2802 pa_strbuf_puts(sb
, s
);
2804 return pa_strbuf_tostring_free(sb
);
2807 char *pa_escape(const char *p
, const char *chars
) {
2810 pa_strbuf
*buf
= pa_strbuf_new();
2812 for (s
= p
; *s
; ++s
) {
2814 pa_strbuf_putc(buf
, '\\');
2816 for (c
= chars
; *c
; ++c
) {
2818 pa_strbuf_putc(buf
, '\\');
2823 pa_strbuf_putc(buf
, *s
);
2826 return pa_strbuf_tostring_free(buf
);
2829 char *pa_unescape(char *p
) {
2831 pa_bool_t escaped
= FALSE
;
2833 for (s
= p
, d
= p
; *s
; s
++) {
2834 if (!escaped
&& *s
== '\\') {
2848 char *pa_realpath(const char *path
) {
2852 /* We want only abolsute paths */
2853 if (path
[0] != '/') {
2858 #if defined(__GLIBC__) || defined(__APPLE__)
2862 if (!(r
= realpath(path
, NULL
)))
2865 /* We copy this here in case our pa_xmalloc() is not
2866 * implemented on top of libc malloc() */
2870 #elif defined(PATH_MAX)
2873 path_buf
= pa_xmalloc(PATH_MAX
);
2875 #if defined(OS_IS_WIN32)
2876 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2881 if (!(t
= realpath(path
, path_buf
))) {
2888 #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."
2894 void pa_disable_sigpipe(void) {
2897 struct sigaction sa
;
2901 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2902 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2906 sa
.sa_handler
= SIG_IGN
;
2908 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2909 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2915 void pa_xfreev(void**a
) {
2921 for (p
= a
; *p
; p
++)
2927 char **pa_split_spaces_strv(const char *s
) {
2929 unsigned i
= 0, n
= 8;
2930 const char *state
= NULL
;
2932 t
= pa_xnew(char*, n
);
2933 while ((e
= pa_split_spaces(s
, &state
))) {
2938 t
= pa_xrenew(char*, t
, n
);
2951 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2954 if (pa_is_path_absolute(path
))
2955 return pa_xstrdup(path
);
2957 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2960 size_t pa_pipe_buf(int fd
) {
2965 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2976 void pa_reset_personality(void) {
2979 if (personality(PER_LINUX
) < 0)
2980 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2985 #if defined(__linux__) && !defined(__OPTIMIZE__)
2987 pa_bool_t
pa_run_from_build_tree(void) {
2989 pa_bool_t b
= FALSE
;
2991 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2994 if ((rp
= pa_readlink("/proc/self/exe"))) {
2995 b
= pa_startswith(rp
, PA_BUILDDIR
);
3004 const char *pa_get_temp_dir(void) {
3007 if ((t
= getenv("TMPDIR")) &&
3008 pa_is_path_absolute(t
))
3011 if ((t
= getenv("TMP")) &&
3012 pa_is_path_absolute(t
))
3015 if ((t
= getenv("TEMP")) &&
3016 pa_is_path_absolute(t
))
3019 if ((t
= getenv("TEMPDIR")) &&
3020 pa_is_path_absolute(t
))
3026 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3034 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3037 if (errno
!= EINVAL
)
3041 if ((fd
= open(fn
, flags
, mode
)) < 0)
3045 /* Some implementations might simply ignore O_CLOEXEC if it is not
3046 * understood, make sure FD_CLOEXEC is enabled anyway */
3048 pa_make_fd_cloexec(fd
);
3052 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3056 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3059 if (errno
!= EINVAL
)
3063 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3067 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3068 * not understood, make sure FD_CLOEXEC is enabled anyway */
3070 pa_make_fd_cloexec(fd
);
3074 int pa_pipe_cloexec(int pipefd
[2]) {
3078 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3081 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3086 if ((r
= pipe(pipefd
)) < 0)
3090 pa_make_fd_cloexec(pipefd
[0]);
3091 pa_make_fd_cloexec(pipefd
[1]);
3096 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3100 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3103 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3108 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3112 pa_make_fd_cloexec(fd
);
3116 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3120 m
= pa_sprintf_malloc("%se", mode
);
3123 if ((f
= fopen(path
, m
))) {
3130 if (errno
!= EINVAL
)
3133 if (!(f
= fopen(path
, mode
)))
3137 pa_make_fd_cloexec(fileno(f
));
3141 void pa_nullify_stdfds(void) {
3144 pa_close(STDIN_FILENO
);
3145 pa_close(STDOUT_FILENO
);
3146 pa_close(STDERR_FILENO
);
3148 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3149 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3150 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3157 char *pa_read_line_from_file(const char *fn
) {
3159 char ln
[256] = "", *r
;
3161 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3164 r
= fgets(ln
, sizeof(ln
)-1, f
);
3173 return pa_xstrdup(ln
);
3176 pa_bool_t
pa_running_in_vm(void) {
3178 #if defined(__i386__) || defined(__x86_64__)
3180 /* Both CPUID and DMI are x86 specific interfaces... */
3182 uint32_t eax
= 0x40000000;
3189 const char *const dmi_vendors
[] = {
3190 "/sys/class/dmi/id/sys_vendor",
3191 "/sys/class/dmi/id/board_vendor",
3192 "/sys/class/dmi/id/bios_vendor"
3197 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3200 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3202 if (pa_startswith(s
, "QEMU") ||
3203 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3204 pa_startswith(s
, "VMware") ||
3205 pa_startswith(s
, "VMW") ||
3206 pa_startswith(s
, "Microsoft Corporation") ||
3207 pa_startswith(s
, "innotek GmbH") ||
3208 pa_startswith(s
, "Xen")) {
3220 /* http://lwn.net/Articles/301888/ */
3223 __asm__
__volatile__ (
3224 /* ebx/rbx is being used for PIC! */
3225 " push %%"PA_REG_b
" \n\t"
3227 " mov %%ebx, %1 \n\t"
3228 " pop %%"PA_REG_b
" \n\t"
3230 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3234 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3235 pa_streq(sig
.text
, "KVMKVMKVM") ||
3236 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3237 pa_streq(sig
.text
, "VMwareVMware") ||
3238 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3239 pa_streq(sig
.text
, "Microsoft Hv"))