summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/core-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore/core-util.c')
-rw-r--r--src/pulsecore/core-util.c160
1 files changed, 137 insertions, 23 deletions
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index b2c91e45..5841df0c 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -40,6 +40,8 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <dirent.h>
+#include <regex.h>
+#include <langinfo.h>
#ifdef HAVE_STRTOF_L
#include <locale.h>
@@ -111,6 +113,8 @@ int pa_set_root(HANDLE handle) {
strcpy(library_path, PULSE_ROOTENV "=");
+ /* FIXME: Needs to set errno */
+
if (!GetModuleFileName(handle, library_path + sizeof(PULSE_ROOTENV), MAX_PATH))
return 0;
@@ -168,7 +172,7 @@ void pa_make_fd_cloexec(int fd) {
/** Creates a directory securely */
int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
struct stat st;
- int r;
+ int r, saved_errno;
pa_assert(dir);
@@ -220,7 +224,10 @@ int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
return 0;
fail:
+ saved_errno = errno;
rmdir(dir);
+ errno = saved_errno;
+
return -1;
}
@@ -230,6 +237,7 @@ char *pa_parent_dir(const char *fn) {
if ((slash = (char*) pa_path_get_filename(dir)) == dir) {
pa_xfree(dir);
+ errno = ENOENT;
return NULL;
}
@@ -546,6 +554,8 @@ int pa_make_realtime(int rtprio) {
pa_log_info("Successfully enabled SCHED_FIFO scheduling for thread, with priority %i.", sp.sched_priority);
return 0;
#else
+
+ errno = ENOTSUP;
return -1;
#endif
}
@@ -653,6 +663,7 @@ int pa_raise_priority(int nice_level) {
if (nice_level < 0) {
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) {
pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
+ errno = EPERM;
return .-1;
} else
pa_log_info("Successfully gained high priority class.");
@@ -679,15 +690,55 @@ void pa_reset_priority(void) {
#endif
}
+static int match(const char *expr, const char *v) {
+ int k;
+ regex_t re;
+ int r;
+
+ if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((k = regexec(&re, v, 0, NULL, 0)) == 0)
+ r = 1;
+ else if (k == REG_NOMATCH)
+ r = 0;
+ else
+ r = -1;
+
+ regfree(&re);
+
+ if (r < 0)
+ errno = EINVAL;
+
+ return r;
+}
+
/* Try to parse a boolean string value.*/
int pa_parse_boolean(const char *v) {
+ const char *expr;
+ int r;
pa_assert(v);
+ /* First we check language independant */
if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
return 1;
else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
return 0;
+ /* And then we check language dependant */
+ if ((expr = nl_langinfo(YESEXPR)))
+ if (expr[0])
+ if ((r = match(expr, v)) > 0)
+ return 1;
+
+ if ((expr = nl_langinfo(NOEXPR)))
+ if (expr[0])
+ if ((r = match(expr, v)) > 0)
+ return 0;
+
+ errno = EINVAL;
return -1;
}
@@ -875,11 +926,18 @@ static int is_group(gid_t gid, const char *name) {
#else
n = -1;
#endif
- if (n < 0) n = 512;
+ if (n < 0)
+ n = 512;
+
data = pa_xmalloc(n);
+ errno = 0;
if (getgrgid_r(gid, &group, data, n, &result) < 0 || !result) {
- pa_log("getgrgid_r(%u): %s", (unsigned)gid, pa_cstrerror(errno));
+ pa_log("getgrgid_r(%u): %s", (unsigned) gid, pa_cstrerror(errno));
+
+ if (!errno)
+ errno = ENOENT;
+
goto finish;
}
@@ -890,8 +948,14 @@ finish:
#else
/* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X) that do not
* support getgrgid_r. */
+
+ errno = 0;
if ((result = getgrgid(gid)) == NULL) {
pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno));
+
+ if (!errno)
+ errno = ENOENT;
+
goto finish;
}
@@ -907,7 +971,7 @@ finish:
int pa_own_uid_in_group(const char *name, gid_t *gid) {
GETGROUPS_T *gids, tgid;
int n = sysconf(_SC_NGROUPS_MAX);
- int r = -1, i;
+ int r = -1, i, k;
pa_assert(n > 0);
@@ -919,14 +983,19 @@ int pa_own_uid_in_group(const char *name, gid_t *gid) {
}
for (i = 0; i < n; i++) {
- if (is_group(gids[i], name) > 0) {
+
+ if ((k = is_group(gids[i], name)) < 0)
+ goto finish;
+ else if (k > 0) {
*gid = gids[i];
r = 1;
goto finish;
}
}
- if (is_group(tgid = getgid(), name) > 0) {
+ if ((k = is_group(tgid = getgid(), name)) < 0)
+ goto finish;
+ else if (k > 0) {
*gid = tgid;
r = 1;
goto finish;
@@ -954,13 +1023,20 @@ int pa_uid_in_group(uid_t uid, const char *name) {
p_n = sysconf(_SC_GETPW_R_SIZE_MAX);
p_buf = pa_xmalloc(p_n);
- if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
+ errno = 0;
+ if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) {
+
+ if (!errno)
+ errno = ENOENT;
+
goto finish;
+ }
r = 0;
for (i = gr->gr_mem; *i; i++) {
struct passwd pwbuf, *pw;
+ errno = 0;
if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw)
continue;
@@ -987,8 +1063,14 @@ gid_t pa_get_gid_of_group(const char *name) {
g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
g_buf = pa_xmalloc(g_n);
- if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
+ errno = 0;
+ if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr) {
+
+ if (!errno)
+ errno = ENOENT;
+
goto finish;
+ }
ret = gr->gr_gid;
@@ -1014,19 +1096,23 @@ int pa_check_in_group(gid_t g) {
#else /* HAVE_GRP_H */
int pa_own_uid_in_group(const char *name, gid_t *gid) {
+ errno = ENOSUP;
return -1;
}
int pa_uid_in_group(uid_t uid, const char *name) {
+ errno = ENOSUP;
return -1;
}
gid_t pa_get_gid_of_group(const char *name) {
+ errno = ENOSUP;
return (gid_t) -1;
}
int pa_check_in_group(gid_t g) {
+ errno = ENOSUP;
return -1;
}
@@ -1067,6 +1153,8 @@ int pa_lock_fd(int fd, int b) {
return 0;
pa_log("%slock failed: 0x%08X", !b ? "un" : "", GetLastError());
+
+ /* FIXME: Needs to set errno! */
#endif
return -1;
@@ -1133,8 +1221,11 @@ int pa_lock_lockfile(const char *fn) {
fail:
- if (fd >= 0)
+ if (fd >= 0) {
+ int saved_errno = errno;
pa_close(fd);
+ errno = saved_errno;
+ }
return -1;
}
@@ -1180,6 +1271,7 @@ static char *get_pulse_home(void) {
if (st.st_uid != getuid()) {
pa_log_error("Home directory %s not ours.", h);
+ errno = EACCES;
return NULL;
}
@@ -1332,6 +1424,7 @@ char *pa_get_runtime_dir(void) {
/* Make sure that this actually makes sense */
if (!pa_is_path_absolute(p)) {
pa_log_error("Path %s in link %s is not absolute.", p, k);
+ errno = ENOENT;
goto fail;
}
@@ -1423,6 +1516,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
+ /* FIXME: Needs to set errno! */
return NULL;
fn = buf;
#endif
@@ -1453,6 +1547,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
+ /* FIXME: Needs to set errno! */
pa_xfree(lfn);
return NULL;
}
@@ -1481,6 +1576,7 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
+ /* FIXME: Needs to set errno! */
return NULL;
global = buf;
#endif
@@ -1492,9 +1588,9 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
return f;
}
- } else
- errno = ENOENT;
+ }
+ errno = ENOENT;
return NULL;
}
@@ -1511,6 +1607,7 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(fn, buf, PATH_MAX))
+ /* FIXME: Needs to set errno! */
return NULL;
fn = buf;
#endif
@@ -1536,6 +1633,7 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX)) {
+ /* FIXME: Needs to set errno! */
pa_xfree(lfn);
return NULL;
}
@@ -1560,14 +1658,16 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
if (global) {
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(global, buf, PATH_MAX))
+ /* FIXME: Needs to set errno! */
return NULL;
global = buf;
#endif
if (access(global, R_OK) == 0)
return pa_xstrdup(global);
- } else
- errno = ENOENT;
+ }
+
+ errno = ENOENT;
return NULL;
}
@@ -1604,6 +1704,7 @@ static int hexc(char c) {
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
+ errno = EINVAL;
return -1;
}
@@ -1742,11 +1843,16 @@ int pa_atoi(const char *s, int32_t *ret_i) {
errno = 0;
l = strtol(s, &x, 0);
- if (!x || *x || errno != 0)
+ if (!x || *x || errno) {
+ if (!errno)
+ errno = EINVAL;
return -1;
+ }
- if ((int32_t) l != l)
+ if ((int32_t) l != l) {
+ errno = ERANGE;
return -1;
+ }
*ret_i = (int32_t) l;
@@ -1764,11 +1870,16 @@ int pa_atou(const char *s, uint32_t *ret_u) {
errno = 0;
l = strtoul(s, &x, 0);
- if (!x || *x || errno != 0)
+ if (!x || *x || errno) {
+ if (!errno)
+ errno = EINVAL;
return -1;
+ }
- if ((uint32_t) l != l)
+ if ((uint32_t) l != l) {
+ errno = ERANGE;
return -1;
+ }
*ret_u = (uint32_t) l;
@@ -1786,7 +1897,6 @@ static void c_locale_destroy(void) {
int pa_atod(const char *s, double *ret_d) {
char *x = NULL;
double f;
- int r = 0;
pa_assert(s);
pa_assert(ret_d);
@@ -1812,12 +1922,15 @@ int pa_atod(const char *s, double *ret_d) {
f = strtod(s, &x);
}
- if (!x || *x || errno != 0)
- r = -1;
- else
- *ret_d = f;
+ if (!x || *x || errno) {
+ if (!errno)
+ errno = EINVAL;
+ return -1;
+ }
- return r;
+ *ret_d = f;
+
+ return 0;
}
/* Same as snprintf, but guarantees NUL-termination on every platform */
@@ -1921,6 +2034,7 @@ void *pa_will_need(const void *p, size_t l) {
if (rlim.rlim_cur < PA_PAGE_SIZE) {
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));
+ errno = EPERM;
return (void*) p;
}