]>
code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2004 Joe Marcus Clarke
6 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39 #include <sys/types.h>
45 #include <sys/utsname.h>
46 #include <sys/socket.h>
55 #if defined(__linux__) && !defined(SCHED_RESET_ON_FORK)
56 #define SCHED_RESET_ON_FORK 0x40000000
60 #ifdef HAVE_SYS_RESOURCE_H
61 #include <sys/resource.h>
64 #ifdef HAVE_SYS_CAPABILITY_H
65 #include <sys/capability.h>
68 #ifdef HAVE_SYS_MMAN_H
92 #ifdef HAVE_LIBSAMPLERATE
93 #include <samplerate.h>
105 #include <sys/personality.h>
108 #include <pulse/xmalloc.h>
109 #include <pulse/util.h>
110 #include <pulse/utf8.h>
112 #include <pulsecore/core-error.h>
113 #include <pulsecore/winsock.h>
114 #include <pulsecore/log.h>
115 #include <pulsecore/macro.h>
116 #include <pulsecore/thread.h>
117 #include <pulsecore/strbuf.h>
118 #include <pulsecore/usergroup.h>
119 #include <pulsecore/strlist.h>
120 #include <pulsecore/cpu-x86.h>
122 #include "core-util.h"
124 /* Not all platforms have this */
126 #define MSG_NOSIGNAL 0
129 #define NEWLINE " \r\n "
130 #define WHITESPACE " \n\r \t "
132 static pa_strlist
* recorded_env
= NULL
;
136 #define PULSE_ROOTENV "PULSE_ROOT"
138 int pa_set_root ( HANDLE handle
) {
139 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
141 strcpy ( library_path
, PULSE_ROOTENV
"=" );
143 /* FIXME: Needs to set errno */
145 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
148 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
152 if ( _putenv ( library_path
) < 0 )
160 /** Make a file descriptor nonblock. Doesn't do any error checking */
161 void pa_make_fd_nonblock ( int fd
) {
167 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
169 if (!( v
& O_NONBLOCK
))
170 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
172 #elif defined(OS_IS_WIN32)
174 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
175 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
176 pa_log_warn ( "Only sockets can be made non-blocking!" );
179 pa_log_warn ( "Non-blocking I/O not supported.!" );
184 /* Set the FD_CLOEXEC flag for a fd */
185 void pa_make_fd_cloexec ( int fd
) {
191 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
193 if (!( v
& FD_CLOEXEC
))
194 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
199 /** Creates a directory securely */
200 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
202 int r
, saved_errno
, fd
;
211 u
= umask ((~ m
) & 0777 );
217 if ( r
< 0 && errno
!= EEXIST
)
234 if ( fstat ( fd
, & st
) < 0 ) {
235 pa_assert_se ( pa_close ( fd
) >= 0 );
239 if (! S_ISDIR ( st
. st_mode
)) {
240 pa_assert_se ( pa_close ( fd
) >= 0 );
246 if ( uid
== ( uid_t
)- 1 )
248 if ( gid
== ( gid_t
)- 1 )
250 ( void ) fchown ( fd
, uid
, gid
);
254 ( void ) fchmod ( fd
, m
);
257 pa_assert_se ( pa_close ( fd
) >= 0 );
262 if ( lstat ( dir
, & st
) < 0 )
264 if ( stat ( dir
, & st
) < 0 )
269 if (! S_ISDIR ( st
. st_mode
) ||
270 ( st
. st_uid
!= uid
) ||
271 ( st
. st_gid
!= gid
) ||
272 (( st
. st_mode
& 0777 ) != m
)) {
277 pa_log_warn ( "Secure directory creation not supported on Win32." );
290 /* Return a newly allocated sting containing the parent directory of the specified file */
291 char * pa_parent_dir ( const char * fn
) {
292 char * slash
, * dir
= pa_xstrdup ( fn
);
294 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
304 /* Creates a the parent directory of the specified path securely */
305 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
309 if (!( dir
= pa_parent_dir ( fn
)))
312 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
322 /** Platform independent read function. Necessary since not all
323 * systems treat all file descriptors equal. If type is
324 * non-NULL it is used to cache the type of the fd. This is
325 * useful for making sure that only a single syscall is executed per
326 * function call. The variable pointed to should be initialized to 0
328 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
332 if (! type
|| * type
== 0 ) {
335 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
338 if ( WSAGetLastError () != WSAENOTSOCK
) {
339 errno
= WSAGetLastError ();
352 if (( r
= read ( fd
, buf
, count
)) < 0 )
360 /** Similar to pa_read(), but handles writes */
361 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
363 if (! type
|| * type
== 0 ) {
367 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
379 if ( WSAGetLastError () != WSAENOTSOCK
) {
380 errno
= WSAGetLastError ();
384 if ( errno
!= ENOTSOCK
)
395 if (( r
= write ( fd
, buf
, count
)) < 0 )
403 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
404 * unless EOF is reached or an error occurred */
405 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
421 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
428 data
= ( uint8_t *) data
+ r
;
435 /** Similar to pa_loop_read(), but wraps write() */
436 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
452 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
459 data
= ( const uint8_t *) data
+ r
;
466 /** Platform independent read function. Necessary since not all
467 * systems treat all file descriptors equal. */
468 int pa_close ( int fd
) {
473 if (( ret
= closesocket ( fd
)) == 0 )
476 if ( WSAGetLastError () != WSAENOTSOCK
) {
477 errno
= WSAGetLastError ();
485 if (( r
= close ( fd
)) < 0 )
493 /* Print a warning messages in case that the given signal is not
494 * blocked or trapped */
495 void pa_check_signal_is_blocked ( int sig
) {
496 #ifdef HAVE_SIGACTION
500 /* If POSIX threads are supported use thread-aware
501 * pthread_sigmask() function, to check if the signal is
502 * blocked. Otherwise fall back to sigprocmask() */
505 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
507 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
508 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
515 if ( sigismember (& set
, sig
))
518 /* Check whether the signal is trapped */
520 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
521 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
525 if ( sa
. sa_handler
!= SIG_DFL
)
528 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
529 #else /* HAVE_SIGACTION */
530 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
534 /* The following function is based on an example from the GNU libc
535 * documentation. This function is similar to GNU's asprintf(). */
536 char * pa_sprintf_malloc ( const char * format
, ...) {
546 c
= pa_xrealloc ( c
, size
);
548 va_start ( ap
, format
);
549 r
= vsnprintf ( c
, size
, format
, ap
);
554 if ( r
> - 1 && ( size_t ) r
< size
)
557 if ( r
> - 1 ) /* glibc 2.1 */
564 /* Same as the previous function, but use a va_list instead of an
566 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
576 c
= pa_xrealloc ( c
, size
);
579 r
= vsnprintf ( c
, size
, format
, aq
);
584 if ( r
> - 1 && ( size_t ) r
< size
)
587 if ( r
> - 1 ) /* glibc 2.1 */
594 /* Similar to OpenBSD's strlcpy() function */
595 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
613 static int set_scheduler ( int rtprio
) {
614 struct sched_param sp
;
620 dbus_error_init (& error
);
624 sp
. sched_priority
= rtprio
;
626 #ifdef SCHED_RESET_ON_FORK
627 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
) == 0 ) {
628 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
633 if ( pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
) == 0 ) {
634 pa_log_debug ( "SCHED_RR worked." );
639 /* Try to talk to RealtimeKit */
641 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
642 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
643 dbus_error_free (& error
);
648 /* We need to disable exit on disconnect because otherwise
649 * dbus_shutdown will kill us. See
650 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
651 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
653 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
654 dbus_connection_unref ( bus
);
657 pa_log_debug ( "RealtimeKit worked." );
669 /* Make the current thread a realtime thread, and acquire the highest
670 * rtprio we can get that is less or equal the specified parameter. If
671 * the thread is already realtime, don't do anything. */
672 int pa_make_realtime ( int rtprio
) {
674 #ifdef _POSIX_PRIORITY_SCHEDULING
677 if ( set_scheduler ( rtprio
) >= 0 ) {
678 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
682 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
683 if ( set_scheduler ( p
) >= 0 ) {
684 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
688 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
697 static int set_nice ( int nice_level
) {
703 dbus_error_init (& error
);
706 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
707 pa_log_debug ( "setpriority() worked." );
712 /* Try to talk to RealtimeKit */
714 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
715 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
716 dbus_error_free (& error
);
721 /* We need to disable exit on disconnect because otherwise
722 * dbus_shutdown will kill us. See
723 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
724 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
726 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
727 dbus_connection_unref ( bus
);
730 pa_log_debug ( "RealtimeKit worked." );
740 /* Raise the priority of the current process as much as possible that
741 * is <= the specified nice level..*/
742 int pa_raise_priority ( int nice_level
) {
744 #ifdef HAVE_SYS_RESOURCE_H
747 if ( set_nice ( nice_level
) >= 0 ) {
748 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
752 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
753 if ( set_nice ( n
) >= 0 ) {
754 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
758 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
763 if ( nice_level
< 0 ) {
764 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
765 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
770 pa_log_info ( "Successfully gained high priority class." );
777 /* Reset the priority to normal, inverting the changes made by
778 * pa_raise_priority() and pa_make_realtime()*/
779 void pa_reset_priority ( void ) {
780 #ifdef HAVE_SYS_RESOURCE_H
781 struct sched_param sp
;
783 setpriority ( PRIO_PROCESS
, 0 , 0 );
786 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
790 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
794 int pa_match ( const char * expr
, const char * v
) {
799 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
804 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
806 else if ( k
== REG_NOMATCH
)
819 /* Try to parse a boolean string value.*/
820 int pa_parse_boolean ( const char * v
) {
824 /* First we check language independant */
825 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
827 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
830 /* And then we check language dependant */
831 if (( expr
= nl_langinfo ( YESEXPR
)))
833 if ( pa_match ( expr
, v
) > 0 )
836 if (( expr
= nl_langinfo ( NOEXPR
)))
838 if ( pa_match ( expr
, v
) > 0 )
845 /* Split the specified string wherever one of the strings in delimiter
846 * occurs. Each time it is called returns a newly allocated string
847 * with pa_xmalloc(). The variable state points to, should be
848 * initiallized to NULL before the first call. */
849 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
850 const char * current
= * state
? * state
: c
;
856 l
= strcspn ( current
, delimiter
);
862 return pa_xstrndup ( current
, l
);
865 /* Split a string into words. Otherwise similar to pa_split(). */
866 char * pa_split_spaces ( const char * c
, const char ** state
) {
867 const char * current
= * state
? * state
: c
;
870 if (!* current
|| * c
== 0 )
873 current
+= strspn ( current
, WHITESPACE
);
874 l
= strcspn ( current
, WHITESPACE
);
878 return pa_xstrndup ( current
, l
);
881 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
883 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
884 const char * pa_sig2str ( int sig
) {
897 char buf
[ SIG2STR_MAX
];
899 if ( sig2str ( sig
, buf
) == 0 ) {
900 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
901 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
902 PA_STATIC_TLS_SET ( signame
, t
);
910 case SIGHUP
: return "SIGHUP" ;
912 case SIGINT
: return "SIGINT" ;
914 case SIGQUIT
: return "SIGQUIT" ;
916 case SIGILL
: return "SIGULL" ;
918 case SIGTRAP
: return "SIGTRAP" ;
920 case SIGABRT
: return "SIGABRT" ;
922 case SIGBUS
: return "SIGBUS" ;
924 case SIGFPE
: return "SIGFPE" ;
926 case SIGKILL
: return "SIGKILL" ;
929 case SIGUSR1
: return "SIGUSR1" ;
931 case SIGSEGV
: return "SIGSEGV" ;
933 case SIGUSR2
: return "SIGUSR2" ;
936 case SIGPIPE
: return "SIGPIPE" ;
939 case SIGALRM
: return "SIGALRM" ;
941 case SIGTERM
: return "SIGTERM" ;
943 case SIGSTKFLT
: return "SIGSTKFLT" ;
946 case SIGCHLD
: return "SIGCHLD" ;
949 case SIGCONT
: return "SIGCONT" ;
952 case SIGSTOP
: return "SIGSTOP" ;
955 case SIGTSTP
: return "SIGTSTP" ;
958 case SIGTTIN
: return "SIGTTIN" ;
961 case SIGTTOU
: return "SIGTTOU" ;
964 case SIGURG
: return "SIGURG" ;
967 case SIGXCPU
: return "SIGXCPU" ;
970 case SIGXFSZ
: return "SIGXFSZ" ;
973 case SIGVTALRM
: return "SIGVTALRM" ;
976 case SIGPROF
: return "SIGPROF" ;
979 case SIGWINCH
: return "SIGWINCH" ;
982 case SIGIO
: return "SIGIO" ;
985 case SIGPWR
: return "SIGPWR" ;
988 case SIGSYS
: return "SIGSYS" ;
993 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
994 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
995 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
996 PA_STATIC_TLS_SET ( signame
, t
);
1005 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
1006 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
1007 PA_STATIC_TLS_SET ( signame
, t
);
1013 /* Check whether the specified GID and the group name match */
1014 static int is_group ( gid_t gid
, const char * name
) {
1015 struct group
* group
= NULL
;
1019 if (!( group
= pa_getgrgid_malloc ( gid
)))
1024 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
1029 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
1032 pa_getgrgid_free ( group
);
1037 /* Check the current user is member of the specified group */
1038 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1039 GETGROUPS_T
* gids
, tgid
;
1040 long n
= sysconf ( _SC_NGROUPS_MAX
);
1045 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1047 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1048 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1052 for ( i
= 0 ; i
< n
; i
++) {
1054 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1063 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1079 /* Check whether the specifc user id is a member of the specified group */
1080 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1081 struct group
* group
= NULL
;
1086 if (!( group
= pa_getgrnam_malloc ( name
)))
1094 for ( i
= group
-> gr_mem
; * i
; i
++) {
1095 struct passwd
* pw
= NULL
;
1098 if (!( pw
= pa_getpwnam_malloc (* i
)))
1101 if ( pw
-> pw_uid
== uid
)
1104 pa_getpwnam_free ( pw
);
1111 pa_getgrnam_free ( group
);
1116 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1117 gid_t
pa_get_gid_of_group ( const char * name
) {
1118 gid_t ret
= ( gid_t
) - 1 ;
1119 struct group
* gr
= NULL
;
1122 if (!( gr
= pa_getgrnam_malloc ( name
)))
1132 pa_getgrnam_free ( gr
);
1136 int pa_check_in_group ( gid_t g
) {
1137 gid_t gids
[ NGROUPS_MAX
];
1140 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1150 #else /* HAVE_GRP_H */
1152 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1158 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1163 gid_t
pa_get_gid_of_group ( const char * name
) {
1168 int pa_check_in_group ( gid_t g
) {
1175 /* Lock or unlock a file entirely.
1176 (advisory on UNIX, mandatory on Windows) */
1177 int pa_lock_fd ( int fd
, int b
) {
1179 struct flock f_lock
;
1181 /* Try a R/W lock first */
1183 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1184 f_lock
. l_whence
= SEEK_SET
;
1188 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1191 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1192 if ( b
&& errno
== EBADF
) {
1193 f_lock
. l_type
= F_RDLCK
;
1194 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1198 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1202 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1204 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1206 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1209 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1211 /* FIXME: Needs to set errno! */
1217 /* Remove trailing newlines from a string */
1218 char * pa_strip_nl ( char * s
) {
1221 s
[ strcspn ( s
, NEWLINE
)] = 0 ;
1225 char * pa_strip ( char * s
) {
1228 /* Drops trailing whitespace. Modifies the string in
1229 * place. Returns pointer to first non-space character */
1231 s
+= strspn ( s
, WHITESPACE
);
1233 for ( e
= s
; * e
; e
++)
1234 if (! strchr ( WHITESPACE
, * e
))
1245 /* Create a temporary lock file and lock it. */
1246 int pa_lock_lockfile ( const char * fn
) {
1253 if (( fd
= pa_open_cloexec ( fn
, O_CREAT
| O_RDWR
1257 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1258 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1262 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1263 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1267 if ( fstat ( fd
, & st
) < 0 ) {
1268 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1272 /* Check whether the file has been removed meanwhile. When yes,
1273 * restart this loop, otherwise, we're done */
1274 if ( st
. st_nlink
>= 1 )
1277 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1278 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1282 if ( pa_close ( fd
) < 0 ) {
1283 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1294 int saved_errno
= errno
;
1296 errno
= saved_errno
;
1302 /* Unlock a temporary lcok file */
1303 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1308 if ( unlink ( fn
) < 0 ) {
1309 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1314 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1315 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1319 if ( pa_close ( fd
) < 0 ) {
1320 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1327 static char * get_pulse_home ( void ) {
1332 if (!( h
= pa_get_home_dir_malloc ())) {
1333 pa_log_error ( "Failed to get home directory." );
1337 if ( stat ( h
, & st
) < 0 ) {
1338 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1342 if ( st
. st_uid
!= getuid ()) {
1343 pa_log_error ( "Home directory %s not ours." , h
);
1348 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1356 char * pa_get_state_dir ( void ) {
1359 /* The state directory shall contain dynamic data that should be
1360 * kept across reboots, and is private to this user */
1362 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1363 if (!( d
= get_pulse_home ()))
1366 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1367 * dir then this will break. */
1369 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1370 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1378 char * pa_get_home_dir_malloc ( void ) {
1380 size_t allocated
= 128 ;
1383 homedir
= pa_xmalloc ( allocated
);
1385 if (! pa_get_home_dir ( homedir
, allocated
)) {
1390 if ( strlen ( homedir
) < allocated
- 1 )
1400 char * pa_get_binary_name_malloc ( void ) {
1402 size_t allocated
= 128 ;
1405 t
= pa_xmalloc ( allocated
);
1407 if (! pa_get_binary_name ( t
, allocated
)) {
1412 if ( strlen ( t
) < allocated
- 1 )
1422 static char * make_random_dir ( mode_t m
) {
1423 static const char table
[] =
1424 "abcdefghijklmnopqrstuvwxyz"
1425 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1431 fn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX" , pa_get_temp_dir ());
1432 pathlen
= strlen ( fn
);
1440 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1441 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1443 u
= umask ((~ m
) & 0777 );
1446 saved_errno
= errno
;
1448 errno
= saved_errno
;
1453 if ( errno
!= EEXIST
) {
1454 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1461 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1464 if (!( p
= make_random_dir ( m
)))
1467 if ( symlink ( p
, k
) < 0 ) {
1468 int saved_errno
= errno
;
1470 if ( errno
!= EEXIST
)
1471 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1476 errno
= saved_errno
;
1484 char * pa_get_runtime_dir ( void ) {
1485 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1489 /* The runtime directory shall contain dynamic data that needs NOT
1490 * to be kept accross reboots and is usuallly private to the user,
1491 * except in system mode, where it might be accessible by other
1492 * users, too. Since we need POSIX locking and UNIX sockets in
1493 * this directory, we link it to a random subdir in /tmp, if it
1494 * was not explicitly configured. */
1496 m
= pa_in_system_mode () ? 0755U : 0700U ;
1498 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1500 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1501 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1505 return pa_xstrdup ( d
);
1508 if (!( d
= get_pulse_home ()))
1511 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1512 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1517 if (!( mid
= pa_machine_id ())) {
1522 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1527 /* OK, first let's check if the "runtime" symlink is already
1530 if (!( p
= pa_readlink ( k
))) {
1532 if ( errno
!= ENOENT
) {
1533 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1537 /* Hmm, so the runtime directory didn't exist yet, so let's
1538 * create one in /tmp and symlink that to it */
1540 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1542 /* Mhmm, maybe another process was quicker than us,
1543 * let's check if that was valid */
1544 if ( errno
== EEXIST
)
1553 /* Make sure that this actually makes sense */
1554 if (! pa_is_path_absolute ( p
)) {
1555 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1560 /* Hmm, so this symlink is still around, make sure nobody fools
1563 if ( lstat ( p
, & st
) < 0 ) {
1565 if ( errno
!= ENOENT
) {
1566 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1572 if ( S_ISDIR ( st
. st_mode
) &&
1573 ( st
. st_uid
== getuid ()) &&
1574 (( st
. st_mode
& 0777 ) == 0700 )) {
1580 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1586 /* Hmm, so the link points to some nonexisting or invalid
1587 * dir. Let's replace it by a new link. We first create a
1588 * temporary link and then rename that to allow concurrent
1589 * execution of this function. */
1591 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1593 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1595 if ( errno
!= EEXIST
) {
1596 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1603 /* Hmm, someone lese was quicker then us. Let's give
1604 * him some time to finish, and retry. */
1609 /* OK, we succeeded in creating the temporary symlink, so
1610 * let's rename it */
1611 if ( rename ( t
, k
) < 0 ) {
1612 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1628 /* Try to open a configuration file. If "env" is specified, open the
1629 * value of the specified environment variable. Otherwise look for a
1630 * file "local" in the home directory or a file "global" in global
1631 * file system. If "result" is non-NULL, a pointer to a newly
1632 * allocated buffer containing the used configuration file is
1634 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1639 if (! getenv ( PULSE_ROOTENV
))
1643 if ( env
&& ( fn
= getenv ( env
))) {
1647 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1648 /* FIXME: Needs to set errno! */
1653 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1655 * result
= pa_xstrdup ( fn
);
1660 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1670 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1671 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1672 else if (( h
= pa_get_home_dir_malloc ())) {
1673 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1679 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1680 /* FIXME: Needs to set errno! */
1687 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1689 * result
= pa_xstrdup ( fn
);
1695 if ( errno
!= ENOENT
) {
1696 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1708 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1709 /* FIXME: Needs to set errno! */
1714 if (( f
= pa_fopen_cloexec ( global
, "r" ))) {
1717 * result
= pa_xstrdup ( global
);
1727 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1732 if (! getenv ( PULSE_ROOTENV
))
1736 if ( env
&& ( fn
= getenv ( env
))) {
1739 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1740 /* FIXME: Needs to set errno! */
1745 if ( access ( fn
, R_OK
) == 0 )
1746 return pa_xstrdup ( fn
);
1748 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1757 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1758 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1759 else if (( h
= pa_get_home_dir_malloc ())) {
1760 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1766 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1767 /* FIXME: Needs to set errno! */
1774 if ( access ( fn
, R_OK
) == 0 ) {
1775 char * r
= pa_xstrdup ( fn
);
1780 if ( errno
!= ENOENT
) {
1781 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1791 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1792 /* FIXME: Needs to set errno! */
1797 if ( access ( global
, R_OK
) == 0 )
1798 return pa_xstrdup ( global
);
1806 /* Format the specified data as a hexademical string */
1807 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1808 size_t i
= 0 , j
= 0 ;
1809 const char hex
[] = "0123456789abcdef" ;
1813 pa_assert ( slength
> 0 );
1815 while ( i
< dlength
&& j
+ 3 <= slength
) {
1816 s
[ j
++] = hex
[* d
>> 4 ];
1817 s
[ j
++] = hex
[* d
& 0xF ];
1823 s
[ j
< slength
? j
: slength
] = 0 ;
1827 /* Convert a hexadecimal digit to a number or -1 if invalid */
1828 static int hexc ( char c
) {
1829 if ( c
>= '0' && c
<= '9' )
1832 if ( c
>= 'A' && c
<= 'F' )
1833 return c
- 'A' + 10 ;
1835 if ( c
>= 'a' && c
<= 'f' )
1836 return c
- 'a' + 10 ;
1842 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1843 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1849 while ( j
< dlength
&& * p
) {
1852 if (( b
= hexc (*( p
++))) < 0 )
1855 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1860 if (( b
= hexc (*( p
++))) < 0 )
1863 d
[ j
] |= ( uint8_t ) b
;
1870 /* Returns nonzero when *s starts with *pfx */
1871 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1879 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1882 /* Returns nonzero when *s ends with *sfx */
1883 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1892 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1895 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1901 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1905 char * pa_make_path_absolute ( const char * p
) {
1911 if ( pa_is_path_absolute ( p
))
1912 return pa_xstrdup ( p
);
1914 if (!( cwd
= pa_getcwd ()))
1915 return pa_xstrdup ( p
);
1917 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1922 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1923 * if fn is non-null and starts with / return fn
1924 * otherwise append fn to the run time path and return it */
1925 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1928 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1933 if ( pa_is_path_absolute ( fn
))
1934 return pa_xstrdup ( fn
);
1942 if (!( mid
= pa_machine_id ())) {
1947 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1950 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1958 char * pa_runtime_path ( const char * fn
) {
1959 return get_path ( fn
, FALSE
, TRUE
);
1962 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1963 return get_path ( fn
, appendmid
, FALSE
);
1966 /* Convert the string s to a signed integer in *ret_i */
1967 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1975 l
= strtol ( s
, & x
, 0 );
1977 if (! x
|| * x
|| errno
) {
1983 if (( int32_t ) l
!= l
) {
1988 * ret_i
= ( int32_t ) l
;
1993 /* Convert the string s to an unsigned integer in *ret_u */
1994 int pa_atou ( const char * s
, uint32_t * ret_u
) {
2002 l
= strtoul ( s
, & x
, 0 );
2004 if (! x
|| * x
|| errno
) {
2010 if (( uint32_t ) l
!= l
) {
2015 * ret_u
= ( uint32_t ) l
;
2020 #ifdef HAVE_STRTOF_L
2021 static locale_t c_locale
= NULL
;
2023 static void c_locale_destroy ( void ) {
2024 freelocale ( c_locale
);
2028 int pa_atod ( const char * s
, double * ret_d
) {
2035 /* This should be locale independent */
2037 #ifdef HAVE_STRTOF_L
2041 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2042 atexit ( c_locale_destroy
);
2048 f
= strtod_l ( s
, & x
, c_locale
);
2056 if (! x
|| * x
|| errno
) {
2067 /* Same as snprintf, but guarantees NUL-termination on every platform */
2068 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2073 pa_assert ( size
> 0 );
2076 va_start ( ap
, format
);
2077 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2083 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2084 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2088 pa_assert ( size
> 0 );
2091 ret
= vsnprintf ( str
, size
, format
, ap
);
2098 if (( size_t ) ret
> size
- 1 )
2101 return ( size_t ) ret
;
2104 /* Truncate the specified string, but guarantee that the string
2105 * returned still validates as UTF8 */
2106 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2108 pa_assert ( pa_utf8_valid ( c
));
2115 while ( l
> 0 && ! pa_utf8_valid ( c
))
2121 char * pa_getcwd ( void ) {
2125 char * p
= pa_xmalloc ( l
);
2129 if ( errno
!= ERANGE
)
2137 void * pa_will_need ( const void * p
, size_t l
) {
2138 #ifdef RLIMIT_MEMLOCK
2149 a
= PA_PAGE_ALIGN_PTR ( p
);
2150 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2152 #ifdef HAVE_POSIX_MADVISE
2153 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2154 pa_log_debug ( "posix_madvise() worked fine!" );
2159 /* Most likely the memory was not mmap()ed from a file and thus
2160 * madvise() didn't work, so let's misuse mlock() do page this
2161 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2162 * inviting, the man page of mlock() tells us: "All pages that
2163 * contain a part of the specified address range are guaranteed to
2164 * be resident in RAM when the call returns successfully." */
2166 #ifdef RLIMIT_MEMLOCK
2167 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2169 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2170 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
));
2175 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2177 bs
= PA_PAGE_SIZE
* 4 ;
2180 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2183 while ( size
> 0 && bs
> 0 ) {
2188 if ( mlock ( a
, bs
) < 0 ) {
2189 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2193 pa_assert_se ( munlock ( a
, bs
) == 0 );
2195 a
= ( const uint8_t *) a
+ bs
;
2201 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2203 pa_log_debug ( "mlock() worked fine!" );
2208 void pa_close_pipe ( int fds
[ 2 ]) {
2212 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2215 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2217 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2220 char * pa_readlink ( const char * p
) {
2229 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2234 if (( size_t ) n
< l
- 1 ) {
2244 int pa_close_all ( int except_fd
, ...) {
2249 va_start ( ap
, except_fd
);
2252 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2257 p
= pa_xnew ( int , n
+ 1 );
2259 va_start ( ap
, except_fd
);
2262 if ( except_fd
>= 0 ) {
2266 while (( fd
= va_arg ( ap
, int )) >= 0 )
2273 r
= pa_close_allv ( p
);
2279 int pa_close_allv ( const int except_fds
[]) {
2287 if (( d
= opendir ( "/proc/self/fd" ))) {
2291 while (( de
= readdir ( d
))) {
2297 if ( de
-> d_name
[ 0 ] == '.' )
2301 l
= strtol ( de
-> d_name
, & e
, 10 );
2302 if ( errno
!= 0 || ! e
|| * e
) {
2310 if (( long ) fd
!= l
) {
2323 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2324 if ( except_fds
[ i
] == fd
) {
2332 if ( pa_close ( fd
) < 0 ) {
2333 saved_errno
= errno
;
2335 errno
= saved_errno
;
2347 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2348 maxfd
= ( int ) rl
. rlim_max
;
2350 maxfd
= sysconf ( _SC_OPEN_MAX
);
2352 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2357 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2358 if ( except_fds
[ i
] == fd
) {
2366 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2373 int pa_unblock_sigs ( int except
, ...) {
2378 va_start ( ap
, except
);
2381 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2386 p
= pa_xnew ( int , n
+ 1 );
2388 va_start ( ap
, except
);
2395 while (( sig
= va_arg ( ap
, int )) >= 0 )
2402 r
= pa_unblock_sigsv ( p
);
2408 int pa_unblock_sigsv ( const int except
[]) {
2412 if ( sigemptyset (& ss
) < 0 )
2415 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2416 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2419 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2422 int pa_reset_sigs ( int except
, ...) {
2427 va_start ( ap
, except
);
2430 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2435 p
= pa_xnew ( int , n
+ 1 );
2437 va_start ( ap
, except
);
2444 while (( sig
= va_arg ( ap
, int )) >= 0 )
2451 r
= pa_reset_sigsv ( p
);
2457 int pa_reset_sigsv ( const int except
[]) {
2460 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2461 pa_bool_t reset
= TRUE
;
2472 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2473 if ( sig
== except
[ i
]) {
2482 struct sigaction sa
;
2484 memset (& sa
, 0 , sizeof ( sa
));
2485 sa
. sa_handler
= SIG_DFL
;
2487 /* On Linux the first two RT signals are reserved by
2488 * glibc, and sigaction() will return EINVAL for them. */
2489 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2490 if ( errno
!= EINVAL
)
2498 void pa_set_env ( const char * key
, const char * value
) {
2502 /* This is not thread-safe */
2504 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2507 void pa_set_env_and_record ( const char * key
, const char * value
) {
2511 /* This is not thread-safe */
2513 pa_set_env ( key
, value
);
2514 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2517 void pa_unset_env_recorded ( void ) {
2519 /* This is not thread-safe */
2524 recorded_env
= pa_strlist_pop ( recorded_env
, & s
);
2534 pa_bool_t
pa_in_system_mode ( void ) {
2537 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2543 char * pa_get_user_name_malloc ( void ) {
2547 #ifdef _SC_LOGIN_NAME_MAX
2548 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2554 u
= pa_xnew ( char , k
+ 1 );
2556 if (!( pa_get_user_name ( u
, k
))) {
2564 char * pa_get_host_name_malloc ( void ) {
2573 if (! pa_get_host_name ( c
, l
)) {
2575 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2578 } else if ( strlen ( c
) < l
- 1 ) {
2586 u
= pa_utf8_filter ( c
);
2591 /* Hmm, the hostname is as long the space we offered the
2592 * function, we cannot know if it fully fit in, so let's play
2593 * safe and retry. */
2602 char * pa_machine_id ( void ) {
2606 /* The returned value is supposed be some kind of ascii identifier
2607 * that is unique and stable across reboots. */
2609 /* First we try the D-Bus UUID, which is the best option we have,
2610 * since it fits perfectly our needs and is not as volatile as the
2611 * hostname which might be set from dhcp. */
2613 if (( f
= pa_fopen_cloexec ( PA_MACHINE_ID
, "r" ))) {
2614 char ln
[ 34 ] = "" , * r
;
2616 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2622 return pa_utf8_filter ( ln
);
2625 if (( h
= pa_get_host_name_malloc ()))
2628 /* If no hostname was set we use the POSIX hostid. It's usually
2629 * the IPv4 address. Might not be that stable. */
2630 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2633 char * pa_session_id ( void ) {
2636 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2639 return pa_utf8_filter ( e
);
2642 char * pa_uname_string ( void ) {
2645 pa_assert_se ( uname (& u
) >= 0 );
2647 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2650 #ifdef HAVE_VALGRIND_MEMCHECK_H
2651 pa_bool_t
pa_in_valgrind ( void ) {
2654 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2655 * here instead of really checking whether we run in valgrind or
2659 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2665 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2676 void pa_reduce ( unsigned * num
, unsigned * den
) {
2678 unsigned gcd
= pa_gcd (* num
, * den
);
2686 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2689 unsigned pa_ncpus ( void ) {
2692 #ifdef _SC_NPROCESSORS_CONF
2693 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2698 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2701 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2710 sb
= pa_strbuf_new ();
2715 if (!( p
= strstr ( s
, a
)))
2718 pa_strbuf_putsn ( sb
, s
, p
- s
);
2719 pa_strbuf_puts ( sb
, b
);
2723 pa_strbuf_puts ( sb
, s
);
2725 return pa_strbuf_tostring_free ( sb
);
2728 char * pa_escape ( const char * p
, const char * chars
) {
2731 pa_strbuf
* buf
= pa_strbuf_new ();
2733 for ( s
= p
; * s
; ++ s
) {
2735 pa_strbuf_putc ( buf
, ' \\ ' );
2737 for ( c
= chars
; * c
; ++ c
) {
2739 pa_strbuf_putc ( buf
, ' \\ ' );
2744 pa_strbuf_putc ( buf
, * s
);
2747 return pa_strbuf_tostring_free ( buf
);
2750 char * pa_unescape ( char * p
) {
2752 pa_bool_t escaped
= FALSE
;
2754 for ( s
= p
, d
= p
; * s
; s
++) {
2755 if (! escaped
&& * s
== ' \\ ' ) {
2769 char * pa_realpath ( const char * path
) {
2773 /* We want only abolsute paths */
2774 if ( path
[ 0 ] != '/' ) {
2779 #if defined(__GLIBC__) || defined(__APPLE__)
2783 if (!( r
= realpath ( path
, NULL
)))
2786 /* We copy this here in case our pa_xmalloc() is not
2787 * implemented on top of libc malloc() */
2791 #elif defined(PATH_MAX)
2794 path_buf
= pa_xmalloc ( PATH_MAX
);
2796 if (!( t
= realpath ( path
, path_buf
))) {
2802 #error "It's not clear whether this system supports realpath(..., NULL) like GNU libc does. If it doesn't we need a private version of realpath() here."
2808 void pa_disable_sigpipe ( void ) {
2811 struct sigaction sa
;
2815 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2816 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2820 sa
. sa_handler
= SIG_IGN
;
2822 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2823 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2829 void pa_xfreev ( void ** a
) {
2835 for ( p
= a
; * p
; p
++)
2841 char ** pa_split_spaces_strv ( const char * s
) {
2843 unsigned i
= 0 , n
= 8 ;
2844 const char * state
= NULL
;
2846 t
= pa_xnew ( char *, n
);
2847 while (( e
= pa_split_spaces ( s
, & state
))) {
2852 t
= pa_xrenew ( char *, t
, n
);
2865 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2868 if ( pa_is_path_absolute ( path
))
2869 return pa_xstrdup ( path
);
2871 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2874 size_t pa_pipe_buf ( int fd
) {
2879 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2890 void pa_reset_personality ( void ) {
2893 if ( personality ( PER_LINUX
) < 0 )
2894 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2899 #if defined(__linux__) && !defined(__OPTIMIZE__)
2901 pa_bool_t
pa_run_from_build_tree ( void ) {
2903 pa_bool_t b
= FALSE
;
2905 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2908 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2909 b
= pa_startswith ( rp
, PA_BUILDDIR
);
2918 const char * pa_get_temp_dir ( void ) {
2921 if (( t
= getenv ( "TMPDIR" )) &&
2922 pa_is_path_absolute ( t
))
2925 if (( t
= getenv ( "TMP" )) &&
2926 pa_is_path_absolute ( t
))
2929 if (( t
= getenv ( "TEMP" )) &&
2930 pa_is_path_absolute ( t
))
2933 if (( t
= getenv ( "TEMPDIR" )) &&
2934 pa_is_path_absolute ( t
))
2940 int pa_open_cloexec ( const char * fn
, int flags
, mode_t mode
) {
2948 if (( fd
= open ( fn
, flags
| O_CLOEXEC
, mode
)) >= 0 )
2951 if ( errno
!= EINVAL
)
2955 if (( fd
= open ( fn
, flags
, mode
)) < 0 )
2959 /* Some implementations might simply ignore O_CLOEXEC if it is not
2960 * understood, make sure FD_CLOEXEC is enabled anyway */
2962 pa_make_fd_cloexec ( fd
);
2966 int pa_socket_cloexec ( int domain
, int type
, int protocol
) {
2970 if (( fd
= socket ( domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0 )
2973 if ( errno
!= EINVAL
)
2977 if (( fd
= socket ( domain
, type
, protocol
)) < 0 )
2981 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
2982 * not understood, make sure FD_CLOEXEC is enabled anyway */
2984 pa_make_fd_cloexec ( fd
);
2988 int pa_pipe_cloexec ( int pipefd
[ 2 ]) {
2992 if (( r
= pipe2 ( pipefd
, O_CLOEXEC
)) >= 0 )
2995 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3000 if (( r
= pipe ( pipefd
)) < 0 )
3004 pa_make_fd_cloexec ( pipefd
[ 0 ]);
3005 pa_make_fd_cloexec ( pipefd
[ 1 ]);
3010 int pa_accept_cloexec ( int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
3014 if (( fd
= accept4 ( sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0 )
3017 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
3022 if (( fd
= accept ( sockfd
, addr
, addrlen
)) < 0 )
3026 pa_make_fd_cloexec ( fd
);
3030 FILE * pa_fopen_cloexec ( const char * path
, const char * mode
) {
3034 m
= pa_sprintf_malloc ( "%se" , mode
);
3037 if (( f
= fopen ( path
, m
))) {
3044 if ( errno
!= EINVAL
)
3047 if (!( f
= fopen ( path
, mode
)))
3051 pa_make_fd_cloexec ( fileno ( f
));
3055 void pa_nullify_stdfds ( void ) {
3058 pa_close ( STDIN_FILENO
);
3059 pa_close ( STDOUT_FILENO
);
3060 pa_close ( STDERR_FILENO
);
3062 pa_assert_se ( open ( "/dev/null" , O_RDONLY
) == STDIN_FILENO
);
3063 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDOUT_FILENO
);
3064 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDERR_FILENO
);
3071 char * pa_read_line_from_file ( const char * fn
) {
3073 char ln
[ 256 ] = "" , * r
;
3075 if (!( f
= pa_fopen_cloexec ( fn
, "r" )))
3078 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
3087 return pa_xstrdup ( ln
);
3090 pa_bool_t
pa_running_in_vm ( void ) {
3092 #if defined(__i386__) || defined(__x86_64__)
3094 /* Both CPUID and DMI are x86 specific interfaces... */
3096 uint32_t eax
= 0x40000000 ;
3103 const char * const dmi_vendors
[] = {
3104 "/sys/class/dmi/id/sys_vendor" ,
3105 "/sys/class/dmi/id/board_vendor" ,
3106 "/sys/class/dmi/id/bios_vendor"
3111 for ( i
= 0 ; i
< PA_ELEMENTSOF ( dmi_vendors
); i
++) {
3114 if (( s
= pa_read_line_from_file ( dmi_vendors
[ i
]))) {
3116 if ( pa_startswith ( s
, "QEMU" ) ||
3117 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3118 pa_startswith ( s
, "VMware" ) ||
3119 pa_startswith ( s
, "VMW" ) ||
3120 pa_startswith ( s
, "Microsoft Corporation" ) ||
3121 pa_startswith ( s
, "innotek GmbH" ) ||
3122 pa_startswith ( s
, "Xen" )) {
3134 /* http://lwn.net/Articles/301888/ */
3137 __asm__
__volatile__ (
3138 /* ebx/rbx is being used for PIC! */
3139 " push %%" PA_REG_b
" \n\t "
3141 " mov %%ebx, %1 \n\t "
3142 " pop %%" PA_REG_b
" \n\t "
3144 : "=a" ( eax
), "=r" ( sig
. sig32
[ 0 ]), "=c" ( sig
. sig32
[ 1 ]), "=d" ( sig
. sig32
[ 2 ])
3148 if ( pa_streq ( sig
. text
, "XenVMMXenVMM" ) ||
3149 pa_streq ( sig
. text
, "KVMKVMKVM" ) ||
3150 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3151 pa_streq ( sig
. text
, "VMwareVMware" ) ||
3152 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3153 pa_streq ( sig
. text
, "Microsoft Hv" ))