]>
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>
121 #include "core-util.h"
123 /* Not all platforms have this */
125 #define MSG_NOSIGNAL 0
128 static pa_strlist
* recorded_env
= NULL
;
132 #define PULSE_ROOTENV "PULSE_ROOT"
134 int pa_set_root ( HANDLE handle
) {
135 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
137 strcpy ( library_path
, PULSE_ROOTENV
"=" );
139 /* FIXME: Needs to set errno */
141 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
144 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
148 if ( _putenv ( library_path
) < 0 )
156 /** Make a file descriptor nonblock. Doesn't do any error checking */
157 void pa_make_fd_nonblock ( int fd
) {
163 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
165 if (!( v
& O_NONBLOCK
))
166 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
168 #elif defined(OS_IS_WIN32)
170 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
171 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
172 pa_log_warn ( "Only sockets can be made non-blocking!" );
175 pa_log_warn ( "Non-blocking I/O not supported.!" );
180 /* Set the FD_CLOEXEC flag for a fd */
181 void pa_make_fd_cloexec ( int fd
) {
187 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
189 if (!( v
& FD_CLOEXEC
))
190 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
195 /** Creates a directory securely */
196 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
207 u
= umask ((~ m
) & 0777 );
213 if ( r
< 0 && errno
!= EEXIST
)
217 if ( uid
== ( uid_t
)- 1 )
219 if ( gid
== ( gid_t
)- 1 )
221 ( void ) chown ( dir
, uid
, gid
);
229 if ( lstat ( dir
, & st
) < 0 )
231 if ( stat ( dir
, & st
) < 0 )
236 if (! S_ISDIR ( st
. st_mode
) ||
237 ( st
. st_uid
!= uid
) ||
238 ( st
. st_gid
!= gid
) ||
239 (( st
. st_mode
& 0777 ) != m
)) {
244 pa_log_warn ( "Secure directory creation not supported on Win32." );
257 /* Return a newly allocated sting containing the parent directory of the specified file */
258 char * pa_parent_dir ( const char * fn
) {
259 char * slash
, * dir
= pa_xstrdup ( fn
);
261 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
271 /* Creates a the parent directory of the specified path securely */
272 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
276 if (!( dir
= pa_parent_dir ( fn
)))
279 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
289 /** Platform independent read function. Necessary since not all
290 * systems treat all file descriptors equal. If type is
291 * non-NULL it is used to cache the type of the fd. This is
292 * useful for making sure that only a single syscall is executed per
293 * function call. The variable pointed to should be initialized to 0
295 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
299 if (! type
|| * type
== 0 ) {
302 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
305 if ( WSAGetLastError () != WSAENOTSOCK
) {
306 errno
= WSAGetLastError ();
319 if (( r
= read ( fd
, buf
, count
)) < 0 )
327 /** Similar to pa_read(), but handles writes */
328 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
330 if (! type
|| * type
== 0 ) {
334 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
346 if ( WSAGetLastError () != WSAENOTSOCK
) {
347 errno
= WSAGetLastError ();
351 if ( errno
!= ENOTSOCK
)
362 if (( r
= write ( fd
, buf
, count
)) < 0 )
370 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
371 * unless EOF is reached or an error occurred */
372 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
388 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
395 data
= ( uint8_t *) data
+ r
;
402 /** Similar to pa_loop_read(), but wraps write() */
403 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
419 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
426 data
= ( const uint8_t *) data
+ r
;
433 /** Platform independent read function. Necessary since not all
434 * systems treat all file descriptors equal. */
435 int pa_close ( int fd
) {
440 if (( ret
= closesocket ( fd
)) == 0 )
443 if ( WSAGetLastError () != WSAENOTSOCK
) {
444 errno
= WSAGetLastError ();
452 if (( r
= close ( fd
)) < 0 )
460 /* Print a warning messages in case that the given signal is not
461 * blocked or trapped */
462 void pa_check_signal_is_blocked ( int sig
) {
463 #ifdef HAVE_SIGACTION
467 /* If POSIX threads are supported use thread-aware
468 * pthread_sigmask() function, to check if the signal is
469 * blocked. Otherwise fall back to sigprocmask() */
472 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
474 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
475 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
482 if ( sigismember (& set
, sig
))
485 /* Check whether the signal is trapped */
487 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
488 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
492 if ( sa
. sa_handler
!= SIG_DFL
)
495 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
496 #else /* HAVE_SIGACTION */
497 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
501 /* The following function is based on an example from the GNU libc
502 * documentation. This function is similar to GNU's asprintf(). */
503 char * pa_sprintf_malloc ( const char * format
, ...) {
513 c
= pa_xrealloc ( c
, size
);
515 va_start ( ap
, format
);
516 r
= vsnprintf ( c
, size
, format
, ap
);
521 if ( r
> - 1 && ( size_t ) r
< size
)
524 if ( r
> - 1 ) /* glibc 2.1 */
531 /* Same as the previous function, but use a va_list instead of an
533 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
543 c
= pa_xrealloc ( c
, size
);
546 r
= vsnprintf ( c
, size
, format
, aq
);
551 if ( r
> - 1 && ( size_t ) r
< size
)
554 if ( r
> - 1 ) /* glibc 2.1 */
561 /* Similar to OpenBSD's strlcpy() function */
562 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
580 static int set_scheduler ( int rtprio
) {
581 struct sched_param sp
;
587 dbus_error_init (& error
);
591 sp
. sched_priority
= rtprio
;
593 #ifdef SCHED_RESET_ON_FORK
594 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
)) == 0 ) {
595 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
600 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
)) == 0 ) {
601 pa_log_debug ( "SCHED_RR worked." );
606 /* Try to talk to RealtimeKit */
608 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
609 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
610 dbus_error_free (& error
);
615 /* We need to disable exit on disconnect because otherwise
616 * dbus_shutdown will kill us. See
617 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
618 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
620 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
621 dbus_connection_unref ( bus
);
624 pa_log_debug ( "RealtimeKit worked." );
636 /* Make the current thread a realtime thread, and acquire the highest
637 * rtprio we can get that is less or equal the specified parameter. If
638 * the thread is already realtime, don't do anything. */
639 int pa_make_realtime ( int rtprio
) {
641 #ifdef _POSIX_PRIORITY_SCHEDULING
644 if ( set_scheduler ( rtprio
) >= 0 ) {
645 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
649 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
650 if ( set_scheduler ( p
)) {
651 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
655 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
664 static int set_nice ( int nice_level
) {
670 dbus_error_init (& error
);
673 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
674 pa_log_debug ( "setpriority() worked." );
679 /* Try to talk to RealtimeKit */
681 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
682 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
683 dbus_error_free (& error
);
688 /* We need to disable exit on disconnect because otherwise
689 * dbus_shutdown will kill us. See
690 * https://bugs.freedesktop.org/show_bug.cgi?id=16924 */
691 dbus_connection_set_exit_on_disconnect ( bus
, FALSE
);
693 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
694 dbus_connection_unref ( bus
);
697 pa_log_debug ( "RealtimeKit worked." );
707 /* Raise the priority of the current process as much as possible that
708 * is <= the specified nice level..*/
709 int pa_raise_priority ( int nice_level
) {
711 #ifdef HAVE_SYS_RESOURCE_H
714 if ( set_nice ( nice_level
) >= 0 ) {
715 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
719 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
720 if ( set_nice ( n
) > 0 ) {
721 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
725 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
730 if ( nice_level
< 0 ) {
731 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
732 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
737 pa_log_info ( "Successfully gained high priority class." );
744 /* Reset the priority to normal, inverting the changes made by
745 * pa_raise_priority() and pa_make_realtime()*/
746 void pa_reset_priority ( void ) {
747 #ifdef HAVE_SYS_RESOURCE_H
748 struct sched_param sp
;
750 setpriority ( PRIO_PROCESS
, 0 , 0 );
753 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
757 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
761 int pa_match ( const char * expr
, const char * v
) {
766 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
771 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
773 else if ( k
== REG_NOMATCH
)
786 /* Try to parse a boolean string value.*/
787 int pa_parse_boolean ( const char * v
) {
792 /* First we check language independant */
793 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
795 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
798 /* And then we check language dependant */
799 if (( expr
= nl_langinfo ( YESEXPR
)))
801 if (( r
= pa_match ( expr
, v
)) > 0 )
804 if (( expr
= nl_langinfo ( NOEXPR
)))
806 if (( r
= pa_match ( expr
, v
)) > 0 )
813 /* Split the specified string wherever one of the strings in delimiter
814 * occurs. Each time it is called returns a newly allocated string
815 * with pa_xmalloc(). The variable state points to, should be
816 * initiallized to NULL before the first call. */
817 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
818 const char * current
= * state
? * state
: c
;
824 l
= strcspn ( current
, delimiter
);
830 return pa_xstrndup ( current
, l
);
833 /* What is interpreted as whitespace? */
834 #define WHITESPACE " \t\n "
836 /* Split a string into words. Otherwise similar to pa_split(). */
837 char * pa_split_spaces ( const char * c
, const char ** state
) {
838 const char * current
= * state
? * state
: c
;
841 if (!* current
|| * c
== 0 )
844 current
+= strspn ( current
, WHITESPACE
);
845 l
= strcspn ( current
, WHITESPACE
);
849 return pa_xstrndup ( current
, l
);
852 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
854 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
855 const char * pa_sig2str ( int sig
) {
868 char buf
[ SIG2STR_MAX
];
870 if ( sig2str ( sig
, buf
) == 0 ) {
871 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
872 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
873 PA_STATIC_TLS_SET ( signame
, t
);
881 case SIGHUP
: return "SIGHUP" ;
883 case SIGINT
: return "SIGINT" ;
885 case SIGQUIT
: return "SIGQUIT" ;
887 case SIGILL
: return "SIGULL" ;
889 case SIGTRAP
: return "SIGTRAP" ;
891 case SIGABRT
: return "SIGABRT" ;
893 case SIGBUS
: return "SIGBUS" ;
895 case SIGFPE
: return "SIGFPE" ;
897 case SIGKILL
: return "SIGKILL" ;
900 case SIGUSR1
: return "SIGUSR1" ;
902 case SIGSEGV
: return "SIGSEGV" ;
904 case SIGUSR2
: return "SIGUSR2" ;
907 case SIGPIPE
: return "SIGPIPE" ;
910 case SIGALRM
: return "SIGALRM" ;
912 case SIGTERM
: return "SIGTERM" ;
914 case SIGSTKFLT
: return "SIGSTKFLT" ;
917 case SIGCHLD
: return "SIGCHLD" ;
920 case SIGCONT
: return "SIGCONT" ;
923 case SIGSTOP
: return "SIGSTOP" ;
926 case SIGTSTP
: return "SIGTSTP" ;
929 case SIGTTIN
: return "SIGTTIN" ;
932 case SIGTTOU
: return "SIGTTOU" ;
935 case SIGURG
: return "SIGURG" ;
938 case SIGXCPU
: return "SIGXCPU" ;
941 case SIGXFSZ
: return "SIGXFSZ" ;
944 case SIGVTALRM
: return "SIGVTALRM" ;
947 case SIGPROF
: return "SIGPROF" ;
950 case SIGWINCH
: return "SIGWINCH" ;
953 case SIGIO
: return "SIGIO" ;
956 case SIGPWR
: return "SIGPWR" ;
959 case SIGSYS
: return "SIGSYS" ;
964 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
965 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
966 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
967 PA_STATIC_TLS_SET ( signame
, t
);
976 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
977 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
978 PA_STATIC_TLS_SET ( signame
, t
);
984 /* Check whether the specified GID and the group name match */
985 static int is_group ( gid_t gid
, const char * name
) {
986 struct group
* group
= NULL
;
990 if (!( group
= pa_getgrgid_malloc ( gid
)))
995 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
1000 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
1003 pa_getgrgid_free ( group
);
1008 /* Check the current user is member of the specified group */
1009 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1010 GETGROUPS_T
* gids
, tgid
;
1011 long n
= sysconf ( _SC_NGROUPS_MAX
);
1016 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1018 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1019 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1023 for ( i
= 0 ; i
< n
; i
++) {
1025 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1034 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1050 /* Check whether the specifc user id is a member of the specified group */
1051 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1052 struct group
* group
= NULL
;
1057 if (!( group
= pa_getgrnam_malloc ( name
)))
1065 for ( i
= group
-> gr_mem
; * i
; i
++) {
1066 struct passwd
* pw
= NULL
;
1069 if (!( pw
= pa_getpwnam_malloc (* i
)))
1072 if ( pw
-> pw_uid
== uid
)
1075 pa_getpwnam_free ( pw
);
1082 pa_getgrnam_free ( group
);
1087 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1088 gid_t
pa_get_gid_of_group ( const char * name
) {
1089 gid_t ret
= ( gid_t
) - 1 ;
1090 struct group
* gr
= NULL
;
1093 if (!( gr
= pa_getgrnam_malloc ( name
)))
1103 pa_getgrnam_free ( gr
);
1107 int pa_check_in_group ( gid_t g
) {
1108 gid_t gids
[ NGROUPS_MAX
];
1111 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1121 #else /* HAVE_GRP_H */
1123 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1129 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1134 gid_t
pa_get_gid_of_group ( const char * name
) {
1139 int pa_check_in_group ( gid_t g
) {
1146 /* Lock or unlock a file entirely.
1147 (advisory on UNIX, mandatory on Windows) */
1148 int pa_lock_fd ( int fd
, int b
) {
1150 struct flock f_lock
;
1152 /* Try a R/W lock first */
1154 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1155 f_lock
. l_whence
= SEEK_SET
;
1159 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1162 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1163 if ( b
&& errno
== EBADF
) {
1164 f_lock
. l_type
= F_RDLCK
;
1165 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1169 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1173 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1175 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1177 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1180 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1182 /* FIXME: Needs to set errno! */
1188 /* Remove trailing newlines from a string */
1189 char * pa_strip_nl ( char * s
) {
1192 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1196 /* Create a temporary lock file and lock it. */
1197 int pa_lock_lockfile ( const char * fn
) {
1204 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1211 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1212 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1216 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1217 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1221 if ( fstat ( fd
, & st
) < 0 ) {
1222 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1226 /* Check whether the file has been removed meanwhile. When yes,
1227 * restart this loop, otherwise, we're done */
1228 if ( st
. st_nlink
>= 1 )
1231 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1232 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1236 if ( pa_close ( fd
) < 0 ) {
1237 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1250 int saved_errno
= errno
;
1252 errno
= saved_errno
;
1258 /* Unlock a temporary lcok file */
1259 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1264 if ( unlink ( fn
) < 0 ) {
1265 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1270 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1271 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1275 if ( pa_close ( fd
) < 0 ) {
1276 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1283 static char * get_pulse_home ( void ) {
1288 if (!( h
= pa_get_home_dir_malloc ())) {
1289 pa_log_error ( "Failed to get home directory." );
1293 if ( stat ( h
, & st
) < 0 ) {
1294 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1298 if ( st
. st_uid
!= getuid ()) {
1299 pa_log_error ( "Home directory %s not ours." , h
);
1304 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1312 char * pa_get_state_dir ( void ) {
1315 /* The state directory shall contain dynamic data that should be
1316 * kept across reboots, and is private to this user */
1318 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1319 if (!( d
= get_pulse_home ()))
1322 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1323 * dir then this will break. */
1325 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1326 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1334 char * pa_get_home_dir_malloc ( void ) {
1336 size_t allocated
= 128 ;
1339 homedir
= pa_xmalloc ( allocated
);
1341 if (! pa_get_home_dir ( homedir
, allocated
)) {
1346 if ( strlen ( homedir
) < allocated
- 1 )
1356 char * pa_get_binary_name_malloc ( void ) {
1358 size_t allocated
= 128 ;
1361 t
= pa_xmalloc ( allocated
);
1363 if (! pa_get_binary_name ( t
, allocated
)) {
1368 if ( strlen ( t
) < allocated
- 1 )
1378 static char * make_random_dir ( mode_t m
) {
1379 static const char table
[] =
1380 "abcdefghijklmnopqrstuvwxyz"
1381 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1388 if (!( tmpdir
= getenv ( "TMPDIR" )))
1389 if (!( tmpdir
= getenv ( "TMP" )))
1390 if (!( tmpdir
= getenv ( "TEMP" )))
1391 tmpdir
= getenv ( "TEMPDIR" );
1393 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1396 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1397 pathlen
= strlen ( fn
);
1405 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1406 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1408 u
= umask ((~ m
) & 0777 );
1411 saved_errno
= errno
;
1413 errno
= saved_errno
;
1418 if ( errno
!= EEXIST
) {
1419 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1426 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1429 if (!( p
= make_random_dir ( m
)))
1432 if ( symlink ( p
, k
) < 0 ) {
1433 int saved_errno
= errno
;
1435 if ( errno
!= EEXIST
)
1436 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1441 errno
= saved_errno
;
1449 char * pa_get_runtime_dir ( void ) {
1450 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1454 /* The runtime directory shall contain dynamic data that needs NOT
1455 * to be kept accross reboots and is usuallly private to the user,
1456 * except in system mode, where it might be accessible by other
1457 * users, too. Since we need POSIX locking and UNIX sockets in
1458 * this directory, we link it to a random subdir in /tmp, if it
1459 * was not explicitly configured. */
1461 m
= pa_in_system_mode () ? 0755U : 0700U ;
1463 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1465 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1466 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1470 return pa_xstrdup ( d
);
1473 if (!( d
= get_pulse_home ()))
1476 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1477 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1482 if (!( mid
= pa_machine_id ())) {
1487 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1492 /* OK, first let's check if the "runtime" symlink is already
1495 if (!( p
= pa_readlink ( k
))) {
1497 if ( errno
!= ENOENT
) {
1498 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1502 /* Hmm, so the runtime directory didn't exist yet, so let's
1503 * create one in /tmp and symlink that to it */
1505 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1507 /* Mhmm, maybe another process was quicker than us,
1508 * let's check if that was valid */
1509 if ( errno
== EEXIST
)
1518 /* Make sure that this actually makes sense */
1519 if (! pa_is_path_absolute ( p
)) {
1520 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1525 /* Hmm, so this symlink is still around, make sure nobody fools
1528 if ( lstat ( p
, & st
) < 0 ) {
1530 if ( errno
!= ENOENT
) {
1531 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1537 if ( S_ISDIR ( st
. st_mode
) &&
1538 ( st
. st_uid
== getuid ()) &&
1539 (( st
. st_mode
& 0777 ) == 0700 )) {
1545 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1551 /* Hmm, so the link points to some nonexisting or invalid
1552 * dir. Let's replace it by a new link. We first create a
1553 * temporary link and then rename that to allow concurrent
1554 * execution of this function. */
1556 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1558 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1560 if ( errno
!= EEXIST
) {
1561 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1568 /* Hmm, someone lese was quicker then us. Let's give
1569 * him some time to finish, and retry. */
1574 /* OK, we succeeded in creating the temporary symlink, so
1575 * let's rename it */
1576 if ( rename ( t
, k
) < 0 ) {
1577 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1593 /* Try to open a configuration file. If "env" is specified, open the
1594 * value of the specified environment variable. Otherwise look for a
1595 * file "local" in the home directory or a file "global" in global
1596 * file system. If "result" is non-NULL, a pointer to a newly
1597 * allocated buffer containing the used configuration file is
1599 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1604 if (! getenv ( PULSE_ROOTENV
))
1608 if ( env
&& ( fn
= getenv ( env
))) {
1612 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1613 /* FIXME: Needs to set errno! */
1618 if (( f
= fopen ( fn
, "r" ))) {
1620 * result
= pa_xstrdup ( fn
);
1625 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1635 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1636 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1637 else if (( h
= pa_get_home_dir_malloc ())) {
1638 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1644 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1645 /* FIXME: Needs to set errno! */
1652 if (( f
= fopen ( fn
, "r" ))) {
1654 * result
= pa_xstrdup ( fn
);
1660 if ( errno
!= ENOENT
) {
1661 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1673 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1674 /* FIXME: Needs to set errno! */
1679 if (( f
= fopen ( global
, "r" ))) {
1682 * result
= pa_xstrdup ( global
);
1692 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1697 if (! getenv ( PULSE_ROOTENV
))
1701 if ( env
&& ( fn
= getenv ( env
))) {
1704 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1705 /* FIXME: Needs to set errno! */
1710 if ( access ( fn
, R_OK
) == 0 )
1711 return pa_xstrdup ( fn
);
1713 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1722 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1723 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1724 else if (( h
= pa_get_home_dir_malloc ())) {
1725 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1731 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1732 /* FIXME: Needs to set errno! */
1739 if ( access ( fn
, R_OK
) == 0 ) {
1740 char * r
= pa_xstrdup ( fn
);
1745 if ( errno
!= ENOENT
) {
1746 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1756 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1757 /* FIXME: Needs to set errno! */
1762 if ( access ( global
, R_OK
) == 0 )
1763 return pa_xstrdup ( global
);
1771 /* Format the specified data as a hexademical string */
1772 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1773 size_t i
= 0 , j
= 0 ;
1774 const char hex
[] = "0123456789abcdef" ;
1778 pa_assert ( slength
> 0 );
1780 while ( i
< dlength
&& j
+ 3 <= slength
) {
1781 s
[ j
++] = hex
[* d
>> 4 ];
1782 s
[ j
++] = hex
[* d
& 0xF ];
1788 s
[ j
< slength
? j
: slength
] = 0 ;
1792 /* Convert a hexadecimal digit to a number or -1 if invalid */
1793 static int hexc ( char c
) {
1794 if ( c
>= '0' && c
<= '9' )
1797 if ( c
>= 'A' && c
<= 'F' )
1798 return c
- 'A' + 10 ;
1800 if ( c
>= 'a' && c
<= 'f' )
1801 return c
- 'a' + 10 ;
1807 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1808 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1814 while ( j
< dlength
&& * p
) {
1817 if (( b
= hexc (*( p
++))) < 0 )
1820 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1825 if (( b
= hexc (*( p
++))) < 0 )
1828 d
[ j
] |= ( uint8_t ) b
;
1835 /* Returns nonzero when *s starts with *pfx */
1836 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1844 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1847 /* Returns nonzero when *s ends with *sfx */
1848 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1857 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1860 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1866 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1870 char * pa_make_path_absolute ( const char * p
) {
1876 if ( pa_is_path_absolute ( p
))
1877 return pa_xstrdup ( p
);
1879 if (!( cwd
= pa_getcwd ()))
1880 return pa_xstrdup ( p
);
1882 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1887 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1888 * if fn is non-null and starts with / return fn
1889 * otherwise append fn to the run time path and return it */
1890 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1893 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1898 if ( pa_is_path_absolute ( fn
))
1899 return pa_xstrdup ( fn
);
1907 if (!( mid
= pa_machine_id ())) {
1912 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1915 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1923 char * pa_runtime_path ( const char * fn
) {
1924 return get_path ( fn
, FALSE
, TRUE
);
1927 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1928 return get_path ( fn
, appendmid
, FALSE
);
1931 /* Convert the string s to a signed integer in *ret_i */
1932 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1940 l
= strtol ( s
, & x
, 0 );
1942 if (! x
|| * x
|| errno
) {
1948 if (( int32_t ) l
!= l
) {
1953 * ret_i
= ( int32_t ) l
;
1958 /* Convert the string s to an unsigned integer in *ret_u */
1959 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1967 l
= strtoul ( s
, & x
, 0 );
1969 if (! x
|| * x
|| errno
) {
1975 if (( uint32_t ) l
!= l
) {
1980 * ret_u
= ( uint32_t ) l
;
1985 #ifdef HAVE_STRTOF_L
1986 static locale_t c_locale
= NULL
;
1988 static void c_locale_destroy ( void ) {
1989 freelocale ( c_locale
);
1993 int pa_atod ( const char * s
, double * ret_d
) {
2000 /* This should be locale independent */
2002 #ifdef HAVE_STRTOF_L
2006 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2007 atexit ( c_locale_destroy
);
2013 f
= strtod_l ( s
, & x
, c_locale
);
2021 if (! x
|| * x
|| errno
) {
2032 /* Same as snprintf, but guarantees NUL-termination on every platform */
2033 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2038 pa_assert ( size
> 0 );
2041 va_start ( ap
, format
);
2042 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2048 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2049 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2053 pa_assert ( size
> 0 );
2056 ret
= vsnprintf ( str
, size
, format
, ap
);
2063 if (( size_t ) ret
> size
- 1 )
2066 return ( size_t ) ret
;
2069 /* Truncate the specified string, but guarantee that the string
2070 * returned still validates as UTF8 */
2071 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2073 pa_assert ( pa_utf8_valid ( c
));
2080 while ( l
> 0 && ! pa_utf8_valid ( c
))
2086 char * pa_getcwd ( void ) {
2090 char * p
= pa_xmalloc ( l
);
2094 if ( errno
!= ERANGE
)
2102 void * pa_will_need ( const void * p
, size_t l
) {
2103 #ifdef RLIMIT_MEMLOCK
2114 a
= PA_PAGE_ALIGN_PTR ( p
);
2115 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2117 #ifdef HAVE_POSIX_MADVISE
2118 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2119 pa_log_debug ( "posix_madvise() worked fine!" );
2124 /* Most likely the memory was not mmap()ed from a file and thus
2125 * madvise() didn't work, so let's misuse mlock() do page this
2126 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2127 * inviting, the man page of mlock() tells us: "All pages that
2128 * contain a part of the specified address range are guaranteed to
2129 * be resident in RAM when the call returns successfully." */
2131 #ifdef RLIMIT_MEMLOCK
2132 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2134 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2135 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
));
2140 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2142 bs
= PA_PAGE_SIZE
* 4 ;
2145 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2148 while ( size
> 0 && bs
> 0 ) {
2153 if ( mlock ( a
, bs
) < 0 ) {
2154 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2158 pa_assert_se ( munlock ( a
, bs
) == 0 );
2160 a
= ( const uint8_t *) a
+ bs
;
2166 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2168 pa_log_debug ( "mlock() worked fine!" );
2173 void pa_close_pipe ( int fds
[ 2 ]) {
2177 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2180 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2182 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2185 char * pa_readlink ( const char * p
) {
2194 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2199 if (( size_t ) n
< l
- 1 ) {
2209 int pa_close_all ( int except_fd
, ...) {
2214 va_start ( ap
, except_fd
);
2217 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2222 p
= pa_xnew ( int , n
+ 1 );
2224 va_start ( ap
, except_fd
);
2227 if ( except_fd
>= 0 ) {
2231 while (( fd
= va_arg ( ap
, int )) >= 0 )
2238 r
= pa_close_allv ( p
);
2244 int pa_close_allv ( const int except_fds
[]) {
2252 if (( d
= opendir ( "/proc/self/fd" ))) {
2256 while (( de
= readdir ( d
))) {
2262 if ( de
-> d_name
[ 0 ] == '.' )
2266 l
= strtol ( de
-> d_name
, & e
, 10 );
2267 if ( errno
!= 0 || ! e
|| * e
) {
2275 if (( long ) fd
!= l
) {
2288 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2289 if ( except_fds
[ i
] == fd
) {
2297 if ( pa_close ( fd
) < 0 ) {
2298 saved_errno
= errno
;
2300 errno
= saved_errno
;
2312 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2313 maxfd
= ( int ) rl
. rlim_max
;
2315 maxfd
= sysconf ( _SC_OPEN_MAX
);
2317 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2322 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2323 if ( except_fds
[ i
] == fd
) {
2331 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2338 int pa_unblock_sigs ( int except
, ...) {
2343 va_start ( ap
, except
);
2346 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2351 p
= pa_xnew ( int , n
+ 1 );
2353 va_start ( ap
, except
);
2360 while (( sig
= va_arg ( ap
, int )) >= 0 )
2367 r
= pa_unblock_sigsv ( p
);
2373 int pa_unblock_sigsv ( const int except
[]) {
2377 if ( sigemptyset (& ss
) < 0 )
2380 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2381 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2384 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2387 int pa_reset_sigs ( int except
, ...) {
2392 va_start ( ap
, except
);
2395 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2400 p
= pa_xnew ( int , n
+ 1 );
2402 va_start ( ap
, except
);
2409 while (( sig
= va_arg ( ap
, int )) >= 0 )
2416 r
= pa_reset_sigsv ( p
);
2422 int pa_reset_sigsv ( const int except
[]) {
2425 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2426 pa_bool_t reset
= TRUE
;
2437 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2438 if ( sig
== except
[ i
]) {
2447 struct sigaction sa
;
2449 memset (& sa
, 0 , sizeof ( sa
));
2450 sa
. sa_handler
= SIG_DFL
;
2452 /* On Linux the first two RT signals are reserved by
2453 * glibc, and sigaction() will return EINVAL for them. */
2454 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2455 if ( errno
!= EINVAL
)
2463 void pa_set_env ( const char * key
, const char * value
) {
2467 /* This is not thread-safe */
2469 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2472 void pa_set_env_and_record ( const char * key
, const char * value
) {
2476 /* This is not thread-safe */
2478 pa_set_env ( key
, value
);
2479 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2482 void pa_unset_env_recorded ( void ) {
2484 /* This is not thread-safe */
2489 recorded_env
= pa_strlist_pop ( recorded_env
, & s
);
2499 pa_bool_t
pa_in_system_mode ( void ) {
2502 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2508 char * pa_get_user_name_malloc ( void ) {
2512 #ifdef _SC_LOGIN_NAME_MAX
2513 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2519 u
= pa_xnew ( char , k
+ 1 );
2521 if (!( pa_get_user_name ( u
, k
))) {
2529 char * pa_get_host_name_malloc ( void ) {
2538 if (! pa_get_host_name ( c
, l
)) {
2540 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2543 } else if ( strlen ( c
) < l
- 1 ) {
2551 u
= pa_utf8_filter ( c
);
2556 /* Hmm, the hostname is as long the space we offered the
2557 * function, we cannot know if it fully fit in, so let's play
2558 * safe and retry. */
2567 char * pa_machine_id ( void ) {
2571 /* The returned value is supposed be some kind of ascii identifier
2572 * that is unique and stable across reboots. */
2574 /* First we try the D-Bus UUID, which is the best option we have,
2575 * since it fits perfectly our needs and is not as volatile as the
2576 * hostname which might be set from dhcp. */
2578 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2579 char ln
[ 34 ] = "" , * r
;
2581 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2587 return pa_utf8_filter ( ln
);
2590 if (( h
= pa_get_host_name_malloc ()))
2593 /* If no hostname was set we use the POSIX hostid. It's usually
2594 * the IPv4 address. Might not be that stable. */
2595 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2598 char * pa_session_id ( void ) {
2601 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2604 return pa_utf8_filter ( e
);
2607 char * pa_uname_string ( void ) {
2610 pa_assert_se ( uname (& u
) >= 0 );
2612 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2615 #ifdef HAVE_VALGRIND_MEMCHECK_H
2616 pa_bool_t
pa_in_valgrind ( void ) {
2619 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2620 * here instead of really checking whether we run in valgrind or
2624 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2630 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2641 void pa_reduce ( unsigned * num
, unsigned * den
) {
2643 unsigned gcd
= pa_gcd (* num
, * den
);
2651 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2654 unsigned pa_ncpus ( void ) {
2657 #ifdef _SC_NPROCESSORS_CONF
2658 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2663 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2666 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2675 sb
= pa_strbuf_new ();
2680 if (!( p
= strstr ( s
, a
)))
2683 pa_strbuf_putsn ( sb
, s
, p
- s
);
2684 pa_strbuf_puts ( sb
, b
);
2688 pa_strbuf_puts ( sb
, s
);
2690 return pa_strbuf_tostring_free ( sb
);
2693 char * pa_unescape ( char * p
) {
2695 pa_bool_t escaped
= FALSE
;
2697 for ( s
= p
, d
= p
; * s
; s
++) {
2698 if (! escaped
&& * s
== ' \\ ' ) {
2712 char * pa_realpath ( const char * path
) {
2716 /* We want only abolsute paths */
2717 if ( path
[ 0 ] != '/' ) {
2722 #if defined(__GLIBC__) || defined(__APPLE__)
2726 if (!( r
= realpath ( path
, NULL
)))
2729 /* We copy this here in case our pa_xmalloc() is not
2730 * implemented on top of libc malloc() */
2734 #elif defined(PATH_MAX)
2737 path_buf
= pa_xmalloc ( PATH_MAX
);
2739 if (!( t
= realpath ( path
, path_buf
))) {
2745 #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."
2751 void pa_disable_sigpipe ( void ) {
2754 struct sigaction sa
;
2758 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2759 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2763 sa
. sa_handler
= SIG_IGN
;
2765 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2766 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2772 void pa_xfreev ( void ** a
) {
2778 for ( p
= a
; * p
; p
++)
2784 char ** pa_split_spaces_strv ( const char * s
) {
2786 unsigned i
= 0 , n
= 8 ;
2787 const char * state
= NULL
;
2789 t
= pa_xnew ( char *, n
);
2790 while (( e
= pa_split_spaces ( s
, & state
))) {
2795 t
= pa_xrenew ( char *, t
, n
);
2808 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2811 if ( pa_is_path_absolute ( path
))
2812 return pa_xstrdup ( path
);
2814 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2817 size_t pa_pipe_buf ( int fd
) {
2822 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2833 void pa_reset_personality ( void ) {
2836 if ( personality ( PER_LINUX
) < 0 )
2837 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2842 #if defined(__linux__) && !defined(__OPTIMIZE__)
2844 pa_bool_t
pa_run_from_build_tree ( void ) {
2846 pa_bool_t b
= FALSE
;
2848 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2851 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2852 b
= pa_startswith ( rp
, PA_BUILDDIR
);