]>
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 ( 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
= pa_open_cloexec ( fn
, O_CREAT
| O_RDWR
1207 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1208 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1212 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1213 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1217 if ( fstat ( fd
, & st
) < 0 ) {
1218 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1222 /* Check whether the file has been removed meanwhile. When yes,
1223 * restart this loop, otherwise, we're done */
1224 if ( st
. st_nlink
>= 1 )
1227 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1228 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1232 if ( pa_close ( fd
) < 0 ) {
1233 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1244 int saved_errno
= errno
;
1246 errno
= saved_errno
;
1252 /* Unlock a temporary lcok file */
1253 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1258 if ( unlink ( fn
) < 0 ) {
1259 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1264 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1265 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1269 if ( pa_close ( fd
) < 0 ) {
1270 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1277 static char * get_pulse_home ( void ) {
1282 if (!( h
= pa_get_home_dir_malloc ())) {
1283 pa_log_error ( "Failed to get home directory." );
1287 if ( stat ( h
, & st
) < 0 ) {
1288 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1292 if ( st
. st_uid
!= getuid ()) {
1293 pa_log_error ( "Home directory %s not ours." , h
);
1298 ret
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1306 char * pa_get_state_dir ( void ) {
1309 /* The state directory shall contain dynamic data that should be
1310 * kept across reboots, and is private to this user */
1312 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1313 if (!( d
= get_pulse_home ()))
1316 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1317 * dir then this will break. */
1319 if ( pa_make_secure_dir ( d
, 0700U , ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1320 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1328 char * pa_get_home_dir_malloc ( void ) {
1330 size_t allocated
= 128 ;
1333 homedir
= pa_xmalloc ( allocated
);
1335 if (! pa_get_home_dir ( homedir
, allocated
)) {
1340 if ( strlen ( homedir
) < allocated
- 1 )
1350 char * pa_get_binary_name_malloc ( void ) {
1352 size_t allocated
= 128 ;
1355 t
= pa_xmalloc ( allocated
);
1357 if (! pa_get_binary_name ( t
, allocated
)) {
1362 if ( strlen ( t
) < allocated
- 1 )
1372 static char * make_random_dir ( mode_t m
) {
1373 static const char table
[] =
1374 "abcdefghijklmnopqrstuvwxyz"
1375 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1381 fn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"pulse-XXXXXXXXXXXX" , pa_get_temp_dir ());
1382 pathlen
= strlen ( fn
);
1390 for ( i
= pathlen
- 12 ; i
< pathlen
; i
++)
1391 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1393 u
= umask ((~ m
) & 0777 );
1396 saved_errno
= errno
;
1398 errno
= saved_errno
;
1403 if ( errno
!= EEXIST
) {
1404 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1411 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1414 if (!( p
= make_random_dir ( m
)))
1417 if ( symlink ( p
, k
) < 0 ) {
1418 int saved_errno
= errno
;
1420 if ( errno
!= EEXIST
)
1421 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1426 errno
= saved_errno
;
1434 char * pa_get_runtime_dir ( void ) {
1435 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1439 /* The runtime directory shall contain dynamic data that needs NOT
1440 * to be kept accross reboots and is usuallly private to the user,
1441 * except in system mode, where it might be accessible by other
1442 * users, too. Since we need POSIX locking and UNIX sockets in
1443 * this directory, we link it to a random subdir in /tmp, if it
1444 * was not explicitly configured. */
1446 m
= pa_in_system_mode () ? 0755U : 0700U ;
1448 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1450 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1451 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1455 return pa_xstrdup ( d
);
1458 if (!( d
= get_pulse_home ()))
1461 if ( pa_make_secure_dir ( d
, m
, ( uid_t
) - 1 , ( gid_t
) - 1 ) < 0 ) {
1462 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1467 if (!( mid
= pa_machine_id ())) {
1472 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-runtime" , d
, mid
);
1477 /* OK, first let's check if the "runtime" symlink is already
1480 if (!( p
= pa_readlink ( k
))) {
1482 if ( errno
!= ENOENT
) {
1483 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1487 /* Hmm, so the runtime directory didn't exist yet, so let's
1488 * create one in /tmp and symlink that to it */
1490 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1492 /* Mhmm, maybe another process was quicker than us,
1493 * let's check if that was valid */
1494 if ( errno
== EEXIST
)
1503 /* Make sure that this actually makes sense */
1504 if (! pa_is_path_absolute ( p
)) {
1505 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1510 /* Hmm, so this symlink is still around, make sure nobody fools
1513 if ( lstat ( p
, & st
) < 0 ) {
1515 if ( errno
!= ENOENT
) {
1516 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1522 if ( S_ISDIR ( st
. st_mode
) &&
1523 ( st
. st_uid
== getuid ()) &&
1524 (( st
. st_mode
& 0777 ) == 0700 )) {
1530 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1536 /* Hmm, so the link points to some nonexisting or invalid
1537 * dir. Let's replace it by a new link. We first create a
1538 * temporary link and then rename that to allow concurrent
1539 * execution of this function. */
1541 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1543 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1545 if ( errno
!= EEXIST
) {
1546 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1553 /* Hmm, someone lese was quicker then us. Let's give
1554 * him some time to finish, and retry. */
1559 /* OK, we succeeded in creating the temporary symlink, so
1560 * let's rename it */
1561 if ( rename ( t
, k
) < 0 ) {
1562 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1578 /* Try to open a configuration file. If "env" is specified, open the
1579 * value of the specified environment variable. Otherwise look for a
1580 * file "local" in the home directory or a file "global" in global
1581 * file system. If "result" is non-NULL, a pointer to a newly
1582 * allocated buffer containing the used configuration file is
1584 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1589 if (! getenv ( PULSE_ROOTENV
))
1593 if ( env
&& ( fn
= getenv ( env
))) {
1597 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1598 /* FIXME: Needs to set errno! */
1603 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1605 * result
= pa_xstrdup ( fn
);
1610 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1620 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1621 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1622 else if (( h
= pa_get_home_dir_malloc ())) {
1623 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1629 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1630 /* FIXME: Needs to set errno! */
1637 if (( f
= pa_fopen_cloexec ( fn
, "r" ))) {
1639 * result
= pa_xstrdup ( fn
);
1645 if ( errno
!= ENOENT
) {
1646 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1658 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1659 /* FIXME: Needs to set errno! */
1664 if (( f
= pa_fopen_cloexec ( global
, "r" ))) {
1667 * result
= pa_xstrdup ( global
);
1677 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1682 if (! getenv ( PULSE_ROOTENV
))
1686 if ( env
&& ( fn
= getenv ( env
))) {
1689 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1690 /* FIXME: Needs to set errno! */
1695 if ( access ( fn
, R_OK
) == 0 )
1696 return pa_xstrdup ( fn
);
1698 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1707 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1708 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1709 else if (( h
= pa_get_home_dir_malloc ())) {
1710 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1716 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1717 /* FIXME: Needs to set errno! */
1724 if ( access ( fn
, R_OK
) == 0 ) {
1725 char * r
= pa_xstrdup ( fn
);
1730 if ( errno
!= ENOENT
) {
1731 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1741 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1742 /* FIXME: Needs to set errno! */
1747 if ( access ( global
, R_OK
) == 0 )
1748 return pa_xstrdup ( global
);
1756 /* Format the specified data as a hexademical string */
1757 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1758 size_t i
= 0 , j
= 0 ;
1759 const char hex
[] = "0123456789abcdef" ;
1763 pa_assert ( slength
> 0 );
1765 while ( i
< dlength
&& j
+ 3 <= slength
) {
1766 s
[ j
++] = hex
[* d
>> 4 ];
1767 s
[ j
++] = hex
[* d
& 0xF ];
1773 s
[ j
< slength
? j
: slength
] = 0 ;
1777 /* Convert a hexadecimal digit to a number or -1 if invalid */
1778 static int hexc ( char c
) {
1779 if ( c
>= '0' && c
<= '9' )
1782 if ( c
>= 'A' && c
<= 'F' )
1783 return c
- 'A' + 10 ;
1785 if ( c
>= 'a' && c
<= 'f' )
1786 return c
- 'a' + 10 ;
1792 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1793 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1799 while ( j
< dlength
&& * p
) {
1802 if (( b
= hexc (*( p
++))) < 0 )
1805 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1810 if (( b
= hexc (*( p
++))) < 0 )
1813 d
[ j
] |= ( uint8_t ) b
;
1820 /* Returns nonzero when *s starts with *pfx */
1821 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1829 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1832 /* Returns nonzero when *s ends with *sfx */
1833 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1842 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1845 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1851 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1855 char * pa_make_path_absolute ( const char * p
) {
1861 if ( pa_is_path_absolute ( p
))
1862 return pa_xstrdup ( p
);
1864 if (!( cwd
= pa_getcwd ()))
1865 return pa_xstrdup ( p
);
1867 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1872 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1873 * if fn is non-null and starts with / return fn
1874 * otherwise append fn to the run time path and return it */
1875 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1878 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1883 if ( pa_is_path_absolute ( fn
))
1884 return pa_xstrdup ( fn
);
1892 if (!( mid
= pa_machine_id ())) {
1897 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s-%s" , rtp
, mid
, fn
);
1900 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1908 char * pa_runtime_path ( const char * fn
) {
1909 return get_path ( fn
, FALSE
, TRUE
);
1912 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1913 return get_path ( fn
, appendmid
, FALSE
);
1916 /* Convert the string s to a signed integer in *ret_i */
1917 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1925 l
= strtol ( s
, & x
, 0 );
1927 if (! x
|| * x
|| errno
) {
1933 if (( int32_t ) l
!= l
) {
1938 * ret_i
= ( int32_t ) l
;
1943 /* Convert the string s to an unsigned integer in *ret_u */
1944 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1952 l
= strtoul ( s
, & x
, 0 );
1954 if (! x
|| * x
|| errno
) {
1960 if (( uint32_t ) l
!= l
) {
1965 * ret_u
= ( uint32_t ) l
;
1970 #ifdef HAVE_STRTOF_L
1971 static locale_t c_locale
= NULL
;
1973 static void c_locale_destroy ( void ) {
1974 freelocale ( c_locale
);
1978 int pa_atod ( const char * s
, double * ret_d
) {
1985 /* This should be locale independent */
1987 #ifdef HAVE_STRTOF_L
1991 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1992 atexit ( c_locale_destroy
);
1998 f
= strtod_l ( s
, & x
, c_locale
);
2006 if (! x
|| * x
|| errno
) {
2017 /* Same as snprintf, but guarantees NUL-termination on every platform */
2018 size_t pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
2023 pa_assert ( size
> 0 );
2026 va_start ( ap
, format
);
2027 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
2033 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
2034 size_t pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
2038 pa_assert ( size
> 0 );
2041 ret
= vsnprintf ( str
, size
, format
, ap
);
2048 if (( size_t ) ret
> size
- 1 )
2051 return ( size_t ) ret
;
2054 /* Truncate the specified string, but guarantee that the string
2055 * returned still validates as UTF8 */
2056 char * pa_truncate_utf8 ( char * c
, size_t l
) {
2058 pa_assert ( pa_utf8_valid ( c
));
2065 while ( l
> 0 && ! pa_utf8_valid ( c
))
2071 char * pa_getcwd ( void ) {
2075 char * p
= pa_xmalloc ( l
);
2079 if ( errno
!= ERANGE
)
2087 void * pa_will_need ( const void * p
, size_t l
) {
2088 #ifdef RLIMIT_MEMLOCK
2099 a
= PA_PAGE_ALIGN_PTR ( p
);
2100 size
= ( size_t ) (( const uint8_t *) p
+ l
- ( const uint8_t *) a
);
2102 #ifdef HAVE_POSIX_MADVISE
2103 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2104 pa_log_debug ( "posix_madvise() worked fine!" );
2109 /* Most likely the memory was not mmap()ed from a file and thus
2110 * madvise() didn't work, so let's misuse mlock() do page this
2111 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2112 * inviting, the man page of mlock() tells us: "All pages that
2113 * contain a part of the specified address range are guaranteed to
2114 * be resident in RAM when the call returns successfully." */
2116 #ifdef RLIMIT_MEMLOCK
2117 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2119 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2120 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
));
2125 bs
= PA_PAGE_ALIGN (( size_t ) rlim
. rlim_cur
);
2127 bs
= PA_PAGE_SIZE
* 4 ;
2130 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2133 while ( size
> 0 && bs
> 0 ) {
2138 if ( mlock ( a
, bs
) < 0 ) {
2139 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2143 pa_assert_se ( munlock ( a
, bs
) == 0 );
2145 a
= ( const uint8_t *) a
+ bs
;
2151 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2153 pa_log_debug ( "mlock() worked fine!" );
2158 void pa_close_pipe ( int fds
[ 2 ]) {
2162 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2165 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2167 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2170 char * pa_readlink ( const char * p
) {
2179 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2184 if (( size_t ) n
< l
- 1 ) {
2194 int pa_close_all ( int except_fd
, ...) {
2199 va_start ( ap
, except_fd
);
2202 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2207 p
= pa_xnew ( int , n
+ 1 );
2209 va_start ( ap
, except_fd
);
2212 if ( except_fd
>= 0 ) {
2216 while (( fd
= va_arg ( ap
, int )) >= 0 )
2223 r
= pa_close_allv ( p
);
2229 int pa_close_allv ( const int except_fds
[]) {
2237 if (( d
= opendir ( "/proc/self/fd" ))) {
2241 while (( de
= readdir ( d
))) {
2247 if ( de
-> d_name
[ 0 ] == '.' )
2251 l
= strtol ( de
-> d_name
, & e
, 10 );
2252 if ( errno
!= 0 || ! e
|| * e
) {
2260 if (( long ) fd
!= l
) {
2273 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2274 if ( except_fds
[ i
] == fd
) {
2282 if ( pa_close ( fd
) < 0 ) {
2283 saved_errno
= errno
;
2285 errno
= saved_errno
;
2297 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) >= 0 )
2298 maxfd
= ( int ) rl
. rlim_max
;
2300 maxfd
= sysconf ( _SC_OPEN_MAX
);
2302 for ( fd
= 3 ; fd
< maxfd
; fd
++) {
2307 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2308 if ( except_fds
[ i
] == fd
) {
2316 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2323 int pa_unblock_sigs ( int except
, ...) {
2328 va_start ( ap
, except
);
2331 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2336 p
= pa_xnew ( int , n
+ 1 );
2338 va_start ( ap
, except
);
2345 while (( sig
= va_arg ( ap
, int )) >= 0 )
2352 r
= pa_unblock_sigsv ( p
);
2358 int pa_unblock_sigsv ( const int except
[]) {
2362 if ( sigemptyset (& ss
) < 0 )
2365 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2366 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2369 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2372 int pa_reset_sigs ( int except
, ...) {
2377 va_start ( ap
, except
);
2380 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2385 p
= pa_xnew ( int , n
+ 1 );
2387 va_start ( ap
, except
);
2394 while (( sig
= va_arg ( ap
, int )) >= 0 )
2401 r
= pa_reset_sigsv ( p
);
2407 int pa_reset_sigsv ( const int except
[]) {
2410 for ( sig
= 1 ; sig
< NSIG
; sig
++) {
2411 pa_bool_t reset
= TRUE
;
2422 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2423 if ( sig
== except
[ i
]) {
2432 struct sigaction sa
;
2434 memset (& sa
, 0 , sizeof ( sa
));
2435 sa
. sa_handler
= SIG_DFL
;
2437 /* On Linux the first two RT signals are reserved by
2438 * glibc, and sigaction() will return EINVAL for them. */
2439 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2440 if ( errno
!= EINVAL
)
2448 void pa_set_env ( const char * key
, const char * value
) {
2452 /* This is not thread-safe */
2454 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2457 void pa_set_env_and_record ( const char * key
, const char * value
) {
2461 /* This is not thread-safe */
2463 pa_set_env ( key
, value
);
2464 recorded_env
= pa_strlist_prepend ( recorded_env
, key
);
2467 void pa_unset_env_recorded ( void ) {
2469 /* This is not thread-safe */
2474 recorded_env
= pa_strlist_pop ( recorded_env
, & s
);
2484 pa_bool_t
pa_in_system_mode ( void ) {
2487 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2493 char * pa_get_user_name_malloc ( void ) {
2497 #ifdef _SC_LOGIN_NAME_MAX
2498 k
= ( ssize_t
) sysconf ( _SC_LOGIN_NAME_MAX
);
2504 u
= pa_xnew ( char , k
+ 1 );
2506 if (!( pa_get_user_name ( u
, k
))) {
2514 char * pa_get_host_name_malloc ( void ) {
2523 if (! pa_get_host_name ( c
, l
)) {
2525 if ( errno
!= EINVAL
&& errno
!= ENAMETOOLONG
)
2528 } else if ( strlen ( c
) < l
- 1 ) {
2536 u
= pa_utf8_filter ( c
);
2541 /* Hmm, the hostname is as long the space we offered the
2542 * function, we cannot know if it fully fit in, so let's play
2543 * safe and retry. */
2552 char * pa_machine_id ( void ) {
2556 /* The returned value is supposed be some kind of ascii identifier
2557 * that is unique and stable across reboots. */
2559 /* First we try the D-Bus UUID, which is the best option we have,
2560 * since it fits perfectly our needs and is not as volatile as the
2561 * hostname which might be set from dhcp. */
2563 if (( f
= pa_fopen_cloexec ( PA_MACHINE_ID
, "r" ))) {
2564 char ln
[ 34 ] = "" , * r
;
2566 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2572 return pa_utf8_filter ( ln
);
2575 if (( h
= pa_get_host_name_malloc ()))
2578 /* If no hostname was set we use the POSIX hostid. It's usually
2579 * the IPv4 address. Might not be that stable. */
2580 return pa_sprintf_malloc ( "%08lx" , ( unsigned long ) gethostid
);
2583 char * pa_session_id ( void ) {
2586 if (!( e
= getenv ( "XDG_SESSION_COOKIE" )))
2589 return pa_utf8_filter ( e
);
2592 char * pa_uname_string ( void ) {
2595 pa_assert_se ( uname (& u
) >= 0 );
2597 return pa_sprintf_malloc ( "%s %s %s %s" , u
. sysname
, u
. machine
, u
. release
, u
. version
);
2600 #ifdef HAVE_VALGRIND_MEMCHECK_H
2601 pa_bool_t
pa_in_valgrind ( void ) {
2604 /* To make heisenbugs a bit simpler to find we check for $VALGRIND
2605 * here instead of really checking whether we run in valgrind or
2609 b
= getenv ( "VALGRIND" ) ? 2 : 1 ;
2615 unsigned pa_gcd ( unsigned a
, unsigned b
) {
2626 void pa_reduce ( unsigned * num
, unsigned * den
) {
2628 unsigned gcd
= pa_gcd (* num
, * den
);
2636 pa_assert ( pa_gcd (* num
, * den
) == 1 );
2639 unsigned pa_ncpus ( void ) {
2642 #ifdef _SC_NPROCESSORS_CONF
2643 ncpus
= sysconf ( _SC_NPROCESSORS_CONF
);
2648 return ncpus
<= 0 ? 1 : ( unsigned ) ncpus
;
2651 char * pa_replace ( const char * s
, const char * a
, const char * b
) {
2660 sb
= pa_strbuf_new ();
2665 if (!( p
= strstr ( s
, a
)))
2668 pa_strbuf_putsn ( sb
, s
, p
- s
);
2669 pa_strbuf_puts ( sb
, b
);
2673 pa_strbuf_puts ( sb
, s
);
2675 return pa_strbuf_tostring_free ( sb
);
2678 char * pa_escape ( const char * p
, const char * chars
) {
2681 pa_strbuf
* buf
= pa_strbuf_new ();
2683 for ( s
= p
; * s
; ++ s
) {
2685 pa_strbuf_putc ( buf
, ' \\ ' );
2687 for ( c
= chars
; * c
; ++ c
) {
2689 pa_strbuf_putc ( buf
, ' \\ ' );
2694 pa_strbuf_putc ( buf
, * s
);
2697 return pa_strbuf_tostring_free ( buf
);
2700 char * pa_unescape ( char * p
) {
2702 pa_bool_t escaped
= FALSE
;
2704 for ( s
= p
, d
= p
; * s
; s
++) {
2705 if (! escaped
&& * s
== ' \\ ' ) {
2719 char * pa_realpath ( const char * path
) {
2723 /* We want only abolsute paths */
2724 if ( path
[ 0 ] != '/' ) {
2729 #if defined(__GLIBC__) || defined(__APPLE__)
2733 if (!( r
= realpath ( path
, NULL
)))
2736 /* We copy this here in case our pa_xmalloc() is not
2737 * implemented on top of libc malloc() */
2741 #elif defined(PATH_MAX)
2744 path_buf
= pa_xmalloc ( PATH_MAX
);
2746 if (!( t
= realpath ( path
, path_buf
))) {
2752 #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."
2758 void pa_disable_sigpipe ( void ) {
2761 struct sigaction sa
;
2765 if ( sigaction ( SIGPIPE
, NULL
, & sa
) < 0 ) {
2766 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2770 sa
. sa_handler
= SIG_IGN
;
2772 if ( sigaction ( SIGPIPE
, & sa
, NULL
) < 0 ) {
2773 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
2779 void pa_xfreev ( void ** a
) {
2785 for ( p
= a
; * p
; p
++)
2791 char ** pa_split_spaces_strv ( const char * s
) {
2793 unsigned i
= 0 , n
= 8 ;
2794 const char * state
= NULL
;
2796 t
= pa_xnew ( char *, n
);
2797 while (( e
= pa_split_spaces ( s
, & state
))) {
2802 t
= pa_xrenew ( char *, t
, n
);
2815 char * pa_maybe_prefix_path ( const char * path
, const char * prefix
) {
2818 if ( pa_is_path_absolute ( path
))
2819 return pa_xstrdup ( path
);
2821 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , prefix
, path
);
2824 size_t pa_pipe_buf ( int fd
) {
2829 if (( n
= fpathconf ( fd
, _PC_PIPE_BUF
)) >= 0 )
2840 void pa_reset_personality ( void ) {
2843 if ( personality ( PER_LINUX
) < 0 )
2844 pa_log_warn ( "Uh, personality() failed: %s" , pa_cstrerror ( errno
));
2849 #if defined(__linux__) && !defined(__OPTIMIZE__)
2851 pa_bool_t
pa_run_from_build_tree ( void ) {
2853 pa_bool_t b
= FALSE
;
2855 /* We abuse __OPTIMIZE__ as a check whether we are a debug build
2858 if (( rp
= pa_readlink ( "/proc/self/exe" ))) {
2859 b
= pa_startswith ( rp
, PA_BUILDDIR
);
2868 const char * pa_get_temp_dir ( void ) {
2871 if (( t
= getenv ( "TMPDIR" )) &&
2872 pa_is_path_absolute ( t
))
2875 if (( t
= getenv ( "TMP" )) &&
2876 pa_is_path_absolute ( t
))
2879 if (( t
= getenv ( "TEMP" )) &&
2880 pa_is_path_absolute ( t
))
2883 if (( t
= getenv ( "TEMPDIR" )) &&
2884 pa_is_path_absolute ( t
))
2890 int pa_open_cloexec ( const char * fn
, int flags
, mode_t mode
) {
2898 if (( fd
= open ( fn
, flags
| O_CLOEXEC
, mode
)) >= 0 )
2901 if ( errno
!= EINVAL
)
2905 if (( fd
= open ( fn
, flags
, mode
)) < 0 )
2909 /* Some implementations might simply ignore O_CLOEXEC if it is not
2910 * understood, make sure FD_CLOEXEC is enabled anyway */
2912 pa_make_fd_cloexec ( fd
);
2916 int pa_socket_cloexec ( int domain
, int type
, int protocol
) {
2920 if (( fd
= socket ( domain
, type
| SOCK_CLOEXEC
, protocol
)) >= 0 )
2923 if ( errno
!= EINVAL
)
2927 if (( fd
= socket ( domain
, type
, protocol
)) < 0 )
2931 /* Some implementations might simply ignore SOCK_CLOEXEC if it is
2932 * not understood, make sure FD_CLOEXEC is enabled anyway */
2934 pa_make_fd_cloexec ( fd
);
2938 int pa_pipe_cloexec ( int pipefd
[ 2 ]) {
2942 if (( r
= pipe2 ( pipefd
, O_CLOEXEC
)) >= 0 )
2945 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
2950 if (( r
= pipe ( pipefd
)) < 0 )
2954 pa_make_fd_cloexec ( pipefd
[ 0 ]);
2955 pa_make_fd_cloexec ( pipefd
[ 1 ]);
2960 int pa_accept_cloexec ( int sockfd
, struct sockaddr
* addr
, socklen_t
* addrlen
) {
2964 if (( fd
= accept4 ( sockfd
, addr
, addrlen
, SOCK_CLOEXEC
)) >= 0 )
2967 if ( errno
!= EINVAL
&& errno
!= ENOSYS
)
2972 if (( fd
= accept ( sockfd
, addr
, addrlen
)) < 0 )
2976 pa_make_fd_cloexec ( fd
);
2980 FILE * pa_fopen_cloexec ( const char * path
, const char * mode
) {
2984 m
= pa_sprintf_malloc ( "%se" , mode
);
2987 if (( f
= fopen ( path
, m
))) {
2994 if ( errno
!= EINVAL
)
2997 if (!( f
= fopen ( path
, mode
)))
3001 pa_make_fd_cloexec ( fileno ( f
));
3005 void pa_nullify_stdfds ( void ) {
3008 pa_close ( STDIN_FILENO
);
3009 pa_close ( STDOUT_FILENO
);
3010 pa_close ( STDERR_FILENO
);
3012 pa_assert_se ( open ( "/dev/null" , O_RDONLY
) == STDIN_FILENO
);
3013 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDOUT_FILENO
);
3014 pa_assert_se ( open ( "/dev/null" , O_WRONLY
) == STDERR_FILENO
);
3021 char * pa_read_line_from_file ( const char * fn
) {
3023 char ln
[ 256 ] = "" , * r
;
3025 if (!( f
= pa_fopen_cloexec ( fn
, "r" )))
3028 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
3037 return pa_xstrdup ( ln
);
3040 pa_bool_t
pa_running_in_vm ( void ) {
3042 #if defined(__i386__) || defined(__x86_64__)
3044 /* Both CPUID and DMI are x86 specific interfaces... */
3046 uint32_t eax
= 0x40000000 ;
3053 const char * const dmi_vendors
[] = {
3054 "/sys/class/dmi/id/sys_vendor" ,
3055 "/sys/class/dmi/id/board_vendor" ,
3056 "/sys/class/dmi/id/bios_vendor"
3061 for ( i
= 0 ; i
< PA_ELEMENTSOF ( dmi_vendors
); i
++) {
3064 if (( s
= pa_read_line_from_file ( dmi_vendors
[ i
]))) {
3066 if ( pa_startswith ( s
, "QEMU" ) ||
3067 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3068 pa_startswith ( s
, "VMware" ) ||
3069 pa_startswith ( s
, "VMW" ) ||
3070 pa_startswith ( s
, "Microsoft Corporation" ) ||
3071 pa_startswith ( s
, "innotek GmbH" ) ||
3072 pa_startswith ( s
, "Xen" )) {
3084 /* http://lwn.net/Articles/301888/ */
3087 __asm__
__volatile__ (
3088 " xor %%ebx, %%ebx \n\t "
3091 : "=a" ( eax
), "=b" ( sig
. sig32
[ 0 ]), "=c" ( sig
. sig32
[ 1 ]), "=d" ( sig
. sig32
[ 2 ])
3095 if ( pa_streq ( sig
. text
, "XenVMMXenVMM" ) ||
3096 pa_streq ( sig
. text
, "KVMKVMKVM" ) ||
3097 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
3098 pa_streq ( sig
. text
, "VMwareVMware" ) ||
3099 /* http://msdn.microsoft.com/en-us/library/bb969719.aspx */
3100 pa_streq ( sig
. text
, "Microsoft Hv" ))