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