2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39 #include <sys/types.h>
45 #include <sys/utsname.h>
46 #include <sys/socket.h>
55 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
56 #define SCHED_RESET_ON_FORK 0x40000000
60 #ifdef HAVE_SYS_RESOURCE_H
61 #include <sys/resource.h>
64 #ifdef HAVE_SYS_CAPABILITY_H
65 #include <sys/capability.h>
68 #ifdef HAVE_SYS_MMAN_H
92 #ifdef HAVE_LIBSAMPLERATE
93 #include <samplerate.h>
105 #include <sys/personality.h>
108 #include <pulse/xmalloc.h>
109 #include <pulse/util.h>
110 #include <pulse/utf8.h>
112 #include <pulsecore/core-error.h>
113 #include <pulsecore/winsock.h>
114 #include <pulsecore/log.h>
115 #include <pulsecore/macro.h>
116 #include <pulsecore/thread.h>
117 #include <pulsecore/strbuf.h>
118 #include <pulsecore/usergroup.h>
120 #include "core-util.h"
122 /* Not all platforms have this */
124 #define MSG_NOSIGNAL 0
129 #define PULSE_ROOTENV "PULSE_ROOT"
131 int pa_set_root(HANDLE handle
) {
132 char library_path
[MAX_PATH
+ sizeof(PULSE_ROOTENV
) + 1], *sep
;
134 strcpy(library_path
, PULSE_ROOTENV
"=");
136 /* FIXME: Needs to set errno */
138 if (!GetModuleFileName(handle
, library_path
+ sizeof(PULSE_ROOTENV
), MAX_PATH
))
141 sep
= strrchr(library_path
, PA_PATH_SEP_CHAR
);
145 if (_putenv(library_path
) < 0)
153 /** Make a file descriptor nonblock. Doesn't do any error checking */
154 void pa_make_fd_nonblock(int fd
) {
160 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
162 if (!(v
& O_NONBLOCK
))
163 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
165 #elif defined(OS_IS_WIN32)
167 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
168 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
169 pa_log_warn("Only sockets can be made non-blocking!");
172 pa_log_warn("Non-blocking I/O not supported.!");
177 /* Set the FD_CLOEXEC flag for a fd */
178 void pa_make_fd_cloexec(int fd
) {
184 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
186 if (!(v
& FD_CLOEXEC
))
187 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
192 /** Creates a directory securely */
193 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
204 u
= umask((~m
) & 0777);
210 if (r
< 0 && errno
!= EEXIST
)
214 if (uid
== (uid_t
)-1)
216 if (gid
== (gid_t
)-1)
218 (void) chown(dir
, uid
, gid
);
226 if (lstat(dir
, &st
) < 0)
228 if (stat(dir
, &st
) < 0)
233 if (!S_ISDIR(st
.st_mode
) ||
234 (st
.st_uid
!= uid
) ||
235 (st
.st_gid
!= gid
) ||
236 ((st
.st_mode
& 0777) != m
)) {
241 pa_log_warn("Secure directory creation not supported on Win32.");
254 /* Return a newly allocated sting containing the parent directory of the specified file */
255 char *pa_parent_dir(const char *fn
) {
256 char *slash
, *dir
= pa_xstrdup(fn
);
258 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
268 /* Creates a the parent directory of the specified path securely */
269 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
273 if (!(dir
= pa_parent_dir(fn
)))
276 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
286 /** Platform independent read function. Necessary since not all
287 * systems treat all file descriptors equal. If type is
288 * non-NULL it is used to cache the type of the fd. This is
289 * useful for making sure that only a single syscall is executed per
290 * function call. The variable pointed to should be initialized to 0
292 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
296 if (!type
|| *type
== 0) {
299 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
302 if (WSAGetLastError() != WSAENOTSOCK
) {
303 errno
= WSAGetLastError();
316 if ((r
= read(fd
, buf
, count
)) < 0)
324 /** Similar to pa_read(), but handles writes */
325 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
327 if (!type
|| *type
== 0) {
331 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) < 0) {
343 if (WSAGetLastError() != WSAENOTSOCK
) {
344 errno
= WSAGetLastError();
348 if (errno
!= ENOTSOCK
)
359 if ((r
= write(fd
, buf
, count
)) < 0)
367 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
368 * unless EOF is reached or an error occurred */
369 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
385 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
392 data
= (uint8_t*) data
+ r
;
399 /** Similar to pa_loop_read(), but wraps write() */
400 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
416 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
423 data
= (const uint8_t*) data
+ r
;
430 /** Platform independent read function. Necessary since not all
431 * systems treat all file descriptors equal. */
432 int pa_close(int fd
) {
437 if ((ret
= closesocket(fd
)) == 0)
440 if (WSAGetLastError() != WSAENOTSOCK
) {
441 errno
= WSAGetLastError();
449 if ((r
= close(fd
)) < 0)
457 /* Print a warning messages in case that the given signal is not
458 * blocked or trapped */
459 void pa_check_signal_is_blocked(int sig
) {
460 #ifdef HAVE_SIGACTION
464 /* If POSIX threads are supported use thread-aware
465 * pthread_sigmask() function, to check if the signal is
466 * blocked. Otherwise fall back to sigprocmask() */
469 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
471 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
472 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
479 if (sigismember(&set
, sig
))
482 /* Check whether the signal is trapped */
484 if (sigaction(sig
, NULL
, &sa
) < 0) {
485 pa_log("sigaction(): %s", pa_cstrerror(errno
));
489 if (sa
.sa_handler
!= SIG_DFL
)
492 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
493 #else /* HAVE_SIGACTION */
494 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
498 /* The following function is based on an example from the GNU libc
499 * documentation. This function is similar to GNU's asprintf(). */
500 char *pa_sprintf_malloc(const char *format
, ...) {
510 c
= pa_xrealloc(c
, size
);
512 va_start(ap
, format
);
513 r
= vsnprintf(c
, size
, format
, ap
);
518 if (r
> -1 && (size_t) r
< size
)
521 if (r
> -1) /* glibc 2.1 */
528 /* Same as the previous function, but use a va_list instead of an
530 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
540 c
= pa_xrealloc(c
, size
);
543 r
= vsnprintf(c
, size
, format
, aq
);
548 if (r
> -1 && (size_t) r
< size
)
551 if (r
> -1) /* glibc 2.1 */
558 /* Similar to OpenBSD's strlcpy() function */
559 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
577 static int set_scheduler(int rtprio
) {
578 struct sched_param sp
;
584 dbus_error_init(&error
);
588 sp
.sched_priority
= rtprio
;
590 #ifdef SCHED_RESET_ON_FORK
591 if ((r
= pthread_setschedparam(pthread_self(), SCHED_RR
|SCHED_RESET_ON_FORK
, &sp
)) == 0) {
592 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
597 if ((r
= pthread_setschedparam(pthread_self(), SCHED_RR
, &sp
)) == 0) {
598 pa_log_debug("SCHED_RR worked.");
603 /* Try to talk to RealtimeKit */
605 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
606 pa_log("Failed to connect to system bus: %s\n", error
.message
);
607 dbus_error_free(&error
);
612 r
= rtkit_make_realtime(bus
, 0, rtprio
);
613 dbus_connection_unref(bus
);
616 pa_log_debug("RealtimeKit worked.");
628 /* Make the current thread a realtime thread, and acquire the highest
629 * rtprio we can get that is less or equal the specified parameter. If
630 * the thread is already realtime, don't do anything. */
631 int pa_make_realtime(int rtprio
) {
633 #ifdef _POSIX_PRIORITY_SCHEDULING
636 if (set_scheduler(rtprio
) >= 0) {
637 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio
);
641 for (p
= rtprio
-1; p
>= 1; p
--)
642 if (set_scheduler(p
)) {
643 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p
, rtprio
);
647 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno
));
656 static int set_nice(int nice_level
) {
662 dbus_error_init(&error
);
665 if (setpriority(PRIO_PROCESS
, 0, nice_level
) >= 0) {
666 pa_log_debug("setpriority() worked.");
671 /* Try to talk to RealtimeKit */
673 if (!(bus
= dbus_bus_get(DBUS_BUS_SYSTEM
, &error
))) {
674 pa_log("Failed to connect to system bus: %s\n", error
.message
);
675 dbus_error_free(&error
);
680 r
= rtkit_make_high_priority(bus
, 0, nice_level
);
681 dbus_connection_unref(bus
);
684 pa_log_debug("RealtimeKit worked.");
694 /* Raise the priority of the current process as much as possible that
695 * is <= the specified nice level..*/
696 int pa_raise_priority(int nice_level
) {
698 #ifdef HAVE_SYS_RESOURCE_H
701 if (set_nice(nice_level
) >= 0) {
702 pa_log_info("Successfully gained nice level %i.", nice_level
);
706 for (n
= nice_level
+1; n
< 0; n
++)
707 if (set_nice(n
) > 0) {
708 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n
, nice_level
);
712 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno
));
717 if (nice_level
< 0) {
718 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
)) {
719 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
724 pa_log_info("Successfully gained high priority class.");
731 /* Reset the priority to normal, inverting the changes made by
732 * pa_raise_priority() and pa_make_realtime()*/
733 void pa_reset_priority(void) {
734 #ifdef HAVE_SYS_RESOURCE_H
735 struct sched_param sp
;
737 setpriority(PRIO_PROCESS
, 0, 0);
740 pthread_setschedparam(pthread_self(), SCHED_OTHER
, &sp
);
744 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
748 int pa_match(const char *expr
, const char *v
) {
753 if (regcomp(&re
, expr
, REG_NOSUB
|REG_EXTENDED
) != 0) {
758 if ((k
= regexec(&re
, v
, 0, NULL
, 0)) == 0)
760 else if (k
== REG_NOMATCH
)
773 /* Try to parse a boolean string value.*/
774 int pa_parse_boolean(const char *v
) {
779 /* First we check language independant */
780 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
782 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
785 /* And then we check language dependant */
786 if ((expr
= nl_langinfo(YESEXPR
)))
788 if ((r
= pa_match(expr
, v
)) > 0)
791 if ((expr
= nl_langinfo(NOEXPR
)))
793 if ((r
= pa_match(expr
, v
)) > 0)
800 /* Split the specified string wherever one of the strings in delimiter
801 * occurs. Each time it is called returns a newly allocated string
802 * with pa_xmalloc(). The variable state points to, should be
803 * initiallized to NULL before the first call. */
804 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
805 const char *current
= *state
? *state
: c
;
811 l
= strcspn(current
, delimiter
);
817 return pa_xstrndup(current
, l
);
820 /* What is interpreted as whitespace? */
821 #define WHITESPACE " \t\n"
823 /* Split a string into words. Otherwise similar to pa_split(). */
824 char *pa_split_spaces(const char *c
, const char **state
) {
825 const char *current
= *state
? *state
: c
;
828 if (!*current
|| *c
== 0)
831 current
+= strspn(current
, WHITESPACE
);
832 l
= strcspn(current
, WHITESPACE
);
836 return pa_xstrndup(current
, l
);
839 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
841 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
842 const char *pa_sig2str(int sig
) {
855 char buf
[SIG2STR_MAX
];
857 if (sig2str(sig
, buf
) == 0) {
858 pa_xfree(PA_STATIC_TLS_GET(signame
));
859 t
= pa_sprintf_malloc("SIG%s", buf
);
860 PA_STATIC_TLS_SET(signame
, t
);
868 case SIGHUP
: return "SIGHUP";
870 case SIGINT
: return "SIGINT";
872 case SIGQUIT
: return "SIGQUIT";
874 case SIGILL
: return "SIGULL";
876 case SIGTRAP
: return "SIGTRAP";
878 case SIGABRT
: return "SIGABRT";
880 case SIGBUS
: return "SIGBUS";
882 case SIGFPE
: return "SIGFPE";
884 case SIGKILL
: return "SIGKILL";
887 case SIGUSR1
: return "SIGUSR1";
889 case SIGSEGV
: return "SIGSEGV";
891 case SIGUSR2
: return "SIGUSR2";
894 case SIGPIPE
: return "SIGPIPE";
897 case SIGALRM
: return "SIGALRM";
899 case SIGTERM
: return "SIGTERM";
901 case SIGSTKFLT
: return "SIGSTKFLT";
904 case SIGCHLD
: return "SIGCHLD";
907 case SIGCONT
: return "SIGCONT";
910 case SIGSTOP
: return "SIGSTOP";
913 case SIGTSTP
: return "SIGTSTP";
916 case SIGTTIN
: return "SIGTTIN";
919 case SIGTTOU
: return "SIGTTOU";
922 case SIGURG
: return "SIGURG";
925 case SIGXCPU
: return "SIGXCPU";
928 case SIGXFSZ
: return "SIGXFSZ";
931 case SIGVTALRM
: return "SIGVTALRM";
934 case SIGPROF
: return "SIGPROF";
937 case SIGWINCH
: return "SIGWINCH";
940 case SIGIO
: return "SIGIO";
943 case SIGPWR
: return "SIGPWR";
946 case SIGSYS
: return "SIGSYS";
951 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
952 pa_xfree(PA_STATIC_TLS_GET(signame
));
953 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
954 PA_STATIC_TLS_SET(signame
, t
);
963 pa_xfree(PA_STATIC_TLS_GET(signame
));
964 t
= pa_sprintf_malloc("SIG%i", sig
);
965 PA_STATIC_TLS_SET(signame
, t
);
971 /* Check whether the specified GID and the group name match */
972 static int is_group(gid_t gid
, const char *name
) {
973 struct group
*group
= NULL
;
977 if (!(group
= pa_getgrgid_malloc(gid
)))
982 pa_log("pa_getgrgid_malloc(%u): %s", gid
, pa_cstrerror(errno
));
987 r
= strcmp(name
, group
->gr_name
) == 0;
990 pa_getgrgid_free(group
);
995 /* Check the current user is member of the specified group */
996 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
997 GETGROUPS_T
*gids
, tgid
;
998 long n
= sysconf(_SC_NGROUPS_MAX
);
1003 gids
= pa_xmalloc(sizeof(GETGROUPS_T
) * (size_t) n
);
1005 if ((n
= getgroups((int) n
, gids
)) < 0) {
1006 pa_log("getgroups(): %s", pa_cstrerror(errno
));
1010 for (i
= 0; i
< n
; i
++) {
1012 if ((k
= is_group(gids
[i
], name
)) < 0)
1021 if ((k
= is_group(tgid
= getgid(), name
)) < 0)
1037 /* Check whether the specifc user id is a member of the specified group */
1038 int pa_uid_in_group(uid_t uid
, const char *name
) {
1039 struct group
*group
= NULL
;
1044 if (!(group
= pa_getgrnam_malloc(name
)))
1052 for (i
= group
->gr_mem
; *i
; i
++) {
1053 struct passwd
*pw
= NULL
;
1056 if (!(pw
= pa_getpwnam_malloc(*i
)))
1059 if (pw
->pw_uid
== uid
)
1062 pa_getpwnam_free(pw
);
1069 pa_getgrnam_free(group
);
1074 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1075 gid_t
pa_get_gid_of_group(const char *name
) {
1076 gid_t ret
= (gid_t
) -1;
1077 struct group
*gr
= NULL
;
1080 if (!(gr
= pa_getgrnam_malloc(name
)))
1090 pa_getgrnam_free(gr
);
1094 int pa_check_in_group(gid_t g
) {
1095 gid_t gids
[NGROUPS_MAX
];
1098 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
1108 #else /* HAVE_GRP_H */
1110 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
1116 int pa_uid_in_group(uid_t uid
, const char *name
) {
1121 gid_t
pa_get_gid_of_group(const char *name
) {
1126 int pa_check_in_group(gid_t g
) {
1133 /* Lock or unlock a file entirely.
1134 (advisory on UNIX, mandatory on Windows) */
1135 int pa_lock_fd(int fd
, int b
) {
1137 struct flock f_lock
;
1139 /* Try a R/W lock first */
1141 f_lock
.l_type
= (short) (b
? F_WRLCK
: F_UNLCK
);
1142 f_lock
.l_whence
= SEEK_SET
;
1146 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1149 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1150 if (b
&& errno
== EBADF
) {
1151 f_lock
.l_type
= F_RDLCK
;
1152 if (fcntl(fd
, F_SETLKW
, &f_lock
) >= 0)
1156 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
1160 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
1162 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1164 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1167 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
1169 /* FIXME: Needs to set errno! */
1175 /* Remove trailing newlines from a string */
1176 char* pa_strip_nl(char *s
) {
1179 s
[strcspn(s
, "\r\n")] = 0;
1183 /* Create a temporary lock file and lock it. */
1184 int pa_lock_lockfile(const char *fn
) {
1191 if ((fd
= open(fn
, O_CREAT
|O_RDWR
1198 , S_IRUSR
|S_IWUSR
)) < 0) {
1199 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
1203 if (pa_lock_fd(fd
, 1) < 0) {
1204 pa_log_warn("Failed to lock file '%s'.", fn
);
1208 if (fstat(fd
, &st
) < 0) {
1209 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1213 /* Check whether the file has been removed meanwhile. When yes,
1214 * restart this loop, otherwise, we're done */
1215 if (st
.st_nlink
>= 1)
1218 if (pa_lock_fd(fd
, 0) < 0) {
1219 pa_log_warn("Failed to unlock file '%s'.", fn
);
1223 if (pa_close(fd
) < 0) {
1224 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1237 int saved_errno
= errno
;
1239 errno
= saved_errno
;
1245 /* Unlock a temporary lcok file */
1246 int pa_unlock_lockfile(const char *fn
, int fd
) {
1251 if (unlink(fn
) < 0) {
1252 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1257 if (pa_lock_fd(fd
, 0) < 0) {
1258 pa_log_warn("Failed to unlock file '%s'.", fn
);
1262 if (pa_close(fd
) < 0) {
1263 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1270 static char *get_pulse_home(void) {
1275 if (!(h
= pa_get_home_dir_malloc())) {
1276 pa_log_error("Failed to get home directory.");
1280 if (stat(h
, &st
) < 0) {
1281 pa_log_error("Failed to stat home directory %s: %s", h
, pa_cstrerror(errno
));
1285 if (st
.st_uid
!= getuid()) {
1286 pa_log_error("Home directory %s not ours.", h
);
1291 ret
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse", h
);
1299 char *pa_get_state_dir(void) {
1302 /* The state directory shall contain dynamic data that should be
1303 * kept across reboots, and is private to this user */
1305 if (!(d
= pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1306 if (!(d
= get_pulse_home()))
1309 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1310 * dir then this will break. */
1312 if (pa_make_secure_dir(d
, 0700U, (uid_t
) -1, (gid_t
) -1) < 0) {
1313 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1321 char *pa_get_home_dir_malloc(void) {
1323 size_t allocated
= 128;
1326 homedir
= pa_xmalloc(allocated
);
1328 if (!pa_get_home_dir(homedir
, allocated
)) {
1333 if (strlen(homedir
) < allocated
- 1)
1343 char *pa_get_binary_name_malloc(void) {
1345 size_t allocated
= 128;
1348 t
= pa_xmalloc(allocated
);
1350 if (!pa_get_binary_name(t
, allocated
)) {
1355 if (strlen(t
) < allocated
- 1)
1365 static char* make_random_dir(mode_t m
) {
1366 static const char table
[] =
1367 "abcdefghijklmnopqrstuvwxyz"
1368 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1375 if (!(tmpdir
= getenv("TMPDIR")))
1376 if (!(tmpdir
= getenv("TMP")))
1377 if (!(tmpdir
= getenv("TEMP")))
1378 tmpdir
= getenv("TEMPDIR");
1380 if (!tmpdir
|| !pa_is_path_absolute(tmpdir
))
1383 fn
= pa_sprintf_malloc("%s/pulse-XXXXXXXXXXXX", tmpdir
);
1384 pathlen
= strlen(fn
);
1392 for (i
= pathlen
- 12; i
< pathlen
; i
++)
1393 fn
[i
] = table
[rand() % (sizeof(table
)-1)];
1395 u
= umask((~m
) & 0777);
1398 saved_errno
= errno
;
1400 errno
= saved_errno
;
1405 if (errno
!= EEXIST
) {
1406 pa_log_error("Failed to create random directory %s: %s", fn
, pa_cstrerror(errno
));
1413 static int make_random_dir_and_link(mode_t m
, const char *k
) {
1416 if (!(p
= make_random_dir(m
)))
1419 if (symlink(p
, k
) < 0) {
1420 int saved_errno
= errno
;
1422 if (errno
!= EEXIST
)
1423 pa_log_error("Failed to symlink %s to %s: %s", k
, p
, pa_cstrerror(errno
));
1428 errno
= saved_errno
;
1436 char *pa_get_runtime_dir(void) {
1437 char *d
, *k
= NULL
, *p
= NULL
, *t
= NULL
, *mid
;
1441 /* The runtime directory shall contain dynamic data that needs NOT
1442 * to be kept accross reboots and is usuallly private to the user,
1443 * except in system mode, where it might be accessible by other
1444 * users, too. Since we need POSIX locking and UNIX sockets in
1445 * this directory, we link it to a random subdir in /tmp, if it
1446 * was not explicitly configured. */
1448 m
= pa_in_system_mode() ? 0755U : 0700U;
1450 if ((d
= getenv("PULSE_RUNTIME_PATH"))) {
1452 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1453 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1457 return pa_xstrdup(d
);
1460 if (!(d
= get_pulse_home()))
1463 if (pa_make_secure_dir(d
, m
, (uid_t
) -1, (gid_t
) -1) < 0) {
1464 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno
));
1469 if (!(mid
= pa_machine_id())) {
1474 k
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-runtime", d
, mid
);
1479 /* OK, first let's check if the "runtime" symlink is already
1482 if (!(p
= pa_readlink(k
))) {
1484 if (errno
!= ENOENT
) {
1485 pa_log_error("Failed to stat runtime directory %s: %s", k
, pa_cstrerror(errno
));
1489 /* Hmm, so the runtime directory didn't exist yet, so let's
1490 * create one in /tmp and symlink that to it */
1492 if (make_random_dir_and_link(0700, k
) < 0) {
1494 /* Mhmm, maybe another process was quicker than us,
1495 * let's check if that was valid */
1496 if (errno
== EEXIST
)
1505 /* Make sure that this actually makes sense */
1506 if (!pa_is_path_absolute(p
)) {
1507 pa_log_error("Path %s in link %s is not absolute.", p
, k
);
1512 /* Hmm, so this symlink is still around, make sure nobody fools
1515 if (lstat(p
, &st
) < 0) {
1517 if (errno
!= ENOENT
) {
1518 pa_log_error("Failed to stat runtime directory %s: %s", p
, pa_cstrerror(errno
));
1524 if (S_ISDIR(st
.st_mode
) &&
1525 (st
.st_uid
== getuid()) &&
1526 ((st
.st_mode
& 0777) == 0700)) {
1532 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1538 /* Hmm, so the link points to some nonexisting or invalid
1539 * dir. Let's replace it by a new link. We first create a
1540 * temporary link and then rename that to allow concurrent
1541 * execution of this function. */
1543 t
= pa_sprintf_malloc("%s.tmp", k
);
1545 if (make_random_dir_and_link(0700, t
) < 0) {
1547 if (errno
!= EEXIST
) {
1548 pa_log_error("Failed to symlink %s: %s", t
, pa_cstrerror(errno
));
1555 /* Hmm, someone lese was quicker then us. Let's give
1556 * him some time to finish, and retry. */
1561 /* OK, we succeeded in creating the temporary symlink, so
1562 * let's rename it */
1563 if (rename(t
, k
) < 0) {
1564 pa_log_error("Failed to rename %s to %s: %s", t
, k
, pa_cstrerror(errno
));
1580 /* Try to open a configuration file. If "env" is specified, open the
1581 * value of the specified environment variable. Otherwise look for a
1582 * file "local" in the home directory or a file "global" in global
1583 * file system. If "result" is non-NULL, a pointer to a newly
1584 * allocated buffer containing the used configuration file is
1586 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
) {
1591 if (!getenv(PULSE_ROOTENV
))
1595 if (env
&& (fn
= getenv(env
))) {
1599 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1600 /* FIXME: Needs to set errno! */
1605 if ((f
= fopen(fn
, "r"))) {
1607 *result
= pa_xstrdup(fn
);
1612 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1622 if ((e
= getenv("PULSE_CONFIG_PATH")))
1623 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1624 else if ((h
= pa_get_home_dir_malloc())) {
1625 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1631 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1632 /* FIXME: Needs to set errno! */
1639 if ((f
= fopen(fn
, "r"))) {
1641 *result
= pa_xstrdup(fn
);
1647 if (errno
!= ENOENT
) {
1648 pa_log_warn("Failed to open configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1660 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1661 /* FIXME: Needs to set errno! */
1666 if ((f
= fopen(global
, "r"))) {
1669 *result
= pa_xstrdup(global
);
1679 char *pa_find_config_file(const char *global
, const char *local
, const char *env
) {
1684 if (!getenv(PULSE_ROOTENV
))
1688 if (env
&& (fn
= getenv(env
))) {
1691 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1692 /* FIXME: Needs to set errno! */
1697 if (access(fn
, R_OK
) == 0)
1698 return pa_xstrdup(fn
);
1700 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1709 if ((e
= getenv("PULSE_CONFIG_PATH")))
1710 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", e
, local
);
1711 else if ((h
= pa_get_home_dir_malloc())) {
1712 fn
= lfn
= pa_sprintf_malloc("%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s", h
, local
);
1718 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
)) {
1719 /* FIXME: Needs to set errno! */
1726 if (access(fn
, R_OK
) == 0) {
1727 char *r
= pa_xstrdup(fn
);
1732 if (errno
!= ENOENT
) {
1733 pa_log_warn("Failed to access configuration file '%s': %s", fn
, pa_cstrerror(errno
));
1743 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1744 /* FIXME: Needs to set errno! */
1749 if (access(global
, R_OK
) == 0)
1750 return pa_xstrdup(global
);
1758 /* Format the specified data as a hexademical string */
1759 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1760 size_t i
= 0, j
= 0;
1761 const char hex
[] = "0123456789abcdef";
1765 pa_assert(slength
> 0);
1767 while (i
< dlength
&& j
+3 <= slength
) {
1768 s
[j
++] = hex
[*d
>> 4];
1769 s
[j
++] = hex
[*d
& 0xF];
1775 s
[j
< slength
? j
: slength
] = 0;
1779 /* Convert a hexadecimal digit to a number or -1 if invalid */
1780 static int hexc(char c
) {
1781 if (c
>= '0' && c
<= '9')
1784 if (c
>= 'A' && c
<= 'F')
1785 return c
- 'A' + 10;
1787 if (c
>= 'a' && c
<= 'f')
1788 return c
- 'a' + 10;
1794 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1795 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1801 while (j
< dlength
&& *p
) {
1804 if ((b
= hexc(*(p
++))) < 0)
1807 d
[j
] = (uint8_t) (b
<< 4);
1812 if ((b
= hexc(*(p
++))) < 0)
1815 d
[j
] |= (uint8_t) b
;
1822 /* Returns nonzero when *s starts with *pfx */
1823 pa_bool_t
pa_startswith(const char *s
, const char *pfx
) {
1831 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1834 /* Returns nonzero when *s ends with *sfx */
1835 pa_bool_t
pa_endswith(const char *s
, const char *sfx
) {
1844 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1847 pa_bool_t
pa_is_path_absolute(const char *fn
) {
1853 return strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\';
1857 char *pa_make_path_absolute(const char *p
) {
1863 if (pa_is_path_absolute(p
))
1864 return pa_xstrdup(p
);
1866 if (!(cwd
= pa_getcwd()))
1867 return pa_xstrdup(p
);
1869 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", cwd
, p
);
1874 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1875 * if fn is non-null and starts with / return fn
1876 * otherwise append fn to the run time path and return it */
1877 static char *get_path(const char *fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1880 if (pa_is_path_absolute(fn
))
1881 return pa_xstrdup(fn
);
1883 rtp
= rt
? pa_get_runtime_dir() : pa_get_state_dir();
1894 if (!(mid
= pa_machine_id())) {
1899 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s-%s", rtp
, mid
, fn
);
1902 r
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", rtp
, fn
);
1910 char *pa_runtime_path(const char *fn
) {
1911 return get_path(fn
, FALSE
, TRUE
);
1914 char *pa_state_path(const char *fn
, pa_bool_t appendmid
) {
1915 return get_path(fn
, appendmid
, FALSE
);
1918 /* Convert the string s to a signed integer in *ret_i */
1919 int pa_atoi(const char *s
, int32_t *ret_i
) {
1927 l
= strtol(s
, &x
, 0);
1929 if (!x
|| *x
|| errno
) {
1935 if ((int32_t) l
!= l
) {
1940 *ret_i
= (int32_t) l
;
1945 /* Convert the string s to an unsigned integer in *ret_u */
1946 int pa_atou(const char *s
, uint32_t *ret_u
) {
1954 l
= strtoul(s
, &x
, 0);
1956 if (!x
|| *x
|| errno
) {
1962 if ((uint32_t) l
!= l
) {
1967 *ret_u
= (uint32_t) l
;
1972 #ifdef HAVE_STRTOF_L
1973 static locale_t c_locale
= NULL
;
1975 static void c_locale_destroy(void) {
1976 freelocale(c_locale
);
1980 int pa_atod(const char *s
, double *ret_d
) {
1987 /* This should be locale independent */
1989 #ifdef HAVE_STRTOF_L
1993 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
1994 atexit(c_locale_destroy
);
2000 f
= strtod_l(s
, &x
, c_locale
);
2008 if (!x
|| *x
|| errno
) {
2019 /* Same as snprintf, but guarantees NUL-termination on every platform */
2020 size_t pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
2025 pa_assert(size
> 0);
2028 va_start(ap
, format
);
2029 ret
= pa_vsnprintf(str
, size
, format
, ap
);
2035 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2036 size_t pa_vsnprintf(char *str
, size_t size
, const char *format
, va_list ap
) {
2040 pa_assert(size
> 0);
2043 ret
= vsnprintf(str
, size
, format
, ap
);
2050 if ((size_t) ret
> size
-1)
2053 return (size_t) ret
;
2056 /* Truncate the specified string, but guarantee that the string
2057 * returned still validates as UTF8 */
2058 char *pa_truncate_utf8(char *c
, size_t l
) {
2060 pa_assert(pa_utf8_valid(c
));
2067 while (l
> 0 && !pa_utf8_valid(c
))
2073 char *pa_getcwd(void) {
2077 char *p
= pa_xmalloc(l
);
2081 if (errno
!= ERANGE
)
2089 void *pa_will_need(const void *p
, size_t l
) {
2090 #ifdef RLIMIT_MEMLOCK
2101 a
= PA_PAGE_ALIGN_PTR(p
);
2102 size
= (size_t) ((const uint8_t*) p
+ l
- (const uint8_t*) a
);
2104 #ifdef HAVE_POSIX_MADVISE
2105 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
2106 pa_log_debug("posix_madvise() worked fine!");
2111 /* Most likely the memory was not mmap()ed from a file and thus
2112 * madvise() didn't work, so let's misuse mlock() do page this
2113 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2114 * inviting, the man page of mlock() tells us: "All pages that
2115 * contain a part of the specified address range are guaranteed to
2116 * be resident in RAM when the call returns successfully." */
2118 #ifdef RLIMIT_MEMLOCK
2119 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
2121 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
2122 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
));
2127 bs
= PA_PAGE_ALIGN((size_t) rlim
.rlim_cur
);
2129 bs
= PA_PAGE_SIZE
*4;
2132 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
2135 while (size
> 0 && bs
> 0) {
2140 if (mlock(a
, bs
) < 0) {
2141 bs
= PA_PAGE_ALIGN(bs
/ 2);
2145 pa_assert_se(munlock(a
, bs
) == 0);
2147 a
= (const uint8_t*) a
+ bs
;
2153 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
2155 pa_log_debug("mlock() worked fine!");
2160 void pa_close_pipe(int fds
[2]) {
2164 pa_assert_se(pa_close(fds
[0]) == 0);
2167 pa_assert_se(pa_close(fds
[1]) == 0);
2169 fds
[0] = fds
[1] = -1;
2172 char *pa_readlink(const char *p
) {
2181 if ((n
= readlink(p
, c
, l
-1)) < 0) {
2186 if ((size_t) n
< l
-1) {
2196 int pa_close_all(int except_fd
, ...) {
2201 va_start(ap
, except_fd
);
2204 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2209 p
= pa_xnew(int, n
+1);
2211 va_start(ap
, except_fd
);
2214 if (except_fd
>= 0) {
2218 while ((fd
= va_arg(ap
, int)) >= 0)
2225 r
= pa_close_allv(p
);
2231 int pa_close_allv(const int except_fds
[]) {
2239 if ((d
= opendir("/proc/self/fd"))) {
2243 while ((de
= readdir(d
))) {
2249 if (de
->d_name
[0] == '.')
2253 l
= strtol(de
->d_name
, &e
, 10);
2254 if (errno
!= 0 || !e
|| *e
) {
2262 if ((long) fd
!= l
) {
2275 for (i
= 0; except_fds
[i
] >= 0; i
++)
2276 if (except_fds
[i
] == fd
) {
2284 if (pa_close(fd
) < 0) {
2285 saved_errno
= errno
;
2287 errno
= saved_errno
;
2299 if (getrlimit(RLIMIT_NOFILE
, &rl
) >= 0)
2300 maxfd
= (int) rl
.rlim_max
;
2302 maxfd
= sysconf(_SC_OPEN_MAX
);
2304 for (fd
= 3; fd
< maxfd
; fd
++) {
2309 for (i
= 0; except_fds
[i
] >= 0; i
++)
2310 if (except_fds
[i
] == fd
) {
2318 if (pa_close(fd
) < 0 && errno
!= EBADF
)
2325 int pa_unblock_sigs(int except
, ...) {
2330 va_start(ap
, except
);
2333 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2338 p
= pa_xnew(int, n
+1);
2340 va_start(ap
, except
);
2347 while ((sig
= va_arg(ap
, int)) >= 0)
2354 r
= pa_unblock_sigsv(p
);
2360 int pa_unblock_sigsv(const int except
[]) {
2364 if (sigemptyset(&ss
) < 0)
2367 for (i
= 0; except
[i
] > 0; i
++)
2368 if (sigaddset(&ss
, except
[i
]) < 0)
2371 return sigprocmask(SIG_SETMASK
, &ss
, NULL
);
2374 int pa_reset_sigs(int except
, ...) {
2379 va_start(ap
, except
);
2382 for (n
= 1; va_arg(ap
, int) >= 0; n
++)
2387 p
= pa_xnew(int, n
+1);
2389 va_start(ap
, except
);
2396 while ((sig
= va_arg(ap
, int)) >= 0)
2403 r
= pa_reset_sigsv(p
);
2409 int pa_reset_sigsv(const int except
[]) {
2412 for (sig
= 1; sig
< NSIG
; sig
++) {
2413 pa_bool_t reset
= TRUE
;
2424 for (i
= 0; except
[i
] > 0; i
++) {
2425 if (sig
== except
[i
]) {
2434 struct sigaction sa
;
2436 memset(&sa
, 0, sizeof(sa
));
2437 sa
.sa_handler
= SIG_DFL
;
2439 /* On Linux the first two RT signals are reserved by
2440 * glibc, and sigaction() will return EINVAL for them. */
2441 if ((sigaction(sig
, &sa
, NULL
) < 0))
2442 if (errno
!= EINVAL
)
2450 void pa_set_env(const char *key
, const char *value
) {
2454 putenv(pa_sprintf_malloc("%s=%s", key
, value
));
2457 pa_bool_t
pa_in_system_mode(void) {
2460 if (!(e
= getenv("PULSE_SYSTEM")))
2466 char *pa_get_user_name_malloc(void) {
2470 #ifdef _SC_LOGIN_NAME_MAX
2471 k
= (ssize_t
) sysconf(_SC_LOGIN_NAME_MAX
);
2477 u
= pa_xnew(char, k
+1);
2479 if (!(pa_get_user_name(u
, k
))) {
2487 char *pa_get_host_name_malloc(void) {
2496 if (!pa_get_host_name(c
, l
)) {
2498 if (errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2501 } else if (strlen(c
) < l
-1) {
2509 u
= pa_utf8_filter(c
);
2514 /* Hmm, the hostname is as long the space we offered the
2515 * function, we cannot know if it fully fit in, so let's play
2516 * safe and retry. */
2525 char *pa_machine_id(void) {
2529 /* The returned value is supposed be some kind of ascii identifier
2530 * that is unique and stable across reboots. */
2532 /* First we try the D-Bus UUID, which is the best option we have,
2533 * since it fits perfectly our needs and is not as volatile as the
2534 * hostname which might be set from dhcp. */
2536 if ((f
= fopen(PA_MACHINE_ID
, "r"))) {
2537 char ln
[34] = "", *r
;
2539 r
= fgets(ln
, sizeof(ln
)-1, f
);
2545 return pa_utf8_filter(ln
);
2548 if ((h
= pa_get_host_name_malloc()))
2551 /* If no hostname was set we use the POSIX hostid. It's usually
2552 * the IPv4 address. Might not be that stable. */
2553 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid
);
2556 char *pa_session_id(void) {
2559 if (!(e
= getenv("XDG_SESSION_COOKIE")))
2562 return pa_utf8_filter(e
);
2565 char *pa_uname_string(void) {
2568 pa_assert_se(uname(&u
) >= 0);
2570 return pa_sprintf_malloc("%s %s %s %s", u
.sysname
, u
.machine
, u
.release
, u
.version
);
2573 #ifdef HAVE_VALGRIND_MEMCHECK_H
2574 pa_bool_t
pa_in_valgrind(void) {
2577 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2578 * here instead of really checking whether we run in valgrind or
2582 b
= getenv("VALGRIND") ? 2 : 1;
2588 unsigned pa_gcd(unsigned a
, unsigned b
) {
2599 void pa_reduce(unsigned *num
, unsigned *den
) {
2601 unsigned gcd
= pa_gcd(*num
, *den
);
2609 pa_assert(pa_gcd(*num
, *den
) == 1);
2612 unsigned pa_ncpus(void) {
2615 #ifdef _SC_NPROCESSORS_CONF
2616 ncpus
= sysconf(_SC_NPROCESSORS_CONF
);
2621 return ncpus
<= 0 ? 1 : (unsigned) ncpus
;
2624 char *pa_replace(const char*s
, const char*a
, const char *b
) {
2633 sb
= pa_strbuf_new();
2638 if (!(p
= strstr(s
, a
)))
2641 pa_strbuf_putsn(sb
, s
, p
-s
);
2642 pa_strbuf_puts(sb
, b
);
2646 pa_strbuf_puts(sb
, s
);
2648 return pa_strbuf_tostring_free(sb
);
2651 char *pa_unescape(char *p
) {
2653 pa_bool_t escaped
= FALSE
;
2655 for (s
= p
, d
= p
; *s
; s
++) {
2656 if (!escaped
&& *s
== '\\') {
2670 char *pa_realpath(const char *path
) {
2674 /* We want only abolsute paths */
2675 if (path
[0] != '/') {
2680 #if defined(__GLIBC__) || defined(__APPLE__)
2684 if (!(r
= realpath(path
, NULL
)))
2687 /* We copy this here in case our pa_xmalloc() is not
2688 * implemented on top of libc malloc() */
2692 #elif defined(PATH_MAX)
2695 path_buf
= pa_xmalloc(PATH_MAX
);
2697 if (!(t
= realpath(path
, path_buf
))) {
2703 #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."
2709 void pa_disable_sigpipe(void) {
2712 struct sigaction sa
;
2716 if (sigaction(SIGPIPE
, NULL
, &sa
) < 0) {
2717 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2721 sa
.sa_handler
= SIG_IGN
;
2723 if (sigaction(SIGPIPE
, &sa
, NULL
) < 0) {
2724 pa_log("sigaction(): %s", pa_cstrerror(errno
));
2730 void pa_xfreev(void**a
) {
2736 for (p
= a
; *p
; p
++)
2742 char **pa_split_spaces_strv(const char *s
) {
2744 unsigned i
= 0, n
= 8;
2745 const char *state
= NULL
;
2747 t
= pa_xnew(char*, n
);
2748 while ((e
= pa_split_spaces(s
, &state
))) {
2753 t
= pa_xrenew(char*, t
, n
);
2766 char* pa_maybe_prefix_path(const char *path
, const char *prefix
) {
2769 if (pa_is_path_absolute(path
))
2770 return pa_xstrdup(path
);
2772 return pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", prefix
, path
);
2775 size_t pa_pipe_buf(int fd
) {
2780 if ((n
= fpathconf(fd
, _PC_PIPE_BUF
)) >= 0)
2791 void pa_reset_personality(void) {
2794 if (personality(PER_LINUX
) < 0)
2795 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno
));
2800 #if defined(__linux__) && !defined(__OPTIMIZE__)
2802 pa_bool_t
pa_run_from_build_tree(void) {
2804 pa_bool_t b
= FALSE
;
2806 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2809 if ((rp
= pa_readlink("/proc/self/exe"))) {
2810 b
= pa_startswith(rp
, PA_BUILDDIR
);