]>
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>
104 #include <pulse/xmalloc.h>
105 #include <pulse/util.h>
106 #include <pulse/utf8.h>
108 #include <pulsecore/core-error.h>
109 #include <pulsecore/winsock.h>
110 #include <pulsecore/log.h>
111 #include <pulsecore/macro.h>
112 #include <pulsecore/thread.h>
113 #include <pulsecore/strbuf.h>
115 #include "core-util.h"
117 /* Not all platforms have this */
119 #define MSG_NOSIGNAL 0
124 #define PULSE_ROOTENV "PULSE_ROOT"
126 int pa_set_root ( HANDLE handle
) {
127 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
129 strcpy ( library_path
, PULSE_ROOTENV
"=" );
131 /* FIXME: Needs to set errno */
133 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
136 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
140 if ( _putenv ( library_path
) < 0 )
148 /** Make a file descriptor nonblock. Doesn't do any error checking */
149 void pa_make_fd_nonblock ( int fd
) {
155 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
157 if (!( v
& O_NONBLOCK
))
158 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
160 #elif defined(OS_IS_WIN32)
162 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
163 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
164 pa_log_warn ( "Only sockets can be made non-blocking!" );
167 pa_log_warn ( "Non-blocking I/O not supported.!" );
172 /* Set the FD_CLOEXEC flag for a fd */
173 void pa_make_fd_cloexec ( int fd
) {
179 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
181 if (!( v
& FD_CLOEXEC
))
182 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
187 /** Creates a directory securely */
188 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
199 u
= umask ((~ m
) & 0777 );
205 if ( r
< 0 && errno
!= EEXIST
)
209 if ( uid
== ( uid_t
)- 1 )
211 if ( gid
== ( gid_t
)- 1 )
213 ( void ) chown ( dir
, uid
, gid
);
221 if ( lstat ( dir
, & st
) < 0 )
223 if ( stat ( dir
, & st
) < 0 )
228 if (! S_ISDIR ( st
. st_mode
) ||
229 ( st
. st_uid
!= uid
) ||
230 ( st
. st_gid
!= gid
) ||
231 (( st
. st_mode
& 0777 ) != m
)) {
236 pa_log_warn ( "Secure directory creation not supported on Win32." );
249 /* Return a newly allocated sting containing the parent directory of the specified file */
250 char * pa_parent_dir ( const char * fn
) {
251 char * slash
, * dir
= pa_xstrdup ( fn
);
253 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
263 /* Creates a the parent directory of the specified path securely */
264 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
268 if (!( dir
= pa_parent_dir ( fn
)))
271 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
281 /** Platform independent read function. Necessary since not all
282 * systems treat all file descriptors equal. If type is
283 * non-NULL it is used to cache the type of the fd. This is
284 * useful for making sure that only a single syscall is executed per
285 * function call. The variable pointed to should be initialized to 0
287 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
291 if (! type
|| * type
== 0 ) {
294 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
297 if ( WSAGetLastError () != WSAENOTSOCK
) {
298 errno
= WSAGetLastError ();
311 if (( r
= read ( fd
, buf
, count
)) < 0 )
319 /** Similar to pa_read(), but handles writes */
320 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
322 if (! type
|| * type
== 0 ) {
326 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) < 0 ) {
338 if ( WSAGetLastError () != WSAENOTSOCK
) {
339 errno
= WSAGetLastError ();
343 if ( errno
!= ENOTSOCK
)
354 if (( r
= write ( fd
, buf
, count
)) < 0 )
362 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
363 * unless EOF is reached or an error occurred */
364 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
380 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
387 data
= ( uint8_t *) data
+ r
;
394 /** Similar to pa_loop_read(), but wraps write() */
395 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
411 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
418 data
= ( const uint8_t *) data
+ r
;
425 /** Platform independent read function. Necessary since not all
426 * systems treat all file descriptors equal. */
427 int pa_close ( int fd
) {
432 if (( ret
= closesocket ( fd
)) == 0 )
435 if ( WSAGetLastError () != WSAENOTSOCK
) {
436 errno
= WSAGetLastError ();
444 if (( r
= close ( fd
)) < 0 )
452 /* Print a warning messages in case that the given signal is not
453 * blocked or trapped */
454 void pa_check_signal_is_blocked ( int sig
) {
455 #ifdef HAVE_SIGACTION
459 /* If POSIX threads are supported use thread-aware
460 * pthread_sigmask() function, to check if the signal is
461 * blocked. Otherwise fall back to sigprocmask() */
464 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
466 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
467 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
474 if ( sigismember (& set
, sig
))
477 /* Check whether the signal is trapped */
479 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
480 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
484 if ( sa
. sa_handler
!= SIG_DFL
)
487 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
488 #else /* HAVE_SIGACTION */
489 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
493 /* The following function is based on an example from the GNU libc
494 * documentation. This function is similar to GNU's asprintf(). */
495 char * pa_sprintf_malloc ( const char * format
, ...) {
505 c
= pa_xrealloc ( c
, size
);
507 va_start ( ap
, format
);
508 r
= vsnprintf ( c
, size
, format
, ap
);
513 if ( r
> - 1 && ( size_t ) r
< size
)
516 if ( r
> - 1 ) /* glibc 2.1 */
523 /* Same as the previous function, but use a va_list instead of an
525 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
535 c
= pa_xrealloc ( c
, size
);
538 r
= vsnprintf ( c
, size
, format
, aq
);
543 if ( r
> - 1 && ( size_t ) r
< size
)
546 if ( r
> - 1 ) /* glibc 2.1 */
553 /* Similar to OpenBSD's strlcpy() function */
554 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
564 static int set_scheduler ( int rtprio
) {
565 struct sched_param sp
;
571 dbus_error_init (& error
);
575 sp
. sched_priority
= rtprio
;
577 #ifdef SCHED_RESET_ON_FORK
578 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
| SCHED_RESET_ON_FORK
, & sp
)) == 0 ) {
579 pa_log_debug ( "SCHED_RR|SCHED_RESET_ON_FORK worked." );
584 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_RR
, & sp
)) == 0 ) {
585 pa_log_debug ( "SCHED_RR worked." );
590 /* Try to talk to RealtimeKit */
592 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
593 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
594 dbus_error_free (& error
);
599 r
= rtkit_make_realtime ( bus
, 0 , rtprio
);
600 dbus_connection_unref ( bus
);
603 pa_log_debug ( "RealtimeKit worked." );
615 /* Make the current thread a realtime thread, and acquire the highest
616 * rtprio we can get that is less or equal the specified parameter. If
617 * the thread is already realtime, don't do anything. */
618 int pa_make_realtime ( int rtprio
) {
620 #ifdef _POSIX_PRIORITY_SCHEDULING
623 if ( set_scheduler ( rtprio
) >= 0 ) {
624 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i." , rtprio
);
628 for ( p
= rtprio
- 1 ; p
>= 1 ; p
--)
629 if ( set_scheduler ( p
)) {
630 pa_log_info ( "Successfully enabled SCHED_RR scheduling for thread, with priority %i, which is lower than the requested %i." , p
, rtprio
);
634 pa_log_info ( "Failed to acquire real-time scheduling: %s" , pa_cstrerror ( errno
));
643 static int set_nice ( int nice_level
) {
649 dbus_error_init (& error
);
652 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) >= 0 ) {
653 pa_log_debug ( "setpriority() worked." );
658 /* Try to talk to RealtimeKit */
660 if (!( bus
= dbus_bus_get ( DBUS_BUS_SYSTEM
, & error
))) {
661 pa_log ( "Failed to connect to system bus: %s \n " , error
. message
);
662 dbus_error_free (& error
);
667 r
= rtkit_make_high_priority ( bus
, 0 , nice_level
);
668 dbus_connection_unref ( bus
);
671 pa_log_debug ( "RealtimeKit worked." );
681 /* Raise the priority of the current process as much as possible that
682 * is <= the specified nice level..*/
683 int pa_raise_priority ( int nice_level
) {
685 #ifdef HAVE_SYS_RESOURCE_H
688 if ( set_nice ( nice_level
) >= 0 ) {
689 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
693 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++)
694 if ( set_nice ( n
) > 0 ) {
695 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
699 pa_log_info ( "Failed to acquire high-priority scheduling: %s" , pa_cstrerror ( errno
));
704 if ( nice_level
< 0 ) {
705 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
706 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
711 pa_log_info ( "Successfully gained high priority class." );
718 /* Reset the priority to normal, inverting the changes made by
719 * pa_raise_priority() and pa_make_realtime()*/
720 void pa_reset_priority ( void ) {
721 #ifdef HAVE_SYS_RESOURCE_H
722 struct sched_param sp
;
724 setpriority ( PRIO_PROCESS
, 0 , 0 );
727 pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
);
731 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
735 int pa_match ( const char * expr
, const char * v
) {
740 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
745 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
747 else if ( k
== REG_NOMATCH
)
760 /* Try to parse a boolean string value.*/
761 int pa_parse_boolean ( const char * v
) {
766 /* First we check language independant */
767 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
769 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
772 /* And then we check language dependant */
773 if (( expr
= nl_langinfo ( YESEXPR
)))
775 if (( r
= pa_match ( expr
, v
)) > 0 )
778 if (( expr
= nl_langinfo ( NOEXPR
)))
780 if (( r
= pa_match ( expr
, v
)) > 0 )
787 /* Split the specified string wherever one of the strings in delimiter
788 * occurs. Each time it is called returns a newly allocated string
789 * with pa_xmalloc(). The variable state points to, should be
790 * initiallized to NULL before the first call. */
791 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
792 const char * current
= * state
? * state
: c
;
798 l
= strcspn ( current
, delimiter
);
804 return pa_xstrndup ( current
, l
);
807 /* What is interpreted as whitespace? */
808 #define WHITESPACE " \t\n "
810 /* Split a string into words. Otherwise similar to pa_split(). */
811 char * pa_split_spaces ( const char * c
, const char ** state
) {
812 const char * current
= * state
? * state
: c
;
815 if (!* current
|| * c
== 0 )
818 current
+= strspn ( current
, WHITESPACE
);
819 l
= strcspn ( current
, WHITESPACE
);
823 return pa_xstrndup ( current
, l
);
826 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
828 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
829 const char * pa_sig2str ( int sig
) {
842 char buf
[ SIG2STR_MAX
];
844 if ( sig2str ( sig
, buf
) == 0 ) {
845 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
846 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
847 PA_STATIC_TLS_SET ( signame
, t
);
855 case SIGHUP
: return "SIGHUP" ;
857 case SIGINT
: return "SIGINT" ;
859 case SIGQUIT
: return "SIGQUIT" ;
861 case SIGILL
: return "SIGULL" ;
863 case SIGTRAP
: return "SIGTRAP" ;
865 case SIGABRT
: return "SIGABRT" ;
867 case SIGBUS
: return "SIGBUS" ;
869 case SIGFPE
: return "SIGFPE" ;
871 case SIGKILL
: return "SIGKILL" ;
874 case SIGUSR1
: return "SIGUSR1" ;
876 case SIGSEGV
: return "SIGSEGV" ;
878 case SIGUSR2
: return "SIGUSR2" ;
881 case SIGPIPE
: return "SIGPIPE" ;
884 case SIGALRM
: return "SIGALRM" ;
886 case SIGTERM
: return "SIGTERM" ;
888 case SIGSTKFLT
: return "SIGSTKFLT" ;
891 case SIGCHLD
: return "SIGCHLD" ;
894 case SIGCONT
: return "SIGCONT" ;
897 case SIGSTOP
: return "SIGSTOP" ;
900 case SIGTSTP
: return "SIGTSTP" ;
903 case SIGTTIN
: return "SIGTTIN" ;
906 case SIGTTOU
: return "SIGTTOU" ;
909 case SIGURG
: return "SIGURG" ;
912 case SIGXCPU
: return "SIGXCPU" ;
915 case SIGXFSZ
: return "SIGXFSZ" ;
918 case SIGVTALRM
: return "SIGVTALRM" ;
921 case SIGPROF
: return "SIGPROF" ;
924 case SIGWINCH
: return "SIGWINCH" ;
927 case SIGIO
: return "SIGIO" ;
930 case SIGPWR
: return "SIGPWR" ;
933 case SIGSYS
: return "SIGSYS" ;
938 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
939 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
940 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
941 PA_STATIC_TLS_SET ( signame
, t
);
950 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
951 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
952 PA_STATIC_TLS_SET ( signame
, t
);
958 /* Check whether the specified GID and the group name match */
959 static int is_group ( gid_t gid
, const char * name
) {
960 struct group group
, * result
= NULL
;
965 #ifdef HAVE_GETGRGID_R
966 #ifdef _SC_GETGR_R_SIZE_MAX
967 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
974 data
= pa_xmalloc (( size_t ) n
);
977 if ( getgrgid_r ( gid
, & group
, data
, ( size_t ) n
, & result
) < 0 || ! result
) {
978 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
986 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
991 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
992 * support getgrgid_r. */
995 if (!( result
= getgrgid ( gid
))) {
996 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
1004 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
1012 /* Check the current user is member of the specified group */
1013 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1014 GETGROUPS_T
* gids
, tgid
;
1015 long n
= sysconf ( _SC_NGROUPS_MAX
);
1020 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1022 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1023 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1027 for ( i
= 0 ; i
< n
; i
++) {
1029 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1038 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1054 /* Check whether the specifc user id is a member of the specified group */
1055 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1056 char * g_buf
, * p_buf
;
1058 struct group grbuf
, * gr
;
1062 #ifdef _SC_GETGR_R_SIZE_MAX
1063 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1070 g_buf
= pa_xmalloc (( size_t ) g_n
);
1072 #ifdef _SC_GETPW_R_SIZE_MAX
1073 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1080 p_buf
= pa_xmalloc (( size_t ) p_n
);
1083 #ifdef HAVE_GETGRNAM_R
1084 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1086 if (!( gr
= getgrnam ( name
)))
1095 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1096 struct passwd pwbuf
, * pw
;
1098 #ifdef HAVE_GETPWNAM_R
1099 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1101 if (!( pw
= getpwnam (* i
)))
1105 if ( pw
-> pw_uid
== uid
) {
1118 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1119 gid_t
pa_get_gid_of_group ( const char * name
) {
1120 gid_t ret
= ( gid_t
) - 1 ;
1123 struct group grbuf
, * gr
;
1125 #ifdef _SC_GETGR_R_SIZE_MAX
1126 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1133 g_buf
= pa_xmalloc (( size_t ) g_n
);
1136 #ifdef HAVE_GETGRNAM_R
1137 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
)
1139 if (!( gr
= getgrnam ( name
)))
1154 int pa_check_in_group ( gid_t g
) {
1155 gid_t gids
[ NGROUPS_MAX
];
1158 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1168 #else /* HAVE_GRP_H */
1170 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1176 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1181 gid_t
pa_get_gid_of_group ( const char * name
) {
1186 int pa_check_in_group ( gid_t g
) {
1193 /* Lock or unlock a file entirely.
1194 (advisory on UNIX, mandatory on Windows) */
1195 int pa_lock_fd ( int fd
, int b
) {
1197 struct flock f_lock
;
1199 /* Try a R/W lock first */
1201 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1202 f_lock
. l_whence
= SEEK_SET
;
1206 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1209 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1210 if ( b
&& errno
== EBADF
) {
1211 f_lock
. l_type
= F_RDLCK
;
1212 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1216 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1220 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1222 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1224 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1227 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1229 /* FIXME: Needs to set errno! */
1235 /* Remove trailing newlines from a string */
1236 char * pa_strip_nl ( char * s
) {
1239 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1243 /* Create a temporary lock file and lock it. */
1244 int pa_lock_lockfile ( const char * fn
) {
1251 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1258 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1259 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1263 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1264 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1268 if ( fstat ( fd
, & st
) < 0 ) {
1269 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1273 /* Check whether the file has been removed meanwhile. When yes,
1274 * restart this loop, otherwise, we're done */
1275 if ( st
. st_nlink
>= 1 )
1278 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1279 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1283 if ( pa_close ( fd
) < 0 ) {
1284 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1297 int saved_errno
= errno
;
1299 errno
= saved_errno
;
1305 /* Unlock a temporary lcok file */
1306 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1311 if ( unlink ( fn
) < 0 ) {
1312 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1317 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1318 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1322 if ( pa_close ( fd
) < 0 ) {
1323 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1330 static char * get_pulse_home ( void ) {
1334 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1335 pa_log_error ( "Failed to get home directory." );
1339 if ( stat ( h
, & st
) < 0 ) {
1340 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1344 if ( st
. st_uid
!= getuid ()) {
1345 pa_log_error ( "Home directory %s not ours." , h
);
1350 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1353 char * pa_get_state_dir ( void ) {
1356 /* The state directory shall contain dynamic data that should be
1357 * kept across reboots, and is private to this user */
1359 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1360 if (!( d
= get_pulse_home ()))
1363 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1364 * dir then this will break. */
1366 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1367 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1375 static char * make_random_dir ( mode_t m
) {
1376 static const char table
[] =
1377 "abcdefghijklmnopqrstuvwxyz"
1378 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1385 if (!( tmpdir
= getenv ( "TMPDIR" )))
1386 if (!( tmpdir
= getenv ( "TMP" )))
1387 if (!( tmpdir
= getenv ( "TEMP" )))
1388 tmpdir
= getenv ( "TEMPDIR" );
1390 if (! tmpdir
|| ! pa_is_path_absolute ( tmpdir
))
1393 fn
= pa_sprintf_malloc ( "%s/pulse-XXXXXXXXXXXX" , tmpdir
);
1394 pathlen
= strlen ( fn
);
1402 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1403 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1405 u
= umask ((~ m
) & 0777 );
1408 saved_errno
= errno
;
1410 errno
= saved_errno
;
1415 if ( errno
!= EEXIST
) {
1416 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1423 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1426 if (!( p
= make_random_dir ( m
)))
1429 if ( symlink ( p
, k
) < 0 ) {
1430 int saved_errno
= errno
;
1432 if ( errno
!= EEXIST
)
1433 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1438 errno
= saved_errno
;
1446 char * pa_get_runtime_dir ( void ) {
1447 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1451 /* The runtime directory shall contain dynamic data that needs NOT
1452 * to be kept accross reboots and is usuallly private to the user,
1453 * except in system mode, where it might be accessible by other
1454 * users, too. Since we need POSIX locking and UNIX sockets in
1455 * this directory, we link it to a random subdir in /tmp, if it
1456 * was not explicitly configured. */
1458 m
= pa_in_system_mode () ? 0755U : 0700U ;
1460 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1462 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1463 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1467 return pa_xstrdup ( d
);
1470 if (!( d
= get_pulse_home ()))
1473 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1474 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1479 if (!( mid
= pa_machine_id ())) {
1484 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1489 /* OK, first let's check if the "runtime" symlink is already
1492 if (!( p
= pa_readlink ( k
))) {
1494 if ( errno
!= ENOENT
) {
1495 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1499 /* Hmm, so the runtime directory didn't exist yet, so let's
1500 * create one in /tmp and symlink that to it */
1502 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1504 /* Mhmm, maybe another process was quicker than us,
1505 * let's check if that was valid */
1506 if ( errno
== EEXIST
)
1515 /* Make sure that this actually makes sense */
1516 if (! pa_is_path_absolute ( p
)) {
1517 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1522 /* Hmm, so this symlink is still around, make sure nobody fools
1525 if ( lstat ( p
, & st
) < 0 ) {
1527 if ( errno
!= ENOENT
) {
1528 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1534 if ( S_ISDIR ( st
. st_mode
) &&
1535 ( st
. st_uid
== getuid ()) &&
1536 (( st
. st_mode
& 0777 ) == 0700 )) {
1542 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1548 /* Hmm, so the link points to some nonexisting or invalid
1549 * dir. Let's replace it by a new link. We first create a
1550 * temporary link and then rename that to allow concurrent
1551 * execution of this function. */
1553 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1555 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1557 if ( errno
!= EEXIST
) {
1558 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1565 /* Hmm, someone lese was quicker then us. Let's give
1566 * him some time to finish, and retry. */
1571 /* OK, we succeeded in creating the temporary symlink, so
1572 * let's rename it */
1573 if ( rename ( t
, k
) < 0 ) {
1574 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1590 /* Try to open a configuration file. If "env" is specified, open the
1591 * value of the specified environment variable. Otherwise look for a
1592 * file "local" in the home directory or a file "global" in global
1593 * file system. If "result" is non-NULL, a pointer to a newly
1594 * allocated buffer containing the used configuration file is
1596 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1601 if (! getenv ( PULSE_ROOTENV
))
1605 if ( env
&& ( fn
= getenv ( env
))) {
1609 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1610 /* FIXME: Needs to set errno! */
1615 if (( f
= fopen ( fn
, "r" ))) {
1617 * result
= pa_xstrdup ( fn
);
1622 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1632 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1633 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1634 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1635 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1640 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1641 /* FIXME: Needs to set errno! */
1648 if (( f
= fopen ( fn
, "r" ))) {
1650 * result
= pa_xstrdup ( fn
);
1656 if ( errno
!= ENOENT
) {
1657 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1669 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1670 /* FIXME: Needs to set errno! */
1675 if (( f
= fopen ( global
, "r" ))) {
1678 * result
= pa_xstrdup ( global
);
1688 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1693 if (! getenv ( PULSE_ROOTENV
))
1697 if ( env
&& ( fn
= getenv ( env
))) {
1700 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1701 /* FIXME: Needs to set errno! */
1706 if ( access ( fn
, R_OK
) == 0 )
1707 return pa_xstrdup ( fn
);
1709 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1718 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1719 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1720 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1721 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1726 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1727 /* FIXME: Needs to set errno! */
1734 if ( access ( fn
, R_OK
) == 0 ) {
1735 char * r
= pa_xstrdup ( fn
);
1740 if ( errno
!= ENOENT
) {
1741 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1751 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1752 /* FIXME: Needs to set errno! */
1757 if ( access ( global
, R_OK
) == 0 )
1758 return pa_xstrdup ( global
);
1766 /* Format the specified data as a hexademical string */
1767 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1768 size_t i
= 0 , j
= 0 ;
1769 const char hex
[] = "0123456789abcdef" ;
1773 pa_assert ( slength
> 0 );
1775 while ( i
< dlength
&& j
+ 3 <= slength
) {
1776 s
[ j
++] = hex
[* d
>> 4 ];
1777 s
[ j
++] = hex
[* d
& 0xF ];
1783 s
[ j
< slength
? j
: slength
] = 0 ;
1787 /* Convert a hexadecimal digit to a number or -1 if invalid */
1788 static int hexc ( char c
) {
1789 if ( c
>= '0' && c
<= '9' )
1792 if ( c
>= 'A' && c
<= 'F' )
1793 return c
- 'A' + 10 ;
1795 if ( c
>= 'a' && c
<= 'f' )
1796 return c
- 'a' + 10 ;
1802 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1803 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1809 while ( j
< dlength
&& * p
) {
1812 if (( b
= hexc (*( p
++))) < 0 )
1815 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1820 if (( b
= hexc (*( p
++))) < 0 )
1823 d
[ j
] |= ( uint8_t ) b
;
1830 /* Returns nonzero when *s starts with *pfx */
1831 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1839 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1842 /* Returns nonzero when *s ends with *sfx */
1843 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1852 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1855 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1861 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1865 char * pa_make_path_absolute ( const char * p
) {
1871 if ( pa_is_path_absolute ( p
))
1872 return pa_xstrdup ( p
);
1874 if (!( cwd
= pa_getcwd ()))
1875 return pa_xstrdup ( p
);
1877 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1882 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1883 * if fn is non-null and starts with / return fn
1884 * otherwise append fn to the run time path and return it */
1885 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1888 if ( pa_is_path_absolute ( fn
))
1889 return pa_xstrdup ( fn
);
1891 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1902 if (!( mid
= pa_machine_id ())) {
1907 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1910 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1918 char * pa_runtime_path ( const char * fn
) {
1919 return get_path ( fn
, FALSE
, TRUE
);
1922 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1923 return get_path ( fn
, appendmid
, FALSE
);
1926 /* Convert the string s to a signed integer in *ret_i */
1927 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1935 l
= strtol ( s
, & x
, 0 );
1937 if (! x
|| * x
|| errno
) {
1943 if (( int32_t ) l
!= l
) {
1948 * ret_i
= ( int32_t ) l
;
1953 /* Convert the string s to an unsigned integer in *ret_u */
1954 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1962 l
= strtoul ( s
, & x
, 0 );
1964 if (! x
|| * x
|| errno
) {
1970 if (( uint32_t ) l
!= l
) {
1975 * ret_u
= ( uint32_t ) l
;
1980 #ifdef HAVE_STRTOF_L
1981 static locale_t c_locale
= NULL
;
1983 static void c_locale_destroy ( void ) {
1984 freelocale ( c_locale
);
1988 int pa_atod ( const char * s
, double * ret_d
) {
1995 /* This should be locale independent */
1997 #ifdef HAVE_STRTOF_L
2001 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
2002 atexit ( c_locale_destroy
);
2008 f
= strtod_l ( s
, & x
, c_locale
);
2016 if (! x
|| * x
|| errno
) {
2027 /* Same as snprintf, but guarantees NUL-termination on every platform */
2028 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2033 pa_assert ( size
> 0 );
2036 va_start ( ap
, format
);
2037 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2043 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2044 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2048 pa_assert ( size
> 0 );
2051 ret
= vsnprintf ( str
, size
, format
, ap
);
2058 if (( size_t ) ret
> size
- 1 )
2061 return ( size_t ) ret
;
2064 /* Truncate the specified string, but guarantee that the string
2065 * returned still validates as UTF8 */
2066 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2068 pa_assert ( pa_utf8_valid ( c
));
2075 while ( l
> 0 && ! pa_utf8_valid ( c
))
2081 char * pa_getcwd ( void ) {
2085 char * p
= pa_xmalloc ( l
);
2089 if ( errno
!= ERANGE
)
2097 void * pa_will_need ( const void * p
, size_t l
) {
2098 #ifdef RLIMIT_MEMLOCK
2109 a
= PA_PAGE_ALIGN_PTR ( p
);
2110 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2112 #ifdef HAVE_POSIX_MADVISE
2113 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2114 pa_log_debug ( "posix_madvise() worked fine!" );
2119 /* Most likely the memory was not mmap()ed from a file and thus
2120 * madvise() didn't work, so let's misuse mlock() do page this
2121 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2122 * inviting, the man page of mlock() tells us: "All pages that
2123 * contain a part of the specified address range are guaranteed to
2124 * be resident in RAM when the call returns successfully." */
2126 #ifdef RLIMIT_MEMLOCK
2127 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2129 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2130 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
));
2135 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2137 bs
= PA_PAGE_SIZE
* 4 ;
2140 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2143 while ( size
> 0 && bs
> 0 ) {
2148 if ( mlock ( a
, bs
) < 0 ) {
2149 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2153 pa_assert_se ( munlock ( a
, bs
) == 0 );
2155 a
= ( const uint8_t *) a
+ bs
;
2161 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2163 pa_log_debug ( "mlock() worked fine!" );
2168 void pa_close_pipe ( int fds
[ 2 ]) {
2172 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2175 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2177 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2180 char * pa_readlink ( const char * p
) {
2189 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2194 if (( size_t ) n
< l
- 1 ) {
2204 int pa_close_all ( int except_fd
, ...) {
2209 va_start ( ap
, except_fd
);
2212 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2217 p
= pa_xnew ( int , n
+ 1 );
2219 va_start ( ap
, except_fd
);
2222 if ( except_fd
>= 0 ) {
2226 while (( fd
= va_arg ( ap
, int )) >= 0 )
2233 r
= pa_close_allv ( p
);
2239 int pa_close_allv ( const int except_fds
[]) {
2247 if (( d
= opendir ( "/proc/self/fd" ))) {
2251 while (( de
= readdir ( d
))) {
2257 if ( de
-> d_name
[ 0 ] == '.' )
2261 l
= strtol ( de
-> d_name
, & e
, 10 );
2262 if ( errno
!= 0 || ! e
|| * e
) {
2270 if (( long ) fd
!= l
) {
2283 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2284 if ( except_fds
[ i
] == fd
) {
2292 if ( pa_close ( fd
) < 0 ) {
2293 saved_errno
= errno
;
2295 errno
= saved_errno
;
2307 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2308 maxfd
= ( int ) rl
. rlim_max
;
2310 maxfd
= sysconf ( _SC_OPEN_MAX
);
2312 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2317 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2318 if ( except_fds
[ i
] == fd
) {
2326 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2333 int pa_unblock_sigs ( int except
, ...) {
2338 va_start ( ap
, except
);
2341 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2346 p
= pa_xnew ( int , n
+ 1 );
2348 va_start ( ap
, except
);
2355 while (( sig
= va_arg ( ap
, int )) >= 0 )
2362 r
= pa_unblock_sigsv ( p
);
2368 int pa_unblock_sigsv ( const int except
[]) {
2372 if ( sigemptyset (& ss
) < 0 )
2375 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2376 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2379 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2382 int pa_reset_sigs ( int except
, ...) {
2387 va_start ( ap
, except
);
2390 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2395 p
= pa_xnew ( int , n
+ 1 );
2397 va_start ( ap
, except
);
2404 while (( sig
= va_arg ( ap
, int )) >= 0 )
2411 r
= pa_reset_sigsv ( p
);
2417 int pa_reset_sigsv ( const int except
[]) {
2420 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2421 pa_bool_t reset
= TRUE
;
2432 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2433 if ( sig
== except
[ i
]) {
2442 struct sigaction sa
;
2444 memset (& sa
, 0 , sizeof ( sa
));
2445 sa
. sa_handler
= SIG_DFL
;
2447 /* On Linux the first two RT signals are reserved by
2448 * glibc, and sigaction() will return EINVAL for them. */
2449 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2450 if ( errno
!= EINVAL
)
2458 void pa_set_env ( const char * key
, const char * value
) {
2462 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2465 pa_bool_t
pa_in_system_mode ( void ) {
2468 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2474 char * pa_get_user_name_malloc ( void ) {
2478 #ifdef _SC_LOGIN_NAME_MAX
2479 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2485 u
= pa_xnew ( char , k
+ 1 );
2487 if (!( pa_get_user_name ( u
, k
))) {
2495 char * pa_get_host_name_malloc ( void ) {
2504 if (! pa_get_host_name ( c
, l
)) {
2506 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2509 } else if ( strlen ( c
) < l
- 1 ) {
2517 u
= pa_utf8_filter ( c
);
2522 /* Hmm, the hostname is as long the space we offered the
2523 * function, we cannot know if it fully fit in, so let's play
2524 * safe and retry. */
2533 char * pa_machine_id ( void ) {
2537 /* The returned value is supposed be some kind of ascii identifier
2538 * that is unique and stable across reboots. */
2540 /* First we try the D-Bus UUID, which is the best option we have,
2541 * since it fits perfectly our needs and is not as volatile as the
2542 * hostname which might be set from dhcp. */
2544 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2545 char ln
[ 34 ] = "" , * r
;
2547 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2553 return pa_utf8_filter ( ln
);
2556 if (( h
= pa_get_host_name_malloc ()))
2559 /* If no hostname was set we use the POSIX hostid. It's usually
2560 * the IPv4 address. Might not be that stable. */
2561 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2564 char * pa_session_id ( void ) {
2567 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2570 return pa_utf8_filter ( e
);
2573 char * pa_uname_string ( void ) {
2576 pa_assert_se ( uname (& u
) >= 0 );
2578 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2581 #ifdef HAVE_VALGRIND_MEMCHECK_H
2582 pa_bool_t
pa_in_valgrind ( void ) {
2585 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2586 * here instead of really checking whether we run in valgrind or
2590 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2596 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2607 void pa_reduce ( unsigned * num
, unsigned * den
) {
2609 unsigned gcd
= pa_gcd (* num
, * den
);
2617 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2620 unsigned pa_ncpus ( void ) {
2623 #ifdef _SC_NPROCESSORS_CONF
2624 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2629 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2632 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2641 sb
= pa_strbuf_new ();
2646 if (!( p
= strstr ( s
, a
)))
2649 pa_strbuf_putsn ( sb
, s
, p
- s
);
2650 pa_strbuf_puts ( sb
, b
);
2654 pa_strbuf_puts ( sb
, s
);
2656 return pa_strbuf_tostring_free ( sb
);
2659 char * pa_escape ( const char * p
, const char * chars
) {
2662 pa_strbuf
* buf
= pa_strbuf_new ();
2664 for ( s
= p
; * s
; ++ s
) {
2666 pa_strbuf_putc ( buf
, ' \\ ' );
2668 for ( c
= chars
; * c
; ++ c
) {
2670 pa_strbuf_putc ( buf
, ' \\ ' );
2675 pa_strbuf_putc ( buf
, * s
);
2678 return pa_strbuf_tostring_free ( buf
);
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
);