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