]>
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 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
616 dbus_connection_unref ( bus
);
619 pa_log_debug ( "RealtimeKit worked." );
631 /* Make the current thread a realtime thread, and acquire the highest
632 * rtprio we can get that is less or equal the specified parameter. If
633 * the thread is already realtime, don't do anything. */
634 int pa_make_realtime ( int rtprio
) {
636 #ifdef _POSIX_PRIORITY_SCHEDULING
639 if ( set_scheduler ( rtprio
) >= 0 ) {
640 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
644 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
645 if ( set_scheduler ( p
)) {
646 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
650 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
659 static int set_nice ( int nice_level
) {
665 dbus_error_init (& error
);
668 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
669 pa_log_debug ( "setpriority() worked." );
674 /* Try to talk to RealtimeKit */
676 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
677 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
678 dbus_error_free (& error
);
683 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
684 dbus_connection_unref ( bus
);
687 pa_log_debug ( "RealtimeKit worked." );
697 /* Raise the priority of the current process as much as possible that
698 * is <= the specified nice level..*/
699 int pa_raise_priority ( int nice_level
) {
701 #ifdef HAVE_SYS_RESOURCE_H
704 if ( set_nice ( nice_level
) >= 0 ) {
705 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
709 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
710 if ( set_nice ( n
) > 0 ) {
711 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
715 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
720 if ( nice_level
< 0 ) {
721 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
722 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
727 pa_log_info ( "Successfully gained high priority class." );
734 /* Reset the priority to normal, inverting the changes made by
735 * pa_raise_priority() and pa_make_realtime()*/
736 void pa_reset_priority ( void ) {
737 #ifdef HAVE_SYS_RESOURCE_H
738 struct sched_param sp
;
740 setpriority ( PRIO_PROCESS
, 0 , 0 );
743 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
747 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
751 int pa_match ( const char * expr
, const char * v
) {
756 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
761 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
763 else if ( k
== REG_NOMATCH
)
776 /* Try to parse a boolean string value.*/
777 int pa_parse_boolean ( const char * v
) {
782 /* First we check language independant */
783 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
785 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
788 /* And then we check language dependant */
789 if (( expr
= nl_langinfo ( YESEXPR
)))
791 if (( r
= pa_match ( expr
, v
)) > 0 )
794 if (( expr
= nl_langinfo ( NOEXPR
)))
796 if (( r
= pa_match ( expr
, v
)) > 0 )
803 /* Split the specified string wherever one of the strings in delimiter
804 * occurs. Each time it is called returns a newly allocated string
805 * with pa_xmalloc(). The variable state points to, should be
806 * initiallized to NULL before the first call. */
807 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
808 const char * current
= * state
? * state
: c
;
814 l
= strcspn ( current
, delimiter
);
820 return pa_xstrndup ( current
, l
);
823 /* What is interpreted as whitespace? */
824 #define WHITESPACE " \t\n "
826 /* Split a string into words. Otherwise similar to pa_split(). */
827 char * pa_split_spaces ( const char * c
, const char ** state
) {
828 const char * current
= * state
? * state
: c
;
831 if (!* current
|| * c
== 0 )
834 current
+= strspn ( current
, WHITESPACE
);
835 l
= strcspn ( current
, WHITESPACE
);
839 return pa_xstrndup ( current
, l
);
842 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
844 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
845 const char * pa_sig2str ( int sig
) {
858 char buf
[ SIG2STR_MAX
];
860 if ( sig2str ( sig
, buf
) == 0 ) {
861 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
862 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
863 PA_STATIC_TLS_SET ( signame
, t
);
871 case SIGHUP
: return "SIGHUP" ;
873 case SIGINT
: return "SIGINT" ;
875 case SIGQUIT
: return "SIGQUIT" ;
877 case SIGILL
: return "SIGULL" ;
879 case SIGTRAP
: return "SIGTRAP" ;
881 case SIGABRT
: return "SIGABRT" ;
883 case SIGBUS
: return "SIGBUS" ;
885 case SIGFPE
: return "SIGFPE" ;
887 case SIGKILL
: return "SIGKILL" ;
890 case SIGUSR1
: return "SIGUSR1" ;
892 case SIGSEGV
: return "SIGSEGV" ;
894 case SIGUSR2
: return "SIGUSR2" ;
897 case SIGPIPE
: return "SIGPIPE" ;
900 case SIGALRM
: return "SIGALRM" ;
902 case SIGTERM
: return "SIGTERM" ;
904 case SIGSTKFLT
: return "SIGSTKFLT" ;
907 case SIGCHLD
: return "SIGCHLD" ;
910 case SIGCONT
: return "SIGCONT" ;
913 case SIGSTOP
: return "SIGSTOP" ;
916 case SIGTSTP
: return "SIGTSTP" ;
919 case SIGTTIN
: return "SIGTTIN" ;
922 case SIGTTOU
: return "SIGTTOU" ;
925 case SIGURG
: return "SIGURG" ;
928 case SIGXCPU
: return "SIGXCPU" ;
931 case SIGXFSZ
: return "SIGXFSZ" ;
934 case SIGVTALRM
: return "SIGVTALRM" ;
937 case SIGPROF
: return "SIGPROF" ;
940 case SIGWINCH
: return "SIGWINCH" ;
943 case SIGIO
: return "SIGIO" ;
946 case SIGPWR
: return "SIGPWR" ;
949 case SIGSYS
: return "SIGSYS" ;
954 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
955 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
956 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
957 PA_STATIC_TLS_SET ( signame
, t
);
966 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
967 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
968 PA_STATIC_TLS_SET ( signame
, t
);
974 /* Check whether the specified GID and the group name match */
975 static int is_group ( gid_t gid
, const char * name
) {
976 struct group
* group
= NULL
;
980 if (!( group
= pa_getgrgid_malloc ( gid
)))
985 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
990 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
993 pa_getgrgid_free ( group
);
998 /* Check the current user is member of the specified group */
999 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1000 GETGROUPS_T
* gids
, tgid
;
1001 long n
= sysconf ( _SC_NGROUPS_MAX
);
1006 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1008 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1009 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1013 for ( i
= 0 ; i
< n
; i
++) {
1015 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1024 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1040 /* Check whether the specifc user id is a member of the specified group */
1041 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1042 struct group
* group
= NULL
;
1047 if (!( group
= pa_getgrnam_malloc ( name
)))
1055 for ( i
= group
-> gr_mem
; * i
; i
++) {
1056 struct passwd
* pw
= NULL
;
1059 if (!( pw
= pa_getpwnam_malloc (* i
)))
1062 if ( pw
-> pw_uid
== uid
)
1065 pa_getpwnam_free ( pw
);
1072 pa_getgrnam_free ( group
);
1077 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1078 gid_t
pa_get_gid_of_group ( const char * name
) {
1079 gid_t ret
= ( gid_t
) - 1 ;
1080 struct group
* gr
= NULL
;
1083 if (!( gr
= pa_getgrnam_malloc ( name
)))
1093 pa_getgrnam_free ( gr
);
1097 int pa_check_in_group ( gid_t g
) {
1098 gid_t gids
[ NGROUPS_MAX
];
1101 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1111 #else /* HAVE_GRP_H */
1113 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1119 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1124 gid_t
pa_get_gid_of_group ( const char * name
) {
1129 int pa_check_in_group ( gid_t g
) {
1136 /* Lock or unlock a file entirely.
1137 (advisory on UNIX, mandatory on Windows) */
1138 int pa_lock_fd ( int fd
, int b
) {
1140 struct flock f_lock
;
1142 /* Try a R/W lock first */
1144 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1145 f_lock
. l_whence
= SEEK_SET
;
1149 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1152 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1153 if ( b
&& errno
== EBADF
) {
1154 f_lock
. l_type
= F_RDLCK
;
1155 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1159 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1163 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1165 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1167 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1170 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1172 /* FIXME: Needs to set errno! */
1178 /* Remove trailing newlines from a string */
1179 char * pa_strip_nl ( char * s
) {
1182 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1186 /* Create a temporary lock file and lock it. */
1187 int pa_lock_lockfile ( const char * fn
) {
1194 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1201 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1202 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1206 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1207 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1211 if ( fstat ( fd
, & st
) < 0 ) {
1212 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1216 /* Check whether the file has been removed meanwhile. When yes,
1217 * restart this loop, otherwise, we're done */
1218 if ( st
. st_nlink
>= 1 )
1221 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1222 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1226 if ( pa_close ( fd
) < 0 ) {
1227 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1240 int saved_errno
= errno
;
1242 errno
= saved_errno
;
1248 /* Unlock a temporary lcok file */
1249 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1254 if ( unlink ( fn
) < 0 ) {
1255 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1260 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1261 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1265 if ( pa_close ( fd
) < 0 ) {
1266 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1273 static char * get_pulse_home ( void ) {
1278 if (!( h
= pa_get_home_dir_malloc ())) {
1279 pa_log_error ( "Failed to get home directory." );
1283 if ( stat ( h
, & st
) < 0 ) {
1284 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1288 if ( st
. st_uid
!= getuid ()) {
1289 pa_log_error ( "Home directory %s not ours." , h
);
1294 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1302 char * pa_get_state_dir ( void ) {
1305 /* The state directory shall contain dynamic data that should be
1306 * kept across reboots, and is private to this user */
1308 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1309 if (!( d
= get_pulse_home ()))
1312 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1313 * dir then this will break. */
1315 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1316 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1324 char * pa_get_home_dir_malloc ( void ) {
1326 size_t allocated
= 128 ;
1329 homedir
= pa_xmalloc ( allocated
);
1331 if (! pa_get_home_dir ( homedir
, allocated
)) {
1336 if ( strlen ( homedir
) < allocated
- 1 )
1346 char * pa_get_binary_name_malloc ( void ) {
1348 size_t allocated
= 128 ;
1351 t
= pa_xmalloc ( allocated
);
1353 if (! pa_get_binary_name ( t
, allocated
)) {
1358 if ( strlen ( t
) < allocated
- 1 )
1368 static char * make_random_dir ( mode_t m
) {
1369 static const char table
[] =
1370 "abcdefghijklmnopqrstuvwxyz"
1371 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1378 if (!( tmpdir
= getenv ( "TMPDIR" )))
1379 if (!( tmpdir
= getenv ( "TMP" )))
1380 if (!( tmpdir
= getenv ( "TEMP" )))
1381 tmpdir
= getenv ( "TEMPDIR" );
1383 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1386 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1387 pathlen
= strlen ( fn
);
1395 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1396 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1398 u
= umask ((~ m
) & 0777 );
1401 saved_errno
= errno
;
1403 errno
= saved_errno
;
1408 if ( errno
!= EEXIST
) {
1409 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1416 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1419 if (!( p
= make_random_dir ( m
)))
1422 if ( symlink ( p
, k
) < 0 ) {
1423 int saved_errno
= errno
;
1425 if ( errno
!= EEXIST
)
1426 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1431 errno
= saved_errno
;
1439 char * pa_get_runtime_dir ( void ) {
1440 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1444 /* The runtime directory shall contain dynamic data that needs NOT
1445 * to be kept accross reboots and is usuallly private to the user,
1446 * except in system mode, where it might be accessible by other
1447 * users, too. Since we need POSIX locking and UNIX sockets in
1448 * this directory, we link it to a random subdir in /tmp, if it
1449 * was not explicitly configured. */
1451 m
= pa_in_system_mode () ? 0755U : 0700U ;
1453 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1455 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1456 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1460 return pa_xstrdup ( d
);
1463 if (!( d
= get_pulse_home ()))
1466 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1467 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1472 if (!( mid
= pa_machine_id ())) {
1477 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1482 /* OK, first let's check if the "runtime" symlink is already
1485 if (!( p
= pa_readlink ( k
))) {
1487 if ( errno
!= ENOENT
) {
1488 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1492 /* Hmm, so the runtime directory didn't exist yet, so let's
1493 * create one in /tmp and symlink that to it */
1495 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1497 /* Mhmm, maybe another process was quicker than us,
1498 * let's check if that was valid */
1499 if ( errno
== EEXIST
)
1508 /* Make sure that this actually makes sense */
1509 if (! pa_is_path_absolute ( p
)) {
1510 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1515 /* Hmm, so this symlink is still around, make sure nobody fools
1518 if ( lstat ( p
, & st
) < 0 ) {
1520 if ( errno
!= ENOENT
) {
1521 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1527 if ( S_ISDIR ( st
. st_mode
) &&
1528 ( st
. st_uid
== getuid ()) &&
1529 (( st
. st_mode
& 0777 ) == 0700 )) {
1535 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1541 /* Hmm, so the link points to some nonexisting or invalid
1542 * dir. Let's replace it by a new link. We first create a
1543 * temporary link and then rename that to allow concurrent
1544 * execution of this function. */
1546 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1548 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1550 if ( errno
!= EEXIST
) {
1551 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1558 /* Hmm, someone lese was quicker then us. Let's give
1559 * him some time to finish, and retry. */
1564 /* OK, we succeeded in creating the temporary symlink, so
1565 * let's rename it */
1566 if ( rename ( t
, k
) < 0 ) {
1567 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1583 /* Try to open a configuration file. If "env" is specified, open the
1584 * value of the specified environment variable. Otherwise look for a
1585 * file "local" in the home directory or a file "global" in global
1586 * file system. If "result" is non-NULL, a pointer to a newly
1587 * allocated buffer containing the used configuration file is
1589 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1594 if (! getenv ( PULSE_ROOTENV
))
1598 if ( env
&& ( fn
= getenv ( env
))) {
1602 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1603 /* FIXME: Needs to set errno! */
1608 if (( f
= fopen ( fn
, "r" ))) {
1610 * result
= pa_xstrdup ( fn
);
1615 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1625 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1626 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1627 else if (( h
= pa_get_home_dir_malloc ())) {
1628 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1634 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1635 /* FIXME: Needs to set errno! */
1642 if (( f
= fopen ( fn
, "r" ))) {
1644 * result
= pa_xstrdup ( fn
);
1650 if ( errno
!= ENOENT
) {
1651 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1663 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1664 /* FIXME: Needs to set errno! */
1669 if (( f
= fopen ( global
, "r" ))) {
1672 * result
= pa_xstrdup ( global
);
1682 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1687 if (! getenv ( PULSE_ROOTENV
))
1691 if ( env
&& ( fn
= getenv ( env
))) {
1694 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1695 /* FIXME: Needs to set errno! */
1700 if ( access ( fn
, R_OK
) == 0 )
1701 return pa_xstrdup ( fn
);
1703 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1712 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1713 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1714 else if (( h
= pa_get_home_dir_malloc ())) {
1715 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1721 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1722 /* FIXME: Needs to set errno! */
1729 if ( access ( fn
, R_OK
) == 0 ) {
1730 char * r
= pa_xstrdup ( fn
);
1735 if ( errno
!= ENOENT
) {
1736 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1746 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1747 /* FIXME: Needs to set errno! */
1752 if ( access ( global
, R_OK
) == 0 )
1753 return pa_xstrdup ( global
);
1761 /* Format the specified data as a hexademical string */
1762 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1763 size_t i
= 0 , j
= 0 ;
1764 const char hex
[] = "0123456789abcdef" ;
1768 pa_assert ( slength
> 0 );
1770 while ( i
< dlength
&& j
+ 3 <= slength
) {
1771 s
[ j
++] = hex
[* d
>> 4 ];
1772 s
[ j
++] = hex
[* d
& 0xF ];
1778 s
[ j
< slength
? j
: slength
] = 0 ;
1782 /* Convert a hexadecimal digit to a number or -1 if invalid */
1783 static int hexc ( char c
) {
1784 if ( c
>= '0' && c
<= '9' )
1787 if ( c
>= 'A' && c
<= 'F' )
1788 return c
- 'A' + 10 ;
1790 if ( c
>= 'a' && c
<= 'f' )
1791 return c
- 'a' + 10 ;
1797 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1798 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1804 while ( j
< dlength
&& * p
) {
1807 if (( b
= hexc (*( p
++))) < 0 )
1810 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1815 if (( b
= hexc (*( p
++))) < 0 )
1818 d
[ j
] |= ( uint8_t ) b
;
1825 /* Returns nonzero when *s starts with *pfx */
1826 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1834 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1837 /* Returns nonzero when *s ends with *sfx */
1838 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1847 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1850 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1856 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1860 char * pa_make_path_absolute ( const char * p
) {
1866 if ( pa_is_path_absolute ( p
))
1867 return pa_xstrdup ( p
);
1869 if (!( cwd
= pa_getcwd ()))
1870 return pa_xstrdup ( p
);
1872 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1877 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1878 * if fn is non-null and starts with / return fn
1879 * otherwise append fn to the run time path and return it */
1880 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1883 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1888 if ( pa_is_path_absolute ( fn
))
1889 return pa_xstrdup ( fn
);
1897 if (!( mid
= pa_machine_id ())) {
1902 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1905 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1913 char * pa_runtime_path ( const char * fn
) {
1914 return get_path ( fn
, FALSE
, TRUE
);
1917 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1918 return get_path ( fn
, appendmid
, FALSE
);
1921 /* Convert the string s to a signed integer in *ret_i */
1922 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1930 l
= strtol ( s
, & x
, 0 );
1932 if (! x
|| * x
|| errno
) {
1938 if (( int32_t ) l
!= l
) {
1943 * ret_i
= ( int32_t ) l
;
1948 /* Convert the string s to an unsigned integer in *ret_u */
1949 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1957 l
= strtoul ( s
, & x
, 0 );
1959 if (! x
|| * x
|| errno
) {
1965 if (( uint32_t ) l
!= l
) {
1970 * ret_u
= ( uint32_t ) l
;
1975 #ifdef HAVE_STRTOF_L
1976 static locale_t c_locale
= NULL
;
1978 static void c_locale_destroy ( void ) {
1979 freelocale ( c_locale
);
1983 int pa_atod ( const char * s
, double * ret_d
) {
1990 /* This should be locale independent */
1992 #ifdef HAVE_STRTOF_L
1996 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1997 atexit ( c_locale_destroy
);
2003 f
= strtod_l ( s
, & x
, c_locale
);
2011 if (! x
|| * x
|| errno
) {
2022 /* Same as snprintf, but guarantees NUL-termination on every platform */
2023 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2028 pa_assert ( size
> 0 );
2031 va_start ( ap
, format
);
2032 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2038 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2039 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2043 pa_assert ( size
> 0 );
2046 ret
= vsnprintf ( str
, size
, format
, ap
);
2053 if (( size_t ) ret
> size
- 1 )
2056 return ( size_t ) ret
;
2059 /* Truncate the specified string, but guarantee that the string
2060 * returned still validates as UTF8 */
2061 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2063 pa_assert ( pa_utf8_valid ( c
));
2070 while ( l
> 0 && ! pa_utf8_valid ( c
))
2076 char * pa_getcwd ( void ) {
2080 char * p
= pa_xmalloc ( l
);
2084 if ( errno
!= ERANGE
)
2092 void * pa_will_need ( const void * p
, size_t l
) {
2093 #ifdef RLIMIT_MEMLOCK
2104 a
= PA_PAGE_ALIGN_PTR ( p
);
2105 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2107 #ifdef HAVE_POSIX_MADVISE
2108 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2109 pa_log_debug ( "posix_madvise() worked fine!" );
2114 /* Most likely the memory was not mmap()ed from a file and thus
2115 * madvise() didn't work, so let's misuse mlock() do page this
2116 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2117 * inviting, the man page of mlock() tells us: "All pages that
2118 * contain a part of the specified address range are guaranteed to
2119 * be resident in RAM when the call returns successfully." */
2121 #ifdef RLIMIT_MEMLOCK
2122 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2124 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2125 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
));
2130 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2132 bs
= PA_PAGE_SIZE
* 4 ;
2135 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2138 while ( size
> 0 && bs
> 0 ) {
2143 if ( mlock ( a
, bs
) < 0 ) {
2144 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2148 pa_assert_se ( munlock ( a
, bs
) == 0 );
2150 a
= ( const uint8_t *) a
+ bs
;
2156 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2158 pa_log_debug ( "mlock() worked fine!" );
2163 void pa_close_pipe ( int fds
[ 2 ]) {
2167 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2170 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2172 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2175 char * pa_readlink ( const char * p
) {
2184 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2189 if (( size_t ) n
< l
- 1 ) {
2199 int pa_close_all ( int except_fd
, ...) {
2204 va_start ( ap
, except_fd
);
2207 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2212 p
= pa_xnew ( int , n
+ 1 );
2214 va_start ( ap
, except_fd
);
2217 if ( except_fd
>= 0 ) {
2221 while (( fd
= va_arg ( ap
, int )) >= 0 )
2228 r
= pa_close_allv ( p
);
2234 int pa_close_allv ( const int except_fds
[]) {
2242 if (( d
= opendir ( "/proc/self/fd" ))) {
2246 while (( de
= readdir ( d
))) {
2252 if ( de
-> d_name
[ 0 ] == '.' )
2256 l
= strtol ( de
-> d_name
, & e
, 10 );
2257 if ( errno
!= 0 || ! e
|| * e
) {
2265 if (( long ) fd
!= l
) {
2278 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2279 if ( except_fds
[ i
] == fd
) {
2287 if ( pa_close ( fd
) < 0 ) {
2288 saved_errno
= errno
;
2290 errno
= saved_errno
;
2302 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2303 maxfd
= ( int ) rl
. rlim_max
;
2305 maxfd
= sysconf ( _SC_OPEN_MAX
);
2307 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2312 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2313 if ( except_fds
[ i
] == fd
) {
2321 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2328 int pa_unblock_sigs ( int except
, ...) {
2333 va_start ( ap
, except
);
2336 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2341 p
= pa_xnew ( int , n
+ 1 );
2343 va_start ( ap
, except
);
2350 while (( sig
= va_arg ( ap
, int )) >= 0 )
2357 r
= pa_unblock_sigsv ( p
);
2363 int pa_unblock_sigsv ( const int except
[]) {
2367 if ( sigemptyset (& ss
) < 0 )
2370 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2371 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2374 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2377 int pa_reset_sigs ( int except
, ...) {
2382 va_start ( ap
, except
);
2385 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2390 p
= pa_xnew ( int , n
+ 1 );
2392 va_start ( ap
, except
);
2399 while (( sig
= va_arg ( ap
, int )) >= 0 )
2406 r
= pa_reset_sigsv ( p
);
2412 int pa_reset_sigsv ( const int except
[]) {
2415 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2416 pa_bool_t reset
= TRUE
;
2427 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2428 if ( sig
== except
[ i
]) {
2437 struct sigaction sa
;
2439 memset (& sa
, 0 , sizeof ( sa
));
2440 sa
. sa_handler
= SIG_DFL
;
2442 /* On Linux the first two RT signals are reserved by
2443 * glibc, and sigaction() will return EINVAL for them. */
2444 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2445 if ( errno
!= EINVAL
)
2453 void pa_set_env ( const char * key
, const char * value
) {
2457 /* This is not thread-safe */
2459 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2462 void pa_set_env_and_record ( const char * key
, const char * value
) {
2466 /* This is not thread-safe */
2468 pa_set_env ( key
, value
);
2469 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2472 void pa_unset_env_recorded ( void ) {
2474 /* This is not thread-safe */
2479 if (!( recorded_env
= pa_strlist_pop ( recorded_env
, & s
)))
2487 pa_bool_t
pa_in_system_mode ( void ) {
2490 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2496 char * pa_get_user_name_malloc ( void ) {
2500 #ifdef _SC_LOGIN_NAME_MAX
2501 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2507 u
= pa_xnew ( char , k
+ 1 );
2509 if (!( pa_get_user_name ( u
, k
))) {
2517 char * pa_get_host_name_malloc ( void ) {
2526 if (! pa_get_host_name ( c
, l
)) {
2528 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2531 } else if ( strlen ( c
) < l
- 1 ) {
2539 u
= pa_utf8_filter ( c
);
2544 /* Hmm, the hostname is as long the space we offered the
2545 * function, we cannot know if it fully fit in, so let's play
2546 * safe and retry. */
2555 char * pa_machine_id ( void ) {
2559 /* The returned value is supposed be some kind of ascii identifier
2560 * that is unique and stable across reboots. */
2562 /* First we try the D-Bus UUID, which is the best option we have,
2563 * since it fits perfectly our needs and is not as volatile as the
2564 * hostname which might be set from dhcp. */
2566 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2567 char ln
[ 34 ] = "" , * r
;
2569 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2575 return pa_utf8_filter ( ln
);
2578 if (( h
= pa_get_host_name_malloc ()))
2581 /* If no hostname was set we use the POSIX hostid. It's usually
2582 * the IPv4 address. Might not be that stable. */
2583 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2586 char * pa_session_id ( void ) {
2589 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2592 return pa_utf8_filter ( e
);
2595 char * pa_uname_string ( void ) {
2598 pa_assert_se ( uname (& u
) >= 0 );
2600 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2603 #ifdef HAVE_VALGRIND_MEMCHECK_H
2604 pa_bool_t
pa_in_valgrind ( void ) {
2607 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2608 * here instead of really checking whether we run in valgrind or
2612 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2618 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2629 void pa_reduce ( unsigned * num
, unsigned * den
) {
2631 unsigned gcd
= pa_gcd (* num
, * den
);
2639 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2642 unsigned pa_ncpus ( void ) {
2645 #ifdef _SC_NPROCESSORS_CONF
2646 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2651 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2654 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2663 sb
= pa_strbuf_new ();
2668 if (!( p
= strstr ( s
, a
)))
2671 pa_strbuf_putsn ( sb
, s
, p
- s
);
2672 pa_strbuf_puts ( sb
, b
);
2676 pa_strbuf_puts ( sb
, s
);
2678 return pa_strbuf_tostring_free ( sb
);
2681 char * pa_unescape ( char * p
) {
2683 pa_bool_t escaped
= FALSE
;
2685 for ( s
= p
, d
= p
; * s
; s
++) {
2686 if (! escaped
&& * s
== ' \\ ' ) {
2700 char * pa_realpath ( const char * path
) {
2704 /* We want only abolsute paths */
2705 if ( path
[ 0 ] != '/' ) {
2710 #if defined(__GLIBC__) || defined(__APPLE__)
2714 if (!( r
= realpath ( path
, NULL
)))
2717 /* We copy this here in case our pa_xmalloc() is not
2718 * implemented on top of libc malloc() */
2722 #elif defined(PATH_MAX)
2725 path_buf
= pa_xmalloc ( PATH_MAX
);
2727 if (!( t
= realpath ( path
, path_buf
))) {
2733 #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."
2739 void pa_disable_sigpipe ( void ) {
2742 struct sigaction sa
;
2746 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2747 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2751 sa
. sa_handler
= SIG_IGN
;
2753 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2754 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2760 void pa_xfreev ( void ** a
) {
2766 for ( p
= a
; * p
; p
++)
2772 char ** pa_split_spaces_strv ( const char * s
) {
2774 unsigned i
= 0 , n
= 8 ;
2775 const char * state
= NULL
;
2777 t
= pa_xnew ( char *, n
);
2778 while (( e
= pa_split_spaces ( s
, & state
))) {
2783 t
= pa_xrenew ( char *, t
, n
);
2796 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2799 if ( pa_is_path_absolute ( path
))
2800 return pa_xstrdup ( path
);
2802 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2805 size_t pa_pipe_buf ( int fd
) {
2810 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2821 void pa_reset_personality ( void ) {
2824 if ( personality ( PER_LINUX
) < 0 )
2825 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2830 #if defined(__linux__) && !defined(__OPTIMIZE__)
2832 pa_bool_t
pa_run_from_build_tree ( void ) {
2834 pa_bool_t b
= FALSE
;
2836 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2839 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2840 b
= pa_startswith ( rp
, PA_BUILDDIR
);