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