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 if (fchown(fd
, uid
, gid
) < 0)
271 (void) fchmod(fd
, m
);
274 pa_assert_se(pa_close(fd
) >= 0);
278 if (lstat(dir
, &st
) < 0)
280 if (stat(dir
, &st
) < 0)
285 if (!S_ISDIR(st
.st_mode
) ||
286 (st
.st_uid
!= uid
) ||
287 (st
.st_gid
!= gid
) ||
288 ((st
.st_mode
& 0777) != m
)) {
293 pa_log_warn("Secure directory creation not supported on Win32.");
306 /* Return a newly allocated sting containing the parent directory of the specified file */
307 char *pa_parent_dir(const char *fn
) {
308 char *slash
, *dir
= pa_xstrdup(fn
);
310 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
320 /* Creates a the parent directory of the specified path securely */
321 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
325 if (!(dir
= pa_parent_dir(fn
)))
328 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
338 /** Platform independent read function. Necessary since not all
339 * systems treat all file descriptors equal. If type is
340 * non-NULL it is used to cache the type of the fd. This is
341 * useful for making sure that only a single syscall is executed per
342 * function call. The variable pointed to should be initialized to 0
344 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
348 if (!type
|| *type
== 0) {
351 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
354 if (WSAGetLastError() != WSAENOTSOCK
) {
355 errno
= WSAGetLastError();
368 if ((r
= read(fd
, buf
, count
)) < 0)
376 /** Similar to pa_read(), but handles writes */
377 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
379 if (!type
|| *type
== 0) {
383 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
395 if (WSAGetLastError() != WSAENOTSOCK
) {
396 errno
= WSAGetLastError();
400 if (errno
!= ENOTSOCK
)
411 if ((r
= write(fd
, buf
, count
)) < 0)
419 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
420 * unless EOF is reached or an error occurred */
421 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
437 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
444 data
= (uint8_t*) data
+ r
;
451 /** Similar to pa_loop_read(), but wraps write() */
452 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
468 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
475 data
= (const uint8_t*) data
+ r
;
482 /** Platform independent read function. Necessary since not all
483 * systems treat all file descriptors equal. */
484 int pa_close(int fd
) {
489 if ((ret
= closesocket(fd
)) == 0)
492 if (WSAGetLastError() != WSAENOTSOCK
) {
493 errno
= WSAGetLastError();
501 if ((r
= close(fd
)) < 0)
509 /* Print a warning messages in case that the given signal is not
510 * blocked or trapped */
511 void pa_check_signal_is_blocked(int sig
) {
512 #ifdef HAVE_SIGACTION
516 /* If POSIX threads are supported use thread-aware
517 * pthread_sigmask() function, to check if the signal is
518 * blocked. Otherwise fall back to sigprocmask() */
521 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
523 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
524 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
531 if (sigismember(&set
, sig
))
534 /* Check whether the signal is trapped */
536 if (sigaction(sig
, NULL
, &sa
) < 0) {
537 pa_log("sigaction(): %s", pa_cstrerror(errno
));
541 if (sa
.sa_handler
!= SIG_DFL
)
544 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
545 #else /* HAVE_SIGACTION */
546 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
550 /* The following function is based on an example from the GNU libc
551 * documentation. This function is similar to GNU's asprintf(). */
552 char *pa_sprintf_malloc(const char *format
, ...) {
562 c
= pa_xrealloc(c
, size
);
564 va_start(ap
, format
);
565 r
= vsnprintf(c
, size
, format
, ap
);
570 if (r
> -1 && (size_t) r
< size
)
573 if (r
> -1) /* glibc 2.1 */
580 /* Same as the previous function, but use a va_list instead of an
582 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
592 c
= pa_xrealloc(c
, size
);
595 r
= vsnprintf(c
, size
, format
, aq
);
600 if (r
> -1 && (size_t) r
< size
)
603 if (r
> -1) /* glibc 2.1 */
610 /* Similar to OpenBSD's strlcpy() function */
611 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
629 #ifdef _POSIX_PRIORITY_SCHEDULING
630 static int set_scheduler(int rtprio
) {
632 struct sched_param sp
;
638 dbus_error_init(&error
);
642 sp
.sched_priority
= rtprio
;
644 #ifdef SCHED_RESET_ON_FORK
645 if (pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
) == 0) {
646 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
651 if (pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
) == 0) {
652 pa_log_debug("SCHED_RR worked.");
655 #endif /* HAVE_SCHED_H */
658 /* Try to talk to RealtimeKit */
660 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
661 pa_log("Failed to connect to system bus: %s\n", error
.message
);
662 dbus_error_free(&error
);
667 /* We need to disable exit on disconnect because otherwise
668 * dbus_shutdown will kill us. See
669 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
670 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
672 r
= rtkit_make_realtime(bus
, 0, rtprio
);
673 dbus_connection_unref(bus
);
676 pa_log_debug("RealtimeKit worked.");
689 /* Make the current thread a realtime thread, and acquire the highest
690 * rtprio we can get that is less or equal the specified parameter. If
691 * the thread is already realtime, don't do anything. */
692 int pa_make_realtime(int rtprio
) {
694 #ifdef _POSIX_PRIORITY_SCHEDULING
697 if (set_scheduler(rtprio
) >= 0) {
698 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
702 for (p
= rtprio
-1; p
>= 1; p
--)
703 if (set_scheduler(p
) >= 0) {
704 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
707 #elif defined(OS_IS_WIN32)
708 /* Windows only allows realtime scheduling to be set on a per process basis.
709 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
710 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
)) {
711 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
715 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
720 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
724 #ifdef HAVE_SYS_RESOURCE_H
725 static int set_nice(int nice_level
) {
731 dbus_error_init(&error
);
734 #ifdef HAVE_SYS_RESOURCE_H
735 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
736 pa_log_debug("setpriority() worked.");
742 /* Try to talk to RealtimeKit */
744 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
745 pa_log("Failed to connect to system bus: %s\n", error
.message
);
746 dbus_error_free(&error
);
751 /* We need to disable exit on disconnect because otherwise
752 * dbus_shutdown will kill us. See
753 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
754 dbus_connection_set_exit_on_disconnect(bus
, FALSE
);
756 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
757 dbus_connection_unref(bus
);
760 pa_log_debug("RealtimeKit worked.");
771 /* Raise the priority of the current process as much as possible that
772 * is <= the specified nice level..*/
773 int pa_raise_priority(int nice_level
) {
775 #ifdef HAVE_SYS_RESOURCE_H
778 if (set_nice(nice_level
) >= 0) {
779 pa_log_info("Successfully gained nice level %i.", nice_level
);
783 for (n
= nice_level
+1; n
< 0; n
++)
784 if (set_nice(n
) >= 0) {
785 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
789 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
794 if (nice_level
< 0) {
795 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
796 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
801 pa_log_info("Successfully gained high priority class.");
808 /* Reset the priority to normal, inverting the changes made by
809 * pa_raise_priority() and pa_make_realtime()*/
810 void pa_reset_priority(void) {
811 #ifdef HAVE_SYS_RESOURCE_H
812 struct sched_param sp
;
814 setpriority(PRIO_PROCESS
, 0, 0);
817 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
821 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
825 int pa_match(const char *expr
, const char *v
) {
830 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
835 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
837 else if (k
== REG_NOMATCH
)
850 /* Try to parse a boolean string value.*/
851 int pa_parse_boolean(const char *v
) {
855 /* First we check language independant */
856 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
858 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
861 #ifdef HAVE_LANGINFO_H
862 /* And then we check language dependant */
863 if ((expr
= nl_langinfo(YESEXPR
)))
865 if (pa_match(expr
, v
) > 0)
868 if ((expr
= nl_langinfo(NOEXPR
)))
870 if (pa_match(expr
, v
) > 0)
878 /* Split the specified string wherever one of the strings in delimiter
879 * occurs. Each time it is called returns a newly allocated string
880 * with pa_xmalloc(). The variable state points to, should be
881 * initiallized to NULL before the first call. */
882 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
883 const char *current
= *state
? *state
: c
;
889 l
= strcspn(current
, delimiter
);
895 return pa_xstrndup(current
, l
);
898 /* Split a string into words. Otherwise similar to pa_split(). */
899 char *pa_split_spaces(const char *c
, const char **state
) {
900 const char *current
= *state
? *state
: c
;
903 if (!*current
|| *c
== 0)
906 current
+= strspn(current
, WHITESPACE
);
907 l
= strcspn(current
, WHITESPACE
);
911 return pa_xstrndup(current
, l
);
914 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
916 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
917 const char *pa_sig2str(int sig
) {
930 char buf
[SIG2STR_MAX
];
932 if (sig2str(sig
, buf
) == 0) {
933 pa_xfree(PA_STATIC_TLS_GET(signame
));
934 t
= pa_sprintf_malloc("SIG%s", buf
);
935 PA_STATIC_TLS_SET(signame
, t
);
943 case SIGHUP
: return "SIGHUP";
945 case SIGINT
: return "SIGINT";
947 case SIGQUIT
: return "SIGQUIT";
949 case SIGILL
: return "SIGULL";
951 case SIGTRAP
: return "SIGTRAP";
953 case SIGABRT
: return "SIGABRT";
955 case SIGBUS
: return "SIGBUS";
957 case SIGFPE
: return "SIGFPE";
959 case SIGKILL
: return "SIGKILL";
962 case SIGUSR1
: return "SIGUSR1";
964 case SIGSEGV
: return "SIGSEGV";
966 case SIGUSR2
: return "SIGUSR2";
969 case SIGPIPE
: return "SIGPIPE";
972 case SIGALRM
: return "SIGALRM";
974 case SIGTERM
: return "SIGTERM";
976 case SIGSTKFLT
: return "SIGSTKFLT";
979 case SIGCHLD
: return "SIGCHLD";
982 case SIGCONT
: return "SIGCONT";
985 case SIGSTOP
: return "SIGSTOP";
988 case SIGTSTP
: return "SIGTSTP";
991 case SIGTTIN
: return "SIGTTIN";
994 case SIGTTOU
: return "SIGTTOU";
997 case SIGURG
: return "SIGURG";
1000 case SIGXCPU
: return "SIGXCPU";
1003 case SIGXFSZ
: return "SIGXFSZ";
1006 case SIGVTALRM
: return "SIGVTALRM";
1009 case SIGPROF
: return "SIGPROF";
1012 case SIGWINCH
: return "SIGWINCH";
1015 case SIGIO
: return "SIGIO";
1018 case SIGPWR
: return "SIGPWR";
1021 case SIGSYS
: return "SIGSYS";
1026 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
1027 pa_xfree(PA_STATIC_TLS_GET(signame
));
1028 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
1029 PA_STATIC_TLS_SET(signame
, t
);
1038 pa_xfree(PA_STATIC_TLS_GET(signame
));
1039 t
= pa_sprintf_malloc("SIG%i", sig
);
1040 PA_STATIC_TLS_SET(signame
, t
);
1046 /* Check whether the specified GID and the group name match */
1047 static int is_group(gid_t gid
, const char *name
) {
1048 struct group
*group
= NULL
;
1052 if (!(group
= pa_getgrgid_malloc(gid
))) {
1056 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
1061 r
= strcmp(name
, group
->gr_name
) == 0;
1064 pa_getgrgid_free(group
);
1069 /* Check the current user is member of the specified group */
1070 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1071 GETGROUPS_T
*gids
, tgid
;
1072 long n
= sysconf(_SC_NGROUPS_MAX
);
1077 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1079 if ((n
= getgroups((int) n
, gids
)) < 0) {
1080 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1084 for (i
= 0; i
< n
; i
++) {
1086 if ((k
= is_group(gids
[i
], name
)) < 0)
1095 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1111 /* Check whether the specifc user id is a member of the specified group */
1112 int pa_uid_in_group(uid_t uid
, const char *name
) {
1113 struct group
*group
= NULL
;
1118 if (!(group
= pa_getgrnam_malloc(name
))) {
1125 for (i
= group
->gr_mem
; *i
; i
++) {
1126 struct passwd
*pw
= NULL
;
1129 if (!(pw
= pa_getpwnam_malloc(*i
)))
1132 if (pw
->pw_uid
== uid
)
1135 pa_getpwnam_free(pw
);
1142 pa_getgrnam_free(group
);
1147 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1148 gid_t
pa_get_gid_of_group(const char *name
) {
1149 gid_t ret
= (gid_t
) -1;
1150 struct group
*gr
= NULL
;
1153 if (!(gr
= pa_getgrnam_malloc(name
))) {
1162 pa_getgrnam_free(gr
);
1166 int pa_check_in_group(gid_t g
) {
1167 gid_t gids
[NGROUPS_MAX
];
1170 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1180 #else /* HAVE_GRP_H */
1182 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1188 int pa_uid_in_group(uid_t uid
, const char *name
) {
1193 gid_t
pa_get_gid_of_group(const char *name
) {
1198 int pa_check_in_group(gid_t g
) {
1205 /* Lock or unlock a file entirely.
1206 (advisory on UNIX, mandatory on Windows) */
1207 int pa_lock_fd(int fd
, int b
) {
1209 struct flock f_lock
;
1211 /* Try a R/W lock first */
1213 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1214 f_lock
.l_whence
= SEEK_SET
;
1218 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1221 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1222 if (b
&& errno
== EBADF
) {
1223 f_lock
.l_type
= F_RDLCK
;
1224 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1228 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1232 HANDLE h
= (HANDLE
) _get_osfhandle(fd
);
1234 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1236 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1239 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1241 /* FIXME: Needs to set errno! */
1247 /* Remove trailing newlines from a string */
1248 char* pa_strip_nl(char *s
) {
1251 s
[strcspn(s
, NEWLINE
)] = 0;
1255 char *pa_strip(char *s
) {
1258 /* Drops trailing whitespace. Modifies the string in
1259 * place. Returns pointer to first non-space character */
1261 s
+= strspn(s
, WHITESPACE
);
1263 for (e
= s
; *e
; e
++)
1264 if (!strchr(WHITESPACE
, *e
))
1275 /* Create a temporary lock file and lock it. */
1276 int pa_lock_lockfile(const char *fn
) {
1283 if ((fd
= pa_open_cloexec(fn
, O_CREAT
|O_RDWR
1287 , S_IRUSR
|S_IWUSR
)) < 0) {
1288 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1292 if (pa_lock_fd(fd
, 1) < 0) {
1293 pa_log_warn("Failed to lock file '%s'.", fn
);
1297 if (fstat(fd
, &st
) < 0) {
1298 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1302 /* Check whether the file has been removed meanwhile. When yes,
1303 * restart this loop, otherwise, we're done */
1304 if (st
.st_nlink
>= 1)
1307 if (pa_lock_fd(fd
, 0) < 0) {
1308 pa_log_warn("Failed to unlock file '%s'.", fn
);
1312 if (pa_close(fd
) < 0) {
1313 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1324 int saved_errno
= errno
;
1326 errno
= saved_errno
;
1332 /* Unlock a temporary lcok file */
1333 int pa_unlock_lockfile(const char *fn
, int fd
) {
1338 if (unlink(fn
) < 0) {
1339 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1344 if (pa_lock_fd(fd
, 0) < 0) {
1345 pa_log_warn("Failed to unlock file '%s'.", fn
);
1349 if (pa_close(fd
) < 0) {
1350 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1357 static char *get_pulse_home(void) {
1362 if (!(h
= pa_get_home_dir_malloc())) {
1363 pa_log_error("Failed to get home directory.");
1367 if (stat(h
, &st
) < 0) {
1368 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1373 if (st
.st_uid
!= getuid()) {
1374 pa_log_error("Home directory %s not ours.", h
);
1380 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1388 char *pa_get_state_dir(void) {
1391 /* The state directory shall contain dynamic data that should be
1392 * kept across reboots, and is private to this user */
1394 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1395 if (!(d
= get_pulse_home()))
1398 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1399 * dir then this will break. */
1401 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1402 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1410 char *pa_get_home_dir_malloc(void) {
1412 size_t allocated
= 128;
1415 homedir
= pa_xmalloc(allocated
);
1417 if (!pa_get_home_dir(homedir
, allocated
)) {
1422 if (strlen(homedir
) < allocated
- 1)
1432 char *pa_get_binary_name_malloc(void) {
1434 size_t allocated
= 128;
1437 t
= pa_xmalloc(allocated
);
1439 if (!pa_get_binary_name(t
, allocated
)) {
1444 if (strlen(t
) < allocated
- 1)
1454 static char* make_random_dir(mode_t m
) {
1455 static const char table
[] =
1456 "abcdefghijklmnopqrstuvwxyz"
1457 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1463 fn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1464 pathlen
= strlen(fn
);
1472 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1473 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1475 u
= umask((~m
) & 0777);
1482 saved_errno
= errno
;
1484 errno
= saved_errno
;
1489 if (errno
!= EEXIST
) {
1490 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1497 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1500 if (!(p
= make_random_dir(m
)))
1504 if (symlink(p
, k
) < 0) {
1505 int saved_errno
= errno
;
1507 if (errno
!= EEXIST
)
1508 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1513 errno
= saved_errno
;
1525 char *pa_get_runtime_dir(void) {
1526 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1530 /* The runtime directory shall contain dynamic data that needs NOT
1531 * to be kept accross reboots and is usuallly private to the user,
1532 * except in system mode, where it might be accessible by other
1533 * users, too. Since we need POSIX locking and UNIX sockets in
1534 * this directory, we link it to a random subdir in /tmp, if it
1535 * was not explicitly configured. */
1537 m
= pa_in_system_mode() ? 0755U : 0700U;
1539 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1541 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1542 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1546 return pa_xstrdup(d
);
1549 if (!(d
= get_pulse_home()))
1552 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1553 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1558 if (!(mid
= pa_machine_id())) {
1563 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1568 /* OK, first let's check if the "runtime" symlink is already
1571 if (!(p
= pa_readlink(k
))) {
1573 if (errno
!= ENOENT
) {
1574 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1579 /* Hmm, so the runtime directory didn't exist yet, so let's
1580 * create one in /tmp and symlink that to it */
1582 if (make_random_dir_and_link(0700, k
) < 0) {
1584 /* Mhmm, maybe another process was quicker than us,
1585 * let's check if that was valid */
1586 if (errno
== EEXIST
)
1592 /* No symlink possible, so let's just create the runtime directly */
1600 /* Make sure that this actually makes sense */
1601 if (!pa_is_path_absolute(p
)) {
1602 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1607 /* Hmm, so this symlink is still around, make sure nobody fools
1611 if (lstat(p
, &st
) < 0) {
1613 if (errno
!= ENOENT
) {
1614 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1620 if (S_ISDIR(st
.st_mode
) &&
1621 (st
.st_uid
== getuid()) &&
1622 ((st
.st_mode
& 0777) == 0700)) {
1628 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1635 /* Hmm, so the link points to some nonexisting or invalid
1636 * dir. Let's replace it by a new link. We first create a
1637 * temporary link and then rename that to allow concurrent
1638 * execution of this function. */
1640 t
= pa_sprintf_malloc("%s.tmp", k
);
1642 if (make_random_dir_and_link(0700, t
) < 0) {
1644 if (errno
!= EEXIST
) {
1645 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1652 /* Hmm, someone lese was quicker then us. Let's give
1653 * him some time to finish, and retry. */
1658 /* OK, we succeeded in creating the temporary symlink, so
1659 * let's rename it */
1660 if (rename(t
, k
) < 0) {
1661 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1677 /* Try to open a configuration file. If "env" is specified, open the
1678 * value of the specified environment variable. Otherwise look for a
1679 * file "local" in the home directory or a file "global" in global
1680 * file system. If "result" is non-NULL, a pointer to a newly
1681 * allocated buffer containing the used configuration file is
1683 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1687 if (env
&& (fn
= getenv(env
))) {
1688 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1690 *result
= pa_xstrdup(fn
);
1695 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1704 if ((e
= getenv("PULSE_CONFIG_PATH")))
1705 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1706 else if ((h
= pa_get_home_dir_malloc())) {
1707 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1712 if ((f
= pa_fopen_cloexec(fn
, "r"))) {
1714 *result
= pa_xstrdup(fn
);
1720 if (errno
!= ENOENT
) {
1721 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1733 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1734 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1735 pa_win32_get_toplevel(NULL
),
1736 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1739 gfn
= pa_xstrdup(global
);
1741 if ((f
= pa_fopen_cloexec(gfn
, "r"))) {
1756 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1759 if (env
&& (fn
= getenv(env
))) {
1760 if (access(fn
, R_OK
) == 0)
1761 return pa_xstrdup(fn
);
1763 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1772 if ((e
= getenv("PULSE_CONFIG_PATH")))
1773 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1774 else if ((h
= pa_get_home_dir_malloc())) {
1775 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1780 if (access(fn
, R_OK
) == 0) {
1781 char *r
= pa_xstrdup(fn
);
1786 if (errno
!= ENOENT
) {
1787 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1799 if (strncmp(global
, PA_DEFAULT_CONFIG_DIR
, strlen(PA_DEFAULT_CONFIG_DIR
)) == 0)
1800 gfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"etc" PA_PATH_SEP
"pulse%s",
1801 pa_win32_get_toplevel(NULL
),
1802 global
+ strlen(PA_DEFAULT_CONFIG_DIR
));
1805 gfn
= pa_xstrdup(global
);
1807 if (access(gfn
, R_OK
) == 0)
1817 /* Format the specified data as a hexademical string */
1818 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1819 size_t i
= 0, j
= 0;
1820 const char hex
[] = "0123456789abcdef";
1824 pa_assert(slength
> 0);
1826 while (i
< dlength
&& j
+3 <= slength
) {
1827 s
[j
++] = hex
[*d
>> 4];
1828 s
[j
++] = hex
[*d
& 0xF];
1834 s
[j
< slength
? j
: slength
] = 0;
1838 /* Convert a hexadecimal digit to a number or -1 if invalid */
1839 static int hexc(char c
) {
1840 if (c
>= '0' && c
<= '9')
1843 if (c
>= 'A' && c
<= 'F')
1844 return c
- 'A' + 10;
1846 if (c
>= 'a' && c
<= 'f')
1847 return c
- 'a' + 10;
1853 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1854 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1860 while (j
< dlength
&& *p
) {
1863 if ((b
= hexc(*(p
++))) < 0)
1866 d
[j
] = (uint8_t) (b
<< 4);
1871 if ((b
= hexc(*(p
++))) < 0)
1874 d
[j
] |= (uint8_t) b
;
1881 /* Returns nonzero when *s starts with *pfx */
1882 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1890 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1893 /* Returns nonzero when *s ends with *sfx */
1894 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1903 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1906 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1912 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1916 char *pa_make_path_absolute(const char *p
) {
1922 if (pa_is_path_absolute(p
))
1923 return pa_xstrdup(p
);
1925 if (!(cwd
= pa_getcwd()))
1926 return pa_xstrdup(p
);
1928 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1933 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1934 * if fn is non-null and starts with / return fn
1935 * otherwise append fn to the run time path and return it */
1936 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1939 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1944 if (pa_is_path_absolute(fn
))
1945 return pa_xstrdup(fn
);
1953 if (!(mid
= pa_machine_id())) {
1958 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1961 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
1969 char *pa_runtime_path(const char *fn
) {
1970 return get_path(fn
, FALSE
, TRUE
);
1973 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
1974 return get_path(fn
, appendmid
, FALSE
);
1977 /* Convert the string s to a signed integer in *ret_i */
1978 int pa_atoi(const char *s
, int32_t *ret_i
) {
1986 l
= strtol(s
, &x
, 0);
1988 if (!x
|| *x
|| errno
) {
1994 if ((int32_t) l
!= l
) {
1999 *ret_i
= (int32_t) l
;
2004 /* Convert the string s to an unsigned integer in *ret_u */
2005 int pa_atou(const char *s
, uint32_t *ret_u
) {
2013 l
= strtoul(s
, &x
, 0);
2015 if (!x
|| *x
|| errno
) {
2021 if ((uint32_t) l
!= l
) {
2026 *ret_u
= (uint32_t) l
;
2031 #ifdef HAVE_STRTOF_L
2032 static locale_t c_locale
= NULL
;
2034 static void c_locale_destroy(void) {
2035 freelocale(c_locale
);
2039 int pa_atod(const char *s
, double *ret_d
) {
2046 /* This should be locale independent */
2048 #ifdef HAVE_STRTOF_L
2052 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
2053 atexit(c_locale_destroy
);
2059 f
= strtod_l(s
, &x
, c_locale
);
2067 if (!x
|| *x
|| errno
) {
2078 /* Same as snprintf, but guarantees NUL-termination on every platform */
2079 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2084 pa_assert(size
> 0);
2087 va_start(ap
, format
);
2088 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2094 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2095 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2099 pa_assert(size
> 0);
2102 ret
= vsnprintf(str
, size
, format
, ap
);
2109 if ((size_t) ret
> size
-1)
2112 return (size_t) ret
;
2115 /* Truncate the specified string, but guarantee that the string
2116 * returned still validates as UTF8 */
2117 char *pa_truncate_utf8(char *c
, size_t l
) {
2119 pa_assert(pa_utf8_valid(c
));
2126 while (l
> 0 && !pa_utf8_valid(c
))
2132 char *pa_getcwd(void) {
2136 char *p
= pa_xmalloc(l
);
2140 if (errno
!= ERANGE
)
2148 void *pa_will_need(const void *p
, size_t l
) {
2149 #ifdef RLIMIT_MEMLOCK
2160 a
= PA_PAGE_ALIGN_PTR(p
);
2161 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2163 #ifdef HAVE_POSIX_MADVISE
2164 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2165 pa_log_debug("posix_madvise() worked fine!");
2170 /* Most likely the memory was not mmap()ed from a file and thus
2171 * madvise() didn't work, so let's misuse mlock() do page this
2172 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2173 * inviting, the man page of mlock() tells us: "All pages that
2174 * contain a part of the specified address range are guaranteed to
2175 * be resident in RAM when the call returns successfully." */
2177 #ifdef RLIMIT_MEMLOCK
2178 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2180 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2181 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
));
2186 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2188 bs
= PA_PAGE_SIZE
*4;
2191 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2194 while (size
> 0 && bs
> 0) {
2199 if (mlock(a
, bs
) < 0) {
2200 bs
= PA_PAGE_ALIGN(bs
/ 2);
2204 pa_assert_se(munlock(a
, bs
) == 0);
2206 a
= (const uint8_t*) a
+ bs
;
2212 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2214 pa_log_debug("mlock() worked fine!");
2219 void pa_close_pipe(int fds
[2]) {
2223 pa_assert_se(pa_close(fds
[0]) == 0);
2226 pa_assert_se(pa_close(fds
[1]) == 0);
2228 fds
[0] = fds
[1] = -1;
2231 char *pa_readlink(const char *p
) {
2232 #ifdef HAVE_READLINK
2241 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2246 if ((size_t) n
< l
-1) {
2259 int pa_close_all(int except_fd
, ...) {
2264 va_start(ap
, except_fd
);
2267 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2272 p
= pa_xnew(int, n
+1);
2274 va_start(ap
, except_fd
);
2277 if (except_fd
>= 0) {
2281 while ((fd
= va_arg(ap
, int)) >= 0)
2288 r
= pa_close_allv(p
);
2294 int pa_close_allv(const int except_fds
[]) {
2303 if ((d
= opendir("/proc/self/fd"))) {
2307 while ((de
= readdir(d
))) {
2313 if (de
->d_name
[0] == '.')
2317 l
= strtol(de
->d_name
, &e
, 10);
2318 if (errno
!= 0 || !e
|| *e
) {
2326 if ((long) fd
!= l
) {
2339 for (i
= 0; except_fds
[i
] >= 0; i
++)
2340 if (except_fds
[i
] == fd
) {
2348 if (pa_close(fd
) < 0) {
2349 saved_errno
= errno
;
2351 errno
= saved_errno
;
2363 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2364 maxfd
= (int) rl
.rlim_max
;
2366 maxfd
= sysconf(_SC_OPEN_MAX
);
2368 for (fd
= 3; fd
< maxfd
; fd
++) {
2373 for (i
= 0; except_fds
[i
] >= 0; i
++)
2374 if (except_fds
[i
] == fd
) {
2382 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2385 #endif /* !OS_IS_WIN32 */
2390 int pa_unblock_sigs(int except
, ...) {
2395 va_start(ap
, except
);
2398 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2403 p
= pa_xnew(int, n
+1);
2405 va_start(ap
, except
);
2412 while ((sig
= va_arg(ap
, int)) >= 0)
2419 r
= pa_unblock_sigsv(p
);
2425 int pa_unblock_sigsv(const int except
[]) {
2430 if (sigemptyset(&ss
) < 0)
2433 for (i
= 0; except
[i
] > 0; i
++)
2434 if (sigaddset(&ss
, except
[i
]) < 0)
2437 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2443 int pa_reset_sigs(int except
, ...) {
2448 va_start(ap
, except
);
2451 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2456 p
= pa_xnew(int, n
+1);
2458 va_start(ap
, except
);
2465 while ((sig
= va_arg(ap
, int)) >= 0)
2472 r
= pa_reset_sigsv(p
);
2478 int pa_reset_sigsv(const int except
[]) {
2482 for (sig
= 1; sig
< NSIG
; sig
++) {
2483 pa_bool_t reset
= TRUE
;
2494 for (i
= 0; except
[i
] > 0; i
++) {
2495 if (sig
== except
[i
]) {
2504 struct sigaction sa
;
2506 memset(&sa
, 0, sizeof(sa
));
2507 sa
.sa_handler
= SIG_DFL
;
2509 /* On Linux the first two RT signals are reserved by
2510 * glibc, and sigaction() will return EINVAL for them. */
2511 if ((sigaction(sig
, &sa
, NULL
) < 0))
2512 if (errno
!= EINVAL
)
2521 void pa_set_env(const char *key
, const char *value
) {
2525 /* This is not thread-safe */
2528 SetEnvironmentVariable(key
, value
);
2530 setenv(key
, value
, 1);
2534 void pa_set_env_and_record(const char *key
, const char *value
) {
2538 /* This is not thread-safe */
2540 pa_set_env(key
, value
);
2541 recorded_env
= pa_strlist_prepend(recorded_env
, key
);
2544 void pa_unset_env_recorded(void) {
2546 /* This is not thread-safe */
2551 recorded_env
= pa_strlist_pop(recorded_env
, &s
);
2557 SetEnvironmentVariable(s
, NULL
);
2565 pa_bool_t
pa_in_system_mode(void) {
2568 if (!(e
= getenv("PULSE_SYSTEM")))
2574 char *pa_get_user_name_malloc(void) {
2578 #ifdef _SC_LOGIN_NAME_MAX
2579 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2585 u
= pa_xnew(char, k
+1);
2587 if (!(pa_get_user_name(u
, k
))) {
2595 char *pa_get_host_name_malloc(void) {
2604 if (!pa_get_host_name(c
, l
)) {
2606 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2609 } else if (strlen(c
) < l
-1) {
2617 u
= pa_utf8_filter(c
);
2622 /* Hmm, the hostname is as long the space we offered the
2623 * function, we cannot know if it fully fit in, so let's play
2624 * safe and retry. */
2633 char *pa_machine_id(void) {
2637 /* The returned value is supposed be some kind of ascii identifier
2638 * that is unique and stable across reboots. */
2640 /* First we try the D-Bus UUID, which is the best option we have,
2641 * since it fits perfectly our needs and is not as volatile as the
2642 * hostname which might be set from dhcp. */
2644 if ((f
= pa_fopen_cloexec(PA_MACHINE_ID
, "r"))) {
2645 char ln
[34] = "", *r
;
2647 r
= fgets(ln
, sizeof(ln
)-1, f
);
2653 return pa_utf8_filter(ln
);
2656 if ((h
= pa_get_host_name_malloc()))
2660 /* If no hostname was set we use the POSIX hostid. It's usually
2661 * the IPv4 address. Might not be that stable. */
2662 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2668 char *pa_session_id(void) {
2671 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2674 return pa_utf8_filter(e
);
2677 char *pa_uname_string(void) {
2681 pa_assert_se(uname(&u
) >= 0);
2683 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2689 i
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
2690 pa_assert_se(GetVersionEx(&i
));
2692 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i
.dwMajorVersion
, i
.dwMinorVersion
, i
.dwBuildNumber
, i
.szCSDVersion
);
2696 #ifdef HAVE_VALGRIND_MEMCHECK_H
2697 pa_bool_t
pa_in_valgrind(void) {
2700 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2701 * here instead of really checking whether we run in valgrind or
2705 b
= getenv("VALGRIND") ? 2 : 1;
2711 unsigned pa_gcd(unsigned a
, unsigned b
) {
2722 void pa_reduce(unsigned *num
, unsigned *den
) {
2724 unsigned gcd
= pa_gcd(*num
, *den
);
2732 pa_assert(pa_gcd(*num
, *den
) == 1);
2735 unsigned pa_ncpus(void) {
2738 #ifdef _SC_NPROCESSORS_CONF
2739 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2744 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2747 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2756 sb
= pa_strbuf_new();
2761 if (!(p
= strstr(s
, a
)))
2764 pa_strbuf_putsn(sb
, s
, p
-s
);
2765 pa_strbuf_puts(sb
, b
);
2769 pa_strbuf_puts(sb
, s
);
2771 return pa_strbuf_tostring_free(sb
);
2774 char *pa_escape(const char *p
, const char *chars
) {
2777 pa_strbuf
*buf
= pa_strbuf_new();
2779 for (s
= p
; *s
; ++s
) {
2781 pa_strbuf_putc(buf
, '\\');
2783 for (c
= chars
; *c
; ++c
) {
2785 pa_strbuf_putc(buf
, '\\');
2790 pa_strbuf_putc(buf
, *s
);
2793 return pa_strbuf_tostring_free(buf
);
2796 char *pa_unescape(char *p
) {
2798 pa_bool_t escaped
= FALSE
;
2800 for (s
= p
, d
= p
; *s
; s
++) {
2801 if (!escaped
&& *s
== '\\') {
2815 char *pa_realpath(const char *path
) {
2819 /* We want only abolsute paths */
2820 if (path
[0] != '/') {
2825 #if defined(__GLIBC__) || defined(__APPLE__)
2829 if (!(r
= realpath(path
, NULL
)))
2832 /* We copy this here in case our pa_xmalloc() is not
2833 * implemented on top of libc malloc() */
2837 #elif defined(PATH_MAX)
2840 path_buf
= pa_xmalloc(PATH_MAX
);
2842 #if defined(OS_IS_WIN32)
2843 if (!(t
= _fullpath(path_buf
, path
, _MAX_PATH
))) {
2848 if (!(t
= realpath(path
, path_buf
))) {
2855 #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."
2861 void pa_disable_sigpipe(void) {
2864 struct sigaction sa
;
2868 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2869 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2873 sa
.sa_handler
= SIG_IGN
;
2875 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2876 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2882 void pa_xfreev(void**a
) {
2888 for (p
= a
; *p
; p
++)
2894 char **pa_split_spaces_strv(const char *s
) {
2896 unsigned i
= 0, n
= 8;
2897 const char *state
= NULL
;
2899 t
= pa_xnew(char*, n
);
2900 while ((e
= pa_split_spaces(s
, &state
))) {
2905 t
= pa_xrenew(char*, t
, n
);
2918 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2921 if (pa_is_path_absolute(path
))
2922 return pa_xstrdup(path
);
2924 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2927 size_t pa_pipe_buf(int fd
) {
2932 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2943 void pa_reset_personality(void) {
2946 if (personality(PER_LINUX
) < 0)
2947 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2952 #if defined(__linux__) && !defined(__OPTIMIZE__)
2954 pa_bool_t
pa_run_from_build_tree(void) {
2956 pa_bool_t b
= FALSE
;
2958 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2961 if ((rp
= pa_readlink("/proc/self/exe"))) {
2962 b
= pa_startswith(rp
, PA_BUILDDIR
);
2971 const char *pa_get_temp_dir(void) {
2974 if ((t
= getenv("TMPDIR")) &&
2975 pa_is_path_absolute(t
))
2978 if ((t
= getenv("TMP")) &&
2979 pa_is_path_absolute(t
))
2982 if ((t
= getenv("TEMP")) &&
2983 pa_is_path_absolute(t
))
2986 if ((t
= getenv("TEMPDIR")) &&
2987 pa_is_path_absolute(t
))
2993 int pa_open_cloexec(const char *fn
, int flags
, mode_t mode
) {
3001 if ((fd
= open(fn
, flags
|O_CLOEXEC
, mode
)) >= 0)
3004 if (errno
!= EINVAL
)
3008 if ((fd
= open(fn
, flags
, mode
)) < 0)
3012 /* Some implementations might simply ignore O_CLOEXEC if it is not
3013 * understood, make sure FD_CLOEXEC is enabled anyway */
3015 pa_make_fd_cloexec(fd
);
3019 int pa_socket_cloexec(int domain
, int type
, int protocol
) {
3023 if ((fd
= socket(domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0)
3026 if (errno
!= EINVAL
)
3030 if ((fd
= socket(domain
, type
, protocol
)) < 0)
3034 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3035 * not understood, make sure FD_CLOEXEC is enabled anyway */
3037 pa_make_fd_cloexec(fd
);
3041 int pa_pipe_cloexec(int pipefd
[2]) {
3045 if ((r
= pipe2(pipefd
, O_CLOEXEC
)) >= 0)
3048 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3053 if ((r
= pipe(pipefd
)) < 0)
3057 pa_make_fd_cloexec(pipefd
[0]);
3058 pa_make_fd_cloexec(pipefd
[1]);
3063 int pa_accept_cloexec(int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
) {
3067 if ((fd
= accept4(sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0)
3070 if (errno
!= EINVAL
&& errno
!= ENOSYS
)
3075 if ((fd
= accept(sockfd
, addr
, addrlen
)) < 0)
3079 pa_make_fd_cloexec(fd
);
3083 FILE* pa_fopen_cloexec(const char *path
, const char *mode
) {
3087 m
= pa_sprintf_malloc("%se", mode
);
3090 if ((f
= fopen(path
, m
))) {
3097 if (errno
!= EINVAL
)
3100 if (!(f
= fopen(path
, mode
)))
3104 pa_make_fd_cloexec(fileno(f
));
3108 void pa_nullify_stdfds(void) {
3111 pa_close(STDIN_FILENO
);
3112 pa_close(STDOUT_FILENO
);
3113 pa_close(STDERR_FILENO
);
3115 pa_assert_se(open("/dev/null", O_RDONLY
) == STDIN_FILENO
);
3116 pa_assert_se(open("/dev/null", O_WRONLY
) == STDOUT_FILENO
);
3117 pa_assert_se(open("/dev/null", O_WRONLY
) == STDERR_FILENO
);
3124 char *pa_read_line_from_file(const char *fn
) {
3126 char ln
[256] = "", *r
;
3128 if (!(f
= pa_fopen_cloexec(fn
, "r")))
3131 r
= fgets(ln
, sizeof(ln
)-1, f
);
3140 return pa_xstrdup(ln
);
3143 pa_bool_t
pa_running_in_vm(void) {
3145 #if defined(__i386__) || defined(__x86_64__)
3147 /* Both CPUID and DMI are x86 specific interfaces... */
3149 uint32_t eax
= 0x40000000;
3156 const char *const dmi_vendors
[] = {
3157 "/sys/class/dmi/id/sys_vendor",
3158 "/sys/class/dmi/id/board_vendor",
3159 "/sys/class/dmi/id/bios_vendor"
3164 for (i
= 0; i
< PA_ELEMENTSOF(dmi_vendors
); i
++) {
3167 if ((s
= pa_read_line_from_file(dmi_vendors
[i
]))) {
3169 if (pa_startswith(s
, "QEMU") ||
3170 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3171 pa_startswith(s
, "VMware") ||
3172 pa_startswith(s
, "VMW") ||
3173 pa_startswith(s
, "Microsoft Corporation") ||
3174 pa_startswith(s
, "innotek GmbH") ||
3175 pa_startswith(s
, "Xen")) {
3187 /* http://lwn.net/Articles/301888/ */
3190 __asm__
__volatile__ (
3191 /* ebx/rbx is being used for PIC! */
3192 " push %%"PA_REG_b
" \n\t"
3194 " mov %%ebx, %1 \n\t"
3195 " pop %%"PA_REG_b
" \n\t"
3197 : "=a" (eax
), "=r" (sig
.sig32
[0]), "=c" (sig
.sig32
[1]), "=d" (sig
.sig32
[2])
3201 if (pa_streq(sig
.text
, "XenVMMXenVMM") ||
3202 pa_streq(sig
.text
, "KVMKVMKVM") ||
3203 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3204 pa_streq(sig
.text
, "VMwareVMware") ||
3205 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3206 pa_streq(sig
.text
, "Microsoft Hv"))