]>
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>
54 #ifdef HAVE_SYS_RESOURCE_H
55 #include <sys/resource.h>
58 #ifdef HAVE_SYS_CAPABILITY_H
59 #include <sys/capability.h>
62 #ifdef HAVE_SYS_MMAN_H
86 #ifdef HAVE_LIBSAMPLERATE
87 #include <samplerate.h>
90 #include <pulse/xmalloc.h>
91 #include <pulse/util.h>
92 #include <pulse/utf8.h>
94 #include <pulsecore/core-error.h>
95 #include <pulsecore/winsock.h>
96 #include <pulsecore/log.h>
97 #include <pulsecore/macro.h>
98 #include <pulsecore/thread.h>
100 #include "core-util.h"
102 /* Not all platforms have this */
104 #define MSG_NOSIGNAL 0
109 #define PULSE_ROOTENV "PULSE_ROOT"
111 int pa_set_root ( HANDLE handle
) {
112 char library_path
[ MAX_PATH
+ sizeof ( PULSE_ROOTENV
) + 1 ], * sep
;
114 strcpy ( library_path
, PULSE_ROOTENV
"=" );
116 /* FIXME: Needs to set errno */
118 if (! GetModuleFileName ( handle
, library_path
+ sizeof ( PULSE_ROOTENV
), MAX_PATH
))
121 sep
= strrchr ( library_path
, PA_PATH_SEP_CHAR
);
125 if ( _putenv ( library_path
) < 0 )
133 /** Make a file descriptor nonblock. Doesn't do any error checking */
134 void pa_make_fd_nonblock ( int fd
) {
140 pa_assert_se (( v
= fcntl ( fd
, F_GETFL
)) >= 0 );
142 if (!( v
& O_NONBLOCK
))
143 pa_assert_se ( fcntl ( fd
, F_SETFL
, v
| O_NONBLOCK
) >= 0 );
145 #elif defined(OS_IS_WIN32)
147 if ( ioctlsocket ( fd
, FIONBIO
, & arg
) < 0 ) {
148 pa_assert_se ( WSAGetLastError () == WSAENOTSOCK
);
149 pa_log_warn ( "Only sockets can be made non-blocking!" );
152 pa_log_warn ( "Non-blocking I/O not supported.!" );
157 /* Set the FD_CLOEXEC flag for a fd */
158 void pa_make_fd_cloexec ( int fd
) {
164 pa_assert_se (( v
= fcntl ( fd
, F_GETFD
, 0 )) >= 0 );
166 if (!( v
& FD_CLOEXEC
))
167 pa_assert_se ( fcntl ( fd
, F_SETFD
, v
| FD_CLOEXEC
) >= 0 );
172 /** Creates a directory securely */
173 int pa_make_secure_dir ( const char * dir
, mode_t m
, uid_t uid
, gid_t gid
) {
184 u
= umask ((~ m
) & 0777 );
190 if ( r
< 0 && errno
!= EEXIST
)
194 if ( uid
== ( uid_t
)- 1 )
196 if ( gid
== ( gid_t
)- 1 )
198 ( void ) chown ( dir
, uid
, gid
);
206 if ( lstat ( dir
, & st
) < 0 )
208 if ( stat ( dir
, & st
) < 0 )
213 if (! S_ISDIR ( st
. st_mode
) ||
214 ( st
. st_uid
!= uid
) ||
215 ( st
. st_gid
!= gid
) ||
216 (( st
. st_mode
& 0777 ) != m
)) {
221 pa_log_warn ( "Secure directory creation not supported on Win32." );
234 /* Return a newly allocated sting containing the parent directory of the specified file */
235 char * pa_parent_dir ( const char * fn
) {
236 char * slash
, * dir
= pa_xstrdup ( fn
);
238 if (( slash
= ( char *) pa_path_get_filename ( dir
)) == dir
) {
248 /* Creates a the parent directory of the specified path securely */
249 int pa_make_secure_parent_dir ( const char * fn
, mode_t m
, uid_t uid
, gid_t gid
) {
253 if (!( dir
= pa_parent_dir ( fn
)))
256 if ( pa_make_secure_dir ( dir
, m
, uid
, gid
) < 0 )
266 /** Platform independent read function. Necessary since not all
267 * systems treat all file descriptors equal. If type is
268 * non-NULL it is used to cache the type of the fd. This is
269 * useful for making sure that only a single syscall is executed per
270 * function call. The variable pointed to should be initialized to 0
272 ssize_t
pa_read ( int fd
, void * buf
, size_t count
, int * type
) {
276 if (! type
|| * type
== 0 ) {
279 if (( r
= recv ( fd
, buf
, count
, 0 )) >= 0 )
282 if ( WSAGetLastError () != WSAENOTSOCK
) {
283 errno
= WSAGetLastError ();
293 return read ( fd
, buf
, count
);
296 /** Similar to pa_read(), but handles writes */
297 ssize_t
pa_write ( int fd
, const void * buf
, size_t count
, int * type
) {
299 if (! type
|| * type
== 0 ) {
302 if (( r
= send ( fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0 )
306 if ( WSAGetLastError () != WSAENOTSOCK
) {
307 errno
= WSAGetLastError ();
311 if ( errno
!= ENOTSOCK
)
319 return write ( fd
, buf
, count
);
322 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
323 * unless EOF is reached or an error occured */
324 ssize_t
pa_loop_read ( int fd
, void * data
, size_t size
, int * type
) {
340 if (( r
= pa_read ( fd
, data
, size
, type
)) < 0 )
347 data
= ( uint8_t *) data
+ r
;
354 /** Similar to pa_loop_read(), but wraps write() */
355 ssize_t
pa_loop_write ( int fd
, const void * data
, size_t size
, int * type
) {
371 if (( r
= pa_write ( fd
, data
, size
, type
)) < 0 )
378 data
= ( const uint8_t *) data
+ r
;
385 /** Platform independent read function. Necessary since not all
386 * systems treat all file descriptors equal. */
387 int pa_close ( int fd
) {
392 if (( ret
= closesocket ( fd
)) == 0 )
395 if ( WSAGetLastError () != WSAENOTSOCK
) {
396 errno
= WSAGetLastError ();
404 /* Print a warning messages in case that the given signal is not
405 * blocked or trapped */
406 void pa_check_signal_is_blocked ( int sig
) {
407 #ifdef HAVE_SIGACTION
411 /* If POSIX threads are supported use thread-aware
412 * pthread_sigmask() function, to check if the signal is
413 * blocked. Otherwise fall back to sigprocmask() */
416 if ( pthread_sigmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
418 if ( sigprocmask ( SIG_SETMASK
, NULL
, & set
) < 0 ) {
419 pa_log ( "sigprocmask(): %s" , pa_cstrerror ( errno
));
426 if ( sigismember (& set
, sig
))
429 /* Check whether the signal is trapped */
431 if ( sigaction ( sig
, NULL
, & sa
) < 0 ) {
432 pa_log ( "sigaction(): %s" , pa_cstrerror ( errno
));
436 if ( sa
. sa_handler
!= SIG_DFL
)
439 pa_log_warn ( "%s is not trapped. This might cause malfunction!" , pa_sig2str ( sig
));
440 #else /* HAVE_SIGACTION */
441 pa_log_warn ( "%s might not be trapped. This might cause malfunction!" , pa_sig2str ( sig
));
445 /* The following function is based on an example from the GNU libc
446 * documentation. This function is similar to GNU's asprintf(). */
447 char * pa_sprintf_malloc ( const char * format
, ...) {
457 c
= pa_xrealloc ( c
, size
);
459 va_start ( ap
, format
);
460 r
= vsnprintf ( c
, size
, format
, ap
);
465 if ( r
> - 1 && r
< size
)
468 if ( r
> - 1 ) /* glibc 2.1 */
475 /* Same as the previous function, but use a va_list instead of an
477 char * pa_vsprintf_malloc ( const char * format
, va_list ap
) {
487 c
= pa_xrealloc ( c
, size
);
490 r
= vsnprintf ( c
, size
, format
, aq
);
495 if ( r
> - 1 && r
< size
)
498 if ( r
> - 1 ) /* glibc 2.1 */
505 /* Similar to OpenBSD's strlcpy() function */
506 char * pa_strlcpy ( char * b
, const char * s
, size_t l
) {
516 /* Make the current thread a realtime thread, and acquire the highest
517 * rtprio we can get that is less or equal the specified parameter. If
518 * the thread is already realtime, don't do anything. */
519 int pa_make_realtime ( int rtprio
) {
521 #ifdef _POSIX_PRIORITY_SCHEDULING
522 struct sched_param sp
;
525 memset (& sp
, 0 , sizeof ( sp
));
528 if (( r
= pthread_getschedparam ( pthread_self (), & policy
, & sp
)) != 0 ) {
529 pa_log ( "pthread_getschedgetparam(): %s" , pa_cstrerror ( r
));
533 if ( policy
== SCHED_FIFO
&& sp
. sched_priority
>= rtprio
) {
534 pa_log_info ( "Thread already being scheduled with SCHED_FIFO with priority %i." , sp
. sched_priority
);
538 sp
. sched_priority
= rtprio
;
539 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) != 0 ) {
541 while ( sp
. sched_priority
> 1 ) {
542 sp
. sched_priority
--;
544 if (( r
= pthread_setschedparam ( pthread_self (), SCHED_FIFO
, & sp
)) == 0 ) {
545 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i, which is lower than the requested %i." , sp
. sched_priority
, rtprio
);
550 pa_log_warn ( "pthread_setschedparam(): %s" , pa_cstrerror ( r
));
554 pa_log_info ( "Successfully enabled SCHED_FIFO scheduling for thread, with priority %i." , sp
. sched_priority
);
563 /* This is merely used for giving the user a hint. This is not correct
564 * for anything security related */
565 pa_bool_t
pa_can_realtime ( void ) {
570 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
574 if ( getrlimit ( RLIMIT_RTPRIO
, & rl
) >= 0 )
575 if ( rl
. rlim_cur
> 0 || rl
. rlim_cur
== RLIM_INFINITY
)
580 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
584 if (( cap
= cap_get_proc ())) {
585 cap_flag_value_t flag
= CAP_CLEAR
;
587 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
588 if ( flag
== CAP_SET
) {
601 /* This is merely used for giving the user a hint. This is not correct
602 * for anything security related */
603 pa_bool_t
pa_can_high_priority ( void ) {
608 #if defined(HAVE_SYS_RESOURCE_H) && defined(RLIMIT_RTPRIO)
612 if ( getrlimit ( RLIMIT_NICE
, & rl
) >= 0 )
613 if ( rl
. rlim_cur
>= 21 || rl
. rlim_cur
== RLIM_INFINITY
)
618 #if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_NICE)
622 if (( cap
= cap_get_proc ())) {
623 cap_flag_value_t flag
= CAP_CLEAR
;
625 if ( cap_get_flag ( cap
, CAP_SYS_NICE
, CAP_EFFECTIVE
, & flag
) >= 0 )
626 if ( flag
== CAP_SET
) {
639 /* Raise the priority of the current process as much as possible that
640 * is <= the specified nice level..*/
641 int pa_raise_priority ( int nice_level
) {
643 #ifdef HAVE_SYS_RESOURCE_H
644 if ( setpriority ( PRIO_PROCESS
, 0 , nice_level
) < 0 ) {
647 for ( n
= nice_level
+ 1 ; n
< 0 ; n
++) {
649 if ( setpriority ( PRIO_PROCESS
, 0 , n
) == 0 ) {
650 pa_log_info ( "Successfully acquired nice level %i, which is lower than the requested %i." , n
, nice_level
);
655 pa_log_warn ( "setpriority(): %s" , pa_cstrerror ( errno
));
659 pa_log_info ( "Successfully gained nice level %i." , nice_level
);
663 if ( nice_level
< 0 ) {
664 if (! SetPriorityClass ( GetCurrentProcess (), HIGH_PRIORITY_CLASS
)) {
665 pa_log_warn ( "SetPriorityClass() failed: 0x%08X" , GetLastError ());
669 pa_log_info ( "Successfully gained high priority class." );
676 /* Reset the priority to normal, inverting the changes made by
677 * pa_raise_priority() and pa_make_realtime()*/
678 void pa_reset_priority ( void ) {
679 #ifdef HAVE_SYS_RESOURCE_H
680 struct sched_param sp
;
682 setpriority ( PRIO_PROCESS
, 0 , 0 );
684 memset (& sp
, 0 , sizeof ( sp
));
685 pa_assert_se ( pthread_setschedparam ( pthread_self (), SCHED_OTHER
, & sp
) == 0 );
689 SetPriorityClass ( GetCurrentProcess (), NORMAL_PRIORITY_CLASS
);
693 static int match ( const char * expr
, const char * v
) {
697 if ( regcomp (& re
, expr
, REG_NOSUB
| REG_EXTENDED
) != 0 ) {
702 if (( k
= regexec (& re
, v
, 0 , NULL
, 0 )) == 0 )
704 else if ( k
== REG_NOMATCH
)
711 /* Try to parse a boolean string value.*/
712 int pa_parse_boolean ( const char * v
) {
717 /* First we check language independant */
718 if (! strcmp ( v
, "1" ) || v
[ 0 ] == 'y' || v
[ 0 ] == 'Y' || v
[ 0 ] == 't' || v
[ 0 ] == 'T' || ! strcasecmp ( v
, "on" ))
720 else if (! strcmp ( v
, "0" ) || v
[ 0 ] == 'n' || v
[ 0 ] == 'N' || v
[ 0 ] == 'f' || v
[ 0 ] == 'F' || ! strcasecmp ( v
, "off" ))
723 /* And then we check language dependant */
724 if (( expr
= nl_langinfo ( YESEXPR
)))
726 if (( r
= match ( expr
, v
)) > 0 )
729 if (( expr
= nl_langinfo ( NOEXPR
)))
731 if (( r
= match ( expr
, v
)) > 0 )
738 /* Split the specified string wherever one of the strings in delimiter
739 * occurs. Each time it is called returns a newly allocated string
740 * with pa_xmalloc(). The variable state points to, should be
741 * initiallized to NULL before the first call. */
742 char * pa_split ( const char * c
, const char * delimiter
, const char ** state
) {
743 const char * current
= * state
? * state
: c
;
749 l
= strcspn ( current
, delimiter
);
755 return pa_xstrndup ( current
, l
);
758 /* What is interpreted as whitespace? */
759 #define WHITESPACE " \t\n "
761 /* Split a string into words. Otherwise similar to pa_split(). */
762 char * pa_split_spaces ( const char * c
, const char ** state
) {
763 const char * current
= * state
? * state
: c
;
766 if (!* current
|| * c
== 0 )
769 current
+= strspn ( current
, WHITESPACE
);
770 l
= strcspn ( current
, WHITESPACE
);
774 return pa_xstrndup ( current
, l
);
777 PA_STATIC_TLS_DECLARE ( signame
, pa_xfree
);
779 /* Return the name of an UNIX signal. Similar to Solaris sig2str() */
780 const char * pa_sig2str ( int sig
) {
793 char buf
[ SIG2STR_MAX
];
795 if ( sig2str ( sig
, buf
) == 0 ) {
796 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
797 t
= pa_sprintf_malloc ( "SIG%s" , buf
);
798 PA_STATIC_TLS_SET ( signame
, t
);
806 case SIGHUP
: return "SIGHUP" ;
808 case SIGINT
: return "SIGINT" ;
810 case SIGQUIT
: return "SIGQUIT" ;
812 case SIGILL
: return "SIGULL" ;
814 case SIGTRAP
: return "SIGTRAP" ;
816 case SIGABRT
: return "SIGABRT" ;
818 case SIGBUS
: return "SIGBUS" ;
820 case SIGFPE
: return "SIGFPE" ;
822 case SIGKILL
: return "SIGKILL" ;
825 case SIGUSR1
: return "SIGUSR1" ;
827 case SIGSEGV
: return "SIGSEGV" ;
829 case SIGUSR2
: return "SIGUSR2" ;
832 case SIGPIPE
: return "SIGPIPE" ;
835 case SIGALRM
: return "SIGALRM" ;
837 case SIGTERM
: return "SIGTERM" ;
839 case SIGSTKFLT
: return "SIGSTKFLT" ;
842 case SIGCHLD
: return "SIGCHLD" ;
845 case SIGCONT
: return "SIGCONT" ;
848 case SIGSTOP
: return "SIGSTOP" ;
851 case SIGTSTP
: return "SIGTSTP" ;
854 case SIGTTIN
: return "SIGTTIN" ;
857 case SIGTTOU
: return "SIGTTOU" ;
860 case SIGURG
: return "SIGURG" ;
863 case SIGXCPU
: return "SIGXCPU" ;
866 case SIGXFSZ
: return "SIGXFSZ" ;
869 case SIGVTALRM
: return "SIGVTALRM" ;
872 case SIGPROF
: return "SIGPROF" ;
875 case SIGWINCH
: return "SIGWINCH" ;
878 case SIGIO
: return "SIGIO" ;
881 case SIGPWR
: return "SIGPWR" ;
884 case SIGSYS
: return "SIGSYS" ;
889 if ( sig
>= SIGRTMIN
&& sig
<= SIGRTMAX
) {
890 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
891 t
= pa_sprintf_malloc ( "SIGRTMIN+%i" , sig
- SIGRTMIN
);
892 PA_STATIC_TLS_SET ( signame
, t
);
901 pa_xfree ( PA_STATIC_TLS_GET ( signame
));
902 t
= pa_sprintf_malloc ( "SIG%i" , sig
);
903 PA_STATIC_TLS_SET ( signame
, t
);
909 /* Check whether the specified GID and the group name match */
910 static int is_group ( gid_t gid
, const char * name
) {
911 struct group group
, * result
= NULL
;
916 #ifdef HAVE_GETGRGID_R
917 #ifdef _SC_GETGR_R_SIZE_MAX
918 n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
925 data
= pa_xmalloc ( n
);
928 if ( getgrgid_r ( gid
, & group
, data
, n
, & result
) < 0 || ! result
) {
929 pa_log ( "getgrgid_r(%u): %s" , ( unsigned ) gid
, pa_cstrerror ( errno
));
937 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
942 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
943 * support getgrgid_r. */
946 if (( result
= getgrgid ( gid
)) == NULL
) {
947 pa_log ( "getgrgid(%u): %s" , gid
, pa_cstrerror ( errno
));
955 r
= strcmp ( name
, result
-> gr_name
) == 0 ;
963 /* Check the current user is member of the specified group */
964 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
965 GETGROUPS_T
* gids
, tgid
;
966 int n
= sysconf ( _SC_NGROUPS_MAX
);
971 gids
= pa_xmalloc ( sizeof ( GETGROUPS_T
)* n
);
973 if (( n
= getgroups ( n
, gids
)) < 0 ) {
974 pa_log ( "getgroups(): %s" , pa_cstrerror ( errno
));
978 for ( i
= 0 ; i
< n
; i
++) {
980 if (( k
= is_group ( gids
[ i
], name
)) < 0 )
989 if (( k
= is_group ( tgid
= getgid (), name
)) < 0 )
1005 /* Check whether the specifc user id is a member of the specified group */
1006 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1007 char * g_buf
, * p_buf
;
1009 struct group grbuf
, * gr
;
1013 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1014 g_buf
= pa_xmalloc ( g_n
);
1016 p_n
= sysconf ( _SC_GETPW_R_SIZE_MAX
);
1017 p_buf
= pa_xmalloc ( p_n
);
1020 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
) {
1029 for ( i
= gr
-> gr_mem
; * i
; i
++) {
1030 struct passwd pwbuf
, * pw
;
1033 if ( getpwnam_r (* i
, & pwbuf
, p_buf
, ( size_t ) p_n
, & pw
) != 0 || ! pw
)
1036 if ( pw
-> pw_uid
== uid
) {
1049 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
1050 gid_t
pa_get_gid_of_group ( const char * name
) {
1051 gid_t ret
= ( gid_t
) - 1 ;
1054 struct group grbuf
, * gr
;
1056 g_n
= sysconf ( _SC_GETGR_R_SIZE_MAX
);
1057 g_buf
= pa_xmalloc ( g_n
);
1060 if ( getgrnam_r ( name
, & grbuf
, g_buf
, ( size_t ) g_n
, & gr
) != 0 || ! gr
) {
1075 int pa_check_in_group ( gid_t g
) {
1076 gid_t gids
[ NGROUPS_MAX
];
1079 if (( r
= getgroups ( NGROUPS_MAX
, gids
)) < 0 )
1089 #else /* HAVE_GRP_H */
1091 int pa_own_uid_in_group ( const char * name
, gid_t
* gid
) {
1097 int pa_uid_in_group ( uid_t uid
, const char * name
) {
1102 gid_t
pa_get_gid_of_group ( const char * name
) {
1107 int pa_check_in_group ( gid_t g
) {
1114 /* Lock or unlock a file entirely.
1115 (advisory on UNIX, mandatory on Windows) */
1116 int pa_lock_fd ( int fd
, int b
) {
1120 /* Try a R/W lock first */
1122 flock
. l_type
= b
? F_WRLCK
: F_UNLCK
;
1123 flock
. l_whence
= SEEK_SET
;
1127 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1130 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
1131 if ( b
&& errno
== EBADF
) {
1132 flock
. l_type
= F_RDLCK
;
1133 if ( fcntl ( fd
, F_SETLKW
, & flock
) >= 0 )
1137 pa_log ( "%slock: %s" , ! b
? "un" : "" , pa_cstrerror ( errno
));
1141 HANDLE h
= ( HANDLE
) _get_osfhandle ( fd
);
1143 if ( b
&& LockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1145 if (! b
&& UnlockFile ( h
, 0 , 0 , 0xFFFFFFFF , 0xFFFFFFFF ))
1148 pa_log ( "%slock failed: 0x%08X" , ! b
? "un" : "" , GetLastError ());
1150 /* FIXME: Needs to set errno! */
1156 /* Remove trailing newlines from a string */
1157 char * pa_strip_nl ( char * s
) {
1160 s
[ strcspn ( s
, " \r\n " )] = 0 ;
1164 /* Create a temporary lock file and lock it. */
1165 int pa_lock_lockfile ( const char * fn
) {
1172 if (( fd
= open ( fn
, O_CREAT
| O_RDWR
1179 , S_IRUSR
| S_IWUSR
)) < 0 ) {
1180 pa_log_warn ( "Failed to create lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1184 if ( pa_lock_fd ( fd
, 1 ) < 0 ) {
1185 pa_log_warn ( "Failed to lock file '%s'." , fn
);
1189 if ( fstat ( fd
, & st
) < 0 ) {
1190 pa_log_warn ( "Failed to fstat() file '%s': %s" , fn
, pa_cstrerror ( errno
));
1194 /* Check wheter the file has been removed meanwhile. When yes,
1195 * restart this loop, otherwise, we're done */
1196 if ( st
. st_nlink
>= 1 )
1199 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1200 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1204 if ( pa_close ( fd
) < 0 ) {
1205 pa_log_warn ( "Failed to close file '%s': %s" , fn
, pa_cstrerror ( errno
));
1218 int saved_errno
= errno
;
1220 errno
= saved_errno
;
1226 /* Unlock a temporary lcok file */
1227 int pa_unlock_lockfile ( const char * fn
, int fd
) {
1232 if ( unlink ( fn
) < 0 ) {
1233 pa_log_warn ( "Unable to remove lock file '%s': %s" , fn
, pa_cstrerror ( errno
));
1238 if ( pa_lock_fd ( fd
, 0 ) < 0 ) {
1239 pa_log_warn ( "Failed to unlock file '%s'." , fn
);
1243 if ( pa_close ( fd
) < 0 ) {
1244 pa_log_warn ( "Failed to close '%s': %s" , fn
, pa_cstrerror ( errno
));
1251 static char * get_pulse_home ( void ) {
1255 if (! pa_get_home_dir ( h
, sizeof ( h
))) {
1256 pa_log_error ( "Failed to get home directory." );
1260 if ( stat ( h
, & st
) < 0 ) {
1261 pa_log_error ( "Failed to stat home directory %s: %s" , h
, pa_cstrerror ( errno
));
1265 if ( st
. st_uid
!= getuid ()) {
1266 pa_log_error ( "Home directory %s not ours." , h
);
1271 return pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" , h
);
1274 char * pa_get_state_dir ( void ) {
1277 /* The state directory shall contain dynamic data that should be
1278 * kept across reboots, and is private to this user */
1280 if (!( d
= pa_xstrdup ( getenv ( "PULSE_STATE_PATH" ))))
1281 if (!( d
= get_pulse_home ()))
1284 /* If PULSE_STATE_PATH and PULSE_RUNTIME_PATH point to the same
1285 * dir then this will break. */
1287 if ( pa_make_secure_dir ( d
, 0700 , ( pid_t
) - 1 , ( pid_t
) - 1 ) < 0 ) {
1288 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1296 static char * make_random_dir ( mode_t m
) {
1297 static const char table
[] =
1298 "abcdefghijklmnopqrstuvwxyz"
1299 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1302 char fn
[ 24 ] = "/tmp/pulse-" ;
1304 fn
[ sizeof ( fn
)- 1 ] = 0 ;
1312 for ( i
= 11 ; i
< sizeof ( fn
)- 1 ; i
++)
1313 fn
[ i
] = table
[ rand () % ( sizeof ( table
)- 1 )];
1315 u
= umask ((~ m
) & 0777 );
1317 saved_errno
= errno
;
1321 return pa_xstrdup ( fn
);
1323 errno
= saved_errno
;
1325 if ( errno
!= EEXIST
) {
1326 pa_log_error ( "Failed to create random directory %s: %s" , fn
, pa_cstrerror ( errno
));
1332 static int make_random_dir_and_link ( mode_t m
, const char * k
) {
1335 if (!( p
= make_random_dir ( m
)))
1338 if ( symlink ( p
, k
) < 0 ) {
1339 int saved_errno
= errno
;
1341 if ( errno
!= EEXIST
)
1342 pa_log_error ( "Failed to symlink %s to %s: %s" , k
, p
, pa_cstrerror ( errno
));
1347 errno
= saved_errno
;
1354 char * pa_get_runtime_dir ( void ) {
1355 char * d
, * k
= NULL
, * p
= NULL
, * t
= NULL
, * mid
;
1358 /* The runtime directory shall contain dynamic data that needs NOT
1359 * to be kept accross reboots and is usuallly private to the user,
1360 * except in system mode, where it might be accessible by other
1361 * users, too. Since we need POSIX locking and UNIX sockets in
1362 * this directory, we link it to a random subdir in /tmp, if it
1363 * was not explicitly configured. */
1365 if (( d
= getenv ( "PULSE_RUNTIME_PATH" ))) {
1368 m
= pa_in_system_mode () ? 0755 : 0700 ;
1370 if ( pa_make_secure_dir ( d
, m
, ( pid_t
) - 1 , ( pid_t
) - 1 ) < 0 ) {
1371 pa_log_error ( "Failed to create secure directory: %s" , pa_cstrerror ( errno
));
1375 return pa_xstrdup ( d
);
1378 if (!( d
= get_pulse_home ()))
1381 if (!( mid
= pa_machine_id ())) {
1386 k
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:runtime" , d
, mid
);
1391 /* OK, first let's check if the "runtime" symlink is already
1394 if (!( p
= pa_readlink ( k
))) {
1396 if ( errno
!= ENOENT
) {
1397 pa_log_error ( "Failed to stat runtime directory %s: %s" , k
, pa_cstrerror ( errno
));
1401 /* Hmm, so the runtime directory didn't exist yet, so let's
1402 * create one in /tmp and symlink that to it */
1404 if ( make_random_dir_and_link ( 0700 , k
) < 0 ) {
1406 /* Mhmm, maybe another process was quicker than us,
1407 * let's check if that was valid */
1408 if ( errno
== EEXIST
)
1417 /* Make sure that this actually makes sense */
1418 if (! pa_is_path_absolute ( p
)) {
1419 pa_log_error ( "Path %s in link %s is not absolute." , p
, k
);
1424 /* Hmm, so this symlink is still around, make sure nobody fools
1427 if ( lstat ( p
, & st
) < 0 ) {
1429 if ( errno
!= ENOENT
) {
1430 pa_log_error ( "Failed to stat runtime directory %s: %s" , p
, pa_cstrerror ( errno
));
1436 if ( S_ISDIR ( st
. st_mode
) &&
1437 ( st
. st_uid
== getuid ()) &&
1438 (( st
. st_mode
& 0777 ) == 0700 )) {
1444 pa_log_info ( "Hmm, runtime path exists, but points to an invalid directory. Changing runtime directory." );
1450 /* Hmm, so the link points to some nonexisting or invalid
1451 * dir. Let's replace it by a new link. We first create a
1452 * temporary link and then rename that to allow concurrent
1453 * execution of this function. */
1455 t
= pa_sprintf_malloc ( "%s.tmp" , k
);
1457 if ( make_random_dir_and_link ( 0700 , t
) < 0 ) {
1459 if ( errno
!= EEXIST
) {
1460 pa_log_error ( "Failed to symlink %s: %s" , t
, pa_cstrerror ( errno
));
1467 /* Hmm, someone lese was quicker then us. Let's give
1468 * him some time to finish, and retry. */
1473 /* OK, we succeeded in creating the temporary symlink, so
1474 * let's rename it */
1475 if ( rename ( t
, k
) < 0 ) {
1476 pa_log_error ( "Failed to rename %s to %s: %s" , t
, k
, pa_cstrerror ( errno
));
1492 /* Try to open a configuration file. If "env" is specified, open the
1493 * value of the specified environment variable. Otherwise look for a
1494 * file "local" in the home directory or a file "global" in global
1495 * file system. If "result" is non-NULL, a pointer to a newly
1496 * allocated buffer containing the used configuration file is
1498 FILE * pa_open_config_file ( const char * global
, const char * local
, const char * env
, char ** result
) {
1503 if (! getenv ( PULSE_ROOTENV
))
1507 if ( env
&& ( fn
= getenv ( env
))) {
1511 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1512 /* FIXME: Needs to set errno! */
1517 if (( f
= fopen ( fn
, "r" ))) {
1519 * result
= pa_xstrdup ( fn
);
1524 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1534 if (( e
= getenv ( "PULSE_CONFIG_PATH" )))
1535 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , e
, local
);
1536 else if ( pa_get_home_dir ( h
, sizeof ( h
)))
1537 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1542 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1543 /* FIXME: Needs to set errno! */
1550 if (( f
= fopen ( fn
, "r" ))) {
1552 * result
= pa_xstrdup ( fn
);
1558 if ( errno
!= ENOENT
) {
1559 pa_log_warn ( "Failed to open configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1571 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1572 /* FIXME: Needs to set errno! */
1577 if (( f
= fopen ( global
, "r" ))) {
1580 * result
= pa_xstrdup ( global
);
1590 char * pa_find_config_file ( const char * global
, const char * local
, const char * env
) {
1595 if (! getenv ( PULSE_ROOTENV
))
1599 if ( env
&& ( fn
= getenv ( env
))) {
1602 if (! ExpandEnvironmentStrings ( fn
, buf
, PATH_MAX
))
1603 /* FIXME: Needs to set errno! */
1608 if ( access ( fn
, R_OK
) == 0 )
1609 return pa_xstrdup ( fn
);
1611 pa_log_warn ( "Failed to access 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 ( pa_get_home_dir ( h
, sizeof ( h
)))
1623 fn
= lfn
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
".pulse" PA_PATH_SEP
"%s" , h
, local
);
1628 if (! ExpandEnvironmentStrings ( lfn
, buf
, PATH_MAX
)) {
1629 /* FIXME: Needs to set errno! */
1636 if ( access ( fn
, R_OK
) == 0 ) {
1637 char * r
= pa_xstrdup ( fn
);
1642 if ( errno
!= ENOENT
) {
1643 pa_log_warn ( "Failed to access configuration file '%s': %s" , fn
, pa_cstrerror ( errno
));
1653 if (! ExpandEnvironmentStrings ( global
, buf
, PATH_MAX
))
1654 /* FIXME: Needs to set errno! */
1659 if ( access ( global
, R_OK
) == 0 )
1660 return pa_xstrdup ( global
);
1668 /* Format the specified data as a hexademical string */
1669 char * pa_hexstr ( const uint8_t * d
, size_t dlength
, char * s
, size_t slength
) {
1670 size_t i
= 0 , j
= 0 ;
1671 const char hex
[] = "0123456789abcdef" ;
1675 pa_assert ( slength
> 0 );
1677 while ( i
< dlength
&& j
+ 3 <= slength
) {
1678 s
[ j
++] = hex
[* d
>> 4 ];
1679 s
[ j
++] = hex
[* d
& 0xF ];
1685 s
[ j
< slength
? j
: slength
] = 0 ;
1689 /* Convert a hexadecimal digit to a number or -1 if invalid */
1690 static int hexc ( char c
) {
1691 if ( c
>= '0' && c
<= '9' )
1694 if ( c
>= 'A' && c
<= 'F' )
1695 return c
- 'A' + 10 ;
1697 if ( c
>= 'a' && c
<= 'f' )
1698 return c
- 'a' + 10 ;
1704 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1705 size_t pa_parsehex ( const char * p
, uint8_t * d
, size_t dlength
) {
1711 while ( j
< dlength
&& * p
) {
1714 if (( b
= hexc (*( p
++))) < 0 )
1717 d
[ j
] = ( uint8_t ) ( b
<< 4 );
1722 if (( b
= hexc (*( p
++))) < 0 )
1725 d
[ j
] |= ( uint8_t ) b
;
1732 /* Returns nonzero when *s starts with *pfx */
1733 pa_bool_t
pa_startswith ( const char * s
, const char * pfx
) {
1741 return strlen ( s
) >= l
&& strncmp ( s
, pfx
, l
) == 0 ;
1744 /* Returns nonzero when *s ends with *sfx */
1745 pa_bool_t
pa_endswith ( const char * s
, const char * sfx
) {
1754 return l1
>= l2
&& strcmp ( s
+ l1
- l2
, sfx
) == 0 ;
1757 pa_bool_t
pa_is_path_absolute ( const char * fn
) {
1763 return strlen ( fn
) >= 3 && isalpha ( fn
[ 0 ]) && fn
[ 1 ] == ':' && fn
[ 2 ] == ' \\ ' ;
1767 char * pa_make_path_absolute ( const char * p
) {
1773 if ( pa_is_path_absolute ( p
))
1774 return pa_xstrdup ( p
);
1776 if (!( cwd
= pa_getcwd ()))
1777 return pa_xstrdup ( p
);
1779 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , cwd
, p
);
1784 /* if fn is null return the PulseAudio run time path in s (~/.pulse)
1785 * if fn is non-null and starts with / return fn
1786 * otherwise append fn to the run time path and return it */
1787 static char * get_path ( const char * fn
, pa_bool_t prependmid
, pa_bool_t rt
) {
1790 if ( pa_is_path_absolute ( fn
))
1791 return pa_xstrdup ( fn
);
1793 rtp
= rt
? pa_get_runtime_dir () : pa_get_state_dir ();
1804 if (!( mid
= pa_machine_id ())) {
1809 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s:%s" , rtp
, mid
, fn
);
1812 r
= pa_sprintf_malloc ( "%s" PA_PATH_SEP
"%s" , rtp
, fn
);
1820 char * pa_runtime_path ( const char * fn
) {
1821 return get_path ( fn
, FALSE
, TRUE
);
1824 char * pa_state_path ( const char * fn
, pa_bool_t appendmid
) {
1825 return get_path ( fn
, appendmid
, FALSE
);
1828 /* Convert the string s to a signed integer in *ret_i */
1829 int pa_atoi ( const char * s
, int32_t * ret_i
) {
1837 l
= strtol ( s
, & x
, 0 );
1839 if (! x
|| * x
|| errno
) {
1845 if (( int32_t ) l
!= l
) {
1850 * ret_i
= ( int32_t ) l
;
1855 /* Convert the string s to an unsigned integer in *ret_u */
1856 int pa_atou ( const char * s
, uint32_t * ret_u
) {
1864 l
= strtoul ( s
, & x
, 0 );
1866 if (! x
|| * x
|| errno
) {
1872 if (( uint32_t ) l
!= l
) {
1877 * ret_u
= ( uint32_t ) l
;
1882 #ifdef HAVE_STRTOF_L
1883 static locale_t c_locale
= NULL
;
1885 static void c_locale_destroy ( void ) {
1886 freelocale ( c_locale
);
1890 int pa_atod ( const char * s
, double * ret_d
) {
1897 /* This should be locale independent */
1899 #ifdef HAVE_STRTOF_L
1903 if (( c_locale
= newlocale ( LC_ALL_MASK
, "C" , NULL
)))
1904 atexit ( c_locale_destroy
);
1910 f
= strtod_l ( s
, & x
, c_locale
);
1918 if (! x
|| * x
|| errno
) {
1929 /* Same as snprintf, but guarantees NUL-termination on every platform */
1930 int pa_snprintf ( char * str
, size_t size
, const char * format
, ...) {
1935 pa_assert ( size
> 0 );
1938 va_start ( ap
, format
);
1939 ret
= pa_vsnprintf ( str
, size
, format
, ap
);
1945 /* Same as vsnprintf, but guarantees NUL-termination on every platform */
1946 int pa_vsnprintf ( char * str
, size_t size
, const char * format
, va_list ap
) {
1950 pa_assert ( size
> 0 );
1953 ret
= vsnprintf ( str
, size
, format
, ap
);
1960 return PA_MIN (( int ) size
- 1 , ret
);
1963 /* Truncate the specified string, but guarantee that the string
1964 * returned still validates as UTF8 */
1965 char * pa_truncate_utf8 ( char * c
, size_t l
) {
1967 pa_assert ( pa_utf8_valid ( c
));
1974 while ( l
> 0 && ! pa_utf8_valid ( c
))
1980 char * pa_getcwd ( void ) {
1984 char * p
= pa_xnew ( char , l
);
1988 if ( errno
!= ERANGE
)
1996 void * pa_will_need ( const void * p
, size_t l
) {
1997 #ifdef RLIMIT_MEMLOCK
2008 a
= PA_PAGE_ALIGN_PTR ( p
);
2009 size
= ( const uint8_t *) p
+ l
- ( const uint8_t *) a
;
2011 #ifdef HAVE_POSIX_MADVISE
2012 if (( r
= posix_madvise (( void *) a
, size
, POSIX_MADV_WILLNEED
)) == 0 ) {
2013 pa_log_debug ( "posix_madvise() worked fine!" );
2018 /* Most likely the memory was not mmap()ed from a file and thus
2019 * madvise() didn't work, so let's misuse mlock() do page this
2020 * stuff back into RAM. Yeah, let's fuck with the MM! It's so
2021 * inviting, the man page of mlock() tells us: "All pages that
2022 * contain a part of the specified address range are guaranteed to
2023 * be resident in RAM when the call returns successfully." */
2025 #ifdef RLIMIT_MEMLOCK
2026 pa_assert_se ( getrlimit ( RLIMIT_MEMLOCK
, & rlim
) == 0 );
2028 if ( rlim
. rlim_cur
< PA_PAGE_SIZE
) {
2029 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
));
2034 bs
= PA_PAGE_ALIGN ( rlim
. rlim_cur
);
2036 bs
= PA_PAGE_SIZE
* 4 ;
2039 pa_log_debug ( "posix_madvise() failed (or doesn't exist), trying mlock(): %s" , pa_cstrerror ( r
));
2042 while ( size
> 0 && bs
> 0 ) {
2047 if ( mlock ( a
, bs
) < 0 ) {
2048 bs
= PA_PAGE_ALIGN ( bs
/ 2 );
2052 pa_assert_se ( munlock ( a
, bs
) == 0 );
2054 a
= ( const uint8_t *) a
+ bs
;
2060 pa_log_debug ( "mlock() failed too (or doesn't exist), giving up: %s" , pa_cstrerror ( errno
));
2062 pa_log_debug ( "mlock() worked fine!" );
2067 void pa_close_pipe ( int fds
[ 2 ]) {
2071 pa_assert_se ( pa_close ( fds
[ 0 ]) == 0 );
2074 pa_assert_se ( pa_close ( fds
[ 1 ]) == 0 );
2076 fds
[ 0 ] = fds
[ 1 ] = - 1 ;
2079 char * pa_readlink ( const char * p
) {
2086 c
= pa_xnew ( char , l
);
2088 if (( n
= readlink ( p
, c
, l
- 1 )) < 0 ) {
2093 if (( size_t ) n
< l
- 1 ) {
2103 int pa_close_all ( int except_fd
, ...) {
2108 va_start ( ap
, except_fd
);
2111 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2116 p
= pa_xnew ( int , n
+ 1 );
2118 va_start ( ap
, except_fd
);
2121 if ( except_fd
>= 0 ) {
2125 while (( fd
= va_arg ( ap
, int )) >= 0 )
2132 r
= pa_close_allv ( p
);
2138 int pa_close_allv ( const int except_fds
[]) {
2147 if (( d
= opendir ( "/proc/self/fd" ))) {
2151 while (( de
= readdir ( d
))) {
2157 if ( de
-> d_name
[ 0 ] == '.' )
2161 l
= strtol ( de
-> d_name
, & e
, 10 );
2162 if ( errno
!= 0 || ! e
|| * e
) {
2170 if (( long ) fd
!= l
) {
2183 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2184 if ( except_fds
[ i
] == fd
) {
2192 if ( pa_close ( fd
) < 0 ) {
2193 saved_errno
= errno
;
2195 errno
= saved_errno
;
2207 if ( getrlimit ( RLIMIT_NOFILE
, & rl
) < 0 )
2210 for ( fd
= 3 ; fd
< ( int ) rl
. rlim_max
; fd
++) {
2215 for ( i
= 0 ; except_fds
[ i
] >= 0 ; i
++)
2216 if ( except_fds
[ i
] == fd
) {
2224 if ( pa_close ( fd
) < 0 && errno
!= EBADF
)
2231 int pa_unblock_sigs ( int except
, ...) {
2236 va_start ( ap
, except
);
2239 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2244 p
= pa_xnew ( int , n
+ 1 );
2246 va_start ( ap
, except
);
2253 while (( sig
= va_arg ( ap
, int )) >= 0 )
2260 r
= pa_unblock_sigsv ( p
);
2266 int pa_unblock_sigsv ( const int except
[]) {
2270 if ( sigemptyset (& ss
) < 0 )
2273 for ( i
= 0 ; except
[ i
] > 0 ; i
++)
2274 if ( sigaddset (& ss
, except
[ i
]) < 0 )
2277 return sigprocmask ( SIG_SETMASK
, & ss
, NULL
);
2280 int pa_reset_sigs ( int except
, ...) {
2285 va_start ( ap
, except
);
2288 for ( n
= 1 ; va_arg ( ap
, int ) >= 0 ; n
++)
2293 p
= pa_xnew ( int , n
+ 1 );
2295 va_start ( ap
, except
);
2302 while (( sig
= va_arg ( ap
, int )) >= 0 )
2309 r
= pa_reset_sigsv ( p
);
2315 int pa_reset_sigsv ( const int except
[]) {
2318 for ( sig
= 1 ; sig
< _NSIG
; sig
++) {
2319 pa_bool_t reset
= TRUE
;
2330 for ( i
= 0 ; except
[ i
] > 0 ; i
++) {
2331 if ( sig
== except
[ i
]) {
2340 struct sigaction sa
;
2342 memset (& sa
, 0 , sizeof ( sa
));
2343 sa
. sa_handler
= SIG_DFL
;
2345 /* On Linux the first two RT signals are reserved by
2346 * glibc, and sigaction() will return EINVAL for them. */
2347 if (( sigaction ( sig
, & sa
, NULL
) < 0 ))
2348 if ( errno
!= EINVAL
)
2356 void pa_set_env ( const char * key
, const char * value
) {
2360 putenv ( pa_sprintf_malloc ( "%s=%s" , key
, value
));
2363 pa_bool_t
pa_in_system_mode ( void ) {
2366 if (!( e
= getenv ( "PULSE_SYSTEM" )))
2372 char * pa_machine_id ( void ) {
2376 if (( f
= fopen ( PA_MACHINE_ID
, "r" ))) {
2377 char ln
[ 34 ] = "" , * r
;
2379 r
= fgets ( ln
, sizeof ( ln
)- 1 , f
);
2383 return pa_xstrdup ( pa_strip_nl ( ln
));
2391 c
= pa_xnew ( char , l
);
2393 if (! pa_get_host_name ( c
, l
)) {
2395 if ( errno
== EINVAL
|| errno
== ENAMETOOLONG
) {
2404 if ( strlen ( c
) < l
- 1 )
2407 /* Hmm, the hostname is as long the space we offered the
2408 * function, we cannot know if it fully fit in, so let's play
2409 * safe and retry. */