]> code.delx.au - pulseaudio/blobdiff - polyp/util.c
Make the whole stuff LGPL only
[pulseaudio] / polyp / util.c
index 6e97bae4a9f455900b3e277236b09c51b7cf4204..e8a47df0c7042cb37935cc07bae8fd01eae7b75f 100644 (file)
@@ -4,17 +4,17 @@
   This file is part of polypaudio.
  
   polypaudio is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
-  or (at your option) any later version.
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
  
   polypaudio is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  General Public License for more details.
+  Lesser General Public License for more details.
  
-  You should have received a copy of the GNU General Public License
-  along with polypaudio; if not, write to the Free Software
+  You should have received a copy of the GNU Lesser General Public
+  License along with polypaudio; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA.
 ***/
@@ -43,6 +43,7 @@
 #include <limits.h>
 #include <unistd.h>
 #include <grp.h>
+#include <netdb.h>
 
 #include <samplerate.h>
 
@@ -50,6 +51,8 @@
 #include "xmalloc.h"
 #include "log.h"
 
+#define PA_RUNTIME_PATH_PREFIX "/tmp/polypaudio-"
+
 /** Make a file descriptor nonblock. Doesn't do any error checking */
 void pa_make_nonblock_fd(int fd) {
     int v;
@@ -82,6 +85,26 @@ fail:
     return -1;
 }
 
+/* Creates a the parent directory of the specified path securely */
+int pa_make_secure_parent_dir(const char *fn) {
+    int ret = -1;
+    char *slash, *dir = pa_xstrdup(fn);
+    
+    if (!(slash = strrchr(dir, '/')))
+        goto finish;
+    *slash = 0;
+    
+    if (pa_make_secure_dir(dir) < 0)
+        goto finish;
+
+    ret = 0;
+    
+finish:
+    pa_xfree(dir);
+    return ret;
+}
+
+
 /** Calls read() in a loop. Makes sure that as much as 'size' bytes,
  * unless EOF is reached or an error occured */
 ssize_t pa_loop_read(int fd, void*data, size_t size) {
@@ -224,31 +247,32 @@ char *pa_get_user_name(char *s, size_t l) {
     char *p;
     assert(s && l > 0);
 
-    if (!(p = getenv("USER")))
-        if (!(p = getenv("LOGNAME")))
-            if (!(p = getenv("USERNAME"))) {
-                
+    if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
+        
 #ifdef HAVE_GETPWUID_R
-                if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
+        if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
 #else
-               /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
-                * that do not support getpwuid_r. */
-               if ((r = getpwuid(getuid())) == NULL) {
+            /* XXX Not thread-safe, but needed on OSes (e.g. FreeBSD 4.X)
+             * that do not support getpwuid_r. */
+            if ((r = getpwuid(getuid())) == NULL) {
 #endif
-                    snprintf(s, l, "%lu", (unsigned long) getuid());
-                    return s;
-                }
-                
-                p = r->pw_name;
+                snprintf(s, l, "%lu", (unsigned long) getuid());
+                return s;
             }
+            
+            p = r->pw_name;
+        }
 
     return pa_strlcpy(s, p, l);
-}
+    }
 
 /* Return the current hostname in the specified buffer. */
 char *pa_get_host_name(char *s, size_t l) {
     assert(s && l > 0);
-    gethostname(s, l);
+    if (gethostname(s, l) < 0) {
+        pa_log(__FILE__": gethostname(): %s\n", strerror(errno));
+        return NULL;
+    }
     s[l-1] = 0;
     return s;
 }
@@ -263,8 +287,10 @@ char *pa_get_home_dir(char *s, size_t l) {
     if ((e = getenv("HOME")))
         return pa_strlcpy(s, e, l);
 
-    if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r)
+    if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
+        pa_log(__FILE__": getpwuid_r() failed\n");
         return NULL;
+    }
 
     return pa_strlcpy(s, r->pw_dir, l);
 }
@@ -478,7 +504,7 @@ char *pa_split_spaces(const char *c, const char **state) {
     const char *current = *state ? *state : c;
     size_t l;
 
-    if (!*current)
+    if (!*current || *c == 0)
         return NULL;
 
     current += strspn(current, WHITESPACE);
@@ -715,3 +741,102 @@ FILE *pa_open_config_file(const char *global, const char *local, const char *env
     return fopen(global, "r");
 }
                  
+/* Format the specified data as a hexademical string */
+char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
+    size_t i = 0, j = 0;
+    const char hex[] = "0123456789abcdef";
+    assert(d && s && slength > 0);
+
+    while (i < dlength && j+3 <= slength) {
+        s[j++] = hex[*d >> 4];
+        s[j++] = hex[*d & 0xF];
+
+        d++;
+        i++;
+    }
+
+    s[j < slength ? j : slength] = 0;
+    return s;
+}
+
+/* Convert a hexadecimal digit to a number or -1 if invalid */
+static int hexc(char c) {
+    if (c >= '0' && c <= '9')
+        return c - '0';
+
+    if (c >= 'A' && c <= 'F')
+        return c - 'A' + 10;
+
+    if (c >= 'a' && c <= 'f')
+        return c - 'a' + 10;
+
+    return -1;
+}
+
+/* Parse a hexadecimal string as created by pa_hexstr() to a BLOB */
+size_t pa_parsehex(const char *p, uint8_t *d, size_t dlength) {
+    size_t j = 0;
+    assert(p && d);
+
+    while (j < dlength && *p) {
+        int b;
+
+        if ((b = hexc(*(p++))) < 0)
+            return (size_t) -1;
+        
+        d[j] = (uint8_t) (b << 4);
+
+        if (!*p)
+            return (size_t) -1;
+
+        if ((b = hexc(*(p++))) < 0)
+            return (size_t) -1;
+
+        d[j] |= (uint8_t) b;
+        j++;
+    }
+
+    return j;
+}
+
+/* Return the fully qualified domain name in *s */
+char *pa_get_fqdn(char *s, size_t l) {
+    char hn[256];
+    struct addrinfo *a, hints;
+
+    if (!pa_get_host_name(hn, sizeof(hn)))
+        return NULL;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_flags = AI_CANONNAME;
+    
+    if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname)
+        return pa_strlcpy(s, hn, l);
+
+    pa_strlcpy(s, a->ai_canonname, l);
+    freeaddrinfo(a);
+    return s;
+}
+
+/* Returns nonzero when *s starts with *pfx */
+int pa_startswith(const char *s, const char *pfx) {
+    size_t l;
+    assert(s && pfx);
+    l = strlen(pfx);
+
+    return strlen(s) >= l && strncmp(s, pfx, l) == 0;
+}
+
+/* if fn is null return the polypaudio run time path in s (/tmp/polypaudio)
+ * if fn is non-null and starts with / return fn in s
+ * otherwise append fn to the run time path and return it in s */
+char *pa_runtime_path(const char *fn, char *s, size_t l) {
+    char u[256];
+
+    if (fn && *fn == '/')
+        return pa_strlcpy(s, fn, l);
+    
+    snprintf(s, l, PA_RUNTIME_PATH_PREFIX"%s%s%s", pa_get_user_name(u, sizeof(u)), fn ? "/" : "", fn ? fn : "");
+    return s;
+}