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