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>
117 #include <sys/personality.h>
120 #include <pulse/xmalloc.h>
121 #include <pulse/util.h>
122 #include <pulse/utf8.h>
124 #include <pulsecore/core-error.h>
125 #include <pulsecore/socket.h>
126 #include <pulsecore/log.h>
127 #include <pulsecore/macro.h>
128 #include <pulsecore/thread.h>
129 #include <pulsecore/strbuf.h>
130 #include <pulsecore/usergroup.h>
131 #include <pulsecore/strlist.h>
132 #include <pulsecore/cpu-x86.h>
133 #include <pulsecore/pipe.h>
135 #include "core-util.h"
137 /* Not all platforms have this */
139 #define MSG_NOSIGNAL 0
142 #define NEWLINE "\r\n"
143 #define WHITESPACE "\n\r \t"
145 static pa_strlist
*recorded_env
= NULL
;
149 #define PULSE_ROOTENV "PULSE_ROOT"
151 int pa_set_root(HANDLE handle
) {
152 char library_path
[MAX_PATH
], *sep
;
154 /* FIXME: Needs to set errno */
156 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
159 sep
= strrchr(library_path
, PA_PATH_SEP_CHAR
);
163 if (!SetEnvironmentVariable(PULSE_ROOTENV
, library_path
))
171 /** Make a file descriptor nonblock. Doesn't do any error checking */
172 void pa_make_fd_nonblock(int fd
) {
178 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
180 if (!(v
& O_NONBLOCK
))
181 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
183 #elif defined(OS_IS_WIN32)
185 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
186 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
187 pa_log_warn("Only sockets can be made non-blocking!");
190 pa_log_warn("Non-blocking I/O not supported.!");
195 /* Set the FD_CLOEXEC flag for a fd */
196 void pa_make_fd_cloexec(int fd
) {
202 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
204 if (!(v
& FD_CLOEXEC
))
205 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
210 /** Creates a directory securely */
211 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
213 int r
, saved_errno
, fd
;
222 u
= umask((~m
) & 0777);
228 if (r
< 0 && errno
!= EEXIST
)
231 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
245 if (fstat(fd
, &st
) < 0) {
246 pa_assert_se(pa_close(fd
) >= 0);
250 if (!S_ISDIR(st
.st_mode
)) {
251 pa_assert_se(pa_close(fd
) >= 0);
257 if (uid
== (uid_t
)-1)
259 if (gid
== (gid_t
)-1)
261 (void) fchown(fd
, uid
, gid
);
265 (void) fchmod(fd
, m
);
268 pa_assert_se(pa_close(fd
) >= 0);
272 if (lstat(dir
, &st
) < 0)
274 if (stat(dir
, &st
) < 0)
279 if (!S_ISDIR(st
.st_mode
) ||
280 (st
.st_uid
!= uid
) ||
281 (st
.st_gid
!= gid
) ||
282 ((st
.st_mode
& 0777) != m
)) {
287 pa_log_warn("Secure directory creation not supported on Win32.");
300 /* Return a newly allocated sting containing the parent directory of the specified file */
301 char *pa_parent_dir(const char *fn
) {
302 char *slash
, *dir
= pa_xstrdup(fn
);
304 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
314 /* Creates a the parent directory of the specified path securely */
315 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
319 if (!(dir
= pa_parent_dir(fn
)))
322 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
332 /** Platform independent read function. Necessary since not all
333 * systems treat all file descriptors equal. If type is
334 * non-NULL it is used to cache the type of the fd. This is
335 * useful for making sure that only a single syscall is executed per
336 * function call. The variable pointed to should be initialized to 0
338 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
342 if (!type
|| *type
== 0) {
345 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
348 if (WSAGetLastError() != WSAENOTSOCK
) {
349 errno
= WSAGetLastError();
362 if ((r
= read(fd
, buf
, count
)) < 0)
370 /** Similar to pa_read(), but handles writes */
371 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
373 if (!type
|| *type
== 0) {
377 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
389 if (WSAGetLastError() != WSAENOTSOCK
) {
390 errno
= WSAGetLastError();
394 if (errno
!= ENOTSOCK
)
405 if ((r
= write(fd
, buf
, count
)) < 0)
413 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
414 * unless EOF is reached or an error occurred */
415 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
431 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
438 data
= (uint8_t*) data
+ r
;
445 /** Similar to pa_loop_read(), but wraps write() */
446 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
462 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
469 data
= (const uint8_t*) data
+ r
;
476 /** Platform independent read function. Necessary since not all
477 * systems treat all file descriptors equal. */
478 int pa_close(int fd
) {
483 if ((ret
= closesocket(fd
)) == 0)
486 if (WSAGetLastError() != WSAENOTSOCK
) {
487 errno
= WSAGetLastError();
495 if ((r
= close(fd
)) < 0)
503 /* Print a warning messages in case that the given signal is not
504 * blocked or trapped */
505 void pa_check_signal_is_blocked(int sig
) {
506 #ifdef HAVE_SIGACTION
510 /* If POSIX threads are supported use thread-aware
511 * pthread_sigmask() function, to check if the signal is
512 * blocked. Otherwise fall back to sigprocmask() */
515 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
517 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
518 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
525 if (sigismember(&set
, sig
))
528 /* Check whether the signal is trapped */
530 if (sigaction(sig
, NULL
, &sa
) < 0) {
531 pa_log("sigaction(): %s", pa_cstrerror(errno
));
535 if (sa
.sa_handler
!= SIG_DFL
)
538 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
539 #else /* HAVE_SIGACTION */
540 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
544 /* The following function is based on an example from the GNU libc
545 * documentation. This function is similar to GNU's asprintf(). */
546 char *pa_sprintf_malloc(const char *format
, ...) {
556 c
= pa_xrealloc(c
, size
);
558 va_start(ap
, format
);
559 r
= vsnprintf(c
, size
, format
, ap
);
564 if (r
> -1 && (size_t) r
< size
)
567 if (r
> -1) /* glibc 2.1 */
574 /* Same as the previous function, but use a va_list instead of an
576 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
586 c
= pa_xrealloc(c
, size
);
589 r
= vsnprintf(c
, size
, format
, aq
);
594 if (r
> -1 && (size_t) r
< size
)
597 if (r
> -1) /* glibc 2.1 */
604 /* Similar to OpenBSD's strlcpy() function */
605 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
623 static int set_scheduler(int rtprio
) {
625 struct sched_param sp
;
631 dbus_error_init(&error
);
635 sp
.sched_priority
= rtprio
;
637 #ifdef SCHED_RESET_ON_FORK
638 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
639 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
644 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
645 pa_log_debug("SCHED_RR worked.");
648 #endif /* HAVE_SCHED_H */
651 /* Try to talk to RealtimeKit */
653 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
654 pa_log("Failed to connect to system bus: %s\n", error
.message
);
655 dbus_error_free(&error
);
660 /* We need to disable exit on disconnect because otherwise
661 * dbus_shutdown will kill us. See
662 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
663 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
665 r
= rtkit_make_realtime(bus
, 0, rtprio
);
666 dbus_connection_unref(bus
);
669 pa_log_debug("RealtimeKit worked.");
681 /* Make the current thread a realtime thread, and acquire the highest
682 * rtprio we can get that is less or equal the specified parameter. If
683 * the thread is already realtime, don't do anything. */
684 int pa_make_realtime(int rtprio
) {
686 #ifdef _POSIX_PRIORITY_SCHEDULING
689 if (set_scheduler(rtprio
) >= 0) {
690 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
694 for (p
= rtprio
-1; p
>= 1; p
--)
695 if (set_scheduler(p
) >= 0) {
696 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
699 #elif defined(OS_IS_WIN32)
700 /* Windows only allows realtime scheduling to be set on a per process basis.
701 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
702 if(SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
703 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
707 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
712 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
716 static int set_nice(int nice_level
) {
722 dbus_error_init(&error
);
725 #ifdef HAVE_SYS_RESOURCE_H
726 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
727 pa_log_debug("setpriority() worked.");
733 /* Try to talk to RealtimeKit */
735 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
736 pa_log("Failed to connect to system bus: %s\n", error
.message
);
737 dbus_error_free(&error
);
742 /* We need to disable exit on disconnect because otherwise
743 * dbus_shutdown will kill us. See
744 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
745 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
747 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
748 dbus_connection_unref(bus
);
751 pa_log_debug("RealtimeKit worked.");
761 /* Raise the priority of the current process as much as possible that
762 * is <= the specified nice level..*/
763 int pa_raise_priority(int nice_level
) {
765 #ifdef HAVE_SYS_RESOURCE_H
768 if (set_nice(nice_level
) >= 0) {
769 pa_log_info("Successfully gained nice level %i.", nice_level
);
773 for (n
= nice_level
+1; n
< 0; n
++)
774 if (set_nice(n
) >= 0) {
775 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
779 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
784 if (nice_level
< 0) {
785 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
786 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
791 pa_log_info("Successfully gained high priority class.");
798 /* Reset the priority to normal, inverting the changes made by
799 * pa_raise_priority() and pa_make_realtime()*/
800 void pa_reset_priority(void) {
801 #ifdef HAVE_SYS_RESOURCE_H
802 struct sched_param sp
;
804 setpriority(PRIO_PROCESS
, 0, 0);
807 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
811 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
815 int pa_match(const char *expr
, const char *v
) {
820 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
825 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
827 else if (k
== REG_NOMATCH
)
840 /* Try to parse a boolean string value.*/
841 int pa_parse_boolean(const char *v
) {
845 /* First we check language independant */
846 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
848 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
851 #ifdef HAVE_LANGINFO_H
852 /* And then we check language dependant */
853 if ((expr
= nl_langinfo(YESEXPR
)))
855 if (pa_match(expr
, v
) > 0)
858 if ((expr
= nl_langinfo(NOEXPR
)))
860 if (pa_match(expr
, v
) > 0)
868 /* Split the specified string wherever one of the strings in delimiter
869 * occurs. Each time it is called returns a newly allocated string
870 * with pa_xmalloc(). The variable state points to, should be
871 * initiallized to NULL before the first call. */
872 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
873 const char *current
= *state
? *state
: c
;
879 l
= strcspn(current
, delimiter
);
885 return pa_xstrndup(current
, l
);
888 /* Split a string into words. Otherwise similar to pa_split(). */
889 char *pa_split_spaces(const char *c
, const char **state
) {
890 const char *current
= *state
? *state
: c
;
893 if (!*current
|| *c
== 0)
896 current
+= strspn(current
, WHITESPACE
);
897 l
= strcspn(current
, WHITESPACE
);
901 return pa_xstrndup(current
, l
);
904 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
906 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
907 const char *pa_sig2str(int sig
) {
920 char buf
[SIG2STR_MAX
];
922 if (sig2str(sig
, buf
) == 0) {
923 pa_xfree(PA_STATIC_TLS_GET(signame
));
924 t
= pa_sprintf_malloc("SIG%s", buf
);
925 PA_STATIC_TLS_SET(signame
, t
);
933 case SIGHUP
: return "SIGHUP";
935 case SIGINT
: return "SIGINT";
937 case SIGQUIT
: return "SIGQUIT";
939 case SIGILL
: return "SIGULL";
941 case SIGTRAP
: return "SIGTRAP";
943 case SIGABRT
: return "SIGABRT";
945 case SIGBUS
: return "SIGBUS";
947 case SIGFPE
: return "SIGFPE";
949 case SIGKILL
: return "SIGKILL";
952 case SIGUSR1
: return "SIGUSR1";
954 case SIGSEGV
: return "SIGSEGV";
956 case SIGUSR2
: return "SIGUSR2";
959 case SIGPIPE
: return "SIGPIPE";
962 case SIGALRM
: return "SIGALRM";
964 case SIGTERM
: return "SIGTERM";
966 case SIGSTKFLT
: return "SIGSTKFLT";
969 case SIGCHLD
: return "SIGCHLD";
972 case SIGCONT
: return "SIGCONT";
975 case SIGSTOP
: return "SIGSTOP";
978 case SIGTSTP
: return "SIGTSTP";
981 case SIGTTIN
: return "SIGTTIN";
984 case SIGTTOU
: return "SIGTTOU";
987 case SIGURG
: return "SIGURG";
990 case SIGXCPU
: return "SIGXCPU";
993 case SIGXFSZ
: return "SIGXFSZ";
996 case SIGVTALRM
: return "SIGVTALRM";
999 case SIGPROF
: return "SIGPROF";
1002 case SIGWINCH
: return "SIGWINCH";
1005 case SIGIO
: return "SIGIO";
1008 case SIGPWR
: return "SIGPWR";
1011 case SIGSYS
: return "SIGSYS";
1016 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1017 pa_xfree(PA_STATIC_TLS_GET(signame
));
1018 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1019 PA_STATIC_TLS_SET(signame
, t
);
1028 pa_xfree(PA_STATIC_TLS_GET(signame
));
1029 t
= pa_sprintf_malloc("SIG%i", sig
);
1030 PA_STATIC_TLS_SET(signame
, t
);
1036 /* Check whether the specified GID and the group name match */
1037 static int is_group(gid_t gid
, const char *name
) {
1038 struct group
*group
= NULL
;
1042 if (!(group
= pa_getgrgid_malloc(gid
)))
1047 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1052 r
= strcmp(name
, group
->gr_name
) == 0;
1055 pa_getgrgid_free(group
);
1060 /* Check the current user is member of the specified group */
1061 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1062 GETGROUPS_T
*gids
, tgid
;
1063 long n
= sysconf(_SC_NGROUPS_MAX
);
1068 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1070 if ((n
= getgroups((int) n
, gids
)) < 0) {
1071 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1075 for (i
= 0; i
< n
; i
++) {
1077 if ((k
= is_group(gids
[i
], name
)) < 0)
1086 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1102 /* Check whether the specifc user id is a member of the specified group */
1103 int pa_uid_in_group(uid_t uid
, const char *name
) {
1104 struct group
*group
= NULL
;
1109 if (!(group
= pa_getgrnam_malloc(name
)))
1117 for (i
= group
->gr_mem
; *i
; i
++) {
1118 struct passwd
*pw
= NULL
;
1121 if (!(pw
= pa_getpwnam_malloc(*i
)))
1124 if (pw
->pw_uid
== uid
)
1127 pa_getpwnam_free(pw
);
1134 pa_getgrnam_free(group
);
1139 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1140 gid_t
pa_get_gid_of_group(const char *name
) {
1141 gid_t ret
= (gid_t
) -1;
1142 struct group
*gr
= NULL
;
1145 if (!(gr
= pa_getgrnam_malloc(name
)))
1155 pa_getgrnam_free(gr
);
1159 int pa_check_in_group(gid_t g
) {
1160 gid_t gids
[NGROUPS_MAX
];
1163 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1173 #else /* HAVE_GRP_H */
1175 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1181 int pa_uid_in_group(uid_t uid
, const char *name
) {
1186 gid_t
pa_get_gid_of_group(const char *name
) {
1191 int pa_check_in_group(gid_t g
) {
1198 /* Lock or unlock a file entirely.
1199 (advisory on UNIX, mandatory on Windows) */
1200 int pa_lock_fd(int fd
, int b
) {
1202 struct flock f_lock
;
1204 /* Try a R/W lock first */
1206 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1207 f_lock
.l_whence
= SEEK_SET
;
1211 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1214 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1215 if (b
&& errno
== EBADF
) {
1216 f_lock
.l_type
= F_RDLCK
;
1217 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1221 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1225 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
1227 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1229 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1232 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1234 /* FIXME: Needs to set errno! */
1240 /* Remove trailing newlines from a string */
1241 char* pa_strip_nl(char *s
) {
1244 s
[strcspn(s
, NEWLINE
)] = 0;
1248 char *pa_strip(char *s
) {
1251 /* Drops trailing whitespace. Modifies the string in
1252 * place. Returns pointer to first non-space character */
1254 s
+= strspn(s
, WHITESPACE
);
1256 for (e
= s
; *e
; e
++)
1257 if (!strchr(WHITESPACE
, *e
))
1268 /* Create a temporary lock file and lock it. */
1269 int pa_lock_lockfile(const char *fn
) {
1276 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1280 , S_IRUSR
|S_IWUSR
)) < 0) {
1281 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1285 if (pa_lock_fd(fd
, 1) < 0) {
1286 pa_log_warn("Failed to lock file '%s'.", fn
);
1290 if (fstat(fd
, &st
) < 0) {
1291 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1295 /* Check whether the file has been removed meanwhile. When yes,
1296 * restart this loop, otherwise, we're done */
1297 if (st
.st_nlink
>= 1)
1300 if (pa_lock_fd(fd
, 0) < 0) {
1301 pa_log_warn("Failed to unlock file '%s'.", fn
);
1305 if (pa_close(fd
) < 0) {
1306 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1317 int saved_errno
= errno
;
1319 errno
= saved_errno
;
1325 /* Unlock a temporary lcok file */
1326 int pa_unlock_lockfile(const char *fn
, int fd
) {
1331 if (unlink(fn
) < 0) {
1332 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1337 if (pa_lock_fd(fd
, 0) < 0) {
1338 pa_log_warn("Failed to unlock file '%s'.", fn
);
1342 if (pa_close(fd
) < 0) {
1343 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1350 static char *get_pulse_home(void) {
1355 if (!(h
= pa_get_home_dir_malloc())) {
1356 pa_log_error("Failed to get home directory.");
1360 if (stat(h
, &st
) < 0) {
1361 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1366 if (st
.st_uid
!= getuid()) {
1367 pa_log_error("Home directory %s not ours.", h
);
1373 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1381 char *pa_get_state_dir(void) {
1384 /* The state directory shall contain dynamic data that should be
1385 * kept across reboots, and is private to this user */
1387 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1388 if (!(d
= get_pulse_home()))
1391 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1392 * dir then this will break. */
1394 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1395 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1403 char *pa_get_home_dir_malloc(void) {
1405 size_t allocated
= 128;
1408 homedir
= pa_xmalloc(allocated
);
1410 if (!pa_get_home_dir(homedir
, allocated
)) {
1415 if (strlen(homedir
) < allocated
- 1)
1425 char *pa_get_binary_name_malloc(void) {
1427 size_t allocated
= 128;
1430 t
= pa_xmalloc(allocated
);
1432 if (!pa_get_binary_name(t
, allocated
)) {
1437 if (strlen(t
) < allocated
- 1)
1447 static char* make_random_dir(mode_t m
) {
1448 static const char table
[] =
1449 "abcdefghijklmnopqrstuvwxyz"
1450 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1456 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1457 pathlen
= strlen(fn
);
1465 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1466 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1468 u
= umask((~m
) & 0777);
1475 saved_errno
= errno
;
1477 errno
= saved_errno
;
1482 if (errno
!= EEXIST
) {
1483 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1490 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1493 if (!(p
= make_random_dir(m
)))
1497 if (symlink(p
, k
) < 0) {
1498 int saved_errno
= errno
;
1500 if (errno
!= EEXIST
)
1501 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1506 errno
= saved_errno
;
1518 char *pa_get_runtime_dir(void) {
1519 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1523 /* The runtime directory shall contain dynamic data that needs NOT
1524 * to be kept accross reboots and is usuallly private to the user,
1525 * except in system mode, where it might be accessible by other
1526 * users, too. Since we need POSIX locking and UNIX sockets in
1527 * this directory, we link it to a random subdir in /tmp, if it
1528 * was not explicitly configured. */
1530 m
= pa_in_system_mode() ? 0755U : 0700U;
1532 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1534 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1535 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1539 return pa_xstrdup(d
);
1542 if (!(d
= get_pulse_home()))
1545 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1546 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1551 if (!(mid
= pa_machine_id())) {
1556 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1561 /* OK, first let's check if the "runtime" symlink is already
1564 if (!(p
= pa_readlink(k
))) {
1566 if (errno
!= ENOENT
) {
1567 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1572 /* Hmm, so the runtime directory didn't exist yet, so let's
1573 * create one in /tmp and symlink that to it */
1575 if (make_random_dir_and_link(0700, k
) < 0) {
1577 /* Mhmm, maybe another process was quicker than us,
1578 * let's check if that was valid */
1579 if (errno
== EEXIST
)
1585 /* No symlink possible, so let's just create the runtime directly */
1593 /* Make sure that this actually makes sense */
1594 if (!pa_is_path_absolute(p
)) {
1595 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1600 /* Hmm, so this symlink is still around, make sure nobody fools
1604 if (lstat(p
, &st
) < 0) {
1606 if (errno
!= ENOENT
) {
1607 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1613 if (S_ISDIR(st
.st_mode
) &&
1614 (st
.st_uid
== getuid()) &&
1615 ((st
.st_mode
& 0777) == 0700)) {
1621 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1628 /* Hmm, so the link points to some nonexisting or invalid
1629 * dir. Let's replace it by a new link. We first create a
1630 * temporary link and then rename that to allow concurrent
1631 * execution of this function. */
1633 t
= pa_sprintf_malloc("%s.tmp", k
);
1635 if (make_random_dir_and_link(0700, t
) < 0) {
1637 if (errno
!= EEXIST
) {
1638 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1645 /* Hmm, someone lese was quicker then us. Let's give
1646 * him some time to finish, and retry. */
1651 /* OK, we succeeded in creating the temporary symlink, so
1652 * let's rename it */
1653 if (rename(t
, k
) < 0) {
1654 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1670 /* Try to open a configuration file. If "env" is specified, open the
1671 * value of the specified environment variable. Otherwise look for a
1672 * file "local" in the home directory or a file "global" in global
1673 * file system. If "result" is non-NULL, a pointer to a newly
1674 * allocated buffer containing the used configuration file is
1676 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1681 if (!getenv(PULSE_ROOTENV
))
1685 if (env
&& (fn
= getenv(env
))) {
1689 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1690 /* FIXME: Needs to set errno! */
1695 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1697 *result
= pa_xstrdup(fn
);
1702 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1712 if ((e
= getenv("PULSE_CONFIG_PATH")))
1713 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1714 else if ((h
= pa_get_home_dir_malloc())) {
1715 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1721 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1722 /* FIXME: Needs to set errno! */
1729 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1731 *result
= pa_xstrdup(fn
);
1737 if (errno
!= ENOENT
) {
1738 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1750 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1751 /* FIXME: Needs to set errno! */
1756 if ((f
= pa_fopen_cloexec(global
, "r"))) {
1759 *result
= pa_xstrdup(global
);
1769 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1774 if (!getenv(PULSE_ROOTENV
))
1778 if (env
&& (fn
= getenv(env
))) {
1781 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1782 /* FIXME: Needs to set errno! */
1787 if (access(fn
, R_OK
) == 0)
1788 return pa_xstrdup(fn
);
1790 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1799 if ((e
= getenv("PULSE_CONFIG_PATH")))
1800 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1801 else if ((h
= pa_get_home_dir_malloc())) {
1802 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1808 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1809 /* FIXME: Needs to set errno! */
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
));
1833 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1834 /* FIXME: Needs to set errno! */
1839 if (access(global
, R_OK
) == 0)
1840 return pa_xstrdup(global
);
1848 /* Format the specified data as a hexademical string */
1849 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1850 size_t i
= 0, j
= 0;
1851 const char hex
[] = "0123456789abcdef";
1855 pa_assert(slength
> 0);
1857 while (i
< dlength
&& j
+3 <= slength
) {
1858 s
[j
++] = hex
[*d
>> 4];
1859 s
[j
++] = hex
[*d
& 0xF];
1865 s
[j
< slength
? j
: slength
] = 0;
1869 /* Convert a hexadecimal digit to a number or -1 if invalid */
1870 static int hexc(char c
) {
1871 if (c
>= '0' && c
<= '9')
1874 if (c
>= 'A' && c
<= 'F')
1875 return c
- 'A' + 10;
1877 if (c
>= 'a' && c
<= 'f')
1878 return c
- 'a' + 10;
1884 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1885 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1891 while (j
< dlength
&& *p
) {
1894 if ((b
= hexc(*(p
++))) < 0)
1897 d
[j
] = (uint8_t) (b
<< 4);
1902 if ((b
= hexc(*(p
++))) < 0)
1905 d
[j
] |= (uint8_t) b
;
1912 /* Returns nonzero when *s starts with *pfx */
1913 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1921 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1924 /* Returns nonzero when *s ends with *sfx */
1925 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1934 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1937 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1943 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1947 char *pa_make_path_absolute(const char *p
) {
1953 if (pa_is_path_absolute(p
))
1954 return pa_xstrdup(p
);
1956 if (!(cwd
= pa_getcwd()))
1957 return pa_xstrdup(p
);
1959 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1964 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1965 * if fn is non-null and starts with / return fn
1966 * otherwise append fn to the run time path and return it */
1967 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1970 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1975 if (pa_is_path_absolute(fn
))
1976 return pa_xstrdup(fn
);
1984 if (!(mid
= pa_machine_id())) {
1989 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1992 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
2000 char *pa_runtime_path(const char *fn
) {
2001 return get_path(fn
, FALSE
, TRUE
);
2004 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
2005 return get_path(fn
, appendmid
, FALSE
);
2008 /* Convert the string s to a signed integer in *ret_i */
2009 int pa_atoi(const char *s
, int32_t *ret_i
) {
2017 l
= strtol(s
, &x
, 0);
2019 if (!x
|| *x
|| errno
) {
2025 if ((int32_t) l
!= l
) {
2030 *ret_i
= (int32_t) l
;
2035 /* Convert the string s to an unsigned integer in *ret_u */
2036 int pa_atou(const char *s
, uint32_t *ret_u
) {
2044 l
= strtoul(s
, &x
, 0);
2046 if (!x
|| *x
|| errno
) {
2052 if ((uint32_t) l
!= l
) {
2057 *ret_u
= (uint32_t) l
;
2062 #ifdef HAVE_STRTOF_L
2063 static locale_t c_locale
= NULL
;
2065 static void c_locale_destroy(void) {
2066 freelocale(c_locale
);
2070 int pa_atod(const char *s
, double *ret_d
) {
2077 /* This should be locale independent */
2079 #ifdef HAVE_STRTOF_L
2083 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2084 atexit(c_locale_destroy
);
2090 f
= strtod_l(s
, &x
, c_locale
);
2098 if (!x
|| *x
|| errno
) {
2109 /* Same as snprintf, but guarantees NUL-termination on every platform */
2110 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2115 pa_assert(size
> 0);
2118 va_start(ap
, format
);
2119 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2125 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2126 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2130 pa_assert(size
> 0);
2133 ret
= vsnprintf(str
, size
, format
, ap
);
2140 if ((size_t) ret
> size
-1)
2143 return (size_t) ret
;
2146 /* Truncate the specified string, but guarantee that the string
2147 * returned still validates as UTF8 */
2148 char *pa_truncate_utf8(char *c
, size_t l
) {
2150 pa_assert(pa_utf8_valid(c
));
2157 while (l
> 0 && !pa_utf8_valid(c
))
2163 char *pa_getcwd(void) {
2167 char *p
= pa_xmalloc(l
);
2171 if (errno
!= ERANGE
)
2179 void *pa_will_need(const void *p
, size_t l
) {
2180 #ifdef RLIMIT_MEMLOCK
2191 a
= PA_PAGE_ALIGN_PTR(p
);
2192 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2194 #ifdef HAVE_POSIX_MADVISE
2195 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2196 pa_log_debug("posix_madvise() worked fine!");
2201 /* Most likely the memory was not mmap()ed from a file and thus
2202 * madvise() didn't work, so let's misuse mlock() do page this
2203 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2204 * inviting, the man page of mlock() tells us: "All pages that
2205 * contain a part of the specified address range are guaranteed to
2206 * be resident in RAM when the call returns successfully." */
2208 #ifdef RLIMIT_MEMLOCK
2209 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2211 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2212 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
));
2217 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2219 bs
= PA_PAGE_SIZE
*4;
2222 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2225 while (size
> 0 && bs
> 0) {
2230 if (mlock(a
, bs
) < 0) {
2231 bs
= PA_PAGE_ALIGN(bs
/ 2);
2235 pa_assert_se(munlock(a
, bs
) == 0);
2237 a
= (const uint8_t*) a
+ bs
;
2243 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2245 pa_log_debug("mlock() worked fine!");
2250 void pa_close_pipe(int fds
[2]) {
2254 pa_assert_se(pa_close(fds
[0]) == 0);
2257 pa_assert_se(pa_close(fds
[1]) == 0);
2259 fds
[0] = fds
[1] = -1;
2262 char *pa_readlink(const char *p
) {
2263 #ifdef HAVE_READLINK
2272 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2277 if ((size_t) n
< l
-1) {
2290 int pa_close_all(int except_fd
, ...) {
2295 va_start(ap
, except_fd
);
2298 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2303 p
= pa_xnew(int, n
+1);
2305 va_start(ap
, except_fd
);
2308 if (except_fd
>= 0) {
2312 while ((fd
= va_arg(ap
, int)) >= 0)
2319 r
= pa_close_allv(p
);
2325 int pa_close_allv(const int except_fds
[]) {
2334 if ((d
= opendir("/proc/self/fd"))) {
2338 while ((de
= readdir(d
))) {
2344 if (de
->d_name
[0] == '.')
2348 l
= strtol(de
->d_name
, &e
, 10);
2349 if (errno
!= 0 || !e
|| *e
) {
2357 if ((long) fd
!= l
) {
2370 for (i
= 0; except_fds
[i
] >= 0; i
++)
2371 if (except_fds
[i
] == fd
) {
2379 if (pa_close(fd
) < 0) {
2380 saved_errno
= errno
;
2382 errno
= saved_errno
;
2394 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2395 maxfd
= (int) rl
.rlim_max
;
2397 maxfd
= sysconf(_SC_OPEN_MAX
);
2399 for (fd
= 3; fd
< maxfd
; fd
++) {
2404 for (i
= 0; except_fds
[i
] >= 0; i
++)
2405 if (except_fds
[i
] == fd
) {
2413 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2416 #endif /* !OS_IS_WIN32 */
2421 int pa_unblock_sigs(int except
, ...) {
2426 va_start(ap
, except
);
2429 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2434 p
= pa_xnew(int, n
+1);
2436 va_start(ap
, except
);
2443 while ((sig
= va_arg(ap
, int)) >= 0)
2450 r
= pa_unblock_sigsv(p
);
2456 int pa_unblock_sigsv(const int except
[]) {
2461 if (sigemptyset(&ss
) < 0)
2464 for (i
= 0; except
[i
] > 0; i
++)
2465 if (sigaddset(&ss
, except
[i
]) < 0)
2468 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2474 int pa_reset_sigs(int except
, ...) {
2479 va_start(ap
, except
);
2482 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2487 p
= pa_xnew(int, n
+1);
2489 va_start(ap
, except
);
2496 while ((sig
= va_arg(ap
, int)) >= 0)
2503 r
= pa_reset_sigsv(p
);
2509 int pa_reset_sigsv(const int except
[]) {
2513 for (sig
= 1; sig
< NSIG
; sig
++) {
2514 pa_bool_t reset
= TRUE
;
2525 for (i
= 0; except
[i
] > 0; i
++) {
2526 if (sig
== except
[i
]) {
2535 struct sigaction sa
;
2537 memset(&sa
, 0, sizeof(sa
));
2538 sa
.sa_handler
= SIG_DFL
;
2540 /* On Linux the first two RT signals are reserved by
2541 * glibc, and sigaction() will return EINVAL for them. */
2542 if ((sigaction(sig
, &sa
, NULL
) < 0))
2543 if (errno
!= EINVAL
)
2552 void pa_set_env(const char *key
, const char *value
) {
2556 /* This is not thread-safe */
2559 SetEnvironmentVariable(key
, value
);
2561 setenv(key
, value
, 1);
2565 void pa_set_env_and_record(const char *key
, const char *value
) {
2569 /* This is not thread-safe */
2571 pa_set_env(key
, value
);
2572 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2575 void pa_unset_env_recorded(void) {
2577 /* This is not thread-safe */
2582 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2588 SetEnvironmentVariable(s
, NULL
);
2596 pa_bool_t
pa_in_system_mode(void) {
2599 if (!(e
= getenv("PULSE_SYSTEM")))
2605 char *pa_get_user_name_malloc(void) {
2609 #ifdef _SC_LOGIN_NAME_MAX
2610 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2616 u
= pa_xnew(char, k
+1);
2618 if (!(pa_get_user_name(u
, k
))) {
2626 char *pa_get_host_name_malloc(void) {
2635 if (!pa_get_host_name(c
, l
)) {
2637 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2640 } else if (strlen(c
) < l
-1) {
2648 u
= pa_utf8_filter(c
);
2653 /* Hmm, the hostname is as long the space we offered the
2654 * function, we cannot know if it fully fit in, so let's play
2655 * safe and retry. */
2664 char *pa_machine_id(void) {
2668 /* The returned value is supposed be some kind of ascii identifier
2669 * that is unique and stable across reboots. */
2671 /* First we try the D-Bus UUID, which is the best option we have,
2672 * since it fits perfectly our needs and is not as volatile as the
2673 * hostname which might be set from dhcp. */
2675 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2676 char ln
[34] = "", *r
;
2678 r
= fgets(ln
, sizeof(ln
)-1, f
);
2684 return pa_utf8_filter(ln
);
2687 if ((h
= pa_get_host_name_malloc()))
2691 /* If no hostname was set we use the POSIX hostid. It's usually
2692 * the IPv4 address. Might not be that stable. */
2693 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2699 char *pa_session_id(void) {
2702 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2705 return pa_utf8_filter(e
);
2708 char *pa_uname_string(void) {
2712 pa_assert_se(uname(&u
) >= 0);
2714 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2720 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2721 pa_assert_se(GetVersionEx(&i
));
2723 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2727 #ifdef HAVE_VALGRIND_MEMCHECK_H
2728 pa_bool_t
pa_in_valgrind(void) {
2731 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2732 * here instead of really checking whether we run in valgrind or
2736 b
= getenv("VALGRIND") ? 2 : 1;
2742 unsigned pa_gcd(unsigned a
, unsigned b
) {
2753 void pa_reduce(unsigned *num
, unsigned *den
) {
2755 unsigned gcd
= pa_gcd(*num
, *den
);
2763 pa_assert(pa_gcd(*num
, *den
) == 1);
2766 unsigned pa_ncpus(void) {
2769 #ifdef _SC_NPROCESSORS_CONF
2770 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2775 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2778 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2787 sb
= pa_strbuf_new();
2792 if (!(p
= strstr(s
, a
)))
2795 pa_strbuf_putsn(sb
, s
, p
-s
);
2796 pa_strbuf_puts(sb
, b
);
2800 pa_strbuf_puts(sb
, s
);
2802 return pa_strbuf_tostring_free(sb
);
2805 char *pa_escape(const char *p
, const char *chars
) {
2808 pa_strbuf
*buf
= pa_strbuf_new();
2810 for (s
= p
; *s
; ++s
) {
2812 pa_strbuf_putc(buf
, '\\');
2814 for (c
= chars
; *c
; ++c
) {
2816 pa_strbuf_putc(buf
, '\\');
2821 pa_strbuf_putc(buf
, *s
);
2824 return pa_strbuf_tostring_free(buf
);
2827 char *pa_unescape(char *p
) {
2829 pa_bool_t escaped
= FALSE
;
2831 for (s
= p
, d
= p
; *s
; s
++) {
2832 if (!escaped
&& *s
== '\\') {
2846 char *pa_realpath(const char *path
) {
2850 /* We want only abolsute paths */
2851 if (path
[0] != '/') {
2856 #if defined(__GLIBC__) || defined(__APPLE__)
2860 if (!(r
= realpath(path
, NULL
)))
2863 /* We copy this here in case our pa_xmalloc() is not
2864 * implemented on top of libc malloc() */
2868 #elif defined(PATH_MAX)
2871 path_buf
= pa_xmalloc(PATH_MAX
);
2873 #if defined(OS_IS_WIN32)
2874 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2879 if (!(t
= realpath(path
, path_buf
))) {
2886 #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."
2892 void pa_disable_sigpipe(void) {
2895 struct sigaction sa
;
2899 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2900 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2904 sa
.sa_handler
= SIG_IGN
;
2906 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2907 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2913 void pa_xfreev(void**a
) {
2919 for (p
= a
; *p
; p
++)
2925 char **pa_split_spaces_strv(const char *s
) {
2927 unsigned i
= 0, n
= 8;
2928 const char *state
= NULL
;
2930 t
= pa_xnew(char*, n
);
2931 while ((e
= pa_split_spaces(s
, &state
))) {
2936 t
= pa_xrenew(char*, t
, n
);
2949 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2952 if (pa_is_path_absolute(path
))
2953 return pa_xstrdup(path
);
2955 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2958 size_t pa_pipe_buf(int fd
) {
2963 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2974 void pa_reset_personality(void) {
2977 if (personality(PER_LINUX
) < 0)
2978 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2983 #if defined(__linux__) && !defined(__OPTIMIZE__)
2985 pa_bool_t
pa_run_from_build_tree(void) {
2987 pa_bool_t b
= FALSE
;
2989 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2992 if ((rp
= pa_readlink("/proc/self/exe"))) {
2993 b
= pa_startswith(rp
, PA_BUILDDIR
);
3002 const char *pa_get_temp_dir(void) {
3005 if ((t
= getenv("TMPDIR")) &&
3006 pa_is_path_absolute(t
))
3009 if ((t
= getenv("TMP")) &&
3010 pa_is_path_absolute(t
))
3013 if ((t
= getenv("TEMP")) &&
3014 pa_is_path_absolute(t
))
3017 if ((t
= getenv("TEMPDIR")) &&
3018 pa_is_path_absolute(t
))
3024 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3032 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3035 if (errno
!= EINVAL
)
3039 if ((fd
= open(fn
, flags
, mode
)) < 0)
3043 /* Some implementations might simply ignore O_CLOEXEC if it is not
3044 * understood, make sure FD_CLOEXEC is enabled anyway */
3046 pa_make_fd_cloexec(fd
);
3050 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3054 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3057 if (errno
!= EINVAL
)
3061 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3065 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3066 * not understood, make sure FD_CLOEXEC is enabled anyway */
3068 pa_make_fd_cloexec(fd
);
3072 int pa_pipe_cloexec(int pipefd
[2]) {
3076 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3079 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3084 if ((r
= pipe(pipefd
)) < 0)
3088 pa_make_fd_cloexec(pipefd
[0]);
3089 pa_make_fd_cloexec(pipefd
[1]);
3094 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3098 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3101 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3106 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3110 pa_make_fd_cloexec(fd
);
3114 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3118 m
= pa_sprintf_malloc("%se", mode
);
3121 if ((f
= fopen(path
, m
))) {
3128 if (errno
!= EINVAL
)
3131 if (!(f
= fopen(path
, mode
)))
3135 pa_make_fd_cloexec(fileno(f
));
3139 void pa_nullify_stdfds(void) {
3142 pa_close(STDIN_FILENO
);
3143 pa_close(STDOUT_FILENO
);
3144 pa_close(STDERR_FILENO
);
3146 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3147 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3148 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3155 char *pa_read_line_from_file(const char *fn
) {
3157 char ln
[256] = "", *r
;
3159 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3162 r
= fgets(ln
, sizeof(ln
)-1, f
);
3171 return pa_xstrdup(ln
);
3174 pa_bool_t
pa_running_in_vm(void) {
3176 #if defined(__i386__) || defined(__x86_64__)
3178 /* Both CPUID and DMI are x86 specific interfaces... */
3180 uint32_t eax
= 0x40000000;
3187 const char *const dmi_vendors
[] = {
3188 "/sys/class/dmi/id/sys_vendor",
3189 "/sys/class/dmi/id/board_vendor",
3190 "/sys/class/dmi/id/bios_vendor"
3195 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3198 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3200 if (pa_startswith(s
, "QEMU") ||
3201 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3202 pa_startswith(s
, "VMware") ||
3203 pa_startswith(s
, "VMW") ||
3204 pa_startswith(s
, "Microsoft Corporation") ||
3205 pa_startswith(s
, "innotek GmbH") ||
3206 pa_startswith(s
, "Xen")) {
3218 /* http://lwn.net/Articles/301888/ */
3221 __asm__
__volatile__ (
3222 /* ebx/rbx is being used for PIC! */
3223 " push %%"PA_REG_b
" \n\t"
3225 " mov %%ebx, %1 \n\t"
3226 " pop %%"PA_REG_b
" \n\t"
3228 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3232 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3233 pa_streq(sig
.text
, "KVMKVMKVM") ||
3234 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3235 pa_streq(sig
.text
, "VMwareVMware") ||
3236 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3237 pa_streq(sig
.text
, "Microsoft Hv"))