]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
e6c21beac5667178a506c1ff83b0db7107221f4a
[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_config_home(char *home) {
1400 char *t;
1401
1402 t = getenv("XDG_CONFIG_HOME");
1403 if (t)
1404 return pa_xstrdup(t);
1405
1406 return pa_sprintf_malloc("%s" PA_PATH_SEP ".config", home);
1407 }
1408
1409 static int check_ours(const char *p) {
1410 struct stat st;
1411
1412 pa_assert(p);
1413
1414 if (stat(p, &st) < 0)
1415 return -errno;
1416
1417 #ifdef HAVE_GETUID
1418 if (st.st_uid != getuid())
1419 return -EACCES;
1420 #endif
1421
1422 return 0;
1423 }
1424
1425 static char *get_pulse_home(void) {
1426 char *h, *ret, *config_home;
1427 int t;
1428
1429 h = pa_get_home_dir_malloc();
1430 if (!h) {
1431 pa_log_error("Failed to get home directory.");
1432 return NULL;
1433 }
1434
1435 t = check_ours(h);
1436 if (t < 0 && t != -ENOENT) {
1437 pa_log_error("Home directory not accessible: %s", pa_cstrerror(-t));
1438 pa_xfree(h);
1439 return NULL;
1440 }
1441
1442 /* If the old directory exists, use it. */
1443 ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1444 if (access(ret, F_OK) >= 0) {
1445 free(h);
1446 return ret;
1447 }
1448 free(ret);
1449
1450 /* Otherwise go for the XDG compliant directory. */
1451 config_home = get_config_home(h);
1452 free(h);
1453 ret = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse", config_home);
1454 free(config_home);
1455
1456 return ret;
1457 }
1458
1459 char *pa_get_state_dir(void) {
1460 char *d;
1461
1462 /* The state directory shall contain dynamic data that should be
1463 * kept across reboots, and is private to this user */
1464
1465 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1466 if (!(d = get_pulse_home()))
1467 return NULL;
1468
1469 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1470 * dir then this will break. */
1471
1472 if (pa_make_secure_dir(d, 0700U, (uid_t) -1, (gid_t) -1) < 0) {
1473 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1474 pa_xfree(d);
1475 return NULL;
1476 }
1477
1478 return d;
1479 }
1480
1481 char *pa_get_home_dir_malloc(void) {
1482 char *homedir;
1483 size_t allocated = 128;
1484
1485 for (;;) {
1486 homedir = pa_xmalloc(allocated);
1487
1488 if (!pa_get_home_dir(homedir, allocated)) {
1489 pa_xfree(homedir);
1490 return NULL;
1491 }
1492
1493 if (strlen(homedir) < allocated - 1)
1494 break;
1495
1496 pa_xfree(homedir);
1497 allocated *= 2;
1498 }
1499
1500 return homedir;
1501 }
1502
1503 char *pa_get_binary_name_malloc(void) {
1504 char *t;
1505 size_t allocated = 128;
1506
1507 for (;;) {
1508 t = pa_xmalloc(allocated);
1509
1510 if (!pa_get_binary_name(t, allocated)) {
1511 pa_xfree(t);
1512 return NULL;
1513 }
1514
1515 if (strlen(t) < allocated - 1)
1516 break;
1517
1518 pa_xfree(t);
1519 allocated *= 2;
1520 }
1521
1522 return t;
1523 }
1524
1525 static char* make_random_dir(mode_t m) {
1526 static const char table[] =
1527 "abcdefghijklmnopqrstuvwxyz"
1528 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1529 "0123456789";
1530
1531 char *fn;
1532 size_t pathlen;
1533
1534 fn = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse-XXXXXXXXXXXX", pa_get_temp_dir());
1535 pathlen = strlen(fn);
1536
1537 for (;;) {
1538 size_t i;
1539 int r;
1540 mode_t u;
1541 int saved_errno;
1542
1543 for (i = pathlen - 12; i < pathlen; i++)
1544 fn[i] = table[rand() % (sizeof(table)-1)];
1545
1546 u = umask((~m) & 0777);
1547 #ifndef OS_IS_WIN32
1548 r = mkdir(fn, m);
1549 #else
1550 r = mkdir(fn);
1551 #endif
1552
1553 saved_errno = errno;
1554 umask(u);
1555 errno = saved_errno;
1556
1557 if (r >= 0)
1558 return fn;
1559
1560 if (errno != EEXIST) {
1561 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1562 pa_xfree(fn);
1563 return NULL;
1564 }
1565 }
1566 }
1567
1568 static int make_random_dir_and_link(mode_t m, const char *k) {
1569 char *p;
1570
1571 if (!(p = make_random_dir(m)))
1572 return -1;
1573
1574 #ifdef HAVE_SYMLINK
1575 if (symlink(p, k) < 0) {
1576 int saved_errno = errno;
1577
1578 if (errno != EEXIST)
1579 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1580
1581 rmdir(p);
1582 pa_xfree(p);
1583
1584 errno = saved_errno;
1585 return -1;
1586 }
1587 #else
1588 pa_xfree(p);
1589 return -1;
1590 #endif
1591
1592 pa_xfree(p);
1593 return 0;
1594 }
1595
1596 char *pa_get_runtime_dir(void) {
1597 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1598 mode_t m;
1599
1600 /* The runtime directory shall contain dynamic data that needs NOT
1601 * to be kept across reboots and is usually private to the user,
1602 * except in system mode, where it might be accessible by other
1603 * users, too. Since we need POSIX locking and UNIX sockets in
1604 * this directory, we try XDG_RUNTIME_DIR first, and if that isn't
1605 * set create a directory in $HOME and link it to a random subdir
1606 * in /tmp, if it was not explicitly configured. */
1607
1608 m = pa_in_system_mode() ? 0755U : 0700U;
1609
1610 /* Use the explicitly configured value if it is set */
1611 d = getenv("PULSE_RUNTIME_PATH");
1612 if (d) {
1613
1614 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1615 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1616 goto fail;
1617 }
1618
1619 return pa_xstrdup(d);
1620 }
1621
1622 /* Use the XDG standard for the runtime directory. */
1623 d = getenv("XDG_RUNTIME_DIR");
1624 if (d) {
1625 k = pa_sprintf_malloc("%s" PA_PATH_SEP "pulse", d);
1626
1627 if (pa_make_secure_dir(k, m, (uid_t) -1, (gid_t) -1) < 0) {
1628 free(k);
1629 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1630 goto fail;
1631 }
1632
1633 return k;
1634 }
1635
1636 /* XDG_RUNTIME_DIR wasn't set, use the old legacy fallback */
1637 d = get_pulse_home();
1638 if (!d)
1639 goto fail;
1640
1641 if (pa_make_secure_dir(d, m, (uid_t) -1, (gid_t) -1) < 0) {
1642 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1643 pa_xfree(d);
1644 goto fail;
1645 }
1646
1647 mid = pa_machine_id();
1648 if (!mid) {
1649 pa_xfree(d);
1650 goto fail;
1651 }
1652
1653 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
1654 pa_xfree(d);
1655 pa_xfree(mid);
1656
1657 for (;;) {
1658 /* OK, first let's check if the "runtime" symlink already exists */
1659
1660 p = pa_readlink(k);
1661 if (!p) {
1662
1663 if (errno != ENOENT) {
1664 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1665 goto fail;
1666 }
1667
1668 #ifdef HAVE_SYMLINK
1669 /* Hmm, so the runtime directory didn't exist yet, so let's
1670 * create one in /tmp and symlink that to it */
1671
1672 if (make_random_dir_and_link(0700, k) < 0) {
1673
1674 /* Mhmm, maybe another process was quicker than us,
1675 * let's check if that was valid */
1676 if (errno == EEXIST)
1677 continue;
1678
1679 goto fail;
1680 }
1681 #else
1682 /* No symlink possible, so let's just create the runtime directly */
1683 if (mkdir(k) < 0)
1684 goto fail;
1685 #endif
1686
1687 return k;
1688 }
1689
1690 /* Make sure that this actually makes sense */
1691 if (!pa_is_path_absolute(p)) {
1692 pa_log_error("Path %s in link %s is not absolute.", p, k);
1693 errno = ENOENT;
1694 goto fail;
1695 }
1696
1697 /* Hmm, so this symlink is still around, make sure nobody fools us */
1698 #ifdef HAVE_LSTAT
1699 {
1700 struct stat st;
1701 if (lstat(p, &st) < 0) {
1702
1703 if (errno != ENOENT) {
1704 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1705 goto fail;
1706 }
1707
1708 } else {
1709
1710 if (S_ISDIR(st.st_mode) &&
1711 (st.st_uid == getuid()) &&
1712 ((st.st_mode & 0777) == 0700)) {
1713
1714 pa_xfree(p);
1715 return k;
1716 }
1717
1718 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1719 }
1720 }
1721 #endif
1722
1723 pa_xfree(p);
1724 p = NULL;
1725
1726 /* Hmm, so the link points to some nonexisting or invalid
1727 * dir. Let's replace it by a new link. We first create a
1728 * temporary link and then rename that to allow concurrent
1729 * execution of this function. */
1730
1731 t = pa_sprintf_malloc("%s.tmp", k);
1732
1733 if (make_random_dir_and_link(0700, t) < 0) {
1734
1735 if (errno != EEXIST) {
1736 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1737 goto fail;
1738 }
1739
1740 pa_xfree(t);
1741 t = NULL;
1742
1743 /* Hmm, someone else was quicker then us. Let's give
1744 * him some time to finish, and retry. */
1745 pa_msleep(10);
1746 continue;
1747 }
1748
1749 /* OK, we succeeded in creating the temporary symlink, so
1750 * let's rename it */
1751 if (rename(t, k) < 0) {
1752 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1753 goto fail;
1754 }
1755
1756 pa_xfree(t);
1757 return k;
1758 }
1759
1760 fail:
1761 pa_xfree(p);
1762 pa_xfree(k);
1763 pa_xfree(t);
1764
1765 return NULL;
1766 }
1767
1768 /* Try to open a configuration file. If "env" is specified, open the
1769 * value of the specified environment variable. Otherwise look for a
1770 * file "local" in the home directory or a file "global" in global
1771 * file system. If "result" is non-NULL, a pointer to a newly
1772 * allocated buffer containing the used configuration file is
1773 * stored there.*/
1774 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1775 const char *fn;
1776 FILE *f;
1777
1778 if (env && (fn = getenv(env))) {
1779 if ((f = pa_fopen_cloexec(fn, "r"))) {
1780 if (result)
1781 *result = pa_xstrdup(fn);
1782
1783 return f;
1784 }
1785
1786 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1787 return NULL;
1788 }
1789
1790 if (local) {
1791 const char *e;
1792 char *lfn;
1793 char *h;
1794
1795 if ((e = getenv("PULSE_CONFIG_PATH")))
1796 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1797 else if ((h = pa_get_home_dir_malloc())) {
1798 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1799 pa_xfree(h);
1800 } else
1801 return NULL;
1802
1803 if ((f = pa_fopen_cloexec(fn, "r"))) {
1804 if (result)
1805 *result = pa_xstrdup(fn);
1806
1807 pa_xfree(lfn);
1808 return f;
1809 }
1810
1811 if (errno != ENOENT) {
1812 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1813 pa_xfree(lfn);
1814 return NULL;
1815 }
1816
1817 pa_xfree(lfn);
1818 }
1819
1820 if (global) {
1821 char *gfn;
1822
1823 #ifdef OS_IS_WIN32
1824 if (strncmp(global, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
1825 gfn = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse%s",
1826 pa_win32_get_toplevel(NULL),
1827 global + strlen(PA_DEFAULT_CONFIG_DIR));
1828 else
1829 #endif
1830 gfn = pa_xstrdup(global);
1831
1832 if ((f = pa_fopen_cloexec(gfn, "r"))) {
1833 if (result)
1834 *result = gfn;
1835 else
1836 pa_xfree(gfn);
1837
1838 return f;
1839 }
1840 pa_xfree(gfn);
1841 }
1842
1843 errno = ENOENT;
1844 return NULL;
1845 }
1846
1847 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1848 const char *fn;
1849
1850 if (env && (fn = getenv(env))) {
1851 if (access(fn, R_OK) == 0)
1852 return pa_xstrdup(fn);
1853
1854 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1855 return NULL;
1856 }
1857
1858 if (local) {
1859 const char *e;
1860 char *lfn;
1861 char *h;
1862
1863 if ((e = getenv("PULSE_CONFIG_PATH")))
1864 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1865 else if ((h = pa_get_home_dir_malloc())) {
1866 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1867 pa_xfree(h);
1868 } else
1869 return NULL;
1870
1871 if (access(fn, R_OK) == 0) {
1872 char *r = pa_xstrdup(fn);
1873 pa_xfree(lfn);
1874 return r;
1875 }
1876
1877 if (errno != ENOENT) {
1878 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1879 pa_xfree(lfn);
1880 return NULL;
1881 }
1882
1883 pa_xfree(lfn);
1884 }
1885
1886 if (global) {
1887 char *gfn;
1888
1889 #ifdef OS_IS_WIN32
1890 if (strncmp(global, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
1891 gfn = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse%s",
1892 pa_win32_get_toplevel(NULL),
1893 global + strlen(PA_DEFAULT_CONFIG_DIR));
1894 else
1895 #endif
1896 gfn = pa_xstrdup(global);
1897
1898 if (access(gfn, R_OK) == 0)
1899 return gfn;
1900 pa_xfree(gfn);
1901 }
1902
1903 errno = ENOENT;
1904
1905 return NULL;
1906 }
1907
1908 /* Format the specified data as a hexademical string */
1909 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1910 size_t i = 0, j = 0;
1911 const char hex[] = "0123456789abcdef";
1912
1913 pa_assert(d);
1914 pa_assert(s);
1915 pa_assert(slength > 0);
1916
1917 while (j+2 < slength && i < dlength) {
1918 s[j++] = hex[*d >> 4];
1919 s[j++] = hex[*d & 0xF];
1920
1921 d++;
1922 i++;
1923 }
1924
1925 s[j < slength ? j : slength] = 0;
1926 return s;
1927 }
1928
1929 /* Convert a hexadecimal digit to a number or -1 if invalid */
1930 static int hexc(char c) {
1931 if (c >= '0' && c <= '9')
1932 return c - '0';
1933
1934 if (c >= 'A' && c <= 'F')
1935 return c - 'A' + 10;
1936
1937 if (c >= 'a' && c <= 'f')
1938 return c - 'a' + 10;
1939
1940 errno = EINVAL;
1941 return -1;
1942 }
1943
1944 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1945 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1946 size_t j = 0;
1947
1948 pa_assert(p);
1949 pa_assert(d);
1950
1951 while (j < dlength && *p) {
1952 int b;
1953
1954 if ((b = hexc(*(p++))) < 0)
1955 return (size_t) -1;
1956
1957 d[j] = (uint8_t) (b << 4);
1958
1959 if (!*p)
1960 return (size_t) -1;
1961
1962 if ((b = hexc(*(p++))) < 0)
1963 return (size_t) -1;
1964
1965 d[j] |= (uint8_t) b;
1966 j++;
1967 }
1968
1969 return j;
1970 }
1971
1972 /* Returns nonzero when *s starts with *pfx */
1973 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1974 size_t l;
1975
1976 pa_assert(s);
1977 pa_assert(pfx);
1978
1979 l = strlen(pfx);
1980
1981 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1982 }
1983
1984 /* Returns nonzero when *s ends with *sfx */
1985 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1986 size_t l1, l2;
1987
1988 pa_assert(s);
1989 pa_assert(sfx);
1990
1991 l1 = strlen(s);
1992 l2 = strlen(sfx);
1993
1994 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1995 }
1996
1997 pa_bool_t pa_is_path_absolute(const char *fn) {
1998 pa_assert(fn);
1999
2000 #ifndef OS_IS_WIN32
2001 return *fn == '/';
2002 #else
2003 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
2004 #endif
2005 }
2006
2007 char *pa_make_path_absolute(const char *p) {
2008 char *r;
2009 char *cwd;
2010
2011 pa_assert(p);
2012
2013 if (pa_is_path_absolute(p))
2014 return pa_xstrdup(p);
2015
2016 if (!(cwd = pa_getcwd()))
2017 return pa_xstrdup(p);
2018
2019 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
2020 pa_xfree(cwd);
2021 return r;
2022 }
2023
2024 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
2025 * if fn is non-null and starts with / return fn
2026 * otherwise append fn to the run time path and return it */
2027 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
2028 char *rtp;
2029
2030 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
2031
2032 if (fn) {
2033 char *r, *canonical_rtp;
2034
2035 if (pa_is_path_absolute(fn)) {
2036 pa_xfree(rtp);
2037 return pa_xstrdup(fn);
2038 }
2039
2040 if (!rtp)
2041 return NULL;
2042
2043 /* Hopefully make the path smaller to avoid 108 char limit (fdo#44680) */
2044 if ((canonical_rtp = pa_realpath(rtp))) {
2045 if (strlen(rtp) >= strlen(canonical_rtp))
2046 pa_xfree(rtp);
2047 else {
2048 pa_xfree(canonical_rtp);
2049 canonical_rtp = rtp;
2050 }
2051 } else
2052 canonical_rtp = rtp;
2053
2054 if (prependmid) {
2055 char *mid;
2056
2057 if (!(mid = pa_machine_id())) {
2058 pa_xfree(canonical_rtp);
2059 return NULL;
2060 }
2061
2062 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", canonical_rtp, mid, fn);
2063 pa_xfree(mid);
2064 } else
2065 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", canonical_rtp, fn);
2066
2067 pa_xfree(canonical_rtp);
2068 return r;
2069 } else
2070 return rtp;
2071 }
2072
2073 char *pa_runtime_path(const char *fn) {
2074 return get_path(fn, FALSE, TRUE);
2075 }
2076
2077 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
2078 return get_path(fn, appendmid, FALSE);
2079 }
2080
2081 /* Convert the string s to a signed integer in *ret_i */
2082 int pa_atoi(const char *s, int32_t *ret_i) {
2083 long l;
2084
2085 pa_assert(s);
2086 pa_assert(ret_i);
2087
2088 if (pa_atol(s, &l) < 0)
2089 return -1;
2090
2091 if ((int32_t) l != l) {
2092 errno = ERANGE;
2093 return -1;
2094 }
2095
2096 *ret_i = (int32_t) l;
2097
2098 return 0;
2099 }
2100
2101 /* Convert the string s to an unsigned integer in *ret_u */
2102 int pa_atou(const char *s, uint32_t *ret_u) {
2103 char *x = NULL;
2104 unsigned long l;
2105
2106 pa_assert(s);
2107 pa_assert(ret_u);
2108
2109 errno = 0;
2110 l = strtoul(s, &x, 0);
2111
2112 if (!x || *x || errno) {
2113 if (!errno)
2114 errno = EINVAL;
2115 return -1;
2116 }
2117
2118 if ((uint32_t) l != l) {
2119 errno = ERANGE;
2120 return -1;
2121 }
2122
2123 *ret_u = (uint32_t) l;
2124
2125 return 0;
2126 }
2127
2128 /* Convert the string s to a signed long integer in *ret_l. */
2129 int pa_atol(const char *s, long *ret_l) {
2130 char *x = NULL;
2131 long l;
2132
2133 pa_assert(s);
2134 pa_assert(ret_l);
2135
2136 errno = 0;
2137 l = strtol(s, &x, 0);
2138
2139 if (!x || *x || errno) {
2140 if (!errno)
2141 errno = EINVAL;
2142 return -1;
2143 }
2144
2145 *ret_l = l;
2146
2147 return 0;
2148 }
2149
2150 #ifdef HAVE_STRTOF_L
2151 static locale_t c_locale = NULL;
2152
2153 static void c_locale_destroy(void) {
2154 freelocale(c_locale);
2155 }
2156 #endif
2157
2158 int pa_atod(const char *s, double *ret_d) {
2159 char *x = NULL;
2160 double f;
2161
2162 pa_assert(s);
2163 pa_assert(ret_d);
2164
2165 /* This should be locale independent */
2166
2167 #ifdef HAVE_STRTOF_L
2168
2169 PA_ONCE_BEGIN {
2170
2171 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
2172 atexit(c_locale_destroy);
2173
2174 } PA_ONCE_END;
2175
2176 if (c_locale) {
2177 errno = 0;
2178 f = strtod_l(s, &x, c_locale);
2179 } else
2180 #endif
2181 {
2182 errno = 0;
2183 f = strtod(s, &x);
2184 }
2185
2186 if (!x || *x || errno) {
2187 if (!errno)
2188 errno = EINVAL;
2189 return -1;
2190 }
2191
2192 *ret_d = f;
2193
2194 return 0;
2195 }
2196
2197 /* Same as snprintf, but guarantees NUL-termination on every platform */
2198 size_t pa_snprintf(char *str, size_t size, const char *format, ...) {
2199 size_t ret;
2200 va_list ap;
2201
2202 pa_assert(str);
2203 pa_assert(size > 0);
2204 pa_assert(format);
2205
2206 va_start(ap, format);
2207 ret = pa_vsnprintf(str, size, format, ap);
2208 va_end(ap);
2209
2210 return ret;
2211 }
2212
2213 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2214 size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
2215 int ret;
2216
2217 pa_assert(str);
2218 pa_assert(size > 0);
2219 pa_assert(format);
2220
2221 ret = vsnprintf(str, size, format, ap);
2222
2223 str[size-1] = 0;
2224
2225 if (ret < 0)
2226 return strlen(str);
2227
2228 if ((size_t) ret > size-1)
2229 return size-1;
2230
2231 return (size_t) ret;
2232 }
2233
2234 /* Truncate the specified string, but guarantee that the string
2235 * returned still validates as UTF8 */
2236 char *pa_truncate_utf8(char *c, size_t l) {
2237 pa_assert(c);
2238 pa_assert(pa_utf8_valid(c));
2239
2240 if (strlen(c) <= l)
2241 return c;
2242
2243 c[l] = 0;
2244
2245 while (l > 0 && !pa_utf8_valid(c))
2246 c[--l] = 0;
2247
2248 return c;
2249 }
2250
2251 char *pa_getcwd(void) {
2252 size_t l = 128;
2253
2254 for (;;) {
2255 char *p = pa_xmalloc(l);
2256 if (getcwd(p, l))
2257 return p;
2258
2259 if (errno != ERANGE)
2260 return NULL;
2261
2262 pa_xfree(p);
2263 l *= 2;
2264 }
2265 }
2266
2267 void *pa_will_need(const void *p, size_t l) {
2268 #ifdef RLIMIT_MEMLOCK
2269 struct rlimit rlim;
2270 #endif
2271 const void *a;
2272 size_t size;
2273 int r = ENOTSUP;
2274 size_t bs;
2275
2276 pa_assert(p);
2277 pa_assert(l > 0);
2278
2279 a = PA_PAGE_ALIGN_PTR(p);
2280 size = (size_t) ((const uint8_t*) p + l - (const uint8_t*) a);
2281
2282 #ifdef HAVE_POSIX_MADVISE
2283 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2284 pa_log_debug("posix_madvise() worked fine!");
2285 return (void*) p;
2286 }
2287 #endif
2288
2289 /* Most likely the memory was not mmap()ed from a file and thus
2290 * madvise() didn't work, so let's misuse mlock() do page this
2291 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2292 * inviting, the man page of mlock() tells us: "All pages that
2293 * contain a part of the specified address range are guaranteed to
2294 * be resident in RAM when the call returns successfully." */
2295
2296 #ifdef RLIMIT_MEMLOCK
2297 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2298
2299 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2300 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));
2301 errno = EPERM;
2302 return (void*) p;
2303 }
2304
2305 bs = PA_PAGE_ALIGN((size_t) rlim.rlim_cur);
2306 #else
2307 bs = PA_PAGE_SIZE*4;
2308 #endif
2309
2310 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2311
2312 #ifdef HAVE_MLOCK
2313 while (size > 0 && bs > 0) {
2314
2315 if (bs > size)
2316 bs = size;
2317
2318 if (mlock(a, bs) < 0) {
2319 bs = PA_PAGE_ALIGN(bs / 2);
2320 continue;
2321 }
2322
2323 pa_assert_se(munlock(a, bs) == 0);
2324
2325 a = (const uint8_t*) a + bs;
2326 size -= bs;
2327 }
2328 #endif
2329
2330 if (bs <= 0)
2331 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2332 else
2333 pa_log_debug("mlock() worked fine!");
2334
2335 return (void*) p;
2336 }
2337
2338 void pa_close_pipe(int fds[2]) {
2339 pa_assert(fds);
2340
2341 if (fds[0] >= 0)
2342 pa_assert_se(pa_close(fds[0]) == 0);
2343
2344 if (fds[1] >= 0)
2345 pa_assert_se(pa_close(fds[1]) == 0);
2346
2347 fds[0] = fds[1] = -1;
2348 }
2349
2350 char *pa_readlink(const char *p) {
2351 #ifdef HAVE_READLINK
2352 size_t l = 100;
2353
2354 for (;;) {
2355 char *c;
2356 ssize_t n;
2357
2358 c = pa_xmalloc(l);
2359
2360 if ((n = readlink(p, c, l-1)) < 0) {
2361 pa_xfree(c);
2362 return NULL;
2363 }
2364
2365 if ((size_t) n < l-1) {
2366 c[n] = 0;
2367 return c;
2368 }
2369
2370 pa_xfree(c);
2371 l *= 2;
2372 }
2373 #else
2374 return NULL;
2375 #endif
2376 }
2377
2378 int pa_close_all(int except_fd, ...) {
2379 va_list ap;
2380 unsigned n = 0, i;
2381 int r, *p;
2382
2383 va_start(ap, except_fd);
2384
2385 if (except_fd >= 0)
2386 for (n = 1; va_arg(ap, int) >= 0; n++)
2387 ;
2388
2389 va_end(ap);
2390
2391 p = pa_xnew(int, n+1);
2392
2393 va_start(ap, except_fd);
2394
2395 i = 0;
2396 if (except_fd >= 0) {
2397 int fd;
2398 p[i++] = except_fd;
2399
2400 while ((fd = va_arg(ap, int)) >= 0)
2401 p[i++] = fd;
2402 }
2403 p[i] = -1;
2404
2405 va_end(ap);
2406
2407 r = pa_close_allv(p);
2408 pa_xfree(p);
2409
2410 return r;
2411 }
2412
2413 int pa_close_allv(const int except_fds[]) {
2414 #ifndef OS_IS_WIN32
2415 struct rlimit rl;
2416 int maxfd, fd;
2417
2418 #ifdef __linux__
2419 int saved_errno;
2420 DIR *d;
2421
2422 if ((d = opendir("/proc/self/fd"))) {
2423
2424 struct dirent *de;
2425
2426 while ((de = readdir(d))) {
2427 pa_bool_t found;
2428 long l;
2429 char *e = NULL;
2430 int i;
2431
2432 if (de->d_name[0] == '.')
2433 continue;
2434
2435 errno = 0;
2436 l = strtol(de->d_name, &e, 10);
2437 if (errno != 0 || !e || *e) {
2438 closedir(d);
2439 errno = EINVAL;
2440 return -1;
2441 }
2442
2443 fd = (int) l;
2444
2445 if ((long) fd != l) {
2446 closedir(d);
2447 errno = EINVAL;
2448 return -1;
2449 }
2450
2451 if (fd < 3)
2452 continue;
2453
2454 if (fd == dirfd(d))
2455 continue;
2456
2457 found = FALSE;
2458 for (i = 0; except_fds[i] >= 0; i++)
2459 if (except_fds[i] == fd) {
2460 found = TRUE;
2461 break;
2462 }
2463
2464 if (found)
2465 continue;
2466
2467 if (pa_close(fd) < 0) {
2468 saved_errno = errno;
2469 closedir(d);
2470 errno = saved_errno;
2471
2472 return -1;
2473 }
2474 }
2475
2476 closedir(d);
2477 return 0;
2478 }
2479
2480 #endif
2481
2482 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2483 maxfd = (int) rl.rlim_max;
2484 else
2485 maxfd = sysconf(_SC_OPEN_MAX);
2486
2487 for (fd = 3; fd < maxfd; fd++) {
2488 int i;
2489 pa_bool_t found;
2490
2491 found = FALSE;
2492 for (i = 0; except_fds[i] >= 0; i++)
2493 if (except_fds[i] == fd) {
2494 found = TRUE;
2495 break;
2496 }
2497
2498 if (found)
2499 continue;
2500
2501 if (pa_close(fd) < 0 && errno != EBADF)
2502 return -1;
2503 }
2504 #endif /* !OS_IS_WIN32 */
2505
2506 return 0;
2507 }
2508
2509 int pa_unblock_sigs(int except, ...) {
2510 va_list ap;
2511 unsigned n = 0, i;
2512 int r, *p;
2513
2514 va_start(ap, except);
2515
2516 if (except >= 1)
2517 for (n = 1; va_arg(ap, int) >= 0; n++)
2518 ;
2519
2520 va_end(ap);
2521
2522 p = pa_xnew(int, n+1);
2523
2524 va_start(ap, except);
2525
2526 i = 0;
2527 if (except >= 1) {
2528 int sig;
2529 p[i++] = except;
2530
2531 while ((sig = va_arg(ap, int)) >= 0)
2532 p[i++] = sig;
2533 }
2534 p[i] = -1;
2535
2536 va_end(ap);
2537
2538 r = pa_unblock_sigsv(p);
2539 pa_xfree(p);
2540
2541 return r;
2542 }
2543
2544 int pa_unblock_sigsv(const int except[]) {
2545 #ifndef OS_IS_WIN32
2546 int i;
2547 sigset_t ss;
2548
2549 if (sigemptyset(&ss) < 0)
2550 return -1;
2551
2552 for (i = 0; except[i] > 0; i++)
2553 if (sigaddset(&ss, except[i]) < 0)
2554 return -1;
2555
2556 return sigprocmask(SIG_SETMASK, &ss, NULL);
2557 #else
2558 return 0;
2559 #endif
2560 }
2561
2562 int pa_reset_sigs(int except, ...) {
2563 va_list ap;
2564 unsigned n = 0, i;
2565 int *p, r;
2566
2567 va_start(ap, except);
2568
2569 if (except >= 1)
2570 for (n = 1; va_arg(ap, int) >= 0; n++)
2571 ;
2572
2573 va_end(ap);
2574
2575 p = pa_xnew(int, n+1);
2576
2577 va_start(ap, except);
2578
2579 i = 0;
2580 if (except >= 1) {
2581 int sig;
2582 p[i++] = except;
2583
2584 while ((sig = va_arg(ap, int)) >= 0)
2585 p[i++] = sig;
2586 }
2587 p[i] = -1;
2588
2589 va_end(ap);
2590
2591 r = pa_reset_sigsv(p);
2592 pa_xfree(p);
2593
2594 return r;
2595 }
2596
2597 int pa_reset_sigsv(const int except[]) {
2598 #ifndef OS_IS_WIN32
2599 int sig;
2600
2601 for (sig = 1; sig < NSIG; sig++) {
2602 pa_bool_t reset = TRUE;
2603
2604 switch (sig) {
2605 case SIGKILL:
2606 case SIGSTOP:
2607 reset = FALSE;
2608 break;
2609
2610 default: {
2611 int i;
2612
2613 for (i = 0; except[i] > 0; i++) {
2614 if (sig == except[i]) {
2615 reset = FALSE;
2616 break;
2617 }
2618 }
2619 }
2620 }
2621
2622 if (reset) {
2623 struct sigaction sa;
2624
2625 memset(&sa, 0, sizeof(sa));
2626 sa.sa_handler = SIG_DFL;
2627
2628 /* On Linux the first two RT signals are reserved by
2629 * glibc, and sigaction() will return EINVAL for them. */
2630 if ((sigaction(sig, &sa, NULL) < 0))
2631 if (errno != EINVAL)
2632 return -1;
2633 }
2634 }
2635 #endif
2636
2637 return 0;
2638 }
2639
2640 void pa_set_env(const char *key, const char *value) {
2641 pa_assert(key);
2642 pa_assert(value);
2643
2644 /* This is not thread-safe */
2645
2646 #ifdef OS_IS_WIN32
2647 SetEnvironmentVariable(key, value);
2648 #else
2649 setenv(key, value, 1);
2650 #endif
2651 }
2652
2653 void pa_set_env_and_record(const char *key, const char *value) {
2654 pa_assert(key);
2655 pa_assert(value);
2656
2657 /* This is not thread-safe */
2658
2659 pa_set_env(key, value);
2660 recorded_env = pa_strlist_prepend(recorded_env, key);
2661 }
2662
2663 void pa_unset_env_recorded(void) {
2664
2665 /* This is not thread-safe */
2666
2667 for (;;) {
2668 char *s;
2669
2670 recorded_env = pa_strlist_pop(recorded_env, &s);
2671
2672 if (!s)
2673 break;
2674
2675 #ifdef OS_IS_WIN32
2676 SetEnvironmentVariable(s, NULL);
2677 #else
2678 unsetenv(s);
2679 #endif
2680 pa_xfree(s);
2681 }
2682 }
2683
2684 pa_bool_t pa_in_system_mode(void) {
2685 const char *e;
2686
2687 if (!(e = getenv("PULSE_SYSTEM")))
2688 return FALSE;
2689
2690 return !!atoi(e);
2691 }
2692
2693 /* Checks a whitespace-separated list of words in haystack for needle */
2694 pa_bool_t pa_str_in_list_spaces(const char *haystack, const char *needle) {
2695 char *s;
2696 const char *state = NULL;
2697
2698 if (!haystack || !needle)
2699 return FALSE;
2700
2701 while ((s = pa_split_spaces(haystack, &state))) {
2702 if (pa_streq(needle, s)) {
2703 pa_xfree(s);
2704 return TRUE;
2705 }
2706
2707 pa_xfree(s);
2708 }
2709
2710 return FALSE;
2711 }
2712
2713 char *pa_get_user_name_malloc(void) {
2714 ssize_t k;
2715 char *u;
2716
2717 #ifdef _SC_LOGIN_NAME_MAX
2718 k = (ssize_t) sysconf(_SC_LOGIN_NAME_MAX);
2719
2720 if (k <= 0)
2721 #endif
2722 k = 32;
2723
2724 u = pa_xnew(char, k+1);
2725
2726 if (!(pa_get_user_name(u, k))) {
2727 pa_xfree(u);
2728 return NULL;
2729 }
2730
2731 return u;
2732 }
2733
2734 char *pa_get_host_name_malloc(void) {
2735 size_t l;
2736
2737 l = 100;
2738 for (;;) {
2739 char *c;
2740
2741 c = pa_xmalloc(l);
2742
2743 if (!pa_get_host_name(c, l)) {
2744
2745 if (errno != EINVAL && errno != ENAMETOOLONG)
2746 break;
2747
2748 } else if (strlen(c) < l-1) {
2749 char *u;
2750
2751 if (*c == 0) {
2752 pa_xfree(c);
2753 break;
2754 }
2755
2756 u = pa_utf8_filter(c);
2757 pa_xfree(c);
2758 return u;
2759 }
2760
2761 /* Hmm, the hostname is as long the space we offered the
2762 * function, we cannot know if it fully fit in, so let's play
2763 * safe and retry. */
2764
2765 pa_xfree(c);
2766 l *= 2;
2767 }
2768
2769 return NULL;
2770 }
2771
2772 char *pa_machine_id(void) {
2773 FILE *f;
2774 char *h;
2775
2776 /* The returned value is supposed be some kind of ascii identifier
2777 * that is unique and stable across reboots. */
2778
2779 /* First we try the /etc/machine-id, which is the best option we
2780 * have, since it fits perfectly our needs and is not as volatile
2781 * as the hostname which might be set from dhcp. */
2782
2783 if ((f = pa_fopen_cloexec(PA_MACHINE_ID, "r")) ||
2784 (f = pa_fopen_cloexec(PA_MACHINE_ID_FALLBACK, "r"))) {
2785 char ln[34] = "", *r;
2786
2787 r = fgets(ln, sizeof(ln)-1, f);
2788 fclose(f);
2789
2790 pa_strip_nl(ln);
2791
2792 if (r && ln[0])
2793 return pa_utf8_filter(ln);
2794 }
2795
2796 if ((h = pa_get_host_name_malloc()))
2797 return h;
2798
2799 #ifndef OS_IS_WIN32
2800 /* If no hostname was set we use the POSIX hostid. It's usually
2801 * the IPv4 address. Might not be that stable. */
2802 return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
2803 #else
2804 return NULL;
2805 #endif
2806 }
2807
2808 char *pa_session_id(void) {
2809 const char *e;
2810
2811 e = getenv("XDG_SESSION_ID");
2812 if (!e)
2813 return NULL;
2814
2815 return pa_utf8_filter(e);
2816 }
2817
2818 char *pa_uname_string(void) {
2819 #ifdef HAVE_UNAME
2820 struct utsname u;
2821
2822 pa_assert_se(uname(&u) >= 0);
2823
2824 return pa_sprintf_malloc("%s %s %s %s", u.sysname, u.machine, u.release, u.version);
2825 #endif
2826 #ifdef OS_IS_WIN32
2827 OSVERSIONINFO i;
2828
2829 pa_zero(i);
2830 i.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
2831 pa_assert_se(GetVersionEx(&i));
2832
2833 return pa_sprintf_malloc("Windows %d.%d (%d) %s", i.dwMajorVersion, i.dwMinorVersion, i.dwBuildNumber, i.szCSDVersion);
2834 #endif
2835 }
2836
2837 #ifdef HAVE_VALGRIND_MEMCHECK_H
2838 pa_bool_t pa_in_valgrind(void) {
2839 static int b = 0;
2840
2841 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2842 * here instead of really checking whether we run in valgrind or
2843 * not. */
2844
2845 if (b < 1)
2846 b = getenv("VALGRIND") ? 2 : 1;
2847
2848 return b > 1;
2849 }
2850 #endif
2851
2852 unsigned pa_gcd(unsigned a, unsigned b) {
2853
2854 while (b > 0) {
2855 unsigned t = b;
2856 b = a % b;
2857 a = t;
2858 }
2859
2860 return a;
2861 }
2862
2863 void pa_reduce(unsigned *num, unsigned *den) {
2864
2865 unsigned gcd = pa_gcd(*num, *den);
2866
2867 if (gcd <= 0)
2868 return;
2869
2870 *num /= gcd;
2871 *den /= gcd;
2872
2873 pa_assert(pa_gcd(*num, *den) == 1);
2874 }
2875
2876 unsigned pa_ncpus(void) {
2877 long ncpus;
2878
2879 #ifdef _SC_NPROCESSORS_CONF
2880 ncpus = sysconf(_SC_NPROCESSORS_CONF);
2881 #else
2882 ncpus = 1;
2883 #endif
2884
2885 return ncpus <= 0 ? 1 : (unsigned) ncpus;
2886 }
2887
2888 char *pa_replace(const char*s, const char*a, const char *b) {
2889 pa_strbuf *sb;
2890 size_t an;
2891
2892 pa_assert(s);
2893 pa_assert(a);
2894 pa_assert(b);
2895
2896 an = strlen(a);
2897 sb = pa_strbuf_new();
2898
2899 for (;;) {
2900 const char *p;
2901
2902 if (!(p = strstr(s, a)))
2903 break;
2904
2905 pa_strbuf_putsn(sb, s, p-s);
2906 pa_strbuf_puts(sb, b);
2907 s = p + an;
2908 }
2909
2910 pa_strbuf_puts(sb, s);
2911
2912 return pa_strbuf_tostring_free(sb);
2913 }
2914
2915 char *pa_escape(const char *p, const char *chars) {
2916 const char *s;
2917 const char *c;
2918 pa_strbuf *buf = pa_strbuf_new();
2919
2920 for (s = p; *s; ++s) {
2921 if (*s == '\\')
2922 pa_strbuf_putc(buf, '\\');
2923 else if (chars) {
2924 for (c = chars; *c; ++c) {
2925 if (*s == *c) {
2926 pa_strbuf_putc(buf, '\\');
2927 break;
2928 }
2929 }
2930 }
2931 pa_strbuf_putc(buf, *s);
2932 }
2933
2934 return pa_strbuf_tostring_free(buf);
2935 }
2936
2937 char *pa_unescape(char *p) {
2938 char *s, *d;
2939 pa_bool_t escaped = FALSE;
2940
2941 for (s = p, d = p; *s; s++) {
2942 if (!escaped && *s == '\\') {
2943 escaped = TRUE;
2944 continue;
2945 }
2946
2947 *(d++) = *s;
2948 escaped = FALSE;
2949 }
2950
2951 *d = 0;
2952
2953 return p;
2954 }
2955
2956 char *pa_realpath(const char *path) {
2957 char *t;
2958 pa_assert(path);
2959
2960 /* We want only absolute paths */
2961 if (path[0] != '/') {
2962 errno = EINVAL;
2963 return NULL;
2964 }
2965
2966 #if defined(__GLIBC__) || defined(__APPLE__)
2967 {
2968 char *r;
2969
2970 if (!(r = realpath(path, NULL)))
2971 return NULL;
2972
2973 /* We copy this here in case our pa_xmalloc() is not
2974 * implemented on top of libc malloc() */
2975 t = pa_xstrdup(r);
2976 pa_xfree(r);
2977 }
2978 #elif defined(PATH_MAX)
2979 {
2980 char *path_buf;
2981 path_buf = pa_xmalloc(PATH_MAX);
2982
2983 #if defined(OS_IS_WIN32)
2984 if (!(t = _fullpath(path_buf, path, _MAX_PATH))) {
2985 pa_xfree(path_buf);
2986 return NULL;
2987 }
2988 #else
2989 if (!(t = realpath(path, path_buf))) {
2990 pa_xfree(path_buf);
2991 return NULL;
2992 }
2993 #endif
2994 }
2995 #else
2996 #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."
2997 #endif
2998
2999 return t;
3000 }
3001
3002 void pa_disable_sigpipe(void) {
3003
3004 #ifdef SIGPIPE
3005 struct sigaction sa;
3006
3007 pa_zero(sa);
3008
3009 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
3010 pa_log("sigaction(): %s", pa_cstrerror(errno));
3011 return;
3012 }
3013
3014 sa.sa_handler = SIG_IGN;
3015
3016 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
3017 pa_log("sigaction(): %s", pa_cstrerror(errno));
3018 return;
3019 }
3020 #endif
3021 }
3022
3023 void pa_xfreev(void**a) {
3024 void **p;
3025
3026 if (!a)
3027 return;
3028
3029 for (p = a; *p; p++)
3030 pa_xfree(*p);
3031
3032 pa_xfree(a);
3033 }
3034
3035 char **pa_split_spaces_strv(const char *s) {
3036 char **t, *e;
3037 unsigned i = 0, n = 8;
3038 const char *state = NULL;
3039
3040 t = pa_xnew(char*, n);
3041 while ((e = pa_split_spaces(s, &state))) {
3042 t[i++] = e;
3043
3044 if (i >= n) {
3045 n *= 2;
3046 t = pa_xrenew(char*, t, n);
3047 }
3048 }
3049
3050 if (i <= 0) {
3051 pa_xfree(t);
3052 return NULL;
3053 }
3054
3055 t[i] = NULL;
3056 return t;
3057 }
3058
3059 char* pa_maybe_prefix_path(const char *path, const char *prefix) {
3060 pa_assert(path);
3061
3062 if (pa_is_path_absolute(path))
3063 return pa_xstrdup(path);
3064
3065 return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
3066 }
3067
3068 size_t pa_pipe_buf(int fd) {
3069
3070 #ifdef _PC_PIPE_BUF
3071 long n;
3072
3073 if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
3074 return (size_t) n;
3075 #endif
3076
3077 #ifdef PIPE_BUF
3078 return PIPE_BUF;
3079 #else
3080 return 4096;
3081 #endif
3082 }
3083
3084 void pa_reset_personality(void) {
3085
3086 #ifdef __linux__
3087 if (personality(PER_LINUX) < 0)
3088 pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
3089 #endif
3090
3091 }
3092
3093 #if defined(__linux__) && !defined(__OPTIMIZE__)
3094
3095 pa_bool_t pa_run_from_build_tree(void) {
3096 char *rp;
3097 pa_bool_t b = FALSE;
3098
3099 if ((rp = pa_readlink("/proc/self/exe"))) {
3100 b = pa_startswith(rp, PA_BUILDDIR);
3101 pa_xfree(rp);
3102 }
3103
3104 return b;
3105 }
3106
3107 #endif
3108
3109 const char *pa_get_temp_dir(void) {
3110 const char *t;
3111
3112 if ((t = getenv("TMPDIR")) &&
3113 pa_is_path_absolute(t))
3114 return t;
3115
3116 if ((t = getenv("TMP")) &&
3117 pa_is_path_absolute(t))
3118 return t;
3119
3120 if ((t = getenv("TEMP")) &&
3121 pa_is_path_absolute(t))
3122 return t;
3123
3124 if ((t = getenv("TEMPDIR")) &&
3125 pa_is_path_absolute(t))
3126 return t;
3127
3128 return "/tmp";
3129 }
3130
3131 int pa_open_cloexec(const char *fn, int flags, mode_t mode) {
3132 int fd;
3133
3134 #ifdef O_NOCTTY
3135 flags |= O_NOCTTY;
3136 #endif
3137
3138 #ifdef O_CLOEXEC
3139 if ((fd = open(fn, flags|O_CLOEXEC, mode)) >= 0)
3140 goto finish;
3141
3142 if (errno != EINVAL)
3143 return fd;
3144 #endif
3145
3146 if ((fd = open(fn, flags, mode)) < 0)
3147 return fd;
3148
3149 finish:
3150 /* Some implementations might simply ignore O_CLOEXEC if it is not
3151 * understood, make sure FD_CLOEXEC is enabled anyway */
3152
3153 pa_make_fd_cloexec(fd);
3154 return fd;
3155 }
3156
3157 int pa_socket_cloexec(int domain, int type, int protocol) {
3158 int fd;
3159
3160 #ifdef SOCK_CLOEXEC
3161 if ((fd = socket(domain, type | SOCK_CLOEXEC, protocol)) >= 0)
3162 goto finish;
3163
3164 if (errno != EINVAL)
3165 return fd;
3166 #endif
3167
3168 if ((fd = socket(domain, type, protocol)) < 0)
3169 return fd;
3170
3171 finish:
3172 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
3173 * not understood, make sure FD_CLOEXEC is enabled anyway */
3174
3175 pa_make_fd_cloexec(fd);
3176 return fd;
3177 }
3178
3179 int pa_pipe_cloexec(int pipefd[2]) {
3180 int r;
3181
3182 #ifdef HAVE_PIPE2
3183 if ((r = pipe2(pipefd, O_CLOEXEC)) >= 0)
3184 goto finish;
3185
3186 if (errno != EINVAL && errno != ENOSYS)
3187 return r;
3188
3189 #endif
3190
3191 if ((r = pipe(pipefd)) < 0)
3192 return r;
3193
3194 finish:
3195 pa_make_fd_cloexec(pipefd[0]);
3196 pa_make_fd_cloexec(pipefd[1]);
3197
3198 return 0;
3199 }
3200
3201 int pa_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
3202 int fd;
3203
3204 #ifdef HAVE_ACCEPT4
3205 if ((fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC)) >= 0)
3206 goto finish;
3207
3208 if (errno != EINVAL && errno != ENOSYS)
3209 return fd;
3210
3211 #endif
3212
3213 if ((fd = accept(sockfd, addr, addrlen)) < 0)
3214 return fd;
3215
3216 finish:
3217 pa_make_fd_cloexec(fd);
3218 return fd;
3219 }
3220
3221 FILE* pa_fopen_cloexec(const char *path, const char *mode) {
3222 FILE *f;
3223 char *m;
3224
3225 m = pa_sprintf_malloc("%se", mode);
3226
3227 errno = 0;
3228 if ((f = fopen(path, m))) {
3229 pa_xfree(m);
3230 goto finish;
3231 }
3232
3233 pa_xfree(m);
3234
3235 if (errno != EINVAL)
3236 return NULL;
3237
3238 if (!(f = fopen(path, mode)))
3239 return NULL;
3240
3241 finish:
3242 pa_make_fd_cloexec(fileno(f));
3243 return f;
3244 }
3245
3246 void pa_nullify_stdfds(void) {
3247
3248 #ifndef OS_IS_WIN32
3249 pa_close(STDIN_FILENO);
3250 pa_close(STDOUT_FILENO);
3251 pa_close(STDERR_FILENO);
3252
3253 pa_assert_se(open("/dev/null", O_RDONLY) == STDIN_FILENO);
3254 pa_assert_se(open("/dev/null", O_WRONLY) == STDOUT_FILENO);
3255 pa_assert_se(open("/dev/null", O_WRONLY) == STDERR_FILENO);
3256 #else
3257 FreeConsole();
3258 #endif
3259
3260 }
3261
3262 char *pa_read_line_from_file(const char *fn) {
3263 FILE *f;
3264 char ln[256] = "", *r;
3265
3266 if (!(f = pa_fopen_cloexec(fn, "r")))
3267 return NULL;
3268
3269 r = fgets(ln, sizeof(ln)-1, f);
3270 fclose(f);
3271
3272 if (!r) {
3273 errno = EIO;
3274 return NULL;
3275 }
3276
3277 pa_strip_nl(ln);
3278 return pa_xstrdup(ln);
3279 }
3280
3281 pa_bool_t pa_running_in_vm(void) {
3282
3283 #if defined(__i386__) || defined(__x86_64__)
3284
3285 /* Both CPUID and DMI are x86 specific interfaces... */
3286
3287 uint32_t eax = 0x40000000;
3288 union {
3289 uint32_t sig32[3];
3290 char text[13];
3291 } sig;
3292
3293 #ifdef __linux__
3294 const char *const dmi_vendors[] = {
3295 "/sys/class/dmi/id/sys_vendor",
3296 "/sys/class/dmi/id/board_vendor",
3297 "/sys/class/dmi/id/bios_vendor"
3298 };
3299
3300 unsigned i;
3301
3302 for (i = 0; i < PA_ELEMENTSOF(dmi_vendors); i++) {
3303 char *s;
3304
3305 if ((s = pa_read_line_from_file(dmi_vendors[i]))) {
3306
3307 if (pa_startswith(s, "QEMU") ||
3308 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3309 pa_startswith(s, "VMware") ||
3310 pa_startswith(s, "VMW") ||
3311 pa_startswith(s, "Microsoft Corporation") ||
3312 pa_startswith(s, "innotek GmbH") ||
3313 pa_startswith(s, "Xen")) {
3314
3315 pa_xfree(s);
3316 return TRUE;
3317 }
3318
3319 pa_xfree(s);
3320 }
3321 }
3322
3323 #endif
3324
3325 /* http://lwn.net/Articles/301888/ */
3326 pa_zero(sig);
3327
3328 __asm__ __volatile__ (
3329 /* ebx/rbx is being used for PIC! */
3330 " push %%"PA_REG_b" \n\t"
3331 " cpuid \n\t"
3332 " mov %%ebx, %1 \n\t"
3333 " pop %%"PA_REG_b" \n\t"
3334
3335 : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
3336 : "0" (eax)
3337 );
3338
3339 if (pa_streq(sig.text, "XenVMMXenVMM") ||
3340 pa_streq(sig.text, "KVMKVMKVM") ||
3341 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3342 pa_streq(sig.text, "VMwareVMware") ||
3343 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3344 pa_streq(sig.text, "Microsoft Hv"))
3345 return TRUE;
3346
3347 #endif
3348
3349 return FALSE;
3350 }