2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
38 #include <sys/types.h>
42 #ifdef HAVE_LANGINFO_H
47 #include <sys/utsname.h>
50 #if defined(HAVE_REGEX_H)
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
76 #ifdef HAVE_SYS_MMAN_H
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
117 #include <sys/personality.h>
120 #include <pulse/xmalloc.h>
121 #include <pulse/util.h>
122 #include <pulse/utf8.h>
124 #include <pulsecore/core-error.h>
125 #include <pulsecore/socket.h>
126 #include <pulsecore/log.h>
127 #include <pulsecore/macro.h>
128 #include <pulsecore/thread.h>
129 #include <pulsecore/strbuf.h>
130 #include <pulsecore/usergroup.h>
131 #include <pulsecore/strlist.h>
132 #include <pulsecore/cpu-x86.h>
133 #include <pulsecore/pipe.h>
135 #include "core-util.h"
137 /* Not all platforms have this */
139 #define MSG_NOSIGNAL 0
142 #define NEWLINE "\r\n"
143 #define WHITESPACE "\n\r \t"
145 static pa_strlist *recorded_env = NULL;
149 #define PULSE_ROOTENV "PULSE_ROOT"
151 int pa_set_root(HANDLE handle) {
152 char library_path[MAX_PATH], *sep;
154 /* FIXME: Needs to set errno */
156 if (!GetModuleFileName(handle, library_path, MAX_PATH))
159 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
163 if (!SetEnvironmentVariable(PULSE_ROOTENV, library_path))
171 /** Make a file descriptor nonblock. Doesn't do any error checking */
172 void pa_make_fd_nonblock(int fd) {
178 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
180 if (!(v & O_NONBLOCK))
181 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
183 #elif defined(OS_IS_WIN32)
185 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
186 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
187 pa_log_warn("Only sockets can be made non-blocking!");
190 pa_log_warn("Non-blocking I/O not supported.!");
195 /* Set the FD_CLOEXEC flag for a fd */
196 void pa_make_fd_cloexec(int fd) {
202 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
204 if (!(v & FD_CLOEXEC))
205 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
210 /** Creates a directory securely */
211 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
213 int r, saved_errno, fd;
222 u = umask((~m) & 0777);
228 if (r < 0 && errno != EEXIST)
231 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
245 if (fstat(fd, &st) < 0) {
246 pa_assert_se(pa_close(fd) >= 0);
250 if (!S_ISDIR(st.st_mode)) {
251 pa_assert_se(pa_close(fd) >= 0);
257 if (uid == (uid_t)-1)
259 if (gid == (gid_t)-1)
261 (void) fchown(fd, uid, gid);
265 (void) fchmod(fd, m);
268 pa_assert_se(pa_close(fd) >= 0);
272 if (lstat(dir, &st) < 0)
274 if (stat(dir, &st) < 0)
279 if (!S_ISDIR(st.st_mode) ||
280 (st.st_uid != uid) ||
281 (st.st_gid != gid) ||
282 ((st.st_mode & 0777) != m)) {
287 pa_log_warn("Secure directory creation not supported on Win32.");
300 /* Return a newly allocated sting containing the parent directory of the specified file */
301 char *pa_parent_dir(const char *fn) {
302 char *slash, *dir = pa_xstrdup(fn);
304 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
314 /* Creates a the parent directory of the specified path securely */
315 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
319 if (!(dir = pa_parent_dir(fn)))
322 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
332 /** Platform independent read function. Necessary since not all
333 * systems treat all file descriptors equal. If type is
334 * non-NULL it is used to cache the type of the fd. This is
335 * useful for making sure that only a single syscall is executed per
336 * function call. The variable pointed to should be initialized to 0
338 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
342 if (!type || *type == 0) {
345 if ((r = recv(fd, buf, count, 0)) >= 0)
348 if (WSAGetLastError() != WSAENOTSOCK) {
349 errno = WSAGetLastError();
362 if ((r = read(fd, buf, count)) < 0)
370 /** Similar to pa_read(), but handles writes */
371 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
373 if (!type || *type == 0) {
377 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
389 if (WSAGetLastError() != WSAENOTSOCK) {
390 errno = WSAGetLastError();
394 if (errno != ENOTSOCK)
405 if ((r = write(fd, buf, count)) < 0)
413 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
414 * unless EOF is reached or an error occurred */
415 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
431 if ((r = pa_read(fd, data, size, type)) < 0)
438 data = (uint8_t*) data + r;
445 /** Similar to pa_loop_read(), but wraps write() */
446 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
462 if ((r = pa_write(fd, data, size, type)) < 0)
469 data = (const uint8_t*) data + r;
476 /** Platform independent read function. Necessary since not all
477 * systems treat all file descriptors equal. */
478 int pa_close(int fd) {
483 if ((ret = closesocket(fd)) == 0)
486 if (WSAGetLastError() != WSAENOTSOCK) {
487 errno = WSAGetLastError();
495 if ((r = close(fd)) < 0)
503 /* Print a warning messages in case that the given signal is not
504 * blocked or trapped */
505 void pa_check_signal_is_blocked(int sig) {
506 #ifdef HAVE_SIGACTION
510 /* If POSIX threads are supported use thread-aware
511 * pthread_sigmask() function, to check if the signal is
512 * blocked. Otherwise fall back to sigprocmask() */
515 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
517 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
518 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
525 if (sigismember(&set, sig))
528 /* Check whether the signal is trapped */
530 if (sigaction(sig, NULL, &sa) < 0) {
531 pa_log("sigaction(): %s", pa_cstrerror(errno));
535 if (sa.sa_handler != SIG_DFL)
538 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
539 #else /* HAVE_SIGACTION */
540 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
544 /* The following function is based on an example from the GNU libc
545 * documentation. This function is similar to GNU's asprintf(). */
546 char *pa_sprintf_malloc(const char *format, ...) {
556 c = pa_xrealloc(c, size);
558 va_start(ap, format);
559 r = vsnprintf(c, size, format, ap);
564 if (r > -1 && (size_t) r < size)
567 if (r > -1) /* glibc 2.1 */
574 /* Same as the previous function, but use a va_list instead of an
576 char *pa_vsprintf_malloc(const char *format, va_list ap) {
586 c = pa_xrealloc(c, size);
589 r = vsnprintf(c, size, format, aq);
594 if (r > -1 && (size_t) r < size)
597 if (r > -1) /* glibc 2.1 */
604 /* Similar to OpenBSD's strlcpy() function */
605 char *pa_strlcpy(char *b, const char *s, size_t l) {
623 #ifdef _POSIX_PRIORITY_SCHEDULING
624 static int set_scheduler(int rtprio) {
626 struct sched_param sp;
632 dbus_error_init(&error);
636 sp.sched_priority = rtprio;
638 #ifdef SCHED_RESET_ON_FORK
639 if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
640 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
645 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
646 pa_log_debug("SCHED_RR worked.");
649 #endif /* HAVE_SCHED_H */
652 /* Try to talk to RealtimeKit */
654 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
655 pa_log("Failed to connect to system bus: %s\n", error.message);
656 dbus_error_free(&error);
661 /* We need to disable exit on disconnect because otherwise
662 * dbus_shutdown will kill us. See
663 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
664 dbus_connection_set_exit_on_disconnect(bus, FALSE);
666 r = rtkit_make_realtime(bus, 0, rtprio);
667 dbus_connection_unref(bus);
670 pa_log_debug("RealtimeKit worked.");
683 /* Make the current thread a realtime thread, and acquire the highest
684 * rtprio we can get that is less or equal the specified parameter. If
685 * the thread is already realtime, don't do anything. */
686 int pa_make_realtime(int rtprio) {
688 #ifdef _POSIX_PRIORITY_SCHEDULING
691 if (set_scheduler(rtprio) >= 0) {
692 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
696 for (p = rtprio-1; p >= 1; p--)
697 if (set_scheduler(p) >= 0) {
698 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
701 #elif defined(OS_IS_WIN32)
702 /* Windows only allows realtime scheduling to be set on a per process basis.
703 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
704 if(SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) {
705 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
709 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
714 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
718 #ifdef HAVE_SYS_RESOURCE_H
719 static int set_nice(int nice_level) {
725 dbus_error_init(&error);
728 #ifdef HAVE_SYS_RESOURCE_H
729 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
730 pa_log_debug("setpriority() worked.");
736 /* Try to talk to RealtimeKit */
738 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
739 pa_log("Failed to connect to system bus: %s\n", error.message);
740 dbus_error_free(&error);
745 /* We need to disable exit on disconnect because otherwise
746 * dbus_shutdown will kill us. See
747 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
748 dbus_connection_set_exit_on_disconnect(bus, FALSE);
750 r = rtkit_make_high_priority(bus, 0, nice_level);
751 dbus_connection_unref(bus);
754 pa_log_debug("RealtimeKit worked.");
765 /* Raise the priority of the current process as much as possible that
766 * is <= the specified nice level..*/
767 int pa_raise_priority(int nice_level) {
769 #ifdef HAVE_SYS_RESOURCE_H
772 if (set_nice(nice_level) >= 0) {
773 pa_log_info("Successfully gained nice level %i.", nice_level);
777 for (n = nice_level+1; n < 0; n++)
778 if (set_nice(n) >= 0) {
779 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
783 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
788 if (nice_level < 0) {
789 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
790 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
795 pa_log_info("Successfully gained high priority class.");
802 /* Reset the priority to normal, inverting the changes made by
803 * pa_raise_priority() and pa_make_realtime()*/
804 void pa_reset_priority(void) {
805 #ifdef HAVE_SYS_RESOURCE_H
806 struct sched_param sp;
808 setpriority(PRIO_PROCESS, 0, 0);
811 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
815 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
819 int pa_match(const char *expr, const char *v) {
824 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
829 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
831 else if (k == REG_NOMATCH)
844 /* Try to parse a boolean string value.*/
845 int pa_parse_boolean(const char *v) {
849 /* First we check language independant */
850 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
852 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
855 #ifdef HAVE_LANGINFO_H
856 /* And then we check language dependant */
857 if ((expr = nl_langinfo(YESEXPR)))
859 if (pa_match(expr, v) > 0)
862 if ((expr = nl_langinfo(NOEXPR)))
864 if (pa_match(expr, v) > 0)
872 /* Split the specified string wherever one of the strings in delimiter
873 * occurs. Each time it is called returns a newly allocated string
874 * with pa_xmalloc(). The variable state points to, should be
875 * initiallized to NULL before the first call. */
876 char *pa_split(const char *c, const char *delimiter, const char**state) {
877 const char *current = *state ? *state : c;
883 l = strcspn(current, delimiter);
889 return pa_xstrndup(current, l);
892 /* Split a string into words. Otherwise similar to pa_split(). */
893 char *pa_split_spaces(const char *c, const char **state) {
894 const char *current = *state ? *state : c;
897 if (!*current || *c == 0)
900 current += strspn(current, WHITESPACE);
901 l = strcspn(current, WHITESPACE);
905 return pa_xstrndup(current, l);
908 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
910 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
911 const char *pa_sig2str(int sig) {
924 char buf[SIG2STR_MAX];
926 if (sig2str(sig, buf) == 0) {
927 pa_xfree(PA_STATIC_TLS_GET(signame));
928 t = pa_sprintf_malloc("SIG%s", buf);
929 PA_STATIC_TLS_SET(signame, t);
937 case SIGHUP: return "SIGHUP";
939 case SIGINT: return "SIGINT";
941 case SIGQUIT: return "SIGQUIT";
943 case SIGILL: return "SIGULL";
945 case SIGTRAP: return "SIGTRAP";
947 case SIGABRT: return "SIGABRT";
949 case SIGBUS: return "SIGBUS";
951 case SIGFPE: return "SIGFPE";
953 case SIGKILL: return "SIGKILL";
956 case SIGUSR1: return "SIGUSR1";
958 case SIGSEGV: return "SIGSEGV";
960 case SIGUSR2: return "SIGUSR2";
963 case SIGPIPE: return "SIGPIPE";
966 case SIGALRM: return "SIGALRM";
968 case SIGTERM: return "SIGTERM";
970 case SIGSTKFLT: return "SIGSTKFLT";
973 case SIGCHLD: return "SIGCHLD";
976 case SIGCONT: return "SIGCONT";
979 case SIGSTOP: return "SIGSTOP";
982 case SIGTSTP: return "SIGTSTP";
985 case SIGTTIN: return "SIGTTIN";
988 case SIGTTOU: return "SIGTTOU";
991 case SIGURG: return "SIGURG";
994 case SIGXCPU: return "SIGXCPU";
997 case SIGXFSZ: return "SIGXFSZ";
1000 case SIGVTALRM: return "SIGVTALRM";
1003 case SIGPROF: return "SIGPROF";
1006 case SIGWINCH: return "SIGWINCH";
1009 case SIGIO: return "SIGIO";
1012 case SIGPWR: return "SIGPWR";
1015 case SIGSYS: return "SIGSYS";
1020 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
1021 pa_xfree(PA_STATIC_TLS_GET(signame));
1022 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
1023 PA_STATIC_TLS_SET(signame, t);
1032 pa_xfree(PA_STATIC_TLS_GET(signame));
1033 t = pa_sprintf_malloc("SIG%i", sig);
1034 PA_STATIC_TLS_SET(signame, t);
1040 /* Check whether the specified GID and the group name match */
1041 static int is_group(gid_t gid, const char *name) {
1042 struct group *group = NULL;
1046 if (!(group = pa_getgrgid_malloc(gid))) {
1050 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1055 r = strcmp(name, group->gr_name) == 0;
1058 pa_getgrgid_free(group);
1063 /* Check the current user is member of the specified group */
1064 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1065 GETGROUPS_T *gids, tgid;
1066 long n = sysconf(_SC_NGROUPS_MAX);
1071 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1073 if ((n = getgroups((int) n, gids)) < 0) {
1074 pa_log("getgroups(): %s", pa_cstrerror(errno));
1078 for (i = 0; i < n; i++) {
1080 if ((k = is_group(gids[i], name)) < 0)
1089 if ((k = is_group(tgid = getgid(), name)) < 0)
1105 /* Check whether the specifc user id is a member of the specified group */
1106 int pa_uid_in_group(uid_t uid, const char *name) {
1107 struct group *group = NULL;
1112 if (!(group = pa_getgrnam_malloc(name))) {
1119 for (i = group->gr_mem; *i; i++) {
1120 struct passwd *pw = NULL;
1123 if (!(pw = pa_getpwnam_malloc(*i)))
1126 if (pw->pw_uid == uid)
1129 pa_getpwnam_free(pw);
1136 pa_getgrnam_free(group);
1141 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1142 gid_t pa_get_gid_of_group(const char *name) {
1143 gid_t ret = (gid_t) -1;
1144 struct group *gr = NULL;
1147 if (!(gr = pa_getgrnam_malloc(name))) {
1156 pa_getgrnam_free(gr);
1160 int pa_check_in_group(gid_t g) {
1161 gid_t gids[NGROUPS_MAX];
1164 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1174 #else /* HAVE_GRP_H */
1176 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1182 int pa_uid_in_group(uid_t uid, const char *name) {
1187 gid_t pa_get_gid_of_group(const char *name) {
1192 int pa_check_in_group(gid_t g) {
1199 /* Lock or unlock a file entirely.
1200 (advisory on UNIX, mandatory on Windows) */
1201 int pa_lock_fd(int fd, int b) {
1203 struct flock f_lock;
1205 /* Try a R/W lock first */
1207 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1208 f_lock.l_whence = SEEK_SET;
1212 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1215 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1216 if (b && errno == EBADF) {
1217 f_lock.l_type = F_RDLCK;
1218 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1222 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1226 HANDLE h = (HANDLE)_get_osfhandle(fd);
1228 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1230 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1233 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1235 /* FIXME: Needs to set errno! */
1241 /* Remove trailing newlines from a string */
1242 char* pa_strip_nl(char *s) {
1245 s[strcspn(s, NEWLINE)] = 0;
1249 char *pa_strip(char *s) {
1252 /* Drops trailing whitespace. Modifies the string in
1253 * place. Returns pointer to first non-space character */
1255 s += strspn(s, WHITESPACE);
1257 for (e = s; *e; e++)
1258 if (!strchr(WHITESPACE, *e))
1269 /* Create a temporary lock file and lock it. */
1270 int pa_lock_lockfile(const char *fn) {
1277 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1281 , S_IRUSR|S_IWUSR)) < 0) {
1282 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1286 if (pa_lock_fd(fd, 1) < 0) {
1287 pa_log_warn("Failed to lock file '%s'.", fn);
1291 if (fstat(fd, &st) < 0) {
1292 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1296 /* Check whether the file has been removed meanwhile. When yes,
1297 * restart this loop, otherwise, we're done */
1298 if (st.st_nlink >= 1)
1301 if (pa_lock_fd(fd, 0) < 0) {
1302 pa_log_warn("Failed to unlock file '%s'.", fn);
1306 if (pa_close(fd) < 0) {
1307 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1318 int saved_errno = errno;
1320 errno = saved_errno;
1326 /* Unlock a temporary lcok file */
1327 int pa_unlock_lockfile(const char *fn, int fd) {
1332 if (unlink(fn) < 0) {
1333 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1338 if (pa_lock_fd(fd, 0) < 0) {
1339 pa_log_warn("Failed to unlock file '%s'.", fn);
1343 if (pa_close(fd) < 0) {
1344 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1351 static char *get_pulse_home(void) {
1356 if (!(h = pa_get_home_dir_malloc())) {
1357 pa_log_error("Failed to get home directory.");
1361 if (stat(h, &st) < 0) {
1362 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1367 if (st.st_uid != getuid()) {
1368 pa_log_error("Home directory %s not ours.", h);
1374 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1382 char *pa_get_state_dir(void) {
1385 /* The state directory shall contain dynamic data that should be
1386 * kept across reboots, and is private to this user */
1388 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1389 if (!(d = get_pulse_home()))
1392 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1393 * dir then this will break. */
1395 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1396 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1404 char *pa_get_home_dir_malloc(void) {
1406 size_t allocated = 128;
1409 homedir = pa_xmalloc(allocated);
1411 if (!pa_get_home_dir(homedir, allocated)) {
1416 if (strlen(homedir) < allocated - 1)
1426 char *pa_get_binary_name_malloc(void) {
1428 size_t allocated = 128;
1431 t = pa_xmalloc(allocated);
1433 if (!pa_get_binary_name(t, allocated)) {
1438 if (strlen(t) < allocated - 1)
1448 static char* make_random_dir(mode_t m) {
1449 static const char table[] =
1450 "abcdefghijklmnopqrstuvwxyz"
1451 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1457 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1458 pathlen = strlen(fn);
1466 for (i = pathlen - 12; i < pathlen; i++)
1467 fn[i] = table[rand() % (sizeof(table)-1)];
1469 u = umask((~m) & 0777);
1476 saved_errno = errno;
1478 errno = saved_errno;
1483 if (errno != EEXIST) {
1484 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1491 static int make_random_dir_and_link(mode_t m, const char *k) {
1494 if (!(p = make_random_dir(m)))
1498 if (symlink(p, k) < 0) {
1499 int saved_errno = errno;
1501 if (errno != EEXIST)
1502 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1507 errno = saved_errno;
1519 char *pa_get_runtime_dir(void) {
1520 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1524 /* The runtime directory shall contain dynamic data that needs NOT
1525 * to be kept accross reboots and is usuallly private to the user,
1526 * except in system mode, where it might be accessible by other
1527 * users, too. Since we need POSIX locking and UNIX sockets in
1528 * this directory, we link it to a random subdir in /tmp, if it
1529 * was not explicitly configured. */
1531 m = pa_in_system_mode() ? 0755U : 0700U;
1533 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1535 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1536 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1540 return pa_xstrdup(d);
1543 if (!(d = get_pulse_home()))
1546 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1547 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1552 if (!(mid = pa_machine_id())) {
1557 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1562 /* OK, first let's check if the "runtime" symlink is already
1565 if (!(p = pa_readlink(k))) {
1567 if (errno != ENOENT) {
1568 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1573 /* Hmm, so the runtime directory didn't exist yet, so let's
1574 * create one in /tmp and symlink that to it */
1576 if (make_random_dir_and_link(0700, k) < 0) {
1578 /* Mhmm, maybe another process was quicker than us,
1579 * let's check if that was valid */
1580 if (errno == EEXIST)
1586 /* No symlink possible, so let's just create the runtime directly */
1594 /* Make sure that this actually makes sense */
1595 if (!pa_is_path_absolute(p)) {
1596 pa_log_error("Path %s in link %s is not absolute.", p, k);
1601 /* Hmm, so this symlink is still around, make sure nobody fools
1605 if (lstat(p, &st) < 0) {
1607 if (errno != ENOENT) {
1608 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1614 if (S_ISDIR(st.st_mode) &&
1615 (st.st_uid == getuid()) &&
1616 ((st.st_mode & 0777) == 0700)) {
1622 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1629 /* Hmm, so the link points to some nonexisting or invalid
1630 * dir. Let's replace it by a new link. We first create a
1631 * temporary link and then rename that to allow concurrent
1632 * execution of this function. */
1634 t = pa_sprintf_malloc("%s.tmp", k);
1636 if (make_random_dir_and_link(0700, t) < 0) {
1638 if (errno != EEXIST) {
1639 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1646 /* Hmm, someone lese was quicker then us. Let's give
1647 * him some time to finish, and retry. */
1652 /* OK, we succeeded in creating the temporary symlink, so
1653 * let's rename it */
1654 if (rename(t, k) < 0) {
1655 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1671 /* Try to open a configuration file. If "env" is specified, open the
1672 * value of the specified environment variable. Otherwise look for a
1673 * file "local" in the home directory or a file "global" in global
1674 * file system. If "result" is non-NULL, a pointer to a newly
1675 * allocated buffer containing the used configuration file is
1677 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1682 if (!getenv(PULSE_ROOTENV))
1686 if (env && (fn = getenv(env))) {
1690 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1691 /* FIXME: Needs to set errno! */
1696 if ((f = pa_fopen_cloexec(fn, "r"))) {
1698 *result = pa_xstrdup(fn);
1703 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1713 if ((e = getenv("PULSE_CONFIG_PATH")))
1714 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1715 else if ((h = pa_get_home_dir_malloc())) {
1716 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1722 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1723 /* FIXME: Needs to set errno! */
1730 if ((f = pa_fopen_cloexec(fn, "r"))) {
1732 *result = pa_xstrdup(fn);
1738 if (errno != ENOENT) {
1739 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1751 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1752 /* FIXME: Needs to set errno! */
1757 if ((f = pa_fopen_cloexec(global, "r"))) {
1760 *result = pa_xstrdup(global);
1770 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1775 if (!getenv(PULSE_ROOTENV))
1779 if (env && (fn = getenv(env))) {
1782 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1783 /* FIXME: Needs to set errno! */
1788 if (access(fn, R_OK) == 0)
1789 return pa_xstrdup(fn);
1791 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1800 if ((e = getenv("PULSE_CONFIG_PATH")))
1801 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1802 else if ((h = pa_get_home_dir_malloc())) {
1803 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1809 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1810 /* FIXME: Needs to set errno! */
1817 if (access(fn, R_OK) == 0) {
1818 char *r = pa_xstrdup(fn);
1823 if (errno != ENOENT) {
1824 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1834 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1835 /* FIXME: Needs to set errno! */
1840 if (access(global, R_OK) == 0)
1841 return pa_xstrdup(global);
1849 /* Format the specified data as a hexademical string */
1850 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1851 size_t i = 0, j = 0;
1852 const char hex[] = "0123456789abcdef";
1856 pa_assert(slength > 0);
1858 while (i < dlength && j+3 <= slength) {
1859 s[j++] = hex[*d >> 4];
1860 s[j++] = hex[*d & 0xF];
1866 s[j < slength ? j : slength] = 0;
1870 /* Convert a hexadecimal digit to a number or -1 if invalid */
1871 static int hexc(char c) {
1872 if (c >= '0' && c <= '9')
1875 if (c >= 'A' && c <= 'F')
1876 return c - 'A' + 10;
1878 if (c >= 'a' && c <= 'f')
1879 return c - 'a' + 10;
1885 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1886 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1892 while (j < dlength && *p) {
1895 if ((b = hexc(*(p++))) < 0)
1898 d[j] = (uint8_t) (b << 4);
1903 if ((b = hexc(*(p++))) < 0)
1906 d[j] |= (uint8_t) b;
1913 /* Returns nonzero when *s starts with *pfx */
1914 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1922 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1925 /* Returns nonzero when *s ends with *sfx */
1926 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1935 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1938 pa_bool_t pa_is_path_absolute(const char *fn) {
1944 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1948 char *pa_make_path_absolute(const char *p) {
1954 if (pa_is_path_absolute(p))
1955 return pa_xstrdup(p);
1957 if (!(cwd = pa_getcwd()))
1958 return pa_xstrdup(p);
1960 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1965 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1966 * if fn is non-null and starts with / return fn
1967 * otherwise append fn to the run time path and return it */
1968 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1971 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1976 if (pa_is_path_absolute(fn))
1977 return pa_xstrdup(fn);
1985 if (!(mid = pa_machine_id())) {
1990 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1993 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
2001 char *pa_runtime_path(const char *fn) {
2002 return get_path(fn, FALSE, TRUE);
2005 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
2006 return get_path(fn, appendmid, FALSE);
2009 /* Convert the string s to a signed integer in *ret_i */
2010 int pa_atoi(const char *s, int32_t *ret_i) {
2018 l = strtol(s, &x, 0);
2020 if (!x || *x || errno) {
2026 if ((int32_t) l != l) {
2031 *ret_i = (int32_t) l;
2036 /* Convert the string s to an unsigned integer in *ret_u */
2037 int pa_atou(const char *s, uint32_t *ret_u) {
2045 l = strtoul(s, &x, 0);
2047 if (!x || *x || errno) {
2053 if ((uint32_t) l != l) {
2058 *ret_u = (uint32_t) l;
2063 #ifdef HAVE_STRTOF_L
2064 static locale_t c_locale = NULL;
2066 static void c_locale_destroy(void) {
2067 freelocale(c_locale);
2071 int pa_atod(const char *s, double *ret_d) {
2078 /* This should be locale independent */
2080 #ifdef HAVE_STRTOF_L
2084 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2085 atexit(c_locale_destroy);
2091 f = strtod_l(s, &x, c_locale);
2099 if (!x || *x || errno) {
2110 /* Same as snprintf, but guarantees NUL-termination on every platform */
2111 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2116 pa_assert(size > 0);
2119 va_start(ap, format);
2120 ret = pa_vsnprintf(str, size, format, ap);
2126 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2127 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2131 pa_assert(size > 0);
2134 ret = vsnprintf(str, size, format, ap);
2141 if ((size_t) ret > size-1)
2144 return (size_t) ret;
2147 /* Truncate the specified string, but guarantee that the string
2148 * returned still validates as UTF8 */
2149 char *pa_truncate_utf8(char *c, size_t l) {
2151 pa_assert(pa_utf8_valid(c));
2158 while (l > 0 && !pa_utf8_valid(c))
2164 char *pa_getcwd(void) {
2168 char *p = pa_xmalloc(l);
2172 if (errno != ERANGE)
2180 void *pa_will_need(const void *p, size_t l) {
2181 #ifdef RLIMIT_MEMLOCK
2192 a = PA_PAGE_ALIGN_PTR(p);
2193 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2195 #ifdef HAVE_POSIX_MADVISE
2196 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2197 pa_log_debug("posix_madvise() worked fine!");
2202 /* Most likely the memory was not mmap()ed from a file and thus
2203 * madvise() didn't work, so let's misuse mlock() do page this
2204 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2205 * inviting, the man page of mlock() tells us: "All pages that
2206 * contain a part of the specified address range are guaranteed to
2207 * be resident in RAM when the call returns successfully." */
2209 #ifdef RLIMIT_MEMLOCK
2210 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2212 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2213 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));
2218 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2220 bs = PA_PAGE_SIZE*4;
2223 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2226 while (size > 0 && bs > 0) {
2231 if (mlock(a, bs) < 0) {
2232 bs = PA_PAGE_ALIGN(bs / 2);
2236 pa_assert_se(munlock(a, bs) == 0);
2238 a = (const uint8_t*) a + bs;
2244 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2246 pa_log_debug("mlock() worked fine!");
2251 void pa_close_pipe(int fds[2]) {
2255 pa_assert_se(pa_close(fds[0]) == 0);
2258 pa_assert_se(pa_close(fds[1]) == 0);
2260 fds[0] = fds[1] = -1;
2263 char *pa_readlink(const char *p) {
2264 #ifdef HAVE_READLINK
2273 if ((n = readlink(p, c, l-1)) < 0) {
2278 if ((size_t) n < l-1) {
2291 int pa_close_all(int except_fd, ...) {
2296 va_start(ap, except_fd);
2299 for (n = 1; va_arg(ap, int) >= 0; n++)
2304 p = pa_xnew(int, n+1);
2306 va_start(ap, except_fd);
2309 if (except_fd >= 0) {
2313 while ((fd = va_arg(ap, int)) >= 0)
2320 r = pa_close_allv(p);
2326 int pa_close_allv(const int except_fds[]) {
2335 if ((d = opendir("/proc/self/fd"))) {
2339 while ((de = readdir(d))) {
2345 if (de->d_name[0] == '.')
2349 l = strtol(de->d_name, &e, 10);
2350 if (errno != 0 || !e || *e) {
2358 if ((long) fd != l) {
2371 for (i = 0; except_fds[i] >= 0; i++)
2372 if (except_fds[i] == fd) {
2380 if (pa_close(fd) < 0) {
2381 saved_errno = errno;
2383 errno = saved_errno;
2395 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2396 maxfd = (int) rl.rlim_max;
2398 maxfd = sysconf(_SC_OPEN_MAX);
2400 for (fd = 3; fd < maxfd; fd++) {
2405 for (i = 0; except_fds[i] >= 0; i++)
2406 if (except_fds[i] == fd) {
2414 if (pa_close(fd) < 0 && errno != EBADF)
2417 #endif /* !OS_IS_WIN32 */
2422 int pa_unblock_sigs(int except, ...) {
2427 va_start(ap, except);
2430 for (n = 1; va_arg(ap, int) >= 0; n++)
2435 p = pa_xnew(int, n+1);
2437 va_start(ap, except);
2444 while ((sig = va_arg(ap, int)) >= 0)
2451 r = pa_unblock_sigsv(p);
2457 int pa_unblock_sigsv(const int except[]) {
2462 if (sigemptyset(&ss) < 0)
2465 for (i = 0; except[i] > 0; i++)
2466 if (sigaddset(&ss, except[i]) < 0)
2469 return sigprocmask(SIG_SETMASK, &ss, NULL);
2475 int pa_reset_sigs(int except, ...) {
2480 va_start(ap, except);
2483 for (n = 1; va_arg(ap, int) >= 0; n++)
2488 p = pa_xnew(int, n+1);
2490 va_start(ap, except);
2497 while ((sig = va_arg(ap, int)) >= 0)
2504 r = pa_reset_sigsv(p);
2510 int pa_reset_sigsv(const int except[]) {
2514 for (sig = 1; sig < NSIG; sig++) {
2515 pa_bool_t reset = TRUE;
2526 for (i = 0; except[i] > 0; i++) {
2527 if (sig == except[i]) {
2536 struct sigaction sa;
2538 memset(&sa, 0, sizeof(sa));
2539 sa.sa_handler = SIG_DFL;
2541 /* On Linux the first two RT signals are reserved by
2542 * glibc, and sigaction() will return EINVAL for them. */
2543 if ((sigaction(sig, &sa, NULL) < 0))
2544 if (errno != EINVAL)
2553 void pa_set_env(const char *key, const char *value) {
2557 /* This is not thread-safe */
2560 SetEnvironmentVariable(key, value);
2562 setenv(key, value, 1);
2566 void pa_set_env_and_record(const char *key, const char *value) {
2570 /* This is not thread-safe */
2572 pa_set_env(key, value);
2573 recorded_env = pa_strlist_prepend(recorded_env, key);
2576 void pa_unset_env_recorded(void) {
2578 /* This is not thread-safe */
2583 recorded_env = pa_strlist_pop(recorded_env, &s);
2589 SetEnvironmentVariable(s, NULL);
2597 pa_bool_t pa_in_system_mode(void) {
2600 if (!(e = getenv("PULSE_SYSTEM")))
2606 char *pa_get_user_name_malloc(void) {
2610 #ifdef _SC_LOGIN_NAME_MAX
2611 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2617 u = pa_xnew(char, k+1);
2619 if (!(pa_get_user_name(u, k))) {
2627 char *pa_get_host_name_malloc(void) {
2636 if (!pa_get_host_name(c, l)) {
2638 if (errno != EINVAL && errno != ENAMETOOLONG)
2641 } else if (strlen(c) < l-1) {
2649 u = pa_utf8_filter(c);
2654 /* Hmm, the hostname is as long the space we offered the
2655 * function, we cannot know if it fully fit in, so let's play
2656 * safe and retry. */
2665 char *pa_machine_id(void) {
2669 /* The returned value is supposed be some kind of ascii identifier
2670 * that is unique and stable across reboots. */
2672 /* First we try the D-Bus UUID, which is the best option we have,
2673 * since it fits perfectly our needs and is not as volatile as the
2674 * hostname which might be set from dhcp. */
2676 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
2677 char ln[34] = "", *r;
2679 r = fgets(ln, sizeof(ln)-1, f);
2685 return pa_utf8_filter(ln);
2688 if ((h = pa_get_host_name_malloc()))
2692 /* If no hostname was set we use the POSIX hostid. It's usually
2693 * the IPv4 address. Might not be that stable. */
2694 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2700 char *pa_session_id(void) {
2703 if (!(e = getenv("XDG_SESSION_COOKIE")))
2706 return pa_utf8_filter(e);
2709 char *pa_uname_string(void) {
2713 pa_assert_se(uname(&u) >= 0);
2715 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2721 i.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2722 pa_assert_se(GetVersionEx(&i));
2724 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i.dwMajorVersion, i.dwMinorVersion, i.dwBuildNumber, i.szCSDVersion);
2728 #ifdef HAVE_VALGRIND_MEMCHECK_H
2729 pa_bool_t pa_in_valgrind(void) {
2732 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2733 * here instead of really checking whether we run in valgrind or
2737 b = getenv("VALGRIND") ? 2 : 1;
2743 unsigned pa_gcd(unsigned a, unsigned b) {
2754 void pa_reduce(unsigned *num, unsigned *den) {
2756 unsigned gcd = pa_gcd(*num, *den);
2764 pa_assert(pa_gcd(*num, *den) == 1);
2767 unsigned pa_ncpus(void) {
2770 #ifdef _SC_NPROCESSORS_CONF
2771 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2776 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2779 char *pa_replace(const char*s, const char*a, const char *b) {
2788 sb = pa_strbuf_new();
2793 if (!(p = strstr(s, a)))
2796 pa_strbuf_putsn(sb, s, p-s);
2797 pa_strbuf_puts(sb, b);
2801 pa_strbuf_puts(sb, s);
2803 return pa_strbuf_tostring_free(sb);
2806 char *pa_escape(const char *p, const char *chars) {
2809 pa_strbuf *buf = pa_strbuf_new();
2811 for (s = p; *s; ++s) {
2813 pa_strbuf_putc(buf, '\\');
2815 for (c = chars; *c; ++c) {
2817 pa_strbuf_putc(buf, '\\');
2822 pa_strbuf_putc(buf, *s);
2825 return pa_strbuf_tostring_free(buf);
2828 char *pa_unescape(char *p) {
2830 pa_bool_t escaped = FALSE;
2832 for (s = p, d = p; *s; s++) {
2833 if (!escaped && *s == '\\') {
2847 char *pa_realpath(const char *path) {
2851 /* We want only abolsute paths */
2852 if (path[0] != '/') {
2857 #if defined(__GLIBC__) || defined(__APPLE__)
2861 if (!(r = realpath(path, NULL)))
2864 /* We copy this here in case our pa_xmalloc() is not
2865 * implemented on top of libc malloc() */
2869 #elif defined(PATH_MAX)
2872 path_buf = pa_xmalloc(PATH_MAX);
2874 #if defined(OS_IS_WIN32)
2875 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2880 if (!(t = realpath(path, path_buf))) {
2887 #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."
2893 void pa_disable_sigpipe(void) {
2896 struct sigaction sa;
2900 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2901 pa_log("sigaction(): %s", pa_cstrerror(errno));
2905 sa.sa_handler = SIG_IGN;
2907 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2908 pa_log("sigaction(): %s", pa_cstrerror(errno));
2914 void pa_xfreev(void**a) {
2920 for (p = a; *p; p++)
2926 char **pa_split_spaces_strv(const char *s) {
2928 unsigned i = 0, n = 8;
2929 const char *state = NULL;
2931 t = pa_xnew(char*, n);
2932 while ((e = pa_split_spaces(s, &state))) {
2937 t = pa_xrenew(char*, t, n);
2950 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2953 if (pa_is_path_absolute(path))
2954 return pa_xstrdup(path);
2956 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2959 size_t pa_pipe_buf(int fd) {
2964 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2975 void pa_reset_personality(void) {
2978 if (personality(PER_LINUX) < 0)
2979 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2984 #if defined(__linux__) && !defined(__OPTIMIZE__)
2986 pa_bool_t pa_run_from_build_tree(void) {
2988 pa_bool_t b = FALSE;
2990 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2993 if ((rp = pa_readlink("/proc/self/exe"))) {
2994 b = pa_startswith(rp, PA_BUILDDIR);
3003 const char *pa_get_temp_dir(void) {
3006 if ((t = getenv("TMPDIR")) &&
3007 pa_is_path_absolute(t))
3010 if ((t = getenv("TMP")) &&
3011 pa_is_path_absolute(t))
3014 if ((t = getenv("TEMP")) &&
3015 pa_is_path_absolute(t))
3018 if ((t = getenv("TEMPDIR")) &&
3019 pa_is_path_absolute(t))
3025 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3033 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3036 if (errno != EINVAL)
3040 if ((fd = open(fn, flags, mode)) < 0)
3044 /* Some implementations might simply ignore O_CLOEXEC if it is not
3045 * understood, make sure FD_CLOEXEC is enabled anyway */
3047 pa_make_fd_cloexec(fd);
3051 int pa_socket_cloexec(int domain, int type, int protocol) {
3055 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3058 if (errno != EINVAL)
3062 if ((fd = socket(domain, type, protocol)) < 0)
3066 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3067 * not understood, make sure FD_CLOEXEC is enabled anyway */
3069 pa_make_fd_cloexec(fd);
3073 int pa_pipe_cloexec(int pipefd[2]) {
3077 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3080 if (errno != EINVAL && errno != ENOSYS)
3085 if ((r = pipe(pipefd)) < 0)
3089 pa_make_fd_cloexec(pipefd[0]);
3090 pa_make_fd_cloexec(pipefd[1]);
3095 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3099 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3102 if (errno != EINVAL && errno != ENOSYS)
3107 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3111 pa_make_fd_cloexec(fd);
3115 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3119 m = pa_sprintf_malloc("%se", mode);
3122 if ((f = fopen(path, m))) {
3129 if (errno != EINVAL)
3132 if (!(f = fopen(path, mode)))
3136 pa_make_fd_cloexec(fileno(f));
3140 void pa_nullify_stdfds(void) {
3143 pa_close(STDIN_FILENO);
3144 pa_close(STDOUT_FILENO);
3145 pa_close(STDERR_FILENO);
3147 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3148 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3149 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3156 char *pa_read_line_from_file(const char *fn) {
3158 char ln[256] = "", *r;
3160 if (!(f = pa_fopen_cloexec(fn, "r")))
3163 r = fgets(ln, sizeof(ln)-1, f);
3172 return pa_xstrdup(ln);
3175 pa_bool_t pa_running_in_vm(void) {
3177 #if defined(__i386__) || defined(__x86_64__)
3179 /* Both CPUID and DMI are x86 specific interfaces... */
3181 uint32_t eax = 0x40000000;
3188 const char *const dmi_vendors[] = {
3189 "/sys/class/dmi/id/sys_vendor",
3190 "/sys/class/dmi/id/board_vendor",
3191 "/sys/class/dmi/id/bios_vendor"
3196 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3199 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3201 if (pa_startswith(s, "QEMU") ||
3202 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3203 pa_startswith(s, "VMware") ||
3204 pa_startswith(s, "VMW") ||
3205 pa_startswith(s, "Microsoft Corporation") ||
3206 pa_startswith(s, "innotek GmbH") ||
3207 pa_startswith(s, "Xen")) {
3219 /* http://lwn.net/Articles/301888/ */
3222 __asm__ __volatile__ (
3223 /* ebx/rbx is being used for PIC! */
3224 " push %%"PA_REG_b" \n\t"
3226 " mov %%ebx, %1 \n\t"
3227 " pop %%"PA_REG_b" \n\t"
3229 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3233 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3234 pa_streq(sig.text, "KVMKVMKVM") ||
3235 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3236 pa_streq(sig.text, "VMwareVMware") ||
3237 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3238 pa_streq(sig.text, "Microsoft Hv"))