This hides the differences between Windows and UNIX,
and adds standard error reporting.

Signed-off-by: Daniel P. Berrangé <berra...@redhat.com>
---
 configure.ac             |  1 +
 src/libvirt_private.syms |  3 ++
 src/util/virutil.c       | 64 ++++++++++++++++++++++++++++++++++++++++
 src/util/virutil.h       | 34 +++++++++++++++++++++
 4 files changed, 102 insertions(+)

diff --git a/configure.ac b/configure.ac
index 0964ab8d51..005753e8a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -369,6 +369,7 @@ AC_CHECK_FUNCS_ONCE([\
   newlocale \
   posix_fallocate \
   posix_memalign \
+  pipe2 \
   prlimit \
   sched_getaffinity \
   sched_setscheduler \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 674f553403..56981541c5 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3394,6 +3394,9 @@ virMemoryLimitTruncate;
 virMemoryMaxValue;
 virParseOwnershipIds;
 virParseVersionString;
+virPipe;
+virPipeNonBlock;
+virPipeQuiet;
 virScaleInteger;
 virSetBlocking;
 virSetCloseExec;
diff --git a/src/util/virutil.c b/src/util/virutil.c
index fa6b56fd79..d5f3e72ba9 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -1769,3 +1769,67 @@ char *virGetPassword(void)
     return g_strdup(getpass(""));
 #endif /* ! WIN32 */
 }
+
+
+static int
+virPipeImpl(int fds[2], bool nonblock, bool errreport)
+{
+#ifdef HAVE_PIPE2
+    int flags = O_CLOEXEC;
+    if (nonblock)
+        flags |= O_NONBLOCK;
+    int rv = pipe2(fds, flags);
+#else /* !HAVE_PIPE2 */
+# ifdef WIN32
+    int rv = _pipe(fds, 4096, _O_BINARY);
+# else /* !WIN32 */
+    int rv = pipe(fds);
+# endif /* !WIN32 */
+#endif /* !HAVE_PIPE2 */
+
+    if (rv < 0) {
+        if (errreport)
+            virReportSystemError(errno, "%s",
+                                 _("Unable to create pipes"));
+        return rv;
+    }
+
+#ifndef HAVE_PIPE2
+    if (nonblock) {
+        if (virSetNonBlock(fds[0]) < 0 ||
+            virSetNonBlock(fds[1]) < 0) {
+            if (errreport)
+                virReportSystemError(errno, "%s",
+                                     _("Unable to set pipes to non-blocking"));
+            virReportSystemError(errno, "%s",
+                                 _("Unable to create pipes"));
+            VIR_FORCE_CLOSE(fds[0]);
+            VIR_FORCE_CLOSE(fds[1]);
+            return -1;
+        }
+    }
+#endif /* !HAVE_PIPE2 */
+
+    return 0;
+}
+
+
+int
+virPipe(int fds[2])
+{
+    return virPipeImpl(fds, false, true);
+}
+
+
+int
+virPipeQuiet(int fds[2])
+{
+    return virPipeImpl(fds, false, false);
+}
+
+
+int
+virPipeNonBlock(int fds[2])
+{
+    return virPipeImpl(fds, true, true);
+}
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 62a53f34cb..7377c8c8da 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -161,3 +161,37 @@ char *virHostGetDRMRenderNode(void) G_GNUC_NO_INLINE;
     (((lvalue) = (rvalue)) != (rvalue))
 
 char *virGetPassword(void);
+
+/*
+ * virPipe:
+ *
+ * Open a pair of FDs which can be used to communicate
+ * with each other. The FDs will have O_CLOEXEC set.
+ * This will report a libvirt error on failure.
+ *
+ * Returns: -1 on error, 0 on success
+ */
+int virPipe(int fds[2]);
+
+/*
+ * virPipeQuiet:
+ *
+ * Open a pair of FDs which can be used to communicate
+ * with each other. The FDs will have O_CLOEXEC set.
+ * This will set errno on failure.
+ *
+ * Returns: -1 on error, 0 on success
+ */
+int virPipeQuiet(int fds[2]);
+
+/*
+ * virPipe:
+ *
+ * Open a pair of FDs which can be used to communicate
+ * with each other. The FDs will have O_CLOEXEC and
+ * O_NONBLOCK set.
+ * This will report a libvirt error on failure.
+ *
+ * Returns: -1 on error, 0 on success
+ */
+int virPipeNonBlock(int fds[2]);
-- 
2.24.1

Reply via email to