4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2004 Joe Marcus Clarke
8 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
41 #include <sys/types.h>
53 #ifdef HAVE_SYS_RESOURCE_H
54 #include <sys/resource.h>
57 #ifdef HAVE_SYS_CAPABILITY_H
58 #include <sys/capability.h>
61 #ifdef HAVE_SYS_MMAN_H
85 #ifdef HAVE_LIBSAMPLERATE
86 #include <samplerate.h>
89 #include <pulse/xmalloc.h>
90 #include <pulse/util.h>
91 #include <pulse/utf8.h>
93 #include <pulsecore/core-error.h>
94 #include <pulsecore/winsock.h>
95 #include <pulsecore/log.h>
96 #include <pulsecore/macro.h>
97 #include <pulsecore/thread.h>
99 #include "core-util.h"
101 /* Not all platforms have this */
103 #define MSG_NOSIGNAL 0
107 #define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-"
109 #define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-"
114 #define PULSE_ROOTENV "PULSE_ROOT"
116 int pa_set_root(HANDLE handle
) {
117 char library_path
[MAX_PATH
+ sizeof(PULSE_ROOTENV
) + 1], *sep
;
119 strcpy(library_path
, PULSE_ROOTENV
"=");
121 if (!GetModuleFileName(handle
, library_path
+ sizeof(PULSE_ROOTENV
), MAX_PATH
))
124 sep
= strrchr(library_path
, PA_PATH_SEP_CHAR
);
128 if (_putenv(library_path
) < 0)
136 /** Make a file descriptor nonblock. Doesn't do any error checking */
137 void pa_make_nonblock_fd(int fd
) {
142 if ((v
= fcntl(fd
, F_GETFL
)) >= 0)
143 if (!(v
& O_NONBLOCK
))
144 fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
);
145 #elif defined(OS_IS_WIN32)
147 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
148 if (WSAGetLastError() == WSAENOTSOCK
)
149 pa_log_warn("Only sockets can be made non-blocking!");
152 pa_log_warn("Non-blocking I/O not supported.!");
156 /** Creates a directory securely */
157 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
174 if (r
< 0 && errno
!= EEXIST
)
178 if (uid
== (uid_t
)-1)
180 if (gid
== (gid_t
)-1)
182 (void) chown(dir
, uid
, gid
);
190 if (lstat(dir
, &st
) < 0)
192 if (stat(dir
, &st
) < 0)
197 if (!S_ISDIR(st
.st_mode
) ||
198 (st
.st_uid
!= uid
) ||
199 (st
.st_gid
!= gid
) ||
200 ((st
.st_mode
& 0777) != m
)) {
205 pa_log_warn("secure directory creation not supported on Win32.");
215 /* Return a newly allocated sting containing the parent directory of the specified file */
216 char *pa_parent_dir(const char *fn
) {
217 char *slash
, *dir
= pa_xstrdup(fn
);
219 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
228 /* Creates a the parent directory of the specified path securely */
229 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
233 if (!(dir
= pa_parent_dir(fn
)))
236 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
246 /** Platform independent read function. Necessary since not all
247 * systems treat all file descriptors equal. If type is
248 * non-NULL it is used to cache the type of the fd. This is
249 * useful for making sure that only a single syscall is executed per
250 * function call. The variable pointed to should be initialized to 0
252 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
256 if (!type
|| *type
== 0) {
259 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
262 if (WSAGetLastError() != WSAENOTSOCK
) {
263 errno
= WSAGetLastError();
273 return read(fd
, buf
, count
);
276 /** Similar to pa_read(), but handles writes */
277 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
279 if (!type
|| *type
== 0) {
282 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0)
286 if (WSAGetLastError() != WSAENOTSOCK
) {
287 errno
= WSAGetLastError();
291 if (errno
!= ENOTSOCK
)
299 return write(fd
, buf
, count
);
302 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
303 * unless EOF is reached or an error occured */
304 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
320 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
327 data
= (uint8_t*) data
+ r
;
334 /** Similar to pa_loop_read(), but wraps write() */
335 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
351 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
358 data
= (const uint8_t*) data
+ r
;
365 /** Platform independent read function. Necessary since not all
366 * systems treat all file descriptors equal. */
367 int pa_close(int fd
) {
372 if ((ret
= closesocket(fd
)) == 0)
375 if (WSAGetLastError() != WSAENOTSOCK
) {
376 errno
= WSAGetLastError();
384 /* Print a warning messages in case that the given signal is not
385 * blocked or trapped */
386 void pa_check_signal_is_blocked(int sig
) {
387 #ifdef HAVE_SIGACTION
391 /* If POSIX threads are supported use thread-aware
392 * pthread_sigmask() function, to check if the signal is
393 * blocked. Otherwise fall back to sigprocmask() */
396 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
398 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
399 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
406 if (sigismember(&set
, sig
))
409 /* Check whether the signal is trapped */
411 if (sigaction(sig
, NULL
, &sa
) < 0) {
412 pa_log("sigaction(): %s", pa_cstrerror(errno
));
416 if (sa
.sa_handler
!= SIG_DFL
)
419 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
420 #else /* HAVE_SIGACTION */
421 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
425 /* The following function is based on an example from the GNU libc
426 * documentation. This function is similar to GNU's asprintf(). */
427 char *pa_sprintf_malloc(const char *format
, ...) {
437 c
= pa_xrealloc(c
, size
);
439 va_start(ap
, format
);
440 r
= vsnprintf(c
, size
, format
, ap
);
445 if (r
> -1 && r
< size
)
448 if (r
> -1) /* glibc 2.1 */
455 /* Same as the previous function, but use a va_list instead of an
457 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
467 c
= pa_xrealloc(c
, size
);
470 r
= vsnprintf(c
, size
, format
, aq
);
475 if (r
> -1 && r
< size
)
478 if (r
> -1) /* glibc 2.1 */
485 /* Similar to OpenBSD's strlcpy() function */
486 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
496 /* Make the current thread a realtime thread*/
497 void pa_make_realtime(void) {
499 #ifdef _POSIX_PRIORITY_SCHEDULING
500 struct sched_param sp
;
503 memset(&sp
, 0, sizeof(sp
));
506 if ((r
= pthread_getschedparam(pthread_self(), &policy
, &sp
)) != 0) {
507 pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r
));
511 sp
.sched_priority
= 1;
512 if ((r
= pthread_setschedparam(pthread_self(), SCHED_FIFO
, &sp
)) != 0) {
513 pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r
));
517 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread.");
522 #define NICE_LEVEL (-11)
524 /* Raise the priority of the current process as much as possible and
525 sensible: set the nice level to -15.*/
526 void pa_raise_priority(void) {
528 #ifdef HAVE_SYS_RESOURCE_H
529 if (setpriority(PRIO_PROCESS
, 0, NICE_LEVEL
) < 0)
530 pa_log_warn("setpriority(): %s", pa_cstrerror(errno
));
532 pa_log_info("Successfully gained nice level %i.", NICE_LEVEL
);
536 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
))
537 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
539 pa_log_info("Successfully gained high priority class.");
543 /* Reset the priority to normal, inverting the changes made by
544 * pa_raise_priority() */
545 void pa_reset_priority(void) {
547 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
550 #ifdef HAVE_SYS_RESOURCE_H
551 setpriority(PRIO_PROCESS
, 0, 0);
555 /* Set the FD_CLOEXEC flag for a fd */
556 int pa_fd_set_cloexec(int fd
, int b
) {
562 if ((v
= fcntl(fd
, F_GETFD
, 0)) < 0)
565 v
= (v
& ~FD_CLOEXEC
) | (b
? FD_CLOEXEC
: 0);
567 if (fcntl(fd
, F_SETFD
, v
) < 0)
574 /* Try to parse a boolean string value.*/
575 int pa_parse_boolean(const char *v
) {
577 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
579 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
585 /* Split the specified string wherever one of the strings in delimiter
586 * occurs. Each time it is called returns a newly allocated string
587 * with pa_xmalloc(). The variable state points to, should be
588 * initiallized to NULL before the first call. */
589 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
590 const char *current
= *state
? *state
: c
;
596 l
= strcspn(current
, delimiter
);
602 return pa_xstrndup(current
, l
);
605 /* What is interpreted as whitespace? */
606 #define WHITESPACE " \t\n"
608 /* Split a string into words. Otherwise similar to pa_split(). */
609 char *pa_split_spaces(const char *c
, const char **state
) {
610 const char *current
= *state
? *state
: c
;
613 if (!*current
|| *c
== 0)
616 current
+= strspn(current
, WHITESPACE
);
617 l
= strcspn(current
, WHITESPACE
);
621 return pa_xstrndup(current
, l
);
624 PA_STATIC_TLS_DECLARE(signame
, pa_xfree
);
626 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
627 const char *pa_sig2str(int sig
) {
630 if (sig
<= 0 || sig
>= _NSIG
)
635 char buf
[SIG2STR_MAX
];
637 if (str2sig(sig
, buf
) == 0) {
638 pa_xfree(PA_STATIC_TLS_GET(signame
));
639 t
= pa_sprintf_malloc("SIG%s", buf
);
640 PA_STATIC_TLS_SET(signame
, t
);
648 case SIGHUP
: return "SIGHUP";
650 case SIGINT
: return "SIGINT";
651 case SIGQUIT
: return "SIGQUIT";
652 case SIGILL
: return "SIGULL";
653 case SIGTRAP
: return "SIGTRAP";
654 case SIGABRT
: return "SIGABRT";
655 case SIGBUS
: return "SIGBUS";
656 case SIGFPE
: return "SIGFPE";
657 case SIGKILL
: return "SIGKILL";
659 case SIGUSR1
: return "SIGUSR1";
661 case SIGSEGV
: return "SIGSEGV";
663 case SIGUSR2
: return "SIGUSR2";
666 case SIGPIPE
: return "SIGPIPE";
668 case SIGALRM
: return "SIGALRM";
669 case SIGTERM
: return "SIGTERM";
670 case SIGSTKFLT
: return "SIGSTKFLT";
672 case SIGCHLD
: return "SIGCHLD";
674 case SIGCONT
: return "SIGCONT";
675 case SIGSTOP
: return "SIGSTOP";
676 case SIGTSTP
: return "SIGTSTP";
677 case SIGTTIN
: return "SIGTTIN";
678 case SIGTTOU
: return "SIGTTOU";
679 case SIGURG
: return "SIGURG";
681 case SIGXCPU
: return "SIGXCPU";
684 case SIGXFSZ
: return "SIGXFSZ";
686 case SIGVTALRM
: return "SIGVTALRM";
687 case SIGPROF
: return "SIGPROF";
688 case SIGWINCH
: return "SIGWINCH";
689 case SIGIO
: return "SIGIO";
690 case SIGPWR
: return "SIGPWR";
691 case SIGSYS
: return "SIGSYS";
695 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
696 pa_xfree(PA_STATIC_TLS_GET(signame
));
697 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
698 PA_STATIC_TLS_SET(signame
, t
);
707 pa_xfree(PA_STATIC_TLS_GET(signame
));
708 t
= pa_sprintf_malloc("SIG%i", sig
);
709 PA_STATIC_TLS_SET(signame
, t
);
715 /* Check whether the specified GID and the group name match */
716 static int is_group(gid_t gid
, const char *name
) {
717 struct group group
, *result
= NULL
;
722 #ifdef HAVE_GETGRGID_R
723 #ifdef _SC_GETGR_R_SIZE_MAX
724 n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
729 data
= pa_xmalloc(n
);
731 if (getgrgid_r(gid
, &group
, data
, n
, &result
) < 0 || !result
) {
732 pa_log("getgrgid_r(%u): %s", (unsigned)gid
, pa_cstrerror(errno
));
736 r
= strcmp(name
, result
->gr_name
) == 0;
741 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
742 * support getgrgid_r. */
743 if ((result
= getgrgid(gid
)) == NULL
) {
744 pa_log("getgrgid(%u): %s", gid
, pa_cstrerror(errno
));
748 r
= strcmp(name
, result
->gr_name
) == 0;
756 /* Check the current user is member of the specified group */
757 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
758 GETGROUPS_T
*gids
, tgid
;
759 int n
= sysconf(_SC_NGROUPS_MAX
);
764 gids
= pa_xmalloc(sizeof(GETGROUPS_T
)*n
);
766 if ((n
= getgroups(n
, gids
)) < 0) {
767 pa_log("getgroups(): %s", pa_cstrerror(errno
));
771 for (i
= 0; i
< n
; i
++) {
772 if (is_group(gids
[i
], name
) > 0) {
779 if (is_group(tgid
= getgid(), name
) > 0) {
793 /* Check whether the specifc user id is a member of the specified group */
794 int pa_uid_in_group(uid_t uid
, const char *name
) {
797 struct group grbuf
, *gr
;
801 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
802 g_buf
= pa_xmalloc(g_n
);
804 p_n
= sysconf(_SC_GETPW_R_SIZE_MAX
);
805 p_buf
= pa_xmalloc(p_n
);
807 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
811 for (i
= gr
->gr_mem
; *i
; i
++) {
812 struct passwd pwbuf
, *pw
;
814 if (getpwnam_r(*i
, &pwbuf
, p_buf
, (size_t) p_n
, &pw
) != 0 || !pw
)
817 if (pw
->pw_uid
== uid
) {
830 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
831 gid_t
pa_get_gid_of_group(const char *name
) {
832 gid_t ret
= (gid_t
) -1;
835 struct group grbuf
, *gr
;
837 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
838 g_buf
= pa_xmalloc(g_n
);
840 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
850 int pa_check_in_group(gid_t g
) {
851 gid_t gids
[NGROUPS_MAX
];
854 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
864 #else /* HAVE_GRP_H */
866 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
871 int pa_uid_in_group(uid_t uid
, const char *name
) {
875 gid_t
pa_get_gid_of_group(const char *name
) {
879 int pa_check_in_group(gid_t g
) {
885 /* Lock or unlock a file entirely.
886 (advisory on UNIX, mandatory on Windows) */
887 int pa_lock_fd(int fd
, int b
) {
891 /* Try a R/W lock first */
893 flock
.l_type
= b
? F_WRLCK
: F_UNLCK
;
894 flock
.l_whence
= SEEK_SET
;
898 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
901 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
902 if (b
&& errno
== EBADF
) {
903 flock
.l_type
= F_RDLCK
;
904 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
908 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
912 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
914 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
916 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
919 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
925 /* Remove trailing newlines from a string */
926 char* pa_strip_nl(char *s
) {
929 s
[strcspn(s
, "\r\n")] = 0;
933 /* Create a temporary lock file and lock it. */
934 int pa_lock_lockfile(const char *fn
) {
941 if ((fd
= open(fn
, O_CREAT
|O_RDWR
, S_IRUSR
|S_IWUSR
)) < 0) {
942 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
946 if (pa_lock_fd(fd
, 1) < 0) {
947 pa_log_warn("Failed to lock file '%s'.", fn
);
951 if (fstat(fd
, &st
) < 0) {
952 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
956 /* Check wheter the file has been removed meanwhile. When yes,
957 * restart this loop, otherwise, we're done */
958 if (st
.st_nlink
>= 1)
961 if (pa_lock_fd(fd
, 0) < 0) {
962 pa_log_warn("Failed to unlock file '%s'.", fn
);
966 if (pa_close(fd
) < 0) {
967 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
985 /* Unlock a temporary lcok file */
986 int pa_unlock_lockfile(const char *fn
, int fd
) {
991 if (unlink(fn
) < 0) {
992 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
996 if (pa_lock_fd(fd
, 0) < 0) {
997 pa_log_warn("Failed to unlock file '%s'.", fn
);
1001 if (pa_close(fd
) < 0) {
1002 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1009 /* Try to open a configuration file. If "env" is specified, open the
1010 * value of the specified environment variable. Otherwise look for a
1011 * file "local" in the home directory or a file "global" in global
1012 * file system. If "result" is non-NULL, a pointer to a newly
1013 * allocated buffer containing the used configuration file is
1015 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
, const char *mode
) {
1022 if (!getenv(PULSE_ROOTENV
))
1026 if (env
&& (fn
= getenv(env
))) {
1028 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1034 *result
= pa_xstrdup(fn
);
1036 return fopen(fn
, mode
);
1043 if ((e
= getenv("PULSE_CONFIG_PATH")))
1044 fn
= lfn
= pa_sprintf_malloc("%s/%s", e
, local
);
1045 else if (pa_get_home_dir(h
, sizeof(h
)))
1046 fn
= lfn
= pa_sprintf_malloc("%s/.pulse/%s", h
, local
);
1052 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
))
1057 f
= fopen(fn
, mode
);
1060 *result
= pa_xstrdup(fn
);
1065 if (errno
!= ENOENT
)
1066 pa_log_warn("Failed to open configuration file '%s': %s", lfn
, pa_cstrerror(errno
));
1080 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1086 *result
= pa_xstrdup(global
);
1088 return fopen(global
, mode
);
1091 /* Format the specified data as a hexademical string */
1092 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1093 size_t i
= 0, j
= 0;
1094 const char hex
[] = "0123456789abcdef";
1098 pa_assert(slength
> 0);
1100 while (i
< dlength
&& j
+3 <= slength
) {
1101 s
[j
++] = hex
[*d
>> 4];
1102 s
[j
++] = hex
[*d
& 0xF];
1108 s
[j
< slength
? j
: slength
] = 0;
1112 /* Convert a hexadecimal digit to a number or -1 if invalid */
1113 static int hexc(char c
) {
1114 if (c
>= '0' && c
<= '9')
1117 if (c
>= 'A' && c
<= 'F')
1118 return c
- 'A' + 10;
1120 if (c
>= 'a' && c
<= 'f')
1121 return c
- 'a' + 10;
1126 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1127 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1133 while (j
< dlength
&& *p
) {
1136 if ((b
= hexc(*(p
++))) < 0)
1139 d
[j
] = (uint8_t) (b
<< 4);
1144 if ((b
= hexc(*(p
++))) < 0)
1147 d
[j
] |= (uint8_t) b
;
1154 /* Returns nonzero when *s starts with *pfx */
1155 int pa_startswith(const char *s
, const char *pfx
) {
1163 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1166 /* Returns nonzero when *s ends with *sfx */
1167 int pa_endswith(const char *s
, const char *sfx
) {
1176 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1179 /* if fn is null return the PulseAudio run time path in s (/tmp/pulse)
1180 * if fn is non-null and starts with / return fn in s
1181 * otherwise append fn to the run time path and return it in s */
1182 char *pa_runtime_path(const char *fn
, char *s
, size_t l
) {
1186 if (fn
&& *fn
== '/')
1188 if (fn
&& strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\')
1190 return pa_strlcpy(s
, fn
, l
);
1192 if ((e
= getenv("PULSE_RUNTIME_PATH"))) {
1195 pa_snprintf(s
, l
, "%s%c%s", e
, PA_PATH_SEP_CHAR
, fn
);
1197 pa_snprintf(s
, l
, "%s", e
);
1203 pa_snprintf(s
, l
, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX
, pa_get_user_name(u
, sizeof(u
)), PA_PATH_SEP_CHAR
, fn
);
1205 pa_snprintf(s
, l
, "%s%s", PA_USER_RUNTIME_PATH_PREFIX
, pa_get_user_name(u
, sizeof(u
)));
1213 ExpandEnvironmentStrings(buf
, s
, l
);
1220 /* Convert the string s to a signed integer in *ret_i */
1221 int pa_atoi(const char *s
, int32_t *ret_i
) {
1229 l
= strtol(s
, &x
, 0);
1231 if (!x
|| *x
|| errno
!= 0)
1234 if ((int32_t) l
!= l
)
1237 *ret_i
= (int32_t) l
;
1242 /* Convert the string s to an unsigned integer in *ret_u */
1243 int pa_atou(const char *s
, uint32_t *ret_u
) {
1251 l
= strtoul(s
, &x
, 0);
1253 if (!x
|| *x
|| errno
!= 0)
1256 if ((uint32_t) l
!= l
)
1259 *ret_u
= (uint32_t) l
;
1264 #ifdef HAVE_STRTOF_L
1265 static locale_t c_locale
= NULL
;
1267 static void c_locale_destroy(void) {
1268 freelocale(c_locale
);
1272 int pa_atof(const char *s
, float *ret_f
) {
1280 /* This should be locale independent */
1282 #ifdef HAVE_STRTOF_L
1286 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
1287 atexit(c_locale_destroy
);
1293 f
= strtof_l(s
, &x
, c_locale
);
1301 if (!x
|| *x
|| errno
!= 0)
1309 /* Same as snprintf, but guarantees NUL-termination on every platform */
1310 int pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
1315 pa_assert(size
> 0);
1318 va_start(ap
, format
);
1319 ret
= vsnprintf(str
, size
, format
, ap
);
1327 /* Truncate the specified string, but guarantee that the string
1328 * returned still validates as UTF8 */
1329 char *pa_truncate_utf8(char *c
, size_t l
) {
1331 pa_assert(pa_utf8_valid(c
));
1338 while (l
> 0 && !pa_utf8_valid(c
))
1344 char *pa_getcwd(void) {
1348 char *p
= pa_xnew(char, l
);
1352 if (errno
!= ERANGE
)
1360 char *pa_make_path_absolute(const char *p
) {
1367 return pa_xstrdup(p
);
1369 if (!(cwd
= pa_getcwd()))
1370 return pa_xstrdup(p
);
1372 r
= pa_sprintf_malloc("%s/%s", cwd
, p
);
1377 void *pa_will_need(const void *p
, size_t l
) {
1378 #ifdef RLIMIT_MEMLOCK
1389 a
= PA_PAGE_ALIGN_PTR(p
);
1390 size
= (const uint8_t*) p
+ l
- (const uint8_t*) a
;
1392 #ifdef HAVE_POSIX_MADVISE
1393 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
1394 pa_log_debug("posix_madvise() worked fine!");
1399 /* Most likely the memory was not mmap()ed from a file and thus
1400 * madvise() didn't work, so let's misuse mlock() do page this
1401 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
1402 * inviting, the man page of mlock() tells us: "All pages that
1403 * contain a part of the specified address range are guaranteed to
1404 * be resident in RAM when the call returns successfully." */
1406 #ifdef RLIMIT_MEMLOCK
1407 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
1409 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
1410 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
));
1414 bs
= PA_PAGE_ALIGN(rlim
.rlim_cur
);
1416 bs
= PA_PAGE_SIZE
*4;
1419 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
1421 while (size
> 0 && bs
> 0) {
1426 if (mlock(a
, bs
) < 0) {
1427 bs
= PA_PAGE_ALIGN(bs
/ 2);
1431 pa_assert_se(munlock(a
, bs
) == 0);
1433 a
= (const uint8_t*) a
+ bs
;
1438 pa_log_debug("mlock() failed too, giving up: %s", pa_cstrerror(errno
));
1440 pa_log_debug("mlock() worked fine!");
1445 void pa_close_pipe(int fds
[2]) {
1449 pa_assert_se(pa_close(fds
[0]) == 0);
1452 pa_assert_se(pa_close(fds
[1]) == 0);
1454 fds
[0] = fds
[1] = -1;