]>
code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
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>
54 #ifdef HAVE_SYS_RESOURCE_H
55 #include <sys/resource.h>
58 #ifdef HAVE_SYS_CAPABILITY_H
59 #include <sys/capability.h>
62 #ifdef HAVE_SYS_MMAN_H
86 #ifdef HAVE_LIBSAMPLERATE
87 #include <samplerate.h>
90 #include <pulse/xmalloc.h>
91 #include <pulse/util.h>
92 #include <pulse/utf8.h>
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>
100 #include "core-util.h"
102 /* Not all platforms have this */
104 #define MSG_NOSIGNAL 0
109 #define PULSE_ROOTENV "PULSE_ROOT"
111 int pa_set_root ( HANDLE handle
) {
112 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
114 strcpy ( library_path
, PULSE_ROOTENV
"=" );
116 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
119 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
123 if ( _putenv ( library_path
) < 0 )
131 /** Make a file descriptor nonblock. Doesn't do any error checking */
132 void pa_make_fd_nonblock ( int fd
) {
138 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
140 if (!( v
& O_NONBLOCK
))
141 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
143 #elif defined(OS_IS_WIN32)
145 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
146 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
147 pa_log_warn ( "Only sockets can be made non-blocking!" );
150 pa_log_warn ( "Non-blocking I/O not supported.!" );
155 /* Set the FD_CLOEXEC flag for a fd */
156 void pa_make_fd_cloexec ( int fd
) {
162 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
164 if (!( v
& FD_CLOEXEC
))
165 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
170 /** Creates a directory securely */
171 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
188 if ( r
< 0 && errno
!= EEXIST
)
192 if ( uid
== ( uid_t
)- 1 )
194 if ( gid
== ( gid_t
)- 1 )
196 ( void ) chown ( dir
, uid
, gid
);
204 if ( lstat ( dir
, & st
) < 0 )
206 if ( stat ( dir
, & st
) < 0 )
211 if (! S_ISDIR ( st
. st_mode
) ||
212 ( st
. st_uid
!= uid
) ||
213 ( st
. st_gid
!= gid
) ||
214 (( st
. st_mode
& 0777 ) != m
)) {
219 pa_log_warn ( "Secure directory creation not supported on Win32." );
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
);
233 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
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
) {
247 if (!( dir
= pa_parent_dir ( fn
)))
250 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
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
266 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
270 if (! type
|| * type
== 0 ) {
273 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
276 if ( WSAGetLastError () != WSAENOTSOCK
) {
277 errno
= WSAGetLastError ();
287 return read ( fd
, buf
, count
);
290 /** Similar to pa_read(), but handles writes */
291 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
293 if (! type
|| * type
== 0 ) {
296 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0 )
300 if ( WSAGetLastError () != WSAENOTSOCK
) {
301 errno
= WSAGetLastError ();
305 if ( errno
!= ENOTSOCK
)
313 return write ( fd
, buf
, count
);
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
) {
334 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
341 data
= ( uint8_t *) data
+ r
;
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
) {
365 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
372 data
= ( const uint8_t *) data
+ r
;
379 /** Platform independent read function. Necessary since not all
380 * systems treat all file descriptors equal. */
381 int pa_close ( int fd
) {
386 if (( ret
= closesocket ( fd
)) == 0 )
389 if ( WSAGetLastError () != WSAENOTSOCK
) {
390 errno
= WSAGetLastError ();
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
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() */
410 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
412 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
413 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
420 if ( sigismember (& set
, sig
))
423 /* Check whether the signal is trapped */
425 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
426 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
430 if ( sa
. sa_handler
!= SIG_DFL
)
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
));
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
, ...) {
451 c
= pa_xrealloc ( c
, size
);
453 va_start ( ap
, format
);
454 r
= vsnprintf ( c
, size
, format
, ap
);
459 if ( r
> - 1 && r
< size
)
462 if ( r
> - 1 ) /* glibc 2.1 */
469 /* Same as the previous function, but use a va_list instead of an
471 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
481 c
= pa_xrealloc ( c
, size
);
484 r
= vsnprintf ( c
, size
, format
, aq
);
489 if ( r
> - 1 && r
< size
)
492 if ( r
> - 1 ) /* glibc 2.1 */
499 /* Similar to OpenBSD's strlcpy() function */
500 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
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
) {
515 #ifdef _POSIX_PRIORITY_SCHEDULING
516 struct sched_param sp
;
519 memset (& sp
, 0 , sizeof ( sp
));
522 if (( r
= pthread_getschedparam ( pthread_self (), & policy
, & sp
)) != 0 ) {
523 pa_log ( "pthread_getschedgetparam(): %s" , pa_cstrerror ( r
));
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
);
532 sp
. sched_priority
= rtprio
;
533 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) != 0 ) {
535 while ( sp
. sched_priority
> 1 ) {
536 sp
. sched_priority
--;
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
);
544 pa_log_warn ( "pthread_setschedparam(): %s" , pa_cstrerror ( r
));
548 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i." , sp
. sched_priority
);
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 ) {
562 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
566 if ( getrlimit ( RLIMIT_RTPRIO
, & rl
) >= 0 )
567 if ( rl
. rlim_cur
> 0 || rl
. rlim_cur
== RLIM_INFINITY
)
572 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
576 if (( cap
= cap_get_proc ())) {
577 cap_flag_value_t flag
= CAP_CLEAR
;
579 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
580 if ( flag
== CAP_SET
) {
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 ) {
600 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
604 if ( getrlimit ( RLIMIT_NICE
, & rl
) >= 0 )
605 if ( rl
. rlim_cur
>= 21 || rl
. rlim_cur
== RLIM_INFINITY
)
610 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
614 if (( cap
= cap_get_proc ())) {
615 cap_flag_value_t flag
= CAP_CLEAR
;
617 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
618 if ( flag
== CAP_SET
) {
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
) {
635 #ifdef HAVE_SYS_RESOURCE_H
636 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) < 0 ) {
639 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++) {
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
);
647 pa_log_warn ( "setpriority(): %s" , pa_cstrerror ( errno
));
651 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
655 if ( nice_level
< 0 ) {
656 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
657 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
660 pa_log_info ( "Successfully gained high priority class." );
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
;
673 setpriority ( PRIO_PROCESS
, 0 , 0 );
675 memset (& sp
, 0 , sizeof ( sp
));
676 pa_assert_se ( pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
) == 0 );
680 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
684 /* Try to parse a boolean string value.*/
685 int pa_parse_boolean ( const char * v
) {
688 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
690 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
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
;
707 l
= strcspn ( current
, delimiter
);
713 return pa_xstrndup ( current
, l
);
716 /* What is interpreted as whitespace? */
717 #define WHITESPACE " \t\n "
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
;
724 if (!* current
|| * c
== 0 )
727 current
+= strspn ( current
, WHITESPACE
);
728 l
= strcspn ( current
, WHITESPACE
);
732 return pa_xstrndup ( current
, l
);
735 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
737 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
738 const char * pa_sig2str ( int sig
) {
751 char buf
[ SIG2STR_MAX
];
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
);
764 case SIGHUP
: return "SIGHUP" ;
766 case SIGINT
: return "SIGINT" ;
768 case SIGQUIT
: return "SIGQUIT" ;
770 case SIGILL
: return "SIGULL" ;
772 case SIGTRAP
: return "SIGTRAP" ;
774 case SIGABRT
: return "SIGABRT" ;
776 case SIGBUS
: return "SIGBUS" ;
778 case SIGFPE
: return "SIGFPE" ;
780 case SIGKILL
: return "SIGKILL" ;
783 case SIGUSR1
: return "SIGUSR1" ;
785 case SIGSEGV
: return "SIGSEGV" ;
787 case SIGUSR2
: return "SIGUSR2" ;
790 case SIGPIPE
: return "SIGPIPE" ;
793 case SIGALRM
: return "SIGALRM" ;
795 case SIGTERM
: return "SIGTERM" ;
797 case SIGSTKFLT
: return "SIGSTKFLT" ;
800 case SIGCHLD
: return "SIGCHLD" ;
803 case SIGCONT
: return "SIGCONT" ;
806 case SIGSTOP
: return "SIGSTOP" ;
809 case SIGTSTP
: return "SIGTSTP" ;
812 case SIGTTIN
: return "SIGTTIN" ;
815 case SIGTTOU
: return "SIGTTOU" ;
818 case SIGURG
: return "SIGURG" ;
821 case SIGXCPU
: return "SIGXCPU" ;
824 case SIGXFSZ
: return "SIGXFSZ" ;
827 case SIGVTALRM
: return "SIGVTALRM" ;
830 case SIGPROF
: return "SIGPROF" ;
833 case SIGWINCH
: return "SIGWINCH" ;
836 case SIGIO
: return "SIGIO" ;
839 case SIGPWR
: return "SIGPWR" ;
842 case SIGSYS
: return "SIGSYS" ;
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
);
859 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
860 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
861 PA_STATIC_TLS_SET ( signame
, t
);
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
;
874 #ifdef HAVE_GETGRGID_R
875 #ifdef _SC_GETGR_R_SIZE_MAX
876 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
881 data
= pa_xmalloc ( n
);
883 if ( getgrgid_r ( gid
, & group
, data
, n
, & result
) < 0 || ! result
) {
884 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
888 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
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
));
900 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
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
);
916 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
)* n
);
918 if (( n
= getgroups ( n
, gids
)) < 0 ) {
919 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
923 for ( i
= 0 ; i
< n
; i
++) {
924 if ( is_group ( gids
[ i
], name
) > 0 ) {
931 if ( is_group ( tgid
= getgid (), name
) > 0 ) {
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
) {
949 struct group grbuf
, * gr
;
953 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
954 g_buf
= pa_xmalloc ( g_n
);
956 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
957 p_buf
= pa_xmalloc ( p_n
);
959 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
963 for ( i
= gr
-> gr_mem
; * i
; i
++) {
964 struct passwd pwbuf
, * pw
;
966 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
969 if ( pw
-> pw_uid
== uid
) {
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 ;
987 struct group grbuf
, * gr
;
989 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
990 g_buf
= pa_xmalloc ( g_n
);
992 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1002 int pa_check_in_group ( gid_t g
) {
1003 gid_t gids
[ NGROUPS_MAX
];
1006 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1016 #else /* HAVE_GRP_H */
1018 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1023 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1027 gid_t
pa_get_gid_of_group ( const char * name
) {
1031 int pa_check_in_group ( gid_t g
) {
1037 /* Lock or unlock a file entirely.
1038 (advisory on UNIX, mandatory on Windows) */
1039 int pa_lock_fd ( int fd
, int b
) {
1043 /* Try a R/W lock first */
1045 flock
. l_type
= b
? F_WRLCK
: F_UNLCK
;
1046 flock
. l_whence
= SEEK_SET
;
1050 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
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 )
1060 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1064 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1066 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1068 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1071 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1077 /* Remove trailing newlines from a string */
1078 char * pa_strip_nl ( char * s
) {
1081 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1085 /* Create a temporary lock file and lock it. */
1086 int pa_lock_lockfile ( const char * fn
) {
1093 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1100 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1101 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1105 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1106 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1110 if ( fstat ( fd
, & st
) < 0 ) {
1111 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
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 )
1120 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1121 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1125 if ( pa_close ( fd
) < 0 ) {
1126 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1144 /* Unlock a temporary lcok file */
1145 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1150 if ( unlink ( fn
) < 0 ) {
1151 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1155 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1156 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1160 if ( pa_close ( fd
) < 0 ) {
1161 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1168 char * pa_get_runtime_dir ( void ) {
1172 if (( e
= getenv ( "PULSE_RUNTIME_PATH" )))
1177 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1178 pa_log_error ( "Failed to get home directory." );
1182 d
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
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
));
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
1199 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1204 if (! getenv ( PULSE_ROOTENV
))
1208 if ( env
&& ( fn
= getenv ( env
))) {
1212 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1217 if (( f
= fopen ( fn
, "r" ))) {
1219 * result
= pa_xstrdup ( fn
);
1224 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
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
);
1240 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1247 if (( f
= fopen ( fn
, "r" ))) {
1249 * result
= pa_xstrdup ( fn
);
1255 if ( errno
!= ENOENT
) {
1256 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1268 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1273 if (( f
= fopen ( global
, "r" ))) {
1276 * result
= pa_xstrdup ( global
);
1286 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1291 if (! getenv ( PULSE_ROOTENV
))
1295 if ( env
&& ( fn
= getenv ( env
))) {
1297 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1302 if ( access ( fn
, R_OK
) == 0 )
1303 return pa_xstrdup ( fn
);
1305 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
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
);
1320 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1327 if ( access ( fn
, R_OK
) == 0 ) {
1328 char * r
= pa_xstrdup ( fn
);
1333 if ( errno
!= ENOENT
) {
1334 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1344 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1349 if ( access ( fn
, R_OK
) == 0 )
1350 return pa_xstrdup ( global
);
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" ;
1364 pa_assert ( slength
> 0 );
1366 while ( i
< dlength
&& j
+ 3 <= slength
) {
1367 s
[ j
++] = hex
[* d
>> 4 ];
1368 s
[ j
++] = hex
[* d
& 0xF ];
1374 s
[ j
< slength
? j
: slength
] = 0 ;
1378 /* Convert a hexadecimal digit to a number or -1 if invalid */
1379 static int hexc ( char c
) {
1380 if ( c
>= '0' && c
<= '9' )
1383 if ( c
>= 'A' && c
<= 'F' )
1384 return c
- 'A' + 10 ;
1386 if ( c
>= 'a' && c
<= 'f' )
1387 return c
- 'a' + 10 ;
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
) {
1399 while ( j
< dlength
&& * p
) {
1402 if (( b
= hexc (*( p
++))) < 0 )
1405 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1410 if (( b
= hexc (*( p
++))) < 0 )
1413 d
[ j
] |= ( uint8_t ) b
;
1420 /* Returns nonzero when *s starts with *pfx */
1421 int pa_startswith ( const char * s
, const char * pfx
) {
1429 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1432 /* Returns nonzero when *s ends with *sfx */
1433 int pa_endswith ( const char * s
, const char * sfx
) {
1442 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1445 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1451 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1455 char * pa_make_path_absolute ( const char * p
) {
1461 if ( pa_is_path_absolute ( p
))
1462 return pa_xstrdup ( p
);
1464 if (!( cwd
= pa_getcwd ()))
1465 return pa_xstrdup ( p
);
1467 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
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
) {
1478 if ( pa_is_path_absolute ( fn
))
1479 return pa_xstrdup ( fn
);
1481 rtp
= pa_get_runtime_dir ();
1485 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1492 /* Convert the string s to a signed integer in *ret_i */
1493 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1501 l
= strtol ( s
, & x
, 0 );
1503 if (! x
|| * x
|| errno
!= 0 )
1506 if (( int32_t ) l
!= l
)
1509 * ret_i
= ( int32_t ) l
;
1514 /* Convert the string s to an unsigned integer in *ret_u */
1515 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1523 l
= strtoul ( s
, & x
, 0 );
1525 if (! x
|| * x
|| errno
!= 0 )
1528 if (( uint32_t ) l
!= l
)
1531 * ret_u
= ( uint32_t ) l
;
1536 #ifdef HAVE_STRTOF_L
1537 static locale_t c_locale
= NULL
;
1539 static void c_locale_destroy ( void ) {
1540 freelocale ( c_locale
);
1544 int pa_atof ( const char * s
, float * ret_f
) {
1552 /* This should be locale independent */
1554 #ifdef HAVE_STRTOF_L
1558 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1559 atexit ( c_locale_destroy
);
1565 f
= strtof_l ( s
, & x
, c_locale
);
1577 if (! x
|| * x
|| errno
!= 0 )
1585 /* Same as snprintf, but guarantees NUL-termination on every platform */
1586 int pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
1591 pa_assert ( size
> 0 );
1594 va_start ( ap
, format
);
1595 ret
= vsnprintf ( str
, size
, format
, ap
);
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
) {
1607 pa_assert ( pa_utf8_valid ( c
));
1614 while ( l
> 0 && ! pa_utf8_valid ( c
))
1620 char * pa_getcwd ( void ) {
1624 char * p
= pa_xnew ( char , l
);
1628 if ( errno
!= ERANGE
)
1636 void * pa_will_need ( const void * p
, size_t l
) {
1637 #ifdef RLIMIT_MEMLOCK
1648 a
= PA_PAGE_ALIGN_PTR ( p
);
1649 size
= ( const uint8_t *) p
+ l
- ( const uint8_t *) a
;
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!" );
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." */
1665 #ifdef RLIMIT_MEMLOCK
1666 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
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
));
1673 bs
= PA_PAGE_ALIGN ( rlim
. rlim_cur
);
1675 bs
= PA_PAGE_SIZE
* 4 ;
1678 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
1681 while ( size
> 0 && bs
> 0 ) {
1686 if ( mlock ( a
, bs
) < 0 ) {
1687 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
1691 pa_assert_se ( munlock ( a
, bs
) == 0 );
1693 a
= ( const uint8_t *) a
+ bs
;
1699 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
1701 pa_log_debug ( "mlock() worked fine!" );
1706 void pa_close_pipe ( int fds
[ 2 ]) {
1710 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
1713 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
1715 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
1718 char * pa_readlink ( const char * p
) {
1725 c
= pa_xnew ( char , l
);
1727 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
1732 if (( size_t ) n
< l
- 1 ) {
1742 int pa_close_all ( int except_fd
, ...) {
1747 va_start ( ap
, except_fd
);
1750 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
1755 p
= pa_xnew ( int , n
+ 1 );
1757 va_start ( ap
, except_fd
);
1760 if ( except_fd
>= 0 ) {
1763 while (( p
[ i
++] = va_arg ( ap
, int )) >= 0 )
1770 r
= pa_close_allv ( p
);
1776 int pa_close_allv ( const int except_fds
[]) {
1785 if (( d
= opendir ( "/proc/self/fd" ))) {
1789 while (( de
= readdir ( d
))) {
1794 if ( de
-> d_name
[ 0 ] == '.' )
1798 l
= strtol ( de
-> d_name
, & e
, 10 );
1799 if ( errno
!= 0 || ! e
|| * e
) {
1807 if (( long ) fd
!= l
) {
1819 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
1820 if ( except_fds
[ i
] == fd
)
1823 if ( close ( fd
) < 0 ) {
1824 saved_errno
= errno
;
1826 errno
= saved_errno
;
1838 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) < 0 )
1841 for ( fd
= 0 ; fd
< ( int ) rl
. rlim_max
; fd
++) {
1847 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
1848 if ( except_fds
[ i
] == fd
)
1851 if ( close ( fd
) < 0 && errno
!= EBADF
)
1858 int pa_unblock_sigs ( int except
, ...) {
1863 va_start ( ap
, except
);
1866 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
1871 p
= pa_xnew ( int , n
+ 1 );
1873 va_start ( ap
, except
);
1879 while (( p
[ i
++] = va_arg ( ap
, int )) >= 0 )
1886 r
= pa_unblock_sigsv ( p
);
1892 int pa_unblock_sigsv ( const int except
[]) {
1896 if ( sigemptyset (& ss
) < 0 )
1899 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
1900 if ( sigaddset (& ss
, except
[ i
]) < 0 )
1903 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
1906 int pa_reset_sigs ( int except
, ...) {
1911 va_start ( ap
, except
);
1914 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
1919 p
= pa_xnew ( int , n
+ 1 );
1921 va_start ( ap
, except
);
1927 while (( p
[ i
++] = va_arg ( ap
, int )) >= 0 )
1934 r
= pa_reset_sigsv ( p
);
1940 int pa_reset_sigsv ( const int except
[]) {
1943 for ( sig
= 1 ; sig
< _NSIG
; sig
++) {
1955 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
1956 if ( sig
== except
[ i
]) {
1965 struct sigaction sa
;
1967 memset (& sa
, 0 , sizeof ( sa
));
1968 sa
. sa_handler
= SIG_DFL
;
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
)
1981 void pa_set_env ( const char * key
, const char * value
) {
1985 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));