#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) {
#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) {
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;
#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;
}
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) {
}
#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
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;
#ifdef HAVE_DBUS
int r;
long long rttime;
-#ifdef HAVE_SYS_RESOURCE_H
+#ifdef RLIMIT_RTTIME
struct rlimit rl;
#endif
DBusError error;
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) {
}
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;
errno = EINVAL;
return r;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
}
/* Try to parse a boolean string value.*/
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());
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