4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2004 Joe Marcus Clarke
8 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
10 PulseAudio is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as
12 published by the Free Software Foundation; either version 2.1 of the
13 License, or (at your option) any later version.
15 PulseAudio is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with PulseAudio; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
42 #include <sys/types.h>
50 #ifdef HAVE_SYS_RESOURCE_H
51 #include <sys/resource.h>
74 #include <samplerate.h>
76 #include <pulse/xmalloc.h>
77 #include <pulse/util.h>
79 #include <pulsecore/core-error.h>
80 #include <pulsecore/winsock.h>
81 #include <pulsecore/log.h>
83 #include "core-util.h"
85 /* Not all platforms have this */
87 #define MSG_NOSIGNAL 0
91 #define PA_USER_RUNTIME_PATH_PREFIX "/tmp/pulse-"
94 #define PA_USER_RUNTIME_PATH_PREFIX "%TEMP%\\pulse-"
100 #define PULSE_ROOTENV "PULSE_ROOT"
102 int pa_set_root(HANDLE handle
) {
103 char library_path
[MAX_PATH
+ sizeof(PULSE_ROOTENV
) + 1], *sep
;
105 strcpy(library_path
, PULSE_ROOTENV
"=");
107 if (!GetModuleFileName(handle
, library_path
+ sizeof(PULSE_ROOTENV
), MAX_PATH
))
110 sep
= strrchr(library_path
, '\\');
114 if (_putenv(library_path
) < 0)
122 /** Make a file descriptor nonblock. Doesn't do any error checking */
123 void pa_make_nonblock_fd(int fd
) {
128 if ((v
= fcntl(fd
, F_GETFL
)) >= 0)
129 if (!(v
& O_NONBLOCK
))
130 fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
);
131 #elif defined(OS_IS_WIN32)
133 if (ioctlsocket(fd
, FIONBIO
, &arg
) < 0) {
134 if (WSAGetLastError() == WSAENOTSOCK
)
135 pa_log_warn("WARNING: Only sockets can be made non-blocking!");
138 pa_log_warn("WARNING: Non-blocking I/O not supported.!");
142 /** Creates a directory securely */
143 int pa_make_secure_dir(const char* dir
, mode_t m
, uid_t uid
, gid_t gid
) {
160 if (r
< 0 && errno
!= EEXIST
)
164 if (uid
== (uid_t
)-1)
166 if (gid
== (gid_t
)-1)
168 chown(dir
, uid
, gid
);
176 if (lstat(dir
, &st
) < 0)
178 if (stat(dir
, &st
) < 0)
183 if (!S_ISDIR(st
.st_mode
) ||
184 (st
.st_uid
!= uid
) ||
185 (st
.st_gid
!= gid
) ||
186 ((st
.st_mode
& 0777) != m
)) {
191 pa_log_warn("secure directory creation not supported on Win32.");
201 /* Return a newly allocated sting containing the parent directory of the specified file */
202 char *pa_parent_dir(const char *fn
) {
203 char *slash
, *dir
= pa_xstrdup(fn
);
205 if ((slash
= (char*) pa_path_get_filename(dir
)) == dir
) {
214 /* Creates a the parent directory of the specified path securely */
215 int pa_make_secure_parent_dir(const char *fn
, mode_t m
, uid_t uid
, gid_t gid
) {
219 if (!(dir
= pa_parent_dir(fn
)))
222 if (pa_make_secure_dir(dir
, m
, uid
, gid
) < 0)
232 /** Platform independent read function. Necessary since not all
233 * systems treat all file descriptors equal. If type is
234 * non-NULL it is used to cache the type of the fd. This is
235 * useful for making sure that only a single syscall is executed per
236 * function call. The variable pointed to should be initialized to 0
238 ssize_t
pa_read(int fd
, void *buf
, size_t count
, int *type
) {
242 if (!type
|| *type
== 0) {
245 if ((r
= recv(fd
, buf
, count
, 0)) >= 0)
248 if (WSAGetLastError() != WSAENOTSOCK
) {
249 errno
= WSAGetLastError();
259 return read(fd
, buf
, count
);
262 /** Similar to pa_read(), but handles writes */
263 ssize_t
pa_write(int fd
, const void *buf
, size_t count
, int *type
) {
265 if (!type
|| *type
== 0) {
268 if ((r
= send(fd
, buf
, count
, MSG_NOSIGNAL
)) >= 0)
272 if (WSAGetLastError() != WSAENOTSOCK
) {
273 errno
= WSAGetLastError();
277 if (errno
!= ENOTSOCK
)
285 return write(fd
, buf
, count
);
288 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
289 * unless EOF is reached or an error occured */
290 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
, int *type
) {
306 if ((r
= pa_read(fd
, data
, size
, type
)) < 0)
313 data
= (uint8_t*) data
+ r
;
320 /** Similar to pa_loop_read(), but wraps write() */
321 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
, int *type
) {
337 if ((r
= pa_write(fd
, data
, size
, type
)) < 0)
344 data
= (const uint8_t*) data
+ r
;
351 /** Platform independent read function. Necessary since not all
352 * systems treat all file descriptors equal. */
358 ret
= closesocket(fd
);
362 if (WSAGetLastError() != WSAENOTSOCK
) {
363 errno
= WSAGetLastError();
371 /* Print a warning messages in case that the given signal is not
372 * blocked or trapped */
373 void pa_check_signal_is_blocked(int sig
) {
374 #ifdef HAVE_SIGACTION
378 /* If POSIX threads are supported use thread-aware
379 * pthread_sigmask() function, to check if the signal is
380 * blocked. Otherwise fall back to sigprocmask() */
383 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
385 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
386 pa_log("sigprocmask(): %s", pa_cstrerror(errno
));
393 if (sigismember(&set
, sig
))
396 /* Check whether the signal is trapped */
398 if (sigaction(sig
, NULL
, &sa
) < 0) {
399 pa_log("sigaction(): %s", pa_cstrerror(errno
));
403 if (sa
.sa_handler
!= SIG_DFL
)
406 pa_log("WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig
));
407 #else /* HAVE_SIGACTION */
408 pa_log("WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig
));
412 /* The following function is based on an example from the GNU libc
413 * documentation. This function is similar to GNU's asprintf(). */
414 char *pa_sprintf_malloc(const char *format
, ...) {
424 c
= pa_xrealloc(c
, size
);
426 va_start(ap
, format
);
427 r
= vsnprintf(c
, size
, format
, ap
);
430 if (r
> -1 && r
< size
)
433 if (r
> -1) /* glibc 2.1 */
440 /* Same as the previous function, but use a va_list instead of an
442 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
454 c
= pa_xrealloc(c
, size
);
455 r
= vsnprintf(c
, size
, format
, aq
);
459 if (r
> -1 && r
< size
)
462 if (r
> -1) /* glibc 2.1 */
469 /* Similar to OpenBSD's strlcpy() function */
470 char *pa_strlcpy(char *b
, const char *s
, size_t l
) {
471 assert(b
&& s
&& l
> 0);
478 #define NICE_LEVEL (-15)
480 /* Raise the priority of the current process as much as possible and
481 sensible: set the nice level to -15 and enable realtime scheduling if
483 void pa_raise_priority(void) {
485 #ifdef HAVE_SYS_RESOURCE_H
486 if (setpriority(PRIO_PROCESS
, 0, NICE_LEVEL
) < 0)
487 pa_log_warn("setpriority(): %s", pa_cstrerror(errno
));
489 pa_log_info("Successfully gained nice level %i.", NICE_LEVEL
);
492 #ifdef _POSIX_PRIORITY_SCHEDULING
494 struct sched_param sp
;
496 if (sched_getparam(0, &sp
) < 0) {
497 pa_log("sched_getparam(): %s", pa_cstrerror(errno
));
501 sp
.sched_priority
= 1;
502 if (sched_setscheduler(0, SCHED_FIFO
, &sp
) < 0) {
503 pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno
));
507 pa_log_info("Successfully enabled SCHED_FIFO scheduling.");
512 if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS
))
513 pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
515 pa_log_info("Successfully gained high priority class.");
519 /* Reset the priority to normal, inverting the changes made by pa_raise_priority() */
520 void pa_reset_priority(void) {
522 SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS
);
525 #ifdef _POSIX_PRIORITY_SCHEDULING
527 struct sched_param sp
;
528 sched_getparam(0, &sp
);
529 sp
.sched_priority
= 0;
530 sched_setscheduler(0, SCHED_OTHER
, &sp
);
534 #ifdef HAVE_SYS_RESOURCE_H
535 setpriority(PRIO_PROCESS
, 0, 0);
539 /* Set the FD_CLOEXEC flag for a fd */
540 int pa_fd_set_cloexec(int fd
, int b
) {
546 if ((v
= fcntl(fd
, F_GETFD
, 0)) < 0)
549 v
= (v
& ~FD_CLOEXEC
) | (b
? FD_CLOEXEC
: 0);
551 if (fcntl(fd
, F_SETFD
, v
) < 0)
558 /* Try to parse a boolean string value.*/
559 int pa_parse_boolean(const char *v
) {
561 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
563 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
569 /* Split the specified string wherever one of the strings in delimiter
570 * occurs. Each time it is called returns a newly allocated string
571 * with pa_xmalloc(). The variable state points to, should be
572 * initiallized to NULL before the first call. */
573 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
574 const char *current
= *state
? *state
: c
;
580 l
= strcspn(current
, delimiter
);
586 return pa_xstrndup(current
, l
);
589 /* What is interpreted as whitespace? */
590 #define WHITESPACE " \t\n"
592 /* Split a string into words. Otherwise similar to pa_split(). */
593 char *pa_split_spaces(const char *c
, const char **state
) {
594 const char *current
= *state
? *state
: c
;
597 if (!*current
|| *c
== 0)
600 current
+= strspn(current
, WHITESPACE
);
601 l
= strcspn(current
, WHITESPACE
);
605 return pa_xstrndup(current
, l
);
608 /* Return the name of an UNIX signal. Similar to GNU's strsignal() */
609 const char *pa_strsignal(int sig
) {
611 case SIGINT
: return "SIGINT";
612 case SIGTERM
: return "SIGTERM";
614 case SIGUSR1
: return "SIGUSR1";
617 case SIGUSR2
: return "SIGUSR2";
620 case SIGXCPU
: return "SIGXCPU";
623 case SIGPIPE
: return "SIGPIPE";
626 case SIGCHLD
: return "SIGCHLD";
629 case SIGHUP
: return "SIGHUP";
631 default: return "UNKNOWN SIGNAL";
637 /* Check whether the specified GID and the group name match */
638 static int is_group(gid_t gid
, const char *name
) {
639 struct group group
, *result
= NULL
;
644 #ifdef HAVE_GETGRGID_R
645 #ifdef _SC_GETGR_R_SIZE_MAX
646 n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
651 data
= pa_xmalloc(n
);
653 if (getgrgid_r(gid
, &group
, data
, n
, &result
) < 0 || !result
) {
654 pa_log("getgrgid_r(%u): %s", (unsigned)gid
, pa_cstrerror(errno
));
658 r
= strcmp(name
, result
->gr_name
) == 0;
663 /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
664 * support getgrgid_r. */
665 if ((result
= getgrgid(gid
)) == NULL
) {
666 pa_log("getgrgid(%u): %s", gid
, pa_cstrerror(errno
));
670 r
= strcmp(name
, result
->gr_name
) == 0;
678 /* Check the current user is member of the specified group */
679 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
680 GETGROUPS_T
*gids
, tgid
;
681 int n
= sysconf(_SC_NGROUPS_MAX
);
686 gids
= pa_xmalloc(sizeof(GETGROUPS_T
)*n
);
688 if ((n
= getgroups(n
, gids
)) < 0) {
689 pa_log("getgroups(): %s", pa_cstrerror(errno
));
693 for (i
= 0; i
< n
; i
++) {
694 if (is_group(gids
[i
], name
) > 0) {
701 if (is_group(tgid
= getgid(), name
) > 0) {
715 /* Check whether the specifc user id is a member of the specified group */
716 int pa_uid_in_group(uid_t uid
, const char *name
) {
719 struct group grbuf
, *gr
;
723 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
724 g_buf
= pa_xmalloc(g_n
);
726 p_n
= sysconf(_SC_GETPW_R_SIZE_MAX
);
727 p_buf
= pa_xmalloc(p_n
);
729 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
733 for (i
= gr
->gr_mem
; *i
; i
++) {
734 struct passwd pwbuf
, *pw
;
736 if (getpwnam_r(*i
, &pwbuf
, p_buf
, (size_t) p_n
, &pw
) != 0 || !pw
)
739 if (pw
->pw_uid
== uid
) {
752 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
753 gid_t
pa_get_gid_of_group(const char *name
) {
754 gid_t ret
= (gid_t
) -1;
757 struct group grbuf
, *gr
;
759 g_n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
760 g_buf
= pa_xmalloc(g_n
);
762 if (getgrnam_r(name
, &grbuf
, g_buf
, (size_t) g_n
, &gr
) != 0 || !gr
)
772 int pa_check_in_group(gid_t g
) {
773 gid_t gids
[NGROUPS_MAX
];
776 if ((r
= getgroups(NGROUPS_MAX
, gids
)) < 0)
786 #else /* HAVE_GRP_H */
788 int pa_own_uid_in_group(const char *name
, gid_t
*gid
) {
793 int pa_uid_in_group(uid_t uid
, const char *name
) {
797 gid_t
pa_get_gid_of_group(const char *name
) {
801 int pa_check_in_group(gid_t g
) {
807 /* Lock or unlock a file entirely.
808 (advisory on UNIX, mandatory on Windows) */
809 int pa_lock_fd(int fd
, int b
) {
813 /* Try a R/W lock first */
815 flock
.l_type
= b
? F_WRLCK
: F_UNLCK
;
816 flock
.l_whence
= SEEK_SET
;
820 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
823 /* Perhaps the file descriptor qas opened for read only, than try again with a read lock. */
824 if (b
&& errno
== EBADF
) {
825 flock
.l_type
= F_RDLCK
;
826 if (fcntl(fd
, F_SETLKW
, &flock
) >= 0)
830 pa_log("%slock: %s", !b
? "un" : "",
831 pa_cstrerror(errno
));
835 HANDLE h
= (HANDLE
)_get_osfhandle(fd
);
837 if (b
&& LockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
839 if (!b
&& UnlockFile(h
, 0, 0, 0xFFFFFFFF, 0xFFFFFFFF))
842 pa_log("%slock failed: 0x%08X", !b
? "un" : "", GetLastError());
848 /* Remove trailing newlines from a string */
849 char* pa_strip_nl(char *s
) {
852 s
[strcspn(s
, "\r\n")] = 0;
856 /* Create a temporary lock file and lock it. */
857 int pa_lock_lockfile(const char *fn
) {
864 if ((fd
= open(fn
, O_CREAT
|O_RDWR
, S_IRUSR
|S_IWUSR
)) < 0) {
865 pa_log("failed to create lock file '%s': %s", fn
,
866 pa_cstrerror(errno
));
870 if (pa_lock_fd(fd
, 1) < 0) {
871 pa_log("failed to lock file '%s'.", fn
);
875 if (fstat(fd
, &st
) < 0) {
876 pa_log("failed to fstat() file '%s'.", fn
);
880 /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */
881 if (st
.st_nlink
>= 1)
884 if (pa_lock_fd(fd
, 0) < 0) {
885 pa_log("failed to unlock file '%s'.", fn
);
890 pa_log("failed to close file '%s'.", fn
);
907 /* Unlock a temporary lcok file */
908 int pa_unlock_lockfile(const char *fn
, int fd
) {
910 assert(fn
&& fd
>= 0);
912 if (unlink(fn
) < 0) {
913 pa_log_warn("WARNING: unable to remove lock file '%s': %s",
914 fn
, pa_cstrerror(errno
));
918 if (pa_lock_fd(fd
, 0) < 0) {
919 pa_log_warn("WARNING: failed to unlock file '%s'.", fn
);
924 pa_log_warn("WARNING: failed to close lock file '%s': %s",
925 fn
, pa_cstrerror(errno
));
932 /* Try to open a configuration file. If "env" is specified, open the
933 * value of the specified environment variable. Otherwise look for a
934 * file "local" in the home directory or a file "global" in global
935 * file system. If "result" is non-NULL, a pointer to a newly
936 * allocated buffer containing the used configuration file is
938 FILE *pa_open_config_file(const char *global
, const char *local
, const char *env
, char **result
, const char *mode
) {
945 if (!getenv(PULSE_ROOTENV
))
949 if (env
&& (fn
= getenv(env
))) {
951 if (!ExpandEnvironmentStrings(fn
, buf
, PATH_MAX
))
957 *result
= pa_xstrdup(fn
);
959 return fopen(fn
, mode
);
966 if ((e
= getenv("PULSE_CONFIG_PATH")))
967 fn
= lfn
= pa_sprintf_malloc("%s/%s", e
, local
);
968 else if (pa_get_home_dir(h
, sizeof(h
)))
969 fn
= lfn
= pa_sprintf_malloc("%s/.pulse/%s", h
, local
);
975 if (!ExpandEnvironmentStrings(lfn
, buf
, PATH_MAX
))
983 *result
= pa_xstrdup(fn
);
988 if (errno
!= ENOENT
) {
989 pa_log_warn("WARNING: failed to open configuration file '%s': %s",
990 lfn
, pa_cstrerror(errno
));
1005 if (!ExpandEnvironmentStrings(global
, buf
, PATH_MAX
))
1011 *result
= pa_xstrdup(global
);
1013 return fopen(global
, mode
);
1016 /* Format the specified data as a hexademical string */
1017 char *pa_hexstr(const uint8_t* d
, size_t dlength
, char *s
, size_t slength
) {
1018 size_t i
= 0, j
= 0;
1019 const char hex
[] = "0123456789abcdef";
1020 assert(d
&& s
&& slength
> 0);
1022 while (i
< dlength
&& j
+3 <= slength
) {
1023 s
[j
++] = hex
[*d
>> 4];
1024 s
[j
++] = hex
[*d
& 0xF];
1030 s
[j
< slength
? j
: slength
] = 0;
1034 /* Convert a hexadecimal digit to a number or -1 if invalid */
1035 static int hexc(char c
) {
1036 if (c
>= '0' && c
<= '9')
1039 if (c
>= 'A' && c
<= 'F')
1040 return c
- 'A' + 10;
1042 if (c
>= 'a' && c
<= 'f')
1043 return c
- 'a' + 10;
1048 /* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
1049 size_t pa_parsehex(const char *p
, uint8_t *d
, size_t dlength
) {
1053 while (j
< dlength
&& *p
) {
1056 if ((b
= hexc(*(p
++))) < 0)
1059 d
[j
] = (uint8_t) (b
<< 4);
1064 if ((b
= hexc(*(p
++))) < 0)
1067 d
[j
] |= (uint8_t) b
;
1074 /* Returns nonzero when *s starts with *pfx */
1075 int pa_startswith(const char *s
, const char *pfx
) {
1083 return strlen(s
) >= l
&& strncmp(s
, pfx
, l
) == 0;
1086 /* Returns nonzero when *s ends with *sfx */
1087 int pa_endswith(const char *s
, const char *sfx
) {
1096 return l1
>= l2
&& strcmp(s
+l1
-l2
, sfx
) == 0;
1099 /* if fn is null return the PulseAudio run time path in s (/tmp/pulse)
1100 * if fn is non-null and starts with / return fn in s
1101 * otherwise append fn to the run time path and return it in s */
1102 char *pa_runtime_path(const char *fn
, char *s
, size_t l
) {
1106 if (fn
&& *fn
== '/')
1108 if (fn
&& strlen(fn
) >= 3 && isalpha(fn
[0]) && fn
[1] == ':' && fn
[2] == '\\')
1110 return pa_strlcpy(s
, fn
, l
);
1112 if ((e
= getenv("PULSE_RUNTIME_PATH"))) {
1115 snprintf(s
, l
, "%s%c%s", e
, PATH_SEP
, fn
);
1117 snprintf(s
, l
, "%s", e
);
1123 snprintf(s
, l
, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX
, pa_get_user_name(u
, sizeof(u
)), PATH_SEP
, fn
);
1125 snprintf(s
, l
, "%s%s", PA_USER_RUNTIME_PATH_PREFIX
, pa_get_user_name(u
, sizeof(u
)));
1133 ExpandEnvironmentStrings(buf
, s
, l
);
1140 /* Convert the string s to a signed integer in *ret_i */
1141 int pa_atoi(const char *s
, int32_t *ret_i
) {
1146 l
= strtol(s
, &x
, 0);
1151 *ret_i
= (int32_t) l
;
1156 /* Convert the string s to an unsigned integer in *ret_u */
1157 int pa_atou(const char *s
, uint32_t *ret_u
) {
1162 l
= strtoul(s
, &x
, 0);
1167 *ret_u
= (uint32_t) l
;