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