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