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