• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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