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>
119 #include <pulsecore/strlist.h>
120 #include <pulsecore/cpu-x86.h>
122 #include "core-util.h"
124 /* Not all platforms have this */
126 #define MSG_NOSIGNAL 0
129 static pa_strlist *recorded_env = NULL;
133 #define PULSE_ROOTENV "PULSE_ROOT"
135 int pa_set_root(HANDLE handle) {
136 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
138 strcpy(library_path, PULSE_ROOTENV "=");
140 /* FIXME: Needs to set errno */
142 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
145 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
149 if (_putenv(library_path) < 0)
157 /** Make a file descriptor nonblock. Doesn't do any error checking */
158 void pa_make_fd_nonblock(int fd) {
164 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
166 if (!(v & O_NONBLOCK))
167 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
169 #elif defined(OS_IS_WIN32)
171 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
172 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
173 pa_log_warn("Only sockets can be made non-blocking!");
176 pa_log_warn("Non-blocking I/O not supported.!");
181 /* Set the FD_CLOEXEC flag for a fd */
182 void pa_make_fd_cloexec(int fd) {
188 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
190 if (!(v & FD_CLOEXEC))
191 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
196 /** Creates a directory securely */
197 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
208 u = umask((~m) & 0777);
214 if (r < 0 && errno != EEXIST)
218 if (uid == (uid_t)-1)
220 if (gid == (gid_t)-1)
222 (void) chown(dir, uid, gid);
230 if (lstat(dir, &st) < 0)
232 if (stat(dir, &st) < 0)
237 if (!S_ISDIR(st.st_mode) ||
238 (st.st_uid != uid) ||
239 (st.st_gid != gid) ||
240 ((st.st_mode & 0777) != m)) {
245 pa_log_warn("Secure directory creation not supported on Win32.");
258 /* Return a newly allocated sting containing the parent directory of the specified file */
259 char *pa_parent_dir(const char *fn) {
260 char *slash, *dir = pa_xstrdup(fn);
262 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
272 /* Creates a the parent directory of the specified path securely */
273 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
277 if (!(dir = pa_parent_dir(fn)))
280 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
290 /** Platform independent read function. Necessary since not all
291 * systems treat all file descriptors equal. If type is
292 * non-NULL it is used to cache the type of the fd. This is
293 * useful for making sure that only a single syscall is executed per
294 * function call. The variable pointed to should be initialized to 0
296 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
300 if (!type || *type == 0) {
303 if ((r = recv(fd, buf, count, 0)) >= 0)
306 if (WSAGetLastError() != WSAENOTSOCK) {
307 errno = WSAGetLastError();
320 if ((r = read(fd, buf, count)) < 0)
328 /** Similar to pa_read(), but handles writes */
329 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
331 if (!type || *type == 0) {
335 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
347 if (WSAGetLastError() != WSAENOTSOCK) {
348 errno = WSAGetLastError();
352 if (errno != ENOTSOCK)
363 if ((r = write(fd, buf, count)) < 0)
371 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
372 * unless EOF is reached or an error occurred */
373 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
389 if ((r = pa_read(fd, data, size, type)) < 0)
396 data = (uint8_t*) data + r;
403 /** Similar to pa_loop_read(), but wraps write() */
404 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
420 if ((r = pa_write(fd, data, size, type)) < 0)
427 data = (const uint8_t*) data + r;
434 /** Platform independent read function. Necessary since not all
435 * systems treat all file descriptors equal. */
436 int pa_close(int fd) {
441 if ((ret = closesocket(fd)) == 0)
444 if (WSAGetLastError() != WSAENOTSOCK) {
445 errno = WSAGetLastError();
453 if ((r = close(fd)) < 0)
461 /* Print a warning messages in case that the given signal is not
462 * blocked or trapped */
463 void pa_check_signal_is_blocked(int sig) {
464 #ifdef HAVE_SIGACTION
468 /* If POSIX threads are supported use thread-aware
469 * pthread_sigmask() function, to check if the signal is
470 * blocked. Otherwise fall back to sigprocmask() */
473 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
475 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
476 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
483 if (sigismember(&set, sig))
486 /* Check whether the signal is trapped */
488 if (sigaction(sig, NULL, &sa) < 0) {
489 pa_log("sigaction(): %s", pa_cstrerror(errno));
493 if (sa.sa_handler != SIG_DFL)
496 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
497 #else /* HAVE_SIGACTION */
498 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
502 /* The following function is based on an example from the GNU libc
503 * documentation. This function is similar to GNU's asprintf(). */
504 char *pa_sprintf_malloc(const char *format, ...) {
514 c = pa_xrealloc(c, size);
516 va_start(ap, format);
517 r = vsnprintf(c, size, format, ap);
522 if (r > -1 && (size_t) r < size)
525 if (r > -1) /* glibc 2.1 */
532 /* Same as the previous function, but use a va_list instead of an
534 char *pa_vsprintf_malloc(const char *format, va_list ap) {
544 c = pa_xrealloc(c, size);
547 r = vsnprintf(c, size, format, aq);
552 if (r > -1 && (size_t) r < size)
555 if (r > -1) /* glibc 2.1 */
562 /* Similar to OpenBSD's strlcpy() function */
563 char *pa_strlcpy(char *b, const char *s, size_t l) {
581 static int set_scheduler(int rtprio) {
582 struct sched_param sp;
588 dbus_error_init(&error);
592 sp.sched_priority = rtprio;
594 #ifdef SCHED_RESET_ON_FORK
595 if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
596 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
601 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
602 pa_log_debug("SCHED_RR worked.");
607 /* Try to talk to RealtimeKit */
609 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
610 pa_log("Failed to connect to system bus: %s\n", error.message);
611 dbus_error_free(&error);
616 /* We need to disable exit on disconnect because otherwise
617 * dbus_shutdown will kill us. See
618 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
619 dbus_connection_set_exit_on_disconnect(bus, FALSE);
621 r = rtkit_make_realtime(bus, 0, rtprio);
622 dbus_connection_unref(bus);
625 pa_log_debug("RealtimeKit worked.");
637 /* Make the current thread a realtime thread, and acquire the highest
638 * rtprio we can get that is less or equal the specified parameter. If
639 * the thread is already realtime, don't do anything. */
640 int pa_make_realtime(int rtprio) {
642 #ifdef _POSIX_PRIORITY_SCHEDULING
645 if (set_scheduler(rtprio) >= 0) {
646 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
650 for (p = rtprio-1; p >= 1; p--)
651 if (set_scheduler(p)) {
652 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
656 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
665 static int set_nice(int nice_level) {
671 dbus_error_init(&error);
674 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
675 pa_log_debug("setpriority() worked.");
680 /* Try to talk to RealtimeKit */
682 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
683 pa_log("Failed to connect to system bus: %s\n", error.message);
684 dbus_error_free(&error);
689 /* We need to disable exit on disconnect because otherwise
690 * dbus_shutdown will kill us. See
691 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
692 dbus_connection_set_exit_on_disconnect(bus, FALSE);
694 r = rtkit_make_high_priority(bus, 0, nice_level);
695 dbus_connection_unref(bus);
698 pa_log_debug("RealtimeKit worked.");
708 /* Raise the priority of the current process as much as possible that
709 * is <= the specified nice level..*/
710 int pa_raise_priority(int nice_level) {
712 #ifdef HAVE_SYS_RESOURCE_H
715 if (set_nice(nice_level) >= 0) {
716 pa_log_info("Successfully gained nice level %i.", nice_level);
720 for (n = nice_level+1; n < 0; n++)
721 if (set_nice(n) > 0) {
722 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
726 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
731 if (nice_level < 0) {
732 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
733 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
738 pa_log_info("Successfully gained high priority class.");
745 /* Reset the priority to normal, inverting the changes made by
746 * pa_raise_priority() and pa_make_realtime()*/
747 void pa_reset_priority(void) {
748 #ifdef HAVE_SYS_RESOURCE_H
749 struct sched_param sp;
751 setpriority(PRIO_PROCESS, 0, 0);
754 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
758 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
762 int pa_match(const char *expr, const char *v) {
767 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
772 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
774 else if (k == REG_NOMATCH)
787 /* Try to parse a boolean string value.*/
788 int pa_parse_boolean(const char *v) {
792 /* First we check language independant */
793 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
795 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
798 /* And then we check language dependant */
799 if ((expr = nl_langinfo(YESEXPR)))
801 if (pa_match(expr, v) > 0)
804 if ((expr = nl_langinfo(NOEXPR)))
806 if (pa_match(expr, v) > 0)
813 /* Split the specified string wherever one of the strings in delimiter
814 * occurs. Each time it is called returns a newly allocated string
815 * with pa_xmalloc(). The variable state points to, should be
816 * initiallized to NULL before the first call. */
817 char *pa_split(const char *c, const char *delimiter, const char**state) {
818 const char *current = *state ? *state : c;
824 l = strcspn(current, delimiter);
830 return pa_xstrndup(current, l);
833 /* What is interpreted as whitespace? */
834 #define WHITESPACE " \t\n"
836 /* Split a string into words. Otherwise similar to pa_split(). */
837 char *pa_split_spaces(const char *c, const char **state) {
838 const char *current = *state ? *state : c;
841 if (!*current || *c == 0)
844 current += strspn(current, WHITESPACE);
845 l = strcspn(current, WHITESPACE);
849 return pa_xstrndup(current, l);
852 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
854 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
855 const char *pa_sig2str(int sig) {
868 char buf[SIG2STR_MAX];
870 if (sig2str(sig, buf) == 0) {
871 pa_xfree(PA_STATIC_TLS_GET(signame));
872 t = pa_sprintf_malloc("SIG%s", buf);
873 PA_STATIC_TLS_SET(signame, t);
881 case SIGHUP: return "SIGHUP";
883 case SIGINT: return "SIGINT";
885 case SIGQUIT: return "SIGQUIT";
887 case SIGILL: return "SIGULL";
889 case SIGTRAP: return "SIGTRAP";
891 case SIGABRT: return "SIGABRT";
893 case SIGBUS: return "SIGBUS";
895 case SIGFPE: return "SIGFPE";
897 case SIGKILL: return "SIGKILL";
900 case SIGUSR1: return "SIGUSR1";
902 case SIGSEGV: return "SIGSEGV";
904 case SIGUSR2: return "SIGUSR2";
907 case SIGPIPE: return "SIGPIPE";
910 case SIGALRM: return "SIGALRM";
912 case SIGTERM: return "SIGTERM";
914 case SIGSTKFLT: return "SIGSTKFLT";
917 case SIGCHLD: return "SIGCHLD";
920 case SIGCONT: return "SIGCONT";
923 case SIGSTOP: return "SIGSTOP";
926 case SIGTSTP: return "SIGTSTP";
929 case SIGTTIN: return "SIGTTIN";
932 case SIGTTOU: return "SIGTTOU";
935 case SIGURG: return "SIGURG";
938 case SIGXCPU: return "SIGXCPU";
941 case SIGXFSZ: return "SIGXFSZ";
944 case SIGVTALRM: return "SIGVTALRM";
947 case SIGPROF: return "SIGPROF";
950 case SIGWINCH: return "SIGWINCH";
953 case SIGIO: return "SIGIO";
956 case SIGPWR: return "SIGPWR";
959 case SIGSYS: return "SIGSYS";
964 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
965 pa_xfree(PA_STATIC_TLS_GET(signame));
966 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
967 PA_STATIC_TLS_SET(signame, t);
976 pa_xfree(PA_STATIC_TLS_GET(signame));
977 t = pa_sprintf_malloc("SIG%i", sig);
978 PA_STATIC_TLS_SET(signame, t);
984 /* Check whether the specified GID and the group name match */
985 static int is_group(gid_t gid, const char *name) {
986 struct group *group = NULL;
990 if (!(group = pa_getgrgid_malloc(gid)))
995 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1000 r = strcmp(name, group->gr_name) == 0;
1003 pa_getgrgid_free(group);
1008 /* Check the current user is member of the specified group */
1009 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1010 GETGROUPS_T *gids, tgid;
1011 long n = sysconf(_SC_NGROUPS_MAX);
1016 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1018 if ((n = getgroups((int) n, gids)) < 0) {
1019 pa_log("getgroups(): %s", pa_cstrerror(errno));
1023 for (i = 0; i < n; i++) {
1025 if ((k = is_group(gids[i], name)) < 0)
1034 if ((k = is_group(tgid = getgid(), name)) < 0)
1050 /* Check whether the specifc user id is a member of the specified group */
1051 int pa_uid_in_group(uid_t uid, const char *name) {
1052 struct group *group = NULL;
1057 if (!(group = pa_getgrnam_malloc(name)))
1065 for (i = group->gr_mem; *i; i++) {
1066 struct passwd *pw = NULL;
1069 if (!(pw = pa_getpwnam_malloc(*i)))
1072 if (pw->pw_uid == uid)
1075 pa_getpwnam_free(pw);
1082 pa_getgrnam_free(group);
1087 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1088 gid_t pa_get_gid_of_group(const char *name) {
1089 gid_t ret = (gid_t) -1;
1090 struct group *gr = NULL;
1093 if (!(gr = pa_getgrnam_malloc(name)))
1103 pa_getgrnam_free(gr);
1107 int pa_check_in_group(gid_t g) {
1108 gid_t gids[NGROUPS_MAX];
1111 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1121 #else /* HAVE_GRP_H */
1123 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1129 int pa_uid_in_group(uid_t uid, const char *name) {
1134 gid_t pa_get_gid_of_group(const char *name) {
1139 int pa_check_in_group(gid_t g) {
1146 /* Lock or unlock a file entirely.
1147 (advisory on UNIX, mandatory on Windows) */
1148 int pa_lock_fd(int fd, int b) {
1150 struct flock f_lock;
1152 /* Try a R/W lock first */
1154 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1155 f_lock.l_whence = SEEK_SET;
1159 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1162 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1163 if (b && errno == EBADF) {
1164 f_lock.l_type = F_RDLCK;
1165 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1169 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1173 HANDLE h = (HANDLE)_get_osfhandle(fd);
1175 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1177 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1180 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1182 /* FIXME: Needs to set errno! */
1188 /* Remove trailing newlines from a string */
1189 char* pa_strip_nl(char *s) {
1192 s[strcspn(s, "\r\n")] = 0;
1196 /* Create a temporary lock file and lock it. */
1197 int pa_lock_lockfile(const char *fn) {
1204 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1208 , S_IRUSR|S_IWUSR)) < 0) {
1209 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1213 if (pa_lock_fd(fd, 1) < 0) {
1214 pa_log_warn("Failed to lock file '%s'.", fn);
1218 if (fstat(fd, &st) < 0) {
1219 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1223 /* Check whether the file has been removed meanwhile. When yes,
1224 * restart this loop, otherwise, we're done */
1225 if (st.st_nlink >= 1)
1228 if (pa_lock_fd(fd, 0) < 0) {
1229 pa_log_warn("Failed to unlock file '%s'.", fn);
1233 if (pa_close(fd) < 0) {
1234 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1245 int saved_errno = errno;
1247 errno = saved_errno;
1253 /* Unlock a temporary lcok file */
1254 int pa_unlock_lockfile(const char *fn, int fd) {
1259 if (unlink(fn) < 0) {
1260 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1265 if (pa_lock_fd(fd, 0) < 0) {
1266 pa_log_warn("Failed to unlock file '%s'.", fn);
1270 if (pa_close(fd) < 0) {
1271 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1278 static char *get_pulse_home(void) {
1283 if (!(h = pa_get_home_dir_malloc())) {
1284 pa_log_error("Failed to get home directory.");
1288 if (stat(h, &st) < 0) {
1289 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1293 if (st.st_uid != getuid()) {
1294 pa_log_error("Home directory %s not ours.", h);
1299 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1307 char *pa_get_state_dir(void) {
1310 /* The state directory shall contain dynamic data that should be
1311 * kept across reboots, and is private to this user */
1313 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1314 if (!(d = get_pulse_home()))
1317 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1318 * dir then this will break. */
1320 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1321 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1329 char *pa_get_home_dir_malloc(void) {
1331 size_t allocated = 128;
1334 homedir = pa_xmalloc(allocated);
1336 if (!pa_get_home_dir(homedir, allocated)) {
1341 if (strlen(homedir) < allocated - 1)
1351 char *pa_get_binary_name_malloc(void) {
1353 size_t allocated = 128;
1356 t = pa_xmalloc(allocated);
1358 if (!pa_get_binary_name(t, allocated)) {
1363 if (strlen(t) < allocated - 1)
1373 static char* make_random_dir(mode_t m) {
1374 static const char table[] =
1375 "abcdefghijklmnopqrstuvwxyz"
1376 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1382 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1383 pathlen = strlen(fn);
1391 for (i = pathlen - 12; i < pathlen; i++)
1392 fn[i] = table[rand() % (sizeof(table)-1)];
1394 u = umask((~m) & 0777);
1397 saved_errno = errno;
1399 errno = saved_errno;
1404 if (errno != EEXIST) {
1405 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1412 static int make_random_dir_and_link(mode_t m, const char *k) {
1415 if (!(p = make_random_dir(m)))
1418 if (symlink(p, k) < 0) {
1419 int saved_errno = errno;
1421 if (errno != EEXIST)
1422 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1427 errno = saved_errno;
1435 char *pa_get_runtime_dir(void) {
1436 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1440 /* The runtime directory shall contain dynamic data that needs NOT
1441 * to be kept accross reboots and is usuallly private to the user,
1442 * except in system mode, where it might be accessible by other
1443 * users, too. Since we need POSIX locking and UNIX sockets in
1444 * this directory, we link it to a random subdir in /tmp, if it
1445 * was not explicitly configured. */
1447 m = pa_in_system_mode() ? 0755U : 0700U;
1449 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1451 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1452 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1456 return pa_xstrdup(d);
1459 if (!(d = get_pulse_home()))
1462 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1463 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1468 if (!(mid = pa_machine_id())) {
1473 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1478 /* OK, first let's check if the "runtime" symlink is already
1481 if (!(p = pa_readlink(k))) {
1483 if (errno != ENOENT) {
1484 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1488 /* Hmm, so the runtime directory didn't exist yet, so let's
1489 * create one in /tmp and symlink that to it */
1491 if (make_random_dir_and_link(0700, k) < 0) {
1493 /* Mhmm, maybe another process was quicker than us,
1494 * let's check if that was valid */
1495 if (errno == EEXIST)
1504 /* Make sure that this actually makes sense */
1505 if (!pa_is_path_absolute(p)) {
1506 pa_log_error("Path %s in link %s is not absolute.", p, k);
1511 /* Hmm, so this symlink is still around, make sure nobody fools
1514 if (lstat(p, &st) < 0) {
1516 if (errno != ENOENT) {
1517 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1523 if (S_ISDIR(st.st_mode) &&
1524 (st.st_uid == getuid()) &&
1525 ((st.st_mode & 0777) == 0700)) {
1531 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1537 /* Hmm, so the link points to some nonexisting or invalid
1538 * dir. Let's replace it by a new link. We first create a
1539 * temporary link and then rename that to allow concurrent
1540 * execution of this function. */
1542 t = pa_sprintf_malloc("%s.tmp", k);
1544 if (make_random_dir_and_link(0700, t) < 0) {
1546 if (errno != EEXIST) {
1547 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1554 /* Hmm, someone lese was quicker then us. Let's give
1555 * him some time to finish, and retry. */
1560 /* OK, we succeeded in creating the temporary symlink, so
1561 * let's rename it */
1562 if (rename(t, k) < 0) {
1563 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1579 /* Try to open a configuration file. If "env" is specified, open the
1580 * value of the specified environment variable. Otherwise look for a
1581 * file "local" in the home directory or a file "global" in global
1582 * file system. If "result" is non-NULL, a pointer to a newly
1583 * allocated buffer containing the used configuration file is
1585 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1590 if (!getenv(PULSE_ROOTENV))
1594 if (env && (fn = getenv(env))) {
1598 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1599 /* FIXME: Needs to set errno! */
1604 if ((f = pa_fopen_cloexec(fn, "r"))) {
1606 *result = pa_xstrdup(fn);
1611 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1621 if ((e = getenv("PULSE_CONFIG_PATH")))
1622 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1623 else if ((h = pa_get_home_dir_malloc())) {
1624 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1630 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1631 /* FIXME: Needs to set errno! */
1638 if ((f = pa_fopen_cloexec(fn, "r"))) {
1640 *result = pa_xstrdup(fn);
1646 if (errno != ENOENT) {
1647 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1659 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1660 /* FIXME: Needs to set errno! */
1665 if ((f = pa_fopen_cloexec(global, "r"))) {
1668 *result = pa_xstrdup(global);
1678 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1683 if (!getenv(PULSE_ROOTENV))
1687 if (env && (fn = getenv(env))) {
1690 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1691 /* FIXME: Needs to set errno! */
1696 if (access(fn, R_OK) == 0)
1697 return pa_xstrdup(fn);
1699 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1708 if ((e = getenv("PULSE_CONFIG_PATH")))
1709 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1710 else if ((h = pa_get_home_dir_malloc())) {
1711 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1717 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1718 /* FIXME: Needs to set errno! */
1725 if (access(fn, R_OK) == 0) {
1726 char *r = pa_xstrdup(fn);
1731 if (errno != ENOENT) {
1732 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1742 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1743 /* FIXME: Needs to set errno! */
1748 if (access(global, R_OK) == 0)
1749 return pa_xstrdup(global);
1757 /* Format the specified data as a hexademical string */
1758 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1759 size_t i = 0, j = 0;
1760 const char hex[] = "0123456789abcdef";
1764 pa_assert(slength > 0);
1766 while (i < dlength && j+3 <= slength) {
1767 s[j++] = hex[*d >> 4];
1768 s[j++] = hex[*d & 0xF];
1774 s[j < slength ? j : slength] = 0;
1778 /* Convert a hexadecimal digit to a number or -1 if invalid */
1779 static int hexc(char c) {
1780 if (c >= '0' && c <= '9')
1783 if (c >= 'A' && c <= 'F')
1784 return c - 'A' + 10;
1786 if (c >= 'a' && c <= 'f')
1787 return c - 'a' + 10;
1793 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1794 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1800 while (j < dlength && *p) {
1803 if ((b = hexc(*(p++))) < 0)
1806 d[j] = (uint8_t) (b << 4);
1811 if ((b = hexc(*(p++))) < 0)
1814 d[j] |= (uint8_t) b;
1821 /* Returns nonzero when *s starts with *pfx */
1822 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1830 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1833 /* Returns nonzero when *s ends with *sfx */
1834 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1843 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1846 pa_bool_t pa_is_path_absolute(const char *fn) {
1852 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1856 char *pa_make_path_absolute(const char *p) {
1862 if (pa_is_path_absolute(p))
1863 return pa_xstrdup(p);
1865 if (!(cwd = pa_getcwd()))
1866 return pa_xstrdup(p);
1868 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1873 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1874 * if fn is non-null and starts with / return fn
1875 * otherwise append fn to the run time path and return it */
1876 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1879 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1884 if (pa_is_path_absolute(fn))
1885 return pa_xstrdup(fn);
1893 if (!(mid = pa_machine_id())) {
1898 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1901 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1909 char *pa_runtime_path(const char *fn) {
1910 return get_path(fn, FALSE, TRUE);
1913 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1914 return get_path(fn, appendmid, FALSE);
1917 /* Convert the string s to a signed integer in *ret_i */
1918 int pa_atoi(const char *s, int32_t *ret_i) {
1926 l = strtol(s, &x, 0);
1928 if (!x || *x || errno) {
1934 if ((int32_t) l != l) {
1939 *ret_i = (int32_t) l;
1944 /* Convert the string s to an unsigned integer in *ret_u */
1945 int pa_atou(const char *s, uint32_t *ret_u) {
1953 l = strtoul(s, &x, 0);
1955 if (!x || *x || errno) {
1961 if ((uint32_t) l != l) {
1966 *ret_u = (uint32_t) l;
1971 #ifdef HAVE_STRTOF_L
1972 static locale_t c_locale = NULL;
1974 static void c_locale_destroy(void) {
1975 freelocale(c_locale);
1979 int pa_atod(const char *s, double *ret_d) {
1986 /* This should be locale independent */
1988 #ifdef HAVE_STRTOF_L
1992 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1993 atexit(c_locale_destroy);
1999 f = strtod_l(s, &x, c_locale);
2007 if (!x || *x || errno) {
2018 /* Same as snprintf, but guarantees NUL-termination on every platform */
2019 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2024 pa_assert(size > 0);
2027 va_start(ap, format);
2028 ret = pa_vsnprintf(str, size, format, ap);
2034 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2035 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2039 pa_assert(size > 0);
2042 ret = vsnprintf(str, size, format, ap);
2049 if ((size_t) ret > size-1)
2052 return (size_t) ret;
2055 /* Truncate the specified string, but guarantee that the string
2056 * returned still validates as UTF8 */
2057 char *pa_truncate_utf8(char *c, size_t l) {
2059 pa_assert(pa_utf8_valid(c));
2066 while (l > 0 && !pa_utf8_valid(c))
2072 char *pa_getcwd(void) {
2076 char *p = pa_xmalloc(l);
2080 if (errno != ERANGE)
2088 void *pa_will_need(const void *p, size_t l) {
2089 #ifdef RLIMIT_MEMLOCK
2100 a = PA_PAGE_ALIGN_PTR(p);
2101 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2103 #ifdef HAVE_POSIX_MADVISE
2104 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2105 pa_log_debug("posix_madvise() worked fine!");
2110 /* Most likely the memory was not mmap()ed from a file and thus
2111 * madvise() didn't work, so let's misuse mlock() do page this
2112 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2113 * inviting, the man page of mlock() tells us: "All pages that
2114 * contain a part of the specified address range are guaranteed to
2115 * be resident in RAM when the call returns successfully." */
2117 #ifdef RLIMIT_MEMLOCK
2118 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2120 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2121 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));
2126 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2128 bs = PA_PAGE_SIZE*4;
2131 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2134 while (size > 0 && bs > 0) {
2139 if (mlock(a, bs) < 0) {
2140 bs = PA_PAGE_ALIGN(bs / 2);
2144 pa_assert_se(munlock(a, bs) == 0);
2146 a = (const uint8_t*) a + bs;
2152 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2154 pa_log_debug("mlock() worked fine!");
2159 void pa_close_pipe(int fds[2]) {
2163 pa_assert_se(pa_close(fds[0]) == 0);
2166 pa_assert_se(pa_close(fds[1]) == 0);
2168 fds[0] = fds[1] = -1;
2171 char *pa_readlink(const char *p) {
2180 if ((n = readlink(p, c, l-1)) < 0) {
2185 if ((size_t) n < l-1) {
2195 int pa_close_all(int except_fd, ...) {
2200 va_start(ap, except_fd);
2203 for (n = 1; va_arg(ap, int) >= 0; n++)
2208 p = pa_xnew(int, n+1);
2210 va_start(ap, except_fd);
2213 if (except_fd >= 0) {
2217 while ((fd = va_arg(ap, int)) >= 0)
2224 r = pa_close_allv(p);
2230 int pa_close_allv(const int except_fds[]) {
2238 if ((d = opendir("/proc/self/fd"))) {
2242 while ((de = readdir(d))) {
2248 if (de->d_name[0] == '.')
2252 l = strtol(de->d_name, &e, 10);
2253 if (errno != 0 || !e || *e) {
2261 if ((long) fd != l) {
2274 for (i = 0; except_fds[i] >= 0; i++)
2275 if (except_fds[i] == fd) {
2283 if (pa_close(fd) < 0) {
2284 saved_errno = errno;
2286 errno = saved_errno;
2298 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2299 maxfd = (int) rl.rlim_max;
2301 maxfd = sysconf(_SC_OPEN_MAX);
2303 for (fd = 3; fd < maxfd; fd++) {
2308 for (i = 0; except_fds[i] >= 0; i++)
2309 if (except_fds[i] == fd) {
2317 if (pa_close(fd) < 0 && errno != EBADF)
2324 int pa_unblock_sigs(int except, ...) {
2329 va_start(ap, except);
2332 for (n = 1; va_arg(ap, int) >= 0; n++)
2337 p = pa_xnew(int, n+1);
2339 va_start(ap, except);
2346 while ((sig = va_arg(ap, int)) >= 0)
2353 r = pa_unblock_sigsv(p);
2359 int pa_unblock_sigsv(const int except[]) {
2363 if (sigemptyset(&ss) < 0)
2366 for (i = 0; except[i] > 0; i++)
2367 if (sigaddset(&ss, except[i]) < 0)
2370 return sigprocmask(SIG_SETMASK, &ss, NULL);
2373 int pa_reset_sigs(int except, ...) {
2378 va_start(ap, except);
2381 for (n = 1; va_arg(ap, int) >= 0; n++)
2386 p = pa_xnew(int, n+1);
2388 va_start(ap, except);
2395 while ((sig = va_arg(ap, int)) >= 0)
2402 r = pa_reset_sigsv(p);
2408 int pa_reset_sigsv(const int except[]) {
2411 for (sig = 1; sig < NSIG; sig++) {
2412 pa_bool_t reset = TRUE;
2423 for (i = 0; except[i] > 0; i++) {
2424 if (sig == except[i]) {
2433 struct sigaction sa;
2435 memset(&sa, 0, sizeof(sa));
2436 sa.sa_handler = SIG_DFL;
2438 /* On Linux the first two RT signals are reserved by
2439 * glibc, and sigaction() will return EINVAL for them. */
2440 if ((sigaction(sig, &sa, NULL) < 0))
2441 if (errno != EINVAL)
2449 void pa_set_env(const char *key, const char *value) {
2453 /* This is not thread-safe */
2455 putenv(pa_sprintf_malloc("%s=%s", key, value));
2458 void pa_set_env_and_record(const char *key, const char *value) {
2462 /* This is not thread-safe */
2464 pa_set_env(key, value);
2465 recorded_env = pa_strlist_prepend(recorded_env, key);
2468 void pa_unset_env_recorded(void) {
2470 /* This is not thread-safe */
2475 recorded_env = pa_strlist_pop(recorded_env, &s);
2485 pa_bool_t pa_in_system_mode(void) {
2488 if (!(e = getenv("PULSE_SYSTEM")))
2494 char *pa_get_user_name_malloc(void) {
2498 #ifdef _SC_LOGIN_NAME_MAX
2499 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2505 u = pa_xnew(char, k+1);
2507 if (!(pa_get_user_name(u, k))) {
2515 char *pa_get_host_name_malloc(void) {
2524 if (!pa_get_host_name(c, l)) {
2526 if (errno != EINVAL && errno != ENAMETOOLONG)
2529 } else if (strlen(c) < l-1) {
2537 u = pa_utf8_filter(c);
2542 /* Hmm, the hostname is as long the space we offered the
2543 * function, we cannot know if it fully fit in, so let's play
2544 * safe and retry. */
2553 char *pa_machine_id(void) {
2557 /* The returned value is supposed be some kind of ascii identifier
2558 * that is unique and stable across reboots. */
2560 /* First we try the D-Bus UUID, which is the best option we have,
2561 * since it fits perfectly our needs and is not as volatile as the
2562 * hostname which might be set from dhcp. */
2564 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
2565 char ln[34] = "", *r;
2567 r = fgets(ln, sizeof(ln)-1, f);
2573 return pa_utf8_filter(ln);
2576 if ((h = pa_get_host_name_malloc()))
2579 /* If no hostname was set we use the POSIX hostid. It's usually
2580 * the IPv4 address. Might not be that stable. */
2581 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2584 char *pa_session_id(void) {
2587 if (!(e = getenv("XDG_SESSION_COOKIE")))
2590 return pa_utf8_filter(e);
2593 char *pa_uname_string(void) {
2596 pa_assert_se(uname(&u) >= 0);
2598 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2601 #ifdef HAVE_VALGRIND_MEMCHECK_H
2602 pa_bool_t pa_in_valgrind(void) {
2605 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2606 * here instead of really checking whether we run in valgrind or
2610 b = getenv("VALGRIND") ? 2 : 1;
2616 unsigned pa_gcd(unsigned a, unsigned b) {
2627 void pa_reduce(unsigned *num, unsigned *den) {
2629 unsigned gcd = pa_gcd(*num, *den);
2637 pa_assert(pa_gcd(*num, *den) == 1);
2640 unsigned pa_ncpus(void) {
2643 #ifdef _SC_NPROCESSORS_CONF
2644 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2649 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2652 char *pa_replace(const char*s, const char*a, const char *b) {
2661 sb = pa_strbuf_new();
2666 if (!(p = strstr(s, a)))
2669 pa_strbuf_putsn(sb, s, p-s);
2670 pa_strbuf_puts(sb, b);
2674 pa_strbuf_puts(sb, s);
2676 return pa_strbuf_tostring_free(sb);
2679 char *pa_escape(const char *p, const char *chars) {
2682 pa_strbuf *buf = pa_strbuf_new();
2684 for (s = p; *s; ++s) {
2686 pa_strbuf_putc(buf, '\\');
2688 for (c = chars; *c; ++c) {
2690 pa_strbuf_putc(buf, '\\');
2695 pa_strbuf_putc(buf, *s);
2698 return pa_strbuf_tostring_free(buf);
2701 char *pa_unescape(char *p) {
2703 pa_bool_t escaped = FALSE;
2705 for (s = p, d = p; *s; s++) {
2706 if (!escaped && *s == '\\') {
2720 char *pa_realpath(const char *path) {
2724 /* We want only abolsute paths */
2725 if (path[0] != '/') {
2730 #if defined(__GLIBC__) || defined(__APPLE__)
2734 if (!(r = realpath(path, NULL)))
2737 /* We copy this here in case our pa_xmalloc() is not
2738 * implemented on top of libc malloc() */
2742 #elif defined(PATH_MAX)
2745 path_buf = pa_xmalloc(PATH_MAX);
2747 if (!(t = realpath(path, path_buf))) {
2753 #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."
2759 void pa_disable_sigpipe(void) {
2762 struct sigaction sa;
2766 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2767 pa_log("sigaction(): %s", pa_cstrerror(errno));
2771 sa.sa_handler = SIG_IGN;
2773 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2774 pa_log("sigaction(): %s", pa_cstrerror(errno));
2780 void pa_xfreev(void**a) {
2786 for (p = a; *p; p++)
2792 char **pa_split_spaces_strv(const char *s) {
2794 unsigned i = 0, n = 8;
2795 const char *state = NULL;
2797 t = pa_xnew(char*, n);
2798 while ((e = pa_split_spaces(s, &state))) {
2803 t = pa_xrenew(char*, t, n);
2816 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2819 if (pa_is_path_absolute(path))
2820 return pa_xstrdup(path);
2822 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2825 size_t pa_pipe_buf(int fd) {
2830 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2841 void pa_reset_personality(void) {
2844 if (personality(PER_LINUX) < 0)
2845 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2850 #if defined(__linux__) && !defined(__OPTIMIZE__)
2852 pa_bool_t pa_run_from_build_tree(void) {
2854 pa_bool_t b = FALSE;
2856 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2859 if ((rp = pa_readlink("/proc/self/exe"))) {
2860 b = pa_startswith(rp, PA_BUILDDIR);
2869 const char *pa_get_temp_dir(void) {
2872 if ((t = getenv("TMPDIR")) &&
2873 pa_is_path_absolute(t))
2876 if ((t = getenv("TMP")) &&
2877 pa_is_path_absolute(t))
2880 if ((t = getenv("TEMP")) &&
2881 pa_is_path_absolute(t))
2884 if ((t = getenv("TEMPDIR")) &&
2885 pa_is_path_absolute(t))
2891 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
2899 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
2902 if (errno != EINVAL)
2906 if ((fd = open(fn, flags, mode)) < 0)
2910 /* Some implementations might simply ignore O_CLOEXEC if it is not
2911 * understood, make sure FD_CLOEXEC is enabled anyway */
2913 pa_make_fd_cloexec(fd);
2917 int pa_socket_cloexec(int domain, int type, int protocol) {
2921 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
2924 if (errno != EINVAL)
2928 if ((fd = socket(domain, type, protocol)) < 0)
2932 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
2933 * not understood, make sure FD_CLOEXEC is enabled anyway */
2935 pa_make_fd_cloexec(fd);
2939 int pa_pipe_cloexec(int pipefd[2]) {
2943 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
2946 if (errno != EINVAL && errno != ENOSYS)
2951 if ((r = pipe(pipefd)) < 0)
2955 pa_make_fd_cloexec(pipefd[0]);
2956 pa_make_fd_cloexec(pipefd[1]);
2961 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
2965 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
2968 if (errno != EINVAL && errno != ENOSYS)
2973 if ((fd = accept(sockfd, addr, addrlen)) < 0)
2977 pa_make_fd_cloexec(fd);
2981 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
2985 m = pa_sprintf_malloc("%se", mode);
2988 if ((f = fopen(path, m))) {
2995 if (errno != EINVAL)
2998 if (!(f = fopen(path, mode)))
3002 pa_make_fd_cloexec(fileno(f));
3006 void pa_nullify_stdfds(void) {
3009 pa_close(STDIN_FILENO);
3010 pa_close(STDOUT_FILENO);
3011 pa_close(STDERR_FILENO);
3013 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3014 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3015 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3022 char *pa_read_line_from_file(const char *fn) {
3024 char ln[256] = "", *r;
3026 if (!(f = pa_fopen_cloexec(fn, "r")))
3029 r = fgets(ln, sizeof(ln)-1, f);
3038 return pa_xstrdup(ln);
3041 pa_bool_t pa_running_in_vm(void) {
3043 #if defined(__i386__) || defined(__x86_64__)
3045 /* Both CPUID and DMI are x86 specific interfaces... */
3047 uint32_t eax = 0x40000000;
3054 const char *const dmi_vendors[] = {
3055 "/sys/class/dmi/id/sys_vendor",
3056 "/sys/class/dmi/id/board_vendor",
3057 "/sys/class/dmi/id/bios_vendor"
3062 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3065 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3067 if (pa_startswith(s, "QEMU") ||
3068 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3069 pa_startswith(s, "VMware") ||
3070 pa_startswith(s, "VMW") ||
3071 pa_startswith(s, "Microsoft Corporation") ||
3072 pa_startswith(s, "innotek GmbH") ||
3073 pa_startswith(s, "Xen")) {
3085 /* http://lwn.net/Articles/301888/ */
3088 __asm__ __volatile__ (
3089 /* ebx/rbx is being used for PIC! */
3090 " push %%"PA_REG_b" \n\t"
3092 " mov %%ebx, %1 \n\t"
3093 " pop %%"PA_REG_b" \n\t"
3095 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3099 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3100 pa_streq(sig.text, "KVMKVMKVM") ||
3101 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3102 pa_streq(sig.text, "VMwareVMware") ||
3103 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3104 pa_streq(sig.text, "Microsoft Hv"))