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