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_fd_nonblock(int fd
) {
143 pa_assert_se((v
= fcntl(fd
, F_GETFL
)) >= 0);
145 if (!(v
& O_NONBLOCK
))
146 pa_assert_se(fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
) >= 0);
148 #elif defined(OS_IS_WIN32)
150 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
151 pa_assert_se(WSAGetLastError() == WSAENOTSOCK
);
152 pa_log_warn("Only sockets can be made non-blocking!");
155 pa_log_warn("Non-blocking I/O not supported.!");
160 /* Set the FD_CLOEXEC flag for a fd */
161 void pa_make_fd_cloexec(int fd
) {
167 pa_assert_se((v
= fcntl(fd
, F_GETFD
, 0)) >= 0);
169 if (!(v
& FD_CLOEXEC
))
170 pa_assert_se(fcntl(fd
, F_SETFD
, v
|FD_CLOEXEC
) >= 0);
175 /** Creates a directory securely */
176 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
193 if (r
< 0 && errno
!= EEXIST
)
197 if (uid
== (uid_t
)-1)
199 if (gid
== (gid_t
)-1)
201 (void) chown(dir
, uid
, gid
);
209 if (lstat(dir
, &st
) < 0)
211 if (stat(dir
, &st
) < 0)
216 if (!S_ISDIR(st
.st_mode
) ||
217 (st
.st_uid
!= uid
) ||
218 (st
.st_gid
!= gid
) ||
219 ((st
.st_mode
& 0777) != m
)) {
224 pa_log_warn("secure directory creation not supported on Win32.");
234 /* Return a newly allocated sting containing the parent directory of the specified file */
235 char *pa_parent_dir(const char *fn
) {
236 char *slash
, *dir
= pa_xstrdup(fn
);
238 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
247 /* Creates a the parent directory of the specified path securely */
248 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
252 if (!(dir
= pa_parent_dir(fn
)))
255 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
265 /** Platform independent read function. Necessary since not all
266 * systems treat all file descriptors equal. If type is
267 * non-NULL it is used to cache the type of the fd. This is
268 * useful for making sure that only a single syscall is executed per
269 * function call. The variable pointed to should be initialized to 0
271 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
275 if (!type
|| *type
== 0) {
278 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
281 if (WSAGetLastError() != WSAENOTSOCK
) {
282 errno
= WSAGetLastError();
292 return read(fd
, buf
, count
);
295 /** Similar to pa_read(), but handles writes */
296 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
298 if (!type
|| *type
== 0) {
301 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0)
305 if (WSAGetLastError() != WSAENOTSOCK
) {
306 errno
= WSAGetLastError();
310 if (errno
!= ENOTSOCK
)
318 return write(fd
, buf
, count
);
321 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
322 * unless EOF is reached or an error occured */
323 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
339 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
346 data
= (uint8_t*) data
+ r
;
353 /** Similar to pa_loop_read(), but wraps write() */
354 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
370 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
377 data
= (const uint8_t*) data
+ r
;
384 /** Platform independent read function. Necessary since not all
385 * systems treat all file descriptors equal. */
386 int pa_close(int fd
) {
391 if ((ret
= closesocket(fd
)) == 0)
394 if (WSAGetLastError() != WSAENOTSOCK
) {
395 errno
= WSAGetLastError();
403 /* Print a warning messages in case that the given signal is not
404 * blocked or trapped */
405 void pa_check_signal_is_blocked(int sig
) {
406 #ifdef HAVE_SIGACTION
410 /* If POSIX threads are supported use thread-aware
411 * pthread_sigmask() function, to check if the signal is
412 * blocked. Otherwise fall back to sigprocmask() */
415 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
417 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
418 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
425 if (sigismember(&set
, sig
))
428 /* Check whether the signal is trapped */
430 if (sigaction(sig
, NULL
, &sa
) < 0) {
431 pa_log("sigaction(): %s", pa_cstrerror(errno
));
435 if (sa
.sa_handler
!= SIG_DFL
)
438 pa_log_warn("%s is not trapped. This might cause malfunction!", pa_sig2str(sig
));
439 #else /* HAVE_SIGACTION */
440 pa_log_warn("%s might not be trapped. This might cause malfunction!", pa_sig2str(sig
));
444 /* The following function is based on an example from the GNU libc
445 * documentation. This function is similar to GNU's asprintf(). */
446 char *pa_sprintf_malloc(const char *format
, ...) {
456 c
= pa_xrealloc(c
, size
);
458 va_start(ap
, format
);
459 r
= vsnprintf(c
, size
, format
, ap
);
464 if (r
> -1 && r
< size
)
467 if (r
> -1) /* glibc 2.1 */
474 /* Same as the previous function, but use a va_list instead of an
476 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
486 c
= pa_xrealloc(c
, size
);
489 r
= vsnprintf(c
, size
, format
, aq
);
494 if (r
> -1 && r
< size
)
497 if (r
> -1) /* glibc 2.1 */
504 /* Similar to OpenBSD's strlcpy() function */
505 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
515 /* Make the current thread a realtime thread*/
516 void pa_make_realtime(void) {
518 #ifdef _POSIX_PRIORITY_SCHEDULING
519 struct sched_param sp
;
522 memset(&sp
, 0, sizeof(sp
));
525 if ((r
= pthread_getschedparam(pthread_self(), &policy
, &sp
)) != 0) {
526 pa_log("pthread_getschedgetparam(): %s", pa_cstrerror(r
));
530 sp
.sched_priority
= 1;
531 if ((r
= pthread_setschedparam(pthread_self(), SCHED_FIFO
, &sp
)) != 0) {
532 pa_log_warn("pthread_setschedparam(): %s", pa_cstrerror(r
));
536 pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread.");
541 #define NICE_LEVEL (-11)
543 /* Raise the priority of the current process as much as possible and
544 sensible: set the nice level to -15.*/
545 void pa_raise_priority(void) {
547 #ifdef HAVE_SYS_RESOURCE_H
548 if (setpriority(PRIO_PROCESS
, 0, NICE_LEVEL
) < 0)
549 pa_log_warn("setpriority(): %s", pa_cstrerror(errno
));
551 pa_log_info("Successfully gained nice level %i.", NICE_LEVEL
);
555 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
))
556 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
558 pa_log_info("Successfully gained high priority class.");
562 /* Reset the priority to normal, inverting the changes made by
563 * pa_raise_priority() */
564 void pa_reset_priority(void) {
566 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
569 #ifdef HAVE_SYS_RESOURCE_H
570 setpriority(PRIO_PROCESS
, 0, 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
) {
640 char buf
[SIG2STR_MAX
];
642 if (sig2str(sig
, buf
) == 0) {
643 pa_xfree(PA_STATIC_TLS_GET(signame
));
644 t
= pa_sprintf_malloc("SIG%s", buf
);
645 PA_STATIC_TLS_SET(signame
, t
);
653 case SIGHUP
: return "SIGHUP";
655 case SIGINT
: return "SIGINT";
657 case SIGQUIT
: return "SIGQUIT";
659 case SIGILL
: return "SIGULL";
661 case SIGTRAP
: return "SIGTRAP";
663 case SIGABRT
: return "SIGABRT";
665 case SIGBUS
: return "SIGBUS";
667 case SIGFPE
: return "SIGFPE";
669 case SIGKILL
: return "SIGKILL";
672 case SIGUSR1
: return "SIGUSR1";
674 case SIGSEGV
: return "SIGSEGV";
676 case SIGUSR2
: return "SIGUSR2";
679 case SIGPIPE
: return "SIGPIPE";
682 case SIGALRM
: return "SIGALRM";
684 case SIGTERM
: return "SIGTERM";
686 case SIGSTKFLT
: return "SIGSTKFLT";
689 case SIGCHLD
: return "SIGCHLD";
692 case SIGCONT
: return "SIGCONT";
695 case SIGSTOP
: return "SIGSTOP";
698 case SIGTSTP
: return "SIGTSTP";
701 case SIGTTIN
: return "SIGTTIN";
704 case SIGTTOU
: return "SIGTTOU";
707 case SIGURG
: return "SIGURG";
710 case SIGXCPU
: return "SIGXCPU";
713 case SIGXFSZ
: return "SIGXFSZ";
716 case SIGVTALRM
: return "SIGVTALRM";
719 case SIGPROF
: return "SIGPROF";
722 case SIGWINCH
: return "SIGWINCH";
725 case SIGIO
: return "SIGIO";
728 case SIGPWR
: return "SIGPWR";
731 case SIGSYS
: return "SIGSYS";
736 if (sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
737 pa_xfree(PA_STATIC_TLS_GET(signame
));
738 t
= pa_sprintf_malloc("SIGRTMIN+%i", sig
- SIGRTMIN
);
739 PA_STATIC_TLS_SET(signame
, t
);
748 pa_xfree(PA_STATIC_TLS_GET(signame
));
749 t
= pa_sprintf_malloc("SIG%i", sig
);
750 PA_STATIC_TLS_SET(signame
, t
);
756 /* Check whether the specified GID and the group name match */
757 static int is_group(gid_t gid
, const char *name
) {
758 struct group group
, *result
= NULL
;
763 #ifdef HAVE_GETGRGID_R
764 #ifdef _SC_GETGR_R_SIZE_MAX
765 n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
770 data
= pa_xmalloc(n
);
772 if (getgrgid_r(gid
, &group
, data
, n
, &result
) < 0 || !result
) {
773 pa_log("getgrgid_r(%u): %s", (unsigned)gid
, pa_cstrerror(errno
));
777 r
= strcmp(name
, result
->gr_name
) == 0;
782 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
783 * support getgrgid_r. */
784 if ((result
= getgrgid(gid
)) == NULL
) {
785 pa_log("getgrgid(%u): %s", gid
, pa_cstrerror(errno
));
789 r
= strcmp(name
, result
->gr_name
) == 0;
797 /* Check the current user is member of the specified group */
798 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
799 GETGROUPS_T
*gids
, tgid
;
800 int n
= sysconf(_SC_NGROUPS_MAX
);
805 gids
= pa_xmalloc(sizeof(GETGROUPS_T
)*n
);
807 if ((n
= getgroups(n
, gids
)) < 0) {
808 pa_log("getgroups(): %s", pa_cstrerror(errno
));
812 for (i
= 0; i
< n
; i
++) {
813 if (is_group(gids
[i
], name
) > 0) {
820 if (is_group(tgid
= getgid(), name
) > 0) {
834 /* Check whether the specifc user id is a member of the specified group */
835 int pa_uid_in_group(uid_t uid
, const char *name
) {
838 struct group grbuf
, *gr
;
842 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
843 g_buf
= pa_xmalloc(g_n
);
845 p_n
= sysconf(_SC_GETPW_R_SIZE_MAX
);
846 p_buf
= pa_xmalloc(p_n
);
848 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
852 for (i
= gr
->gr_mem
; *i
; i
++) {
853 struct passwd pwbuf
, *pw
;
855 if (getpwnam_r(*i
, &pwbuf
, p_buf
, (size_t) p_n
, &pw
) != 0 || !pw
)
858 if (pw
->pw_uid
== uid
) {
871 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
872 gid_t
pa_get_gid_of_group(const char *name
) {
873 gid_t ret
= (gid_t
) -1;
876 struct group grbuf
, *gr
;
878 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
879 g_buf
= pa_xmalloc(g_n
);
881 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
891 int pa_check_in_group(gid_t g
) {
892 gid_t gids
[NGROUPS_MAX
];
895 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
905 #else /* HAVE_GRP_H */
907 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
912 int pa_uid_in_group(uid_t uid
, const char *name
) {
916 gid_t
pa_get_gid_of_group(const char *name
) {
920 int pa_check_in_group(gid_t g
) {
926 /* Lock or unlock a file entirely.
927 (advisory on UNIX, mandatory on Windows) */
928 int pa_lock_fd(int fd
, int b
) {
932 /* Try a R/W lock first */
934 flock
.l_type
= b
? F_WRLCK
: F_UNLCK
;
935 flock
.l_whence
= SEEK_SET
;
939 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
942 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
943 if (b
&& errno
== EBADF
) {
944 flock
.l_type
= F_RDLCK
;
945 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
949 pa_log("%slock: %s", !b
? "un" : "", pa_cstrerror(errno
));
953 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
955 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
957 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
960 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
966 /* Remove trailing newlines from a string */
967 char* pa_strip_nl(char *s
) {
970 s
[strcspn(s
, "\r\n")] = 0;
974 /* Create a temporary lock file and lock it. */
975 int pa_lock_lockfile(const char *fn
) {
982 if ((fd
= open(fn
, O_CREAT
|O_RDWR
989 , S_IRUSR
|S_IWUSR
)) < 0) {
990 pa_log_warn("Failed to create lock file '%s': %s", fn
, pa_cstrerror(errno
));
994 if (pa_lock_fd(fd
, 1) < 0) {
995 pa_log_warn("Failed to lock file '%s'.", fn
);
999 if (fstat(fd
, &st
) < 0) {
1000 pa_log_warn("Failed to fstat() file '%s': %s", fn
, pa_cstrerror(errno
));
1004 /* Check wheter the file has been removed meanwhile. When yes,
1005 * restart this loop, otherwise, we're done */
1006 if (st
.st_nlink
>= 1)
1009 if (pa_lock_fd(fd
, 0) < 0) {
1010 pa_log_warn("Failed to unlock file '%s'.", fn
);
1014 if (pa_close(fd
) < 0) {
1015 pa_log_warn("Failed to close file '%s': %s", fn
, pa_cstrerror(errno
));
1033 /* Unlock a temporary lcok file */
1034 int pa_unlock_lockfile(const char *fn
, int fd
) {
1039 if (unlink(fn
) < 0) {
1040 pa_log_warn("Unable to remove lock file '%s': %s", fn
, pa_cstrerror(errno
));
1044 if (pa_lock_fd(fd
, 0) < 0) {
1045 pa_log_warn("Failed to unlock file '%s'.", fn
);
1049 if (pa_close(fd
) < 0) {
1050 pa_log_warn("Failed to close '%s': %s", fn
, pa_cstrerror(errno
));
1057 /* Try to open a configuration file. If "env" is specified, open the
1058 * value of the specified environment variable. Otherwise look for a
1059 * file "local" in the home directory or a file "global" in global
1060 * file system. If "result" is non-NULL, a pointer to a newly
1061 * allocated buffer containing the used configuration file is
1063 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
, const char *mode
) {
1070 if (!getenv(PULSE_ROOTENV
))
1074 if (env
&& (fn
= getenv(env
))) {
1076 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
1082 *result
= pa_xstrdup(fn
);
1084 return fopen(fn
, mode
);
1091 if ((e
= getenv("PULSE_CONFIG_PATH")))
1092 fn
= lfn
= pa_sprintf_malloc("%s/%s", e
, local
);
1093 else if (pa_get_home_dir(h
, sizeof(h
)))
1094 fn
= lfn
= pa_sprintf_malloc("%s/.pulse/%s", h
, local
);
1100 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
))
1105 f
= fopen(fn
, mode
);
1108 *result
= pa_xstrdup(fn
);
1113 if (errno
!= ENOENT
)
1114 pa_log_warn("Failed to open configuration file '%s': %s", lfn
, pa_cstrerror(errno
));
1128 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1134 *result
= pa_xstrdup(global
);
1136 return fopen(global
, mode
);
1139 /* Format the specified data as a hexademical string */
1140 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1141 size_t i
= 0, j
= 0;
1142 const char hex
[] = "0123456789abcdef";
1146 pa_assert(slength
> 0);
1148 while (i
< dlength
&& j
+3 <= slength
) {
1149 s
[j
++] = hex
[*d
>> 4];
1150 s
[j
++] = hex
[*d
& 0xF];
1156 s
[j
< slength
? j
: slength
] = 0;
1160 /* Convert a hexadecimal digit to a number or -1 if invalid */
1161 static int hexc(char c
) {
1162 if (c
>= '0' && c
<= '9')
1165 if (c
>= 'A' && c
<= 'F')
1166 return c
- 'A' + 10;
1168 if (c
>= 'a' && c
<= 'f')
1169 return c
- 'a' + 10;
1174 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1175 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1181 while (j
< dlength
&& *p
) {
1184 if ((b
= hexc(*(p
++))) < 0)
1187 d
[j
] = (uint8_t) (b
<< 4);
1192 if ((b
= hexc(*(p
++))) < 0)
1195 d
[j
] |= (uint8_t) b
;
1202 /* Returns nonzero when *s starts with *pfx */
1203 int pa_startswith(const char *s
, const char *pfx
) {
1211 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1214 /* Returns nonzero when *s ends with *sfx */
1215 int pa_endswith(const char *s
, const char *sfx
) {
1224 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1227 /* if fn is null return the PulseAudio run time path in s (/tmp/pulse)
1228 * if fn is non-null and starts with / return fn in s
1229 * otherwise append fn to the run time path and return it in s */
1230 char *pa_runtime_path(const char *fn
, char *s
, size_t l
) {
1234 if (fn
&& *fn
== '/')
1236 if (fn
&& strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\')
1238 return pa_strlcpy(s
, fn
, l
);
1240 if ((e
= getenv("PULSE_RUNTIME_PATH"))) {
1243 pa_snprintf(s
, l
, "%s%c%s", e
, PA_PATH_SEP_CHAR
, fn
);
1245 pa_snprintf(s
, l
, "%s", e
);
1251 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
);
1253 pa_snprintf(s
, l
, "%s%s", PA_USER_RUNTIME_PATH_PREFIX
, pa_get_user_name(u
, sizeof(u
)));
1261 ExpandEnvironmentStrings(buf
, s
, l
);
1268 /* Convert the string s to a signed integer in *ret_i */
1269 int pa_atoi(const char *s
, int32_t *ret_i
) {
1277 l
= strtol(s
, &x
, 0);
1279 if (!x
|| *x
|| errno
!= 0)
1282 if ((int32_t) l
!= l
)
1285 *ret_i
= (int32_t) l
;
1290 /* Convert the string s to an unsigned integer in *ret_u */
1291 int pa_atou(const char *s
, uint32_t *ret_u
) {
1299 l
= strtoul(s
, &x
, 0);
1301 if (!x
|| *x
|| errno
!= 0)
1304 if ((uint32_t) l
!= l
)
1307 *ret_u
= (uint32_t) l
;
1312 #ifdef HAVE_STRTOF_L
1313 static locale_t c_locale
= NULL
;
1315 static void c_locale_destroy(void) {
1316 freelocale(c_locale
);
1320 int pa_atof(const char *s
, float *ret_f
) {
1328 /* This should be locale independent */
1330 #ifdef HAVE_STRTOF_L
1334 if ((c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
)))
1335 atexit(c_locale_destroy
);
1341 f
= strtof_l(s
, &x
, c_locale
);
1353 if (!x
|| *x
|| errno
!= 0)
1361 /* Same as snprintf, but guarantees NUL-termination on every platform */
1362 int pa_snprintf(char *str
, size_t size
, const char *format
, ...) {
1367 pa_assert(size
> 0);
1370 va_start(ap
, format
);
1371 ret
= vsnprintf(str
, size
, format
, ap
);
1379 /* Truncate the specified string, but guarantee that the string
1380 * returned still validates as UTF8 */
1381 char *pa_truncate_utf8(char *c
, size_t l
) {
1383 pa_assert(pa_utf8_valid(c
));
1390 while (l
> 0 && !pa_utf8_valid(c
))
1396 char *pa_getcwd(void) {
1400 char *p
= pa_xnew(char, l
);
1404 if (errno
!= ERANGE
)
1412 char *pa_make_path_absolute(const char *p
) {
1419 return pa_xstrdup(p
);
1421 if (!(cwd
= pa_getcwd()))
1422 return pa_xstrdup(p
);
1424 r
= pa_sprintf_malloc("%s/%s", cwd
, p
);
1429 void *pa_will_need(const void *p
, size_t l
) {
1430 #ifdef RLIMIT_MEMLOCK
1441 a
= PA_PAGE_ALIGN_PTR(p
);
1442 size
= (const uint8_t*) p
+ l
- (const uint8_t*) a
;
1444 #ifdef HAVE_POSIX_MADVISE
1445 if ((r
= posix_madvise((void*) a
, size
, POSIX_MADV_WILLNEED
)) == 0) {
1446 pa_log_debug("posix_madvise() worked fine!");
1451 /* Most likely the memory was not mmap()ed from a file and thus
1452 * madvise() didn't work, so let's misuse mlock() do page this
1453 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
1454 * inviting, the man page of mlock() tells us: "All pages that
1455 * contain a part of the specified address range are guaranteed to
1456 * be resident in RAM when the call returns successfully." */
1458 #ifdef RLIMIT_MEMLOCK
1459 pa_assert_se(getrlimit(RLIMIT_MEMLOCK
, &rlim
) == 0);
1461 if (rlim
.rlim_cur
< PA_PAGE_SIZE
) {
1462 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
));
1466 bs
= PA_PAGE_ALIGN(rlim
.rlim_cur
);
1468 bs
= PA_PAGE_SIZE
*4;
1471 pa_log_debug("posix_madvise() failed (or doesn't exist), trying mlock(): %s", pa_cstrerror(r
));
1474 while (size
> 0 && bs
> 0) {
1479 if (mlock(a
, bs
) < 0) {
1480 bs
= PA_PAGE_ALIGN(bs
/ 2);
1484 pa_assert_se(munlock(a
, bs
) == 0);
1486 a
= (const uint8_t*) a
+ bs
;
1492 pa_log_debug("mlock() failed too (or doesn't exist), giving up: %s", pa_cstrerror(errno
));
1494 pa_log_debug("mlock() worked fine!");
1499 void pa_close_pipe(int fds
[2]) {
1503 pa_assert_se(pa_close(fds
[0]) == 0);
1506 pa_assert_se(pa_close(fds
[1]) == 0);
1508 fds
[0] = fds
[1] = -1;