]>
code.delx.au - pulseaudio/blob - src/pulsecore/core-util.c
27e09cbce6622dae80d9d4d98a5dd3d49e0e25ad
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 ( 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 ( 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
) {
791 /* First we check language independant */
792 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
794 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
797 /* And then we check language dependant */
798 if (( expr
= nl_langinfo ( YESEXPR
)))
800 if ( pa_match ( expr
, v
) > 0 )
803 if (( expr
= nl_langinfo ( NOEXPR
)))
805 if ( pa_match ( expr
, v
) > 0 )
812 /* Split the specified string wherever one of the strings in delimiter
813 * occurs. Each time it is called returns a newly allocated string
814 * with pa_xmalloc(). The variable state points to, should be
815 * initiallized to NULL before the first call. */
816 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
817 const char * current
= * state
? * state
: c
;
823 l
= strcspn ( current
, delimiter
);
829 return pa_xstrndup ( current
, l
);
832 /* What is interpreted as whitespace? */
833 #define WHITESPACE " \t\n "
835 /* Split a string into words. Otherwise similar to pa_split(). */
836 char * pa_split_spaces ( const char * c
, const char ** state
) {
837 const char * current
= * state
? * state
: c
;
840 if (!* current
|| * c
== 0 )
843 current
+= strspn ( current
, WHITESPACE
);
844 l
= strcspn ( current
, WHITESPACE
);
848 return pa_xstrndup ( current
, l
);
851 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
853 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
854 const char * pa_sig2str ( int sig
) {
867 char buf
[ SIG2STR_MAX
];
869 if ( sig2str ( sig
, buf
) == 0 ) {
870 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
871 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
872 PA_STATIC_TLS_SET ( signame
, t
);
880 case SIGHUP
: return "SIGHUP" ;
882 case SIGINT
: return "SIGINT" ;
884 case SIGQUIT
: return "SIGQUIT" ;
886 case SIGILL
: return "SIGULL" ;
888 case SIGTRAP
: return "SIGTRAP" ;
890 case SIGABRT
: return "SIGABRT" ;
892 case SIGBUS
: return "SIGBUS" ;
894 case SIGFPE
: return "SIGFPE" ;
896 case SIGKILL
: return "SIGKILL" ;
899 case SIGUSR1
: return "SIGUSR1" ;
901 case SIGSEGV
: return "SIGSEGV" ;
903 case SIGUSR2
: return "SIGUSR2" ;
906 case SIGPIPE
: return "SIGPIPE" ;
909 case SIGALRM
: return "SIGALRM" ;
911 case SIGTERM
: return "SIGTERM" ;
913 case SIGSTKFLT
: return "SIGSTKFLT" ;
916 case SIGCHLD
: return "SIGCHLD" ;
919 case SIGCONT
: return "SIGCONT" ;
922 case SIGSTOP
: return "SIGSTOP" ;
925 case SIGTSTP
: return "SIGTSTP" ;
928 case SIGTTIN
: return "SIGTTIN" ;
931 case SIGTTOU
: return "SIGTTOU" ;
934 case SIGURG
: return "SIGURG" ;
937 case SIGXCPU
: return "SIGXCPU" ;
940 case SIGXFSZ
: return "SIGXFSZ" ;
943 case SIGVTALRM
: return "SIGVTALRM" ;
946 case SIGPROF
: return "SIGPROF" ;
949 case SIGWINCH
: return "SIGWINCH" ;
952 case SIGIO
: return "SIGIO" ;
955 case SIGPWR
: return "SIGPWR" ;
958 case SIGSYS
: return "SIGSYS" ;
963 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
964 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
965 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
966 PA_STATIC_TLS_SET ( signame
, t
);
975 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
976 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
977 PA_STATIC_TLS_SET ( signame
, t
);
983 /* Check whether the specified GID and the group name match */
984 static int is_group ( gid_t gid
, const char * name
) {
985 struct group
* group
= NULL
;
989 if (!( group
= pa_getgrgid_malloc ( gid
)))
994 pa_log ( "pa_getgrgid_malloc(%u): %s" , gid
, pa_cstrerror ( errno
));
999 r
= strcmp ( name
, group
-> gr_name
) == 0 ;
1002 pa_getgrgid_free ( group
);
1007 /* Check the current user is member of the specified group */
1008 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1009 GETGROUPS_T
* gids
, tgid
;
1010 long n
= sysconf ( _SC_NGROUPS_MAX
);
1015 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
) * ( size_t ) n
);
1017 if (( n
= getgroups (( int ) n
, gids
)) < 0 ) {
1018 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
1022 for ( i
= 0 ; i
< n
; i
++) {
1024 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
1033 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1049 /* Check whether the specifc user id is a member of the specified group */
1050 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1051 struct group
* group
= NULL
;
1056 if (!( group
= pa_getgrnam_malloc ( name
)))
1064 for ( i
= group
-> gr_mem
; * i
; i
++) {
1065 struct passwd
* pw
= NULL
;
1068 if (!( pw
= pa_getpwnam_malloc (* i
)))
1071 if ( pw
-> pw_uid
== uid
)
1074 pa_getpwnam_free ( pw
);
1081 pa_getgrnam_free ( group
);
1086 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1087 gid_t
pa_get_gid_of_group ( const char * name
) {
1088 gid_t ret
= ( gid_t
) - 1 ;
1089 struct group
* gr
= NULL
;
1092 if (!( gr
= pa_getgrnam_malloc ( name
)))
1102 pa_getgrnam_free ( gr
);
1106 int pa_check_in_group ( gid_t g
) {
1107 gid_t gids
[ NGROUPS_MAX
];
1110 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1120 #else /* HAVE_GRP_H */
1122 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1128 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1133 gid_t
pa_get_gid_of_group ( const char * name
) {
1138 int pa_check_in_group ( gid_t g
) {
1145 /* Lock or unlock a file entirely.
1146 (advisory on UNIX, mandatory on Windows) */
1147 int pa_lock_fd ( int fd
, int b
) {
1149 struct flock f_lock
;
1151 /* Try a R/W lock first */
1153 f_lock
. l_type
= ( short ) ( b
? F_WRLCK
: F_UNLCK
);
1154 f_lock
. l_whence
= SEEK_SET
;
1158 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1161 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1162 if ( b
&& errno
== EBADF
) {
1163 f_lock
. l_type
= F_RDLCK
;
1164 if ( fcntl ( fd
, F_SETLKW
, & f_lock
) >= 0 )
1168 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1172 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1174 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1176 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1179 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1181 /* FIXME: Needs to set errno! */
1187 /* Remove trailing newlines from a string */
1188 char * pa_strip_nl ( char * s
) {
1191 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1195 /* Create a temporary lock file and lock it. */
1196 int pa_lock_lockfile ( const char * fn
) {
1203 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1210 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1211 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1215 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1216 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1220 if ( fstat ( fd
, & st
) < 0 ) {
1221 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1225 /* Check whether the file has been removed meanwhile. When yes,
1226 * restart this loop, otherwise, we're done */
1227 if ( st
. st_nlink
>= 1 )
1230 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1231 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1235 if ( pa_close ( fd
) < 0 ) {
1236 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1247 int saved_errno
= errno
;
1249 errno
= saved_errno
;
1255 /* Unlock a temporary lcok file */
1256 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1261 if ( unlink ( fn
) < 0 ) {
1262 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1267 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1268 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1272 if ( pa_close ( fd
) < 0 ) {
1273 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1280 static char * get_pulse_home ( void ) {
1285 if (!( h
= pa_get_home_dir_malloc ())) {
1286 pa_log_error ( "Failed to get home directory." );
1290 if ( stat ( h
, & st
) < 0 ) {
1291 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1295 if ( st
. st_uid
!= getuid ()) {
1296 pa_log_error ( "Home directory %s not ours." , h
);
1301 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1309 char * pa_get_state_dir ( void ) {
1312 /* The state directory shall contain dynamic data that should be
1313 * kept across reboots, and is private to this user */
1315 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1316 if (!( d
= get_pulse_home ()))
1319 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1320 * dir then this will break. */
1322 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1323 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1331 char * pa_get_home_dir_malloc ( void ) {
1333 size_t allocated
= 128 ;
1336 homedir
= pa_xmalloc ( allocated
);
1338 if (! pa_get_home_dir ( homedir
, allocated
)) {
1343 if ( strlen ( homedir
) < allocated
- 1 )
1353 char * pa_get_binary_name_malloc ( void ) {
1355 size_t allocated
= 128 ;
1358 t
= pa_xmalloc ( allocated
);
1360 if (! pa_get_binary_name ( t
, allocated
)) {
1365 if ( strlen ( t
) < allocated
- 1 )
1375 static char * make_random_dir ( mode_t m
) {
1376 static const char table
[] =
1377 "abcdefghijklmnopqrstuvwxyz"
1378 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1384 fn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX" , pa_get_temp_dir ());
1385 pathlen
= strlen ( fn
);
1393 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1394 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1396 u
= umask ((~ m
) & 0777 );
1399 saved_errno
= errno
;
1401 errno
= saved_errno
;
1406 if ( errno
!= EEXIST
) {
1407 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1414 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1417 if (!( p
= make_random_dir ( m
)))
1420 if ( symlink ( p
, k
) < 0 ) {
1421 int saved_errno
= errno
;
1423 if ( errno
!= EEXIST
)
1424 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1429 errno
= saved_errno
;
1437 char * pa_get_runtime_dir ( void ) {
1438 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1442 /* The runtime directory shall contain dynamic data that needs NOT
1443 * to be kept accross reboots and is usuallly private to the user,
1444 * except in system mode, where it might be accessible by other
1445 * users, too. Since we need POSIX locking and UNIX sockets in
1446 * this directory, we link it to a random subdir in /tmp, if it
1447 * was not explicitly configured. */
1449 m
= pa_in_system_mode () ? 0755U : 0700U ;
1451 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1453 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1454 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1458 return pa_xstrdup ( d
);
1461 if (!( d
= get_pulse_home ()))
1464 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1465 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1470 if (!( mid
= pa_machine_id ())) {
1475 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1480 /* OK, first let's check if the "runtime" symlink is already
1483 if (!( p
= pa_readlink ( k
))) {
1485 if ( errno
!= ENOENT
) {
1486 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1490 /* Hmm, so the runtime directory didn't exist yet, so let's
1491 * create one in /tmp and symlink that to it */
1493 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1495 /* Mhmm, maybe another process was quicker than us,
1496 * let's check if that was valid */
1497 if ( errno
== EEXIST
)
1506 /* Make sure that this actually makes sense */
1507 if (! pa_is_path_absolute ( p
)) {
1508 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1513 /* Hmm, so this symlink is still around, make sure nobody fools
1516 if ( lstat ( p
, & st
) < 0 ) {
1518 if ( errno
!= ENOENT
) {
1519 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1525 if ( S_ISDIR ( st
. st_mode
) &&
1526 ( st
. st_uid
== getuid ()) &&
1527 (( st
. st_mode
& 0777 ) == 0700 )) {
1533 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1539 /* Hmm, so the link points to some nonexisting or invalid
1540 * dir. Let's replace it by a new link. We first create a
1541 * temporary link and then rename that to allow concurrent
1542 * execution of this function. */
1544 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1546 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1548 if ( errno
!= EEXIST
) {
1549 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1556 /* Hmm, someone lese was quicker then us. Let's give
1557 * him some time to finish, and retry. */
1562 /* OK, we succeeded in creating the temporary symlink, so
1563 * let's rename it */
1564 if ( rename ( t
, k
) < 0 ) {
1565 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1581 /* Try to open a configuration file. If "env" is specified, open the
1582 * value of the specified environment variable. Otherwise look for a
1583 * file "local" in the home directory or a file "global" in global
1584 * file system. If "result" is non-NULL, a pointer to a newly
1585 * allocated buffer containing the used configuration file is
1587 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1592 if (! getenv ( PULSE_ROOTENV
))
1596 if ( env
&& ( fn
= getenv ( env
))) {
1600 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1601 /* FIXME: Needs to set errno! */
1606 if (( f
= fopen ( fn
, "r" ))) {
1608 * result
= pa_xstrdup ( fn
);
1613 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1623 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1624 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1625 else if (( h
= pa_get_home_dir_malloc ())) {
1626 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1632 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1633 /* FIXME: Needs to set errno! */
1640 if (( f
= fopen ( fn
, "r" ))) {
1642 * result
= pa_xstrdup ( fn
);
1648 if ( errno
!= ENOENT
) {
1649 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1661 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1662 /* FIXME: Needs to set errno! */
1667 if (( f
= fopen ( global
, "r" ))) {
1670 * result
= pa_xstrdup ( global
);
1680 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1685 if (! getenv ( PULSE_ROOTENV
))
1689 if ( env
&& ( fn
= getenv ( env
))) {
1692 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1693 /* FIXME: Needs to set errno! */
1698 if ( access ( fn
, R_OK
) == 0 )
1699 return pa_xstrdup ( fn
);
1701 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1710 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1711 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1712 else if (( h
= pa_get_home_dir_malloc ())) {
1713 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1719 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1720 /* FIXME: Needs to set errno! */
1727 if ( access ( fn
, R_OK
) == 0 ) {
1728 char * r
= pa_xstrdup ( fn
);
1733 if ( errno
!= ENOENT
) {
1734 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1744 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1745 /* FIXME: Needs to set errno! */
1750 if ( access ( global
, R_OK
) == 0 )
1751 return pa_xstrdup ( global
);
1759 /* Format the specified data as a hexademical string */
1760 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1761 size_t i
= 0 , j
= 0 ;
1762 const char hex
[] = "0123456789abcdef" ;
1766 pa_assert ( slength
> 0 );
1768 while ( i
< dlength
&& j
+ 3 <= slength
) {
1769 s
[ j
++] = hex
[* d
>> 4 ];
1770 s
[ j
++] = hex
[* d
& 0xF ];
1776 s
[ j
< slength
? j
: slength
] = 0 ;
1780 /* Convert a hexadecimal digit to a number or -1 if invalid */
1781 static int hexc ( char c
) {
1782 if ( c
>= '0' && c
<= '9' )
1785 if ( c
>= 'A' && c
<= 'F' )
1786 return c
- 'A' + 10 ;
1788 if ( c
>= 'a' && c
<= 'f' )
1789 return c
- 'a' + 10 ;
1795 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1796 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1802 while ( j
< dlength
&& * p
) {
1805 if (( b
= hexc (*( p
++))) < 0 )
1808 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1813 if (( b
= hexc (*( p
++))) < 0 )
1816 d
[ j
] |= ( uint8_t ) b
;
1823 /* Returns nonzero when *s starts with *pfx */
1824 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1832 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1835 /* Returns nonzero when *s ends with *sfx */
1836 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1845 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1848 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1854 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1858 char * pa_make_path_absolute ( const char * p
) {
1864 if ( pa_is_path_absolute ( p
))
1865 return pa_xstrdup ( p
);
1867 if (!( cwd
= pa_getcwd ()))
1868 return pa_xstrdup ( p
);
1870 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1875 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1876 * if fn is non-null and starts with / return fn
1877 * otherwise append fn to the run time path and return it */
1878 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1881 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1886 if ( pa_is_path_absolute ( fn
))
1887 return pa_xstrdup ( fn
);
1895 if (!( mid
= pa_machine_id ())) {
1900 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1903 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1911 char * pa_runtime_path ( const char * fn
) {
1912 return get_path ( fn
, FALSE
, TRUE
);
1915 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1916 return get_path ( fn
, appendmid
, FALSE
);
1919 /* Convert the string s to a signed integer in *ret_i */
1920 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1928 l
= strtol ( s
, & x
, 0 );
1930 if (! x
|| * x
|| errno
) {
1936 if (( int32_t ) l
!= l
) {
1941 * ret_i
= ( int32_t ) l
;
1946 /* Convert the string s to an unsigned integer in *ret_u */
1947 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1955 l
= strtoul ( s
, & x
, 0 );
1957 if (! x
|| * x
|| errno
) {
1963 if (( uint32_t ) l
!= l
) {
1968 * ret_u
= ( uint32_t ) l
;
1973 #ifdef HAVE_STRTOF_L
1974 static locale_t c_locale
= NULL
;
1976 static void c_locale_destroy ( void ) {
1977 freelocale ( c_locale
);
1981 int pa_atod ( const char * s
, double * ret_d
) {
1988 /* This should be locale independent */
1990 #ifdef HAVE_STRTOF_L
1994 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1995 atexit ( c_locale_destroy
);
2001 f
= strtod_l ( s
, & x
, c_locale
);
2009 if (! x
|| * x
|| errno
) {
2020 /* Same as snprintf, but guarantees NUL-termination on every platform */
2021 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2026 pa_assert ( size
> 0 );
2029 va_start ( ap
, format
);
2030 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2036 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2037 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2041 pa_assert ( size
> 0 );
2044 ret
= vsnprintf ( str
, size
, format
, ap
);
2051 if (( size_t ) ret
> size
- 1 )
2054 return ( size_t ) ret
;
2057 /* Truncate the specified string, but guarantee that the string
2058 * returned still validates as UTF8 */
2059 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2061 pa_assert ( pa_utf8_valid ( c
));
2068 while ( l
> 0 && ! pa_utf8_valid ( c
))
2074 char * pa_getcwd ( void ) {
2078 char * p
= pa_xmalloc ( l
);
2082 if ( errno
!= ERANGE
)
2090 void * pa_will_need ( const void * p
, size_t l
) {
2091 #ifdef RLIMIT_MEMLOCK
2102 a
= PA_PAGE_ALIGN_PTR ( p
);
2103 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2105 #ifdef HAVE_POSIX_MADVISE
2106 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2107 pa_log_debug ( "posix_madvise() worked fine!" );
2112 /* Most likely the memory was not mmap()ed from a file and thus
2113 * madvise() didn't work, so let's misuse mlock() do page this
2114 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2115 * inviting, the man page of mlock() tells us: "All pages that
2116 * contain a part of the specified address range are guaranteed to
2117 * be resident in RAM when the call returns successfully." */
2119 #ifdef RLIMIT_MEMLOCK
2120 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2122 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2123 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
));
2128 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2130 bs
= PA_PAGE_SIZE
* 4 ;
2133 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2136 while ( size
> 0 && bs
> 0 ) {
2141 if ( mlock ( a
, bs
) < 0 ) {
2142 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2146 pa_assert_se ( munlock ( a
, bs
) == 0 );
2148 a
= ( const uint8_t *) a
+ bs
;
2154 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2156 pa_log_debug ( "mlock() worked fine!" );
2161 void pa_close_pipe ( int fds
[ 2 ]) {
2165 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2168 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2170 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2173 char * pa_readlink ( const char * p
) {
2182 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2187 if (( size_t ) n
< l
- 1 ) {
2197 int pa_close_all ( int except_fd
, ...) {
2202 va_start ( ap
, except_fd
);
2205 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2210 p
= pa_xnew ( int , n
+ 1 );
2212 va_start ( ap
, except_fd
);
2215 if ( except_fd
>= 0 ) {
2219 while (( fd
= va_arg ( ap
, int )) >= 0 )
2226 r
= pa_close_allv ( p
);
2232 int pa_close_allv ( const int except_fds
[]) {
2240 if (( d
= opendir ( "/proc/self/fd" ))) {
2244 while (( de
= readdir ( d
))) {
2250 if ( de
-> d_name
[ 0 ] == '.' )
2254 l
= strtol ( de
-> d_name
, & e
, 10 );
2255 if ( errno
!= 0 || ! e
|| * e
) {
2263 if (( long ) fd
!= l
) {
2276 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2277 if ( except_fds
[ i
] == fd
) {
2285 if ( pa_close ( fd
) < 0 ) {
2286 saved_errno
= errno
;
2288 errno
= saved_errno
;
2300 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2301 maxfd
= ( int ) rl
. rlim_max
;
2303 maxfd
= sysconf ( _SC_OPEN_MAX
);
2305 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2310 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2311 if ( except_fds
[ i
] == fd
) {
2319 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2326 int pa_unblock_sigs ( int except
, ...) {
2331 va_start ( ap
, except
);
2334 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2339 p
= pa_xnew ( int , n
+ 1 );
2341 va_start ( ap
, except
);
2348 while (( sig
= va_arg ( ap
, int )) >= 0 )
2355 r
= pa_unblock_sigsv ( p
);
2361 int pa_unblock_sigsv ( const int except
[]) {
2365 if ( sigemptyset (& ss
) < 0 )
2368 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2369 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2372 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2375 int pa_reset_sigs ( int except
, ...) {
2380 va_start ( ap
, except
);
2383 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2388 p
= pa_xnew ( int , n
+ 1 );
2390 va_start ( ap
, except
);
2397 while (( sig
= va_arg ( ap
, int )) >= 0 )
2404 r
= pa_reset_sigsv ( p
);
2410 int pa_reset_sigsv ( const int except
[]) {
2413 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2414 pa_bool_t reset
= TRUE
;
2425 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2426 if ( sig
== except
[ i
]) {
2435 struct sigaction sa
;
2437 memset (& sa
, 0 , sizeof ( sa
));
2438 sa
. sa_handler
= SIG_DFL
;
2440 /* On Linux the first two RT signals are reserved by
2441 * glibc, and sigaction() will return EINVAL for them. */
2442 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2443 if ( errno
!= EINVAL
)
2451 void pa_set_env ( const char * key
, const char * value
) {
2455 /* This is not thread-safe */
2457 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2460 void pa_set_env_and_record ( const char * key
, const char * value
) {
2464 /* This is not thread-safe */
2466 pa_set_env ( key
, value
);
2467 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2470 void pa_unset_env_recorded ( void ) {
2472 /* This is not thread-safe */
2477 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_escape ( const char * p
, const char * chars
) {
2684 pa_strbuf
* buf
= pa_strbuf_new ();
2686 for ( s
= p
; * s
; ++ s
) {
2688 pa_strbuf_putc ( buf
, ' \\ ' );
2690 for ( c
= chars
; * c
; ++ c
) {
2692 pa_strbuf_putc ( buf
, ' \\ ' );
2697 pa_strbuf_putc ( buf
, * s
);
2700 return pa_strbuf_tostring_free ( buf
);
2703 char * pa_unescape ( char * p
) {
2705 pa_bool_t escaped
= FALSE
;
2707 for ( s
= p
, d
= p
; * s
; s
++) {
2708 if (! escaped
&& * s
== ' \\ ' ) {
2722 char * pa_realpath ( const char * path
) {
2726 /* We want only abolsute paths */
2727 if ( path
[ 0 ] != '/' ) {
2732 #if defined(__GLIBC__) || defined(__APPLE__)
2736 if (!( r
= realpath ( path
, NULL
)))
2739 /* We copy this here in case our pa_xmalloc() is not
2740 * implemented on top of libc malloc() */
2744 #elif defined(PATH_MAX)
2747 path_buf
= pa_xmalloc ( PATH_MAX
);
2749 if (!( t
= realpath ( path
, path_buf
))) {
2755 #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."
2761 void pa_disable_sigpipe ( void ) {
2764 struct sigaction sa
;
2768 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2769 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2773 sa
. sa_handler
= SIG_IGN
;
2775 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2776 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2782 void pa_xfreev ( void ** a
) {
2788 for ( p
= a
; * p
; p
++)
2794 char ** pa_split_spaces_strv ( const char * s
) {
2796 unsigned i
= 0 , n
= 8 ;
2797 const char * state
= NULL
;
2799 t
= pa_xnew ( char *, n
);
2800 while (( e
= pa_split_spaces ( s
, & state
))) {
2805 t
= pa_xrenew ( char *, t
, n
);
2818 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2821 if ( pa_is_path_absolute ( path
))
2822 return pa_xstrdup ( path
);
2824 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2827 size_t pa_pipe_buf ( int fd
) {
2832 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2843 void pa_reset_personality ( void ) {
2846 if ( personality ( PER_LINUX
) < 0 )
2847 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2852 #if defined(__linux__) && !defined(__OPTIMIZE__)
2854 pa_bool_t
pa_run_from_build_tree ( void ) {
2856 pa_bool_t b
= FALSE
;
2858 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2861 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2862 b
= pa_startswith ( rp
, PA_BUILDDIR
);
2871 const char * pa_get_temp_dir ( void ) {
2874 if (( t
= getenv ( "TMPDIR" )) &&
2875 pa_is_path_absolute ( t
))
2878 if (( t
= getenv ( "TMP" )) &&
2879 pa_is_path_absolute ( t
))
2882 if (( t
= getenv ( "TEMP" )) &&
2883 pa_is_path_absolute ( t
))
2886 if (( t
= getenv ( "TEMPDIR" )) &&
2887 pa_is_path_absolute ( t
))