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 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
150 char *pa_win32_get_toplevel(HANDLE handle
) {
151 static char *toplevel
= NULL
;
154 char library_path
[MAX_PATH
];
157 if (!GetModuleFileName(handle
, library_path
, MAX_PATH
))
160 toplevel
= pa_xstrdup(library_path
);
162 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
166 p
= strrchr(toplevel
, PA_PATH_SEP_CHAR
);
167 if (p
&& (strcmp(p
+ 1, "bin") == 0))
176 /** Make a file descriptor nonblock. Doesn't do any error checking */
177 void pa_make_fd_nonblock(int fd
) {
183 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
185 if (!(v
& O_NONBLOCK
))
186 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
188 #elif defined(OS_IS_WIN32)
190 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
191 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
192 pa_log_warn("Only sockets can be made non-blocking!");
195 pa_log_warn("Non-blocking I/O not supported.!");
200 /* Set the FD_CLOEXEC flag for a fd */
201 void pa_make_fd_cloexec(int fd
) {
207 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
209 if (!(v
& FD_CLOEXEC
))
210 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
215 /** Creates a directory securely */
216 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
218 int r
, saved_errno
, fd
;
227 u
= umask((~m
) & 0777);
233 if (r
< 0 && errno
!= EEXIST
)
236 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
250 if (fstat(fd
, &st
) < 0) {
251 pa_assert_se(pa_close(fd
) >= 0);
255 if (!S_ISDIR(st
.st_mode
)) {
256 pa_assert_se(pa_close(fd
) >= 0);
262 if (uid
== (uid_t
)-1)
264 if (gid
== (gid_t
)-1)
266 (void) fchown(fd
, uid
, gid
);
270 (void) fchmod(fd
, m
);
273 pa_assert_se(pa_close(fd
) >= 0);
277 if (lstat(dir
, &st
) < 0)
279 if (stat(dir
, &st
) < 0)
284 if (!S_ISDIR(st
.st_mode
) ||
285 (st
.st_uid
!= uid
) ||
286 (st
.st_gid
!= gid
) ||
287 ((st
.st_mode
& 0777) != m
)) {
292 pa_log_warn("Secure directory creation not supported on Win32.");
305 /* Return a newly allocated sting containing the parent directory of the specified file */
306 char *pa_parent_dir(const char *fn
) {
307 char *slash
, *dir
= pa_xstrdup(fn
);
309 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
319 /* Creates a the parent directory of the specified path securely */
320 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
324 if (!(dir
= pa_parent_dir(fn
)))
327 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
337 /** Platform independent read function. Necessary since not all
338 * systems treat all file descriptors equal. If type is
339 * non-NULL it is used to cache the type of the fd. This is
340 * useful for making sure that only a single syscall is executed per
341 * function call. The variable pointed to should be initialized to 0
343 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
347 if (!type
|| *type
== 0) {
350 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
353 if (WSAGetLastError() != WSAENOTSOCK
) {
354 errno
= WSAGetLastError();
367 if ((r
= read(fd
, buf
, count
)) < 0)
375 /** Similar to pa_read(), but handles writes */
376 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
378 if (!type
|| *type
== 0) {
382 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
394 if (WSAGetLastError() != WSAENOTSOCK
) {
395 errno
= WSAGetLastError();
399 if (errno
!= ENOTSOCK
)
410 if ((r
= write(fd
, buf
, count
)) < 0)
418 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
419 * unless EOF is reached or an error occurred */
420 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
436 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
443 data
= (uint8_t*) data
+ r
;
450 /** Similar to pa_loop_read(), but wraps write() */
451 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
467 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
474 data
= (const uint8_t*) data
+ r
;
481 /** Platform independent read function. Necessary since not all
482 * systems treat all file descriptors equal. */
483 int pa_close(int fd
) {
488 if ((ret
= closesocket(fd
)) == 0)
491 if (WSAGetLastError() != WSAENOTSOCK
) {
492 errno
= WSAGetLastError();
500 if ((r
= close(fd
)) < 0)
508 /* Print a warning messages in case that the given signal is not
509 * blocked or trapped */
510 void pa_check_signal_is_blocked(int sig
) {
511 #ifdef HAVE_SIGACTION
515 /* If POSIX threads are supported use thread-aware
516 * pthread_sigmask() function, to check if the signal is
517 * blocked. Otherwise fall back to sigprocmask() */
520 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
522 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
523 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
530 if (sigismember(&set
, sig
))
533 /* Check whether the signal is trapped */
535 if (sigaction(sig
, NULL
, &sa
) < 0) {
536 pa_log("sigaction(): %s", pa_cstrerror(errno
));
540 if (sa
.sa_handler
!= SIG_DFL
)
543 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
544 #else /* HAVE_SIGACTION */
545 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
549 /* The following function is based on an example from the GNU libc
550 * documentation. This function is similar to GNU's asprintf(). */
551 char *pa_sprintf_malloc(const char *format
, ...) {
561 c
= pa_xrealloc(c
, size
);
563 va_start(ap
, format
);
564 r
= vsnprintf(c
, size
, format
, ap
);
569 if (r
> -1 && (size_t) r
< size
)
572 if (r
> -1) /* glibc 2.1 */
579 /* Same as the previous function, but use a va_list instead of an
581 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
591 c
= pa_xrealloc(c
, size
);
594 r
= vsnprintf(c
, size
, format
, aq
);
599 if (r
> -1 && (size_t) r
< size
)
602 if (r
> -1) /* glibc 2.1 */
609 /* Similar to OpenBSD's strlcpy() function */
610 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
628 static int set_scheduler(int rtprio
) {
630 struct sched_param sp
;
636 dbus_error_init(&error
);
640 sp
.sched_priority
= rtprio
;
642 #ifdef SCHED_RESET_ON_FORK
643 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
644 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
649 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
650 pa_log_debug("SCHED_RR worked.");
653 #endif /* HAVE_SCHED_H */
656 /* Try to talk to RealtimeKit */
658 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
659 pa_log("Failed to connect to system bus: %s\n", error
.message
);
660 dbus_error_free(&error
);
665 /* We need to disable exit on disconnect because otherwise
666 * dbus_shutdown will kill us. See
667 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
668 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
670 r
= rtkit_make_realtime(bus
, 0, rtprio
);
671 dbus_connection_unref(bus
);
674 pa_log_debug("RealtimeKit worked.");
686 /* Make the current thread a realtime thread, and acquire the highest
687 * rtprio we can get that is less or equal the specified parameter. If
688 * the thread is already realtime, don't do anything. */
689 int pa_make_realtime(int rtprio
) {
691 #ifdef _POSIX_PRIORITY_SCHEDULING
694 if (set_scheduler(rtprio
) >= 0) {
695 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
699 for (p
= rtprio
-1; p
>= 1; p
--)
700 if (set_scheduler(p
) >= 0) {
701 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
704 #elif defined(OS_IS_WIN32)
705 /* Windows only allows realtime scheduling to be set on a per process basis.
706 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
707 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
708 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
712 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
717 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
721 static int set_nice(int nice_level
) {
727 dbus_error_init(&error
);
730 #ifdef HAVE_SYS_RESOURCE_H
731 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
732 pa_log_debug("setpriority() worked.");
738 /* Try to talk to RealtimeKit */
740 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
741 pa_log("Failed to connect to system bus: %s\n", error
.message
);
742 dbus_error_free(&error
);
747 /* We need to disable exit on disconnect because otherwise
748 * dbus_shutdown will kill us. See
749 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
750 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
752 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
753 dbus_connection_unref(bus
);
756 pa_log_debug("RealtimeKit worked.");
766 /* Raise the priority of the current process as much as possible that
767 * is <= the specified nice level..*/
768 int pa_raise_priority(int nice_level
) {
770 #ifdef HAVE_SYS_RESOURCE_H
773 if (set_nice(nice_level
) >= 0) {
774 pa_log_info("Successfully gained nice level %i.", nice_level
);
778 for (n
= nice_level
+1; n
< 0; n
++)
779 if (set_nice(n
) >= 0) {
780 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
784 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
789 if (nice_level
< 0) {
790 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
791 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
796 pa_log_info("Successfully gained high priority class.");
803 /* Reset the priority to normal, inverting the changes made by
804 * pa_raise_priority() and pa_make_realtime()*/
805 void pa_reset_priority(void) {
806 #ifdef HAVE_SYS_RESOURCE_H
807 struct sched_param sp
;
809 setpriority(PRIO_PROCESS
, 0, 0);
812 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
816 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
820 int pa_match(const char *expr
, const char *v
) {
825 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
830 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
832 else if (k
== REG_NOMATCH
)
845 /* Try to parse a boolean string value.*/
846 int pa_parse_boolean(const char *v
) {
850 /* First we check language independant */
851 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
853 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
856 #ifdef HAVE_LANGINFO_H
857 /* And then we check language dependant */
858 if ((expr
= nl_langinfo(YESEXPR
)))
860 if (pa_match(expr
, v
) > 0)
863 if ((expr
= nl_langinfo(NOEXPR
)))
865 if (pa_match(expr
, v
) > 0)
873 /* Split the specified string wherever one of the strings in delimiter
874 * occurs. Each time it is called returns a newly allocated string
875 * with pa_xmalloc(). The variable state points to, should be
876 * initiallized to NULL before the first call. */
877 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
878 const char *current
= *state
? *state
: c
;
884 l
= strcspn(current
, delimiter
);
890 return pa_xstrndup(current
, l
);
893 /* Split a string into words. Otherwise similar to pa_split(). */
894 char *pa_split_spaces(const char *c
, const char **state
) {
895 const char *current
= *state
? *state
: c
;
898 if (!*current
|| *c
== 0)
901 current
+= strspn(current
, WHITESPACE
);
902 l
= strcspn(current
, WHITESPACE
);
906 return pa_xstrndup(current
, l
);
909 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
911 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
912 const char *pa_sig2str(int sig
) {
925 char buf
[SIG2STR_MAX
];
927 if (sig2str(sig
, buf
) == 0) {
928 pa_xfree(PA_STATIC_TLS_GET(signame
));
929 t
= pa_sprintf_malloc("SIG%s", buf
);
930 PA_STATIC_TLS_SET(signame
, t
);
938 case SIGHUP
: return "SIGHUP";
940 case SIGINT
: return "SIGINT";
942 case SIGQUIT
: return "SIGQUIT";
944 case SIGILL
: return "SIGULL";
946 case SIGTRAP
: return "SIGTRAP";
948 case SIGABRT
: return "SIGABRT";
950 case SIGBUS
: return "SIGBUS";
952 case SIGFPE
: return "SIGFPE";
954 case SIGKILL
: return "SIGKILL";
957 case SIGUSR1
: return "SIGUSR1";
959 case SIGSEGV
: return "SIGSEGV";
961 case SIGUSR2
: return "SIGUSR2";
964 case SIGPIPE
: return "SIGPIPE";
967 case SIGALRM
: return "SIGALRM";
969 case SIGTERM
: return "SIGTERM";
971 case SIGSTKFLT
: return "SIGSTKFLT";
974 case SIGCHLD
: return "SIGCHLD";
977 case SIGCONT
: return "SIGCONT";
980 case SIGSTOP
: return "SIGSTOP";
983 case SIGTSTP
: return "SIGTSTP";
986 case SIGTTIN
: return "SIGTTIN";
989 case SIGTTOU
: return "SIGTTOU";
992 case SIGURG
: return "SIGURG";
995 case SIGXCPU
: return "SIGXCPU";
998 case SIGXFSZ
: return "SIGXFSZ";
1001 case SIGVTALRM
: return "SIGVTALRM";
1004 case SIGPROF
: return "SIGPROF";
1007 case SIGWINCH
: return "SIGWINCH";
1010 case SIGIO
: return "SIGIO";
1013 case SIGPWR
: return "SIGPWR";
1016 case SIGSYS
: return "SIGSYS";
1021 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1022 pa_xfree(PA_STATIC_TLS_GET(signame
));
1023 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1024 PA_STATIC_TLS_SET(signame
, t
);
1033 pa_xfree(PA_STATIC_TLS_GET(signame
));
1034 t
= pa_sprintf_malloc("SIG%i", sig
);
1035 PA_STATIC_TLS_SET(signame
, t
);
1041 /* Check whether the specified GID and the group name match */
1042 static int is_group(gid_t gid
, const char *name
) {
1043 struct group
*group
= NULL
;
1047 if (!(group
= pa_getgrgid_malloc(gid
)))
1052 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1057 r
= strcmp(name
, group
->gr_name
) == 0;
1060 pa_getgrgid_free(group
);
1065 /* Check the current user is member of the specified group */
1066 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1067 GETGROUPS_T
*gids
, tgid
;
1068 long n
= sysconf(_SC_NGROUPS_MAX
);
1073 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1075 if ((n
= getgroups((int) n
, gids
)) < 0) {
1076 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1080 for (i
= 0; i
< n
; i
++) {
1082 if ((k
= is_group(gids
[i
], name
)) < 0)
1091 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1107 /* Check whether the specifc user id is a member of the specified group */
1108 int pa_uid_in_group(uid_t uid
, const char *name
) {
1109 struct group
*group
= NULL
;
1114 if (!(group
= pa_getgrnam_malloc(name
)))
1122 for (i
= group
->gr_mem
; *i
; i
++) {
1123 struct passwd
*pw
= NULL
;
1126 if (!(pw
= pa_getpwnam_malloc(*i
)))
1129 if (pw
->pw_uid
== uid
)
1132 pa_getpwnam_free(pw
);
1139 pa_getgrnam_free(group
);
1144 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1145 gid_t
pa_get_gid_of_group(const char *name
) {
1146 gid_t ret
= (gid_t
) -1;
1147 struct group
*gr
= NULL
;
1150 if (!(gr
= pa_getgrnam_malloc(name
)))
1160 pa_getgrnam_free(gr
);
1164 int pa_check_in_group(gid_t g
) {
1165 gid_t gids
[NGROUPS_MAX
];
1168 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1178 #else /* HAVE_GRP_H */
1180 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1186 int pa_uid_in_group(uid_t uid
, const char *name
) {
1191 gid_t
pa_get_gid_of_group(const char *name
) {
1196 int pa_check_in_group(gid_t g
) {
1203 /* Lock or unlock a file entirely.
1204 (advisory on UNIX, mandatory on Windows) */
1205 int pa_lock_fd(int fd
, int b
) {
1207 struct flock f_lock
;
1209 /* Try a R/W lock first */
1211 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1212 f_lock
.l_whence
= SEEK_SET
;
1216 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1219 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1220 if (b
&& errno
== EBADF
) {
1221 f_lock
.l_type
= F_RDLCK
;
1222 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1226 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1230 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1232 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1234 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1237 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1239 /* FIXME: Needs to set errno! */
1245 /* Remove trailing newlines from a string */
1246 char* pa_strip_nl(char *s
) {
1249 s
[strcspn(s
, NEWLINE
)] = 0;
1253 char *pa_strip(char *s
) {
1256 /* Drops trailing whitespace. Modifies the string in
1257 * place. Returns pointer to first non-space character */
1259 s
+= strspn(s
, WHITESPACE
);
1261 for (e
= s
; *e
; e
++)
1262 if (!strchr(WHITESPACE
, *e
))
1273 /* Create a temporary lock file and lock it. */
1274 int pa_lock_lockfile(const char *fn
) {
1281 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1285 , S_IRUSR
|S_IWUSR
)) < 0) {
1286 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1290 if (pa_lock_fd(fd
, 1) < 0) {
1291 pa_log_warn("Failed to lock file '%s'.", fn
);
1295 if (fstat(fd
, &st
) < 0) {
1296 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1300 /* Check whether the file has been removed meanwhile. When yes,
1301 * restart this loop, otherwise, we're done */
1302 if (st
.st_nlink
>= 1)
1305 if (pa_lock_fd(fd
, 0) < 0) {
1306 pa_log_warn("Failed to unlock file '%s'.", fn
);
1310 if (pa_close(fd
) < 0) {
1311 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1322 int saved_errno
= errno
;
1324 errno
= saved_errno
;
1330 /* Unlock a temporary lcok file */
1331 int pa_unlock_lockfile(const char *fn
, int fd
) {
1336 if (unlink(fn
) < 0) {
1337 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1342 if (pa_lock_fd(fd
, 0) < 0) {
1343 pa_log_warn("Failed to unlock file '%s'.", fn
);
1347 if (pa_close(fd
) < 0) {
1348 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1355 static char *get_pulse_home(void) {
1360 if (!(h
= pa_get_home_dir_malloc())) {
1361 pa_log_error("Failed to get home directory.");
1365 if (stat(h
, &st
) < 0) {
1366 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1371 if (st
.st_uid
!= getuid()) {
1372 pa_log_error("Home directory %s not ours.", h
);
1378 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1386 char *pa_get_state_dir(void) {
1389 /* The state directory shall contain dynamic data that should be
1390 * kept across reboots, and is private to this user */
1392 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1393 if (!(d
= get_pulse_home()))
1396 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1397 * dir then this will break. */
1399 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1400 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1408 char *pa_get_home_dir_malloc(void) {
1410 size_t allocated
= 128;
1413 homedir
= pa_xmalloc(allocated
);
1415 if (!pa_get_home_dir(homedir
, allocated
)) {
1420 if (strlen(homedir
) < allocated
- 1)
1430 char *pa_get_binary_name_malloc(void) {
1432 size_t allocated
= 128;
1435 t
= pa_xmalloc(allocated
);
1437 if (!pa_get_binary_name(t
, allocated
)) {
1442 if (strlen(t
) < allocated
- 1)
1452 static char* make_random_dir(mode_t m
) {
1453 static const char table
[] =
1454 "abcdefghijklmnopqrstuvwxyz"
1455 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1461 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1462 pathlen
= strlen(fn
);
1470 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1471 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1473 u
= umask((~m
) & 0777);
1480 saved_errno
= errno
;
1482 errno
= saved_errno
;
1487 if (errno
!= EEXIST
) {
1488 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1495 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1498 if (!(p
= make_random_dir(m
)))
1502 if (symlink(p
, k
) < 0) {
1503 int saved_errno
= errno
;
1505 if (errno
!= EEXIST
)
1506 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1511 errno
= saved_errno
;
1523 char *pa_get_runtime_dir(void) {
1524 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1528 /* The runtime directory shall contain dynamic data that needs NOT
1529 * to be kept accross reboots and is usuallly private to the user,
1530 * except in system mode, where it might be accessible by other
1531 * users, too. Since we need POSIX locking and UNIX sockets in
1532 * this directory, we link it to a random subdir in /tmp, if it
1533 * was not explicitly configured. */
1535 m
= pa_in_system_mode() ? 0755U : 0700U;
1537 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1539 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1540 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1544 return pa_xstrdup(d
);
1547 if (!(d
= get_pulse_home()))
1550 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1551 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1556 if (!(mid
= pa_machine_id())) {
1561 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1566 /* OK, first let's check if the "runtime" symlink is already
1569 if (!(p
= pa_readlink(k
))) {
1571 if (errno
!= ENOENT
) {
1572 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1577 /* Hmm, so the runtime directory didn't exist yet, so let's
1578 * create one in /tmp and symlink that to it */
1580 if (make_random_dir_and_link(0700, k
) < 0) {
1582 /* Mhmm, maybe another process was quicker than us,
1583 * let's check if that was valid */
1584 if (errno
== EEXIST
)
1590 /* No symlink possible, so let's just create the runtime directly */
1598 /* Make sure that this actually makes sense */
1599 if (!pa_is_path_absolute(p
)) {
1600 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1605 /* Hmm, so this symlink is still around, make sure nobody fools
1609 if (lstat(p
, &st
) < 0) {
1611 if (errno
!= ENOENT
) {
1612 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1618 if (S_ISDIR(st
.st_mode
) &&
1619 (st
.st_uid
== getuid()) &&
1620 ((st
.st_mode
& 0777) == 0700)) {
1626 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1633 /* Hmm, so the link points to some nonexisting or invalid
1634 * dir. Let's replace it by a new link. We first create a
1635 * temporary link and then rename that to allow concurrent
1636 * execution of this function. */
1638 t
= pa_sprintf_malloc("%s.tmp", k
);
1640 if (make_random_dir_and_link(0700, t
) < 0) {
1642 if (errno
!= EEXIST
) {
1643 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1650 /* Hmm, someone lese was quicker then us. Let's give
1651 * him some time to finish, and retry. */
1656 /* OK, we succeeded in creating the temporary symlink, so
1657 * let's rename it */
1658 if (rename(t
, k
) < 0) {
1659 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1675 /* Try to open a configuration file. If "env" is specified, open the
1676 * value of the specified environment variable. Otherwise look for a
1677 * file "local" in the home directory or a file "global" in global
1678 * file system. If "result" is non-NULL, a pointer to a newly
1679 * allocated buffer containing the used configuration file is
1681 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1685 if (env
&& (fn
= getenv(env
))) {
1686 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1688 *result
= pa_xstrdup(fn
);
1693 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1702 if ((e
= getenv("PULSE_CONFIG_PATH")))
1703 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1704 else if ((h
= pa_get_home_dir_malloc())) {
1705 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1710 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1712 *result
= pa_xstrdup(fn
);
1718 if (errno
!= ENOENT
) {
1719 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1731 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1732 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1733 pa_win32_get_toplevel(NULL
),
1734 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1737 gfn
= pa_xstrdup(global
);
1739 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1754 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1757 if (env
&& (fn
= getenv(env
))) {
1758 if (access(fn
, R_OK
) == 0)
1759 return pa_xstrdup(fn
);
1761 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1770 if ((e
= getenv("PULSE_CONFIG_PATH")))
1771 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1772 else if ((h
= pa_get_home_dir_malloc())) {
1773 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1778 if (access(fn
, R_OK
) == 0) {
1779 char *r
= pa_xstrdup(fn
);
1784 if (errno
!= ENOENT
) {
1785 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1797 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1798 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1799 pa_win32_get_toplevel(NULL
),
1800 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1803 gfn
= pa_xstrdup(global
);
1805 if (access(gfn
, R_OK
) == 0)
1815 /* Format the specified data as a hexademical string */
1816 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1817 size_t i
= 0, j
= 0;
1818 const char hex
[] = "0123456789abcdef";
1822 pa_assert(slength
> 0);
1824 while (i
< dlength
&& j
+3 <= slength
) {
1825 s
[j
++] = hex
[*d
>> 4];
1826 s
[j
++] = hex
[*d
& 0xF];
1832 s
[j
< slength
? j
: slength
] = 0;
1836 /* Convert a hexadecimal digit to a number or -1 if invalid */
1837 static int hexc(char c
) {
1838 if (c
>= '0' && c
<= '9')
1841 if (c
>= 'A' && c
<= 'F')
1842 return c
- 'A' + 10;
1844 if (c
>= 'a' && c
<= 'f')
1845 return c
- 'a' + 10;
1851 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1852 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1858 while (j
< dlength
&& *p
) {
1861 if ((b
= hexc(*(p
++))) < 0)
1864 d
[j
] = (uint8_t) (b
<< 4);
1869 if ((b
= hexc(*(p
++))) < 0)
1872 d
[j
] |= (uint8_t) b
;
1879 /* Returns nonzero when *s starts with *pfx */
1880 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1888 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1891 /* Returns nonzero when *s ends with *sfx */
1892 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1901 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1904 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1910 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1914 char *pa_make_path_absolute(const char *p
) {
1920 if (pa_is_path_absolute(p
))
1921 return pa_xstrdup(p
);
1923 if (!(cwd
= pa_getcwd()))
1924 return pa_xstrdup(p
);
1926 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1931 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1932 * if fn is non-null and starts with / return fn
1933 * otherwise append fn to the run time path and return it */
1934 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1937 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1942 if (pa_is_path_absolute(fn
))
1943 return pa_xstrdup(fn
);
1951 if (!(mid
= pa_machine_id())) {
1956 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1959 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
1967 char *pa_runtime_path(const char *fn
) {
1968 return get_path(fn
, FALSE
, TRUE
);
1971 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
1972 return get_path(fn
, appendmid
, FALSE
);
1975 /* Convert the string s to a signed integer in *ret_i */
1976 int pa_atoi(const char *s
, int32_t *ret_i
) {
1984 l
= strtol(s
, &x
, 0);
1986 if (!x
|| *x
|| errno
) {
1992 if ((int32_t) l
!= l
) {
1997 *ret_i
= (int32_t) l
;
2002 /* Convert the string s to an unsigned integer in *ret_u */
2003 int pa_atou(const char *s
, uint32_t *ret_u
) {
2011 l
= strtoul(s
, &x
, 0);
2013 if (!x
|| *x
|| errno
) {
2019 if ((uint32_t) l
!= l
) {
2024 *ret_u
= (uint32_t) l
;
2029 #ifdef HAVE_STRTOF_L
2030 static locale_t c_locale
= NULL
;
2032 static void c_locale_destroy(void) {
2033 freelocale(c_locale
);
2037 int pa_atod(const char *s
, double *ret_d
) {
2044 /* This should be locale independent */
2046 #ifdef HAVE_STRTOF_L
2050 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2051 atexit(c_locale_destroy
);
2057 f
= strtod_l(s
, &x
, c_locale
);
2065 if (!x
|| *x
|| errno
) {
2076 /* Same as snprintf, but guarantees NUL-termination on every platform */
2077 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2082 pa_assert(size
> 0);
2085 va_start(ap
, format
);
2086 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2092 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2093 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2097 pa_assert(size
> 0);
2100 ret
= vsnprintf(str
, size
, format
, ap
);
2107 if ((size_t) ret
> size
-1)
2110 return (size_t) ret
;
2113 /* Truncate the specified string, but guarantee that the string
2114 * returned still validates as UTF8 */
2115 char *pa_truncate_utf8(char *c
, size_t l
) {
2117 pa_assert(pa_utf8_valid(c
));
2124 while (l
> 0 && !pa_utf8_valid(c
))
2130 char *pa_getcwd(void) {
2134 char *p
= pa_xmalloc(l
);
2138 if (errno
!= ERANGE
)
2146 void *pa_will_need(const void *p
, size_t l
) {
2147 #ifdef RLIMIT_MEMLOCK
2158 a
= PA_PAGE_ALIGN_PTR(p
);
2159 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2161 #ifdef HAVE_POSIX_MADVISE
2162 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2163 pa_log_debug("posix_madvise() worked fine!");
2168 /* Most likely the memory was not mmap()ed from a file and thus
2169 * madvise() didn't work, so let's misuse mlock() do page this
2170 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2171 * inviting, the man page of mlock() tells us: "All pages that
2172 * contain a part of the specified address range are guaranteed to
2173 * be resident in RAM when the call returns successfully." */
2175 #ifdef RLIMIT_MEMLOCK
2176 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2178 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2179 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
));
2184 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2186 bs
= PA_PAGE_SIZE
*4;
2189 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2192 while (size
> 0 && bs
> 0) {
2197 if (mlock(a
, bs
) < 0) {
2198 bs
= PA_PAGE_ALIGN(bs
/ 2);
2202 pa_assert_se(munlock(a
, bs
) == 0);
2204 a
= (const uint8_t*) a
+ bs
;
2210 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2212 pa_log_debug("mlock() worked fine!");
2217 void pa_close_pipe(int fds
[2]) {
2221 pa_assert_se(pa_close(fds
[0]) == 0);
2224 pa_assert_se(pa_close(fds
[1]) == 0);
2226 fds
[0] = fds
[1] = -1;
2229 char *pa_readlink(const char *p
) {
2230 #ifdef HAVE_READLINK
2239 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2244 if ((size_t) n
< l
-1) {
2257 int pa_close_all(int except_fd
, ...) {
2262 va_start(ap
, except_fd
);
2265 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2270 p
= pa_xnew(int, n
+1);
2272 va_start(ap
, except_fd
);
2275 if (except_fd
>= 0) {
2279 while ((fd
= va_arg(ap
, int)) >= 0)
2286 r
= pa_close_allv(p
);
2292 int pa_close_allv(const int except_fds
[]) {
2301 if ((d
= opendir("/proc/self/fd"))) {
2305 while ((de
= readdir(d
))) {
2311 if (de
->d_name
[0] == '.')
2315 l
= strtol(de
->d_name
, &e
, 10);
2316 if (errno
!= 0 || !e
|| *e
) {
2324 if ((long) fd
!= l
) {
2337 for (i
= 0; except_fds
[i
] >= 0; i
++)
2338 if (except_fds
[i
] == fd
) {
2346 if (pa_close(fd
) < 0) {
2347 saved_errno
= errno
;
2349 errno
= saved_errno
;
2361 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2362 maxfd
= (int) rl
.rlim_max
;
2364 maxfd
= sysconf(_SC_OPEN_MAX
);
2366 for (fd
= 3; fd
< maxfd
; fd
++) {
2371 for (i
= 0; except_fds
[i
] >= 0; i
++)
2372 if (except_fds
[i
] == fd
) {
2380 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2383 #endif /* !OS_IS_WIN32 */
2388 int pa_unblock_sigs(int except
, ...) {
2393 va_start(ap
, except
);
2396 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2401 p
= pa_xnew(int, n
+1);
2403 va_start(ap
, except
);
2410 while ((sig
= va_arg(ap
, int)) >= 0)
2417 r
= pa_unblock_sigsv(p
);
2423 int pa_unblock_sigsv(const int except
[]) {
2428 if (sigemptyset(&ss
) < 0)
2431 for (i
= 0; except
[i
] > 0; i
++)
2432 if (sigaddset(&ss
, except
[i
]) < 0)
2435 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2441 int pa_reset_sigs(int except
, ...) {
2446 va_start(ap
, except
);
2449 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2454 p
= pa_xnew(int, n
+1);
2456 va_start(ap
, except
);
2463 while ((sig
= va_arg(ap
, int)) >= 0)
2470 r
= pa_reset_sigsv(p
);
2476 int pa_reset_sigsv(const int except
[]) {
2480 for (sig
= 1; sig
< NSIG
; sig
++) {
2481 pa_bool_t reset
= TRUE
;
2492 for (i
= 0; except
[i
] > 0; i
++) {
2493 if (sig
== except
[i
]) {
2502 struct sigaction sa
;
2504 memset(&sa
, 0, sizeof(sa
));
2505 sa
.sa_handler
= SIG_DFL
;
2507 /* On Linux the first two RT signals are reserved by
2508 * glibc, and sigaction() will return EINVAL for them. */
2509 if ((sigaction(sig
, &sa
, NULL
) < 0))
2510 if (errno
!= EINVAL
)
2519 void pa_set_env(const char *key
, const char *value
) {
2523 /* This is not thread-safe */
2526 SetEnvironmentVariable(key
, value
);
2528 setenv(key
, value
, 1);
2532 void pa_set_env_and_record(const char *key
, const char *value
) {
2536 /* This is not thread-safe */
2538 pa_set_env(key
, value
);
2539 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2542 void pa_unset_env_recorded(void) {
2544 /* This is not thread-safe */
2549 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2555 SetEnvironmentVariable(s
, NULL
);
2563 pa_bool_t
pa_in_system_mode(void) {
2566 if (!(e
= getenv("PULSE_SYSTEM")))
2572 char *pa_get_user_name_malloc(void) {
2576 #ifdef _SC_LOGIN_NAME_MAX
2577 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2583 u
= pa_xnew(char, k
+1);
2585 if (!(pa_get_user_name(u
, k
))) {
2593 char *pa_get_host_name_malloc(void) {
2602 if (!pa_get_host_name(c
, l
)) {
2604 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2607 } else if (strlen(c
) < l
-1) {
2615 u
= pa_utf8_filter(c
);
2620 /* Hmm, the hostname is as long the space we offered the
2621 * function, we cannot know if it fully fit in, so let's play
2622 * safe and retry. */
2631 char *pa_machine_id(void) {
2635 /* The returned value is supposed be some kind of ascii identifier
2636 * that is unique and stable across reboots. */
2638 /* First we try the D-Bus UUID, which is the best option we have,
2639 * since it fits perfectly our needs and is not as volatile as the
2640 * hostname which might be set from dhcp. */
2642 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2643 char ln
[34] = "", *r
;
2645 r
= fgets(ln
, sizeof(ln
)-1, f
);
2651 return pa_utf8_filter(ln
);
2654 if ((h
= pa_get_host_name_malloc()))
2658 /* If no hostname was set we use the POSIX hostid. It's usually
2659 * the IPv4 address. Might not be that stable. */
2660 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2666 char *pa_session_id(void) {
2669 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2672 return pa_utf8_filter(e
);
2675 char *pa_uname_string(void) {
2679 pa_assert_se(uname(&u
) >= 0);
2681 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2687 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2688 pa_assert_se(GetVersionEx(&i
));
2690 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2694 #ifdef HAVE_VALGRIND_MEMCHECK_H
2695 pa_bool_t
pa_in_valgrind(void) {
2698 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2699 * here instead of really checking whether we run in valgrind or
2703 b
= getenv("VALGRIND") ? 2 : 1;
2709 unsigned pa_gcd(unsigned a
, unsigned b
) {
2720 void pa_reduce(unsigned *num
, unsigned *den
) {
2722 unsigned gcd
= pa_gcd(*num
, *den
);
2730 pa_assert(pa_gcd(*num
, *den
) == 1);
2733 unsigned pa_ncpus(void) {
2736 #ifdef _SC_NPROCESSORS_CONF
2737 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2742 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2745 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2754 sb
= pa_strbuf_new();
2759 if (!(p
= strstr(s
, a
)))
2762 pa_strbuf_putsn(sb
, s
, p
-s
);
2763 pa_strbuf_puts(sb
, b
);
2767 pa_strbuf_puts(sb
, s
);
2769 return pa_strbuf_tostring_free(sb
);
2772 char *pa_escape(const char *p
, const char *chars
) {
2775 pa_strbuf
*buf
= pa_strbuf_new();
2777 for (s
= p
; *s
; ++s
) {
2779 pa_strbuf_putc(buf
, '\\');
2781 for (c
= chars
; *c
; ++c
) {
2783 pa_strbuf_putc(buf
, '\\');
2788 pa_strbuf_putc(buf
, *s
);
2791 return pa_strbuf_tostring_free(buf
);
2794 char *pa_unescape(char *p
) {
2796 pa_bool_t escaped
= FALSE
;
2798 for (s
= p
, d
= p
; *s
; s
++) {
2799 if (!escaped
&& *s
== '\\') {
2813 char *pa_realpath(const char *path
) {
2817 /* We want only abolsute paths */
2818 if (path
[0] != '/') {
2823 #if defined(__GLIBC__) || defined(__APPLE__)
2827 if (!(r
= realpath(path
, NULL
)))
2830 /* We copy this here in case our pa_xmalloc() is not
2831 * implemented on top of libc malloc() */
2835 #elif defined(PATH_MAX)
2838 path_buf
= pa_xmalloc(PATH_MAX
);
2840 #if defined(OS_IS_WIN32)
2841 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2846 if (!(t
= realpath(path
, path_buf
))) {
2853 #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."
2859 void pa_disable_sigpipe(void) {
2862 struct sigaction sa
;
2866 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2867 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2871 sa
.sa_handler
= SIG_IGN
;
2873 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2874 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2880 void pa_xfreev(void**a
) {
2886 for (p
= a
; *p
; p
++)
2892 char **pa_split_spaces_strv(const char *s
) {
2894 unsigned i
= 0, n
= 8;
2895 const char *state
= NULL
;
2897 t
= pa_xnew(char*, n
);
2898 while ((e
= pa_split_spaces(s
, &state
))) {
2903 t
= pa_xrenew(char*, t
, n
);
2916 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2919 if (pa_is_path_absolute(path
))
2920 return pa_xstrdup(path
);
2922 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2925 size_t pa_pipe_buf(int fd
) {
2930 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2941 void pa_reset_personality(void) {
2944 if (personality(PER_LINUX
) < 0)
2945 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2950 #if defined(__linux__) && !defined(__OPTIMIZE__)
2952 pa_bool_t
pa_run_from_build_tree(void) {
2954 pa_bool_t b
= FALSE
;
2956 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2959 if ((rp
= pa_readlink("/proc/self/exe"))) {
2960 b
= pa_startswith(rp
, PA_BUILDDIR
);
2969 const char *pa_get_temp_dir(void) {
2972 if ((t
= getenv("TMPDIR")) &&
2973 pa_is_path_absolute(t
))
2976 if ((t
= getenv("TMP")) &&
2977 pa_is_path_absolute(t
))
2980 if ((t
= getenv("TEMP")) &&
2981 pa_is_path_absolute(t
))
2984 if ((t
= getenv("TEMPDIR")) &&
2985 pa_is_path_absolute(t
))
2991 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
2999 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3002 if (errno
!= EINVAL
)
3006 if ((fd
= open(fn
, flags
, mode
)) < 0)
3010 /* Some implementations might simply ignore O_CLOEXEC if it is not
3011 * understood, make sure FD_CLOEXEC is enabled anyway */
3013 pa_make_fd_cloexec(fd
);
3017 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3021 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3024 if (errno
!= EINVAL
)
3028 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3032 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3033 * not understood, make sure FD_CLOEXEC is enabled anyway */
3035 pa_make_fd_cloexec(fd
);
3039 int pa_pipe_cloexec(int pipefd
[2]) {
3043 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3046 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3051 if ((r
= pipe(pipefd
)) < 0)
3055 pa_make_fd_cloexec(pipefd
[0]);
3056 pa_make_fd_cloexec(pipefd
[1]);
3061 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3065 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3068 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3073 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3077 pa_make_fd_cloexec(fd
);
3081 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3085 m
= pa_sprintf_malloc("%se", mode
);
3088 if ((f
= fopen(path
, m
))) {
3095 if (errno
!= EINVAL
)
3098 if (!(f
= fopen(path
, mode
)))
3102 pa_make_fd_cloexec(fileno(f
));
3106 void pa_nullify_stdfds(void) {
3109 pa_close(STDIN_FILENO
);
3110 pa_close(STDOUT_FILENO
);
3111 pa_close(STDERR_FILENO
);
3113 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3114 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3115 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3122 char *pa_read_line_from_file(const char *fn
) {
3124 char ln
[256] = "", *r
;
3126 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3129 r
= fgets(ln
, sizeof(ln
)-1, f
);
3138 return pa_xstrdup(ln
);
3141 pa_bool_t
pa_running_in_vm(void) {
3143 #if defined(__i386__) || defined(__x86_64__)
3145 /* Both CPUID and DMI are x86 specific interfaces... */
3147 uint32_t eax
= 0x40000000;
3154 const char *const dmi_vendors
[] = {
3155 "/sys/class/dmi/id/sys_vendor",
3156 "/sys/class/dmi/id/board_vendor",
3157 "/sys/class/dmi/id/bios_vendor"
3162 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3165 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3167 if (pa_startswith(s
, "QEMU") ||
3168 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3169 pa_startswith(s
, "VMware") ||
3170 pa_startswith(s
, "VMW") ||
3171 pa_startswith(s
, "Microsoft Corporation") ||
3172 pa_startswith(s
, "innotek GmbH") ||
3173 pa_startswith(s
, "Xen")) {
3185 /* http://lwn.net/Articles/301888/ */
3188 __asm__
__volatile__ (
3189 /* ebx/rbx is being used for PIC! */
3190 " push %%"PA_REG_b
" \n\t"
3192 " mov %%ebx, %1 \n\t"
3193 " pop %%"PA_REG_b
" \n\t"
3195 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3199 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3200 pa_streq(sig
.text
, "KVMKVMKVM") ||
3201 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3202 pa_streq(sig
.text
, "VMwareVMware") ||
3203 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3204 pa_streq(sig
.text
, "Microsoft Hv"))