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