]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/core-util.c
core-util: Remove redundant check of directory permissions
[pulseaudio] / src / pulsecore / core-util.c
index 19f1a836ff6e68d5e76b723b7a522b9dc9ac54ae..afd872f5d12c077ca42f1d75eca4aa0f64e2b267 100644 (file)
 #include "rtkit.h"
 #endif
 
-#ifdef __linux__
+#if defined(__linux__) && !defined(__ANDROID__)
 #include <sys/personality.h>
 #endif
 
 static pa_strlist *recorded_env = NULL;
 
 #ifdef OS_IS_WIN32
+static fd_set nonblocking_fds;
+#endif
 
-#include "poll.h"
+#ifdef OS_IS_WIN32
 
 /* Returns the directory of the current DLL, with '/bin/' removed if it is the last component */
 char *pa_win32_get_toplevel(HANDLE handle) {
@@ -179,30 +181,76 @@ char *pa_win32_get_toplevel(HANDLE handle) {
 
 #endif
 
-/** Make a file descriptor nonblock. Doesn't do any error checking */
-void pa_make_fd_nonblock(int fd) {
+static void set_nonblock(int fd, bool nonblock) {
 
 #ifdef O_NONBLOCK
-    int v;
+    int v, nv;
     pa_assert(fd >= 0);
 
     pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
 
-    if (!(v & O_NONBLOCK))
+    if (nonblock)
+        nv = v | O_NONBLOCK;
+    else
+        nv = v & ~O_NONBLOCK;
+
+    if (v != nv)
         pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
 
 #elif defined(OS_IS_WIN32)
-    u_long arg = 1;
+    u_long arg;
+
+    if (nonblock)
+        arg = 1;
+    else
+        arg = 0;
+
     if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
         pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
         pa_log_warn("Only sockets can be made non-blocking!");
+        return;
     }
+
+    /* There is no method to query status, so we remember all fds */
+    if (nonblock)
+        FD_SET(fd, &nonblocking_fds);
+    else
+        FD_CLR(fd, &nonblocking_fds);
 #else
     pa_log_warn("Non-blocking I/O not supported.!");
 #endif
 
 }
 
+/** Make a file descriptor nonblock. Doesn't do any error checking */
+void pa_make_fd_nonblock(int fd) {
+    set_nonblock(fd, true);
+}
+
+/** Make a file descriptor blocking. Doesn't do any error checking */
+void pa_make_fd_block(int fd) {
+    set_nonblock(fd, false);
+}
+
+/** Query if a file descriptor is non-blocking */
+bool pa_is_fd_nonblock(int fd) {
+
+#ifdef O_NONBLOCK
+    int v;
+    pa_assert(fd >= 0);
+
+    pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
+
+    return !!(v & O_NONBLOCK);
+
+#elif defined(OS_IS_WIN32)
+    return !!FD_ISSET(fd, &nonblocking_fds);
+#else
+    return false;
+#endif
+
+}
+
 /* Set the FD_CLOEXEC flag for a fd */
 void pa_make_fd_cloexec(int fd) {
 
@@ -278,43 +326,33 @@ again:
         goto fail;
     }
 
-    if (!update_perms)
+    if (!update_perms) {
+        pa_assert_se(pa_close(fd) >= 0);
         return 0;
+    }
 
 #ifdef HAVE_FCHOWN
     if (uid == (uid_t) -1)
         uid = getuid();
     if (gid == (gid_t) -1)
         gid = getgid();
-    if (fchown(fd, uid, gid) < 0)
+    if (((st.st_uid != uid) || (st.st_gid != gid)) && fchown(fd, uid, gid) < 0) {
+        pa_assert_se(pa_close(fd) >= 0);
         goto fail;
+    }
 #endif
 
 #ifdef HAVE_FCHMOD
-    (void) fchmod(fd, m);
+    if (fchmod(fd, m) < 0) {
+        pa_assert_se(pa_close(fd) >= 0);
+        goto fail;
+    };
 #endif
 
     pa_assert_se(pa_close(fd) >= 0);
 }
-#endif
-
-#ifdef HAVE_LSTAT
-    if (lstat(dir, &st) < 0)
 #else
-    if (stat(dir, &st) < 0)
-#endif
-        goto fail;
-
-#ifndef OS_IS_WIN32
-    if (!S_ISDIR(st.st_mode) ||
-        (st.st_uid != uid) ||
-        (st.st_gid != gid) ||
-        ((st.st_mode & 0777) != m)) {
-        errno = EACCES;
-        goto fail;
-    }
-#else
-    pa_log_warn("Secure directory creation not supported on Win32.");
+    pa_log_warn("Secure directory creation not supported on this platform.");
 #endif
 
     return 0;
@@ -370,26 +408,13 @@ ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
 #ifdef OS_IS_WIN32
 
     if (!type || *type == 0) {
-        int err;
         ssize_t r;
 
-retry:
         if ((r = recv(fd, buf, count, 0)) >= 0)
             return r;
 
-        err = WSAGetLastError();
-        if (err != WSAENOTSOCK) {
-            /* transparently handle non-blocking sockets, by waiting
-             * for readiness */
-            if (err == WSAEWOULDBLOCK) {
-                struct pollfd pfd;
-                pfd.fd = fd;
-                pfd.events = POLLIN;
-                if (pa_poll(&pfd, 1, -1) >= 0) {
-                    goto retry;
-                }
-            }
-            errno = err;
+        if (WSAGetLastError() != WSAENOTSOCK) {
+            errno = WSAGetLastError();
             return r;
         }
 
@@ -415,11 +440,7 @@ ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
 
     if (!type || *type == 0) {
         ssize_t r;
-#ifdef OS_IS_WIN32
-        int err;
 
-retry:
-#endif
         for (;;) {
             if ((r = send(fd, buf, count, MSG_NOSIGNAL)) < 0) {
 
@@ -433,19 +454,8 @@ retry:
         }
 
 #ifdef OS_IS_WIN32
-        err = WSAGetLastError();
-        if (err != WSAENOTSOCK) {
-            /* transparently handle non-blocking sockets, by waiting
-             * for readiness */
-            if (err == WSAEWOULDBLOCK) {
-                struct pollfd pfd;
-                pfd.fd = fd;
-                pfd.events = POLLOUT;
-                if (pa_poll(&pfd, 1, -1) >= 0) {
-                    goto retry;
-                }
-            }
-            errno = err;
+        if (WSAGetLastError() != WSAENOTSOCK) {
+            errno = WSAGetLastError();
             return r;
         }
 #else
@@ -531,13 +541,15 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
     return ret;
 }
 
-/** Platform independent read function. Necessary since not all
+/** Platform independent close function. Necessary since not all
  * systems treat all file descriptors equal. */
 int pa_close(int fd) {
 
 #ifdef OS_IS_WIN32
     int ret;
 
+    FD_CLR(fd, &nonblocking_fds);
+
     if ((ret = closesocket(fd)) == 0)
         return 0;
 
@@ -685,7 +697,7 @@ static int set_scheduler(int rtprio) {
 #ifdef HAVE_DBUS
     int r;
     long long rttime;
-#ifdef HAVE_SYS_RESOURCE_H
+#ifdef RLIMIT_RTTIME
     struct rlimit rl;
 #endif
     DBusError error;
@@ -727,7 +739,7 @@ static int set_scheduler(int rtprio) {
 
     rttime = rtkit_get_rttime_usec_max(bus);
     if (rttime >= 0) {
-#ifdef HAVE_SYS_RESOURCE_H
+#ifdef RLIMIT_RTTIME
         r = getrlimit(RLIMIT_RTTIME, &rl);
 
         if (r >= 0 && (long long) rl.rlim_max > rttime) {
@@ -932,6 +944,7 @@ void pa_reset_priority(void) {
 }
 
 int pa_match(const char *expr, const char *v) {
+#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
     int k;
     regex_t re;
     int r;
@@ -954,6 +967,10 @@ int pa_match(const char *expr, const char *v) {
         errno = EINVAL;
 
     return r;
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
 }
 
 /* Try to parse a boolean string value.*/
@@ -2939,7 +2956,7 @@ char *pa_machine_id(void) {
     if ((h = pa_get_host_name_malloc()))
         return h;
 
-#ifndef OS_IS_WIN32
+#if !defined(OS_IS_WIN32) && !defined(__ANDROID__)
     /* If no hostname was set we use the POSIX hostid. It's usually
      * the IPv4 address.  Might not be that stable. */
     return pa_sprintf_malloc("%08lx", (unsigned long) gethostid());
@@ -3226,7 +3243,7 @@ size_t pa_pipe_buf(int fd) {
 
 void pa_reset_personality(void) {
 
-#ifdef __linux__
+#if defined(__linux__) && !defined(__ANDROID__)
     if (personality(PER_LINUX) < 0)
         pa_log_warn("Uh, personality() failed: %s", pa_cstrerror(errno));
 #endif