]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/core-util.c
adjust various data/library paths automatically if we are run from a build tree
[pulseaudio] / src / pulsecore / core-util.c
index 04e7eb24cafd6a5ca3bc8c6528a5a9d33008f74c..843c8377c850e644835135f75307bea2c119cf04 100644 (file)
 #include "rtkit.h"
 #endif
 
+#ifdef __linux__
+#include <sys/personality.h>
+#endif
+
 #include <pulse/xmalloc.h>
 #include <pulse/util.h>
 #include <pulse/utf8.h>
@@ -552,12 +556,20 @@ char *pa_vsprintf_malloc(const char *format, va_list ap) {
 
 /* Similar to OpenBSD's strlcpy() function */
 char *pa_strlcpy(char *b, const char *s, size_t l) {
+    size_t k;
+
     pa_assert(b);
     pa_assert(s);
     pa_assert(l > 0);
 
-    strncpy(b, s, l);
-    b[l-1] = 0;
+    k = strlen(s);
+
+    if (k > l-1)
+        k = l-1;
+
+    memcpy(b, s, k);
+    b[k] = 0;
+
     return b;
 }
 
@@ -963,6 +975,7 @@ static int is_group(gid_t gid, const char *name) {
     int r = -1;
 
 #ifdef HAVE_GETGRGID_R
+
 #ifdef _SC_GETGR_R_SIZE_MAX
     n = sysconf(_SC_GETGR_R_SIZE_MAX);
 #else
@@ -973,38 +986,25 @@ static int is_group(gid_t gid, const char *name) {
 
     data = pa_xmalloc((size_t) n);
 
+    if ((errno = getgrgid_r(gid, &group, data, (size_t) n, &result)) || !result)
+#else
     errno = 0;
-    if (getgrgid_r(gid, &group, data, (size_t) n, &result) < 0 || !result) {
-        pa_log("getgrgid_r(%u): %s", (unsigned) gid, pa_cstrerror(errno));
-
+    if (!(result = getgrgid(gid)))
+#endif
+    {
         if (!errno)
             errno = ENOENT;
 
-        goto finish;
-    }
-
-    r = strcmp(name, result->gr_name) == 0;
-
-finish:
-    pa_xfree(data);
-#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))) {
         pa_log("getgrgid(%u): %s", gid, pa_cstrerror(errno));
 
-        if (!errno)
-            errno = ENOENT;
-
         goto finish;
     }
 
     r = strcmp(name, result->gr_name) == 0;
 
 finish:
-#endif
+
+    pa_xfree(data);
 
     return r;
 }
@@ -1053,12 +1053,14 @@ finish:
 
 /* Check whether the specifc user id is a member of the specified group */
 int pa_uid_in_group(uid_t uid, const char *name) {
-    char *g_buf, *p_buf;
+    char *g_buf = NULL, *p_buf = NULL;
     long g_n, p_n;
-    struct group grbuf, *gr;
+    struct group grbuf, *gr = NULL;
     char **i;
     int r = -1;
 
+#ifdef HAVE_GETGRNAM_R
+
 #ifdef _SC_GETGR_R_SIZE_MAX
     g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
 #else
@@ -1069,6 +1071,19 @@ int pa_uid_in_group(uid_t uid, const char *name) {
 
     g_buf = pa_xmalloc((size_t) g_n);
 
+    if ((errno = getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr)) != 0 || !gr)
+#else
+    errno = 0;
+    if (!(gr = getgrnam(name)))
+#endif
+    {
+        if (!errno)
+            errno = ENOENT;
+        goto finish;
+    }
+
+#ifdef HAVE_GETPWNAM_R
+
 #ifdef _SC_GETPW_R_SIZE_MAX
     p_n = sysconf(_SC_GETPW_R_SIZE_MAX);
 #else
@@ -1078,26 +1093,16 @@ int pa_uid_in_group(uid_t uid, const char *name) {
         p_n = 512;
 
     p_buf = pa_xmalloc((size_t) p_n);
-
-    errno = 0;
-#ifdef HAVE_GETGRNAM_R
-    if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
-#else
-    if (!(gr = getgrnam(name)))
 #endif
-    {
-        if (!errno)
-            errno = ENOENT;
-        goto finish;
-    }
 
     r = 0;
     for (i = gr->gr_mem; *i; i++) {
-        struct passwd pwbuf, *pw;
+        struct passwd pwbuf, *pw = NULL;
 
 #ifdef HAVE_GETPWNAM_R
-        if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw)
+        if ((errno = getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw)) != 0 || !pw)
 #else
+        errno = 0;
         if (!(pw = getpwnam(*i)))
 #endif
             continue;
@@ -1118,9 +1123,11 @@ finish:
 /* Get the GID of a gfiven group, return (gid_t) -1 on failure. */
 gid_t pa_get_gid_of_group(const char *name) {
     gid_t ret = (gid_t) -1;
-    char *g_buf;
+    char *g_buf = NULL;
     long g_n;
-    struct group grbuf, *gr;
+    struct group grbuf, *gr = NULL;
+
+#ifdef HAVE_GETGRNAM_R
 
 #ifdef _SC_GETGR_R_SIZE_MAX
     g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
@@ -1132,10 +1139,9 @@ gid_t pa_get_gid_of_group(const char *name) {
 
     g_buf = pa_xmalloc((size_t) g_n);
 
-    errno = 0;
-#ifdef HAVE_GETGRNAM_R
-    if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
+    if ((errno = getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr)) != 0 || !gr)
 #else
+    errno = 0;
     if (!(gr = getgrnam(name)))
 #endif
     {
@@ -1328,26 +1334,32 @@ int pa_unlock_lockfile(const char *fn, int fd) {
 }
 
 static char *get_pulse_home(void) {
-    char h[PATH_MAX];
+    char *h;
     struct stat st;
+    char *ret = NULL;
 
-    if (!pa_get_home_dir(h, sizeof(h))) {
+    if (!(h = pa_get_home_dir_malloc())) {
         pa_log_error("Failed to get home directory.");
         return NULL;
     }
 
     if (stat(h, &st) < 0) {
         pa_log_error("Failed to stat home directory %s: %s", h, pa_cstrerror(errno));
-        return NULL;
+        goto finish;
     }
 
     if (st.st_uid != getuid()) {
         pa_log_error("Home directory %s not ours.", h);
         errno = EACCES;
-        return NULL;
+        goto finish;
     }
 
-    return pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
+    ret = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse", h);
+
+finish:
+    pa_xfree(h);
+
+    return ret;
 }
 
 char *pa_get_state_dir(void) {
@@ -1372,6 +1384,50 @@ char *pa_get_state_dir(void) {
     return d;
 }
 
+char *pa_get_home_dir_malloc(void) {
+    char *homedir;
+    size_t allocated = 128;
+
+    for (;;) {
+        homedir = pa_xmalloc(allocated);
+
+        if (!pa_get_home_dir(homedir, allocated)) {
+            pa_xfree(homedir);
+            return NULL;
+        }
+
+        if (strlen(homedir) < allocated - 1)
+            break;
+
+        pa_xfree(homedir);
+        allocated *= 2;
+    }
+
+    return homedir;
+}
+
+char *pa_get_binary_name_malloc(void) {
+    char *t;
+    size_t allocated = 128;
+
+    for (;;) {
+        t = pa_xmalloc(allocated);
+
+        if (!pa_get_binary_name(t, allocated)) {
+            pa_xfree(t);
+            return NULL;
+        }
+
+        if (strlen(t) < allocated - 1)
+            break;
+
+        pa_xfree(t);
+        allocated *= 2;
+    }
+
+    return t;
+}
+
 static char* make_random_dir(mode_t m) {
     static const char table[] =
         "abcdefghijklmnopqrstuvwxyz"
@@ -1481,7 +1537,7 @@ char *pa_get_runtime_dir(void) {
         goto fail;
     }
 
-    k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:runtime", d, mid);
+    k = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-runtime", d, mid);
     pa_xfree(d);
     pa_xfree(mid);
 
@@ -1626,14 +1682,15 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
     if (local) {
         const char *e;
         char *lfn;
-        char h[PATH_MAX];
+        char *h;
         FILE *f;
 
         if ((e = getenv("PULSE_CONFIG_PATH")))
             fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
-        else if (pa_get_home_dir(h, sizeof(h)))
+        else if ((h = pa_get_home_dir_malloc())) {
             fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
-        else
+            pa_xfree(h);
+        } else
             return NULL;
 
 #ifdef OS_IS_WIN32
@@ -1713,13 +1770,14 @@ char *pa_find_config_file(const char *global, const char *local, const char *env
     if (local) {
         const char *e;
         char *lfn;
-        char h[PATH_MAX];
+        char *h;
 
         if ((e = getenv("PULSE_CONFIG_PATH")))
             fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", e, local);
-        else if (pa_get_home_dir(h, sizeof(h)))
+        else if ((h = pa_get_home_dir_malloc())) {
             fn = lfn = pa_sprintf_malloc("%s" PA_PATH_SEP ".pulse" PA_PATH_SEP "%s", h, local);
-        else
+            pa_xfree(h);
+        } else
             return NULL;
 
 #ifdef OS_IS_WIN32
@@ -1904,7 +1962,7 @@ static char *get_path(const char *fn, pa_bool_t prependmid, pa_bool_t rt) {
                 return NULL;
             }
 
-            r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s:%s", rtp, mid, fn);
+            r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s-%s", rtp, mid, fn);
             pa_xfree(mid);
         } else
             r = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", rtp, fn);
@@ -2779,3 +2837,47 @@ char* pa_maybe_prefix_path(const char *path, const char *prefix) {
 
     return pa_sprintf_malloc("%s" PA_PATH_SEP "%s", prefix, path);
 }
+
+size_t pa_pipe_buf(int fd) {
+
+#ifdef _PC_PIPE_BUF
+    long n;
+
+    if ((n = fpathconf(fd, _PC_PIPE_BUF)) >= 0)
+        return (size_t) n;
+#endif
+
+#ifdef PIPE_BUF
+    return PIPE_BUF;
+#else
+    return 4096;
+#endif
+}
+
+void pa_reset_personality(void) {
+
+#ifdef __linux__
+    if (personality(PER_LINUX) < 0)
+        pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
+#endif
+
+}
+
+#if defined(__linux__) && !defined(__OPTIMIZE__)
+
+pa_bool_t pa_run_from_build_tree(void) {
+    char *rp;
+    pa_bool_t b = FALSE;
+
+    /* We abuse __OPTIMIZE__ as a check whether we are a debug build
+     * or not. */
+
+    if ((rp = pa_readlink("/proc/self/exe"))) {
+        b = pa_startswith(rp, PA_BUILDDIR);
+        pa_xfree(rp);
+    }
+
+    return b;
+}
+
+#endif