Apply #ifdefs around functionality not available on win32
[pulseaudio-mirror.git] / src / pulsecore / core-util.c
blob4c4fbfe04d2aff2e8118ca91318034d24f145ca7
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 <time.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <dirent.h>
43 #include <regex.h>
45 #ifdef HAVE_LANGINFO_H
46 #include <langinfo.h>
47 #endif
49 #ifdef HAVE_UNAME
50 #include <sys/utsname.h>
51 #endif
53 #ifdef HAVE_STRTOF_L
54 #include <locale.h>
55 #endif
57 #ifdef HAVE_SCHED_H
58 #include <sched.h>
60 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
61 #define SCHED_RESET_ON_FORK 0x40000000
62 #endif
63 #endif
65 #ifdef HAVE_SYS_RESOURCE_H
66 #include <sys/resource.h>
67 #endif
69 #ifdef HAVE_SYS_CAPABILITY_H
70 #include <sys/capability.h>
71 #endif
73 #ifdef HAVE_SYS_MMAN_H
74 #include <sys/mman.h>
75 #endif
77 #ifdef HAVE_PTHREAD
78 #include <pthread.h>
79 #endif
81 #ifdef HAVE_NETDB_H
82 #include <netdb.h>
83 #endif
85 #ifdef HAVE_WINDOWS_H
86 #include <windows.h>
87 #endif
89 #ifdef HAVE_PWD_H
90 #include <pwd.h>
91 #endif
93 #ifdef HAVE_GRP_H
94 #include <grp.h>
95 #endif
97 #ifdef HAVE_LIBSAMPLERATE
98 #include <samplerate.h>
99 #endif
101 #ifdef __APPLE__
102 #include <xlocale.h>
103 #endif
105 #ifdef HAVE_DBUS
106 #include "rtkit.h"
107 #endif
109 #ifdef __linux__
110 #include <sys/personality.h>
111 #endif
113 #include <pulse/xmalloc.h>
114 #include <pulse/util.h>
115 #include <pulse/utf8.h>
117 #include <pulsecore/core-error.h>
118 #include <pulsecore/socket.h>
119 #include <pulsecore/log.h>
120 #include <pulsecore/macro.h>
121 #include <pulsecore/thread.h>
122 #include <pulsecore/strbuf.h>
123 #include <pulsecore/usergroup.h>
124 #include <pulsecore/strlist.h>
125 #include <pulsecore/cpu-x86.h>
127 #include "core-util.h"
129 /* Not all platforms have this */
130 #ifndef MSG_NOSIGNAL
131 #define MSG_NOSIGNAL 0
132 #endif
134 #define NEWLINE "\r\n"
135 #define WHITESPACE "\n\r \t"
137 static pa_strlist *recorded_env = NULL;
139 #ifdef OS_IS_WIN32
141 #define PULSE_ROOTENV "PULSE_ROOT"
143 int pa_set_root(HANDLE handle) {
144 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
146 strcpy(library_path, PULSE_ROOTENV "=");
148 /* FIXME: Needs to set errno */
150 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
151 return 0;
153 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
154 if (sep)
155 *sep = '\0';
157 if (_putenv(library_path) < 0)
158 return 0;
160 return 1;
163 #endif
165 /** Make a file descriptor nonblock. Doesn't do any error checking */
166 void pa_make_fd_nonblock(int fd) {
168 #ifdef O_NONBLOCK
169 int v;
170 pa_assert(fd >= 0);
172 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
174 if (!(v & O_NONBLOCK))
175 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
177 #elif defined(OS_IS_WIN32)
178 u_long arg = 1;
179 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
180 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
181 pa_log_warn("Only sockets can be made non-blocking!");
183 #else
184 pa_log_warn("Non-blocking I/O not supported.!");
185 #endif
189 /* Set the FD_CLOEXEC flag for a fd */
190 void pa_make_fd_cloexec(int fd) {
192 #ifdef FD_CLOEXEC
193 int v;
194 pa_assert(fd >= 0);
196 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
198 if (!(v & FD_CLOEXEC))
199 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
200 #endif
204 /** Creates a directory securely */
205 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
206 struct stat st;
207 int r, saved_errno, fd;
209 pa_assert(dir);
211 #ifdef OS_IS_WIN32
212 r = mkdir(dir);
213 #else
215 mode_t u;
216 u = umask((~m) & 0777);
217 r = mkdir(dir, m);
218 umask(u);
220 #endif
222 if (r < 0 && errno != EEXIST)
223 return -1;
225 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
226 if ((fd = open(dir,
227 #ifdef O_CLOEXEC
228 O_CLOEXEC|
229 #endif
230 #ifdef O_NOCTTY
231 O_NOCTTY|
232 #endif
233 #ifdef O_NOFOLLOW
234 O_NOFOLLOW|
235 #endif
236 O_RDONLY)) < 0)
237 goto fail;
239 if (fstat(fd, &st) < 0) {
240 pa_assert_se(pa_close(fd) >= 0);
241 goto fail;
244 if (!S_ISDIR(st.st_mode)) {
245 pa_assert_se(pa_close(fd) >= 0);
246 errno = EEXIST;
247 goto fail;
250 #ifdef HAVE_FCHOWN
251 if (uid == (uid_t)-1)
252 uid = getuid();
253 if (gid == (gid_t)-1)
254 gid = getgid();
255 (void) fchown(fd, uid, gid);
256 #endif
258 #ifdef HAVE_FCHMOD
259 (void) fchmod(fd, m);
260 #endif
262 pa_assert_se(pa_close(fd) >= 0);
263 #endif
265 #ifdef HAVE_LSTAT
266 if (lstat(dir, &st) < 0)
267 #else
268 if (stat(dir, &st) < 0)
269 #endif
270 goto fail;
272 #ifndef OS_IS_WIN32
273 if (!S_ISDIR(st.st_mode) ||
274 (st.st_uid != uid) ||
275 (st.st_gid != gid) ||
276 ((st.st_mode & 0777) != m)) {
277 errno = EACCES;
278 goto fail;
280 #else
281 pa_log_warn("Secure directory creation not supported on Win32.");
282 #endif
284 return 0;
286 fail:
287 saved_errno = errno;
288 rmdir(dir);
289 errno = saved_errno;
291 return -1;
294 /* Return a newly allocated sting containing the parent directory of the specified file */
295 char *pa_parent_dir(const char *fn) {
296 char *slash, *dir = pa_xstrdup(fn);
298 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
299 pa_xfree(dir);
300 errno = ENOENT;
301 return NULL;
304 *(slash-1) = 0;
305 return dir;
308 /* Creates a the parent directory of the specified path securely */
309 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
310 int ret = -1;
311 char *dir;
313 if (!(dir = pa_parent_dir(fn)))
314 goto finish;
316 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
317 goto finish;
319 ret = 0;
321 finish:
322 pa_xfree(dir);
323 return ret;
326 /** Platform independent read function. Necessary since not all
327 * systems treat all file descriptors equal. If type is
328 * non-NULL it is used to cache the type of the fd. This is
329 * useful for making sure that only a single syscall is executed per
330 * function call. The variable pointed to should be initialized to 0
331 * by the caller. */
332 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
334 #ifdef OS_IS_WIN32
336 if (!type || *type == 0) {
337 ssize_t r;
339 if ((r = recv(fd, buf, count, 0)) >= 0)
340 return r;
342 if (WSAGetLastError() != WSAENOTSOCK) {
343 errno = WSAGetLastError();
344 return r;
347 if (type)
348 *type = 1;
351 #endif
353 for (;;) {
354 ssize_t r;
356 if ((r = read(fd, buf, count)) < 0)
357 if (errno == EINTR)
358 continue;
360 return r;
364 /** Similar to pa_read(), but handles writes */
365 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
367 if (!type || *type == 0) {
368 ssize_t r;
370 for (;;) {
371 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
373 if (errno == EINTR)
374 continue;
376 break;
379 return r;
382 #ifdef OS_IS_WIN32
383 if (WSAGetLastError() != WSAENOTSOCK) {
384 errno = WSAGetLastError();
385 return r;
387 #else
388 if (errno != ENOTSOCK)
389 return r;
390 #endif
392 if (type)
393 *type = 1;
396 for (;;) {
397 ssize_t r;
399 if ((r = write(fd, buf, count)) < 0)
400 if (errno == EINTR)
401 continue;
403 return r;
407 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
408 * unless EOF is reached or an error occurred */
409 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
410 ssize_t ret = 0;
411 int _type;
413 pa_assert(fd >= 0);
414 pa_assert(data);
415 pa_assert(size);
417 if (!type) {
418 _type = 0;
419 type = &_type;
422 while (size > 0) {
423 ssize_t r;
425 if ((r = pa_read(fd, data, size, type)) < 0)
426 return r;
428 if (r == 0)
429 break;
431 ret += r;
432 data = (uint8_t*) data + r;
433 size -= (size_t) r;
436 return ret;
439 /** Similar to pa_loop_read(), but wraps write() */
440 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
441 ssize_t ret = 0;
442 int _type;
444 pa_assert(fd >= 0);
445 pa_assert(data);
446 pa_assert(size);
448 if (!type) {
449 _type = 0;
450 type = &_type;
453 while (size > 0) {
454 ssize_t r;
456 if ((r = pa_write(fd, data, size, type)) < 0)
457 return r;
459 if (r == 0)
460 break;
462 ret += r;
463 data = (const uint8_t*) data + r;
464 size -= (size_t) r;
467 return ret;
470 /** Platform independent read function. Necessary since not all
471 * systems treat all file descriptors equal. */
472 int pa_close(int fd) {
474 #ifdef OS_IS_WIN32
475 int ret;
477 if ((ret = closesocket(fd)) == 0)
478 return 0;
480 if (WSAGetLastError() != WSAENOTSOCK) {
481 errno = WSAGetLastError();
482 return ret;
484 #endif
486 for (;;) {
487 int r;
489 if ((r = close(fd)) < 0)
490 if (errno == EINTR)
491 continue;
493 return r;
497 /* Print a warning messages in case that the given signal is not
498 * blocked or trapped */
499 void pa_check_signal_is_blocked(int sig) {
500 #ifdef HAVE_SIGACTION
501 struct sigaction sa;
502 sigset_t set;
504 /* If POSIX threads are supported use thread-aware
505 * pthread_sigmask() function, to check if the signal is
506 * blocked. Otherwise fall back to sigprocmask() */
508 #ifdef HAVE_PTHREAD
509 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
510 #endif
511 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
512 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
513 return;
515 #ifdef HAVE_PTHREAD
517 #endif
519 if (sigismember(&set, sig))
520 return;
522 /* Check whether the signal is trapped */
524 if (sigaction(sig, NULL, &sa) < 0) {
525 pa_log("sigaction(): %s", pa_cstrerror(errno));
526 return;
529 if (sa.sa_handler != SIG_DFL)
530 return;
532 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
533 #else /* HAVE_SIGACTION */
534 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
535 #endif
538 /* The following function is based on an example from the GNU libc
539 * documentation. This function is similar to GNU's asprintf(). */
540 char *pa_sprintf_malloc(const char *format, ...) {
541 size_t size = 100;
542 char *c = NULL;
544 pa_assert(format);
546 for(;;) {
547 int r;
548 va_list ap;
550 c = pa_xrealloc(c, size);
552 va_start(ap, format);
553 r = vsnprintf(c, size, format, ap);
554 va_end(ap);
556 c[size-1] = 0;
558 if (r > -1 && (size_t) r < size)
559 return c;
561 if (r > -1) /* glibc 2.1 */
562 size = (size_t) r+1;
563 else /* glibc 2.0 */
564 size *= 2;
568 /* Same as the previous function, but use a va_list instead of an
569 * ellipsis */
570 char *pa_vsprintf_malloc(const char *format, va_list ap) {
571 size_t size = 100;
572 char *c = NULL;
574 pa_assert(format);
576 for(;;) {
577 int r;
578 va_list aq;
580 c = pa_xrealloc(c, size);
582 va_copy(aq, ap);
583 r = vsnprintf(c, size, format, aq);
584 va_end(aq);
586 c[size-1] = 0;
588 if (r > -1 && (size_t) r < size)
589 return c;
591 if (r > -1) /* glibc 2.1 */
592 size = (size_t) r+1;
593 else /* glibc 2.0 */
594 size *= 2;
598 /* Similar to OpenBSD's strlcpy() function */
599 char *pa_strlcpy(char *b, const char *s, size_t l) {
600 size_t k;
602 pa_assert(b);
603 pa_assert(s);
604 pa_assert(l > 0);
606 k = strlen(s);
608 if (k > l-1)
609 k = l-1;
611 memcpy(b, s, k);
612 b[k] = 0;
614 return b;
617 static int set_scheduler(int rtprio) {
618 #ifdef HAVE_SCHED_H
619 struct sched_param sp;
620 #ifdef HAVE_DBUS
621 int r;
622 DBusError error;
623 DBusConnection *bus;
625 dbus_error_init(&error);
626 #endif
628 pa_zero(sp);
629 sp.sched_priority = rtprio;
631 #ifdef SCHED_RESET_ON_FORK
632 if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
633 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
634 return 0;
636 #endif
638 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
639 pa_log_debug("SCHED_RR worked.");
640 return 0;
642 #endif /* HAVE_SCHED_H */
644 #ifdef HAVE_DBUS
645 /* Try to talk to RealtimeKit */
647 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
648 pa_log("Failed to connect to system bus: %s\n", error.message);
649 dbus_error_free(&error);
650 errno = -EIO;
651 return -1;
654 /* We need to disable exit on disconnect because otherwise
655 * dbus_shutdown will kill us. See
656 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
657 dbus_connection_set_exit_on_disconnect(bus, FALSE);
659 r = rtkit_make_realtime(bus, 0, rtprio);
660 dbus_connection_unref(bus);
662 if (r >= 0) {
663 pa_log_debug("RealtimeKit worked.");
664 return 0;
667 errno = -r;
668 #else
669 errno = 0;
670 #endif
672 return -1;
675 /* Make the current thread a realtime thread, and acquire the highest
676 * rtprio we can get that is less or equal the specified parameter. If
677 * the thread is already realtime, don't do anything. */
678 int pa_make_realtime(int rtprio) {
680 #ifdef _POSIX_PRIORITY_SCHEDULING
681 int p;
683 if (set_scheduler(rtprio) >= 0) {
684 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
685 return 0;
688 for (p = rtprio-1; p >= 1; p--)
689 if (set_scheduler(p) >= 0) {
690 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
691 return 0;
694 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
695 return -1;
696 #else
698 errno = ENOTSUP;
699 return -1;
700 #endif
703 static int set_nice(int nice_level) {
704 #ifdef HAVE_DBUS
705 DBusError error;
706 DBusConnection *bus;
707 int r;
709 dbus_error_init(&error);
710 #endif
712 #ifdef HAVE_SYS_RESOURCE_H
713 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
714 pa_log_debug("setpriority() worked.");
715 return 0;
717 #endif
719 #ifdef HAVE_DBUS
720 /* Try to talk to RealtimeKit */
722 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
723 pa_log("Failed to connect to system bus: %s\n", error.message);
724 dbus_error_free(&error);
725 errno = -EIO;
726 return -1;
729 /* We need to disable exit on disconnect because otherwise
730 * dbus_shutdown will kill us. See
731 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
732 dbus_connection_set_exit_on_disconnect(bus, FALSE);
734 r = rtkit_make_high_priority(bus, 0, nice_level);
735 dbus_connection_unref(bus);
737 if (r >= 0) {
738 pa_log_debug("RealtimeKit worked.");
739 return 0;
742 errno = -r;
743 #endif
745 return -1;
748 /* Raise the priority of the current process as much as possible that
749 * is <= the specified nice level..*/
750 int pa_raise_priority(int nice_level) {
752 #ifdef HAVE_SYS_RESOURCE_H
753 int n;
755 if (set_nice(nice_level) >= 0) {
756 pa_log_info("Successfully gained nice level %i.", nice_level);
757 return 0;
760 for (n = nice_level+1; n < 0; n++)
761 if (set_nice(n) >= 0) {
762 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
763 return 0;
766 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
767 return -1;
768 #endif
770 #ifdef OS_IS_WIN32
771 if (nice_level < 0) {
772 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
773 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
774 errno = EPERM;
775 return -1;
778 pa_log_info("Successfully gained high priority class.");
780 #endif
782 return 0;
785 /* Reset the priority to normal, inverting the changes made by
786 * pa_raise_priority() and pa_make_realtime()*/
787 void pa_reset_priority(void) {
788 #ifdef HAVE_SYS_RESOURCE_H
789 struct sched_param sp;
791 setpriority(PRIO_PROCESS, 0, 0);
793 pa_zero(sp);
794 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
795 #endif
797 #ifdef OS_IS_WIN32
798 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
799 #endif
802 int pa_match(const char *expr, const char *v) {
803 int k;
804 regex_t re;
805 int r;
807 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
808 errno = EINVAL;
809 return -1;
812 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
813 r = 1;
814 else if (k == REG_NOMATCH)
815 r = 0;
816 else
817 r = -1;
819 regfree(&re);
821 if (r < 0)
822 errno = EINVAL;
824 return r;
827 /* Try to parse a boolean string value.*/
828 int pa_parse_boolean(const char *v) {
829 const char *expr;
830 pa_assert(v);
832 /* First we check language independant */
833 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
834 return 1;
835 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
836 return 0;
838 #ifdef HAVE_LANGINFO_H
839 /* And then we check language dependant */
840 if ((expr = nl_langinfo(YESEXPR)))
841 if (expr[0])
842 if (pa_match(expr, v) > 0)
843 return 1;
845 if ((expr = nl_langinfo(NOEXPR)))
846 if (expr[0])
847 if (pa_match(expr, v) > 0)
848 return 0;
849 #endif
851 errno = EINVAL;
852 return -1;
855 /* Split the specified string wherever one of the strings in delimiter
856 * occurs. Each time it is called returns a newly allocated string
857 * with pa_xmalloc(). The variable state points to, should be
858 * initiallized to NULL before the first call. */
859 char *pa_split(const char *c, const char *delimiter, const char**state) {
860 const char *current = *state ? *state : c;
861 size_t l;
863 if (!*current)
864 return NULL;
866 l = strcspn(current, delimiter);
867 *state = current+l;
869 if (**state)
870 (*state)++;
872 return pa_xstrndup(current, l);
875 /* Split a string into words. Otherwise similar to pa_split(). */
876 char *pa_split_spaces(const char *c, const char **state) {
877 const char *current = *state ? *state : c;
878 size_t l;
880 if (!*current || *c == 0)
881 return NULL;
883 current += strspn(current, WHITESPACE);
884 l = strcspn(current, WHITESPACE);
886 *state = current+l;
888 return pa_xstrndup(current, l);
891 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
893 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
894 const char *pa_sig2str(int sig) {
895 char *t;
897 if (sig <= 0)
898 goto fail;
900 #ifdef NSIG
901 if (sig >= NSIG)
902 goto fail;
903 #endif
905 #ifdef HAVE_SIG2STR
907 char buf[SIG2STR_MAX];
909 if (sig2str(sig, buf) == 0) {
910 pa_xfree(PA_STATIC_TLS_GET(signame));
911 t = pa_sprintf_malloc("SIG%s", buf);
912 PA_STATIC_TLS_SET(signame, t);
913 return t;
916 #else
918 switch(sig) {
919 #ifdef SIGHUP
920 case SIGHUP: return "SIGHUP";
921 #endif
922 case SIGINT: return "SIGINT";
923 #ifdef SIGQUIT
924 case SIGQUIT: return "SIGQUIT";
925 #endif
926 case SIGILL: return "SIGULL";
927 #ifdef SIGTRAP
928 case SIGTRAP: return "SIGTRAP";
929 #endif
930 case SIGABRT: return "SIGABRT";
931 #ifdef SIGBUS
932 case SIGBUS: return "SIGBUS";
933 #endif
934 case SIGFPE: return "SIGFPE";
935 #ifdef SIGKILL
936 case SIGKILL: return "SIGKILL";
937 #endif
938 #ifdef SIGUSR1
939 case SIGUSR1: return "SIGUSR1";
940 #endif
941 case SIGSEGV: return "SIGSEGV";
942 #ifdef SIGUSR2
943 case SIGUSR2: return "SIGUSR2";
944 #endif
945 #ifdef SIGPIPE
946 case SIGPIPE: return "SIGPIPE";
947 #endif
948 #ifdef SIGALRM
949 case SIGALRM: return "SIGALRM";
950 #endif
951 case SIGTERM: return "SIGTERM";
952 #ifdef SIGSTKFLT
953 case SIGSTKFLT: return "SIGSTKFLT";
954 #endif
955 #ifdef SIGCHLD
956 case SIGCHLD: return "SIGCHLD";
957 #endif
958 #ifdef SIGCONT
959 case SIGCONT: return "SIGCONT";
960 #endif
961 #ifdef SIGSTOP
962 case SIGSTOP: return "SIGSTOP";
963 #endif
964 #ifdef SIGTSTP
965 case SIGTSTP: return "SIGTSTP";
966 #endif
967 #ifdef SIGTTIN
968 case SIGTTIN: return "SIGTTIN";
969 #endif
970 #ifdef SIGTTOU
971 case SIGTTOU: return "SIGTTOU";
972 #endif
973 #ifdef SIGURG
974 case SIGURG: return "SIGURG";
975 #endif
976 #ifdef SIGXCPU
977 case SIGXCPU: return "SIGXCPU";
978 #endif
979 #ifdef SIGXFSZ
980 case SIGXFSZ: return "SIGXFSZ";
981 #endif
982 #ifdef SIGVTALRM
983 case SIGVTALRM: return "SIGVTALRM";
984 #endif
985 #ifdef SIGPROF
986 case SIGPROF: return "SIGPROF";
987 #endif
988 #ifdef SIGWINCH
989 case SIGWINCH: return "SIGWINCH";
990 #endif
991 #ifdef SIGIO
992 case SIGIO: return "SIGIO";
993 #endif
994 #ifdef SIGPWR
995 case SIGPWR: return "SIGPWR";
996 #endif
997 #ifdef SIGSYS
998 case SIGSYS: return "SIGSYS";
999 #endif
1002 #ifdef SIGRTMIN
1003 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
1004 pa_xfree(PA_STATIC_TLS_GET(signame));
1005 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
1006 PA_STATIC_TLS_SET(signame, t);
1007 return t;
1009 #endif
1011 #endif
1013 fail:
1015 pa_xfree(PA_STATIC_TLS_GET(signame));
1016 t = pa_sprintf_malloc("SIG%i", sig);
1017 PA_STATIC_TLS_SET(signame, t);
1018 return t;
1021 #ifdef HAVE_GRP_H
1023 /* Check whether the specified GID and the group name match */
1024 static int is_group(gid_t gid, const char *name) {
1025 struct group *group = NULL;
1026 int r = -1;
1028 errno = 0;
1029 if (!(group = pa_getgrgid_malloc(gid)))
1031 if (!errno)
1032 errno = ENOENT;
1034 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1036 goto finish;
1039 r = strcmp(name, group->gr_name) == 0;
1041 finish:
1042 pa_getgrgid_free(group);
1044 return r;
1047 /* Check the current user is member of the specified group */
1048 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1049 GETGROUPS_T *gids, tgid;
1050 long n = sysconf(_SC_NGROUPS_MAX);
1051 int r = -1, i, k;
1053 pa_assert(n > 0);
1055 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1057 if ((n = getgroups((int) n, gids)) < 0) {
1058 pa_log("getgroups(): %s", pa_cstrerror(errno));
1059 goto finish;
1062 for (i = 0; i < n; i++) {
1064 if ((k = is_group(gids[i], name)) < 0)
1065 goto finish;
1066 else if (k > 0) {
1067 *gid = gids[i];
1068 r = 1;
1069 goto finish;
1073 if ((k = is_group(tgid = getgid(), name)) < 0)
1074 goto finish;
1075 else if (k > 0) {
1076 *gid = tgid;
1077 r = 1;
1078 goto finish;
1081 r = 0;
1083 finish:
1085 pa_xfree(gids);
1086 return r;
1089 /* Check whether the specifc user id is a member of the specified group */
1090 int pa_uid_in_group(uid_t uid, const char *name) {
1091 struct group *group = NULL;
1092 char **i;
1093 int r = -1;
1095 errno = 0;
1096 if (!(group = pa_getgrnam_malloc(name)))
1098 if (!errno)
1099 errno = ENOENT;
1100 goto finish;
1103 r = 0;
1104 for (i = group->gr_mem; *i; i++) {
1105 struct passwd *pw = NULL;
1107 errno = 0;
1108 if (!(pw = pa_getpwnam_malloc(*i)))
1109 continue;
1111 if (pw->pw_uid == uid)
1112 r = 1;
1114 pa_getpwnam_free(pw);
1116 if (r == 1)
1117 break;
1120 finish:
1121 pa_getgrnam_free(group);
1123 return r;
1126 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1127 gid_t pa_get_gid_of_group(const char *name) {
1128 gid_t ret = (gid_t) -1;
1129 struct group *gr = NULL;
1131 errno = 0;
1132 if (!(gr = pa_getgrnam_malloc(name)))
1134 if (!errno)
1135 errno = ENOENT;
1136 goto finish;
1139 ret = gr->gr_gid;
1141 finish:
1142 pa_getgrnam_free(gr);
1143 return ret;
1146 int pa_check_in_group(gid_t g) {
1147 gid_t gids[NGROUPS_MAX];
1148 int r;
1150 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1151 return -1;
1153 for (; r > 0; r--)
1154 if (gids[r-1] == g)
1155 return 1;
1157 return 0;
1160 #else /* HAVE_GRP_H */
1162 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1163 errno = ENOSUP;
1164 return -1;
1168 int pa_uid_in_group(uid_t uid, const char *name) {
1169 errno = ENOSUP;
1170 return -1;
1173 gid_t pa_get_gid_of_group(const char *name) {
1174 errno = ENOSUP;
1175 return (gid_t) -1;
1178 int pa_check_in_group(gid_t g) {
1179 errno = ENOSUP;
1180 return -1;
1183 #endif
1185 /* Lock or unlock a file entirely.
1186 (advisory on UNIX, mandatory on Windows) */
1187 int pa_lock_fd(int fd, int b) {
1188 #ifdef F_SETLKW
1189 struct flock f_lock;
1191 /* Try a R/W lock first */
1193 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1194 f_lock.l_whence = SEEK_SET;
1195 f_lock.l_start = 0;
1196 f_lock.l_len = 0;
1198 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1199 return 0;
1201 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1202 if (b && errno == EBADF) {
1203 f_lock.l_type = F_RDLCK;
1204 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1205 return 0;
1208 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1209 #endif
1211 #ifdef OS_IS_WIN32
1212 HANDLE h = (HANDLE)_get_osfhandle(fd);
1214 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1215 return 0;
1216 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1217 return 0;
1219 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1221 /* FIXME: Needs to set errno! */
1222 #endif
1224 return -1;
1227 /* Remove trailing newlines from a string */
1228 char* pa_strip_nl(char *s) {
1229 pa_assert(s);
1231 s[strcspn(s, NEWLINE)] = 0;
1232 return s;
1235 char *pa_strip(char *s) {
1236 char *e, *l = NULL;
1238 /* Drops trailing whitespace. Modifies the string in
1239 * place. Returns pointer to first non-space character */
1241 s += strspn(s, WHITESPACE);
1243 for (e = s; *e; e++)
1244 if (!strchr(WHITESPACE, *e))
1245 l = e;
1247 if (l)
1248 *(l+1) = 0;
1249 else
1250 *s = 0;
1252 return s;
1255 /* Create a temporary lock file and lock it. */
1256 int pa_lock_lockfile(const char *fn) {
1257 int fd;
1258 pa_assert(fn);
1260 for (;;) {
1261 struct stat st;
1263 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1264 #ifdef O_NOFOLLOW
1265 |O_NOFOLLOW
1266 #endif
1267 , S_IRUSR|S_IWUSR)) < 0) {
1268 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1269 goto fail;
1272 if (pa_lock_fd(fd, 1) < 0) {
1273 pa_log_warn("Failed to lock file '%s'.", fn);
1274 goto fail;
1277 if (fstat(fd, &st) < 0) {
1278 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1279 goto fail;
1282 /* Check whether the file has been removed meanwhile. When yes,
1283 * restart this loop, otherwise, we're done */
1284 if (st.st_nlink >= 1)
1285 break;
1287 if (pa_lock_fd(fd, 0) < 0) {
1288 pa_log_warn("Failed to unlock file '%s'.", fn);
1289 goto fail;
1292 if (pa_close(fd) < 0) {
1293 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1294 fd = -1;
1295 goto fail;
1299 return fd;
1301 fail:
1303 if (fd >= 0) {
1304 int saved_errno = errno;
1305 pa_close(fd);
1306 errno = saved_errno;
1309 return -1;
1312 /* Unlock a temporary lcok file */
1313 int pa_unlock_lockfile(const char *fn, int fd) {
1314 int r = 0;
1315 pa_assert(fd >= 0);
1317 if (fn) {
1318 if (unlink(fn) < 0) {
1319 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1320 r = -1;
1324 if (pa_lock_fd(fd, 0) < 0) {
1325 pa_log_warn("Failed to unlock file '%s'.", fn);
1326 r = -1;
1329 if (pa_close(fd) < 0) {
1330 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1331 r = -1;
1334 return r;
1337 static char *get_pulse_home(void) {
1338 char *h;
1339 struct stat st;
1340 char *ret = NULL;
1342 if (!(h = pa_get_home_dir_malloc())) {
1343 pa_log_error("Failed to get home directory.");
1344 return NULL;
1347 if (stat(h, &st) < 0) {
1348 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1349 goto finish;
1352 #ifdef HAVE_GETUID
1353 if (st.st_uid != getuid()) {
1354 pa_log_error("Home directory %s not ours.", h);
1355 errno = EACCES;
1356 goto finish;
1358 #endif
1360 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1362 finish:
1363 pa_xfree(h);
1365 return ret;
1368 char *pa_get_state_dir(void) {
1369 char *d;
1371 /* The state directory shall contain dynamic data that should be
1372 * kept across reboots, and is private to this user */
1374 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1375 if (!(d = get_pulse_home()))
1376 return NULL;
1378 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1379 * dir then this will break. */
1381 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1382 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1383 pa_xfree(d);
1384 return NULL;
1387 return d;
1390 char *pa_get_home_dir_malloc(void) {
1391 char *homedir;
1392 size_t allocated = 128;
1394 for (;;) {
1395 homedir = pa_xmalloc(allocated);
1397 if (!pa_get_home_dir(homedir, allocated)) {
1398 pa_xfree(homedir);
1399 return NULL;
1402 if (strlen(homedir) < allocated - 1)
1403 break;
1405 pa_xfree(homedir);
1406 allocated *= 2;
1409 return homedir;
1412 char *pa_get_binary_name_malloc(void) {
1413 char *t;
1414 size_t allocated = 128;
1416 for (;;) {
1417 t = pa_xmalloc(allocated);
1419 if (!pa_get_binary_name(t, allocated)) {
1420 pa_xfree(t);
1421 return NULL;
1424 if (strlen(t) < allocated - 1)
1425 break;
1427 pa_xfree(t);
1428 allocated *= 2;
1431 return t;
1434 static char* make_random_dir(mode_t m) {
1435 static const char table[] =
1436 "abcdefghijklmnopqrstuvwxyz"
1437 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1438 "0123456789";
1440 char *fn;
1441 size_t pathlen;
1443 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1444 pathlen = strlen(fn);
1446 for (;;) {
1447 size_t i;
1448 int r;
1449 mode_t u;
1450 int saved_errno;
1452 for (i = pathlen - 12; i < pathlen; i++)
1453 fn[i] = table[rand() % (sizeof(table)-1)];
1455 u = umask((~m) & 0777);
1456 #ifndef OS_IS_WIN32
1457 r = mkdir(fn, m);
1458 #else
1459 r = mkdir(fn);
1460 #endif
1462 saved_errno = errno;
1463 umask(u);
1464 errno = saved_errno;
1466 if (r >= 0)
1467 return fn;
1469 if (errno != EEXIST) {
1470 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1471 pa_xfree(fn);
1472 return NULL;
1477 static int make_random_dir_and_link(mode_t m, const char *k) {
1478 char *p;
1480 if (!(p = make_random_dir(m)))
1481 return -1;
1483 #ifdef HAVE_SYMLINK
1484 if (symlink(p, k) < 0) {
1485 int saved_errno = errno;
1487 if (errno != EEXIST)
1488 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1490 rmdir(p);
1491 pa_xfree(p);
1493 errno = saved_errno;
1494 return -1;
1496 #endif
1498 pa_xfree(p);
1499 return 0;
1502 char *pa_get_runtime_dir(void) {
1503 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1504 struct stat st;
1505 mode_t m;
1507 /* The runtime directory shall contain dynamic data that needs NOT
1508 * to be kept accross reboots and is usuallly private to the user,
1509 * except in system mode, where it might be accessible by other
1510 * users, too. Since we need POSIX locking and UNIX sockets in
1511 * this directory, we link it to a random subdir in /tmp, if it
1512 * was not explicitly configured. */
1514 m = pa_in_system_mode() ? 0755U : 0700U;
1516 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1518 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1519 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1520 goto fail;
1523 return pa_xstrdup(d);
1526 if (!(d = get_pulse_home()))
1527 goto fail;
1529 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1530 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1531 pa_xfree(d);
1532 goto fail;
1535 if (!(mid = pa_machine_id())) {
1536 pa_xfree(d);
1537 goto fail;
1540 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1541 pa_xfree(d);
1542 pa_xfree(mid);
1544 for (;;) {
1545 /* OK, first let's check if the "runtime" symlink is already
1546 * existant */
1548 if (!(p = pa_readlink(k))) {
1550 if (errno != ENOENT) {
1551 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1552 goto fail;
1555 /* Hmm, so the runtime directory didn't exist yet, so let's
1556 * create one in /tmp and symlink that to it */
1558 if (make_random_dir_and_link(0700, k) < 0) {
1560 /* Mhmm, maybe another process was quicker than us,
1561 * let's check if that was valid */
1562 if (errno == EEXIST)
1563 continue;
1565 goto fail;
1568 return k;
1571 /* Make sure that this actually makes sense */
1572 if (!pa_is_path_absolute(p)) {
1573 pa_log_error("Path %s in link %s is not absolute.", p, k);
1574 errno = ENOENT;
1575 goto fail;
1578 /* Hmm, so this symlink is still around, make sure nobody fools
1579 * us */
1581 #ifdef HAVE_LSTAT
1582 if (lstat(p, &st) < 0) {
1584 if (errno != ENOENT) {
1585 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1586 goto fail;
1589 } else {
1591 if (S_ISDIR(st.st_mode) &&
1592 (st.st_uid == getuid()) &&
1593 ((st.st_mode & 0777) == 0700)) {
1595 pa_xfree(p);
1596 return k;
1599 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1601 #endif
1603 pa_xfree(p);
1604 p = NULL;
1606 /* Hmm, so the link points to some nonexisting or invalid
1607 * dir. Let's replace it by a new link. We first create a
1608 * temporary link and then rename that to allow concurrent
1609 * execution of this function. */
1611 t = pa_sprintf_malloc("%s.tmp", k);
1613 if (make_random_dir_and_link(0700, t) < 0) {
1615 if (errno != EEXIST) {
1616 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1617 goto fail;
1620 pa_xfree(t);
1621 t = NULL;
1623 /* Hmm, someone lese was quicker then us. Let's give
1624 * him some time to finish, and retry. */
1625 pa_msleep(10);
1626 continue;
1629 /* OK, we succeeded in creating the temporary symlink, so
1630 * let's rename it */
1631 if (rename(t, k) < 0) {
1632 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1633 goto fail;
1636 pa_xfree(t);
1637 return k;
1640 fail:
1641 pa_xfree(p);
1642 pa_xfree(k);
1643 pa_xfree(t);
1645 return NULL;
1648 /* Try to open a configuration file. If "env" is specified, open the
1649 * value of the specified environment variable. Otherwise look for a
1650 * file "local" in the home directory or a file "global" in global
1651 * file system. If "result" is non-NULL, a pointer to a newly
1652 * allocated buffer containing the used configuration file is
1653 * stored there.*/
1654 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1655 const char *fn;
1656 #ifdef OS_IS_WIN32
1657 char buf[PATH_MAX];
1659 if (!getenv(PULSE_ROOTENV))
1660 pa_set_root(NULL);
1661 #endif
1663 if (env && (fn = getenv(env))) {
1664 FILE *f;
1666 #ifdef OS_IS_WIN32
1667 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1668 /* FIXME: Needs to set errno! */
1669 return NULL;
1670 fn = buf;
1671 #endif
1673 if ((f = pa_fopen_cloexec(fn, "r"))) {
1674 if (result)
1675 *result = pa_xstrdup(fn);
1677 return f;
1680 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1681 return NULL;
1684 if (local) {
1685 const char *e;
1686 char *lfn;
1687 char *h;
1688 FILE *f;
1690 if ((e = getenv("PULSE_CONFIG_PATH")))
1691 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1692 else if ((h = pa_get_home_dir_malloc())) {
1693 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1694 pa_xfree(h);
1695 } else
1696 return NULL;
1698 #ifdef OS_IS_WIN32
1699 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1700 /* FIXME: Needs to set errno! */
1701 pa_xfree(lfn);
1702 return NULL;
1704 fn = buf;
1705 #endif
1707 if ((f = pa_fopen_cloexec(fn, "r"))) {
1708 if (result)
1709 *result = pa_xstrdup(fn);
1711 pa_xfree(lfn);
1712 return f;
1715 if (errno != ENOENT) {
1716 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1717 pa_xfree(lfn);
1718 return NULL;
1721 pa_xfree(lfn);
1724 if (global) {
1725 FILE *f;
1727 #ifdef OS_IS_WIN32
1728 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1729 /* FIXME: Needs to set errno! */
1730 return NULL;
1731 global = buf;
1732 #endif
1734 if ((f = pa_fopen_cloexec(global, "r"))) {
1736 if (result)
1737 *result = pa_xstrdup(global);
1739 return f;
1743 errno = ENOENT;
1744 return NULL;
1747 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1748 const char *fn;
1749 #ifdef OS_IS_WIN32
1750 char buf[PATH_MAX];
1752 if (!getenv(PULSE_ROOTENV))
1753 pa_set_root(NULL);
1754 #endif
1756 if (env && (fn = getenv(env))) {
1758 #ifdef OS_IS_WIN32
1759 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1760 /* FIXME: Needs to set errno! */
1761 return NULL;
1762 fn = buf;
1763 #endif
1765 if (access(fn, R_OK) == 0)
1766 return pa_xstrdup(fn);
1768 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1769 return NULL;
1772 if (local) {
1773 const char *e;
1774 char *lfn;
1775 char *h;
1777 if ((e = getenv("PULSE_CONFIG_PATH")))
1778 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1779 else if ((h = pa_get_home_dir_malloc())) {
1780 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1781 pa_xfree(h);
1782 } else
1783 return NULL;
1785 #ifdef OS_IS_WIN32
1786 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1787 /* FIXME: Needs to set errno! */
1788 pa_xfree(lfn);
1789 return NULL;
1791 fn = buf;
1792 #endif
1794 if (access(fn, R_OK) == 0) {
1795 char *r = pa_xstrdup(fn);
1796 pa_xfree(lfn);
1797 return r;
1800 if (errno != ENOENT) {
1801 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1802 pa_xfree(lfn);
1803 return NULL;
1806 pa_xfree(lfn);
1809 if (global) {
1810 #ifdef OS_IS_WIN32
1811 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1812 /* FIXME: Needs to set errno! */
1813 return NULL;
1814 global = buf;
1815 #endif
1817 if (access(global, R_OK) == 0)
1818 return pa_xstrdup(global);
1821 errno = ENOENT;
1823 return NULL;
1826 /* Format the specified data as a hexademical string */
1827 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1828 size_t i = 0, j = 0;
1829 const char hex[] = "0123456789abcdef";
1831 pa_assert(d);
1832 pa_assert(s);
1833 pa_assert(slength > 0);
1835 while (i < dlength && j+3 <= slength) {
1836 s[j++] = hex[*d >> 4];
1837 s[j++] = hex[*d & 0xF];
1839 d++;
1840 i++;
1843 s[j < slength ? j : slength] = 0;
1844 return s;
1847 /* Convert a hexadecimal digit to a number or -1 if invalid */
1848 static int hexc(char c) {
1849 if (c >= '0' && c <= '9')
1850 return c - '0';
1852 if (c >= 'A' && c <= 'F')
1853 return c - 'A' + 10;
1855 if (c >= 'a' && c <= 'f')
1856 return c - 'a' + 10;
1858 errno = EINVAL;
1859 return -1;
1862 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1863 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1864 size_t j = 0;
1866 pa_assert(p);
1867 pa_assert(d);
1869 while (j < dlength && *p) {
1870 int b;
1872 if ((b = hexc(*(p++))) < 0)
1873 return (size_t) -1;
1875 d[j] = (uint8_t) (b << 4);
1877 if (!*p)
1878 return (size_t) -1;
1880 if ((b = hexc(*(p++))) < 0)
1881 return (size_t) -1;
1883 d[j] |= (uint8_t) b;
1884 j++;
1887 return j;
1890 /* Returns nonzero when *s starts with *pfx */
1891 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1892 size_t l;
1894 pa_assert(s);
1895 pa_assert(pfx);
1897 l = strlen(pfx);
1899 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1902 /* Returns nonzero when *s ends with *sfx */
1903 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1904 size_t l1, l2;
1906 pa_assert(s);
1907 pa_assert(sfx);
1909 l1 = strlen(s);
1910 l2 = strlen(sfx);
1912 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1915 pa_bool_t pa_is_path_absolute(const char *fn) {
1916 pa_assert(fn);
1918 #ifndef OS_IS_WIN32
1919 return *fn == '/';
1920 #else
1921 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1922 #endif
1925 char *pa_make_path_absolute(const char *p) {
1926 char *r;
1927 char *cwd;
1929 pa_assert(p);
1931 if (pa_is_path_absolute(p))
1932 return pa_xstrdup(p);
1934 if (!(cwd = pa_getcwd()))
1935 return pa_xstrdup(p);
1937 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1938 pa_xfree(cwd);
1939 return r;
1942 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1943 * if fn is non-null and starts with / return fn
1944 * otherwise append fn to the run time path and return it */
1945 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1946 char *rtp;
1948 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1950 if (fn) {
1951 char *r;
1953 if (pa_is_path_absolute(fn))
1954 return pa_xstrdup(fn);
1956 if (!rtp)
1957 return NULL;
1959 if (prependmid) {
1960 char *mid;
1962 if (!(mid = pa_machine_id())) {
1963 pa_xfree(rtp);
1964 return NULL;
1967 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1968 pa_xfree(mid);
1969 } else
1970 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1972 pa_xfree(rtp);
1973 return r;
1974 } else
1975 return rtp;
1978 char *pa_runtime_path(const char *fn) {
1979 return get_path(fn, FALSE, TRUE);
1982 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1983 return get_path(fn, appendmid, FALSE);
1986 /* Convert the string s to a signed integer in *ret_i */
1987 int pa_atoi(const char *s, int32_t *ret_i) {
1988 char *x = NULL;
1989 long l;
1991 pa_assert(s);
1992 pa_assert(ret_i);
1994 errno = 0;
1995 l = strtol(s, &x, 0);
1997 if (!x || *x || errno) {
1998 if (!errno)
1999 errno = EINVAL;
2000 return -1;
2003 if ((int32_t) l != l) {
2004 errno = ERANGE;
2005 return -1;
2008 *ret_i = (int32_t) l;
2010 return 0;
2013 /* Convert the string s to an unsigned integer in *ret_u */
2014 int pa_atou(const char *s, uint32_t *ret_u) {
2015 char *x = NULL;
2016 unsigned long l;
2018 pa_assert(s);
2019 pa_assert(ret_u);
2021 errno = 0;
2022 l = strtoul(s, &x, 0);
2024 if (!x || *x || errno) {
2025 if (!errno)
2026 errno = EINVAL;
2027 return -1;
2030 if ((uint32_t) l != l) {
2031 errno = ERANGE;
2032 return -1;
2035 *ret_u = (uint32_t) l;
2037 return 0;
2040 #ifdef HAVE_STRTOF_L
2041 static locale_t c_locale = NULL;
2043 static void c_locale_destroy(void) {
2044 freelocale(c_locale);
2046 #endif
2048 int pa_atod(const char *s, double *ret_d) {
2049 char *x = NULL;
2050 double f;
2052 pa_assert(s);
2053 pa_assert(ret_d);
2055 /* This should be locale independent */
2057 #ifdef HAVE_STRTOF_L
2059 PA_ONCE_BEGIN {
2061 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2062 atexit(c_locale_destroy);
2064 } PA_ONCE_END;
2066 if (c_locale) {
2067 errno = 0;
2068 f = strtod_l(s, &x, c_locale);
2069 } else
2070 #endif
2072 errno = 0;
2073 f = strtod(s, &x);
2076 if (!x || *x || errno) {
2077 if (!errno)
2078 errno = EINVAL;
2079 return -1;
2082 *ret_d = f;
2084 return 0;
2087 /* Same as snprintf, but guarantees NUL-termination on every platform */
2088 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2089 size_t ret;
2090 va_list ap;
2092 pa_assert(str);
2093 pa_assert(size > 0);
2094 pa_assert(format);
2096 va_start(ap, format);
2097 ret = pa_vsnprintf(str, size, format, ap);
2098 va_end(ap);
2100 return ret;
2103 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2104 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2105 int ret;
2107 pa_assert(str);
2108 pa_assert(size > 0);
2109 pa_assert(format);
2111 ret = vsnprintf(str, size, format, ap);
2113 str[size-1] = 0;
2115 if (ret < 0)
2116 return strlen(str);
2118 if ((size_t) ret > size-1)
2119 return size-1;
2121 return (size_t) ret;
2124 /* Truncate the specified string, but guarantee that the string
2125 * returned still validates as UTF8 */
2126 char *pa_truncate_utf8(char *c, size_t l) {
2127 pa_assert(c);
2128 pa_assert(pa_utf8_valid(c));
2130 if (strlen(c) <= l)
2131 return c;
2133 c[l] = 0;
2135 while (l > 0 && !pa_utf8_valid(c))
2136 c[--l] = 0;
2138 return c;
2141 char *pa_getcwd(void) {
2142 size_t l = 128;
2144 for (;;) {
2145 char *p = pa_xmalloc(l);
2146 if (getcwd(p, l))
2147 return p;
2149 if (errno != ERANGE)
2150 return NULL;
2152 pa_xfree(p);
2153 l *= 2;
2157 void *pa_will_need(const void *p, size_t l) {
2158 #ifdef RLIMIT_MEMLOCK
2159 struct rlimit rlim;
2160 #endif
2161 const void *a;
2162 size_t size;
2163 int r;
2164 size_t bs;
2166 pa_assert(p);
2167 pa_assert(l > 0);
2169 a = PA_PAGE_ALIGN_PTR(p);
2170 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2172 #ifdef HAVE_POSIX_MADVISE
2173 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2174 pa_log_debug("posix_madvise() worked fine!");
2175 return (void*) p;
2177 #endif
2179 /* Most likely the memory was not mmap()ed from a file and thus
2180 * madvise() didn't work, so let's misuse mlock() do page this
2181 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2182 * inviting, the man page of mlock() tells us: "All pages that
2183 * contain a part of the specified address range are guaranteed to
2184 * be resident in RAM when the call returns successfully." */
2186 #ifdef RLIMIT_MEMLOCK
2187 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2189 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2190 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));
2191 errno = EPERM;
2192 return (void*) p;
2195 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2196 #else
2197 bs = PA_PAGE_SIZE*4;
2198 #endif
2200 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2202 #ifdef HAVE_MLOCK
2203 while (size > 0 && bs > 0) {
2205 if (bs > size)
2206 bs = size;
2208 if (mlock(a, bs) < 0) {
2209 bs = PA_PAGE_ALIGN(bs / 2);
2210 continue;
2213 pa_assert_se(munlock(a, bs) == 0);
2215 a = (const uint8_t*) a + bs;
2216 size -= bs;
2218 #endif
2220 if (bs <= 0)
2221 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2222 else
2223 pa_log_debug("mlock() worked fine!");
2225 return (void*) p;
2228 void pa_close_pipe(int fds[2]) {
2229 pa_assert(fds);
2231 if (fds[0] >= 0)
2232 pa_assert_se(pa_close(fds[0]) == 0);
2234 if (fds[1] >= 0)
2235 pa_assert_se(pa_close(fds[1]) == 0);
2237 fds[0] = fds[1] = -1;
2240 char *pa_readlink(const char *p) {
2241 #ifdef HAVE_READLINK
2242 size_t l = 100;
2244 for (;;) {
2245 char *c;
2246 ssize_t n;
2248 c = pa_xmalloc(l);
2250 if ((n = readlink(p, c, l-1)) < 0) {
2251 pa_xfree(c);
2252 return NULL;
2255 if ((size_t) n < l-1) {
2256 c[n] = 0;
2257 return c;
2260 pa_xfree(c);
2261 l *= 2;
2263 #else
2264 return NULL;
2265 #endif
2268 int pa_close_all(int except_fd, ...) {
2269 va_list ap;
2270 unsigned n = 0, i;
2271 int r, *p;
2273 va_start(ap, except_fd);
2275 if (except_fd >= 0)
2276 for (n = 1; va_arg(ap, int) >= 0; n++)
2279 va_end(ap);
2281 p = pa_xnew(int, n+1);
2283 va_start(ap, except_fd);
2285 i = 0;
2286 if (except_fd >= 0) {
2287 int fd;
2288 p[i++] = except_fd;
2290 while ((fd = va_arg(ap, int)) >= 0)
2291 p[i++] = fd;
2293 p[i] = -1;
2295 va_end(ap);
2297 r = pa_close_allv(p);
2298 pa_xfree(p);
2300 return r;
2303 int pa_close_allv(const int except_fds[]) {
2304 #ifndef OS_IS_WIN32
2305 struct rlimit rl;
2306 int maxfd, fd;
2308 #ifdef __linux__
2309 int saved_errno;
2310 DIR *d;
2312 if ((d = opendir("/proc/self/fd"))) {
2314 struct dirent *de;
2316 while ((de = readdir(d))) {
2317 pa_bool_t found;
2318 long l;
2319 char *e = NULL;
2320 int i;
2322 if (de->d_name[0] == '.')
2323 continue;
2325 errno = 0;
2326 l = strtol(de->d_name, &e, 10);
2327 if (errno != 0 || !e || *e) {
2328 closedir(d);
2329 errno = EINVAL;
2330 return -1;
2333 fd = (int) l;
2335 if ((long) fd != l) {
2336 closedir(d);
2337 errno = EINVAL;
2338 return -1;
2341 if (fd < 3)
2342 continue;
2344 if (fd == dirfd(d))
2345 continue;
2347 found = FALSE;
2348 for (i = 0; except_fds[i] >= 0; i++)
2349 if (except_fds[i] == fd) {
2350 found = TRUE;
2351 break;
2354 if (found)
2355 continue;
2357 if (pa_close(fd) < 0) {
2358 saved_errno = errno;
2359 closedir(d);
2360 errno = saved_errno;
2362 return -1;
2366 closedir(d);
2367 return 0;
2370 #endif
2372 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2373 maxfd = (int) rl.rlim_max;
2374 else
2375 maxfd = sysconf(_SC_OPEN_MAX);
2377 for (fd = 3; fd < maxfd; fd++) {
2378 int i;
2379 pa_bool_t found;
2381 found = FALSE;
2382 for (i = 0; except_fds[i] >= 0; i++)
2383 if (except_fds[i] == fd) {
2384 found = TRUE;
2385 break;
2388 if (found)
2389 continue;
2391 if (pa_close(fd) < 0 && errno != EBADF)
2392 return -1;
2394 #endif /* !OS_IS_WIN32 */
2396 return 0;
2399 int pa_unblock_sigs(int except, ...) {
2400 va_list ap;
2401 unsigned n = 0, i;
2402 int r, *p;
2404 va_start(ap, except);
2406 if (except >= 1)
2407 for (n = 1; va_arg(ap, int) >= 0; n++)
2410 va_end(ap);
2412 p = pa_xnew(int, n+1);
2414 va_start(ap, except);
2416 i = 0;
2417 if (except >= 1) {
2418 int sig;
2419 p[i++] = except;
2421 while ((sig = va_arg(ap, int)) >= 0)
2422 p[i++] = sig;
2424 p[i] = -1;
2426 va_end(ap);
2428 r = pa_unblock_sigsv(p);
2429 pa_xfree(p);
2431 return r;
2434 int pa_unblock_sigsv(const int except[]) {
2435 #ifndef OS_IS_WIN32
2436 int i;
2437 sigset_t ss;
2439 if (sigemptyset(&ss) < 0)
2440 return -1;
2442 for (i = 0; except[i] > 0; i++)
2443 if (sigaddset(&ss, except[i]) < 0)
2444 return -1;
2446 return sigprocmask(SIG_SETMASK, &ss, NULL);
2447 #else
2448 return 0;
2449 #endif
2452 int pa_reset_sigs(int except, ...) {
2453 va_list ap;
2454 unsigned n = 0, i;
2455 int *p, r;
2457 va_start(ap, except);
2459 if (except >= 1)
2460 for (n = 1; va_arg(ap, int) >= 0; n++)
2463 va_end(ap);
2465 p = pa_xnew(int, n+1);
2467 va_start(ap, except);
2469 i = 0;
2470 if (except >= 1) {
2471 int sig;
2472 p[i++] = except;
2474 while ((sig = va_arg(ap, int)) >= 0)
2475 p[i++] = sig;
2477 p[i] = -1;
2479 va_end(ap);
2481 r = pa_reset_sigsv(p);
2482 pa_xfree(p);
2484 return r;
2487 int pa_reset_sigsv(const int except[]) {
2488 #ifndef OS_IS_WIN32
2489 int sig;
2491 for (sig = 1; sig < NSIG; sig++) {
2492 pa_bool_t reset = TRUE;
2494 switch (sig) {
2495 case SIGKILL:
2496 case SIGSTOP:
2497 reset = FALSE;
2498 break;
2500 default: {
2501 int i;
2503 for (i = 0; except[i] > 0; i++) {
2504 if (sig == except[i]) {
2505 reset = FALSE;
2506 break;
2512 if (reset) {
2513 struct sigaction sa;
2515 memset(&sa, 0, sizeof(sa));
2516 sa.sa_handler = SIG_DFL;
2518 /* On Linux the first two RT signals are reserved by
2519 * glibc, and sigaction() will return EINVAL for them. */
2520 if ((sigaction(sig, &sa, NULL) < 0))
2521 if (errno != EINVAL)
2522 return -1;
2525 #endif
2527 return 0;
2530 void pa_set_env(const char *key, const char *value) {
2531 pa_assert(key);
2532 pa_assert(value);
2534 /* This is not thread-safe */
2536 setenv(key, value, 1);
2539 void pa_set_env_and_record(const char *key, const char *value) {
2540 pa_assert(key);
2541 pa_assert(value);
2543 /* This is not thread-safe */
2545 pa_set_env(key, value);
2546 recorded_env = pa_strlist_prepend(recorded_env, key);
2549 void pa_unset_env_recorded(void) {
2551 /* This is not thread-safe */
2553 for (;;) {
2554 char *s;
2556 recorded_env = pa_strlist_pop(recorded_env, &s);
2558 if (!s)
2559 break;
2561 unsetenv(s);
2562 pa_xfree(s);
2566 pa_bool_t pa_in_system_mode(void) {
2567 const char *e;
2569 if (!(e = getenv("PULSE_SYSTEM")))
2570 return FALSE;
2572 return !!atoi(e);
2575 char *pa_get_user_name_malloc(void) {
2576 ssize_t k;
2577 char *u;
2579 #ifdef _SC_LOGIN_NAME_MAX
2580 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2582 if (k <= 0)
2583 #endif
2584 k = 32;
2586 u = pa_xnew(char, k+1);
2588 if (!(pa_get_user_name(u, k))) {
2589 pa_xfree(u);
2590 return NULL;
2593 return u;
2596 char *pa_get_host_name_malloc(void) {
2597 size_t l;
2599 l = 100;
2600 for (;;) {
2601 char *c;
2603 c = pa_xmalloc(l);
2605 if (!pa_get_host_name(c, l)) {
2607 if (errno != EINVAL && errno != ENAMETOOLONG)
2608 break;
2610 } else if (strlen(c) < l-1) {
2611 char *u;
2613 if (*c == 0) {
2614 pa_xfree(c);
2615 break;
2618 u = pa_utf8_filter(c);
2619 pa_xfree(c);
2620 return u;
2623 /* Hmm, the hostname is as long the space we offered the
2624 * function, we cannot know if it fully fit in, so let's play
2625 * safe and retry. */
2627 pa_xfree(c);
2628 l *= 2;
2631 return NULL;
2634 char *pa_machine_id(void) {
2635 FILE *f;
2636 char *h;
2638 /* The returned value is supposed be some kind of ascii identifier
2639 * that is unique and stable across reboots. */
2641 /* First we try the D-Bus UUID, which is the best option we have,
2642 * since it fits perfectly our needs and is not as volatile as the
2643 * hostname which might be set from dhcp. */
2645 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
2646 char ln[34] = "", *r;
2648 r = fgets(ln, sizeof(ln)-1, f);
2649 fclose(f);
2651 pa_strip_nl(ln);
2653 if (r && ln[0])
2654 return pa_utf8_filter(ln);
2657 if ((h = pa_get_host_name_malloc()))
2658 return h;
2660 #ifndef OS_IS_WIN32
2661 /* If no hostname was set we use the POSIX hostid. It's usually
2662 * the IPv4 address. Might not be that stable. */
2663 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2664 #else
2665 return NULL;
2666 #endif
2669 char *pa_session_id(void) {
2670 const char *e;
2672 if (!(e = getenv("XDG_SESSION_COOKIE")))
2673 return NULL;
2675 return pa_utf8_filter(e);
2678 char *pa_uname_string(void) {
2679 struct utsname u;
2681 pa_assert_se(uname(&u) >= 0);
2683 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2686 #ifdef HAVE_VALGRIND_MEMCHECK_H
2687 pa_bool_t pa_in_valgrind(void) {
2688 static int b = 0;
2690 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2691 * here instead of really checking whether we run in valgrind or
2692 * not. */
2694 if (b < 1)
2695 b = getenv("VALGRIND") ? 2 : 1;
2697 return b > 1;
2699 #endif
2701 unsigned pa_gcd(unsigned a, unsigned b) {
2703 while (b > 0) {
2704 unsigned t = b;
2705 b = a % b;
2706 a = t;
2709 return a;
2712 void pa_reduce(unsigned *num, unsigned *den) {
2714 unsigned gcd = pa_gcd(*num, *den);
2716 if (gcd <= 0)
2717 return;
2719 *num /= gcd;
2720 *den /= gcd;
2722 pa_assert(pa_gcd(*num, *den) == 1);
2725 unsigned pa_ncpus(void) {
2726 long ncpus;
2728 #ifdef _SC_NPROCESSORS_CONF
2729 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2730 #else
2731 ncpus = 1;
2732 #endif
2734 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2737 char *pa_replace(const char*s, const char*a, const char *b) {
2738 pa_strbuf *sb;
2739 size_t an;
2741 pa_assert(s);
2742 pa_assert(a);
2743 pa_assert(b);
2745 an = strlen(a);
2746 sb = pa_strbuf_new();
2748 for (;;) {
2749 const char *p;
2751 if (!(p = strstr(s, a)))
2752 break;
2754 pa_strbuf_putsn(sb, s, p-s);
2755 pa_strbuf_puts(sb, b);
2756 s = p + an;
2759 pa_strbuf_puts(sb, s);
2761 return pa_strbuf_tostring_free(sb);
2764 char *pa_escape(const char *p, const char *chars) {
2765 const char *s;
2766 const char *c;
2767 pa_strbuf *buf = pa_strbuf_new();
2769 for (s = p; *s; ++s) {
2770 if (*s == '\\')
2771 pa_strbuf_putc(buf, '\\');
2772 else if (chars) {
2773 for (c = chars; *c; ++c) {
2774 if (*s == *c) {
2775 pa_strbuf_putc(buf, '\\');
2776 break;
2780 pa_strbuf_putc(buf, *s);
2783 return pa_strbuf_tostring_free(buf);
2786 char *pa_unescape(char *p) {
2787 char *s, *d;
2788 pa_bool_t escaped = FALSE;
2790 for (s = p, d = p; *s; s++) {
2791 if (!escaped && *s == '\\') {
2792 escaped = TRUE;
2793 continue;
2796 *(d++) = *s;
2797 escaped = FALSE;
2800 *d = 0;
2802 return p;
2805 char *pa_realpath(const char *path) {
2806 char *t;
2807 pa_assert(path);
2809 /* We want only abolsute paths */
2810 if (path[0] != '/') {
2811 errno = EINVAL;
2812 return NULL;
2815 #if defined(__GLIBC__) || defined(__APPLE__)
2817 char *r;
2819 if (!(r = realpath(path, NULL)))
2820 return NULL;
2822 /* We copy this here in case our pa_xmalloc() is not
2823 * implemented on top of libc malloc() */
2824 t = pa_xstrdup(r);
2825 pa_xfree(r);
2827 #elif defined(PATH_MAX)
2829 char *path_buf;
2830 path_buf = pa_xmalloc(PATH_MAX);
2832 if (!(t = realpath(path, path_buf))) {
2833 pa_xfree(path_buf);
2834 return NULL;
2837 #else
2838 #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."
2839 #endif
2841 return t;
2844 void pa_disable_sigpipe(void) {
2846 #ifdef SIGPIPE
2847 struct sigaction sa;
2849 pa_zero(sa);
2851 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2852 pa_log("sigaction(): %s", pa_cstrerror(errno));
2853 return;
2856 sa.sa_handler = SIG_IGN;
2858 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2859 pa_log("sigaction(): %s", pa_cstrerror(errno));
2860 return;
2862 #endif
2865 void pa_xfreev(void**a) {
2866 void **p;
2868 if (!a)
2869 return;
2871 for (p = a; *p; p++)
2872 pa_xfree(*p);
2874 pa_xfree(a);
2877 char **pa_split_spaces_strv(const char *s) {
2878 char **t, *e;
2879 unsigned i = 0, n = 8;
2880 const char *state = NULL;
2882 t = pa_xnew(char*, n);
2883 while ((e = pa_split_spaces(s, &state))) {
2884 t[i++] = e;
2886 if (i >= n) {
2887 n *= 2;
2888 t = pa_xrenew(char*, t, n);
2892 if (i <= 0) {
2893 pa_xfree(t);
2894 return NULL;
2897 t[i] = NULL;
2898 return t;
2901 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2902 pa_assert(path);
2904 if (pa_is_path_absolute(path))
2905 return pa_xstrdup(path);
2907 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2910 size_t pa_pipe_buf(int fd) {
2912 #ifdef _PC_PIPE_BUF
2913 long n;
2915 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2916 return (size_t) n;
2917 #endif
2919 #ifdef PIPE_BUF
2920 return PIPE_BUF;
2921 #else
2922 return 4096;
2923 #endif
2926 void pa_reset_personality(void) {
2928 #ifdef __linux__
2929 if (personality(PER_LINUX) < 0)
2930 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2931 #endif
2935 #if defined(__linux__) && !defined(__OPTIMIZE__)
2937 pa_bool_t pa_run_from_build_tree(void) {
2938 char *rp;
2939 pa_bool_t b = FALSE;
2941 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2942 * or not. */
2944 if ((rp = pa_readlink("/proc/self/exe"))) {
2945 b = pa_startswith(rp, PA_BUILDDIR);
2946 pa_xfree(rp);
2949 return b;
2952 #endif
2954 const char *pa_get_temp_dir(void) {
2955 const char *t;
2957 if ((t = getenv("TMPDIR")) &&
2958 pa_is_path_absolute(t))
2959 return t;
2961 if ((t = getenv("TMP")) &&
2962 pa_is_path_absolute(t))
2963 return t;
2965 if ((t = getenv("TEMP")) &&
2966 pa_is_path_absolute(t))
2967 return t;
2969 if ((t = getenv("TEMPDIR")) &&
2970 pa_is_path_absolute(t))
2971 return t;
2973 return "/tmp";
2976 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
2977 int fd;
2979 #ifdef O_NOCTTY
2980 flags |= O_NOCTTY;
2981 #endif
2983 #ifdef O_CLOEXEC
2984 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
2985 goto finish;
2987 if (errno != EINVAL)
2988 return fd;
2989 #endif
2991 if ((fd = open(fn, flags, mode)) < 0)
2992 return fd;
2994 finish:
2995 /* Some implementations might simply ignore O_CLOEXEC if it is not
2996 * understood, make sure FD_CLOEXEC is enabled anyway */
2998 pa_make_fd_cloexec(fd);
2999 return fd;
3002 int pa_socket_cloexec(int domain, int type, int protocol) {
3003 int fd;
3005 #ifdef SOCK_CLOEXEC
3006 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3007 goto finish;
3009 if (errno != EINVAL)
3010 return fd;
3011 #endif
3013 if ((fd = socket(domain, type, protocol)) < 0)
3014 return fd;
3016 finish:
3017 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3018 * not understood, make sure FD_CLOEXEC is enabled anyway */
3020 pa_make_fd_cloexec(fd);
3021 return fd;
3024 int pa_pipe_cloexec(int pipefd[2]) {
3025 int r;
3027 #ifdef HAVE_PIPE2
3028 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3029 goto finish;
3031 if (errno != EINVAL && errno != ENOSYS)
3032 return r;
3034 #endif
3036 if ((r = pipe(pipefd)) < 0)
3037 return r;
3039 finish:
3040 pa_make_fd_cloexec(pipefd[0]);
3041 pa_make_fd_cloexec(pipefd[1]);
3043 return 0;
3046 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3047 int fd;
3049 #ifdef HAVE_ACCEPT4
3050 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3051 goto finish;
3053 if (errno != EINVAL && errno != ENOSYS)
3054 return fd;
3056 #endif
3058 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3059 return fd;
3061 finish:
3062 pa_make_fd_cloexec(fd);
3063 return fd;
3066 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3067 FILE *f;
3068 char *m;
3070 m = pa_sprintf_malloc("%se", mode);
3072 errno = 0;
3073 if ((f = fopen(path, m))) {
3074 pa_xfree(m);
3075 goto finish;
3078 pa_xfree(m);
3080 if (errno != EINVAL)
3081 return NULL;
3083 if (!(f = fopen(path, mode)))
3084 return NULL;
3086 finish:
3087 pa_make_fd_cloexec(fileno(f));
3088 return f;
3091 void pa_nullify_stdfds(void) {
3093 #ifndef OS_IS_WIN32
3094 pa_close(STDIN_FILENO);
3095 pa_close(STDOUT_FILENO);
3096 pa_close(STDERR_FILENO);
3098 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3099 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3100 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3101 #else
3102 FreeConsole();
3103 #endif
3107 char *pa_read_line_from_file(const char *fn) {
3108 FILE *f;
3109 char ln[256] = "", *r;
3111 if (!(f = pa_fopen_cloexec(fn, "r")))
3112 return NULL;
3114 r = fgets(ln, sizeof(ln)-1, f);
3115 fclose(f);
3117 if (!r) {
3118 errno = EIO;
3119 return NULL;
3122 pa_strip_nl(ln);
3123 return pa_xstrdup(ln);
3126 pa_bool_t pa_running_in_vm(void) {
3128 #if defined(__i386__) || defined(__x86_64__)
3130 /* Both CPUID and DMI are x86 specific interfaces... */
3132 uint32_t eax = 0x40000000;
3133 union {
3134 uint32_t sig32[3];
3135 char text[13];
3136 } sig;
3138 #ifdef __linux__
3139 const char *const dmi_vendors[] = {
3140 "/sys/class/dmi/id/sys_vendor",
3141 "/sys/class/dmi/id/board_vendor",
3142 "/sys/class/dmi/id/bios_vendor"
3145 unsigned i;
3147 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3148 char *s;
3150 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3152 if (pa_startswith(s, "QEMU") ||
3153 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3154 pa_startswith(s, "VMware") ||
3155 pa_startswith(s, "VMW") ||
3156 pa_startswith(s, "Microsoft Corporation") ||
3157 pa_startswith(s, "innotek GmbH") ||
3158 pa_startswith(s, "Xen")) {
3160 pa_xfree(s);
3161 return TRUE;
3164 pa_xfree(s);
3168 #endif
3170 /* http://lwn.net/Articles/301888/ */
3171 pa_zero(sig);
3173 __asm__ __volatile__ (
3174 /* ebx/rbx is being used for PIC! */
3175 " push %%"PA_REG_b" \n\t"
3176 " cpuid \n\t"
3177 " mov %%ebx, %1 \n\t"
3178 " pop %%"PA_REG_b" \n\t"
3180 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3181 : "0" (eax)
3184 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3185 pa_streq(sig.text, "KVMKVMKVM") ||
3186 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3187 pa_streq(sig.text, "VMwareVMware") ||
3188 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3189 pa_streq(sig.text, "Microsoft Hv"))
3190 return TRUE;
3192 #endif
3194 return FALSE;