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