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 #ifdef _POSIX_PRIORITY_SCHEDULING
629 static int set_scheduler(int rtprio
) {
631 struct sched_param sp
;
637 dbus_error_init(&error
);
641 sp
.sched_priority
= rtprio
;
643 #ifdef SCHED_RESET_ON_FORK
644 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
645 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
650 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
651 pa_log_debug("SCHED_RR worked.");
654 #endif /* HAVE_SCHED_H */
657 /* Try to talk to RealtimeKit */
659 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
660 pa_log("Failed to connect to system bus: %s\n", error
.message
);
661 dbus_error_free(&error
);
666 /* We need to disable exit on disconnect because otherwise
667 * dbus_shutdown will kill us. See
668 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
669 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
671 r
= rtkit_make_realtime(bus
, 0, rtprio
);
672 dbus_connection_unref(bus
);
675 pa_log_debug("RealtimeKit worked.");
688 /* Make the current thread a realtime thread, and acquire the highest
689 * rtprio we can get that is less or equal the specified parameter. If
690 * the thread is already realtime, don't do anything. */
691 int pa_make_realtime(int rtprio
) {
693 #ifdef _POSIX_PRIORITY_SCHEDULING
696 if (set_scheduler(rtprio
) >= 0) {
697 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
701 for (p
= rtprio
-1; p
>= 1; p
--)
702 if (set_scheduler(p
) >= 0) {
703 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
706 #elif defined(OS_IS_WIN32)
707 /* Windows only allows realtime scheduling to be set on a per process basis.
708 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
709 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
710 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
714 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
719 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
723 #ifdef HAVE_SYS_RESOURCE_H
724 static int set_nice(int nice_level
) {
730 dbus_error_init(&error
);
733 #ifdef HAVE_SYS_RESOURCE_H
734 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
735 pa_log_debug("setpriority() worked.");
741 /* Try to talk to RealtimeKit */
743 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
744 pa_log("Failed to connect to system bus: %s\n", error
.message
);
745 dbus_error_free(&error
);
750 /* We need to disable exit on disconnect because otherwise
751 * dbus_shutdown will kill us. See
752 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
753 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
755 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
756 dbus_connection_unref(bus
);
759 pa_log_debug("RealtimeKit worked.");
770 /* Raise the priority of the current process as much as possible that
771 * is <= the specified nice level..*/
772 int pa_raise_priority(int nice_level
) {
774 #ifdef HAVE_SYS_RESOURCE_H
777 if (set_nice(nice_level
) >= 0) {
778 pa_log_info("Successfully gained nice level %i.", nice_level
);
782 for (n
= nice_level
+1; n
< 0; n
++)
783 if (set_nice(n
) >= 0) {
784 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
788 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
793 if (nice_level
< 0) {
794 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
795 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
800 pa_log_info("Successfully gained high priority class.");
807 /* Reset the priority to normal, inverting the changes made by
808 * pa_raise_priority() and pa_make_realtime()*/
809 void pa_reset_priority(void) {
810 #ifdef HAVE_SYS_RESOURCE_H
811 struct sched_param sp
;
813 setpriority(PRIO_PROCESS
, 0, 0);
816 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
820 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
824 int pa_match(const char *expr
, const char *v
) {
829 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
834 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
836 else if (k
== REG_NOMATCH
)
849 /* Try to parse a boolean string value.*/
850 int pa_parse_boolean(const char *v
) {
854 /* First we check language independant */
855 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
857 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
860 #ifdef HAVE_LANGINFO_H
861 /* And then we check language dependant */
862 if ((expr
= nl_langinfo(YESEXPR
)))
864 if (pa_match(expr
, v
) > 0)
867 if ((expr
= nl_langinfo(NOEXPR
)))
869 if (pa_match(expr
, v
) > 0)
877 /* Split the specified string wherever one of the strings in delimiter
878 * occurs. Each time it is called returns a newly allocated string
879 * with pa_xmalloc(). The variable state points to, should be
880 * initiallized to NULL before the first call. */
881 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
882 const char *current
= *state
? *state
: c
;
888 l
= strcspn(current
, delimiter
);
894 return pa_xstrndup(current
, l
);
897 /* Split a string into words. Otherwise similar to pa_split(). */
898 char *pa_split_spaces(const char *c
, const char **state
) {
899 const char *current
= *state
? *state
: c
;
902 if (!*current
|| *c
== 0)
905 current
+= strspn(current
, WHITESPACE
);
906 l
= strcspn(current
, WHITESPACE
);
910 return pa_xstrndup(current
, l
);
913 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
915 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
916 const char *pa_sig2str(int sig
) {
929 char buf
[SIG2STR_MAX
];
931 if (sig2str(sig
, buf
) == 0) {
932 pa_xfree(PA_STATIC_TLS_GET(signame
));
933 t
= pa_sprintf_malloc("SIG%s", buf
);
934 PA_STATIC_TLS_SET(signame
, t
);
942 case SIGHUP
: return "SIGHUP";
944 case SIGINT
: return "SIGINT";
946 case SIGQUIT
: return "SIGQUIT";
948 case SIGILL
: return "SIGULL";
950 case SIGTRAP
: return "SIGTRAP";
952 case SIGABRT
: return "SIGABRT";
954 case SIGBUS
: return "SIGBUS";
956 case SIGFPE
: return "SIGFPE";
958 case SIGKILL
: return "SIGKILL";
961 case SIGUSR1
: return "SIGUSR1";
963 case SIGSEGV
: return "SIGSEGV";
965 case SIGUSR2
: return "SIGUSR2";
968 case SIGPIPE
: return "SIGPIPE";
971 case SIGALRM
: return "SIGALRM";
973 case SIGTERM
: return "SIGTERM";
975 case SIGSTKFLT
: return "SIGSTKFLT";
978 case SIGCHLD
: return "SIGCHLD";
981 case SIGCONT
: return "SIGCONT";
984 case SIGSTOP
: return "SIGSTOP";
987 case SIGTSTP
: return "SIGTSTP";
990 case SIGTTIN
: return "SIGTTIN";
993 case SIGTTOU
: return "SIGTTOU";
996 case SIGURG
: return "SIGURG";
999 case SIGXCPU
: return "SIGXCPU";
1002 case SIGXFSZ
: return "SIGXFSZ";
1005 case SIGVTALRM
: return "SIGVTALRM";
1008 case SIGPROF
: return "SIGPROF";
1011 case SIGWINCH
: return "SIGWINCH";
1014 case SIGIO
: return "SIGIO";
1017 case SIGPWR
: return "SIGPWR";
1020 case SIGSYS
: return "SIGSYS";
1025 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1026 pa_xfree(PA_STATIC_TLS_GET(signame
));
1027 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1028 PA_STATIC_TLS_SET(signame
, t
);
1037 pa_xfree(PA_STATIC_TLS_GET(signame
));
1038 t
= pa_sprintf_malloc("SIG%i", sig
);
1039 PA_STATIC_TLS_SET(signame
, t
);
1045 /* Check whether the specified GID and the group name match */
1046 static int is_group(gid_t gid
, const char *name
) {
1047 struct group
*group
= NULL
;
1051 if (!(group
= pa_getgrgid_malloc(gid
))) {
1055 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1060 r
= strcmp(name
, group
->gr_name
) == 0;
1063 pa_getgrgid_free(group
);
1068 /* Check the current user is member of the specified group */
1069 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1070 GETGROUPS_T
*gids
, tgid
;
1071 long n
= sysconf(_SC_NGROUPS_MAX
);
1076 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1078 if ((n
= getgroups((int) n
, gids
)) < 0) {
1079 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1083 for (i
= 0; i
< n
; i
++) {
1085 if ((k
= is_group(gids
[i
], name
)) < 0)
1094 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1110 /* Check whether the specifc user id is a member of the specified group */
1111 int pa_uid_in_group(uid_t uid
, const char *name
) {
1112 struct group
*group
= NULL
;
1117 if (!(group
= pa_getgrnam_malloc(name
))) {
1124 for (i
= group
->gr_mem
; *i
; i
++) {
1125 struct passwd
*pw
= NULL
;
1128 if (!(pw
= pa_getpwnam_malloc(*i
)))
1131 if (pw
->pw_uid
== uid
)
1134 pa_getpwnam_free(pw
);
1141 pa_getgrnam_free(group
);
1146 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1147 gid_t
pa_get_gid_of_group(const char *name
) {
1148 gid_t ret
= (gid_t
) -1;
1149 struct group
*gr
= NULL
;
1152 if (!(gr
= pa_getgrnam_malloc(name
))) {
1161 pa_getgrnam_free(gr
);
1165 int pa_check_in_group(gid_t g
) {
1166 gid_t gids
[NGROUPS_MAX
];
1169 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1179 #else /* HAVE_GRP_H */
1181 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1187 int pa_uid_in_group(uid_t uid
, const char *name
) {
1192 gid_t
pa_get_gid_of_group(const char *name
) {
1197 int pa_check_in_group(gid_t g
) {
1204 /* Lock or unlock a file entirely.
1205 (advisory on UNIX, mandatory on Windows) */
1206 int pa_lock_fd(int fd
, int b
) {
1208 struct flock f_lock
;
1210 /* Try a R/W lock first */
1212 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1213 f_lock
.l_whence
= SEEK_SET
;
1217 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1220 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1221 if (b
&& errno
== EBADF
) {
1222 f_lock
.l_type
= F_RDLCK
;
1223 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1227 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1231 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1233 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1235 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1238 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1240 /* FIXME: Needs to set errno! */
1246 /* Remove trailing newlines from a string */
1247 char* pa_strip_nl(char *s
) {
1250 s
[strcspn(s
, NEWLINE
)] = 0;
1254 char *pa_strip(char *s
) {
1257 /* Drops trailing whitespace. Modifies the string in
1258 * place. Returns pointer to first non-space character */
1260 s
+= strspn(s
, WHITESPACE
);
1262 for (e
= s
; *e
; e
++)
1263 if (!strchr(WHITESPACE
, *e
))
1274 /* Create a temporary lock file and lock it. */
1275 int pa_lock_lockfile(const char *fn
) {
1282 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1286 , S_IRUSR
|S_IWUSR
)) < 0) {
1287 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1291 if (pa_lock_fd(fd
, 1) < 0) {
1292 pa_log_warn("Failed to lock file '%s'.", fn
);
1296 if (fstat(fd
, &st
) < 0) {
1297 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1301 /* Check whether the file has been removed meanwhile. When yes,
1302 * restart this loop, otherwise, we're done */
1303 if (st
.st_nlink
>= 1)
1306 if (pa_lock_fd(fd
, 0) < 0) {
1307 pa_log_warn("Failed to unlock file '%s'.", fn
);
1311 if (pa_close(fd
) < 0) {
1312 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1323 int saved_errno
= errno
;
1325 errno
= saved_errno
;
1331 /* Unlock a temporary lcok file */
1332 int pa_unlock_lockfile(const char *fn
, int fd
) {
1337 if (unlink(fn
) < 0) {
1338 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1343 if (pa_lock_fd(fd
, 0) < 0) {
1344 pa_log_warn("Failed to unlock file '%s'.", fn
);
1348 if (pa_close(fd
) < 0) {
1349 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1356 static char *get_pulse_home(void) {
1361 if (!(h
= pa_get_home_dir_malloc())) {
1362 pa_log_error("Failed to get home directory.");
1366 if (stat(h
, &st
) < 0) {
1367 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1372 if (st
.st_uid
!= getuid()) {
1373 pa_log_error("Home directory %s not ours.", h
);
1379 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1387 char *pa_get_state_dir(void) {
1390 /* The state directory shall contain dynamic data that should be
1391 * kept across reboots, and is private to this user */
1393 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1394 if (!(d
= get_pulse_home()))
1397 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1398 * dir then this will break. */
1400 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1401 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1409 char *pa_get_home_dir_malloc(void) {
1411 size_t allocated
= 128;
1414 homedir
= pa_xmalloc(allocated
);
1416 if (!pa_get_home_dir(homedir
, allocated
)) {
1421 if (strlen(homedir
) < allocated
- 1)
1431 char *pa_get_binary_name_malloc(void) {
1433 size_t allocated
= 128;
1436 t
= pa_xmalloc(allocated
);
1438 if (!pa_get_binary_name(t
, allocated
)) {
1443 if (strlen(t
) < allocated
- 1)
1453 static char* make_random_dir(mode_t m
) {
1454 static const char table
[] =
1455 "abcdefghijklmnopqrstuvwxyz"
1456 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1462 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1463 pathlen
= strlen(fn
);
1471 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1472 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1474 u
= umask((~m
) & 0777);
1481 saved_errno
= errno
;
1483 errno
= saved_errno
;
1488 if (errno
!= EEXIST
) {
1489 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1496 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1499 if (!(p
= make_random_dir(m
)))
1503 if (symlink(p
, k
) < 0) {
1504 int saved_errno
= errno
;
1506 if (errno
!= EEXIST
)
1507 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1512 errno
= saved_errno
;
1524 char *pa_get_runtime_dir(void) {
1525 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1529 /* The runtime directory shall contain dynamic data that needs NOT
1530 * to be kept accross reboots and is usuallly private to the user,
1531 * except in system mode, where it might be accessible by other
1532 * users, too. Since we need POSIX locking and UNIX sockets in
1533 * this directory, we link it to a random subdir in /tmp, if it
1534 * was not explicitly configured. */
1536 m
= pa_in_system_mode() ? 0755U : 0700U;
1538 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1540 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1541 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1545 return pa_xstrdup(d
);
1548 if (!(d
= get_pulse_home()))
1551 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1552 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1557 if (!(mid
= pa_machine_id())) {
1562 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1567 /* OK, first let's check if the "runtime" symlink is already
1570 if (!(p
= pa_readlink(k
))) {
1572 if (errno
!= ENOENT
) {
1573 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1578 /* Hmm, so the runtime directory didn't exist yet, so let's
1579 * create one in /tmp and symlink that to it */
1581 if (make_random_dir_and_link(0700, k
) < 0) {
1583 /* Mhmm, maybe another process was quicker than us,
1584 * let's check if that was valid */
1585 if (errno
== EEXIST
)
1591 /* No symlink possible, so let's just create the runtime directly */
1599 /* Make sure that this actually makes sense */
1600 if (!pa_is_path_absolute(p
)) {
1601 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1606 /* Hmm, so this symlink is still around, make sure nobody fools
1610 if (lstat(p
, &st
) < 0) {
1612 if (errno
!= ENOENT
) {
1613 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1619 if (S_ISDIR(st
.st_mode
) &&
1620 (st
.st_uid
== getuid()) &&
1621 ((st
.st_mode
& 0777) == 0700)) {
1627 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1634 /* Hmm, so the link points to some nonexisting or invalid
1635 * dir. Let's replace it by a new link. We first create a
1636 * temporary link and then rename that to allow concurrent
1637 * execution of this function. */
1639 t
= pa_sprintf_malloc("%s.tmp", k
);
1641 if (make_random_dir_and_link(0700, t
) < 0) {
1643 if (errno
!= EEXIST
) {
1644 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1651 /* Hmm, someone lese was quicker then us. Let's give
1652 * him some time to finish, and retry. */
1657 /* OK, we succeeded in creating the temporary symlink, so
1658 * let's rename it */
1659 if (rename(t
, k
) < 0) {
1660 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1676 /* Try to open a configuration file. If "env" is specified, open the
1677 * value of the specified environment variable. Otherwise look for a
1678 * file "local" in the home directory or a file "global" in global
1679 * file system. If "result" is non-NULL, a pointer to a newly
1680 * allocated buffer containing the used configuration file is
1682 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1686 if (env
&& (fn
= getenv(env
))) {
1687 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1689 *result
= pa_xstrdup(fn
);
1694 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1703 if ((e
= getenv("PULSE_CONFIG_PATH")))
1704 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1705 else if ((h
= pa_get_home_dir_malloc())) {
1706 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1711 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1713 *result
= pa_xstrdup(fn
);
1719 if (errno
!= ENOENT
) {
1720 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1732 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1733 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1734 pa_win32_get_toplevel(NULL
),
1735 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1738 gfn
= pa_xstrdup(global
);
1740 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1755 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1758 if (env
&& (fn
= getenv(env
))) {
1759 if (access(fn
, R_OK
) == 0)
1760 return pa_xstrdup(fn
);
1762 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1771 if ((e
= getenv("PULSE_CONFIG_PATH")))
1772 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1773 else if ((h
= pa_get_home_dir_malloc())) {
1774 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1779 if (access(fn
, R_OK
) == 0) {
1780 char *r
= pa_xstrdup(fn
);
1785 if (errno
!= ENOENT
) {
1786 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1798 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1799 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1800 pa_win32_get_toplevel(NULL
),
1801 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1804 gfn
= pa_xstrdup(global
);
1806 if (access(gfn
, R_OK
) == 0)
1816 /* Format the specified data as a hexademical string */
1817 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1818 size_t i
= 0, j
= 0;
1819 const char hex
[] = "0123456789abcdef";
1823 pa_assert(slength
> 0);
1825 while (i
< dlength
&& j
+3 <= slength
) {
1826 s
[j
++] = hex
[*d
>> 4];
1827 s
[j
++] = hex
[*d
& 0xF];
1833 s
[j
< slength
? j
: slength
] = 0;
1837 /* Convert a hexadecimal digit to a number or -1 if invalid */
1838 static int hexc(char c
) {
1839 if (c
>= '0' && c
<= '9')
1842 if (c
>= 'A' && c
<= 'F')
1843 return c
- 'A' + 10;
1845 if (c
>= 'a' && c
<= 'f')
1846 return c
- 'a' + 10;
1852 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1853 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1859 while (j
< dlength
&& *p
) {
1862 if ((b
= hexc(*(p
++))) < 0)
1865 d
[j
] = (uint8_t) (b
<< 4);
1870 if ((b
= hexc(*(p
++))) < 0)
1873 d
[j
] |= (uint8_t) b
;
1880 /* Returns nonzero when *s starts with *pfx */
1881 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1889 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1892 /* Returns nonzero when *s ends with *sfx */
1893 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1902 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1905 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1911 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1915 char *pa_make_path_absolute(const char *p
) {
1921 if (pa_is_path_absolute(p
))
1922 return pa_xstrdup(p
);
1924 if (!(cwd
= pa_getcwd()))
1925 return pa_xstrdup(p
);
1927 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1932 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1933 * if fn is non-null and starts with / return fn
1934 * otherwise append fn to the run time path and return it */
1935 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1938 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1943 if (pa_is_path_absolute(fn
))
1944 return pa_xstrdup(fn
);
1952 if (!(mid
= pa_machine_id())) {
1957 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1960 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
1968 char *pa_runtime_path(const char *fn
) {
1969 return get_path(fn
, FALSE
, TRUE
);
1972 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
1973 return get_path(fn
, appendmid
, FALSE
);
1976 /* Convert the string s to a signed integer in *ret_i */
1977 int pa_atoi(const char *s
, int32_t *ret_i
) {
1985 l
= strtol(s
, &x
, 0);
1987 if (!x
|| *x
|| errno
) {
1993 if ((int32_t) l
!= l
) {
1998 *ret_i
= (int32_t) l
;
2003 /* Convert the string s to an unsigned integer in *ret_u */
2004 int pa_atou(const char *s
, uint32_t *ret_u
) {
2012 l
= strtoul(s
, &x
, 0);
2014 if (!x
|| *x
|| errno
) {
2020 if ((uint32_t) l
!= l
) {
2025 *ret_u
= (uint32_t) l
;
2030 #ifdef HAVE_STRTOF_L
2031 static locale_t c_locale
= NULL
;
2033 static void c_locale_destroy(void) {
2034 freelocale(c_locale
);
2038 int pa_atod(const char *s
, double *ret_d
) {
2045 /* This should be locale independent */
2047 #ifdef HAVE_STRTOF_L
2051 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2052 atexit(c_locale_destroy
);
2058 f
= strtod_l(s
, &x
, c_locale
);
2066 if (!x
|| *x
|| errno
) {
2077 /* Same as snprintf, but guarantees NUL-termination on every platform */
2078 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2083 pa_assert(size
> 0);
2086 va_start(ap
, format
);
2087 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2093 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2094 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2098 pa_assert(size
> 0);
2101 ret
= vsnprintf(str
, size
, format
, ap
);
2108 if ((size_t) ret
> size
-1)
2111 return (size_t) ret
;
2114 /* Truncate the specified string, but guarantee that the string
2115 * returned still validates as UTF8 */
2116 char *pa_truncate_utf8(char *c
, size_t l
) {
2118 pa_assert(pa_utf8_valid(c
));
2125 while (l
> 0 && !pa_utf8_valid(c
))
2131 char *pa_getcwd(void) {
2135 char *p
= pa_xmalloc(l
);
2139 if (errno
!= ERANGE
)
2147 void *pa_will_need(const void *p
, size_t l
) {
2148 #ifdef RLIMIT_MEMLOCK
2159 a
= PA_PAGE_ALIGN_PTR(p
);
2160 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2162 #ifdef HAVE_POSIX_MADVISE
2163 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2164 pa_log_debug("posix_madvise() worked fine!");
2169 /* Most likely the memory was not mmap()ed from a file and thus
2170 * madvise() didn't work, so let's misuse mlock() do page this
2171 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2172 * inviting, the man page of mlock() tells us: "All pages that
2173 * contain a part of the specified address range are guaranteed to
2174 * be resident in RAM when the call returns successfully." */
2176 #ifdef RLIMIT_MEMLOCK
2177 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2179 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2180 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
));
2185 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2187 bs
= PA_PAGE_SIZE
*4;
2190 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2193 while (size
> 0 && bs
> 0) {
2198 if (mlock(a
, bs
) < 0) {
2199 bs
= PA_PAGE_ALIGN(bs
/ 2);
2203 pa_assert_se(munlock(a
, bs
) == 0);
2205 a
= (const uint8_t*) a
+ bs
;
2211 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2213 pa_log_debug("mlock() worked fine!");
2218 void pa_close_pipe(int fds
[2]) {
2222 pa_assert_se(pa_close(fds
[0]) == 0);
2225 pa_assert_se(pa_close(fds
[1]) == 0);
2227 fds
[0] = fds
[1] = -1;
2230 char *pa_readlink(const char *p
) {
2231 #ifdef HAVE_READLINK
2240 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2245 if ((size_t) n
< l
-1) {
2258 int pa_close_all(int except_fd
, ...) {
2263 va_start(ap
, except_fd
);
2266 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2271 p
= pa_xnew(int, n
+1);
2273 va_start(ap
, except_fd
);
2276 if (except_fd
>= 0) {
2280 while ((fd
= va_arg(ap
, int)) >= 0)
2287 r
= pa_close_allv(p
);
2293 int pa_close_allv(const int except_fds
[]) {
2302 if ((d
= opendir("/proc/self/fd"))) {
2306 while ((de
= readdir(d
))) {
2312 if (de
->d_name
[0] == '.')
2316 l
= strtol(de
->d_name
, &e
, 10);
2317 if (errno
!= 0 || !e
|| *e
) {
2325 if ((long) fd
!= l
) {
2338 for (i
= 0; except_fds
[i
] >= 0; i
++)
2339 if (except_fds
[i
] == fd
) {
2347 if (pa_close(fd
) < 0) {
2348 saved_errno
= errno
;
2350 errno
= saved_errno
;
2362 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2363 maxfd
= (int) rl
.rlim_max
;
2365 maxfd
= sysconf(_SC_OPEN_MAX
);
2367 for (fd
= 3; fd
< maxfd
; fd
++) {
2372 for (i
= 0; except_fds
[i
] >= 0; i
++)
2373 if (except_fds
[i
] == fd
) {
2381 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2384 #endif /* !OS_IS_WIN32 */
2389 int pa_unblock_sigs(int except
, ...) {
2394 va_start(ap
, except
);
2397 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2402 p
= pa_xnew(int, n
+1);
2404 va_start(ap
, except
);
2411 while ((sig
= va_arg(ap
, int)) >= 0)
2418 r
= pa_unblock_sigsv(p
);
2424 int pa_unblock_sigsv(const int except
[]) {
2429 if (sigemptyset(&ss
) < 0)
2432 for (i
= 0; except
[i
] > 0; i
++)
2433 if (sigaddset(&ss
, except
[i
]) < 0)
2436 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2442 int pa_reset_sigs(int except
, ...) {
2447 va_start(ap
, except
);
2450 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2455 p
= pa_xnew(int, n
+1);
2457 va_start(ap
, except
);
2464 while ((sig
= va_arg(ap
, int)) >= 0)
2471 r
= pa_reset_sigsv(p
);
2477 int pa_reset_sigsv(const int except
[]) {
2481 for (sig
= 1; sig
< NSIG
; sig
++) {
2482 pa_bool_t reset
= TRUE
;
2493 for (i
= 0; except
[i
] > 0; i
++) {
2494 if (sig
== except
[i
]) {
2503 struct sigaction sa
;
2505 memset(&sa
, 0, sizeof(sa
));
2506 sa
.sa_handler
= SIG_DFL
;
2508 /* On Linux the first two RT signals are reserved by
2509 * glibc, and sigaction() will return EINVAL for them. */
2510 if ((sigaction(sig
, &sa
, NULL
) < 0))
2511 if (errno
!= EINVAL
)
2520 void pa_set_env(const char *key
, const char *value
) {
2524 /* This is not thread-safe */
2527 SetEnvironmentVariable(key
, value
);
2529 setenv(key
, value
, 1);
2533 void pa_set_env_and_record(const char *key
, const char *value
) {
2537 /* This is not thread-safe */
2539 pa_set_env(key
, value
);
2540 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2543 void pa_unset_env_recorded(void) {
2545 /* This is not thread-safe */
2550 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2556 SetEnvironmentVariable(s
, NULL
);
2564 pa_bool_t
pa_in_system_mode(void) {
2567 if (!(e
= getenv("PULSE_SYSTEM")))
2573 char *pa_get_user_name_malloc(void) {
2577 #ifdef _SC_LOGIN_NAME_MAX
2578 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2584 u
= pa_xnew(char, k
+1);
2586 if (!(pa_get_user_name(u
, k
))) {
2594 char *pa_get_host_name_malloc(void) {
2603 if (!pa_get_host_name(c
, l
)) {
2605 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2608 } else if (strlen(c
) < l
-1) {
2616 u
= pa_utf8_filter(c
);
2621 /* Hmm, the hostname is as long the space we offered the
2622 * function, we cannot know if it fully fit in, so let's play
2623 * safe and retry. */
2632 char *pa_machine_id(void) {
2636 /* The returned value is supposed be some kind of ascii identifier
2637 * that is unique and stable across reboots. */
2639 /* First we try the D-Bus UUID, which is the best option we have,
2640 * since it fits perfectly our needs and is not as volatile as the
2641 * hostname which might be set from dhcp. */
2643 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2644 char ln
[34] = "", *r
;
2646 r
= fgets(ln
, sizeof(ln
)-1, f
);
2652 return pa_utf8_filter(ln
);
2655 if ((h
= pa_get_host_name_malloc()))
2659 /* If no hostname was set we use the POSIX hostid. It's usually
2660 * the IPv4 address. Might not be that stable. */
2661 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2667 char *pa_session_id(void) {
2670 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2673 return pa_utf8_filter(e
);
2676 char *pa_uname_string(void) {
2680 pa_assert_se(uname(&u
) >= 0);
2682 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2688 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2689 pa_assert_se(GetVersionEx(&i
));
2691 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2695 #ifdef HAVE_VALGRIND_MEMCHECK_H
2696 pa_bool_t
pa_in_valgrind(void) {
2699 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2700 * here instead of really checking whether we run in valgrind or
2704 b
= getenv("VALGRIND") ? 2 : 1;
2710 unsigned pa_gcd(unsigned a
, unsigned b
) {
2721 void pa_reduce(unsigned *num
, unsigned *den
) {
2723 unsigned gcd
= pa_gcd(*num
, *den
);
2731 pa_assert(pa_gcd(*num
, *den
) == 1);
2734 unsigned pa_ncpus(void) {
2737 #ifdef _SC_NPROCESSORS_CONF
2738 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2743 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2746 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2755 sb
= pa_strbuf_new();
2760 if (!(p
= strstr(s
, a
)))
2763 pa_strbuf_putsn(sb
, s
, p
-s
);
2764 pa_strbuf_puts(sb
, b
);
2768 pa_strbuf_puts(sb
, s
);
2770 return pa_strbuf_tostring_free(sb
);
2773 char *pa_escape(const char *p
, const char *chars
) {
2776 pa_strbuf
*buf
= pa_strbuf_new();
2778 for (s
= p
; *s
; ++s
) {
2780 pa_strbuf_putc(buf
, '\\');
2782 for (c
= chars
; *c
; ++c
) {
2784 pa_strbuf_putc(buf
, '\\');
2789 pa_strbuf_putc(buf
, *s
);
2792 return pa_strbuf_tostring_free(buf
);
2795 char *pa_unescape(char *p
) {
2797 pa_bool_t escaped
= FALSE
;
2799 for (s
= p
, d
= p
; *s
; s
++) {
2800 if (!escaped
&& *s
== '\\') {
2814 char *pa_realpath(const char *path
) {
2818 /* We want only abolsute paths */
2819 if (path
[0] != '/') {
2824 #if defined(__GLIBC__) || defined(__APPLE__)
2828 if (!(r
= realpath(path
, NULL
)))
2831 /* We copy this here in case our pa_xmalloc() is not
2832 * implemented on top of libc malloc() */
2836 #elif defined(PATH_MAX)
2839 path_buf
= pa_xmalloc(PATH_MAX
);
2841 #if defined(OS_IS_WIN32)
2842 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2847 if (!(t
= realpath(path
, path_buf
))) {
2854 #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."
2860 void pa_disable_sigpipe(void) {
2863 struct sigaction sa
;
2867 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2868 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2872 sa
.sa_handler
= SIG_IGN
;
2874 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2875 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2881 void pa_xfreev(void**a
) {
2887 for (p
= a
; *p
; p
++)
2893 char **pa_split_spaces_strv(const char *s
) {
2895 unsigned i
= 0, n
= 8;
2896 const char *state
= NULL
;
2898 t
= pa_xnew(char*, n
);
2899 while ((e
= pa_split_spaces(s
, &state
))) {
2904 t
= pa_xrenew(char*, t
, n
);
2917 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2920 if (pa_is_path_absolute(path
))
2921 return pa_xstrdup(path
);
2923 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2926 size_t pa_pipe_buf(int fd
) {
2931 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2942 void pa_reset_personality(void) {
2945 if (personality(PER_LINUX
) < 0)
2946 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2951 #if defined(__linux__) && !defined(__OPTIMIZE__)
2953 pa_bool_t
pa_run_from_build_tree(void) {
2955 pa_bool_t b
= FALSE
;
2957 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2960 if ((rp
= pa_readlink("/proc/self/exe"))) {
2961 b
= pa_startswith(rp
, PA_BUILDDIR
);
2970 const char *pa_get_temp_dir(void) {
2973 if ((t
= getenv("TMPDIR")) &&
2974 pa_is_path_absolute(t
))
2977 if ((t
= getenv("TMP")) &&
2978 pa_is_path_absolute(t
))
2981 if ((t
= getenv("TEMP")) &&
2982 pa_is_path_absolute(t
))
2985 if ((t
= getenv("TEMPDIR")) &&
2986 pa_is_path_absolute(t
))
2992 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3000 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3003 if (errno
!= EINVAL
)
3007 if ((fd
= open(fn
, flags
, mode
)) < 0)
3011 /* Some implementations might simply ignore O_CLOEXEC if it is not
3012 * understood, make sure FD_CLOEXEC is enabled anyway */
3014 pa_make_fd_cloexec(fd
);
3018 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3022 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3025 if (errno
!= EINVAL
)
3029 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3033 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3034 * not understood, make sure FD_CLOEXEC is enabled anyway */
3036 pa_make_fd_cloexec(fd
);
3040 int pa_pipe_cloexec(int pipefd
[2]) {
3044 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3047 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3052 if ((r
= pipe(pipefd
)) < 0)
3056 pa_make_fd_cloexec(pipefd
[0]);
3057 pa_make_fd_cloexec(pipefd
[1]);
3062 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3066 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3069 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3074 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3078 pa_make_fd_cloexec(fd
);
3082 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3086 m
= pa_sprintf_malloc("%se", mode
);
3089 if ((f
= fopen(path
, m
))) {
3096 if (errno
!= EINVAL
)
3099 if (!(f
= fopen(path
, mode
)))
3103 pa_make_fd_cloexec(fileno(f
));
3107 void pa_nullify_stdfds(void) {
3110 pa_close(STDIN_FILENO
);
3111 pa_close(STDOUT_FILENO
);
3112 pa_close(STDERR_FILENO
);
3114 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3115 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3116 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3123 char *pa_read_line_from_file(const char *fn
) {
3125 char ln
[256] = "", *r
;
3127 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3130 r
= fgets(ln
, sizeof(ln
)-1, f
);
3139 return pa_xstrdup(ln
);
3142 pa_bool_t
pa_running_in_vm(void) {
3144 #if defined(__i386__) || defined(__x86_64__)
3146 /* Both CPUID and DMI are x86 specific interfaces... */
3148 uint32_t eax
= 0x40000000;
3155 const char *const dmi_vendors
[] = {
3156 "/sys/class/dmi/id/sys_vendor",
3157 "/sys/class/dmi/id/board_vendor",
3158 "/sys/class/dmi/id/bios_vendor"
3163 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3166 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3168 if (pa_startswith(s
, "QEMU") ||
3169 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3170 pa_startswith(s
, "VMware") ||
3171 pa_startswith(s
, "VMW") ||
3172 pa_startswith(s
, "Microsoft Corporation") ||
3173 pa_startswith(s
, "innotek GmbH") ||
3174 pa_startswith(s
, "Xen")) {
3186 /* http://lwn.net/Articles/301888/ */
3189 __asm__
__volatile__ (
3190 /* ebx/rbx is being used for PIC! */
3191 " push %%"PA_REG_b
" \n\t"
3193 " mov %%ebx, %1 \n\t"
3194 " pop %%"PA_REG_b
" \n\t"
3196 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3200 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3201 pa_streq(sig
.text
, "KVMKVMKVM") ||
3202 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3203 pa_streq(sig
.text
, "VMwareVMware") ||
3204 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3205 pa_streq(sig
.text
, "Microsoft Hv"))