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