Fix up according to Coding Style
[pulseaudio-mirror.git] / src / pulsecore / core-util.c
blobbb0f5601ebc0ef5f855a096e8e0495cdf3b2acca
1 /***
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
21 USA.
22 ***/
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <signal.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <limits.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <dirent.h>
42 #ifdef HAVE_LANGINFO_H
43 #include <langinfo.h>
44 #endif
46 #ifdef HAVE_UNAME
47 #include <sys/utsname.h>
48 #endif
50 #if defined(HAVE_REGEX_H)
51 #include <regex.h>
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
54 #endif
56 #ifdef HAVE_STRTOF_L
57 #include <locale.h>
58 #endif
60 #ifdef HAVE_SCHED_H
61 #include <sched.h>
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
65 #endif
66 #endif
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
70 #endif
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
74 #endif
76 #ifdef HAVE_SYS_MMAN_H
77 #include <sys/mman.h>
78 #endif
80 #ifdef HAVE_PTHREAD
81 #include <pthread.h>
82 #endif
84 #ifdef HAVE_NETDB_H
85 #include <netdb.h>
86 #endif
88 #ifdef HAVE_WINDOWS_H
89 #include <windows.h>
90 #endif
92 #ifndef ENOTSUP
93 #define ENOTSUP 135
94 #endif
96 #ifdef HAVE_PWD_H
97 #include <pwd.h>
98 #endif
100 #ifdef HAVE_GRP_H
101 #include <grp.h>
102 #endif
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
106 #endif
108 #ifdef __APPLE__
109 #include <xlocale.h>
110 #endif
112 #ifdef HAVE_DBUS
113 #include "rtkit.h"
114 #endif
116 #ifdef __linux__
117 #include <sys/personality.h>
118 #endif
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 */
138 #ifndef MSG_NOSIGNAL
139 #define MSG_NOSIGNAL 0
140 #endif
142 #define NEWLINE "\r\n"
143 #define WHITESPACE "\n\r \t"
145 static pa_strlist *recorded_env = NULL;
147 #ifdef OS_IS_WIN32
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))
157 return 0;
159 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
160 if (sep)
161 *sep = '\0';
163 if (!SetEnvironmentVariable(PULSE_ROOTENV, library_path))
164 return 0;
166 return 1;
169 #endif
171 /** Make a file descriptor nonblock. Doesn't do any error checking */
172 void pa_make_fd_nonblock(int fd) {
174 #ifdef O_NONBLOCK
175 int v;
176 pa_assert(fd >= 0);
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)
184 u_long arg = 1;
185 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
186 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
187 pa_log_warn("Only sockets can be made non-blocking!");
189 #else
190 pa_log_warn("Non-blocking I/O not supported.!");
191 #endif
195 /* Set the FD_CLOEXEC flag for a fd */
196 void pa_make_fd_cloexec(int fd) {
198 #ifdef FD_CLOEXEC
199 int v;
200 pa_assert(fd >= 0);
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);
206 #endif
210 /** Creates a directory securely */
211 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
212 struct stat st;
213 int r, saved_errno, fd;
215 pa_assert(dir);
217 #ifdef OS_IS_WIN32
218 r = mkdir(dir);
219 #else
221 mode_t u;
222 u = umask((~m) & 0777);
223 r = mkdir(dir, m);
224 umask(u);
226 #endif
228 if (r < 0 && errno != EEXIST)
229 return -1;
231 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
232 if ((fd = open(dir,
233 #ifdef O_CLOEXEC
234 O_CLOEXEC|
235 #endif
236 #ifdef O_NOCTTY
237 O_NOCTTY|
238 #endif
239 #ifdef O_NOFOLLOW
240 O_NOFOLLOW|
241 #endif
242 O_RDONLY)) < 0)
243 goto fail;
245 if (fstat(fd, &st) < 0) {
246 pa_assert_se(pa_close(fd) >= 0);
247 goto fail;
250 if (!S_ISDIR(st.st_mode)) {
251 pa_assert_se(pa_close(fd) >= 0);
252 errno = EEXIST;
253 goto fail;
256 #ifdef HAVE_FCHOWN
257 if (uid == (uid_t)-1)
258 uid = getuid();
259 if (gid == (gid_t)-1)
260 gid = getgid();
261 (void) fchown(fd, uid, gid);
262 #endif
264 #ifdef HAVE_FCHMOD
265 (void) fchmod(fd, m);
266 #endif
268 pa_assert_se(pa_close(fd) >= 0);
269 #endif
271 #ifdef HAVE_LSTAT
272 if (lstat(dir, &st) < 0)
273 #else
274 if (stat(dir, &st) < 0)
275 #endif
276 goto fail;
278 #ifndef OS_IS_WIN32
279 if (!S_ISDIR(st.st_mode) ||
280 (st.st_uid != uid) ||
281 (st.st_gid != gid) ||
282 ((st.st_mode & 0777) != m)) {
283 errno = EACCES;
284 goto fail;
286 #else
287 pa_log_warn("Secure directory creation not supported on Win32.");
288 #endif
290 return 0;
292 fail:
293 saved_errno = errno;
294 rmdir(dir);
295 errno = saved_errno;
297 return -1;
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) {
305 pa_xfree(dir);
306 errno = ENOENT;
307 return NULL;
310 *(slash-1) = 0;
311 return 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) {
316 int ret = -1;
317 char *dir;
319 if (!(dir = pa_parent_dir(fn)))
320 goto finish;
322 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
323 goto finish;
325 ret = 0;
327 finish:
328 pa_xfree(dir);
329 return ret;
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
337 * by the caller. */
338 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
340 #ifdef OS_IS_WIN32
342 if (!type || *type == 0) {
343 ssize_t r;
345 if ((r = recv(fd, buf, count, 0)) >= 0)
346 return r;
348 if (WSAGetLastError() != WSAENOTSOCK) {
349 errno = WSAGetLastError();
350 return r;
353 if (type)
354 *type = 1;
357 #endif
359 for (;;) {
360 ssize_t r;
362 if ((r = read(fd, buf, count)) < 0)
363 if (errno == EINTR)
364 continue;
366 return r;
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) {
374 ssize_t r;
376 for (;;) {
377 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
379 if (errno == EINTR)
380 continue;
382 break;
385 return r;
388 #ifdef OS_IS_WIN32
389 if (WSAGetLastError() != WSAENOTSOCK) {
390 errno = WSAGetLastError();
391 return r;
393 #else
394 if (errno != ENOTSOCK)
395 return r;
396 #endif
398 if (type)
399 *type = 1;
402 for (;;) {
403 ssize_t r;
405 if ((r = write(fd, buf, count)) < 0)
406 if (errno == EINTR)
407 continue;
409 return r;
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) {
416 ssize_t ret = 0;
417 int _type;
419 pa_assert(fd >= 0);
420 pa_assert(data);
421 pa_assert(size);
423 if (!type) {
424 _type = 0;
425 type = &_type;
428 while (size > 0) {
429 ssize_t r;
431 if ((r = pa_read(fd, data, size, type)) < 0)
432 return r;
434 if (r == 0)
435 break;
437 ret += r;
438 data = (uint8_t*) data + r;
439 size -= (size_t) r;
442 return ret;
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) {
447 ssize_t ret = 0;
448 int _type;
450 pa_assert(fd >= 0);
451 pa_assert(data);
452 pa_assert(size);
454 if (!type) {
455 _type = 0;
456 type = &_type;
459 while (size > 0) {
460 ssize_t r;
462 if ((r = pa_write(fd, data, size, type)) < 0)
463 return r;
465 if (r == 0)
466 break;
468 ret += r;
469 data = (const uint8_t*) data + r;
470 size -= (size_t) r;
473 return ret;
476 /** Platform independent read function. Necessary since not all
477 * systems treat all file descriptors equal. */
478 int pa_close(int fd) {
480 #ifdef OS_IS_WIN32
481 int ret;
483 if ((ret = closesocket(fd)) == 0)
484 return 0;
486 if (WSAGetLastError() != WSAENOTSOCK) {
487 errno = WSAGetLastError();
488 return ret;
490 #endif
492 for (;;) {
493 int r;
495 if ((r = close(fd)) < 0)
496 if (errno == EINTR)
497 continue;
499 return r;
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
507 struct sigaction sa;
508 sigset_t set;
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() */
514 #ifdef HAVE_PTHREAD
515 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
516 #endif
517 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
518 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
519 return;
521 #ifdef HAVE_PTHREAD
523 #endif
525 if (sigismember(&set, sig))
526 return;
528 /* Check whether the signal is trapped */
530 if (sigaction(sig, NULL, &sa) < 0) {
531 pa_log("sigaction(): %s", pa_cstrerror(errno));
532 return;
535 if (sa.sa_handler != SIG_DFL)
536 return;
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));
541 #endif
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, ...) {
547 size_t size = 100;
548 char *c = NULL;
550 pa_assert(format);
552 for(;;) {
553 int r;
554 va_list ap;
556 c = pa_xrealloc(c, size);
558 va_start(ap, format);
559 r = vsnprintf(c, size, format, ap);
560 va_end(ap);
562 c[size-1] = 0;
564 if (r > -1 && (size_t) r < size)
565 return c;
567 if (r > -1) /* glibc 2.1 */
568 size = (size_t) r+1;
569 else /* glibc 2.0 */
570 size *= 2;
574 /* Same as the previous function, but use a va_list instead of an
575 * ellipsis */
576 char *pa_vsprintf_malloc(const char *format, va_list ap) {
577 size_t size = 100;
578 char *c = NULL;
580 pa_assert(format);
582 for(;;) {
583 int r;
584 va_list aq;
586 c = pa_xrealloc(c, size);
588 va_copy(aq, ap);
589 r = vsnprintf(c, size, format, aq);
590 va_end(aq);
592 c[size-1] = 0;
594 if (r > -1 && (size_t) r < size)
595 return c;
597 if (r > -1) /* glibc 2.1 */
598 size = (size_t) r+1;
599 else /* glibc 2.0 */
600 size *= 2;
604 /* Similar to OpenBSD's strlcpy() function */
605 char *pa_strlcpy(char *b, const char *s, size_t l) {
606 size_t k;
608 pa_assert(b);
609 pa_assert(s);
610 pa_assert(l > 0);
612 k = strlen(s);
614 if (k > l-1)
615 k = l-1;
617 memcpy(b, s, k);
618 b[k] = 0;
620 return b;
623 #ifdef _POSIX_PRIORITY_SCHEDULING
624 static int set_scheduler(int rtprio) {
625 #ifdef HAVE_SCHED_H
626 struct sched_param sp;
627 #ifdef HAVE_DBUS
628 int r;
629 DBusError error;
630 DBusConnection *bus;
632 dbus_error_init(&error);
633 #endif
635 pa_zero(sp);
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.");
641 return 0;
643 #endif
645 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
646 pa_log_debug("SCHED_RR worked.");
647 return 0;
649 #endif /* HAVE_SCHED_H */
651 #ifdef HAVE_DBUS
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);
657 errno = -EIO;
658 return -1;
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);
669 if (r >= 0) {
670 pa_log_debug("RealtimeKit worked.");
671 return 0;
674 errno = -r;
675 #else
676 errno = 0;
677 #endif
679 return -1;
681 #endif
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
689 int p;
691 if (set_scheduler(rtprio) >= 0) {
692 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
693 return 0;
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);
699 return 0;
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.");
706 return 0;
709 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
710 errno = EPERM;
711 #else
712 errno = ENOTSUP;
713 #endif
714 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
715 return -1;
718 #ifdef HAVE_SYS_RESOURCE_H
719 static int set_nice(int nice_level) {
720 #ifdef HAVE_DBUS
721 DBusError error;
722 DBusConnection *bus;
723 int r;
725 dbus_error_init(&error);
726 #endif
728 #ifdef HAVE_SYS_RESOURCE_H
729 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
730 pa_log_debug("setpriority() worked.");
731 return 0;
733 #endif
735 #ifdef HAVE_DBUS
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);
741 errno = -EIO;
742 return -1;
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);
753 if (r >= 0) {
754 pa_log_debug("RealtimeKit worked.");
755 return 0;
758 errno = -r;
759 #endif
761 return -1;
763 #endif
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
770 int n;
772 if (set_nice(nice_level) >= 0) {
773 pa_log_info("Successfully gained nice level %i.", nice_level);
774 return 0;
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);
780 return 0;
783 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
784 return -1;
785 #endif
787 #ifdef OS_IS_WIN32
788 if (nice_level < 0) {
789 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
790 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
791 errno = EPERM;
792 return -1;
795 pa_log_info("Successfully gained high priority class.");
797 #endif
799 return 0;
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);
810 pa_zero(sp);
811 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
812 #endif
814 #ifdef OS_IS_WIN32
815 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
816 #endif
819 int pa_match(const char *expr, const char *v) {
820 int k;
821 regex_t re;
822 int r;
824 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
825 errno = EINVAL;
826 return -1;
829 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
830 r = 1;
831 else if (k == REG_NOMATCH)
832 r = 0;
833 else
834 r = -1;
836 regfree(&re);
838 if (r < 0)
839 errno = EINVAL;
841 return r;
844 /* Try to parse a boolean string value.*/
845 int pa_parse_boolean(const char *v) {
846 const char *expr;
847 pa_assert(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"))
851 return 1;
852 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
853 return 0;
855 #ifdef HAVE_LANGINFO_H
856 /* And then we check language dependant */
857 if ((expr = nl_langinfo(YESEXPR)))
858 if (expr[0])
859 if (pa_match(expr, v) > 0)
860 return 1;
862 if ((expr = nl_langinfo(NOEXPR)))
863 if (expr[0])
864 if (pa_match(expr, v) > 0)
865 return 0;
866 #endif
868 errno = EINVAL;
869 return -1;
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;
878 size_t l;
880 if (!*current)
881 return NULL;
883 l = strcspn(current, delimiter);
884 *state = current+l;
886 if (**state)
887 (*state)++;
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;
895 size_t l;
897 if (!*current || *c == 0)
898 return NULL;
900 current += strspn(current, WHITESPACE);
901 l = strcspn(current, WHITESPACE);
903 *state = current+l;
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) {
912 char *t;
914 if (sig <= 0)
915 goto fail;
917 #ifdef NSIG
918 if (sig >= NSIG)
919 goto fail;
920 #endif
922 #ifdef HAVE_SIG2STR
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);
930 return t;
933 #else
935 switch(sig) {
936 #ifdef SIGHUP
937 case SIGHUP: return "SIGHUP";
938 #endif
939 case SIGINT: return "SIGINT";
940 #ifdef SIGQUIT
941 case SIGQUIT: return "SIGQUIT";
942 #endif
943 case SIGILL: return "SIGULL";
944 #ifdef SIGTRAP
945 case SIGTRAP: return "SIGTRAP";
946 #endif
947 case SIGABRT: return "SIGABRT";
948 #ifdef SIGBUS
949 case SIGBUS: return "SIGBUS";
950 #endif
951 case SIGFPE: return "SIGFPE";
952 #ifdef SIGKILL
953 case SIGKILL: return "SIGKILL";
954 #endif
955 #ifdef SIGUSR1
956 case SIGUSR1: return "SIGUSR1";
957 #endif
958 case SIGSEGV: return "SIGSEGV";
959 #ifdef SIGUSR2
960 case SIGUSR2: return "SIGUSR2";
961 #endif
962 #ifdef SIGPIPE
963 case SIGPIPE: return "SIGPIPE";
964 #endif
965 #ifdef SIGALRM
966 case SIGALRM: return "SIGALRM";
967 #endif
968 case SIGTERM: return "SIGTERM";
969 #ifdef SIGSTKFLT
970 case SIGSTKFLT: return "SIGSTKFLT";
971 #endif
972 #ifdef SIGCHLD
973 case SIGCHLD: return "SIGCHLD";
974 #endif
975 #ifdef SIGCONT
976 case SIGCONT: return "SIGCONT";
977 #endif
978 #ifdef SIGSTOP
979 case SIGSTOP: return "SIGSTOP";
980 #endif
981 #ifdef SIGTSTP
982 case SIGTSTP: return "SIGTSTP";
983 #endif
984 #ifdef SIGTTIN
985 case SIGTTIN: return "SIGTTIN";
986 #endif
987 #ifdef SIGTTOU
988 case SIGTTOU: return "SIGTTOU";
989 #endif
990 #ifdef SIGURG
991 case SIGURG: return "SIGURG";
992 #endif
993 #ifdef SIGXCPU
994 case SIGXCPU: return "SIGXCPU";
995 #endif
996 #ifdef SIGXFSZ
997 case SIGXFSZ: return "SIGXFSZ";
998 #endif
999 #ifdef SIGVTALRM
1000 case SIGVTALRM: return "SIGVTALRM";
1001 #endif
1002 #ifdef SIGPROF
1003 case SIGPROF: return "SIGPROF";
1004 #endif
1005 #ifdef SIGWINCH
1006 case SIGWINCH: return "SIGWINCH";
1007 #endif
1008 #ifdef SIGIO
1009 case SIGIO: return "SIGIO";
1010 #endif
1011 #ifdef SIGPWR
1012 case SIGPWR: return "SIGPWR";
1013 #endif
1014 #ifdef SIGSYS
1015 case SIGSYS: return "SIGSYS";
1016 #endif
1019 #ifdef SIGRTMIN
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);
1024 return t;
1026 #endif
1028 #endif
1030 fail:
1032 pa_xfree(PA_STATIC_TLS_GET(signame));
1033 t = pa_sprintf_malloc("SIG%i", sig);
1034 PA_STATIC_TLS_SET(signame, t);
1035 return t;
1038 #ifdef HAVE_GRP_H
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;
1043 int r = -1;
1045 errno = 0;
1046 if (!(group = pa_getgrgid_malloc(gid))) {
1047 if (!errno)
1048 errno = ENOENT;
1050 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1052 goto finish;
1055 r = strcmp(name, group->gr_name) == 0;
1057 finish:
1058 pa_getgrgid_free(group);
1060 return r;
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);
1067 int r = -1, i, k;
1069 pa_assert(n > 0);
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));
1075 goto finish;
1078 for (i = 0; i < n; i++) {
1080 if ((k = is_group(gids[i], name)) < 0)
1081 goto finish;
1082 else if (k > 0) {
1083 *gid = gids[i];
1084 r = 1;
1085 goto finish;
1089 if ((k = is_group(tgid = getgid(), name)) < 0)
1090 goto finish;
1091 else if (k > 0) {
1092 *gid = tgid;
1093 r = 1;
1094 goto finish;
1097 r = 0;
1099 finish:
1101 pa_xfree(gids);
1102 return r;
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;
1108 char **i;
1109 int r = -1;
1111 errno = 0;
1112 if (!(group = pa_getgrnam_malloc(name))) {
1113 if (!errno)
1114 errno = ENOENT;
1115 goto finish;
1118 r = 0;
1119 for (i = group->gr_mem; *i; i++) {
1120 struct passwd *pw = NULL;
1122 errno = 0;
1123 if (!(pw = pa_getpwnam_malloc(*i)))
1124 continue;
1126 if (pw->pw_uid == uid)
1127 r = 1;
1129 pa_getpwnam_free(pw);
1131 if (r == 1)
1132 break;
1135 finish:
1136 pa_getgrnam_free(group);
1138 return r;
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;
1146 errno = 0;
1147 if (!(gr = pa_getgrnam_malloc(name))) {
1148 if (!errno)
1149 errno = ENOENT;
1150 goto finish;
1153 ret = gr->gr_gid;
1155 finish:
1156 pa_getgrnam_free(gr);
1157 return ret;
1160 int pa_check_in_group(gid_t g) {
1161 gid_t gids[NGROUPS_MAX];
1162 int r;
1164 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1165 return -1;
1167 for (; r > 0; r--)
1168 if (gids[r-1] == g)
1169 return 1;
1171 return 0;
1174 #else /* HAVE_GRP_H */
1176 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1177 errno = ENOTSUP;
1178 return -1;
1182 int pa_uid_in_group(uid_t uid, const char *name) {
1183 errno = ENOTSUP;
1184 return -1;
1187 gid_t pa_get_gid_of_group(const char *name) {
1188 errno = ENOTSUP;
1189 return (gid_t) -1;
1192 int pa_check_in_group(gid_t g) {
1193 errno = ENOTSUP;
1194 return -1;
1197 #endif
1199 /* Lock or unlock a file entirely.
1200 (advisory on UNIX, mandatory on Windows) */
1201 int pa_lock_fd(int fd, int b) {
1202 #ifdef F_SETLKW
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;
1209 f_lock.l_start = 0;
1210 f_lock.l_len = 0;
1212 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1213 return 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)
1219 return 0;
1222 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1223 #endif
1225 #ifdef OS_IS_WIN32
1226 HANDLE h = (HANDLE)_get_osfhandle(fd);
1228 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1229 return 0;
1230 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1231 return 0;
1233 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1235 /* FIXME: Needs to set errno! */
1236 #endif
1238 return -1;
1241 /* Remove trailing newlines from a string */
1242 char* pa_strip_nl(char *s) {
1243 pa_assert(s);
1245 s[strcspn(s, NEWLINE)] = 0;
1246 return s;
1249 char *pa_strip(char *s) {
1250 char *e, *l = NULL;
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))
1259 l = e;
1261 if (l)
1262 *(l+1) = 0;
1263 else
1264 *s = 0;
1266 return s;
1269 /* Create a temporary lock file and lock it. */
1270 int pa_lock_lockfile(const char *fn) {
1271 int fd;
1272 pa_assert(fn);
1274 for (;;) {
1275 struct stat st;
1277 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1278 #ifdef O_NOFOLLOW
1279 |O_NOFOLLOW
1280 #endif
1281 , S_IRUSR|S_IWUSR)) < 0) {
1282 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1283 goto fail;
1286 if (pa_lock_fd(fd, 1) < 0) {
1287 pa_log_warn("Failed to lock file '%s'.", fn);
1288 goto fail;
1291 if (fstat(fd, &st) < 0) {
1292 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1293 goto fail;
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)
1299 break;
1301 if (pa_lock_fd(fd, 0) < 0) {
1302 pa_log_warn("Failed to unlock file '%s'.", fn);
1303 goto fail;
1306 if (pa_close(fd) < 0) {
1307 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1308 fd = -1;
1309 goto fail;
1313 return fd;
1315 fail:
1317 if (fd >= 0) {
1318 int saved_errno = errno;
1319 pa_close(fd);
1320 errno = saved_errno;
1323 return -1;
1326 /* Unlock a temporary lcok file */
1327 int pa_unlock_lockfile(const char *fn, int fd) {
1328 int r = 0;
1329 pa_assert(fd >= 0);
1331 if (fn) {
1332 if (unlink(fn) < 0) {
1333 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1334 r = -1;
1338 if (pa_lock_fd(fd, 0) < 0) {
1339 pa_log_warn("Failed to unlock file '%s'.", fn);
1340 r = -1;
1343 if (pa_close(fd) < 0) {
1344 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1345 r = -1;
1348 return r;
1351 static char *get_pulse_home(void) {
1352 char *h;
1353 struct stat st;
1354 char *ret = NULL;
1356 if (!(h = pa_get_home_dir_malloc())) {
1357 pa_log_error("Failed to get home directory.");
1358 return NULL;
1361 if (stat(h, &st) < 0) {
1362 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1363 goto finish;
1366 #ifdef HAVE_GETUID
1367 if (st.st_uid != getuid()) {
1368 pa_log_error("Home directory %s not ours.", h);
1369 errno = EACCES;
1370 goto finish;
1372 #endif
1374 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1376 finish:
1377 pa_xfree(h);
1379 return ret;
1382 char *pa_get_state_dir(void) {
1383 char *d;
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()))
1390 return NULL;
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));
1397 pa_xfree(d);
1398 return NULL;
1401 return d;
1404 char *pa_get_home_dir_malloc(void) {
1405 char *homedir;
1406 size_t allocated = 128;
1408 for (;;) {
1409 homedir = pa_xmalloc(allocated);
1411 if (!pa_get_home_dir(homedir, allocated)) {
1412 pa_xfree(homedir);
1413 return NULL;
1416 if (strlen(homedir) < allocated - 1)
1417 break;
1419 pa_xfree(homedir);
1420 allocated *= 2;
1423 return homedir;
1426 char *pa_get_binary_name_malloc(void) {
1427 char *t;
1428 size_t allocated = 128;
1430 for (;;) {
1431 t = pa_xmalloc(allocated);
1433 if (!pa_get_binary_name(t, allocated)) {
1434 pa_xfree(t);
1435 return NULL;
1438 if (strlen(t) < allocated - 1)
1439 break;
1441 pa_xfree(t);
1442 allocated *= 2;
1445 return t;
1448 static char* make_random_dir(mode_t m) {
1449 static const char table[] =
1450 "abcdefghijklmnopqrstuvwxyz"
1451 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1452 "0123456789";
1454 char *fn;
1455 size_t pathlen;
1457 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1458 pathlen = strlen(fn);
1460 for (;;) {
1461 size_t i;
1462 int r;
1463 mode_t u;
1464 int saved_errno;
1466 for (i = pathlen - 12; i < pathlen; i++)
1467 fn[i] = table[rand() % (sizeof(table)-1)];
1469 u = umask((~m) & 0777);
1470 #ifndef OS_IS_WIN32
1471 r = mkdir(fn, m);
1472 #else
1473 r = mkdir(fn);
1474 #endif
1476 saved_errno = errno;
1477 umask(u);
1478 errno = saved_errno;
1480 if (r >= 0)
1481 return fn;
1483 if (errno != EEXIST) {
1484 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1485 pa_xfree(fn);
1486 return NULL;
1491 static int make_random_dir_and_link(mode_t m, const char *k) {
1492 char *p;
1494 if (!(p = make_random_dir(m)))
1495 return -1;
1497 #ifdef HAVE_SYMLINK
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));
1504 rmdir(p);
1505 pa_xfree(p);
1507 errno = saved_errno;
1508 return -1;
1510 #else
1511 pa_xfree(p);
1512 return -1;
1513 #endif
1515 pa_xfree(p);
1516 return 0;
1519 char *pa_get_runtime_dir(void) {
1520 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1521 struct stat st;
1522 mode_t m;
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));
1537 goto fail;
1540 return pa_xstrdup(d);
1543 if (!(d = get_pulse_home()))
1544 goto fail;
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));
1548 pa_xfree(d);
1549 goto fail;
1552 if (!(mid = pa_machine_id())) {
1553 pa_xfree(d);
1554 goto fail;
1557 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1558 pa_xfree(d);
1559 pa_xfree(mid);
1561 for (;;) {
1562 /* OK, first let's check if the "runtime" symlink is already
1563 * existant */
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));
1569 goto fail;
1572 #ifdef HAVE_SYMLINK
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)
1581 continue;
1583 goto fail;
1585 #else
1586 /* No symlink possible, so let's just create the runtime directly */
1587 if (!mkdir(k))
1588 goto fail;
1589 #endif
1591 return k;
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);
1597 errno = ENOENT;
1598 goto fail;
1601 /* Hmm, so this symlink is still around, make sure nobody fools
1602 * us */
1604 #ifdef HAVE_LSTAT
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));
1609 goto fail;
1612 } else {
1614 if (S_ISDIR(st.st_mode) &&
1615 (st.st_uid == getuid()) &&
1616 ((st.st_mode & 0777) == 0700)) {
1618 pa_xfree(p);
1619 return k;
1622 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1624 #endif
1626 pa_xfree(p);
1627 p = NULL;
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));
1640 goto fail;
1643 pa_xfree(t);
1644 t = NULL;
1646 /* Hmm, someone lese was quicker then us. Let's give
1647 * him some time to finish, and retry. */
1648 pa_msleep(10);
1649 continue;
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));
1656 goto fail;
1659 pa_xfree(t);
1660 return k;
1663 fail:
1664 pa_xfree(p);
1665 pa_xfree(k);
1666 pa_xfree(t);
1668 return NULL;
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
1676 * stored there.*/
1677 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1678 const char *fn;
1679 #ifdef OS_IS_WIN32
1680 char buf[PATH_MAX];
1682 if (!getenv(PULSE_ROOTENV))
1683 pa_set_root(NULL);
1684 #endif
1686 if (env && (fn = getenv(env))) {
1687 FILE *f;
1689 #ifdef OS_IS_WIN32
1690 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1691 /* FIXME: Needs to set errno! */
1692 return NULL;
1693 fn = buf;
1694 #endif
1696 if ((f = pa_fopen_cloexec(fn, "r"))) {
1697 if (result)
1698 *result = pa_xstrdup(fn);
1700 return f;
1703 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1704 return NULL;
1707 if (local) {
1708 const char *e;
1709 char *lfn;
1710 char *h;
1711 FILE *f;
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);
1717 pa_xfree(h);
1718 } else
1719 return NULL;
1721 #ifdef OS_IS_WIN32
1722 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1723 /* FIXME: Needs to set errno! */
1724 pa_xfree(lfn);
1725 return NULL;
1727 fn = buf;
1728 #endif
1730 if ((f = pa_fopen_cloexec(fn, "r"))) {
1731 if (result)
1732 *result = pa_xstrdup(fn);
1734 pa_xfree(lfn);
1735 return f;
1738 if (errno != ENOENT) {
1739 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1740 pa_xfree(lfn);
1741 return NULL;
1744 pa_xfree(lfn);
1747 if (global) {
1748 FILE *f;
1750 #ifdef OS_IS_WIN32
1751 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1752 /* FIXME: Needs to set errno! */
1753 return NULL;
1754 global = buf;
1755 #endif
1757 if ((f = pa_fopen_cloexec(global, "r"))) {
1759 if (result)
1760 *result = pa_xstrdup(global);
1762 return f;
1766 errno = ENOENT;
1767 return NULL;
1770 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1771 const char *fn;
1772 #ifdef OS_IS_WIN32
1773 char buf[PATH_MAX];
1775 if (!getenv(PULSE_ROOTENV))
1776 pa_set_root(NULL);
1777 #endif
1779 if (env && (fn = getenv(env))) {
1781 #ifdef OS_IS_WIN32
1782 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1783 /* FIXME: Needs to set errno! */
1784 return NULL;
1785 fn = buf;
1786 #endif
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));
1792 return NULL;
1795 if (local) {
1796 const char *e;
1797 char *lfn;
1798 char *h;
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);
1804 pa_xfree(h);
1805 } else
1806 return NULL;
1808 #ifdef OS_IS_WIN32
1809 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1810 /* FIXME: Needs to set errno! */
1811 pa_xfree(lfn);
1812 return NULL;
1814 fn = buf;
1815 #endif
1817 if (access(fn, R_OK) == 0) {
1818 char *r = pa_xstrdup(fn);
1819 pa_xfree(lfn);
1820 return r;
1823 if (errno != ENOENT) {
1824 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1825 pa_xfree(lfn);
1826 return NULL;
1829 pa_xfree(lfn);
1832 if (global) {
1833 #ifdef OS_IS_WIN32
1834 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1835 /* FIXME: Needs to set errno! */
1836 return NULL;
1837 global = buf;
1838 #endif
1840 if (access(global, R_OK) == 0)
1841 return pa_xstrdup(global);
1844 errno = ENOENT;
1846 return NULL;
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";
1854 pa_assert(d);
1855 pa_assert(s);
1856 pa_assert(slength > 0);
1858 while (i < dlength && j+3 <= slength) {
1859 s[j++] = hex[*d >> 4];
1860 s[j++] = hex[*d & 0xF];
1862 d++;
1863 i++;
1866 s[j < slength ? j : slength] = 0;
1867 return s;
1870 /* Convert a hexadecimal digit to a number or -1 if invalid */
1871 static int hexc(char c) {
1872 if (c >= '0' && c <= '9')
1873 return c - '0';
1875 if (c >= 'A' && c <= 'F')
1876 return c - 'A' + 10;
1878 if (c >= 'a' && c <= 'f')
1879 return c - 'a' + 10;
1881 errno = EINVAL;
1882 return -1;
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) {
1887 size_t j = 0;
1889 pa_assert(p);
1890 pa_assert(d);
1892 while (j < dlength && *p) {
1893 int b;
1895 if ((b = hexc(*(p++))) < 0)
1896 return (size_t) -1;
1898 d[j] = (uint8_t) (b << 4);
1900 if (!*p)
1901 return (size_t) -1;
1903 if ((b = hexc(*(p++))) < 0)
1904 return (size_t) -1;
1906 d[j] |= (uint8_t) b;
1907 j++;
1910 return j;
1913 /* Returns nonzero when *s starts with *pfx */
1914 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1915 size_t l;
1917 pa_assert(s);
1918 pa_assert(pfx);
1920 l = strlen(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) {
1927 size_t l1, l2;
1929 pa_assert(s);
1930 pa_assert(sfx);
1932 l1 = strlen(s);
1933 l2 = strlen(sfx);
1935 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1938 pa_bool_t pa_is_path_absolute(const char *fn) {
1939 pa_assert(fn);
1941 #ifndef OS_IS_WIN32
1942 return *fn == '/';
1943 #else
1944 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1945 #endif
1948 char *pa_make_path_absolute(const char *p) {
1949 char *r;
1950 char *cwd;
1952 pa_assert(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);
1961 pa_xfree(cwd);
1962 return r;
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) {
1969 char *rtp;
1971 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1973 if (fn) {
1974 char *r;
1976 if (pa_is_path_absolute(fn))
1977 return pa_xstrdup(fn);
1979 if (!rtp)
1980 return NULL;
1982 if (prependmid) {
1983 char *mid;
1985 if (!(mid = pa_machine_id())) {
1986 pa_xfree(rtp);
1987 return NULL;
1990 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1991 pa_xfree(mid);
1992 } else
1993 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1995 pa_xfree(rtp);
1996 return r;
1997 } else
1998 return rtp;
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) {
2011 char *x = NULL;
2012 long l;
2014 pa_assert(s);
2015 pa_assert(ret_i);
2017 errno = 0;
2018 l = strtol(s, &x, 0);
2020 if (!x || *x || errno) {
2021 if (!errno)
2022 errno = EINVAL;
2023 return -1;
2026 if ((int32_t) l != l) {
2027 errno = ERANGE;
2028 return -1;
2031 *ret_i = (int32_t) l;
2033 return 0;
2036 /* Convert the string s to an unsigned integer in *ret_u */
2037 int pa_atou(const char *s, uint32_t *ret_u) {
2038 char *x = NULL;
2039 unsigned long l;
2041 pa_assert(s);
2042 pa_assert(ret_u);
2044 errno = 0;
2045 l = strtoul(s, &x, 0);
2047 if (!x || *x || errno) {
2048 if (!errno)
2049 errno = EINVAL;
2050 return -1;
2053 if ((uint32_t) l != l) {
2054 errno = ERANGE;
2055 return -1;
2058 *ret_u = (uint32_t) l;
2060 return 0;
2063 #ifdef HAVE_STRTOF_L
2064 static locale_t c_locale = NULL;
2066 static void c_locale_destroy(void) {
2067 freelocale(c_locale);
2069 #endif
2071 int pa_atod(const char *s, double *ret_d) {
2072 char *x = NULL;
2073 double f;
2075 pa_assert(s);
2076 pa_assert(ret_d);
2078 /* This should be locale independent */
2080 #ifdef HAVE_STRTOF_L
2082 PA_ONCE_BEGIN {
2084 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2085 atexit(c_locale_destroy);
2087 } PA_ONCE_END;
2089 if (c_locale) {
2090 errno = 0;
2091 f = strtod_l(s, &x, c_locale);
2092 } else
2093 #endif
2095 errno = 0;
2096 f = strtod(s, &x);
2099 if (!x || *x || errno) {
2100 if (!errno)
2101 errno = EINVAL;
2102 return -1;
2105 *ret_d = f;
2107 return 0;
2110 /* Same as snprintf, but guarantees NUL-termination on every platform */
2111 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2112 size_t ret;
2113 va_list ap;
2115 pa_assert(str);
2116 pa_assert(size > 0);
2117 pa_assert(format);
2119 va_start(ap, format);
2120 ret = pa_vsnprintf(str, size, format, ap);
2121 va_end(ap);
2123 return ret;
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) {
2128 int ret;
2130 pa_assert(str);
2131 pa_assert(size > 0);
2132 pa_assert(format);
2134 ret = vsnprintf(str, size, format, ap);
2136 str[size-1] = 0;
2138 if (ret < 0)
2139 return strlen(str);
2141 if ((size_t) ret > size-1)
2142 return 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) {
2150 pa_assert(c);
2151 pa_assert(pa_utf8_valid(c));
2153 if (strlen(c) <= l)
2154 return c;
2156 c[l] = 0;
2158 while (l > 0 && !pa_utf8_valid(c))
2159 c[--l] = 0;
2161 return c;
2164 char *pa_getcwd(void) {
2165 size_t l = 128;
2167 for (;;) {
2168 char *p = pa_xmalloc(l);
2169 if (getcwd(p, l))
2170 return p;
2172 if (errno != ERANGE)
2173 return NULL;
2175 pa_xfree(p);
2176 l *= 2;
2180 void *pa_will_need(const void *p, size_t l) {
2181 #ifdef RLIMIT_MEMLOCK
2182 struct rlimit rlim;
2183 #endif
2184 const void *a;
2185 size_t size;
2186 int r;
2187 size_t bs;
2189 pa_assert(p);
2190 pa_assert(l > 0);
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!");
2198 return (void*) p;
2200 #endif
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));
2214 errno = EPERM;
2215 return (void*) p;
2218 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2219 #else
2220 bs = PA_PAGE_SIZE*4;
2221 #endif
2223 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2225 #ifdef HAVE_MLOCK
2226 while (size > 0 && bs > 0) {
2228 if (bs > size)
2229 bs = size;
2231 if (mlock(a, bs) < 0) {
2232 bs = PA_PAGE_ALIGN(bs / 2);
2233 continue;
2236 pa_assert_se(munlock(a, bs) == 0);
2238 a = (const uint8_t*) a + bs;
2239 size -= bs;
2241 #endif
2243 if (bs <= 0)
2244 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2245 else
2246 pa_log_debug("mlock() worked fine!");
2248 return (void*) p;
2251 void pa_close_pipe(int fds[2]) {
2252 pa_assert(fds);
2254 if (fds[0] >= 0)
2255 pa_assert_se(pa_close(fds[0]) == 0);
2257 if (fds[1] >= 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
2265 size_t l = 100;
2267 for (;;) {
2268 char *c;
2269 ssize_t n;
2271 c = pa_xmalloc(l);
2273 if ((n = readlink(p, c, l-1)) < 0) {
2274 pa_xfree(c);
2275 return NULL;
2278 if ((size_t) n < l-1) {
2279 c[n] = 0;
2280 return c;
2283 pa_xfree(c);
2284 l *= 2;
2286 #else
2287 return NULL;
2288 #endif
2291 int pa_close_all(int except_fd, ...) {
2292 va_list ap;
2293 unsigned n = 0, i;
2294 int r, *p;
2296 va_start(ap, except_fd);
2298 if (except_fd >= 0)
2299 for (n = 1; va_arg(ap, int) >= 0; n++)
2302 va_end(ap);
2304 p = pa_xnew(int, n+1);
2306 va_start(ap, except_fd);
2308 i = 0;
2309 if (except_fd >= 0) {
2310 int fd;
2311 p[i++] = except_fd;
2313 while ((fd = va_arg(ap, int)) >= 0)
2314 p[i++] = fd;
2316 p[i] = -1;
2318 va_end(ap);
2320 r = pa_close_allv(p);
2321 pa_xfree(p);
2323 return r;
2326 int pa_close_allv(const int except_fds[]) {
2327 #ifndef OS_IS_WIN32
2328 struct rlimit rl;
2329 int maxfd, fd;
2331 #ifdef __linux__
2332 int saved_errno;
2333 DIR *d;
2335 if ((d = opendir("/proc/self/fd"))) {
2337 struct dirent *de;
2339 while ((de = readdir(d))) {
2340 pa_bool_t found;
2341 long l;
2342 char *e = NULL;
2343 int i;
2345 if (de->d_name[0] == '.')
2346 continue;
2348 errno = 0;
2349 l = strtol(de->d_name, &e, 10);
2350 if (errno != 0 || !e || *e) {
2351 closedir(d);
2352 errno = EINVAL;
2353 return -1;
2356 fd = (int) l;
2358 if ((long) fd != l) {
2359 closedir(d);
2360 errno = EINVAL;
2361 return -1;
2364 if (fd < 3)
2365 continue;
2367 if (fd == dirfd(d))
2368 continue;
2370 found = FALSE;
2371 for (i = 0; except_fds[i] >= 0; i++)
2372 if (except_fds[i] == fd) {
2373 found = TRUE;
2374 break;
2377 if (found)
2378 continue;
2380 if (pa_close(fd) < 0) {
2381 saved_errno = errno;
2382 closedir(d);
2383 errno = saved_errno;
2385 return -1;
2389 closedir(d);
2390 return 0;
2393 #endif
2395 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2396 maxfd = (int) rl.rlim_max;
2397 else
2398 maxfd = sysconf(_SC_OPEN_MAX);
2400 for (fd = 3; fd < maxfd; fd++) {
2401 int i;
2402 pa_bool_t found;
2404 found = FALSE;
2405 for (i = 0; except_fds[i] >= 0; i++)
2406 if (except_fds[i] == fd) {
2407 found = TRUE;
2408 break;
2411 if (found)
2412 continue;
2414 if (pa_close(fd) < 0 && errno != EBADF)
2415 return -1;
2417 #endif /* !OS_IS_WIN32 */
2419 return 0;
2422 int pa_unblock_sigs(int except, ...) {
2423 va_list ap;
2424 unsigned n = 0, i;
2425 int r, *p;
2427 va_start(ap, except);
2429 if (except >= 1)
2430 for (n = 1; va_arg(ap, int) >= 0; n++)
2433 va_end(ap);
2435 p = pa_xnew(int, n+1);
2437 va_start(ap, except);
2439 i = 0;
2440 if (except >= 1) {
2441 int sig;
2442 p[i++] = except;
2444 while ((sig = va_arg(ap, int)) >= 0)
2445 p[i++] = sig;
2447 p[i] = -1;
2449 va_end(ap);
2451 r = pa_unblock_sigsv(p);
2452 pa_xfree(p);
2454 return r;
2457 int pa_unblock_sigsv(const int except[]) {
2458 #ifndef OS_IS_WIN32
2459 int i;
2460 sigset_t ss;
2462 if (sigemptyset(&ss) < 0)
2463 return -1;
2465 for (i = 0; except[i] > 0; i++)
2466 if (sigaddset(&ss, except[i]) < 0)
2467 return -1;
2469 return sigprocmask(SIG_SETMASK, &ss, NULL);
2470 #else
2471 return 0;
2472 #endif
2475 int pa_reset_sigs(int except, ...) {
2476 va_list ap;
2477 unsigned n = 0, i;
2478 int *p, r;
2480 va_start(ap, except);
2482 if (except >= 1)
2483 for (n = 1; va_arg(ap, int) >= 0; n++)
2486 va_end(ap);
2488 p = pa_xnew(int, n+1);
2490 va_start(ap, except);
2492 i = 0;
2493 if (except >= 1) {
2494 int sig;
2495 p[i++] = except;
2497 while ((sig = va_arg(ap, int)) >= 0)
2498 p[i++] = sig;
2500 p[i] = -1;
2502 va_end(ap);
2504 r = pa_reset_sigsv(p);
2505 pa_xfree(p);
2507 return r;
2510 int pa_reset_sigsv(const int except[]) {
2511 #ifndef OS_IS_WIN32
2512 int sig;
2514 for (sig = 1; sig < NSIG; sig++) {
2515 pa_bool_t reset = TRUE;
2517 switch (sig) {
2518 case SIGKILL:
2519 case SIGSTOP:
2520 reset = FALSE;
2521 break;
2523 default: {
2524 int i;
2526 for (i = 0; except[i] > 0; i++) {
2527 if (sig == except[i]) {
2528 reset = FALSE;
2529 break;
2535 if (reset) {
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)
2545 return -1;
2548 #endif
2550 return 0;
2553 void pa_set_env(const char *key, const char *value) {
2554 pa_assert(key);
2555 pa_assert(value);
2557 /* This is not thread-safe */
2559 #ifdef OS_IS_WIN32
2560 SetEnvironmentVariable(key, value);
2561 #else
2562 setenv(key, value, 1);
2563 #endif
2566 void pa_set_env_and_record(const char *key, const char *value) {
2567 pa_assert(key);
2568 pa_assert(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 */
2580 for (;;) {
2581 char *s;
2583 recorded_env = pa_strlist_pop(recorded_env, &s);
2585 if (!s)
2586 break;
2588 #ifdef OS_IS_WIN32
2589 SetEnvironmentVariable(s, NULL);
2590 #else
2591 unsetenv(s);
2592 #endif
2593 pa_xfree(s);
2597 pa_bool_t pa_in_system_mode(void) {
2598 const char *e;
2600 if (!(e = getenv("PULSE_SYSTEM")))
2601 return FALSE;
2603 return !!atoi(e);
2606 char *pa_get_user_name_malloc(void) {
2607 ssize_t k;
2608 char *u;
2610 #ifdef _SC_LOGIN_NAME_MAX
2611 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2613 if (k <= 0)
2614 #endif
2615 k = 32;
2617 u = pa_xnew(char, k+1);
2619 if (!(pa_get_user_name(u, k))) {
2620 pa_xfree(u);
2621 return NULL;
2624 return u;
2627 char *pa_get_host_name_malloc(void) {
2628 size_t l;
2630 l = 100;
2631 for (;;) {
2632 char *c;
2634 c = pa_xmalloc(l);
2636 if (!pa_get_host_name(c, l)) {
2638 if (errno != EINVAL && errno != ENAMETOOLONG)
2639 break;
2641 } else if (strlen(c) < l-1) {
2642 char *u;
2644 if (*c == 0) {
2645 pa_xfree(c);
2646 break;
2649 u = pa_utf8_filter(c);
2650 pa_xfree(c);
2651 return u;
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. */
2658 pa_xfree(c);
2659 l *= 2;
2662 return NULL;
2665 char *pa_machine_id(void) {
2666 FILE *f;
2667 char *h;
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);
2680 fclose(f);
2682 pa_strip_nl(ln);
2684 if (r && ln[0])
2685 return pa_utf8_filter(ln);
2688 if ((h = pa_get_host_name_malloc()))
2689 return h;
2691 #ifndef OS_IS_WIN32
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);
2695 #else
2696 return NULL;
2697 #endif
2700 char *pa_session_id(void) {
2701 const char *e;
2703 if (!(e = getenv("XDG_SESSION_COOKIE")))
2704 return NULL;
2706 return pa_utf8_filter(e);
2709 char *pa_uname_string(void) {
2710 #ifdef HAVE_UNAME
2711 struct utsname u;
2713 pa_assert_se(uname(&u) >= 0);
2715 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2716 #endif
2717 #ifdef OS_IS_WIN32
2718 OSVERSIONINFO i;
2720 pa_zero(i);
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);
2725 #endif
2728 #ifdef HAVE_VALGRIND_MEMCHECK_H
2729 pa_bool_t pa_in_valgrind(void) {
2730 static int b = 0;
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
2734 * not. */
2736 if (b < 1)
2737 b = getenv("VALGRIND") ? 2 : 1;
2739 return b > 1;
2741 #endif
2743 unsigned pa_gcd(unsigned a, unsigned b) {
2745 while (b > 0) {
2746 unsigned t = b;
2747 b = a % b;
2748 a = t;
2751 return a;
2754 void pa_reduce(unsigned *num, unsigned *den) {
2756 unsigned gcd = pa_gcd(*num, *den);
2758 if (gcd <= 0)
2759 return;
2761 *num /= gcd;
2762 *den /= gcd;
2764 pa_assert(pa_gcd(*num, *den) == 1);
2767 unsigned pa_ncpus(void) {
2768 long ncpus;
2770 #ifdef _SC_NPROCESSORS_CONF
2771 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2772 #else
2773 ncpus = 1;
2774 #endif
2776 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2779 char *pa_replace(const char*s, const char*a, const char *b) {
2780 pa_strbuf *sb;
2781 size_t an;
2783 pa_assert(s);
2784 pa_assert(a);
2785 pa_assert(b);
2787 an = strlen(a);
2788 sb = pa_strbuf_new();
2790 for (;;) {
2791 const char *p;
2793 if (!(p = strstr(s, a)))
2794 break;
2796 pa_strbuf_putsn(sb, s, p-s);
2797 pa_strbuf_puts(sb, b);
2798 s = p + an;
2801 pa_strbuf_puts(sb, s);
2803 return pa_strbuf_tostring_free(sb);
2806 char *pa_escape(const char *p, const char *chars) {
2807 const char *s;
2808 const char *c;
2809 pa_strbuf *buf = pa_strbuf_new();
2811 for (s = p; *s; ++s) {
2812 if (*s == '\\')
2813 pa_strbuf_putc(buf, '\\');
2814 else if (chars) {
2815 for (c = chars; *c; ++c) {
2816 if (*s == *c) {
2817 pa_strbuf_putc(buf, '\\');
2818 break;
2822 pa_strbuf_putc(buf, *s);
2825 return pa_strbuf_tostring_free(buf);
2828 char *pa_unescape(char *p) {
2829 char *s, *d;
2830 pa_bool_t escaped = FALSE;
2832 for (s = p, d = p; *s; s++) {
2833 if (!escaped && *s == '\\') {
2834 escaped = TRUE;
2835 continue;
2838 *(d++) = *s;
2839 escaped = FALSE;
2842 *d = 0;
2844 return p;
2847 char *pa_realpath(const char *path) {
2848 char *t;
2849 pa_assert(path);
2851 /* We want only abolsute paths */
2852 if (path[0] != '/') {
2853 errno = EINVAL;
2854 return NULL;
2857 #if defined(__GLIBC__) || defined(__APPLE__)
2859 char *r;
2861 if (!(r = realpath(path, NULL)))
2862 return NULL;
2864 /* We copy this here in case our pa_xmalloc() is not
2865 * implemented on top of libc malloc() */
2866 t = pa_xstrdup(r);
2867 pa_xfree(r);
2869 #elif defined(PATH_MAX)
2871 char *path_buf;
2872 path_buf = pa_xmalloc(PATH_MAX);
2874 #if defined(OS_IS_WIN32)
2875 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2876 pa_xfree(path_buf);
2877 return NULL;
2879 #else
2880 if (!(t = realpath(path, path_buf))) {
2881 pa_xfree(path_buf);
2882 return NULL;
2884 #endif
2886 #else
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."
2888 #endif
2890 return t;
2893 void pa_disable_sigpipe(void) {
2895 #ifdef SIGPIPE
2896 struct sigaction sa;
2898 pa_zero(sa);
2900 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2901 pa_log("sigaction(): %s", pa_cstrerror(errno));
2902 return;
2905 sa.sa_handler = SIG_IGN;
2907 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2908 pa_log("sigaction(): %s", pa_cstrerror(errno));
2909 return;
2911 #endif
2914 void pa_xfreev(void**a) {
2915 void **p;
2917 if (!a)
2918 return;
2920 for (p = a; *p; p++)
2921 pa_xfree(*p);
2923 pa_xfree(a);
2926 char **pa_split_spaces_strv(const char *s) {
2927 char **t, *e;
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))) {
2933 t[i++] = e;
2935 if (i >= n) {
2936 n *= 2;
2937 t = pa_xrenew(char*, t, n);
2941 if (i <= 0) {
2942 pa_xfree(t);
2943 return NULL;
2946 t[i] = NULL;
2947 return t;
2950 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2951 pa_assert(path);
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) {
2961 #ifdef _PC_PIPE_BUF
2962 long n;
2964 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2965 return (size_t) n;
2966 #endif
2968 #ifdef PIPE_BUF
2969 return PIPE_BUF;
2970 #else
2971 return 4096;
2972 #endif
2975 void pa_reset_personality(void) {
2977 #ifdef __linux__
2978 if (personality(PER_LINUX) < 0)
2979 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2980 #endif
2984 #if defined(__linux__) && !defined(__OPTIMIZE__)
2986 pa_bool_t pa_run_from_build_tree(void) {
2987 char *rp;
2988 pa_bool_t b = FALSE;
2990 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2991 * or not. */
2993 if ((rp = pa_readlink("/proc/self/exe"))) {
2994 b = pa_startswith(rp, PA_BUILDDIR);
2995 pa_xfree(rp);
2998 return b;
3001 #endif
3003 const char *pa_get_temp_dir(void) {
3004 const char *t;
3006 if ((t = getenv("TMPDIR")) &&
3007 pa_is_path_absolute(t))
3008 return t;
3010 if ((t = getenv("TMP")) &&
3011 pa_is_path_absolute(t))
3012 return t;
3014 if ((t = getenv("TEMP")) &&
3015 pa_is_path_absolute(t))
3016 return t;
3018 if ((t = getenv("TEMPDIR")) &&
3019 pa_is_path_absolute(t))
3020 return t;
3022 return "/tmp";
3025 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3026 int fd;
3028 #ifdef O_NOCTTY
3029 flags |= O_NOCTTY;
3030 #endif
3032 #ifdef O_CLOEXEC
3033 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3034 goto finish;
3036 if (errno != EINVAL)
3037 return fd;
3038 #endif
3040 if ((fd = open(fn, flags, mode)) < 0)
3041 return fd;
3043 finish:
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);
3048 return fd;
3051 int pa_socket_cloexec(int domain, int type, int protocol) {
3052 int fd;
3054 #ifdef SOCK_CLOEXEC
3055 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3056 goto finish;
3058 if (errno != EINVAL)
3059 return fd;
3060 #endif
3062 if ((fd = socket(domain, type, protocol)) < 0)
3063 return fd;
3065 finish:
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);
3070 return fd;
3073 int pa_pipe_cloexec(int pipefd[2]) {
3074 int r;
3076 #ifdef HAVE_PIPE2
3077 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3078 goto finish;
3080 if (errno != EINVAL && errno != ENOSYS)
3081 return r;
3083 #endif
3085 if ((r = pipe(pipefd)) < 0)
3086 return r;
3088 finish:
3089 pa_make_fd_cloexec(pipefd[0]);
3090 pa_make_fd_cloexec(pipefd[1]);
3092 return 0;
3095 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3096 int fd;
3098 #ifdef HAVE_ACCEPT4
3099 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3100 goto finish;
3102 if (errno != EINVAL && errno != ENOSYS)
3103 return fd;
3105 #endif
3107 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3108 return fd;
3110 finish:
3111 pa_make_fd_cloexec(fd);
3112 return fd;
3115 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3116 FILE *f;
3117 char *m;
3119 m = pa_sprintf_malloc("%se", mode);
3121 errno = 0;
3122 if ((f = fopen(path, m))) {
3123 pa_xfree(m);
3124 goto finish;
3127 pa_xfree(m);
3129 if (errno != EINVAL)
3130 return NULL;
3132 if (!(f = fopen(path, mode)))
3133 return NULL;
3135 finish:
3136 pa_make_fd_cloexec(fileno(f));
3137 return f;
3140 void pa_nullify_stdfds(void) {
3142 #ifndef OS_IS_WIN32
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);
3150 #else
3151 FreeConsole();
3152 #endif
3156 char *pa_read_line_from_file(const char *fn) {
3157 FILE *f;
3158 char ln[256] = "", *r;
3160 if (!(f = pa_fopen_cloexec(fn, "r")))
3161 return NULL;
3163 r = fgets(ln, sizeof(ln)-1, f);
3164 fclose(f);
3166 if (!r) {
3167 errno = EIO;
3168 return NULL;
3171 pa_strip_nl(ln);
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;
3182 union {
3183 uint32_t sig32[3];
3184 char text[13];
3185 } sig;
3187 #ifdef __linux__
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"
3194 unsigned i;
3196 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3197 char *s;
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")) {
3209 pa_xfree(s);
3210 return TRUE;
3213 pa_xfree(s);
3217 #endif
3219 /* http://lwn.net/Articles/301888/ */
3220 pa_zero(sig);
3222 __asm__ __volatile__ (
3223 /* ebx/rbx is being used for PIC! */
3224 " push %%"PA_REG_b" \n\t"
3225 " cpuid \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])
3230 : "0" (eax)
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"))
3239 return TRUE;
3241 #endif
3243 return FALSE;