]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
Move compile-time checks around pa_run_from_build_tree to core-util
[pulseaudio] / src / pulsecore / core-util.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
7
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.
12
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.
17
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 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
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>
41
42 #ifdef HAVE_LANGINFO_H
43 #include <langinfo.h>
44 #endif
45
46 #ifdef HAVE_UNAME
47 #include <sys/utsname.h>
48 #endif
49
50 #if defined(HAVE_REGEX_H)
51 #include <regex.h>
52 #elif defined(HAVE_PCREPOSIX_H)
53 #include <pcreposix.h>
54 #endif
55
56 #ifdef HAVE_STRTOF_L
57 #include <locale.h>
58 #endif
59
60 #ifdef HAVE_SCHED_H
61 #include <sched.h>
62
63 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
64 #define SCHED_RESET_ON_FORK 0x40000000
65 #endif
66 #endif
67
68 #ifdef HAVE_SYS_RESOURCE_H
69 #include <sys/resource.h>
70 #endif
71
72 #ifdef HAVE_SYS_CAPABILITY_H
73 #include <sys/capability.h>
74 #endif
75
76 #ifdef HAVE_SYS_MMAN_H
77 #include <sys/mman.h>
78 #endif
79
80 #ifdef HAVE_PTHREAD
81 #include <pthread.h>
82 #endif
83
84 #ifdef HAVE_NETDB_H
85 #include <netdb.h>
86 #endif
87
88 #ifdef HAVE_WINDOWS_H
89 #include <windows.h>
90 #endif
91
92 #ifndef ENOTSUP
93 #define ENOTSUP 135
94 #endif
95
96 #ifdef HAVE_PWD_H
97 #include <pwd.h>
98 #endif
99
100 #ifdef HAVE_GRP_H
101 #include <grp.h>
102 #endif
103
104 #ifdef HAVE_LIBSAMPLERATE
105 #include <samplerate.h>
106 #endif
107
108 #ifdef __APPLE__
109 #include <xlocale.h>
110 #include <mach/mach_init.h>
111 #include <mach/thread_act.h>
112 #include <mach/thread_policy.h>
113 #include <sys/sysctl.h>
114 #endif
115
116 #ifdef HAVE_DBUS
117 #include "rtkit.h"
118 #endif
119
120 #ifdef __linux__
121 #include <sys/personality.h>
122 #endif
123
124 #include <pulse/xmalloc.h>
125 #include <pulse/util.h>
126 #include <pulse/utf8.h>
127
128 #include <pulsecore/core-error.h>
129 #include <pulsecore/socket.h>
130 #include <pulsecore/log.h>
131 #include <pulsecore/macro.h>
132 #include <pulsecore/thread.h>
133 #include <pulsecore/strbuf.h>
134 #include <pulsecore/usergroup.h>
135 #include <pulsecore/strlist.h>
136 #include <pulsecore/cpu-x86.h>
137 #include <pulsecore/pipe.h>
138
139 #include "core-util.h"
140
141 /* Not all platforms have this */
142 #ifndef MSG_NOSIGNAL
143 #define MSG_NOSIGNAL 0
144 #endif
145
146 #define NEWLINE "\r\n"
147 #define WHITESPACE "\n\r \t"
148
149 static pa_strlist *recorded_env = NULL;
150
151 #ifdef OS_IS_WIN32
152
153 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
154 char *pa_win32_get_toplevel(HANDLE handle) {
155 static char *toplevel = NULL;
156
157 if (!toplevel) {
158 char library_path[MAX_PATH];
159 char *p;
160
161 if (!GetModuleFileName(handle, library_path, MAX_PATH))
162 return NULL;
163
164 toplevel = pa_xstrdup(library_path);
165
166 p = strrchr(toplevel, PA_PATH_SEP_CHAR);
167 if (p)
168 *p = '\0';
169
170 p = strrchr(toplevel, PA_PATH_SEP_CHAR);
171 if (p && (strcmp(p + 1, "bin") == 0))
172 *p = '\0';
173 }
174
175 return toplevel;
176 }
177
178 #endif
179
180 /** Make a file descriptor nonblock. Doesn't do any error checking */
181 void pa_make_fd_nonblock(int fd) {
182
183 #ifdef O_NONBLOCK
184 int v;
185 pa_assert(fd >= 0);
186
187 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
188
189 if (!(v & O_NONBLOCK))
190 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
191
192 #elif defined(OS_IS_WIN32)
193 u_long arg = 1;
194 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
195 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
196 pa_log_warn("Only sockets can be made non-blocking!");
197 }
198 #else
199 pa_log_warn("Non-blocking I/O not supported.!");
200 #endif
201
202 }
203
204 /* Set the FD_CLOEXEC flag for a fd */
205 void pa_make_fd_cloexec(int fd) {
206
207 #ifdef FD_CLOEXEC
208 int v;
209 pa_assert(fd >= 0);
210
211 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
212
213 if (!(v & FD_CLOEXEC))
214 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
215 #endif
216
217 }
218
219 /** Creates a directory securely */
220 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
221 struct stat st;
222 int r, saved_errno, fd;
223
224 pa_assert(dir);
225
226 #ifdef OS_IS_WIN32
227 r = mkdir(dir);
228 #else
229 {
230 mode_t u;
231 u = umask((~m) & 0777);
232 r = mkdir(dir, m);
233 umask(u);
234 }
235 #endif
236
237 if (r < 0 && errno != EEXIST)
238 return -1;
239
240 #if defined(HAVE_FSTAT) && !defined(OS_IS_WIN32)
241 if ((fd = open(dir,
242 #ifdef O_CLOEXEC
243 O_CLOEXEC|
244 #endif
245 #ifdef O_NOCTTY
246 O_NOCTTY|
247 #endif
248 #ifdef O_NOFOLLOW
249 O_NOFOLLOW|
250 #endif
251 O_RDONLY)) < 0)
252 goto fail;
253
254 if (fstat(fd, &st) < 0) {
255 pa_assert_se(pa_close(fd) >= 0);
256 goto fail;
257 }
258
259 if (!S_ISDIR(st.st_mode)) {
260 pa_assert_se(pa_close(fd) >= 0);
261 errno = EEXIST;
262 goto fail;
263 }
264
265 #ifdef HAVE_FCHOWN
266 if (uid == (uid_t) -1)
267 uid = getuid();
268 if (gid == (gid_t) -1)
269 gid = getgid();
270 if (fchown(fd, uid, gid) < 0)
271 goto fail;
272 #endif
273
274 #ifdef HAVE_FCHMOD
275 (void) fchmod(fd, m);
276 #endif
277
278 pa_assert_se(pa_close(fd) >= 0);
279 #endif
280
281 #ifdef HAVE_LSTAT
282 if (lstat(dir, &st) < 0)
283 #else
284 if (stat(dir, &st) < 0)
285 #endif
286 goto fail;
287
288 #ifndef OS_IS_WIN32
289 if (!S_ISDIR(st.st_mode) ||
290 (st.st_uid != uid) ||
291 (st.st_gid != gid) ||
292 ((st.st_mode & 0777) != m)) {
293 errno = EACCES;
294 goto fail;
295 }
296 #else
297 pa_log_warn("Secure directory creation not supported on Win32.");
298 #endif
299
300 return 0;
301
302 fail:
303 saved_errno = errno;
304 rmdir(dir);
305 errno = saved_errno;
306
307 return -1;
308 }
309
310 /* Return a newly allocated sting containing the parent directory of the specified file */
311 char *pa_parent_dir(const char *fn) {
312 char *slash, *dir = pa_xstrdup(fn);
313
314 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
315 pa_xfree(dir);
316 errno = ENOENT;
317 return NULL;
318 }
319
320 *(slash-1) = 0;
321 return dir;
322 }
323
324 /* Creates a the parent directory of the specified path securely */
325 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
326 int ret = -1;
327 char *dir;
328
329 if (!(dir = pa_parent_dir(fn)))
330 goto finish;
331
332 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
333 goto finish;
334
335 ret = 0;
336
337 finish:
338 pa_xfree(dir);
339 return ret;
340 }
341
342 /** Platform independent read function. Necessary since not all
343 * systems treat all file descriptors equal. If type is
344 * non-NULL it is used to cache the type of the fd. This is
345 * useful for making sure that only a single syscall is executed per
346 * function call. The variable pointed to should be initialized to 0
347 * by the caller. */
348 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
349
350 #ifdef OS_IS_WIN32
351
352 if (!type || *type == 0) {
353 ssize_t r;
354
355 if ((r = recv(fd, buf, count, 0)) >= 0)
356 return r;
357
358 if (WSAGetLastError() != WSAENOTSOCK) {
359 errno = WSAGetLastError();
360 return r;
361 }
362
363 if (type)
364 *type = 1;
365 }
366
367 #endif
368
369 for (;;) {
370 ssize_t r;
371
372 if ((r = read(fd, buf, count)) < 0)
373 if (errno == EINTR)
374 continue;
375
376 return r;
377 }
378 }
379
380 /** Similar to pa_read(), but handles writes */
381 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
382
383 if (!type || *type == 0) {
384 ssize_t r;
385
386 for (;;) {
387 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
388
389 if (errno == EINTR)
390 continue;
391
392 break;
393 }
394
395 return r;
396 }
397
398 #ifdef OS_IS_WIN32
399 if (WSAGetLastError() != WSAENOTSOCK) {
400 errno = WSAGetLastError();
401 return r;
402 }
403 #else
404 if (errno != ENOTSOCK)
405 return r;
406 #endif
407
408 if (type)
409 *type = 1;
410 }
411
412 for (;;) {
413 ssize_t r;
414
415 if ((r = write(fd, buf, count)) < 0)
416 if (errno == EINTR)
417 continue;
418
419 return r;
420 }
421 }
422
423 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
424 * unless EOF is reached or an error occurred */
425 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
426 ssize_t ret = 0;
427 int _type;
428
429 pa_assert(fd >= 0);
430 pa_assert(data);
431 pa_assert(size);
432
433 if (!type) {
434 _type = 0;
435 type = &_type;
436 }
437
438 while (size > 0) {
439 ssize_t r;
440
441 if ((r = pa_read(fd, data, size, type)) < 0)
442 return r;
443
444 if (r == 0)
445 break;
446
447 ret += r;
448 data = (uint8_t*) data + r;
449 size -= (size_t) r;
450 }
451
452 return ret;
453 }
454
455 /** Similar to pa_loop_read(), but wraps write() */
456 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
457 ssize_t ret = 0;
458 int _type;
459
460 pa_assert(fd >= 0);
461 pa_assert(data);
462 pa_assert(size);
463
464 if (!type) {
465 _type = 0;
466 type = &_type;
467 }
468
469 while (size > 0) {
470 ssize_t r;
471
472 if ((r = pa_write(fd, data, size, type)) < 0)
473 return r;
474
475 if (r == 0)
476 break;
477
478 ret += r;
479 data = (const uint8_t*) data + r;
480 size -= (size_t) r;
481 }
482
483 return ret;
484 }
485
486 /** Platform independent read function. Necessary since not all
487 * systems treat all file descriptors equal. */
488 int pa_close(int fd) {
489
490 #ifdef OS_IS_WIN32
491 int ret;
492
493 if ((ret = closesocket(fd)) == 0)
494 return 0;
495
496 if (WSAGetLastError() != WSAENOTSOCK) {
497 errno = WSAGetLastError();
498 return ret;
499 }
500 #endif
501
502 for (;;) {
503 int r;
504
505 if ((r = close(fd)) < 0)
506 if (errno == EINTR)
507 continue;
508
509 return r;
510 }
511 }
512
513 /* Print a warning messages in case that the given signal is not
514 * blocked or trapped */
515 void pa_check_signal_is_blocked(int sig) {
516 #ifdef HAVE_SIGACTION
517 struct sigaction sa;
518 sigset_t set;
519
520 /* If POSIX threads are supported use thread-aware
521 * pthread_sigmask() function, to check if the signal is
522 * blocked. Otherwise fall back to sigprocmask() */
523
524 #ifdef HAVE_PTHREAD
525 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
526 #endif
527 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
528 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
529 return;
530 }
531 #ifdef HAVE_PTHREAD
532 }
533 #endif
534
535 if (sigismember(&set, sig))
536 return;
537
538 /* Check whether the signal is trapped */
539
540 if (sigaction(sig, NULL, &sa) < 0) {
541 pa_log("sigaction(): %s", pa_cstrerror(errno));
542 return;
543 }
544
545 if (sa.sa_handler != SIG_DFL)
546 return;
547
548 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
549 #else /* HAVE_SIGACTION */
550 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
551 #endif
552 }
553
554 /* The following function is based on an example from the GNU libc
555 * documentation. This function is similar to GNU's asprintf(). */
556 char *pa_sprintf_malloc(const char *format, ...) {
557 size_t size = 100;
558 char *c = NULL;
559
560 pa_assert(format);
561
562 for(;;) {
563 int r;
564 va_list ap;
565
566 c = pa_xrealloc(c, size);
567
568 va_start(ap, format);
569 r = vsnprintf(c, size, format, ap);
570 va_end(ap);
571
572 c[size-1] = 0;
573
574 if (r > -1 && (size_t) r < size)
575 return c;
576
577 if (r > -1) /* glibc 2.1 */
578 size = (size_t) r+1;
579 else /* glibc 2.0 */
580 size *= 2;
581 }
582 }
583
584 /* Same as the previous function, but use a va_list instead of an
585 * ellipsis */
586 char *pa_vsprintf_malloc(const char *format, va_list ap) {
587 size_t size = 100;
588 char *c = NULL;
589
590 pa_assert(format);
591
592 for(;;) {
593 int r;
594 va_list aq;
595
596 c = pa_xrealloc(c, size);
597
598 va_copy(aq, ap);
599 r = vsnprintf(c, size, format, aq);
600 va_end(aq);
601
602 c[size-1] = 0;
603
604 if (r > -1 && (size_t) r < size)
605 return c;
606
607 if (r > -1) /* glibc 2.1 */
608 size = (size_t) r+1;
609 else /* glibc 2.0 */
610 size *= 2;
611 }
612 }
613
614 /* Similar to OpenBSD's strlcpy() function */
615 char *pa_strlcpy(char *b, const char *s, size_t l) {
616 size_t k;
617
618 pa_assert(b);
619 pa_assert(s);
620 pa_assert(l > 0);
621
622 k = strlen(s);
623
624 if (k > l-1)
625 k = l-1;
626
627 memcpy(b, s, k);
628 b[k] = 0;
629
630 return b;
631 }
632
633 #ifdef _POSIX_PRIORITY_SCHEDULING
634 static int set_scheduler(int rtprio) {
635 #ifdef HAVE_SCHED_H
636 struct sched_param sp;
637 #ifdef HAVE_DBUS
638 int r;
639 DBusError error;
640 DBusConnection *bus;
641
642 dbus_error_init(&error);
643 #endif
644
645 pa_zero(sp);
646 sp.sched_priority = rtprio;
647
648 #ifdef SCHED_RESET_ON_FORK
649 if (pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, &sp) == 0) {
650 pa_log_debug("SCHED_RR|SCHED_RESET_ON_FORK worked.");
651 return 0;
652 }
653 #endif
654
655 if (pthread_setschedparam(pthread_self(), SCHED_RR, &sp) == 0) {
656 pa_log_debug("SCHED_RR worked.");
657 return 0;
658 }
659 #endif /* HAVE_SCHED_H */
660
661 #ifdef HAVE_DBUS
662 /* Try to talk to RealtimeKit */
663
664 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
665 pa_log("Failed to connect to system bus: %s\n", error.message);
666 dbus_error_free(&error);
667 errno = -EIO;
668 return -1;
669 }
670
671 /* We need to disable exit on disconnect because otherwise
672 * dbus_shutdown will kill us. See
673 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
674 dbus_connection_set_exit_on_disconnect(bus, FALSE);
675
676 r = rtkit_make_realtime(bus, 0, rtprio);
677 dbus_connection_unref(bus);
678
679 if (r >= 0) {
680 pa_log_debug("RealtimeKit worked.");
681 return 0;
682 }
683
684 errno = -r;
685 #else
686 errno = 0;
687 #endif
688
689 return -1;
690 }
691 #endif
692
693 /* Make the current thread a realtime thread, and acquire the highest
694 * rtprio we can get that is less or equal the specified parameter. If
695 * the thread is already realtime, don't do anything. */
696 int pa_make_realtime(int rtprio) {
697
698 #if defined(OS_IS_DARWIN)
699 struct thread_time_constraint_policy ttcpolicy;
700 uint64_t freq = 0;
701 size_t size = sizeof(freq);
702 int ret;
703
704 ret = sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0);
705 if (ret < 0) {
706 pa_log_info("Unable to read CPU frequency, acquisition of real-time scheduling failed.");
707 return -1;
708 }
709
710 pa_log_debug("sysctl for hw.cpufrequency: %llu", freq);
711
712 /* See http://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/scheduler/scheduler.html */
713 ttcpolicy.period = freq / 160;
714 ttcpolicy.computation = freq / 3300;
715 ttcpolicy.constraint = freq / 2200;
716 ttcpolicy.preemptible = 1;
717
718 ret = thread_policy_set(mach_thread_self(),
719 THREAD_TIME_CONSTRAINT_POLICY,
720 (thread_policy_t) &ttcpolicy,
721 THREAD_TIME_CONSTRAINT_POLICY_COUNT);
722 if (ret) {
723 pa_log_info("Unable to set real-time thread priority (%08x).", ret);
724 return -1;
725 }
726
727 pa_log_info("Successfully acquired real-time thread priority.");
728 return 0;
729
730 #elif _POSIX_PRIORITY_SCHEDULING
731 int p;
732
733 if (set_scheduler(rtprio) >= 0) {
734 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i.", rtprio);
735 return 0;
736 }
737
738 for (p = rtprio-1; p >= 1; p--)
739 if (set_scheduler(p) >= 0) {
740 pa_log_info("Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i.", p, rtprio);
741 return 0;
742 }
743 #elif defined(OS_IS_WIN32)
744 /* Windows only allows realtime scheduling to be set on a per process basis.
745 * Therefore, instead of making the thread realtime, just give it the highest non-realtime priority. */
746 if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) {
747 pa_log_info("Successfully enabled THREAD_PRIORITY_TIME_CRITICAL scheduling for thread.");
748 return 0;
749 }
750
751 pa_log_warn("SetThreadPriority() failed: 0x%08X", GetLastError());
752 errno = EPERM;
753 #else
754 errno = ENOTSUP;
755 #endif
756 pa_log_info("Failed to acquire real-time scheduling: %s", pa_cstrerror(errno));
757 return -1;
758 }
759
760 #ifdef HAVE_SYS_RESOURCE_H
761 static int set_nice(int nice_level) {
762 #ifdef HAVE_DBUS
763 DBusError error;
764 DBusConnection *bus;
765 int r;
766
767 dbus_error_init(&error);
768 #endif
769
770 #ifdef HAVE_SYS_RESOURCE_H
771 if (setpriority(PRIO_PROCESS, 0, nice_level) >= 0) {
772 pa_log_debug("setpriority() worked.");
773 return 0;
774 }
775 #endif
776
777 #ifdef HAVE_DBUS
778 /* Try to talk to RealtimeKit */
779
780 if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
781 pa_log("Failed to connect to system bus: %s\n", error.message);
782 dbus_error_free(&error);
783 errno = -EIO;
784 return -1;
785 }
786
787 /* We need to disable exit on disconnect because otherwise
788 * dbus_shutdown will kill us. See
789 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
790 dbus_connection_set_exit_on_disconnect(bus, FALSE);
791
792 r = rtkit_make_high_priority(bus, 0, nice_level);
793 dbus_connection_unref(bus);
794
795 if (r >= 0) {
796 pa_log_debug("RealtimeKit worked.");
797 return 0;
798 }
799
800 errno = -r;
801 #endif
802
803 return -1;
804 }
805 #endif
806
807 /* Raise the priority of the current process as much as possible that
808 * is <= the specified nice level..*/
809 int pa_raise_priority(int nice_level) {
810
811 #ifdef HAVE_SYS_RESOURCE_H
812 int n;
813
814 if (set_nice(nice_level) >= 0) {
815 pa_log_info("Successfully gained nice level %i.", nice_level);
816 return 0;
817 }
818
819 for (n = nice_level+1; n < 0; n++)
820 if (set_nice(n) >= 0) {
821 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
822 return 0;
823 }
824
825 pa_log_info("Failed to acquire high-priority scheduling: %s", pa_cstrerror(errno));
826 return -1;
827 #endif
828
829 #ifdef OS_IS_WIN32
830 if (nice_level < 0) {
831 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
832 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
833 errno = EPERM;
834 return -1;
835 }
836
837 pa_log_info("Successfully gained high priority class.");
838 }
839 #endif
840
841 return 0;
842 }
843
844 /* Reset the priority to normal, inverting the changes made by
845 * pa_raise_priority() and pa_make_realtime()*/
846 void pa_reset_priority(void) {
847 #ifdef HAVE_SYS_RESOURCE_H
848 struct sched_param sp;
849
850 setpriority(PRIO_PROCESS, 0, 0);
851
852 pa_zero(sp);
853 pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp);
854 #endif
855
856 #ifdef OS_IS_WIN32
857 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
858 #endif
859 }
860
861 int pa_match(const char *expr, const char *v) {
862 int k;
863 regex_t re;
864 int r;
865
866 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
867 errno = EINVAL;
868 return -1;
869 }
870
871 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
872 r = 1;
873 else if (k == REG_NOMATCH)
874 r = 0;
875 else
876 r = -1;
877
878 regfree(&re);
879
880 if (r < 0)
881 errno = EINVAL;
882
883 return r;
884 }
885
886 /* Try to parse a boolean string value.*/
887 int pa_parse_boolean(const char *v) {
888 const char *expr;
889 pa_assert(v);
890
891 /* First we check language independant */
892 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
893 return 1;
894 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
895 return 0;
896
897 #ifdef HAVE_LANGINFO_H
898 /* And then we check language dependant */
899 if ((expr = nl_langinfo(YESEXPR)))
900 if (expr[0])
901 if (pa_match(expr, v) > 0)
902 return 1;
903
904 if ((expr = nl_langinfo(NOEXPR)))
905 if (expr[0])
906 if (pa_match(expr, v) > 0)
907 return 0;
908 #endif
909
910 errno = EINVAL;
911 return -1;
912 }
913
914 /* Split the specified string wherever one of the strings in delimiter
915 * occurs. Each time it is called returns a newly allocated string
916 * with pa_xmalloc(). The variable state points to, should be
917 * initiallized to NULL before the first call. */
918 char *pa_split(const char *c, const char *delimiter, const char**state) {
919 const char *current = *state ? *state : c;
920 size_t l;
921
922 if (!*current)
923 return NULL;
924
925 l = strcspn(current, delimiter);
926 *state = current+l;
927
928 if (**state)
929 (*state)++;
930
931 return pa_xstrndup(current, l);
932 }
933
934 /* Split a string into words. Otherwise similar to pa_split(). */
935 char *pa_split_spaces(const char *c, const char **state) {
936 const char *current = *state ? *state : c;
937 size_t l;
938
939 if (!*current || *c == 0)
940 return NULL;
941
942 current += strspn(current, WHITESPACE);
943 l = strcspn(current, WHITESPACE);
944
945 *state = current+l;
946
947 return pa_xstrndup(current, l);
948 }
949
950 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
951
952 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
953 const char *pa_sig2str(int sig) {
954 char *t;
955
956 if (sig <= 0)
957 goto fail;
958
959 #ifdef NSIG
960 if (sig >= NSIG)
961 goto fail;
962 #endif
963
964 #ifdef HAVE_SIG2STR
965 {
966 char buf[SIG2STR_MAX];
967
968 if (sig2str(sig, buf) == 0) {
969 pa_xfree(PA_STATIC_TLS_GET(signame));
970 t = pa_sprintf_malloc("SIG%s", buf);
971 PA_STATIC_TLS_SET(signame, t);
972 return t;
973 }
974 }
975 #else
976
977 switch (sig) {
978 #ifdef SIGHUP
979 case SIGHUP: return "SIGHUP";
980 #endif
981 case SIGINT: return "SIGINT";
982 #ifdef SIGQUIT
983 case SIGQUIT: return "SIGQUIT";
984 #endif
985 case SIGILL: return "SIGULL";
986 #ifdef SIGTRAP
987 case SIGTRAP: return "SIGTRAP";
988 #endif
989 case SIGABRT: return "SIGABRT";
990 #ifdef SIGBUS
991 case SIGBUS: return "SIGBUS";
992 #endif
993 case SIGFPE: return "SIGFPE";
994 #ifdef SIGKILL
995 case SIGKILL: return "SIGKILL";
996 #endif
997 #ifdef SIGUSR1
998 case SIGUSR1: return "SIGUSR1";
999 #endif
1000 case SIGSEGV: return "SIGSEGV";
1001 #ifdef SIGUSR2
1002 case SIGUSR2: return "SIGUSR2";
1003 #endif
1004 #ifdef SIGPIPE
1005 case SIGPIPE: return "SIGPIPE";
1006 #endif
1007 #ifdef SIGALRM
1008 case SIGALRM: return "SIGALRM";
1009 #endif
1010 case SIGTERM: return "SIGTERM";
1011 #ifdef SIGSTKFLT
1012 case SIGSTKFLT: return "SIGSTKFLT";
1013 #endif
1014 #ifdef SIGCHLD
1015 case SIGCHLD: return "SIGCHLD";
1016 #endif
1017 #ifdef SIGCONT
1018 case SIGCONT: return "SIGCONT";
1019 #endif
1020 #ifdef SIGSTOP
1021 case SIGSTOP: return "SIGSTOP";
1022 #endif
1023 #ifdef SIGTSTP
1024 case SIGTSTP: return "SIGTSTP";
1025 #endif
1026 #ifdef SIGTTIN
1027 case SIGTTIN: return "SIGTTIN";
1028 #endif
1029 #ifdef SIGTTOU
1030 case SIGTTOU: return "SIGTTOU";
1031 #endif
1032 #ifdef SIGURG
1033 case SIGURG: return "SIGURG";
1034 #endif
1035 #ifdef SIGXCPU
1036 case SIGXCPU: return "SIGXCPU";
1037 #endif
1038 #ifdef SIGXFSZ
1039 case SIGXFSZ: return "SIGXFSZ";
1040 #endif
1041 #ifdef SIGVTALRM
1042 case SIGVTALRM: return "SIGVTALRM";
1043 #endif
1044 #ifdef SIGPROF
1045 case SIGPROF: return "SIGPROF";
1046 #endif
1047 #ifdef SIGWINCH
1048 case SIGWINCH: return "SIGWINCH";
1049 #endif
1050 #ifdef SIGIO
1051 case SIGIO: return "SIGIO";
1052 #endif
1053 #ifdef SIGPWR
1054 case SIGPWR: return "SIGPWR";
1055 #endif
1056 #ifdef SIGSYS
1057 case SIGSYS: return "SIGSYS";
1058 #endif
1059 }
1060
1061 #ifdef SIGRTMIN
1062 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
1063 pa_xfree(PA_STATIC_TLS_GET(signame));
1064 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
1065 PA_STATIC_TLS_SET(signame, t);
1066 return t;
1067 }
1068 #endif
1069
1070 #endif
1071
1072 fail:
1073
1074 pa_xfree(PA_STATIC_TLS_GET(signame));
1075 t = pa_sprintf_malloc("SIG%i", sig);
1076 PA_STATIC_TLS_SET(signame, t);
1077 return t;
1078 }
1079
1080 #ifdef HAVE_GRP_H
1081
1082 /* Check whether the specified GID and the group name match */
1083 static int is_group(gid_t gid, const char *name) {
1084 struct group *group = NULL;
1085 int r = -1;
1086
1087 errno = 0;
1088 if (!(group = pa_getgrgid_malloc(gid))) {
1089 if (!errno)
1090 errno = ENOENT;
1091
1092 pa_log("pa_getgrgid_malloc(%u): %s", gid, pa_cstrerror(errno));
1093
1094 goto finish;
1095 }
1096
1097 r = strcmp(name, group->gr_name) == 0;
1098
1099 finish:
1100 pa_getgrgid_free(group);
1101
1102 return r;
1103 }
1104
1105 /* Check the current user is member of the specified group */
1106 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1107 GETGROUPS_T *gids, tgid;
1108 long n = sysconf(_SC_NGROUPS_MAX);
1109 int r = -1, i, k;
1110
1111 pa_assert(n > 0);
1112
1113 gids = pa_xmalloc(sizeof(GETGROUPS_T) * (size_t) n);
1114
1115 if ((n = getgroups((int) n, gids)) < 0) {
1116 pa_log("getgroups(): %s", pa_cstrerror(errno));
1117 goto finish;
1118 }
1119
1120 for (i = 0; i < n; i++) {
1121
1122 if ((k = is_group(gids[i], name)) < 0)
1123 goto finish;
1124 else if (k > 0) {
1125 *gid = gids[i];
1126 r = 1;
1127 goto finish;
1128 }
1129 }
1130
1131 if ((k = is_group(tgid = getgid(), name)) < 0)
1132 goto finish;
1133 else if (k > 0) {
1134 *gid = tgid;
1135 r = 1;
1136 goto finish;
1137 }
1138
1139 r = 0;
1140
1141 finish:
1142
1143 pa_xfree(gids);
1144 return r;
1145 }
1146
1147 /* Check whether the specifc user id is a member of the specified group */
1148 int pa_uid_in_group(uid_t uid, const char *name) {
1149 struct group *group = NULL;
1150 char **i;
1151 int r = -1;
1152
1153 errno = 0;
1154 if (!(group = pa_getgrnam_malloc(name))) {
1155 if (!errno)
1156 errno = ENOENT;
1157 goto finish;
1158 }
1159
1160 r = 0;
1161 for (i = group->gr_mem; *i; i++) {
1162 struct passwd *pw = NULL;
1163
1164 errno = 0;
1165 if (!(pw = pa_getpwnam_malloc(*i)))
1166 continue;
1167
1168 if (pw->pw_uid == uid)
1169 r = 1;
1170
1171 pa_getpwnam_free(pw);
1172
1173 if (r == 1)
1174 break;
1175 }
1176
1177 finish:
1178 pa_getgrnam_free(group);
1179
1180 return r;
1181 }
1182
1183 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1184 gid_t pa_get_gid_of_group(const char *name) {
1185 gid_t ret = (gid_t) -1;
1186 struct group *gr = NULL;
1187
1188 errno = 0;
1189 if (!(gr = pa_getgrnam_malloc(name))) {
1190 if (!errno)
1191 errno = ENOENT;
1192 goto finish;
1193 }
1194
1195 ret = gr->gr_gid;
1196
1197 finish:
1198 pa_getgrnam_free(gr);
1199 return ret;
1200 }
1201
1202 int pa_check_in_group(gid_t g) {
1203 gid_t gids[NGROUPS_MAX];
1204 int r;
1205
1206 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1207 return -1;
1208
1209 for (; r > 0; r--)
1210 if (gids[r-1] == g)
1211 return 1;
1212
1213 return 0;
1214 }
1215
1216 #else /* HAVE_GRP_H */
1217
1218 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1219 errno = ENOTSUP;
1220 return -1;
1221
1222 }
1223
1224 int pa_uid_in_group(uid_t uid, const char *name) {
1225 errno = ENOTSUP;
1226 return -1;
1227 }
1228
1229 gid_t pa_get_gid_of_group(const char *name) {
1230 errno = ENOTSUP;
1231 return (gid_t) -1;
1232 }
1233
1234 int pa_check_in_group(gid_t g) {
1235 errno = ENOTSUP;
1236 return -1;
1237 }
1238
1239 #endif
1240
1241 /* Lock or unlock a file entirely.
1242 (advisory on UNIX, mandatory on Windows) */
1243 int pa_lock_fd(int fd, int b) {
1244 #ifdef F_SETLKW
1245 struct flock f_lock;
1246
1247 /* Try a R/W lock first */
1248
1249 f_lock.l_type = (short) (b ? F_WRLCK : F_UNLCK);
1250 f_lock.l_whence = SEEK_SET;
1251 f_lock.l_start = 0;
1252 f_lock.l_len = 0;
1253
1254 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1255 return 0;
1256
1257 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1258 if (b && errno == EBADF) {
1259 f_lock.l_type = F_RDLCK;
1260 if (fcntl(fd, F_SETLKW, &f_lock) >= 0)
1261 return 0;
1262 }
1263
1264 pa_log("%slock: %s", !b ? "un" : "", pa_cstrerror(errno));
1265 #endif
1266
1267 #ifdef OS_IS_WIN32
1268 HANDLE h = (HANDLE) _get_osfhandle(fd);
1269
1270 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1271 return 0;
1272 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1273 return 0;
1274
1275 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1276
1277 /* FIXME: Needs to set errno! */
1278 #endif
1279
1280 return -1;
1281 }
1282
1283 /* Remove trailing newlines from a string */
1284 char* pa_strip_nl(char *s) {
1285 pa_assert(s);
1286
1287 s[strcspn(s, NEWLINE)] = 0;
1288 return s;
1289 }
1290
1291 char *pa_strip(char *s) {
1292 char *e, *l = NULL;
1293
1294 /* Drops trailing whitespace. Modifies the string in
1295 * place. Returns pointer to first non-space character */
1296
1297 s += strspn(s, WHITESPACE);
1298
1299 for (e = s; *e; e++)
1300 if (!strchr(WHITESPACE, *e))
1301 l = e;
1302
1303 if (l)
1304 *(l+1) = 0;
1305 else
1306 *s = 0;
1307
1308 return s;
1309 }
1310
1311 /* Create a temporary lock file and lock it. */
1312 int pa_lock_lockfile(const char *fn) {
1313 int fd;
1314 pa_assert(fn);
1315
1316 for (;;) {
1317 struct stat st;
1318
1319 if ((fd = pa_open_cloexec(fn, O_CREAT|O_RDWR
1320 #ifdef O_NOFOLLOW
1321 |O_NOFOLLOW
1322 #endif
1323 , S_IRUSR|S_IWUSR)) < 0) {
1324 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1325 goto fail;
1326 }
1327
1328 if (pa_lock_fd(fd, 1) < 0) {
1329 pa_log_warn("Failed to lock file '%s'.", fn);
1330 goto fail;
1331 }
1332
1333 if (fstat(fd, &st) < 0) {
1334 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1335 goto fail;
1336 }
1337
1338 /* Check whether the file has been removed meanwhile. When yes,
1339 * restart this loop, otherwise, we're done */
1340 if (st.st_nlink >= 1)
1341 break;
1342
1343 if (pa_lock_fd(fd, 0) < 0) {
1344 pa_log_warn("Failed to unlock file '%s'.", fn);
1345 goto fail;
1346 }
1347
1348 if (pa_close(fd) < 0) {
1349 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1350 fd = -1;
1351 goto fail;
1352 }
1353 }
1354
1355 return fd;
1356
1357 fail:
1358
1359 if (fd >= 0) {
1360 int saved_errno = errno;
1361 pa_close(fd);
1362 errno = saved_errno;
1363 }
1364
1365 return -1;
1366 }
1367
1368 /* Unlock a temporary lcok file */
1369 int pa_unlock_lockfile(const char *fn, int fd) {
1370 int r = 0;
1371 pa_assert(fd >= 0);
1372
1373 if (fn) {
1374 if (unlink(fn) < 0) {
1375 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1376 r = -1;
1377 }
1378 }
1379
1380 if (pa_lock_fd(fd, 0) < 0) {
1381 pa_log_warn("Failed to unlock file '%s'.", fn);
1382 r = -1;
1383 }
1384
1385 if (pa_close(fd) < 0) {
1386 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1387 r = -1;
1388 }
1389
1390 return r;
1391 }
1392
1393 static char *get_pulse_home(void) {
1394 char *h;
1395 struct stat st;
1396 char *ret = NULL;
1397
1398 if (!(h = pa_get_home_dir_malloc())) {
1399 pa_log_error("Failed to get home directory.");
1400 return NULL;
1401 }
1402
1403 if (stat(h, &st) < 0) {
1404 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1405 goto finish;
1406 }
1407
1408 #ifdef HAVE_GETUID
1409 if (st.st_uid != getuid()) {
1410 pa_log_error("Home directory %s not ours.", h);
1411 errno = EACCES;
1412 goto finish;
1413 }
1414 #endif
1415
1416 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1417
1418 finish:
1419 pa_xfree(h);
1420
1421 return ret;
1422 }
1423
1424 char *pa_get_state_dir(void) {
1425 char *d;
1426
1427 /* The state directory shall contain dynamic data that should be
1428 * kept across reboots, and is private to this user */
1429
1430 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1431 if (!(d = get_pulse_home()))
1432 return NULL;
1433
1434 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1435 * dir then this will break. */
1436
1437 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1438 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1439 pa_xfree(d);
1440 return NULL;
1441 }
1442
1443 return d;
1444 }
1445
1446 char *pa_get_home_dir_malloc(void) {
1447 char *homedir;
1448 size_t allocated = 128;
1449
1450 for (;;) {
1451 homedir = pa_xmalloc(allocated);
1452
1453 if (!pa_get_home_dir(homedir, allocated)) {
1454 pa_xfree(homedir);
1455 return NULL;
1456 }
1457
1458 if (strlen(homedir) < allocated - 1)
1459 break;
1460
1461 pa_xfree(homedir);
1462 allocated *= 2;
1463 }
1464
1465 return homedir;
1466 }
1467
1468 char *pa_get_binary_name_malloc(void) {
1469 char *t;
1470 size_t allocated = 128;
1471
1472 for (;;) {
1473 t = pa_xmalloc(allocated);
1474
1475 if (!pa_get_binary_name(t, allocated)) {
1476 pa_xfree(t);
1477 return NULL;
1478 }
1479
1480 if (strlen(t) < allocated - 1)
1481 break;
1482
1483 pa_xfree(t);
1484 allocated *= 2;
1485 }
1486
1487 return t;
1488 }
1489
1490 static char* make_random_dir(mode_t m) {
1491 static const char table[] =
1492 "abcdefghijklmnopqrstuvwxyz"
1493 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1494 "0123456789";
1495
1496 char *fn;
1497 size_t pathlen;
1498
1499 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1500 pathlen = strlen(fn);
1501
1502 for (;;) {
1503 size_t i;
1504 int r;
1505 mode_t u;
1506 int saved_errno;
1507
1508 for (i = pathlen - 12; i < pathlen; i++)
1509 fn[i] = table[rand() % (sizeof(table)-1)];
1510
1511 u = umask((~m) & 0777);
1512 #ifndef OS_IS_WIN32
1513 r = mkdir(fn, m);
1514 #else
1515 r = mkdir(fn);
1516 #endif
1517
1518 saved_errno = errno;
1519 umask(u);
1520 errno = saved_errno;
1521
1522 if (r >= 0)
1523 return fn;
1524
1525 if (errno != EEXIST) {
1526 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1527 pa_xfree(fn);
1528 return NULL;
1529 }
1530 }
1531 }
1532
1533 static int make_random_dir_and_link(mode_t m, const char *k) {
1534 char *p;
1535
1536 if (!(p = make_random_dir(m)))
1537 return -1;
1538
1539 #ifdef HAVE_SYMLINK
1540 if (symlink(p, k) < 0) {
1541 int saved_errno = errno;
1542
1543 if (errno != EEXIST)
1544 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1545
1546 rmdir(p);
1547 pa_xfree(p);
1548
1549 errno = saved_errno;
1550 return -1;
1551 }
1552 #else
1553 pa_xfree(p);
1554 return -1;
1555 #endif
1556
1557 pa_xfree(p);
1558 return 0;
1559 }
1560
1561 char *pa_get_runtime_dir(void) {
1562 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1563 struct stat st;
1564 mode_t m;
1565
1566 /* The runtime directory shall contain dynamic data that needs NOT
1567 * to be kept accross reboots and is usuallly private to the user,
1568 * except in system mode, where it might be accessible by other
1569 * users, too. Since we need POSIX locking and UNIX sockets in
1570 * this directory, we link it to a random subdir in /tmp, if it
1571 * was not explicitly configured. */
1572
1573 m = pa_in_system_mode() ? 0755U : 0700U;
1574
1575 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1576
1577 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1578 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1579 goto fail;
1580 }
1581
1582 return pa_xstrdup(d);
1583 }
1584
1585 if (!(d = get_pulse_home()))
1586 goto fail;
1587
1588 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1589 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1590 pa_xfree(d);
1591 goto fail;
1592 }
1593
1594 if (!(mid = pa_machine_id())) {
1595 pa_xfree(d);
1596 goto fail;
1597 }
1598
1599 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1600 pa_xfree(d);
1601 pa_xfree(mid);
1602
1603 for (;;) {
1604 /* OK, first let's check if the "runtime" symlink is already
1605 * existant */
1606
1607 if (!(p = pa_readlink(k))) {
1608
1609 if (errno != ENOENT) {
1610 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1611 goto fail;
1612 }
1613
1614 #ifdef HAVE_SYMLINK
1615 /* Hmm, so the runtime directory didn't exist yet, so let's
1616 * create one in /tmp and symlink that to it */
1617
1618 if (make_random_dir_and_link(0700, k) < 0) {
1619
1620 /* Mhmm, maybe another process was quicker than us,
1621 * let's check if that was valid */
1622 if (errno == EEXIST)
1623 continue;
1624
1625 goto fail;
1626 }
1627 #else
1628 /* No symlink possible, so let's just create the runtime directly */
1629 if (!mkdir(k))
1630 goto fail;
1631 #endif
1632
1633 return k;
1634 }
1635
1636 /* Make sure that this actually makes sense */
1637 if (!pa_is_path_absolute(p)) {
1638 pa_log_error("Path %s in link %s is not absolute.", p, k);
1639 errno = ENOENT;
1640 goto fail;
1641 }
1642
1643 /* Hmm, so this symlink is still around, make sure nobody fools
1644 * us */
1645
1646 #ifdef HAVE_LSTAT
1647 if (lstat(p, &st) < 0) {
1648
1649 if (errno != ENOENT) {
1650 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1651 goto fail;
1652 }
1653
1654 } else {
1655
1656 if (S_ISDIR(st.st_mode) &&
1657 (st.st_uid == getuid()) &&
1658 ((st.st_mode & 0777) == 0700)) {
1659
1660 pa_xfree(p);
1661 return k;
1662 }
1663
1664 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1665 }
1666 #endif
1667
1668 pa_xfree(p);
1669 p = NULL;
1670
1671 /* Hmm, so the link points to some nonexisting or invalid
1672 * dir. Let's replace it by a new link. We first create a
1673 * temporary link and then rename that to allow concurrent
1674 * execution of this function. */
1675
1676 t = pa_sprintf_malloc("%s.tmp", k);
1677
1678 if (make_random_dir_and_link(0700, t) < 0) {
1679
1680 if (errno != EEXIST) {
1681 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1682 goto fail;
1683 }
1684
1685 pa_xfree(t);
1686 t = NULL;
1687
1688 /* Hmm, someone lese was quicker then us. Let's give
1689 * him some time to finish, and retry. */
1690 pa_msleep(10);
1691 continue;
1692 }
1693
1694 /* OK, we succeeded in creating the temporary symlink, so
1695 * let's rename it */
1696 if (rename(t, k) < 0) {
1697 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1698 goto fail;
1699 }
1700
1701 pa_xfree(t);
1702 return k;
1703 }
1704
1705 fail:
1706 pa_xfree(p);
1707 pa_xfree(k);
1708 pa_xfree(t);
1709
1710 return NULL;
1711 }
1712
1713 /* Try to open a configuration file. If "env" is specified, open the
1714 * value of the specified environment variable. Otherwise look for a
1715 * file "local" in the home directory or a file "global" in global
1716 * file system. If "result" is non-NULL, a pointer to a newly
1717 * allocated buffer containing the used configuration file is
1718 * stored there.*/
1719 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1720 const char *fn;
1721 FILE *f;
1722
1723 if (env && (fn = getenv(env))) {
1724 if ((f = pa_fopen_cloexec(fn, "r"))) {
1725 if (result)
1726 *result = pa_xstrdup(fn);
1727
1728 return f;
1729 }
1730
1731 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1732 return NULL;
1733 }
1734
1735 if (local) {
1736 const char *e;
1737 char *lfn;
1738 char *h;
1739
1740 if ((e = getenv("PULSE_CONFIG_PATH")))
1741 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1742 else if ((h = pa_get_home_dir_malloc())) {
1743 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1744 pa_xfree(h);
1745 } else
1746 return NULL;
1747
1748 if ((f = pa_fopen_cloexec(fn, "r"))) {
1749 if (result)
1750 *result = pa_xstrdup(fn);
1751
1752 pa_xfree(lfn);
1753 return f;
1754 }
1755
1756 if (errno != ENOENT) {
1757 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1758 pa_xfree(lfn);
1759 return NULL;
1760 }
1761
1762 pa_xfree(lfn);
1763 }
1764
1765 if (global) {
1766 char *gfn;
1767
1768 #ifdef OS_IS_WIN32
1769 if (strncmp(global, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
1770 gfn = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse%s",
1771 pa_win32_get_toplevel(NULL),
1772 global + strlen(PA_DEFAULT_CONFIG_DIR));
1773 else
1774 #endif
1775 gfn = pa_xstrdup(global);
1776
1777 if ((f = pa_fopen_cloexec(gfn, "r"))) {
1778 if (result)
1779 *result = gfn;
1780 else
1781 pa_xfree(gfn);
1782
1783 return f;
1784 }
1785 pa_xfree(gfn);
1786 }
1787
1788 errno = ENOENT;
1789 return NULL;
1790 }
1791
1792 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1793 const char *fn;
1794
1795 if (env && (fn = getenv(env))) {
1796 if (access(fn, R_OK) == 0)
1797 return pa_xstrdup(fn);
1798
1799 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1800 return NULL;
1801 }
1802
1803 if (local) {
1804 const char *e;
1805 char *lfn;
1806 char *h;
1807
1808 if ((e = getenv("PULSE_CONFIG_PATH")))
1809 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1810 else if ((h = pa_get_home_dir_malloc())) {
1811 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1812 pa_xfree(h);
1813 } else
1814 return NULL;
1815
1816 if (access(fn, R_OK) == 0) {
1817 char *r = pa_xstrdup(fn);
1818 pa_xfree(lfn);
1819 return r;
1820 }
1821
1822 if (errno != ENOENT) {
1823 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1824 pa_xfree(lfn);
1825 return NULL;
1826 }
1827
1828 pa_xfree(lfn);
1829 }
1830
1831 if (global) {
1832 char *gfn;
1833
1834 #ifdef OS_IS_WIN32
1835 if (strncmp(global, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
1836 gfn = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse%s",
1837 pa_win32_get_toplevel(NULL),
1838 global + strlen(PA_DEFAULT_CONFIG_DIR));
1839 else
1840 #endif
1841 gfn = pa_xstrdup(global);
1842
1843 if (access(gfn, R_OK) == 0)
1844 return gfn;
1845 pa_xfree(gfn);
1846 }
1847
1848 errno = ENOENT;
1849
1850 return NULL;
1851 }
1852
1853 /* Format the specified data as a hexademical string */
1854 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1855 size_t i = 0, j = 0;
1856 const char hex[] = "0123456789abcdef";
1857
1858 pa_assert(d);
1859 pa_assert(s);
1860 pa_assert(slength > 0);
1861
1862 while (j+2 < slength && i < dlength) {
1863 s[j++] = hex[*d >> 4];
1864 s[j++] = hex[*d & 0xF];
1865
1866 d++;
1867 i++;
1868 }
1869
1870 s[j < slength ? j : slength] = 0;
1871 return s;
1872 }
1873
1874 /* Convert a hexadecimal digit to a number or -1 if invalid */
1875 static int hexc(char c) {
1876 if (c >= '0' && c <= '9')
1877 return c - '0';
1878
1879 if (c >= 'A' && c <= 'F')
1880 return c - 'A' + 10;
1881
1882 if (c >= 'a' && c <= 'f')
1883 return c - 'a' + 10;
1884
1885 errno = EINVAL;
1886 return -1;
1887 }
1888
1889 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1890 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1891 size_t j = 0;
1892
1893 pa_assert(p);
1894 pa_assert(d);
1895
1896 while (j < dlength && *p) {
1897 int b;
1898
1899 if ((b = hexc(*(p++))) < 0)
1900 return (size_t) -1;
1901
1902 d[j] = (uint8_t) (b << 4);
1903
1904 if (!*p)
1905 return (size_t) -1;
1906
1907 if ((b = hexc(*(p++))) < 0)
1908 return (size_t) -1;
1909
1910 d[j] |= (uint8_t) b;
1911 j++;
1912 }
1913
1914 return j;
1915 }
1916
1917 /* Returns nonzero when *s starts with *pfx */
1918 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1919 size_t l;
1920
1921 pa_assert(s);
1922 pa_assert(pfx);
1923
1924 l = strlen(pfx);
1925
1926 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1927 }
1928
1929 /* Returns nonzero when *s ends with *sfx */
1930 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1931 size_t l1, l2;
1932
1933 pa_assert(s);
1934 pa_assert(sfx);
1935
1936 l1 = strlen(s);
1937 l2 = strlen(sfx);
1938
1939 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1940 }
1941
1942 pa_bool_t pa_is_path_absolute(const char *fn) {
1943 pa_assert(fn);
1944
1945 #ifndef OS_IS_WIN32
1946 return *fn == '/';
1947 #else
1948 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1949 #endif
1950 }
1951
1952 char *pa_make_path_absolute(const char *p) {
1953 char *r;
1954 char *cwd;
1955
1956 pa_assert(p);
1957
1958 if (pa_is_path_absolute(p))
1959 return pa_xstrdup(p);
1960
1961 if (!(cwd = pa_getcwd()))
1962 return pa_xstrdup(p);
1963
1964 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1965 pa_xfree(cwd);
1966 return r;
1967 }
1968
1969 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1970 * if fn is non-null and starts with / return fn
1971 * otherwise append fn to the run time path and return it */
1972 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1973 char *rtp;
1974
1975 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1976
1977 if (fn) {
1978 char *r;
1979
1980 if (pa_is_path_absolute(fn))
1981 return pa_xstrdup(fn);
1982
1983 if (!rtp)
1984 return NULL;
1985
1986 if (prependmid) {
1987 char *mid;
1988
1989 if (!(mid = pa_machine_id())) {
1990 pa_xfree(rtp);
1991 return NULL;
1992 }
1993
1994 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
1995 pa_xfree(mid);
1996 } else
1997 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1998
1999 pa_xfree(rtp);
2000 return r;
2001 } else
2002 return rtp;
2003 }
2004
2005 char *pa_runtime_path(const char *fn) {
2006 return get_path(fn, FALSE, TRUE);
2007 }
2008
2009 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
2010 return get_path(fn, appendmid, FALSE);
2011 }
2012
2013 /* Convert the string s to a signed integer in *ret_i */
2014 int pa_atoi(const char *s, int32_t *ret_i) {
2015 char *x = NULL;
2016 long l;
2017
2018 pa_assert(s);
2019 pa_assert(ret_i);
2020
2021 errno = 0;
2022 l = strtol(s, &x, 0);
2023
2024 if (!x || *x || errno) {
2025 if (!errno)
2026 errno = EINVAL;
2027 return -1;
2028 }
2029
2030 if ((int32_t) l != l) {
2031 errno = ERANGE;
2032 return -1;
2033 }
2034
2035 *ret_i = (int32_t) l;
2036
2037 return 0;
2038 }
2039
2040 /* Convert the string s to an unsigned integer in *ret_u */
2041 int pa_atou(const char *s, uint32_t *ret_u) {
2042 char *x = NULL;
2043 unsigned long l;
2044
2045 pa_assert(s);
2046 pa_assert(ret_u);
2047
2048 errno = 0;
2049 l = strtoul(s, &x, 0);
2050
2051 if (!x || *x || errno) {
2052 if (!errno)
2053 errno = EINVAL;
2054 return -1;
2055 }
2056
2057 if ((uint32_t) l != l) {
2058 errno = ERANGE;
2059 return -1;
2060 }
2061
2062 *ret_u = (uint32_t) l;
2063
2064 return 0;
2065 }
2066
2067 #ifdef HAVE_STRTOF_L
2068 static locale_t c_locale = NULL;
2069
2070 static void c_locale_destroy(void) {
2071 freelocale(c_locale);
2072 }
2073 #endif
2074
2075 int pa_atod(const char *s, double *ret_d) {
2076 char *x = NULL;
2077 double f;
2078
2079 pa_assert(s);
2080 pa_assert(ret_d);
2081
2082 /* This should be locale independent */
2083
2084 #ifdef HAVE_STRTOF_L
2085
2086 PA_ONCE_BEGIN {
2087
2088 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2089 atexit(c_locale_destroy);
2090
2091 } PA_ONCE_END;
2092
2093 if (c_locale) {
2094 errno = 0;
2095 f = strtod_l(s, &x, c_locale);
2096 } else
2097 #endif
2098 {
2099 errno = 0;
2100 f = strtod(s, &x);
2101 }
2102
2103 if (!x || *x || errno) {
2104 if (!errno)
2105 errno = EINVAL;
2106 return -1;
2107 }
2108
2109 *ret_d = f;
2110
2111 return 0;
2112 }
2113
2114 /* Same as snprintf, but guarantees NUL-termination on every platform */
2115 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2116 size_t ret;
2117 va_list ap;
2118
2119 pa_assert(str);
2120 pa_assert(size > 0);
2121 pa_assert(format);
2122
2123 va_start(ap, format);
2124 ret = pa_vsnprintf(str, size, format, ap);
2125 va_end(ap);
2126
2127 return ret;
2128 }
2129
2130 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2131 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2132 int ret;
2133
2134 pa_assert(str);
2135 pa_assert(size > 0);
2136 pa_assert(format);
2137
2138 ret = vsnprintf(str, size, format, ap);
2139
2140 str[size-1] = 0;
2141
2142 if (ret < 0)
2143 return strlen(str);
2144
2145 if ((size_t) ret > size-1)
2146 return size-1;
2147
2148 return (size_t) ret;
2149 }
2150
2151 /* Truncate the specified string, but guarantee that the string
2152 * returned still validates as UTF8 */
2153 char *pa_truncate_utf8(char *c, size_t l) {
2154 pa_assert(c);
2155 pa_assert(pa_utf8_valid(c));
2156
2157 if (strlen(c) <= l)
2158 return c;
2159
2160 c[l] = 0;
2161
2162 while (l > 0 && !pa_utf8_valid(c))
2163 c[--l] = 0;
2164
2165 return c;
2166 }
2167
2168 char *pa_getcwd(void) {
2169 size_t l = 128;
2170
2171 for (;;) {
2172 char *p = pa_xmalloc(l);
2173 if (getcwd(p, l))
2174 return p;
2175
2176 if (errno != ERANGE)
2177 return NULL;
2178
2179 pa_xfree(p);
2180 l *= 2;
2181 }
2182 }
2183
2184 void *pa_will_need(const void *p, size_t l) {
2185 #ifdef RLIMIT_MEMLOCK
2186 struct rlimit rlim;
2187 #endif
2188 const void *a;
2189 size_t size;
2190 int r;
2191 size_t bs;
2192
2193 pa_assert(p);
2194 pa_assert(l > 0);
2195
2196 a = PA_PAGE_ALIGN_PTR(p);
2197 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2198
2199 #ifdef HAVE_POSIX_MADVISE
2200 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2201 pa_log_debug("posix_madvise() worked fine!");
2202 return (void*) p;
2203 }
2204 #endif
2205
2206 /* Most likely the memory was not mmap()ed from a file and thus
2207 * madvise() didn't work, so let's misuse mlock() do page this
2208 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2209 * inviting, the man page of mlock() tells us: "All pages that
2210 * contain a part of the specified address range are guaranteed to
2211 * be resident in RAM when the call returns successfully." */
2212
2213 #ifdef RLIMIT_MEMLOCK
2214 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2215
2216 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2217 pa_log_debug("posix_madvise() failed (or doesn't exist), resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
2218 errno = EPERM;
2219 return (void*) p;
2220 }
2221
2222 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2223 #else
2224 bs = PA_PAGE_SIZE*4;
2225 #endif
2226
2227 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2228
2229 #ifdef HAVE_MLOCK
2230 while (size > 0 && bs > 0) {
2231
2232 if (bs > size)
2233 bs = size;
2234
2235 if (mlock(a, bs) < 0) {
2236 bs = PA_PAGE_ALIGN(bs / 2);
2237 continue;
2238 }
2239
2240 pa_assert_se(munlock(a, bs) == 0);
2241
2242 a = (const uint8_t*) a + bs;
2243 size -= bs;
2244 }
2245 #endif
2246
2247 if (bs <= 0)
2248 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2249 else
2250 pa_log_debug("mlock() worked fine!");
2251
2252 return (void*) p;
2253 }
2254
2255 void pa_close_pipe(int fds[2]) {
2256 pa_assert(fds);
2257
2258 if (fds[0] >= 0)
2259 pa_assert_se(pa_close(fds[0]) == 0);
2260
2261 if (fds[1] >= 0)
2262 pa_assert_se(pa_close(fds[1]) == 0);
2263
2264 fds[0] = fds[1] = -1;
2265 }
2266
2267 char *pa_readlink(const char *p) {
2268 #ifdef HAVE_READLINK
2269 size_t l = 100;
2270
2271 for (;;) {
2272 char *c;
2273 ssize_t n;
2274
2275 c = pa_xmalloc(l);
2276
2277 if ((n = readlink(p, c, l-1)) < 0) {
2278 pa_xfree(c);
2279 return NULL;
2280 }
2281
2282 if ((size_t) n < l-1) {
2283 c[n] = 0;
2284 return c;
2285 }
2286
2287 pa_xfree(c);
2288 l *= 2;
2289 }
2290 #else
2291 return NULL;
2292 #endif
2293 }
2294
2295 int pa_close_all(int except_fd, ...) {
2296 va_list ap;
2297 unsigned n = 0, i;
2298 int r, *p;
2299
2300 va_start(ap, except_fd);
2301
2302 if (except_fd >= 0)
2303 for (n = 1; va_arg(ap, int) >= 0; n++)
2304 ;
2305
2306 va_end(ap);
2307
2308 p = pa_xnew(int, n+1);
2309
2310 va_start(ap, except_fd);
2311
2312 i = 0;
2313 if (except_fd >= 0) {
2314 int fd;
2315 p[i++] = except_fd;
2316
2317 while ((fd = va_arg(ap, int)) >= 0)
2318 p[i++] = fd;
2319 }
2320 p[i] = -1;
2321
2322 va_end(ap);
2323
2324 r = pa_close_allv(p);
2325 pa_xfree(p);
2326
2327 return r;
2328 }
2329
2330 int pa_close_allv(const int except_fds[]) {
2331 #ifndef OS_IS_WIN32
2332 struct rlimit rl;
2333 int maxfd, fd;
2334
2335 #ifdef __linux__
2336 int saved_errno;
2337 DIR *d;
2338
2339 if ((d = opendir("/proc/self/fd"))) {
2340
2341 struct dirent *de;
2342
2343 while ((de = readdir(d))) {
2344 pa_bool_t found;
2345 long l;
2346 char *e = NULL;
2347 int i;
2348
2349 if (de->d_name[0] == '.')
2350 continue;
2351
2352 errno = 0;
2353 l = strtol(de->d_name, &e, 10);
2354 if (errno != 0 || !e || *e) {
2355 closedir(d);
2356 errno = EINVAL;
2357 return -1;
2358 }
2359
2360 fd = (int) l;
2361
2362 if ((long) fd != l) {
2363 closedir(d);
2364 errno = EINVAL;
2365 return -1;
2366 }
2367
2368 if (fd < 3)
2369 continue;
2370
2371 if (fd == dirfd(d))
2372 continue;
2373
2374 found = FALSE;
2375 for (i = 0; except_fds[i] >= 0; i++)
2376 if (except_fds[i] == fd) {
2377 found = TRUE;
2378 break;
2379 }
2380
2381 if (found)
2382 continue;
2383
2384 if (pa_close(fd) < 0) {
2385 saved_errno = errno;
2386 closedir(d);
2387 errno = saved_errno;
2388
2389 return -1;
2390 }
2391 }
2392
2393 closedir(d);
2394 return 0;
2395 }
2396
2397 #endif
2398
2399 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2400 maxfd = (int) rl.rlim_max;
2401 else
2402 maxfd = sysconf(_SC_OPEN_MAX);
2403
2404 for (fd = 3; fd < maxfd; fd++) {
2405 int i;
2406 pa_bool_t found;
2407
2408 found = FALSE;
2409 for (i = 0; except_fds[i] >= 0; i++)
2410 if (except_fds[i] == fd) {
2411 found = TRUE;
2412 break;
2413 }
2414
2415 if (found)
2416 continue;
2417
2418 if (pa_close(fd) < 0 && errno != EBADF)
2419 return -1;
2420 }
2421 #endif /* !OS_IS_WIN32 */
2422
2423 return 0;
2424 }
2425
2426 int pa_unblock_sigs(int except, ...) {
2427 va_list ap;
2428 unsigned n = 0, i;
2429 int r, *p;
2430
2431 va_start(ap, except);
2432
2433 if (except >= 1)
2434 for (n = 1; va_arg(ap, int) >= 0; n++)
2435 ;
2436
2437 va_end(ap);
2438
2439 p = pa_xnew(int, n+1);
2440
2441 va_start(ap, except);
2442
2443 i = 0;
2444 if (except >= 1) {
2445 int sig;
2446 p[i++] = except;
2447
2448 while ((sig = va_arg(ap, int)) >= 0)
2449 p[i++] = sig;
2450 }
2451 p[i] = -1;
2452
2453 va_end(ap);
2454
2455 r = pa_unblock_sigsv(p);
2456 pa_xfree(p);
2457
2458 return r;
2459 }
2460
2461 int pa_unblock_sigsv(const int except[]) {
2462 #ifndef OS_IS_WIN32
2463 int i;
2464 sigset_t ss;
2465
2466 if (sigemptyset(&ss) < 0)
2467 return -1;
2468
2469 for (i = 0; except[i] > 0; i++)
2470 if (sigaddset(&ss, except[i]) < 0)
2471 return -1;
2472
2473 return sigprocmask(SIG_SETMASK, &ss, NULL);
2474 #else
2475 return 0;
2476 #endif
2477 }
2478
2479 int pa_reset_sigs(int except, ...) {
2480 va_list ap;
2481 unsigned n = 0, i;
2482 int *p, r;
2483
2484 va_start(ap, except);
2485
2486 if (except >= 1)
2487 for (n = 1; va_arg(ap, int) >= 0; n++)
2488 ;
2489
2490 va_end(ap);
2491
2492 p = pa_xnew(int, n+1);
2493
2494 va_start(ap, except);
2495
2496 i = 0;
2497 if (except >= 1) {
2498 int sig;
2499 p[i++] = except;
2500
2501 while ((sig = va_arg(ap, int)) >= 0)
2502 p[i++] = sig;
2503 }
2504 p[i] = -1;
2505
2506 va_end(ap);
2507
2508 r = pa_reset_sigsv(p);
2509 pa_xfree(p);
2510
2511 return r;
2512 }
2513
2514 int pa_reset_sigsv(const int except[]) {
2515 #ifndef OS_IS_WIN32
2516 int sig;
2517
2518 for (sig = 1; sig < NSIG; sig++) {
2519 pa_bool_t reset = TRUE;
2520
2521 switch (sig) {
2522 case SIGKILL:
2523 case SIGSTOP:
2524 reset = FALSE;
2525 break;
2526
2527 default: {
2528 int i;
2529
2530 for (i = 0; except[i] > 0; i++) {
2531 if (sig == except[i]) {
2532 reset = FALSE;
2533 break;
2534 }
2535 }
2536 }
2537 }
2538
2539 if (reset) {
2540 struct sigaction sa;
2541
2542 memset(&sa, 0, sizeof(sa));
2543 sa.sa_handler = SIG_DFL;
2544
2545 /* On Linux the first two RT signals are reserved by
2546 * glibc, and sigaction() will return EINVAL for them. */
2547 if ((sigaction(sig, &sa, NULL) < 0))
2548 if (errno != EINVAL)
2549 return -1;
2550 }
2551 }
2552 #endif
2553
2554 return 0;
2555 }
2556
2557 void pa_set_env(const char *key, const char *value) {
2558 pa_assert(key);
2559 pa_assert(value);
2560
2561 /* This is not thread-safe */
2562
2563 #ifdef OS_IS_WIN32
2564 SetEnvironmentVariable(key, value);
2565 #else
2566 setenv(key, value, 1);
2567 #endif
2568 }
2569
2570 void pa_set_env_and_record(const char *key, const char *value) {
2571 pa_assert(key);
2572 pa_assert(value);
2573
2574 /* This is not thread-safe */
2575
2576 pa_set_env(key, value);
2577 recorded_env = pa_strlist_prepend(recorded_env, key);
2578 }
2579
2580 void pa_unset_env_recorded(void) {
2581
2582 /* This is not thread-safe */
2583
2584 for (;;) {
2585 char *s;
2586
2587 recorded_env = pa_strlist_pop(recorded_env, &s);
2588
2589 if (!s)
2590 break;
2591
2592 #ifdef OS_IS_WIN32
2593 SetEnvironmentVariable(s, NULL);
2594 #else
2595 unsetenv(s);
2596 #endif
2597 pa_xfree(s);
2598 }
2599 }
2600
2601 pa_bool_t pa_in_system_mode(void) {
2602 const char *e;
2603
2604 if (!(e = getenv("PULSE_SYSTEM")))
2605 return FALSE;
2606
2607 return !!atoi(e);
2608 }
2609
2610 char *pa_get_user_name_malloc(void) {
2611 ssize_t k;
2612 char *u;
2613
2614 #ifdef _SC_LOGIN_NAME_MAX
2615 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2616
2617 if (k <= 0)
2618 #endif
2619 k = 32;
2620
2621 u = pa_xnew(char, k+1);
2622
2623 if (!(pa_get_user_name(u, k))) {
2624 pa_xfree(u);
2625 return NULL;
2626 }
2627
2628 return u;
2629 }
2630
2631 char *pa_get_host_name_malloc(void) {
2632 size_t l;
2633
2634 l = 100;
2635 for (;;) {
2636 char *c;
2637
2638 c = pa_xmalloc(l);
2639
2640 if (!pa_get_host_name(c, l)) {
2641
2642 if (errno != EINVAL && errno != ENAMETOOLONG)
2643 break;
2644
2645 } else if (strlen(c) < l-1) {
2646 char *u;
2647
2648 if (*c == 0) {
2649 pa_xfree(c);
2650 break;
2651 }
2652
2653 u = pa_utf8_filter(c);
2654 pa_xfree(c);
2655 return u;
2656 }
2657
2658 /* Hmm, the hostname is as long the space we offered the
2659 * function, we cannot know if it fully fit in, so let's play
2660 * safe and retry. */
2661
2662 pa_xfree(c);
2663 l *= 2;
2664 }
2665
2666 return NULL;
2667 }
2668
2669 char *pa_machine_id(void) {
2670 FILE *f;
2671 char *h;
2672
2673 /* The returned value is supposed be some kind of ascii identifier
2674 * that is unique and stable across reboots. */
2675
2676 /* First we try the D-Bus UUID, which is the best option we have,
2677 * since it fits perfectly our needs and is not as volatile as the
2678 * hostname which might be set from dhcp. */
2679
2680 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r"))) {
2681 char ln[34] = "", *r;
2682
2683 r = fgets(ln, sizeof(ln)-1, f);
2684 fclose(f);
2685
2686 pa_strip_nl(ln);
2687
2688 if (r && ln[0])
2689 return pa_utf8_filter(ln);
2690 }
2691
2692 if ((h = pa_get_host_name_malloc()))
2693 return h;
2694
2695 #ifndef OS_IS_WIN32
2696 /* If no hostname was set we use the POSIX hostid. It's usually
2697 * the IPv4 address. Might not be that stable. */
2698 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2699 #else
2700 return NULL;
2701 #endif
2702 }
2703
2704 char *pa_session_id(void) {
2705 const char *e;
2706
2707 if (!(e = getenv("XDG_SESSION_COOKIE")))
2708 return NULL;
2709
2710 return pa_utf8_filter(e);
2711 }
2712
2713 char *pa_uname_string(void) {
2714 #ifdef HAVE_UNAME
2715 struct utsname u;
2716
2717 pa_assert_se(uname(&u) >= 0);
2718
2719 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2720 #endif
2721 #ifdef OS_IS_WIN32
2722 OSVERSIONINFO i;
2723
2724 pa_zero(i);
2725 i.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2726 pa_assert_se(GetVersionEx(&i));
2727
2728 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i.dwMajorVersion, i.dwMinorVersion, i.dwBuildNumber, i.szCSDVersion);
2729 #endif
2730 }
2731
2732 #ifdef HAVE_VALGRIND_MEMCHECK_H
2733 pa_bool_t pa_in_valgrind(void) {
2734 static int b = 0;
2735
2736 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2737 * here instead of really checking whether we run in valgrind or
2738 * not. */
2739
2740 if (b < 1)
2741 b = getenv("VALGRIND") ? 2 : 1;
2742
2743 return b > 1;
2744 }
2745 #endif
2746
2747 unsigned pa_gcd(unsigned a, unsigned b) {
2748
2749 while (b > 0) {
2750 unsigned t = b;
2751 b = a % b;
2752 a = t;
2753 }
2754
2755 return a;
2756 }
2757
2758 void pa_reduce(unsigned *num, unsigned *den) {
2759
2760 unsigned gcd = pa_gcd(*num, *den);
2761
2762 if (gcd <= 0)
2763 return;
2764
2765 *num /= gcd;
2766 *den /= gcd;
2767
2768 pa_assert(pa_gcd(*num, *den) == 1);
2769 }
2770
2771 unsigned pa_ncpus(void) {
2772 long ncpus;
2773
2774 #ifdef _SC_NPROCESSORS_CONF
2775 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2776 #else
2777 ncpus = 1;
2778 #endif
2779
2780 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2781 }
2782
2783 char *pa_replace(const char*s, const char*a, const char *b) {
2784 pa_strbuf *sb;
2785 size_t an;
2786
2787 pa_assert(s);
2788 pa_assert(a);
2789 pa_assert(b);
2790
2791 an = strlen(a);
2792 sb = pa_strbuf_new();
2793
2794 for (;;) {
2795 const char *p;
2796
2797 if (!(p = strstr(s, a)))
2798 break;
2799
2800 pa_strbuf_putsn(sb, s, p-s);
2801 pa_strbuf_puts(sb, b);
2802 s = p + an;
2803 }
2804
2805 pa_strbuf_puts(sb, s);
2806
2807 return pa_strbuf_tostring_free(sb);
2808 }
2809
2810 char *pa_escape(const char *p, const char *chars) {
2811 const char *s;
2812 const char *c;
2813 pa_strbuf *buf = pa_strbuf_new();
2814
2815 for (s = p; *s; ++s) {
2816 if (*s == '\\')
2817 pa_strbuf_putc(buf, '\\');
2818 else if (chars) {
2819 for (c = chars; *c; ++c) {
2820 if (*s == *c) {
2821 pa_strbuf_putc(buf, '\\');
2822 break;
2823 }
2824 }
2825 }
2826 pa_strbuf_putc(buf, *s);
2827 }
2828
2829 return pa_strbuf_tostring_free(buf);
2830 }
2831
2832 char *pa_unescape(char *p) {
2833 char *s, *d;
2834 pa_bool_t escaped = FALSE;
2835
2836 for (s = p, d = p; *s; s++) {
2837 if (!escaped && *s == '\\') {
2838 escaped = TRUE;
2839 continue;
2840 }
2841
2842 *(d++) = *s;
2843 escaped = FALSE;
2844 }
2845
2846 *d = 0;
2847
2848 return p;
2849 }
2850
2851 char *pa_realpath(const char *path) {
2852 char *t;
2853 pa_assert(path);
2854
2855 /* We want only abolsute paths */
2856 if (path[0] != '/') {
2857 errno = EINVAL;
2858 return NULL;
2859 }
2860
2861 #if defined(__GLIBC__) || defined(__APPLE__)
2862 {
2863 char *r;
2864
2865 if (!(r = realpath(path, NULL)))
2866 return NULL;
2867
2868 /* We copy this here in case our pa_xmalloc() is not
2869 * implemented on top of libc malloc() */
2870 t = pa_xstrdup(r);
2871 pa_xfree(r);
2872 }
2873 #elif defined(PATH_MAX)
2874 {
2875 char *path_buf;
2876 path_buf = pa_xmalloc(PATH_MAX);
2877
2878 #if defined(OS_IS_WIN32)
2879 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2880 pa_xfree(path_buf);
2881 return NULL;
2882 }
2883 #else
2884 if (!(t = realpath(path, path_buf))) {
2885 pa_xfree(path_buf);
2886 return NULL;
2887 }
2888 #endif
2889 }
2890 #else
2891 #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."
2892 #endif
2893
2894 return t;
2895 }
2896
2897 void pa_disable_sigpipe(void) {
2898
2899 #ifdef SIGPIPE
2900 struct sigaction sa;
2901
2902 pa_zero(sa);
2903
2904 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2905 pa_log("sigaction(): %s", pa_cstrerror(errno));
2906 return;
2907 }
2908
2909 sa.sa_handler = SIG_IGN;
2910
2911 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2912 pa_log("sigaction(): %s", pa_cstrerror(errno));
2913 return;
2914 }
2915 #endif
2916 }
2917
2918 void pa_xfreev(void**a) {
2919 void **p;
2920
2921 if (!a)
2922 return;
2923
2924 for (p = a; *p; p++)
2925 pa_xfree(*p);
2926
2927 pa_xfree(a);
2928 }
2929
2930 char **pa_split_spaces_strv(const char *s) {
2931 char **t, *e;
2932 unsigned i = 0, n = 8;
2933 const char *state = NULL;
2934
2935 t = pa_xnew(char*, n);
2936 while ((e = pa_split_spaces(s, &state))) {
2937 t[i++] = e;
2938
2939 if (i >= n) {
2940 n *= 2;
2941 t = pa_xrenew(char*, t, n);
2942 }
2943 }
2944
2945 if (i <= 0) {
2946 pa_xfree(t);
2947 return NULL;
2948 }
2949
2950 t[i] = NULL;
2951 return t;
2952 }
2953
2954 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2955 pa_assert(path);
2956
2957 if (pa_is_path_absolute(path))
2958 return pa_xstrdup(path);
2959
2960 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
2961 }
2962
2963 size_t pa_pipe_buf(int fd) {
2964
2965 #ifdef _PC_PIPE_BUF
2966 long n;
2967
2968 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
2969 return (size_t) n;
2970 #endif
2971
2972 #ifdef PIPE_BUF
2973 return PIPE_BUF;
2974 #else
2975 return 4096;
2976 #endif
2977 }
2978
2979 void pa_reset_personality(void) {
2980
2981 #ifdef __linux__
2982 if (personality(PER_LINUX) < 0)
2983 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
2984 #endif
2985
2986 }
2987
2988 #if defined(__linux__) && !defined(__OPTIMIZE__)
2989
2990 pa_bool_t pa_run_from_build_tree(void) {
2991 char *rp;
2992 pa_bool_t b = FALSE;
2993
2994 if ((rp = pa_readlink("/proc/self/exe"))) {
2995 b = pa_startswith(rp, PA_BUILDDIR);
2996 pa_xfree(rp);
2997 }
2998
2999 return b;
3000 }
3001
3002 #endif
3003
3004 const char *pa_get_temp_dir(void) {
3005 const char *t;
3006
3007 if ((t = getenv("TMPDIR")) &&
3008 pa_is_path_absolute(t))
3009 return t;
3010
3011 if ((t = getenv("TMP")) &&
3012 pa_is_path_absolute(t))
3013 return t;
3014
3015 if ((t = getenv("TEMP")) &&
3016 pa_is_path_absolute(t))
3017 return t;
3018
3019 if ((t = getenv("TEMPDIR")) &&
3020 pa_is_path_absolute(t))
3021 return t;
3022
3023 return "/tmp";
3024 }
3025
3026 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3027 int fd;
3028
3029 #ifdef O_NOCTTY
3030 flags |= O_NOCTTY;
3031 #endif
3032
3033 #ifdef O_CLOEXEC
3034 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3035 goto finish;
3036
3037 if (errno != EINVAL)
3038 return fd;
3039 #endif
3040
3041 if ((fd = open(fn, flags, mode)) < 0)
3042 return fd;
3043
3044 finish:
3045 /* Some implementations might simply ignore O_CLOEXEC if it is not
3046 * understood, make sure FD_CLOEXEC is enabled anyway */
3047
3048 pa_make_fd_cloexec(fd);
3049 return fd;
3050 }
3051
3052 int pa_socket_cloexec(int domain, int type, int protocol) {
3053 int fd;
3054
3055 #ifdef SOCK_CLOEXEC
3056 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3057 goto finish;
3058
3059 if (errno != EINVAL)
3060 return fd;
3061 #endif
3062
3063 if ((fd = socket(domain, type, protocol)) < 0)
3064 return fd;
3065
3066 finish:
3067 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3068 * not understood, make sure FD_CLOEXEC is enabled anyway */
3069
3070 pa_make_fd_cloexec(fd);
3071 return fd;
3072 }
3073
3074 int pa_pipe_cloexec(int pipefd[2]) {
3075 int r;
3076
3077 #ifdef HAVE_PIPE2
3078 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3079 goto finish;
3080
3081 if (errno != EINVAL && errno != ENOSYS)
3082 return r;
3083
3084 #endif
3085
3086 if ((r = pipe(pipefd)) < 0)
3087 return r;
3088
3089 finish:
3090 pa_make_fd_cloexec(pipefd[0]);
3091 pa_make_fd_cloexec(pipefd[1]);
3092
3093 return 0;
3094 }
3095
3096 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3097 int fd;
3098
3099 #ifdef HAVE_ACCEPT4
3100 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3101 goto finish;
3102
3103 if (errno != EINVAL && errno != ENOSYS)
3104 return fd;
3105
3106 #endif
3107
3108 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3109 return fd;
3110
3111 finish:
3112 pa_make_fd_cloexec(fd);
3113 return fd;
3114 }
3115
3116 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3117 FILE *f;
3118 char *m;
3119
3120 m = pa_sprintf_malloc("%se", mode);
3121
3122 errno = 0;
3123 if ((f = fopen(path, m))) {
3124 pa_xfree(m);
3125 goto finish;
3126 }
3127
3128 pa_xfree(m);
3129
3130 if (errno != EINVAL)
3131 return NULL;
3132
3133 if (!(f = fopen(path, mode)))
3134 return NULL;
3135
3136 finish:
3137 pa_make_fd_cloexec(fileno(f));
3138 return f;
3139 }
3140
3141 void pa_nullify_stdfds(void) {
3142
3143 #ifndef OS_IS_WIN32
3144 pa_close(STDIN_FILENO);
3145 pa_close(STDOUT_FILENO);
3146 pa_close(STDERR_FILENO);
3147
3148 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3149 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3150 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3151 #else
3152 FreeConsole();
3153 #endif
3154
3155 }
3156
3157 char *pa_read_line_from_file(const char *fn) {
3158 FILE *f;
3159 char ln[256] = "", *r;
3160
3161 if (!(f = pa_fopen_cloexec(fn, "r")))
3162 return NULL;
3163
3164 r = fgets(ln, sizeof(ln)-1, f);
3165 fclose(f);
3166
3167 if (!r) {
3168 errno = EIO;
3169 return NULL;
3170 }
3171
3172 pa_strip_nl(ln);
3173 return pa_xstrdup(ln);
3174 }
3175
3176 pa_bool_t pa_running_in_vm(void) {
3177
3178 #if defined(__i386__) || defined(__x86_64__)
3179
3180 /* Both CPUID and DMI are x86 specific interfaces... */
3181
3182 uint32_t eax = 0x40000000;
3183 union {
3184 uint32_t sig32[3];
3185 char text[13];
3186 } sig;
3187
3188 #ifdef __linux__
3189 const char *const dmi_vendors[] = {
3190 "/sys/class/dmi/id/sys_vendor",
3191 "/sys/class/dmi/id/board_vendor",
3192 "/sys/class/dmi/id/bios_vendor"
3193 };
3194
3195 unsigned i;
3196
3197 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3198 char *s;
3199
3200 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3201
3202 if (pa_startswith(s, "QEMU") ||
3203 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3204 pa_startswith(s, "VMware") ||
3205 pa_startswith(s, "VMW") ||
3206 pa_startswith(s, "Microsoft Corporation") ||
3207 pa_startswith(s, "innotek GmbH") ||
3208 pa_startswith(s, "Xen")) {
3209
3210 pa_xfree(s);
3211 return TRUE;
3212 }
3213
3214 pa_xfree(s);
3215 }
3216 }
3217
3218 #endif
3219
3220 /* http://lwn.net/Articles/301888/ */
3221 pa_zero(sig);
3222
3223 __asm__ __volatile__ (
3224 /* ebx/rbx is being used for PIC! */
3225 " push %%"PA_REG_b" \n\t"
3226 " cpuid \n\t"
3227 " mov %%ebx, %1 \n\t"
3228 " pop %%"PA_REG_b" \n\t"
3229
3230 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3231 : "0" (eax)
3232 );
3233
3234 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3235 pa_streq(sig.text, "KVMKVMKVM") ||
3236 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3237 pa_streq(sig.text, "VMwareVMware") ||
3238 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3239 pa_streq(sig.text, "Microsoft Hv"))
3240 return TRUE;
3241
3242 #endif
3243
3244 return FALSE;
3245 }