]>
code.delx.au - pulseaudio/blob - polyp/util.c
4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
35 #include <sys/types.h>
42 #include <sys/resource.h>
47 #include <samplerate.h>
53 void pa_make_nonblock_fd(int fd
) {
56 if ((v
= fcntl(fd
, F_GETFL
)) >= 0)
57 if (!(v
& O_NONBLOCK
))
58 fcntl(fd
, F_SETFL
, v
|O_NONBLOCK
);
61 int pa_make_secure_dir(const char* dir
) {
64 if (mkdir(dir
, 0700) < 0)
68 if (lstat(dir
, &st
) < 0)
71 if (!S_ISDIR(st
.st_mode
) || (st
.st_uid
!= getuid()) || ((st
.st_mode
& 0777) != 0700))
81 ssize_t
pa_loop_read(int fd
, void*data
, size_t size
) {
83 assert(fd
>= 0 && data
&& size
);
88 if ((r
= read(fd
, data
, size
)) < 0)
95 data
= (uint8_t*) data
+ r
;
102 ssize_t
pa_loop_write(int fd
, const void*data
, size_t size
) {
104 assert(fd
>= 0 && data
&& size
);
109 if ((r
= write(fd
, data
, size
)) < 0)
116 data
= (uint8_t*) data
+ r
;
123 void pa_check_signal_is_blocked(int sig
) {
128 if (pthread_sigmask(SIG_SETMASK
, NULL
, &set
) < 0) {
130 if (sigprocmask(SIG_SETMASK
, NULL
, &set
) < 0) {
131 pa_log(__FILE__
": sigprocmask() failed: %s\n", strerror(errno
));
138 if (sigismember(&set
, sig
))
141 if (sigaction(sig
, NULL
, &sa
) < 0) {
142 pa_log(__FILE__
": sigaction() failed: %s\n", strerror(errno
));
146 if (sa
.sa_handler
!= SIG_DFL
)
149 pa_log(__FILE__
": WARNING: %s is not trapped. This might cause malfunction!\n", pa_strsignal(sig
));
152 /* The following is based on an example from the GNU libc documentation */
153 char *pa_sprintf_malloc(const char *format
, ...) {
163 c
= pa_xrealloc(c
, size
);
165 va_start(ap
, format
);
166 r
= vsnprintf(c
, size
, format
, ap
);
169 if (r
> -1 && r
< size
)
172 if (r
> -1) /* glibc 2.1 */
179 char *pa_vsprintf_malloc(const char *format
, va_list ap
) {
189 c
= pa_xrealloc(c
, size
);
190 r
= vsnprintf(c
, size
, format
, ap
);
192 if (r
> -1 && r
< size
)
195 if (r
> -1) /* glibc 2.1 */
203 char *pa_get_user_name(char *s
, size_t l
) {
204 struct passwd pw
, *r
;
208 if (!(p
= getenv("USER")))
209 if (!(p
= getenv("LOGNAME")))
210 if (!(p
= getenv("USERNAME"))) {
212 if (getpwuid_r(getuid(), &pw
, buf
, sizeof(buf
), &r
) != 0 || !r
) {
213 snprintf(s
, l
, "%lu", (unsigned long) getuid());
220 snprintf(s
, l
, "%s", p
);
224 char *pa_get_host_name(char *s
, size_t l
) {
230 pa_usec_t
pa_timeval_diff(const struct timeval
*a
, const struct timeval
*b
) {
234 if (pa_timeval_cmp(a
, b
) < 0) {
235 const struct timeval
*c
;
241 r
= ((pa_usec_t
) a
->tv_sec
- b
->tv_sec
)* 1000000;
243 if (a
->tv_usec
> b
->tv_usec
)
244 r
+= ((pa_usec_t
) a
->tv_usec
- b
->tv_usec
);
245 else if (a
->tv_usec
< b
->tv_usec
)
246 r
-= ((pa_usec_t
) b
->tv_usec
- a
->tv_usec
);
251 int pa_timeval_cmp(const struct timeval
*a
, const struct timeval
*b
) {
254 if (a
->tv_sec
< b
->tv_sec
)
257 if (a
->tv_sec
> b
->tv_sec
)
260 if (a
->tv_usec
< b
->tv_usec
)
263 if (a
->tv_usec
> b
->tv_usec
)
269 pa_usec_t
pa_age(const struct timeval
*tv
) {
272 gettimeofday(&now
, NULL
);
273 return pa_timeval_diff(&now
, tv
);
276 void pa_timeval_add(struct timeval
*tv
, pa_usec_t v
) {
281 tv
->tv_sec
+= (unsigned long) secs
;
286 while (tv
->tv_usec
>= 1000000) {
288 tv
->tv_usec
-= 1000000;
292 #define NICE_LEVEL (-15)
294 void pa_raise_priority(void) {
295 if (setpriority(PRIO_PROCESS
, 0, NICE_LEVEL
) < 0)
296 pa_log(__FILE__
": setpriority() failed: %s\n", strerror(errno
));
298 pa_log(__FILE__
": Successfully gained nice level %i.\n", NICE_LEVEL
);
300 #ifdef _POSIX_PRIORITY_SCHEDULING
302 struct sched_param sp
;
304 if (sched_getparam(0, &sp
) < 0) {
305 pa_log(__FILE__
": sched_getparam() failed: %s\n", strerror(errno
));
309 sp
.sched_priority
= 1;
310 if (sched_setscheduler(0, SCHED_FIFO
, &sp
) < 0) {
311 pa_log(__FILE__
": sched_setscheduler() failed: %s\n", strerror(errno
));
315 pa_log(__FILE__
": Successfully enabled SCHED_FIFO scheduling.\n");
320 void pa_reset_priority(void) {
321 #ifdef _POSIX_PRIORITY_SCHEDULING
323 struct sched_param sp
;
324 sched_getparam(0, &sp
);
325 sp
.sched_priority
= 0;
326 sched_setscheduler(0, SCHED_OTHER
, &sp
);
330 setpriority(PRIO_PROCESS
, 0, 0);
333 int pa_fd_set_cloexec(int fd
, int b
) {
337 if ((v
= fcntl(fd
, F_GETFD
, 0)) < 0)
340 v
= (v
& ~FD_CLOEXEC
) | (b
? FD_CLOEXEC
: 0);
342 if (fcntl(fd
, F_SETFD
, v
) < 0)
348 char *pa_get_binary_name(char *s
, size_t l
) {
353 /* This works on Linux only */
355 snprintf(path
, sizeof(path
), "/proc/%u/exe", (unsigned) getpid());
356 if ((i
= readlink(path
, s
, l
-1)) < 0)
363 char *pa_path_get_filename(const char *p
) {
366 if ((fn
= strrchr(p
, '/')))
372 int pa_parse_boolean(const char *v
) {
374 if (!strcmp(v
, "1") || v
[0] == 'y' || v
[0] == 'Y' || v
[0] == 't' || v
[0] == 'T' || !strcasecmp(v
, "on"))
376 else if (!strcmp(v
, "0") || v
[0] == 'n' || v
[0] == 'N' || v
[0] == 'f' || v
[0] == 'F' || !strcasecmp(v
, "off"))
382 char *pa_split(const char *c
, const char *delimiter
, const char**state
) {
383 const char *current
= *state
? *state
: c
;
389 l
= strcspn(current
, delimiter
);
395 return pa_xstrndup(current
, l
);
398 #define WHITESPACE " \t\n"
400 char *pa_split_spaces(const char *c
, const char **state
) {
401 const char *current
= *state
? *state
: c
;
407 current
+= strspn(current
, WHITESPACE
);
408 l
= strcspn(current
, WHITESPACE
);
412 return pa_xstrndup(current
, l
);
415 const char *pa_strsignal(int sig
) {
417 case SIGINT
: return "SIGINT";
418 case SIGTERM
: return "SIGTERM";
419 case SIGUSR1
: return "SIGUSR1";
420 case SIGUSR2
: return "SIGUSR2";
421 case SIGXCPU
: return "SIGXCPU";
422 case SIGPIPE
: return "SIGPIPE";
423 case SIGCHLD
: return "SIGCHLD";
424 case SIGHUP
: return "SIGHUP";
425 default: return "UNKNOWN SIGNAL";
429 int pa_parse_resample_method(const char *string
) {
432 if (!strcmp(string
, "sinc-best-quality"))
433 return SRC_SINC_BEST_QUALITY
;
434 else if (!strcmp(string
, "sinc-medium-quality"))
435 return SRC_SINC_MEDIUM_QUALITY
;
436 else if (!strcmp(string
, "sinc-fastest"))
437 return SRC_SINC_FASTEST
;
438 else if (!strcmp(string
, "zero-order-hold"))
439 return SRC_ZERO_ORDER_HOLD
;
440 else if (!strcmp(string
, "linear"))
446 static int is_group(gid_t gid
, const char *name
) {
447 struct group group
, *result
= NULL
;
448 long n
= sysconf(_SC_GETGR_R_SIZE_MAX
);
453 data
= pa_xmalloc(n
);
455 if (getgrgid_r(gid
, &group
, data
, n
, &result
) < 0 || !result
) {
456 pa_log(__FILE__
": getgrgid_r(%u) failed: %s\n", gid
, strerror(errno
));
461 r
= strcmp(name
, result
->gr_name
) == 0;
469 int pa_uid_in_group(const char *name
, gid_t
*gid
) {
471 long n
= sysconf(_SC_NGROUPS_MAX
);
476 gids
= pa_xmalloc(sizeof(gid_t
)*n
);
478 if ((n
= getgroups(n
, gids
)) < 0) {
479 pa_log(__FILE__
": getgroups() failed: %s\n", strerror(errno
));
483 for (i
= 0; i
< n
; i
++) {
484 if (is_group(gids
[i
], name
) > 0) {
491 if (is_group(tgid
= getgid(), name
) > 0) {
505 int pa_lock_fd(int fd
, int b
) {
509 flock
.l_type
= b
? F_WRLCK
: F_UNLCK
;
510 flock
.l_whence
= SEEK_SET
;
514 if (fcntl(fd
, F_SETLKW
, &flock
) < 0) {
515 pa_log(__FILE__
": %slock failed: %s\n", !b
? "un" : "", strerror(errno
));
522 char* pa_strip_nl(char *s
) {
525 s
[strcspn(s
, "\r\n")] = 0;
529 int pa_lock_lockfile(const char *fn
) {
533 if ((fd
= open(fn
, O_CREAT
|O_RDWR
, S_IRUSR
|S_IWUSR
)) < 0) {
534 pa_log(__FILE__
": failed to create lock file '%s'\n", fn
);
538 if (pa_lock_fd(fd
, 1) < 0)
552 int pa_unlock_lockfile(int fd
) {
556 if (pa_lock_fd(fd
, 0) < 0) {
557 pa_log(__FILE__
": WARNING: failed to unlock file.\n");
562 pa_log(__FILE__
": WARNING: failed to close lock file.\n");