]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
core: Look up /etc/machine-id if D-Bus machine-id is not found
[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;
1984
1985 if (pa_is_path_absolute(fn))
1986 return pa_xstrdup(fn);
1987
1988 if (!rtp)
1989 return NULL;
1990
1991 if (prependmid) {
1992 char *mid;
1993
1994 if (!(mid = pa_machine_id())) {
1995 pa_xfree(rtp);
1996 return NULL;
1997 }
1998
1999 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
2000 pa_xfree(mid);
2001 } else
2002 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
2003
2004 pa_xfree(rtp);
2005 return r;
2006 } else
2007 return rtp;
2008 }
2009
2010 char *pa_runtime_path(const char *fn) {
2011 return get_path(fn, FALSE, TRUE);
2012 }
2013
2014 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
2015 return get_path(fn, appendmid, FALSE);
2016 }
2017
2018 /* Convert the string s to a signed integer in *ret_i */
2019 int pa_atoi(const char *s, int32_t *ret_i) {
2020 long l;
2021
2022 pa_assert(s);
2023 pa_assert(ret_i);
2024
2025 if (pa_atol(s, &l) < 0)
2026 return -1;
2027
2028 if ((int32_t) l != l) {
2029 errno = ERANGE;
2030 return -1;
2031 }
2032
2033 *ret_i = (int32_t) l;
2034
2035 return 0;
2036 }
2037
2038 /* Convert the string s to an unsigned integer in *ret_u */
2039 int pa_atou(const char *s, uint32_t *ret_u) {
2040 char *x = NULL;
2041 unsigned long l;
2042
2043 pa_assert(s);
2044 pa_assert(ret_u);
2045
2046 errno = 0;
2047 l = strtoul(s, &x, 0);
2048
2049 if (!x || *x || errno) {
2050 if (!errno)
2051 errno = EINVAL;
2052 return -1;
2053 }
2054
2055 if ((uint32_t) l != l) {
2056 errno = ERANGE;
2057 return -1;
2058 }
2059
2060 *ret_u = (uint32_t) l;
2061
2062 return 0;
2063 }
2064
2065 /* Convert the string s to a signed long integer in *ret_l. */
2066 int pa_atol(const char *s, long *ret_l) {
2067 char *x = NULL;
2068 long l;
2069
2070 pa_assert(s);
2071 pa_assert(ret_l);
2072
2073 errno = 0;
2074 l = strtol(s, &x, 0);
2075
2076 if (!x || *x || errno) {
2077 if (!errno)
2078 errno = EINVAL;
2079 return -1;
2080 }
2081
2082 *ret_l = l;
2083
2084 return 0;
2085 }
2086
2087 #ifdef HAVE_STRTOF_L
2088 static locale_t c_locale = NULL;
2089
2090 static void c_locale_destroy(void) {
2091 freelocale(c_locale);
2092 }
2093 #endif
2094
2095 int pa_atod(const char *s, double *ret_d) {
2096 char *x = NULL;
2097 double f;
2098
2099 pa_assert(s);
2100 pa_assert(ret_d);
2101
2102 /* This should be locale independent */
2103
2104 #ifdef HAVE_STRTOF_L
2105
2106 PA_ONCE_BEGIN {
2107
2108 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2109 atexit(c_locale_destroy);
2110
2111 } PA_ONCE_END;
2112
2113 if (c_locale) {
2114 errno = 0;
2115 f = strtod_l(s, &x, c_locale);
2116 } else
2117 #endif
2118 {
2119 errno = 0;
2120 f = strtod(s, &x);
2121 }
2122
2123 if (!x || *x || errno) {
2124 if (!errno)
2125 errno = EINVAL;
2126 return -1;
2127 }
2128
2129 *ret_d = f;
2130
2131 return 0;
2132 }
2133
2134 /* Same as snprintf, but guarantees NUL-termination on every platform */
2135 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2136 size_t ret;
2137 va_list ap;
2138
2139 pa_assert(str);
2140 pa_assert(size > 0);
2141 pa_assert(format);
2142
2143 va_start(ap, format);
2144 ret = pa_vsnprintf(str, size, format, ap);
2145 va_end(ap);
2146
2147 return ret;
2148 }
2149
2150 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2151 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2152 int ret;
2153
2154 pa_assert(str);
2155 pa_assert(size > 0);
2156 pa_assert(format);
2157
2158 ret = vsnprintf(str, size, format, ap);
2159
2160 str[size-1] = 0;
2161
2162 if (ret < 0)
2163 return strlen(str);
2164
2165 if ((size_t) ret > size-1)
2166 return size-1;
2167
2168 return (size_t) ret;
2169 }
2170
2171 /* Truncate the specified string, but guarantee that the string
2172 * returned still validates as UTF8 */
2173 char *pa_truncate_utf8(char *c, size_t l) {
2174 pa_assert(c);
2175 pa_assert(pa_utf8_valid(c));
2176
2177 if (strlen(c) <= l)
2178 return c;
2179
2180 c[l] = 0;
2181
2182 while (l > 0 && !pa_utf8_valid(c))
2183 c[--l] = 0;
2184
2185 return c;
2186 }
2187
2188 char *pa_getcwd(void) {
2189 size_t l = 128;
2190
2191 for (;;) {
2192 char *p = pa_xmalloc(l);
2193 if (getcwd(p, l))
2194 return p;
2195
2196 if (errno != ERANGE)
2197 return NULL;
2198
2199 pa_xfree(p);
2200 l *= 2;
2201 }
2202 }
2203
2204 void *pa_will_need(const void *p, size_t l) {
2205 #ifdef RLIMIT_MEMLOCK
2206 struct rlimit rlim;
2207 #endif
2208 const void *a;
2209 size_t size;
2210 int r = ENOTSUP;
2211 size_t bs;
2212
2213 pa_assert(p);
2214 pa_assert(l > 0);
2215
2216 a = PA_PAGE_ALIGN_PTR(p);
2217 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2218
2219 #ifdef HAVE_POSIX_MADVISE
2220 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2221 pa_log_debug("posix_madvise() worked fine!");
2222 return (void*) p;
2223 }
2224 #endif
2225
2226 /* Most likely the memory was not mmap()ed from a file and thus
2227 * madvise() didn't work, so let's misuse mlock() do page this
2228 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2229 * inviting, the man page of mlock() tells us: "All pages that
2230 * contain a part of the specified address range are guaranteed to
2231 * be resident in RAM when the call returns successfully." */
2232
2233 #ifdef RLIMIT_MEMLOCK
2234 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2235
2236 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2237 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));
2238 errno = EPERM;
2239 return (void*) p;
2240 }
2241
2242 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2243 #else
2244 bs = PA_PAGE_SIZE*4;
2245 #endif
2246
2247 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2248
2249 #ifdef HAVE_MLOCK
2250 while (size > 0 && bs > 0) {
2251
2252 if (bs > size)
2253 bs = size;
2254
2255 if (mlock(a, bs) < 0) {
2256 bs = PA_PAGE_ALIGN(bs / 2);
2257 continue;
2258 }
2259
2260 pa_assert_se(munlock(a, bs) == 0);
2261
2262 a = (const uint8_t*) a + bs;
2263 size -= bs;
2264 }
2265 #endif
2266
2267 if (bs <= 0)
2268 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2269 else
2270 pa_log_debug("mlock() worked fine!");
2271
2272 return (void*) p;
2273 }
2274
2275 void pa_close_pipe(int fds[2]) {
2276 pa_assert(fds);
2277
2278 if (fds[0] >= 0)
2279 pa_assert_se(pa_close(fds[0]) == 0);
2280
2281 if (fds[1] >= 0)
2282 pa_assert_se(pa_close(fds[1]) == 0);
2283
2284 fds[0] = fds[1] = -1;
2285 }
2286
2287 char *pa_readlink(const char *p) {
2288 #ifdef HAVE_READLINK
2289 size_t l = 100;
2290
2291 for (;;) {
2292 char *c;
2293 ssize_t n;
2294
2295 c = pa_xmalloc(l);
2296
2297 if ((n = readlink(p, c, l-1)) < 0) {
2298 pa_xfree(c);
2299 return NULL;
2300 }
2301
2302 if ((size_t) n < l-1) {
2303 c[n] = 0;
2304 return c;
2305 }
2306
2307 pa_xfree(c);
2308 l *= 2;
2309 }
2310 #else
2311 return NULL;
2312 #endif
2313 }
2314
2315 int pa_close_all(int except_fd, ...) {
2316 va_list ap;
2317 unsigned n = 0, i;
2318 int r, *p;
2319
2320 va_start(ap, except_fd);
2321
2322 if (except_fd >= 0)
2323 for (n = 1; va_arg(ap, int) >= 0; n++)
2324 ;
2325
2326 va_end(ap);
2327
2328 p = pa_xnew(int, n+1);
2329
2330 va_start(ap, except_fd);
2331
2332 i = 0;
2333 if (except_fd >= 0) {
2334 int fd;
2335 p[i++] = except_fd;
2336
2337 while ((fd = va_arg(ap, int)) >= 0)
2338 p[i++] = fd;
2339 }
2340 p[i] = -1;
2341
2342 va_end(ap);
2343
2344 r = pa_close_allv(p);
2345 pa_xfree(p);
2346
2347 return r;
2348 }
2349
2350 int pa_close_allv(const int except_fds[]) {
2351 #ifndef OS_IS_WIN32
2352 struct rlimit rl;
2353 int maxfd, fd;
2354
2355 #ifdef __linux__
2356 int saved_errno;
2357 DIR *d;
2358
2359 if ((d = opendir("/proc/self/fd"))) {
2360
2361 struct dirent *de;
2362
2363 while ((de = readdir(d))) {
2364 pa_bool_t found;
2365 long l;
2366 char *e = NULL;
2367 int i;
2368
2369 if (de->d_name[0] == '.')
2370 continue;
2371
2372 errno = 0;
2373 l = strtol(de->d_name, &e, 10);
2374 if (errno != 0 || !e || *e) {
2375 closedir(d);
2376 errno = EINVAL;
2377 return -1;
2378 }
2379
2380 fd = (int) l;
2381
2382 if ((long) fd != l) {
2383 closedir(d);
2384 errno = EINVAL;
2385 return -1;
2386 }
2387
2388 if (fd < 3)
2389 continue;
2390
2391 if (fd == dirfd(d))
2392 continue;
2393
2394 found = FALSE;
2395 for (i = 0; except_fds[i] >= 0; i++)
2396 if (except_fds[i] == fd) {
2397 found = TRUE;
2398 break;
2399 }
2400
2401 if (found)
2402 continue;
2403
2404 if (pa_close(fd) < 0) {
2405 saved_errno = errno;
2406 closedir(d);
2407 errno = saved_errno;
2408
2409 return -1;
2410 }
2411 }
2412
2413 closedir(d);
2414 return 0;
2415 }
2416
2417 #endif
2418
2419 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2420 maxfd = (int) rl.rlim_max;
2421 else
2422 maxfd = sysconf(_SC_OPEN_MAX);
2423
2424 for (fd = 3; fd < maxfd; fd++) {
2425 int i;
2426 pa_bool_t found;
2427
2428 found = FALSE;
2429 for (i = 0; except_fds[i] >= 0; i++)
2430 if (except_fds[i] == fd) {
2431 found = TRUE;
2432 break;
2433 }
2434
2435 if (found)
2436 continue;
2437
2438 if (pa_close(fd) < 0 && errno != EBADF)
2439 return -1;
2440 }
2441 #endif /* !OS_IS_WIN32 */
2442
2443 return 0;
2444 }
2445
2446 int pa_unblock_sigs(int except, ...) {
2447 va_list ap;
2448 unsigned n = 0, i;
2449 int r, *p;
2450
2451 va_start(ap, except);
2452
2453 if (except >= 1)
2454 for (n = 1; va_arg(ap, int) >= 0; n++)
2455 ;
2456
2457 va_end(ap);
2458
2459 p = pa_xnew(int, n+1);
2460
2461 va_start(ap, except);
2462
2463 i = 0;
2464 if (except >= 1) {
2465 int sig;
2466 p[i++] = except;
2467
2468 while ((sig = va_arg(ap, int)) >= 0)
2469 p[i++] = sig;
2470 }
2471 p[i] = -1;
2472
2473 va_end(ap);
2474
2475 r = pa_unblock_sigsv(p);
2476 pa_xfree(p);
2477
2478 return r;
2479 }
2480
2481 int pa_unblock_sigsv(const int except[]) {
2482 #ifndef OS_IS_WIN32
2483 int i;
2484 sigset_t ss;
2485
2486 if (sigemptyset(&ss) < 0)
2487 return -1;
2488
2489 for (i = 0; except[i] > 0; i++)
2490 if (sigaddset(&ss, except[i]) < 0)
2491 return -1;
2492
2493 return sigprocmask(SIG_SETMASK, &ss, NULL);
2494 #else
2495 return 0;
2496 #endif
2497 }
2498
2499 int pa_reset_sigs(int except, ...) {
2500 va_list ap;
2501 unsigned n = 0, i;
2502 int *p, r;
2503
2504 va_start(ap, except);
2505
2506 if (except >= 1)
2507 for (n = 1; va_arg(ap, int) >= 0; n++)
2508 ;
2509
2510 va_end(ap);
2511
2512 p = pa_xnew(int, n+1);
2513
2514 va_start(ap, except);
2515
2516 i = 0;
2517 if (except >= 1) {
2518 int sig;
2519 p[i++] = except;
2520
2521 while ((sig = va_arg(ap, int)) >= 0)
2522 p[i++] = sig;
2523 }
2524 p[i] = -1;
2525
2526 va_end(ap);
2527
2528 r = pa_reset_sigsv(p);
2529 pa_xfree(p);
2530
2531 return r;
2532 }
2533
2534 int pa_reset_sigsv(const int except[]) {
2535 #ifndef OS_IS_WIN32
2536 int sig;
2537
2538 for (sig = 1; sig < NSIG; sig++) {
2539 pa_bool_t reset = TRUE;
2540
2541 switch (sig) {
2542 case SIGKILL:
2543 case SIGSTOP:
2544 reset = FALSE;
2545 break;
2546
2547 default: {
2548 int i;
2549
2550 for (i = 0; except[i] > 0; i++) {
2551 if (sig == except[i]) {
2552 reset = FALSE;
2553 break;
2554 }
2555 }
2556 }
2557 }
2558
2559 if (reset) {
2560 struct sigaction sa;
2561
2562 memset(&sa, 0, sizeof(sa));
2563 sa.sa_handler = SIG_DFL;
2564
2565 /* On Linux the first two RT signals are reserved by
2566 * glibc, and sigaction() will return EINVAL for them. */
2567 if ((sigaction(sig, &sa, NULL) < 0))
2568 if (errno != EINVAL)
2569 return -1;
2570 }
2571 }
2572 #endif
2573
2574 return 0;
2575 }
2576
2577 void pa_set_env(const char *key, const char *value) {
2578 pa_assert(key);
2579 pa_assert(value);
2580
2581 /* This is not thread-safe */
2582
2583 #ifdef OS_IS_WIN32
2584 SetEnvironmentVariable(key, value);
2585 #else
2586 setenv(key, value, 1);
2587 #endif
2588 }
2589
2590 void pa_set_env_and_record(const char *key, const char *value) {
2591 pa_assert(key);
2592 pa_assert(value);
2593
2594 /* This is not thread-safe */
2595
2596 pa_set_env(key, value);
2597 recorded_env = pa_strlist_prepend(recorded_env, key);
2598 }
2599
2600 void pa_unset_env_recorded(void) {
2601
2602 /* This is not thread-safe */
2603
2604 for (;;) {
2605 char *s;
2606
2607 recorded_env = pa_strlist_pop(recorded_env, &s);
2608
2609 if (!s)
2610 break;
2611
2612 #ifdef OS_IS_WIN32
2613 SetEnvironmentVariable(s, NULL);
2614 #else
2615 unsetenv(s);
2616 #endif
2617 pa_xfree(s);
2618 }
2619 }
2620
2621 pa_bool_t pa_in_system_mode(void) {
2622 const char *e;
2623
2624 if (!(e = getenv("PULSE_SYSTEM")))
2625 return FALSE;
2626
2627 return !!atoi(e);
2628 }
2629
2630 /* Checks a whitespace-separated list of words in haystack for needle */
2631 pa_bool_t pa_str_in_list_spaces(const char *haystack, const char *needle) {
2632 char *s;
2633 const char *state = NULL;
2634
2635 if (!haystack || !needle)
2636 return FALSE;
2637
2638 while ((s = pa_split_spaces(haystack, &state))) {
2639 if (pa_streq(needle, s)) {
2640 pa_xfree(s);
2641 return TRUE;
2642 }
2643
2644 pa_xfree(s);
2645 }
2646
2647 return FALSE;
2648 }
2649
2650 char *pa_get_user_name_malloc(void) {
2651 ssize_t k;
2652 char *u;
2653
2654 #ifdef _SC_LOGIN_NAME_MAX
2655 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2656
2657 if (k <= 0)
2658 #endif
2659 k = 32;
2660
2661 u = pa_xnew(char, k+1);
2662
2663 if (!(pa_get_user_name(u, k))) {
2664 pa_xfree(u);
2665 return NULL;
2666 }
2667
2668 return u;
2669 }
2670
2671 char *pa_get_host_name_malloc(void) {
2672 size_t l;
2673
2674 l = 100;
2675 for (;;) {
2676 char *c;
2677
2678 c = pa_xmalloc(l);
2679
2680 if (!pa_get_host_name(c, l)) {
2681
2682 if (errno != EINVAL && errno != ENAMETOOLONG)
2683 break;
2684
2685 } else if (strlen(c) < l-1) {
2686 char *u;
2687
2688 if (*c == 0) {
2689 pa_xfree(c);
2690 break;
2691 }
2692
2693 u = pa_utf8_filter(c);
2694 pa_xfree(c);
2695 return u;
2696 }
2697
2698 /* Hmm, the hostname is as long the space we offered the
2699 * function, we cannot know if it fully fit in, so let's play
2700 * safe and retry. */
2701
2702 pa_xfree(c);
2703 l *= 2;
2704 }
2705
2706 return NULL;
2707 }
2708
2709 char *pa_machine_id(void) {
2710 FILE *f;
2711 char *h;
2712
2713 /* The returned value is supposed be some kind of ascii identifier
2714 * that is unique and stable across reboots. */
2715
2716 /* First we try the D-Bus UUID, which is the best option we have,
2717 * since it fits perfectly our needs and is not as volatile as the
2718 * hostname which might be set from dhcp. */
2719
2720 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r")) ||
2721 (f = pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK, "r"))) {
2722 char ln[34] = "", *r;
2723
2724 r = fgets(ln, sizeof(ln)-1, f);
2725 fclose(f);
2726
2727 pa_strip_nl(ln);
2728
2729 if (r && ln[0])
2730 return pa_utf8_filter(ln);
2731 }
2732
2733 if ((h = pa_get_host_name_malloc()))
2734 return h;
2735
2736 #ifndef OS_IS_WIN32
2737 /* If no hostname was set we use the POSIX hostid. It's usually
2738 * the IPv4 address. Might not be that stable. */
2739 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid);
2740 #else
2741 return NULL;
2742 #endif
2743 }
2744
2745 char *pa_session_id(void) {
2746 const char *e;
2747
2748 if (!(e = getenv("XDG_SESSION_COOKIE")))
2749 return NULL;
2750
2751 return pa_utf8_filter(e);
2752 }
2753
2754 char *pa_uname_string(void) {
2755 #ifdef HAVE_UNAME
2756 struct utsname u;
2757
2758 pa_assert_se(uname(&u) >= 0);
2759
2760 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2761 #endif
2762 #ifdef OS_IS_WIN32
2763 OSVERSIONINFO i;
2764
2765 pa_zero(i);
2766 i.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2767 pa_assert_se(GetVersionEx(&i));
2768
2769 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i.dwMajorVersion, i.dwMinorVersion, i.dwBuildNumber, i.szCSDVersion);
2770 #endif
2771 }
2772
2773 #ifdef HAVE_VALGRIND_MEMCHECK_H
2774 pa_bool_t pa_in_valgrind(void) {
2775 static int b = 0;
2776
2777 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2778 * here instead of really checking whether we run in valgrind or
2779 * not. */
2780
2781 if (b < 1)
2782 b = getenv("VALGRIND") ? 2 : 1;
2783
2784 return b > 1;
2785 }
2786 #endif
2787
2788 unsigned pa_gcd(unsigned a, unsigned b) {
2789
2790 while (b > 0) {
2791 unsigned t = b;
2792 b = a % b;
2793 a = t;
2794 }
2795
2796 return a;
2797 }
2798
2799 void pa_reduce(unsigned *num, unsigned *den) {
2800
2801 unsigned gcd = pa_gcd(*num, *den);
2802
2803 if (gcd <= 0)
2804 return;
2805
2806 *num /= gcd;
2807 *den /= gcd;
2808
2809 pa_assert(pa_gcd(*num, *den) == 1);
2810 }
2811
2812 unsigned pa_ncpus(void) {
2813 long ncpus;
2814
2815 #ifdef _SC_NPROCESSORS_CONF
2816 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2817 #else
2818 ncpus = 1;
2819 #endif
2820
2821 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2822 }
2823
2824 char *pa_replace(const char*s, const char*a, const char *b) {
2825 pa_strbuf *sb;
2826 size_t an;
2827
2828 pa_assert(s);
2829 pa_assert(a);
2830 pa_assert(b);
2831
2832 an = strlen(a);
2833 sb = pa_strbuf_new();
2834
2835 for (;;) {
2836 const char *p;
2837
2838 if (!(p = strstr(s, a)))
2839 break;
2840
2841 pa_strbuf_putsn(sb, s, p-s);
2842 pa_strbuf_puts(sb, b);
2843 s = p + an;
2844 }
2845
2846 pa_strbuf_puts(sb, s);
2847
2848 return pa_strbuf_tostring_free(sb);
2849 }
2850
2851 char *pa_escape(const char *p, const char *chars) {
2852 const char *s;
2853 const char *c;
2854 pa_strbuf *buf = pa_strbuf_new();
2855
2856 for (s = p; *s; ++s) {
2857 if (*s == '\\')
2858 pa_strbuf_putc(buf, '\\');
2859 else if (chars) {
2860 for (c = chars; *c; ++c) {
2861 if (*s == *c) {
2862 pa_strbuf_putc(buf, '\\');
2863 break;
2864 }
2865 }
2866 }
2867 pa_strbuf_putc(buf, *s);
2868 }
2869
2870 return pa_strbuf_tostring_free(buf);
2871 }
2872
2873 char *pa_unescape(char *p) {
2874 char *s, *d;
2875 pa_bool_t escaped = FALSE;
2876
2877 for (s = p, d = p; *s; s++) {
2878 if (!escaped && *s == '\\') {
2879 escaped = TRUE;
2880 continue;
2881 }
2882
2883 *(d++) = *s;
2884 escaped = FALSE;
2885 }
2886
2887 *d = 0;
2888
2889 return p;
2890 }
2891
2892 char *pa_realpath(const char *path) {
2893 char *t;
2894 pa_assert(path);
2895
2896 /* We want only absolute paths */
2897 if (path[0] != '/') {
2898 errno = EINVAL;
2899 return NULL;
2900 }
2901
2902 #if defined(__GLIBC__) || defined(__APPLE__)
2903 {
2904 char *r;
2905
2906 if (!(r = realpath(path, NULL)))
2907 return NULL;
2908
2909 /* We copy this here in case our pa_xmalloc() is not
2910 * implemented on top of libc malloc() */
2911 t = pa_xstrdup(r);
2912 pa_xfree(r);
2913 }
2914 #elif defined(PATH_MAX)
2915 {
2916 char *path_buf;
2917 path_buf = pa_xmalloc(PATH_MAX);
2918
2919 #if defined(OS_IS_WIN32)
2920 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2921 pa_xfree(path_buf);
2922 return NULL;
2923 }
2924 #else
2925 if (!(t = realpath(path, path_buf))) {
2926 pa_xfree(path_buf);
2927 return NULL;
2928 }
2929 #endif
2930 }
2931 #else
2932 #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."
2933 #endif
2934
2935 return t;
2936 }
2937
2938 void pa_disable_sigpipe(void) {
2939
2940 #ifdef SIGPIPE
2941 struct sigaction sa;
2942
2943 pa_zero(sa);
2944
2945 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
2946 pa_log("sigaction(): %s", pa_cstrerror(errno));
2947 return;
2948 }
2949
2950 sa.sa_handler = SIG_IGN;
2951
2952 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
2953 pa_log("sigaction(): %s", pa_cstrerror(errno));
2954 return;
2955 }
2956 #endif
2957 }
2958
2959 void pa_xfreev(void**a) {
2960 void **p;
2961
2962 if (!a)
2963 return;
2964
2965 for (p = a; *p; p++)
2966 pa_xfree(*p);
2967
2968 pa_xfree(a);
2969 }
2970
2971 char **pa_split_spaces_strv(const char *s) {
2972 char **t, *e;
2973 unsigned i = 0, n = 8;
2974 const char *state = NULL;
2975
2976 t = pa_xnew(char*, n);
2977 while ((e = pa_split_spaces(s, &state))) {
2978 t[i++] = e;
2979
2980 if (i >= n) {
2981 n *= 2;
2982 t = pa_xrenew(char*, t, n);
2983 }
2984 }
2985
2986 if (i <= 0) {
2987 pa_xfree(t);
2988 return NULL;
2989 }
2990
2991 t[i] = NULL;
2992 return t;
2993 }
2994
2995 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
2996 pa_assert(path);
2997
2998 if (pa_is_path_absolute(path))
2999 return pa_xstrdup(path);
3000
3001 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
3002 }
3003
3004 size_t pa_pipe_buf(int fd) {
3005
3006 #ifdef _PC_PIPE_BUF
3007 long n;
3008
3009 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
3010 return (size_t) n;
3011 #endif
3012
3013 #ifdef PIPE_BUF
3014 return PIPE_BUF;
3015 #else
3016 return 4096;
3017 #endif
3018 }
3019
3020 void pa_reset_personality(void) {
3021
3022 #ifdef __linux__
3023 if (personality(PER_LINUX) < 0)
3024 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
3025 #endif
3026
3027 }
3028
3029 #if defined(__linux__) && !defined(__OPTIMIZE__)
3030
3031 pa_bool_t pa_run_from_build_tree(void) {
3032 char *rp;
3033 pa_bool_t b = FALSE;
3034
3035 if ((rp = pa_readlink("/proc/self/exe"))) {
3036 b = pa_startswith(rp, PA_BUILDDIR);
3037 pa_xfree(rp);
3038 }
3039
3040 return b;
3041 }
3042
3043 #endif
3044
3045 const char *pa_get_temp_dir(void) {
3046 const char *t;
3047
3048 if ((t = getenv("TMPDIR")) &&
3049 pa_is_path_absolute(t))
3050 return t;
3051
3052 if ((t = getenv("TMP")) &&
3053 pa_is_path_absolute(t))
3054 return t;
3055
3056 if ((t = getenv("TEMP")) &&
3057 pa_is_path_absolute(t))
3058 return t;
3059
3060 if ((t = getenv("TEMPDIR")) &&
3061 pa_is_path_absolute(t))
3062 return t;
3063
3064 return "/tmp";
3065 }
3066
3067 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3068 int fd;
3069
3070 #ifdef O_NOCTTY
3071 flags |= O_NOCTTY;
3072 #endif
3073
3074 #ifdef O_CLOEXEC
3075 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3076 goto finish;
3077
3078 if (errno != EINVAL)
3079 return fd;
3080 #endif
3081
3082 if ((fd = open(fn, flags, mode)) < 0)
3083 return fd;
3084
3085 finish:
3086 /* Some implementations might simply ignore O_CLOEXEC if it is not
3087 * understood, make sure FD_CLOEXEC is enabled anyway */
3088
3089 pa_make_fd_cloexec(fd);
3090 return fd;
3091 }
3092
3093 int pa_socket_cloexec(int domain, int type, int protocol) {
3094 int fd;
3095
3096 #ifdef SOCK_CLOEXEC
3097 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3098 goto finish;
3099
3100 if (errno != EINVAL)
3101 return fd;
3102 #endif
3103
3104 if ((fd = socket(domain, type, protocol)) < 0)
3105 return fd;
3106
3107 finish:
3108 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3109 * not understood, make sure FD_CLOEXEC is enabled anyway */
3110
3111 pa_make_fd_cloexec(fd);
3112 return fd;
3113 }
3114
3115 int pa_pipe_cloexec(int pipefd[2]) {
3116 int r;
3117
3118 #ifdef HAVE_PIPE2
3119 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3120 goto finish;
3121
3122 if (errno != EINVAL && errno != ENOSYS)
3123 return r;
3124
3125 #endif
3126
3127 if ((r = pipe(pipefd)) < 0)
3128 return r;
3129
3130 finish:
3131 pa_make_fd_cloexec(pipefd[0]);
3132 pa_make_fd_cloexec(pipefd[1]);
3133
3134 return 0;
3135 }
3136
3137 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3138 int fd;
3139
3140 #ifdef HAVE_ACCEPT4
3141 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3142 goto finish;
3143
3144 if (errno != EINVAL && errno != ENOSYS)
3145 return fd;
3146
3147 #endif
3148
3149 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3150 return fd;
3151
3152 finish:
3153 pa_make_fd_cloexec(fd);
3154 return fd;
3155 }
3156
3157 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3158 FILE *f;
3159 char *m;
3160
3161 m = pa_sprintf_malloc("%se", mode);
3162
3163 errno = 0;
3164 if ((f = fopen(path, m))) {
3165 pa_xfree(m);
3166 goto finish;
3167 }
3168
3169 pa_xfree(m);
3170
3171 if (errno != EINVAL)
3172 return NULL;
3173
3174 if (!(f = fopen(path, mode)))
3175 return NULL;
3176
3177 finish:
3178 pa_make_fd_cloexec(fileno(f));
3179 return f;
3180 }
3181
3182 void pa_nullify_stdfds(void) {
3183
3184 #ifndef OS_IS_WIN32
3185 pa_close(STDIN_FILENO);
3186 pa_close(STDOUT_FILENO);
3187 pa_close(STDERR_FILENO);
3188
3189 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3190 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3191 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3192 #else
3193 FreeConsole();
3194 #endif
3195
3196 }
3197
3198 char *pa_read_line_from_file(const char *fn) {
3199 FILE *f;
3200 char ln[256] = "", *r;
3201
3202 if (!(f = pa_fopen_cloexec(fn, "r")))
3203 return NULL;
3204
3205 r = fgets(ln, sizeof(ln)-1, f);
3206 fclose(f);
3207
3208 if (!r) {
3209 errno = EIO;
3210 return NULL;
3211 }
3212
3213 pa_strip_nl(ln);
3214 return pa_xstrdup(ln);
3215 }
3216
3217 pa_bool_t pa_running_in_vm(void) {
3218
3219 #if defined(__i386__) || defined(__x86_64__)
3220
3221 /* Both CPUID and DMI are x86 specific interfaces... */
3222
3223 uint32_t eax = 0x40000000;
3224 union {
3225 uint32_t sig32[3];
3226 char text[13];
3227 } sig;
3228
3229 #ifdef __linux__
3230 const char *const dmi_vendors[] = {
3231 "/sys/class/dmi/id/sys_vendor",
3232 "/sys/class/dmi/id/board_vendor",
3233 "/sys/class/dmi/id/bios_vendor"
3234 };
3235
3236 unsigned i;
3237
3238 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3239 char *s;
3240
3241 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3242
3243 if (pa_startswith(s, "QEMU") ||
3244 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3245 pa_startswith(s, "VMware") ||
3246 pa_startswith(s, "VMW") ||
3247 pa_startswith(s, "Microsoft Corporation") ||
3248 pa_startswith(s, "innotek GmbH") ||
3249 pa_startswith(s, "Xen")) {
3250
3251 pa_xfree(s);
3252 return TRUE;
3253 }
3254
3255 pa_xfree(s);
3256 }
3257 }
3258
3259 #endif
3260
3261 /* http://lwn.net/Articles/301888/ */
3262 pa_zero(sig);
3263
3264 __asm__ __volatile__ (
3265 /* ebx/rbx is being used for PIC! */
3266 " push %%"PA_REG_b" \n\t"
3267 " cpuid \n\t"
3268 " mov %%ebx, %1 \n\t"
3269 " pop %%"PA_REG_b" \n\t"
3270
3271 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3272 : "0" (eax)
3273 );
3274
3275 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3276 pa_streq(sig.text, "KVMKVMKVM") ||
3277 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3278 pa_streq(sig.text, "VMwareVMware") ||
3279 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3280 pa_streq(sig.text, "Microsoft Hv"))
3281 return TRUE;
3282
3283 #endif
3284
3285 return FALSE;
3286 }