]> code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
set errno properly in all functions from core-util.c
[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
46 #ifdef HAVE_STRTOF_L
47 #include <locale.h>
48 #endif
49
50 #ifdef HAVE_SCHED_H
51 #include <sched.h>
52 #endif
53
54 #ifdef HAVE_SYS_RESOURCE_H
55 #include <sys/resource.h>
56 #endif
57
58 #ifdef HAVE_SYS_CAPABILITY_H
59 #include <sys/capability.h>
60 #endif
61
62 #ifdef HAVE_SYS_MMAN_H
63 #include <sys/mman.h>
64 #endif
65
66 #ifdef HAVE_PTHREAD
67 #include <pthread.h>
68 #endif
69
70 #ifdef HAVE_NETDB_H
71 #include <netdb.h>
72 #endif
73
74 #ifdef HAVE_WINDOWS_H
75 #include <windows.h>
76 #endif
77
78 #ifdef HAVE_PWD_H
79 #include <pwd.h>
80 #endif
81
82 #ifdef HAVE_GRP_H
83 #include <grp.h>
84 #endif
85
86 #ifdef HAVE_LIBSAMPLERATE
87 #include <samplerate.h>
88 #endif
89
90 #include <pulse/xmalloc.h>
91 #include <pulse/util.h>
92 #include <pulse/utf8.h>
93
94 #include <pulsecore/core-error.h>
95 #include <pulsecore/winsock.h>
96 #include <pulsecore/log.h>
97 #include <pulsecore/macro.h>
98 #include <pulsecore/thread.h>
99
100 #include "core-util.h"
101
102 /* Not all platforms have this */
103 #ifndef MSG_NOSIGNAL
104 #define MSG_NOSIGNAL 0
105 #endif
106
107 #ifdef OS_IS_WIN32
108
109 #define PULSE_ROOTENV "PULSE_ROOT"
110
111 int pa_set_root(HANDLE handle) {
112 char library_path[MAX_PATH + sizeof(PULSE_ROOTENV) + 1], *sep;
113
114 strcpy(library_path, PULSE_ROOTENV "=");
115
116 /* FIXME: Needs to set errno */
117
118 if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
119 return 0;
120
121 sep = strrchr(library_path, PA_PATH_SEP_CHAR);
122 if (sep)
123 *sep = '\0';
124
125 if (_putenv(library_path) < 0)
126 return 0;
127
128 return 1;
129 }
130
131 #endif
132
133 /** Make a file descriptor nonblock. Doesn't do any error checking */
134 void pa_make_fd_nonblock(int fd) {
135
136 #ifdef O_NONBLOCK
137 int v;
138 pa_assert(fd >= 0);
139
140 pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
141
142 if (!(v & O_NONBLOCK))
143 pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
144
145 #elif defined(OS_IS_WIN32)
146 u_long arg = 1;
147 if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
148 pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
149 pa_log_warn("Only sockets can be made non-blocking!");
150 }
151 #else
152 pa_log_warn("Non-blocking I/O not supported.!");
153 #endif
154
155 }
156
157 /* Set the FD_CLOEXEC flag for a fd */
158 void pa_make_fd_cloexec(int fd) {
159
160 #ifdef FD_CLOEXEC
161 int v;
162 pa_assert(fd >= 0);
163
164 pa_assert_se((v = fcntl(fd, F_GETFD, 0)) >= 0);
165
166 if (!(v & FD_CLOEXEC))
167 pa_assert_se(fcntl(fd, F_SETFD, v|FD_CLOEXEC) >= 0);
168 #endif
169
170 }
171
172 /** Creates a directory securely */
173 int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
174 struct stat st;
175 int r, saved_errno;
176
177 pa_assert(dir);
178
179 #ifdef OS_IS_WIN32
180 r = mkdir(dir);
181 #else
182 {
183 mode_t u;
184 u = umask((~m) & 0777);
185 r = mkdir(dir, m);
186 umask(u);
187 }
188 #endif
189
190 if (r < 0 && errno != EEXIST)
191 return -1;
192
193 #ifdef HAVE_CHOWN
194 if (uid == (uid_t)-1)
195 uid = getuid();
196 if (gid == (gid_t)-1)
197 gid = getgid();
198 (void) chown(dir, uid, gid);
199 #endif
200
201 #ifdef HAVE_CHMOD
202 chmod(dir, m);
203 #endif
204
205 #ifdef HAVE_LSTAT
206 if (lstat(dir, &st) < 0)
207 #else
208 if (stat(dir, &st) < 0)
209 #endif
210 goto fail;
211
212 #ifndef OS_IS_WIN32
213 if (!S_ISDIR(st.st_mode) ||
214 (st.st_uid != uid) ||
215 (st.st_gid != gid) ||
216 ((st.st_mode & 0777) != m)) {
217 errno = EACCES;
218 goto fail;
219 }
220 #else
221 pa_log_warn("Secure directory creation not supported on Win32.");
222 #endif
223
224 return 0;
225
226 fail:
227 saved_errno = errno;
228 rmdir(dir);
229 errno = saved_errno;
230
231 return -1;
232 }
233
234 /* Return a newly allocated sting containing the parent directory of the specified file */
235 char *pa_parent_dir(const char *fn) {
236 char *slash, *dir = pa_xstrdup(fn);
237
238 if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
239 pa_xfree(dir);
240 errno = ENOENT;
241 return NULL;
242 }
243
244 *(slash-1) = 0;
245 return dir;
246 }
247
248 /* Creates a the parent directory of the specified path securely */
249 int pa_make_secure_parent_dir(const char *fn, mode_t m, uid_t uid, gid_t gid) {
250 int ret = -1;
251 char *dir;
252
253 if (!(dir = pa_parent_dir(fn)))
254 goto finish;
255
256 if (pa_make_secure_dir(dir, m, uid, gid) < 0)
257 goto finish;
258
259 ret = 0;
260
261 finish:
262 pa_xfree(dir);
263 return ret;
264 }
265
266 /** Platform independent read function. Necessary since not all
267 * systems treat all file descriptors equal. If type is
268 * non-NULL it is used to cache the type of the fd. This is
269 * useful for making sure that only a single syscall is executed per
270 * function call. The variable pointed to should be initialized to 0
271 * by the caller. */
272 ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
273
274 #ifdef OS_IS_WIN32
275
276 if (!type || *type == 0) {
277 ssize_t r;
278
279 if ((r = recv(fd, buf, count, 0)) >= 0)
280 return r;
281
282 if (WSAGetLastError() != WSAENOTSOCK) {
283 errno = WSAGetLastError();
284 return r;
285 }
286
287 if (type)
288 *type = 1;
289 }
290
291 #endif
292
293 return read(fd, buf, count);
294 }
295
296 /** Similar to pa_read(), but handles writes */
297 ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
298
299 if (!type || *type == 0) {
300 ssize_t r;
301
302 if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0)
303 return r;
304
305 #ifdef OS_IS_WIN32
306 if (WSAGetLastError() != WSAENOTSOCK) {
307 errno = WSAGetLastError();
308 return r;
309 }
310 #else
311 if (errno != ENOTSOCK)
312 return r;
313 #endif
314
315 if (type)
316 *type = 1;
317 }
318
319 return write(fd, buf, count);
320 }
321
322 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
323 * unless EOF is reached or an error occured */
324 ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
325 ssize_t ret = 0;
326 int _type;
327
328 pa_assert(fd >= 0);
329 pa_assert(data);
330 pa_assert(size);
331
332 if (!type) {
333 _type = 0;
334 type = &_type;
335 }
336
337 while (size > 0) {
338 ssize_t r;
339
340 if ((r = pa_read(fd, data, size, type)) < 0)
341 return r;
342
343 if (r == 0)
344 break;
345
346 ret += r;
347 data = (uint8_t*) data + r;
348 size -= r;
349 }
350
351 return ret;
352 }
353
354 /** Similar to pa_loop_read(), but wraps write() */
355 ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
356 ssize_t ret = 0;
357 int _type;
358
359 pa_assert(fd >= 0);
360 pa_assert(data);
361 pa_assert(size);
362
363 if (!type) {
364 _type = 0;
365 type = &_type;
366 }
367
368 while (size > 0) {
369 ssize_t r;
370
371 if ((r = pa_write(fd, data, size, type)) < 0)
372 return r;
373
374 if (r == 0)
375 break;
376
377 ret += r;
378 data = (const uint8_t*) data + r;
379 size -= r;
380 }
381
382 return ret;
383 }
384
385 /** Platform independent read function. Necessary since not all
386 * systems treat all file descriptors equal. */
387 int pa_close(int fd) {
388
389 #ifdef OS_IS_WIN32
390 int ret;
391
392 if ((ret = closesocket(fd)) == 0)
393 return 0;
394
395 if (WSAGetLastError() != WSAENOTSOCK) {
396 errno = WSAGetLastError();
397 return ret;
398 }
399 #endif
400
401 return close(fd);
402 }
403
404 /* Print a warning messages in case that the given signal is not
405 * blocked or trapped */
406 void pa_check_signal_is_blocked(int sig) {
407 #ifdef HAVE_SIGACTION
408 struct sigaction sa;
409 sigset_t set;
410
411 /* If POSIX threads are supported use thread-aware
412 * pthread_sigmask() function, to check if the signal is
413 * blocked. Otherwise fall back to sigprocmask() */
414
415 #ifdef HAVE_PTHREAD
416 if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
417 #endif
418 if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
419 pa_log("sigprocmask(): %s", pa_cstrerror(errno));
420 return;
421 }
422 #ifdef HAVE_PTHREAD
423 }
424 #endif
425
426 if (sigismember(&set, sig))
427 return;
428
429 /* Check whether the signal is trapped */
430
431 if (sigaction(sig, NULL, &sa) < 0) {
432 pa_log("sigaction(): %s", pa_cstrerror(errno));
433 return;
434 }
435
436 if (sa.sa_handler != SIG_DFL)
437 return;
438
439 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig));
440 #else /* HAVE_SIGACTION */
441 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig));
442 #endif
443 }
444
445 /* The following function is based on an example from the GNU libc
446 * documentation. This function is similar to GNU's asprintf(). */
447 char *pa_sprintf_malloc(const char *format, ...) {
448 int size = 100;
449 char *c = NULL;
450
451 pa_assert(format);
452
453 for(;;) {
454 int r;
455 va_list ap;
456
457 c = pa_xrealloc(c, size);
458
459 va_start(ap, format);
460 r = vsnprintf(c, size, format, ap);
461 va_end(ap);
462
463 c[size-1] = 0;
464
465 if (r > -1 && r < size)
466 return c;
467
468 if (r > -1) /* glibc 2.1 */
469 size = r+1;
470 else /* glibc 2.0 */
471 size *= 2;
472 }
473 }
474
475 /* Same as the previous function, but use a va_list instead of an
476 * ellipsis */
477 char *pa_vsprintf_malloc(const char *format, va_list ap) {
478 int size = 100;
479 char *c = NULL;
480
481 pa_assert(format);
482
483 for(;;) {
484 int r;
485 va_list aq;
486
487 c = pa_xrealloc(c, size);
488
489 va_copy(aq, ap);
490 r = vsnprintf(c, size, format, aq);
491 va_end(aq);
492
493 c[size-1] = 0;
494
495 if (r > -1 && r < size)
496 return c;
497
498 if (r > -1) /* glibc 2.1 */
499 size = r+1;
500 else /* glibc 2.0 */
501 size *= 2;
502 }
503 }
504
505 /* Similar to OpenBSD's strlcpy() function */
506 char *pa_strlcpy(char *b, const char *s, size_t l) {
507 pa_assert(b);
508 pa_assert(s);
509 pa_assert(l > 0);
510
511 strncpy(b, s, l);
512 b[l-1] = 0;
513 return b;
514 }
515
516 /* Make the current thread a realtime thread, and acquire the highest
517 * rtprio we can get that is less or equal the specified parameter. If
518 * the thread is already realtime, don't do anything. */
519 int pa_make_realtime(int rtprio) {
520
521 #ifdef _POSIX_PRIORITY_SCHEDULING
522 struct sched_param sp;
523 int r, policy;
524
525 memset(&sp, 0, sizeof(sp));
526 policy = 0;
527
528 if ((r = pthread_getschedparam(pthread_self(), &policy, &sp)) != 0) {
529 pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r));
530 return -1;
531 }
532
533 if (policy == SCHED_FIFO && sp.sched_priority >= rtprio) {
534 pa_log_info("Thread already being scheduled with SCHED_FIFO with priority %i.", sp.sched_priority);
535 return 0;
536 }
537
538 sp.sched_priority = rtprio;
539 if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) != 0) {
540
541 while (sp.sched_priority > 1) {
542 sp.sched_priority --;
543
544 if ((r = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) == 0) {
545 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i.", sp.sched_priority, rtprio);
546 return 0;
547 }
548 }
549
550 pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r));
551 return -1;
552 }
553
554 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority);
555 return 0;
556 #else
557
558 errno = ENOTSUP;
559 return -1;
560 #endif
561 }
562
563 /* This is merely used for giving the user a hint. This is not correct
564 * for anything security related */
565 pa_bool_t pa_can_realtime(void) {
566
567 if (geteuid() == 0)
568 return TRUE;
569
570 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
571 {
572 struct rlimit rl;
573
574 if (getrlimit(RLIMIT_RTPRIO, &rl) >= 0)
575 if (rl.rlim_cur > 0 || rl.rlim_cur == RLIM_INFINITY)
576 return TRUE;
577 }
578 #endif
579
580 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
581 {
582 cap_t cap;
583
584 if ((cap = cap_get_proc())) {
585 cap_flag_value_t flag = CAP_CLEAR;
586
587 if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
588 if (flag == CAP_SET) {
589 cap_free(cap);
590 return TRUE;
591 }
592
593 cap_free(cap);
594 }
595 }
596 #endif
597
598 return FALSE;
599 }
600
601 /* This is merely used for giving the user a hint. This is not correct
602 * for anything security related */
603 pa_bool_t pa_can_high_priority(void) {
604
605 if (geteuid() == 0)
606 return TRUE;
607
608 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
609 {
610 struct rlimit rl;
611
612 if (getrlimit(RLIMIT_NICE, &rl) >= 0)
613 if (rl.rlim_cur >= 21 || rl.rlim_cur == RLIM_INFINITY)
614 return TRUE;
615 }
616 #endif
617
618 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
619 {
620 cap_t cap;
621
622 if ((cap = cap_get_proc())) {
623 cap_flag_value_t flag = CAP_CLEAR;
624
625 if (cap_get_flag(cap, CAP_SYS_NICE, CAP_EFFECTIVE, &flag) >= 0)
626 if (flag == CAP_SET) {
627 cap_free(cap);
628 return TRUE;
629 }
630
631 cap_free(cap);
632 }
633 }
634 #endif
635
636 return FALSE;
637 }
638
639 /* Raise the priority of the current process as much as possible that
640 * is <= the specified nice level..*/
641 int pa_raise_priority(int nice_level) {
642
643 #ifdef HAVE_SYS_RESOURCE_H
644 if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) {
645 int n;
646
647 for (n = nice_level+1; n < 0; n++) {
648
649 if (setpriority(PRIO_PROCESS, 0, n) == 0) {
650 pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level);
651 return 0;
652 }
653 }
654
655 pa_log_warn("setpriority(): %s", pa_cstrerror(errno));
656 return -1;
657 }
658
659 pa_log_info("Successfully gained nice level %i.", nice_level);
660 #endif
661
662 #ifdef OS_IS_WIN32
663 if (nice_level < 0) {
664 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
665 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
666 errno = EPERM;
667 return .-1;
668 } else
669 pa_log_info("Successfully gained high priority class.");
670 }
671 #endif
672
673 return 0;
674 }
675
676 /* Reset the priority to normal, inverting the changes made by
677 * pa_raise_priority() and pa_make_realtime()*/
678 void pa_reset_priority(void) {
679 #ifdef HAVE_SYS_RESOURCE_H
680 struct sched_param sp;
681
682 setpriority(PRIO_PROCESS, 0, 0);
683
684 memset(&sp, 0, sizeof(sp));
685 pa_assert_se(pthread_setschedparam(pthread_self(), SCHED_OTHER, &sp) == 0);
686 #endif
687
688 #ifdef OS_IS_WIN32
689 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
690 #endif
691 }
692
693 static int match(const char *expr, const char *v) {
694 int k;
695 regex_t re;
696
697 if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
698 errno = EINVAL;
699 return -1;
700 }
701
702 if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
703 return 1;
704 else if (k == REG_NOMATCH)
705 return 0;
706
707 errno = EINVAL;
708 return -1;
709 }
710
711 /* Try to parse a boolean string value.*/
712 int pa_parse_boolean(const char *v) {
713 const char *expr;
714 int r;
715 pa_assert(v);
716
717 /* First we check language independant */
718 if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
719 return 1;
720 else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
721 return 0;
722
723 /* And then we check language dependant */
724 if ((expr = nl_langinfo(YESEXPR)))
725 if (expr[0])
726 if ((r = match(expr, v)) > 0)
727 return 1;
728
729 if ((expr = nl_langinfo(NOEXPR)))
730 if (expr[0])
731 if ((r = match(expr, v)) > 0)
732 return 0;
733
734 errno = EINVAL;
735 return -1;
736 }
737
738 /* Split the specified string wherever one of the strings in delimiter
739 * occurs. Each time it is called returns a newly allocated string
740 * with pa_xmalloc(). The variable state points to, should be
741 * initiallized to NULL before the first call. */
742 char *pa_split(const char *c, const char *delimiter, const char**state) {
743 const char *current = *state ? *state : c;
744 size_t l;
745
746 if (!*current)
747 return NULL;
748
749 l = strcspn(current, delimiter);
750 *state = current+l;
751
752 if (**state)
753 (*state)++;
754
755 return pa_xstrndup(current, l);
756 }
757
758 /* What is interpreted as whitespace? */
759 #define WHITESPACE " \t\n"
760
761 /* Split a string into words. Otherwise similar to pa_split(). */
762 char *pa_split_spaces(const char *c, const char **state) {
763 const char *current = *state ? *state : c;
764 size_t l;
765
766 if (!*current || *c == 0)
767 return NULL;
768
769 current += strspn(current, WHITESPACE);
770 l = strcspn(current, WHITESPACE);
771
772 *state = current+l;
773
774 return pa_xstrndup(current, l);
775 }
776
777 PA_STATIC_TLS_DECLARE(signame, pa_xfree);
778
779 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
780 const char *pa_sig2str(int sig) {
781 char *t;
782
783 if (sig <= 0)
784 goto fail;
785
786 #ifdef NSIG
787 if (sig >= NSIG)
788 goto fail;
789 #endif
790
791 #ifdef HAVE_SIG2STR
792 {
793 char buf[SIG2STR_MAX];
794
795 if (sig2str(sig, buf) == 0) {
796 pa_xfree(PA_STATIC_TLS_GET(signame));
797 t = pa_sprintf_malloc("SIG%s", buf);
798 PA_STATIC_TLS_SET(signame, t);
799 return t;
800 }
801 }
802 #else
803
804 switch(sig) {
805 #ifdef SIGHUP
806 case SIGHUP: return "SIGHUP";
807 #endif
808 case SIGINT: return "SIGINT";
809 #ifdef SIGQUIT
810 case SIGQUIT: return "SIGQUIT";
811 #endif
812 case SIGILL: return "SIGULL";
813 #ifdef SIGTRAP
814 case SIGTRAP: return "SIGTRAP";
815 #endif
816 case SIGABRT: return "SIGABRT";
817 #ifdef SIGBUS
818 case SIGBUS: return "SIGBUS";
819 #endif
820 case SIGFPE: return "SIGFPE";
821 #ifdef SIGKILL
822 case SIGKILL: return "SIGKILL";
823 #endif
824 #ifdef SIGUSR1
825 case SIGUSR1: return "SIGUSR1";
826 #endif
827 case SIGSEGV: return "SIGSEGV";
828 #ifdef SIGUSR2
829 case SIGUSR2: return "SIGUSR2";
830 #endif
831 #ifdef SIGPIPE
832 case SIGPIPE: return "SIGPIPE";
833 #endif
834 #ifdef SIGALRM
835 case SIGALRM: return "SIGALRM";
836 #endif
837 case SIGTERM: return "SIGTERM";
838 #ifdef SIGSTKFLT
839 case SIGSTKFLT: return "SIGSTKFLT";
840 #endif
841 #ifdef SIGCHLD
842 case SIGCHLD: return "SIGCHLD";
843 #endif
844 #ifdef SIGCONT
845 case SIGCONT: return "SIGCONT";
846 #endif
847 #ifdef SIGSTOP
848 case SIGSTOP: return "SIGSTOP";
849 #endif
850 #ifdef SIGTSTP
851 case SIGTSTP: return "SIGTSTP";
852 #endif
853 #ifdef SIGTTIN
854 case SIGTTIN: return "SIGTTIN";
855 #endif
856 #ifdef SIGTTOU
857 case SIGTTOU: return "SIGTTOU";
858 #endif
859 #ifdef SIGURG
860 case SIGURG: return "SIGURG";
861 #endif
862 #ifdef SIGXCPU
863 case SIGXCPU: return "SIGXCPU";
864 #endif
865 #ifdef SIGXFSZ
866 case SIGXFSZ: return "SIGXFSZ";
867 #endif
868 #ifdef SIGVTALRM
869 case SIGVTALRM: return "SIGVTALRM";
870 #endif
871 #ifdef SIGPROF
872 case SIGPROF: return "SIGPROF";
873 #endif
874 #ifdef SIGWINCH
875 case SIGWINCH: return "SIGWINCH";
876 #endif
877 #ifdef SIGIO
878 case SIGIO: return "SIGIO";
879 #endif
880 #ifdef SIGPWR
881 case SIGPWR: return "SIGPWR";
882 #endif
883 #ifdef SIGSYS
884 case SIGSYS: return "SIGSYS";
885 #endif
886 }
887
888 #ifdef SIGRTMIN
889 if (sig >= SIGRTMIN && sig <= SIGRTMAX) {
890 pa_xfree(PA_STATIC_TLS_GET(signame));
891 t = pa_sprintf_malloc("SIGRTMIN+%i", sig - SIGRTMIN);
892 PA_STATIC_TLS_SET(signame, t);
893 return t;
894 }
895 #endif
896
897 #endif
898
899 fail:
900
901 pa_xfree(PA_STATIC_TLS_GET(signame));
902 t = pa_sprintf_malloc("SIG%i", sig);
903 PA_STATIC_TLS_SET(signame, t);
904 return t;
905 }
906
907 #ifdef HAVE_GRP_H
908
909 /* Check whether the specified GID and the group name match */
910 static int is_group(gid_t gid, const char *name) {
911 struct group group, *result = NULL;
912 long n;
913 void *data;
914 int r = -1;
915
916 #ifdef HAVE_GETGRGID_R
917 #ifdef _SC_GETGR_R_SIZE_MAX
918 n = sysconf(_SC_GETGR_R_SIZE_MAX);
919 #else
920 n = -1;
921 #endif
922 if (n < 0)
923 n = 512;
924
925 data = pa_xmalloc(n);
926
927 errno = 0;
928 if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) {
929 pa_log("getgrgid_r(%u): %s", (unsigned) gid, pa_cstrerror(errno));
930
931 if (!errno)
932 errno = ENOENT;
933
934 goto finish;
935 }
936
937 r = strcmp(name, result->gr_name) == 0;
938
939 finish:
940 pa_xfree(data);
941 #else
942 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
943 * support getgrgid_r. */
944
945 errno = 0;
946 if ((result = getgrgid(gid)) == NULL) {
947 pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno));
948
949 if (!errno)
950 errno = ENOENT;
951
952 goto finish;
953 }
954
955 r = strcmp(name, result->gr_name) == 0;
956
957 finish:
958 #endif
959
960 return r;
961 }
962
963 /* Check the current user is member of the specified group */
964 int pa_own_uid_in_group(const char *name, gid_t *gid) {
965 GETGROUPS_T *gids, tgid;
966 int n = sysconf(_SC_NGROUPS_MAX);
967 int r = -1, i, k;
968
969 pa_assert(n > 0);
970
971 gids = pa_xmalloc(sizeof(GETGROUPS_T)*n);
972
973 if ((n = getgroups(n, gids)) < 0) {
974 pa_log("getgroups(): %s", pa_cstrerror(errno));
975 goto finish;
976 }
977
978 for (i = 0; i < n; i++) {
979
980 if ((k = is_group(gids[i], name)) < 0)
981 goto finish;
982 else if (k > 0) {
983 *gid = gids[i];
984 r = 1;
985 goto finish;
986 }
987 }
988
989 if ((k = is_group(tgid = getgid(), name)) < 0)
990 goto finish;
991 else if (k > 0) {
992 *gid = tgid;
993 r = 1;
994 goto finish;
995 }
996
997 r = 0;
998
999 finish:
1000
1001 pa_xfree(gids);
1002 return r;
1003 }
1004
1005 /* Check whether the specifc user id is a member of the specified group */
1006 int pa_uid_in_group(uid_t uid, const char *name) {
1007 char *g_buf, *p_buf;
1008 long g_n, p_n;
1009 struct group grbuf, *gr;
1010 char **i;
1011 int r = -1;
1012
1013 g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
1014 g_buf = pa_xmalloc(g_n);
1015
1016 p_n = sysconf(_SC_GETPW_R_SIZE_MAX);
1017 p_buf = pa_xmalloc(p_n);
1018
1019 errno = 0;
1020 if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) {
1021
1022 if (!errno)
1023 errno = ENOENT;
1024
1025 goto finish;
1026 }
1027
1028 r = 0;
1029 for (i = gr->gr_mem; *i; i++) {
1030 struct passwd pwbuf, *pw;
1031
1032 errno = 0;
1033 if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw)
1034 continue;
1035
1036 if (pw->pw_uid == uid) {
1037 r = 1;
1038 break;
1039 }
1040 }
1041
1042 finish:
1043 pa_xfree(g_buf);
1044 pa_xfree(p_buf);
1045
1046 return r;
1047 }
1048
1049 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1050 gid_t pa_get_gid_of_group(const char *name) {
1051 gid_t ret = (gid_t) -1;
1052 char *g_buf;
1053 long g_n;
1054 struct group grbuf, *gr;
1055
1056 g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
1057 g_buf = pa_xmalloc(g_n);
1058
1059 errno = 0;
1060 if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) {
1061
1062 if (!errno)
1063 errno = ENOENT;
1064
1065 goto finish;
1066 }
1067
1068 ret = gr->gr_gid;
1069
1070 finish:
1071 pa_xfree(g_buf);
1072 return ret;
1073 }
1074
1075 int pa_check_in_group(gid_t g) {
1076 gid_t gids[NGROUPS_MAX];
1077 int r;
1078
1079 if ((r = getgroups(NGROUPS_MAX, gids)) < 0)
1080 return -1;
1081
1082 for (; r > 0; r--)
1083 if (gids[r-1] == g)
1084 return 1;
1085
1086 return 0;
1087 }
1088
1089 #else /* HAVE_GRP_H */
1090
1091 int pa_own_uid_in_group(const char *name, gid_t *gid) {
1092 errno = ENOSUP;
1093 return -1;
1094
1095 }
1096
1097 int pa_uid_in_group(uid_t uid, const char *name) {
1098 errno = ENOSUP;
1099 return -1;
1100 }
1101
1102 gid_t pa_get_gid_of_group(const char *name) {
1103 errno = ENOSUP;
1104 return (gid_t) -1;
1105 }
1106
1107 int pa_check_in_group(gid_t g) {
1108 errno = ENOSUP;
1109 return -1;
1110 }
1111
1112 #endif
1113
1114 /* Lock or unlock a file entirely.
1115 (advisory on UNIX, mandatory on Windows) */
1116 int pa_lock_fd(int fd, int b) {
1117 #ifdef F_SETLKW
1118 struct flock flock;
1119
1120 /* Try a R/W lock first */
1121
1122 flock.l_type = b ? F_WRLCK : F_UNLCK;
1123 flock.l_whence = SEEK_SET;
1124 flock.l_start = 0;
1125 flock.l_len = 0;
1126
1127 if (fcntl(fd, F_SETLKW, &flock) >= 0)
1128 return 0;
1129
1130 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1131 if (b && errno == EBADF) {
1132 flock.l_type = F_RDLCK;
1133 if (fcntl(fd, F_SETLKW, &flock) >= 0)
1134 return 0;
1135 }
1136
1137 pa_log("%slock: %s", !b? "un" : "", pa_cstrerror(errno));
1138 #endif
1139
1140 #ifdef OS_IS_WIN32
1141 HANDLE h = (HANDLE)_get_osfhandle(fd);
1142
1143 if (b && LockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1144 return 0;
1145 if (!b && UnlockFile(h, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
1146 return 0;
1147
1148 pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
1149
1150 /* FIXME: Needs to set errno! */
1151 #endif
1152
1153 return -1;
1154 }
1155
1156 /* Remove trailing newlines from a string */
1157 char* pa_strip_nl(char *s) {
1158 pa_assert(s);
1159
1160 s[strcspn(s, "\r\n")] = 0;
1161 return s;
1162 }
1163
1164 /* Create a temporary lock file and lock it. */
1165 int pa_lock_lockfile(const char *fn) {
1166 int fd = -1;
1167 pa_assert(fn);
1168
1169 for (;;) {
1170 struct stat st;
1171
1172 if ((fd = open(fn, O_CREAT|O_RDWR
1173 #ifdef O_NOCTTY
1174 |O_NOCTTY
1175 #endif
1176 #ifdef O_NOFOLLOW
1177 |O_NOFOLLOW
1178 #endif
1179 , S_IRUSR|S_IWUSR)) < 0) {
1180 pa_log_warn("Failed to create lock file '%s': %s", fn, pa_cstrerror(errno));
1181 goto fail;
1182 }
1183
1184 if (pa_lock_fd(fd, 1) < 0) {
1185 pa_log_warn("Failed to lock file '%s'.", fn);
1186 goto fail;
1187 }
1188
1189 if (fstat(fd, &st) < 0) {
1190 pa_log_warn("Failed to fstat() file '%s': %s", fn, pa_cstrerror(errno));
1191 goto fail;
1192 }
1193
1194 /* Check wheter the file has been removed meanwhile. When yes,
1195 * restart this loop, otherwise, we're done */
1196 if (st.st_nlink >= 1)
1197 break;
1198
1199 if (pa_lock_fd(fd, 0) < 0) {
1200 pa_log_warn("Failed to unlock file '%s'.", fn);
1201 goto fail;
1202 }
1203
1204 if (pa_close(fd) < 0) {
1205 pa_log_warn("Failed to close file '%s': %s", fn, pa_cstrerror(errno));
1206 fd = -1;
1207 goto fail;
1208 }
1209
1210 fd = -1;
1211 }
1212
1213 return fd;
1214
1215 fail:
1216
1217 if (fd >= 0) {
1218 int saved_errno = errno;
1219 pa_close(fd);
1220 errno = saved_errno;
1221 }
1222
1223 return -1;
1224 }
1225
1226 /* Unlock a temporary lcok file */
1227 int pa_unlock_lockfile(const char *fn, int fd) {
1228 int r = 0;
1229 pa_assert(fd >= 0);
1230
1231 if (fn) {
1232 if (unlink(fn) < 0) {
1233 pa_log_warn("Unable to remove lock file '%s': %s", fn, pa_cstrerror(errno));
1234 r = -1;
1235 }
1236 }
1237
1238 if (pa_lock_fd(fd, 0) < 0) {
1239 pa_log_warn("Failed to unlock file '%s'.", fn);
1240 r = -1;
1241 }
1242
1243 if (pa_close(fd) < 0) {
1244 pa_log_warn("Failed to close '%s': %s", fn, pa_cstrerror(errno));
1245 r = -1;
1246 }
1247
1248 return r;
1249 }
1250
1251 static char *get_pulse_home(void) {
1252 char h[PATH_MAX];
1253 struct stat st;
1254
1255 if (!pa_get_home_dir(h, sizeof(h))) {
1256 pa_log_error("Failed to get home directory.");
1257 return NULL;
1258 }
1259
1260 if (stat(h, &st) < 0) {
1261 pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
1262 return NULL;
1263 }
1264
1265 if (st.st_uid != getuid()) {
1266 pa_log_error("Home directory %s not ours.", h);
1267 errno = EACCES;
1268 return NULL;
1269 }
1270
1271 return pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
1272 }
1273
1274 char *pa_get_state_dir(void) {
1275 char *d;
1276
1277 /* The state directory shall contain dynamic data that should be
1278 * kept across reboots, and is private to this user */
1279
1280 if (!(d = pa_xstrdup(getenv("PULSE_STATE_PATH"))))
1281 if (!(d = get_pulse_home()))
1282 return NULL;
1283
1284 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1285 * dir then this will break. */
1286
1287 if (pa_make_secure_dir(d, 0700, (pid_t) -1, (pid_t) -1) < 0) {
1288 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1289 pa_xfree(d);
1290 return NULL;
1291 }
1292
1293 return d;
1294 }
1295
1296 static char* make_random_dir(mode_t m) {
1297 static const char table[] =
1298 "abcdefghijklmnopqrstuvwxyz"
1299 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1300 "0123456789";
1301
1302 char fn[24] = "/tmp/pulse-";
1303
1304 fn[sizeof(fn)-1] = 0;
1305
1306 for (;;) {
1307 unsigned i;
1308 int r;
1309 mode_t u;
1310 int saved_errno;
1311
1312 for (i = 11; i < sizeof(fn)-1; i++)
1313 fn[i] = table[rand() % (sizeof(table)-1)];
1314
1315 u = umask((~m) & 0777);
1316 r = mkdir(fn, m);
1317 saved_errno = errno;
1318 umask(u);
1319
1320 if (r >= 0)
1321 return pa_xstrdup(fn);
1322
1323 errno = saved_errno;
1324
1325 if (errno != EEXIST) {
1326 pa_log_error("Failed to create random directory %s: %s", fn, pa_cstrerror(errno));
1327 return NULL;
1328 }
1329 }
1330 }
1331
1332 static int make_random_dir_and_link(mode_t m, const char *k) {
1333 char *p;
1334
1335 if (!(p = make_random_dir(m)))
1336 return -1;
1337
1338 if (symlink(p, k) < 0) {
1339 int saved_errno = errno;
1340
1341 if (errno != EEXIST)
1342 pa_log_error("Failed to symlink %s to %s: %s", k, p, pa_cstrerror(errno));
1343
1344 rmdir(p);
1345 pa_xfree(p);
1346
1347 errno = saved_errno;
1348 return -1;
1349 }
1350
1351 return 0;
1352 }
1353
1354 char *pa_get_runtime_dir(void) {
1355 char *d, *k = NULL, *p = NULL, *t = NULL, *mid;
1356 struct stat st;
1357
1358 /* The runtime directory shall contain dynamic data that needs NOT
1359 * to be kept accross reboots and is usuallly private to the user,
1360 * except in system mode, where it might be accessible by other
1361 * users, too. Since we need POSIX locking and UNIX sockets in
1362 * this directory, we link it to a random subdir in /tmp, if it
1363 * was not explicitly configured. */
1364
1365 if ((d = getenv("PULSE_RUNTIME_PATH"))) {
1366 mode_t m;
1367
1368 m = pa_in_system_mode() ? 0755 : 0700;
1369
1370 if (pa_make_secure_dir(d, m, (pid_t) -1, (pid_t) -1) < 0) {
1371 pa_log_error("Failed to create secure directory: %s", pa_cstrerror(errno));
1372 goto fail;
1373 }
1374
1375 return pa_xstrdup(d);
1376 }
1377
1378 if (!(d = get_pulse_home()))
1379 goto fail;
1380
1381 if (!(mid = pa_machine_id())) {
1382 pa_xfree(d);
1383 goto fail;
1384 }
1385
1386 k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:runtime", d, mid);
1387 pa_xfree(d);
1388 pa_xfree(mid);
1389
1390 for (;;) {
1391 /* OK, first let's check if the "runtime" symlink is already
1392 * existant */
1393
1394 if (!(p = pa_readlink(k))) {
1395
1396 if (errno != ENOENT) {
1397 pa_log_error("Failed to stat runtime directory %s: %s", k, pa_cstrerror(errno));
1398 goto fail;
1399 }
1400
1401 /* Hmm, so the runtime directory didn't exist yet, so let's
1402 * create one in /tmp and symlink that to it */
1403
1404 if (make_random_dir_and_link(0700, k) < 0) {
1405
1406 /* Mhmm, maybe another process was quicker than us,
1407 * let's check if that was valid */
1408 if (errno == EEXIST)
1409 continue;
1410
1411 goto fail;
1412 }
1413
1414 return k;
1415 }
1416
1417 /* Make sure that this actually makes sense */
1418 if (!pa_is_path_absolute(p)) {
1419 pa_log_error("Path %s in link %s is not absolute.", p, k);
1420 errno = ENOENT;
1421 goto fail;
1422 }
1423
1424 /* Hmm, so this symlink is still around, make sure nobody fools
1425 * us */
1426
1427 if (lstat(p, &st) < 0) {
1428
1429 if (errno != ENOENT) {
1430 pa_log_error("Failed to stat runtime directory %s: %s", p, pa_cstrerror(errno));
1431 goto fail;
1432 }
1433
1434 } else {
1435
1436 if (S_ISDIR(st.st_mode) &&
1437 (st.st_uid == getuid()) &&
1438 ((st.st_mode & 0777) == 0700)) {
1439
1440 pa_xfree(p);
1441 return k;
1442 }
1443
1444 pa_log_info("Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory.");
1445 }
1446
1447 pa_xfree(p);
1448 p = NULL;
1449
1450 /* Hmm, so the link points to some nonexisting or invalid
1451 * dir. Let's replace it by a new link. We first create a
1452 * temporary link and then rename that to allow concurrent
1453 * execution of this function. */
1454
1455 t = pa_sprintf_malloc("%s.tmp", k);
1456
1457 if (make_random_dir_and_link(0700, t) < 0) {
1458
1459 if (errno != EEXIST) {
1460 pa_log_error("Failed to symlink %s: %s", t, pa_cstrerror(errno));
1461 goto fail;
1462 }
1463
1464 pa_xfree(t);
1465 t = NULL;
1466
1467 /* Hmm, someone lese was quicker then us. Let's give
1468 * him some time to finish, and retry. */
1469 pa_msleep(10);
1470 continue;
1471 }
1472
1473 /* OK, we succeeded in creating the temporary symlink, so
1474 * let's rename it */
1475 if (rename(t, k) < 0) {
1476 pa_log_error("Failed to rename %s to %s: %s", t, k, pa_cstrerror(errno));
1477 goto fail;
1478 }
1479
1480 pa_xfree(t);
1481 return k;
1482 }
1483
1484 fail:
1485 pa_xfree(p);
1486 pa_xfree(k);
1487 pa_xfree(t);
1488
1489 return NULL;
1490 }
1491
1492 /* Try to open a configuration file. If "env" is specified, open the
1493 * value of the specified environment variable. Otherwise look for a
1494 * file "local" in the home directory or a file "global" in global
1495 * file system. If "result" is non-NULL, a pointer to a newly
1496 * allocated buffer containing the used configuration file is
1497 * stored there.*/
1498 FILE *pa_open_config_file(const char *global, const char *local, const char *env, char **result) {
1499 const char *fn;
1500 #ifdef OS_IS_WIN32
1501 char buf[PATH_MAX];
1502
1503 if (!getenv(PULSE_ROOTENV))
1504 pa_set_root(NULL);
1505 #endif
1506
1507 if (env && (fn = getenv(env))) {
1508 FILE *f;
1509
1510 #ifdef OS_IS_WIN32
1511 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1512 /* FIXME: Needs to set errno! */
1513 return NULL;
1514 fn = buf;
1515 #endif
1516
1517 if ((f = fopen(fn, "r"))) {
1518 if (result)
1519 *result = pa_xstrdup(fn);
1520
1521 return f;
1522 }
1523
1524 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1525 return NULL;
1526 }
1527
1528 if (local) {
1529 const char *e;
1530 char *lfn;
1531 char h[PATH_MAX];
1532 FILE *f;
1533
1534 if ((e = getenv("PULSE_CONFIG_PATH")))
1535 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1536 else if (pa_get_home_dir(h, sizeof(h)))
1537 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1538 else
1539 return NULL;
1540
1541 #ifdef OS_IS_WIN32
1542 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1543 /* FIXME: Needs to set errno! */
1544 pa_xfree(lfn);
1545 return NULL;
1546 }
1547 fn = buf;
1548 #endif
1549
1550 if ((f = fopen(fn, "r"))) {
1551 if (result)
1552 *result = pa_xstrdup(fn);
1553
1554 pa_xfree(lfn);
1555 return f;
1556 }
1557
1558 if (errno != ENOENT) {
1559 pa_log_warn("Failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
1560 pa_xfree(lfn);
1561 return NULL;
1562 }
1563
1564 pa_xfree(lfn);
1565 }
1566
1567 if (global) {
1568 FILE *f;
1569
1570 #ifdef OS_IS_WIN32
1571 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1572 /* FIXME: Needs to set errno! */
1573 return NULL;
1574 global = buf;
1575 #endif
1576
1577 if ((f = fopen(global, "r"))) {
1578
1579 if (result)
1580 *result = pa_xstrdup(global);
1581
1582 return f;
1583 }
1584 }
1585
1586 errno = ENOENT;
1587 return NULL;
1588 }
1589
1590 char *pa_find_config_file(const char *global, const char *local, const char *env) {
1591 const char *fn;
1592 #ifdef OS_IS_WIN32
1593 char buf[PATH_MAX];
1594
1595 if (!getenv(PULSE_ROOTENV))
1596 pa_set_root(NULL);
1597 #endif
1598
1599 if (env && (fn = getenv(env))) {
1600
1601 #ifdef OS_IS_WIN32
1602 if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
1603 /* FIXME: Needs to set errno! */
1604 return NULL;
1605 fn = buf;
1606 #endif
1607
1608 if (access(fn, R_OK) == 0)
1609 return pa_xstrdup(fn);
1610
1611 pa_log_warn("Failed to access 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[PATH_MAX];
1619
1620 if ((e = getenv("PULSE_CONFIG_PATH")))
1621 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
1622 else if (pa_get_home_dir(h, sizeof(h)))
1623 fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
1624 else
1625 return NULL;
1626
1627 #ifdef OS_IS_WIN32
1628 if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
1629 /* FIXME: Needs to set errno! */
1630 pa_xfree(lfn);
1631 return NULL;
1632 }
1633 fn = buf;
1634 #endif
1635
1636 if (access(fn, R_OK) == 0) {
1637 char *r = pa_xstrdup(fn);
1638 pa_xfree(lfn);
1639 return r;
1640 }
1641
1642 if (errno != ENOENT) {
1643 pa_log_warn("Failed to access configuration file '%s': %s", fn, pa_cstrerror(errno));
1644 pa_xfree(lfn);
1645 return NULL;
1646 }
1647
1648 pa_xfree(lfn);
1649 }
1650
1651 if (global) {
1652 #ifdef OS_IS_WIN32
1653 if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
1654 /* FIXME: Needs to set errno! */
1655 return NULL;
1656 global = buf;
1657 #endif
1658
1659 if (access(global, R_OK) == 0)
1660 return pa_xstrdup(global);
1661 }
1662
1663 errno = ENOENT;
1664
1665 return NULL;
1666 }
1667
1668 /* Format the specified data as a hexademical string */
1669 char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
1670 size_t i = 0, j = 0;
1671 const char hex[] = "0123456789abcdef";
1672
1673 pa_assert(d);
1674 pa_assert(s);
1675 pa_assert(slength > 0);
1676
1677 while (i < dlength && j+3 <= slength) {
1678 s[j++] = hex[*d >> 4];
1679 s[j++] = hex[*d & 0xF];
1680
1681 d++;
1682 i++;
1683 }
1684
1685 s[j < slength ? j : slength] = 0;
1686 return s;
1687 }
1688
1689 /* Convert a hexadecimal digit to a number or -1 if invalid */
1690 static int hexc(char c) {
1691 if (c >= '0' && c <= '9')
1692 return c - '0';
1693
1694 if (c >= 'A' && c <= 'F')
1695 return c - 'A' + 10;
1696
1697 if (c >= 'a' && c <= 'f')
1698 return c - 'a' + 10;
1699
1700 errno = EINVAL;
1701 return -1;
1702 }
1703
1704 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1705 size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
1706 size_t j = 0;
1707
1708 pa_assert(p);
1709 pa_assert(d);
1710
1711 while (j < dlength && *p) {
1712 int b;
1713
1714 if ((b = hexc(*(p++))) < 0)
1715 return (size_t) -1;
1716
1717 d[j] = (uint8_t) (b << 4);
1718
1719 if (!*p)
1720 return (size_t) -1;
1721
1722 if ((b = hexc(*(p++))) < 0)
1723 return (size_t) -1;
1724
1725 d[j] |= (uint8_t) b;
1726 j++;
1727 }
1728
1729 return j;
1730 }
1731
1732 /* Returns nonzero when *s starts with *pfx */
1733 pa_bool_t pa_startswith(const char *s, const char *pfx) {
1734 size_t l;
1735
1736 pa_assert(s);
1737 pa_assert(pfx);
1738
1739 l = strlen(pfx);
1740
1741 return strlen(s) >= l && strncmp(s, pfx, l) == 0;
1742 }
1743
1744 /* Returns nonzero when *s ends with *sfx */
1745 pa_bool_t pa_endswith(const char *s, const char *sfx) {
1746 size_t l1, l2;
1747
1748 pa_assert(s);
1749 pa_assert(sfx);
1750
1751 l1 = strlen(s);
1752 l2 = strlen(sfx);
1753
1754 return l1 >= l2 && strcmp(s+l1-l2, sfx) == 0;
1755 }
1756
1757 pa_bool_t pa_is_path_absolute(const char *fn) {
1758 pa_assert(fn);
1759
1760 #ifndef OS_IS_WIN32
1761 return *fn == '/';
1762 #else
1763 return strlen(fn) >= 3 && isalpha(fn[0]) && fn[1] == ':' && fn[2] == '\\';
1764 #endif
1765 }
1766
1767 char *pa_make_path_absolute(const char *p) {
1768 char *r;
1769 char *cwd;
1770
1771 pa_assert(p);
1772
1773 if (pa_is_path_absolute(p))
1774 return pa_xstrdup(p);
1775
1776 if (!(cwd = pa_getcwd()))
1777 return pa_xstrdup(p);
1778
1779 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", cwd, p);
1780 pa_xfree(cwd);
1781 return r;
1782 }
1783
1784 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1785 * if fn is non-null and starts with / return fn
1786 * otherwise append fn to the run time path and return it */
1787 static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
1788 char *rtp;
1789
1790 if (pa_is_path_absolute(fn))
1791 return pa_xstrdup(fn);
1792
1793 rtp = rt ? pa_get_runtime_dir() : pa_get_state_dir();
1794
1795 if (!rtp)
1796 return NULL;
1797
1798 if (fn) {
1799 char *r;
1800
1801 if (prependmid) {
1802 char *mid;
1803
1804 if (!(mid = pa_machine_id())) {
1805 pa_xfree(rtp);
1806 return NULL;
1807 }
1808
1809 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:%s", rtp, mid, fn);
1810 pa_xfree(mid);
1811 } else
1812 r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
1813
1814 pa_xfree(rtp);
1815 return r;
1816 } else
1817 return rtp;
1818 }
1819
1820 char *pa_runtime_path(const char *fn) {
1821 return get_path(fn, FALSE, TRUE);
1822 }
1823
1824 char *pa_state_path(const char *fn, pa_bool_t appendmid) {
1825 return get_path(fn, appendmid, FALSE);
1826 }
1827
1828 /* Convert the string s to a signed integer in *ret_i */
1829 int pa_atoi(const char *s, int32_t *ret_i) {
1830 char *x = NULL;
1831 long l;
1832
1833 pa_assert(s);
1834 pa_assert(ret_i);
1835
1836 errno = 0;
1837 l = strtol(s, &x, 0);
1838
1839 if (!x || *x || errno) {
1840 if (!errno)
1841 errno = EINVAL;
1842 return -1;
1843 }
1844
1845 if ((int32_t) l != l) {
1846 errno = ERANGE;
1847 return -1;
1848 }
1849
1850 *ret_i = (int32_t) l;
1851
1852 return 0;
1853 }
1854
1855 /* Convert the string s to an unsigned integer in *ret_u */
1856 int pa_atou(const char *s, uint32_t *ret_u) {
1857 char *x = NULL;
1858 unsigned long l;
1859
1860 pa_assert(s);
1861 pa_assert(ret_u);
1862
1863 errno = 0;
1864 l = strtoul(s, &x, 0);
1865
1866 if (!x || *x || errno) {
1867 if (!errno)
1868 errno = EINVAL;
1869 return -1;
1870 }
1871
1872 if ((uint32_t) l != l) {
1873 errno = ERANGE;
1874 return -1;
1875 }
1876
1877 *ret_u = (uint32_t) l;
1878
1879 return 0;
1880 }
1881
1882 #ifdef HAVE_STRTOF_L
1883 static locale_t c_locale = NULL;
1884
1885 static void c_locale_destroy(void) {
1886 freelocale(c_locale);
1887 }
1888 #endif
1889
1890 int pa_atod(const char *s, double *ret_d) {
1891 char *x = NULL;
1892 double f;
1893
1894 pa_assert(s);
1895 pa_assert(ret_d);
1896
1897 /* This should be locale independent */
1898
1899 #ifdef HAVE_STRTOF_L
1900
1901 PA_ONCE_BEGIN {
1902
1903 if ((c_locale = newlocale(LC_ALL_MASK, "C", NULL)))
1904 atexit(c_locale_destroy);
1905
1906 } PA_ONCE_END;
1907
1908 if (c_locale) {
1909 errno = 0;
1910 f = strtod_l(s, &x, c_locale);
1911 } else
1912 #endif
1913 {
1914 errno = 0;
1915 f = strtod(s, &x);
1916 }
1917
1918 if (!x || *x || errno) {
1919 if (!errno)
1920 errno = EINVAL;
1921 return -1;
1922 }
1923
1924 *ret_d = f;
1925
1926 return 0;
1927 }
1928
1929 /* Same as snprintf, but guarantees NUL-termination on every platform */
1930 int pa_snprintf(char *str, size_t size, const char *format, ...) {
1931 int ret;
1932 va_list ap;
1933
1934 pa_assert(str);
1935 pa_assert(size > 0);
1936 pa_assert(format);
1937
1938 va_start(ap, format);
1939 ret = pa_vsnprintf(str, size, format, ap);
1940 va_end(ap);
1941
1942 return ret;
1943 }
1944
1945 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
1946 int pa_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
1947 int ret;
1948
1949 pa_assert(str);
1950 pa_assert(size > 0);
1951 pa_assert(format);
1952
1953 ret = vsnprintf(str, size, format, ap);
1954
1955 str[size-1] = 0;
1956
1957 if (ret < 0)
1958 ret = strlen(str);
1959
1960 return PA_MIN((int) size-1, ret);
1961 }
1962
1963 /* Truncate the specified string, but guarantee that the string
1964 * returned still validates as UTF8 */
1965 char *pa_truncate_utf8(char *c, size_t l) {
1966 pa_assert(c);
1967 pa_assert(pa_utf8_valid(c));
1968
1969 if (strlen(c) <= l)
1970 return c;
1971
1972 c[l] = 0;
1973
1974 while (l > 0 && !pa_utf8_valid(c))
1975 c[--l] = 0;
1976
1977 return c;
1978 }
1979
1980 char *pa_getcwd(void) {
1981 size_t l = 128;
1982
1983 for (;;) {
1984 char *p = pa_xnew(char, l);
1985 if (getcwd(p, l))
1986 return p;
1987
1988 if (errno != ERANGE)
1989 return NULL;
1990
1991 pa_xfree(p);
1992 l *= 2;
1993 }
1994 }
1995
1996 void *pa_will_need(const void *p, size_t l) {
1997 #ifdef RLIMIT_MEMLOCK
1998 struct rlimit rlim;
1999 #endif
2000 const void *a;
2001 size_t size;
2002 int r;
2003 size_t bs;
2004
2005 pa_assert(p);
2006 pa_assert(l > 0);
2007
2008 a = PA_PAGE_ALIGN_PTR(p);
2009 size = (const uint8_t*) p + l - (const uint8_t*) a;
2010
2011 #ifdef HAVE_POSIX_MADVISE
2012 if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
2013 pa_log_debug("posix_madvise() worked fine!");
2014 return (void*) p;
2015 }
2016 #endif
2017
2018 /* Most likely the memory was not mmap()ed from a file and thus
2019 * madvise() didn't work, so let's misuse mlock() do page this
2020 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2021 * inviting, the man page of mlock() tells us: "All pages that
2022 * contain a part of the specified address range are guaranteed to
2023 * be resident in RAM when the call returns successfully." */
2024
2025 #ifdef RLIMIT_MEMLOCK
2026 pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
2027
2028 if (rlim.rlim_cur < PA_PAGE_SIZE) {
2029 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));
2030 errno = EPERM;
2031 return (void*) p;
2032 }
2033
2034 bs = PA_PAGE_ALIGN(rlim.rlim_cur);
2035 #else
2036 bs = PA_PAGE_SIZE*4;
2037 #endif
2038
2039 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r));
2040
2041 #ifdef HAVE_MLOCK
2042 while (size > 0 && bs > 0) {
2043
2044 if (bs > size)
2045 bs = size;
2046
2047 if (mlock(a, bs) < 0) {
2048 bs = PA_PAGE_ALIGN(bs / 2);
2049 continue;
2050 }
2051
2052 pa_assert_se(munlock(a, bs) == 0);
2053
2054 a = (const uint8_t*) a + bs;
2055 size -= bs;
2056 }
2057 #endif
2058
2059 if (bs <= 0)
2060 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno));
2061 else
2062 pa_log_debug("mlock() worked fine!");
2063
2064 return (void*) p;
2065 }
2066
2067 void pa_close_pipe(int fds[2]) {
2068 pa_assert(fds);
2069
2070 if (fds[0] >= 0)
2071 pa_assert_se(pa_close(fds[0]) == 0);
2072
2073 if (fds[1] >= 0)
2074 pa_assert_se(pa_close(fds[1]) == 0);
2075
2076 fds[0] = fds[1] = -1;
2077 }
2078
2079 char *pa_readlink(const char *p) {
2080 size_t l = 100;
2081
2082 for (;;) {
2083 char *c;
2084 ssize_t n;
2085
2086 c = pa_xnew(char, l);
2087
2088 if ((n = readlink(p, c, l-1)) < 0) {
2089 pa_xfree(c);
2090 return NULL;
2091 }
2092
2093 if ((size_t) n < l-1) {
2094 c[n] = 0;
2095 return c;
2096 }
2097
2098 pa_xfree(c);
2099 l *= 2;
2100 }
2101 }
2102
2103 int pa_close_all(int except_fd, ...) {
2104 va_list ap;
2105 int n = 0, i, r;
2106 int *p;
2107
2108 va_start(ap, except_fd);
2109
2110 if (except_fd >= 0)
2111 for (n = 1; va_arg(ap, int) >= 0; n++)
2112 ;
2113
2114 va_end(ap);
2115
2116 p = pa_xnew(int, n+1);
2117
2118 va_start(ap, except_fd);
2119
2120 i = 0;
2121 if (except_fd >= 0) {
2122 int fd;
2123 p[i++] = except_fd;
2124
2125 while ((fd = va_arg(ap, int)) >= 0)
2126 p[i++] = fd;
2127 }
2128 p[i] = -1;
2129
2130 va_end(ap);
2131
2132 r = pa_close_allv(p);
2133 free(p);
2134
2135 return r;
2136 }
2137
2138 int pa_close_allv(const int except_fds[]) {
2139 struct rlimit rl;
2140 int fd;
2141 int saved_errno;
2142
2143 #ifdef __linux__
2144
2145 DIR *d;
2146
2147 if ((d = opendir("/proc/self/fd"))) {
2148
2149 struct dirent *de;
2150
2151 while ((de = readdir(d))) {
2152 pa_bool_t found;
2153 long l;
2154 char *e = NULL;
2155 int i;
2156
2157 if (de->d_name[0] == '.')
2158 continue;
2159
2160 errno = 0;
2161 l = strtol(de->d_name, &e, 10);
2162 if (errno != 0 || !e || *e) {
2163 closedir(d);
2164 errno = EINVAL;
2165 return -1;
2166 }
2167
2168 fd = (int) l;
2169
2170 if ((long) fd != l) {
2171 closedir(d);
2172 errno = EINVAL;
2173 return -1;
2174 }
2175
2176 if (fd < 3)
2177 continue;
2178
2179 if (fd == dirfd(d))
2180 continue;
2181
2182 found = FALSE;
2183 for (i = 0; except_fds[i] >= 0; i++)
2184 if (except_fds[i] == fd) {
2185 found = TRUE;
2186 break;
2187 }
2188
2189 if (found)
2190 continue;
2191
2192 if (pa_close(fd) < 0) {
2193 saved_errno = errno;
2194 closedir(d);
2195 errno = saved_errno;
2196
2197 return -1;
2198 }
2199 }
2200
2201 closedir(d);
2202 return 0;
2203 }
2204
2205 #endif
2206
2207 if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
2208 return -1;
2209
2210 for (fd = 3; fd < (int) rl.rlim_max; fd++) {
2211 int i;
2212 pa_bool_t found;
2213
2214 found = FALSE;
2215 for (i = 0; except_fds[i] >= 0; i++)
2216 if (except_fds[i] == fd) {
2217 found = TRUE;
2218 break;
2219 }
2220
2221 if (found)
2222 continue;
2223
2224 if (pa_close(fd) < 0 && errno != EBADF)
2225 return -1;
2226 }
2227
2228 return 0;
2229 }
2230
2231 int pa_unblock_sigs(int except, ...) {
2232 va_list ap;
2233 int n = 0, i, r;
2234 int *p;
2235
2236 va_start(ap, except);
2237
2238 if (except >= 1)
2239 for (n = 1; va_arg(ap, int) >= 0; n++)
2240 ;
2241
2242 va_end(ap);
2243
2244 p = pa_xnew(int, n+1);
2245
2246 va_start(ap, except);
2247
2248 i = 0;
2249 if (except >= 1) {
2250 int sig;
2251 p[i++] = except;
2252
2253 while ((sig = va_arg(ap, int)) >= 0)
2254 p[i++] = sig;
2255 }
2256 p[i] = -1;
2257
2258 va_end(ap);
2259
2260 r = pa_unblock_sigsv(p);
2261 pa_xfree(p);
2262
2263 return r;
2264 }
2265
2266 int pa_unblock_sigsv(const int except[]) {
2267 int i;
2268 sigset_t ss;
2269
2270 if (sigemptyset(&ss) < 0)
2271 return -1;
2272
2273 for (i = 0; except[i] > 0; i++)
2274 if (sigaddset(&ss, except[i]) < 0)
2275 return -1;
2276
2277 return sigprocmask(SIG_SETMASK, &ss, NULL);
2278 }
2279
2280 int pa_reset_sigs(int except, ...) {
2281 va_list ap;
2282 int n = 0, i, r;
2283 int *p;
2284
2285 va_start(ap, except);
2286
2287 if (except >= 1)
2288 for (n = 1; va_arg(ap, int) >= 0; n++)
2289 ;
2290
2291 va_end(ap);
2292
2293 p = pa_xnew(int, n+1);
2294
2295 va_start(ap, except);
2296
2297 i = 0;
2298 if (except >= 1) {
2299 int sig;
2300 p[i++] = except;
2301
2302 while ((sig = va_arg(ap, int)) >= 0)
2303 sig = p[i++];
2304 }
2305 p[i] = -1;
2306
2307 va_end(ap);
2308
2309 r = pa_reset_sigsv(p);
2310 pa_xfree(p);
2311
2312 return r;
2313 }
2314
2315 int pa_reset_sigsv(const int except[]) {
2316 int sig;
2317
2318 for (sig = 1; sig < _NSIG; sig++) {
2319 pa_bool_t reset = TRUE;
2320
2321 switch (sig) {
2322 case SIGKILL:
2323 case SIGSTOP:
2324 reset = FALSE;
2325 break;
2326
2327 default: {
2328 int i;
2329
2330 for (i = 0; except[i] > 0; i++) {
2331 if (sig == except[i]) {
2332 reset = FALSE;
2333 break;
2334 }
2335 }
2336 }
2337 }
2338
2339 if (reset) {
2340 struct sigaction sa;
2341
2342 memset(&sa, 0, sizeof(sa));
2343 sa.sa_handler = SIG_DFL;
2344
2345 /* On Linux the first two RT signals are reserved by
2346 * glibc, and sigaction() will return EINVAL for them. */
2347 if ((sigaction(sig, &sa, NULL) < 0))
2348 if (errno != EINVAL)
2349 return -1;
2350 }
2351 }
2352
2353 return 0;
2354 }
2355
2356 void pa_set_env(const char *key, const char *value) {
2357 pa_assert(key);
2358 pa_assert(value);
2359
2360 putenv(pa_sprintf_malloc("%s=%s", key, value));
2361 }
2362
2363 pa_bool_t pa_in_system_mode(void) {
2364 const char *e;
2365
2366 if (!(e = getenv("PULSE_SYSTEM")))
2367 return FALSE;
2368
2369 return !!atoi(e);
2370 }
2371
2372 char *pa_machine_id(void) {
2373 FILE *f;
2374 size_t l;
2375
2376 if ((f = fopen(PA_MACHINE_ID, "r"))) {
2377 char ln[34] = "", *r;
2378
2379 r = fgets(ln, sizeof(ln)-1, f);
2380 fclose(f);
2381
2382 if (r)
2383 return pa_xstrdup(pa_strip_nl(ln));
2384 }
2385
2386 l = 100;
2387
2388 for (;;) {
2389 char *c;
2390
2391 c = pa_xnew(char, l);
2392
2393 if (!pa_get_host_name(c, l)) {
2394
2395 if (errno == EINVAL || errno == ENAMETOOLONG) {
2396 pa_xfree(c);
2397 l *= 2;
2398 continue;
2399 }
2400
2401 return NULL;
2402 }
2403
2404 if (strlen(c) < l-1)
2405 return c;
2406
2407 /* Hmm, the hostname is as long the space we offered the
2408 * function, we cannot know if it fully fit in, so let's play
2409 * safe and retry. */
2410
2411 pa_xfree(c);
2412 l *= 2;
2413 }
2414 }