[vte] lib: Move utility function to the file of its only caller



commit d7a9beeffee2f5177b5fec79cf5cdc8e5bc4f636
Author: Christian Persch <chpe src gnome org>
Date:   Mon Apr 27 20:49:04 2020 +0200

    lib: Move utility function to the file of its only caller
    
    read_ints is only used in spawn.cc, so move it there. Make a note
    that this code is copied from glib.

 po/POTFILES.in   |   1 +
 src/libc-glue.hh |  57 ++++++++++++++++++-----
 src/spawn.cc     | 125 ++++++++++++++++++++++++++++++++++++++++++++++++---
 src/vtespawn.cc  | 134 -------------------------------------------------------
 src/vtespawn.hh  |   8 ----
 5 files changed, 166 insertions(+), 159 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 69e94a0a..22dc0f9c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
 src/pty.cc
 src/vte.cc
 src/vtegtk.cc
+src/spawn.cc
diff --git a/src/libc-glue.hh b/src/libc-glue.hh
index d2a3271b..218ebf22 100644
--- a/src/libc-glue.hh
+++ b/src/libc-glue.hh
@@ -101,18 +101,6 @@ constexpr bool operator!=(FD const& lhs, int rhs) { return !(lhs == rhs); }
 
 /* FD convenience functions */
 
-static inline int
-fd_dupfd_cloexec(int oldfd,
-                 int newfd)
-{
-        auto fd = int{};
-        do {
-                fd = fcntl(F_DUPFD_CLOEXEC, oldfd, newfd);
-        } while (fd == -1 && errno == EINTR);
-
-        return fd;
-}
-
 static inline int
 fd_get_descriptor_flags(int fd)
 {
@@ -152,6 +140,45 @@ fd_change_descriptor_flags(int fd,
         return fd_set_descriptor_flags(fd, new_flags);
 }
 
+static inline int
+fd_get_status_flags(int fd)
+{
+        auto flags = int{};
+        do {
+                flags = fcntl(fd, F_GETFL, 0);
+        } while (flags == -1 && errno == EINTR);
+
+        return flags;
+}
+
+static inline int
+fd_set_status_flags(int fd,
+                    int flags)
+{
+        auto r = int{};
+        do {
+                r = fcntl(fd, F_SETFL, flags);
+        } while (r == -1 && errno == EINTR);
+
+        return r;
+}
+
+static inline int
+fd_change_status_flags(int fd,
+                       int set_flags,
+                       int unset_flags)
+{
+        auto const flags = fd_get_status_flags(fd);
+        if (flags == -1)
+                return -1;
+
+        auto const new_flags = (flags | set_flags) & ~unset_flags;
+        if (new_flags == flags)
+                return 0;
+
+        return fd_set_status_flags(fd, new_flags);
+}
+
 static inline bool
 fd_get_cloexec(int fd)
 {
@@ -171,6 +198,12 @@ fd_unset_cloexec(int fd)
         return fd_change_descriptor_flags(fd, 0, FD_CLOEXEC);
 }
 
+static inline int
+fd_set_nonblock(int fd)
+{
+        return fd_change_status_flags(fd, O_NONBLOCK, 0);
+}
+
 static inline int
 fd_dup_cloexec(int oldfd,
                int newfd)
diff --git a/src/spawn.cc b/src/spawn.cc
index b8b78311..1e337d1a 100644
--- a/src/spawn.cc
+++ b/src/spawn.cc
@@ -80,6 +80,120 @@ make_pipe(int flags,
         return true;
 }
 
+/* Code for read_ints copied from glib/glib/gspawn.c, there under LGPL2.1+,
+ * and used here under LGPL3+.
+ *
+ * Copyright 2000 Red Hat, Inc.
+ */
+static bool
+read_ints(int fd,
+          int* buf,
+          int n_ints_in_buf,
+          int *n_ints_read,
+          int timeout,
+          GPollFD *cancellable_pollfd,
+          vte::glib::Error& error)
+{
+        GPollFD pollfds[2];
+        auto n_pollfds = unsigned{0};
+
+        if (timeout >= 0 || cancellable_pollfd != nullptr) {
+                if (vte::libc::fd_set_nonblock(fd) < 0) {
+                        auto errsv = vte::libc::ErrnoSaver{};
+                        error.set(G_IO_ERROR, g_io_error_from_errno(errsv),
+                                  _("Failed to set pipe nonblocking: %s"), g_strerror(errsv));
+                        return false;
+                }
+
+                pollfds[0].fd = fd;
+                pollfds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+                n_pollfds = 1;
+
+                if (cancellable_pollfd != nullptr) {
+                        pollfds[1] = *cancellable_pollfd;
+                        n_pollfds = 2;
+                }
+        } else
+                n_pollfds = 0;
+
+        auto start_time = int64_t{0};
+        if (timeout >= 0)
+                start_time = g_get_monotonic_time();
+
+        auto bytes = size_t{0};
+        while (true) {
+                if (bytes >= sizeof(int)*2)
+                        break; /* give up, who knows what happened, should not be
+                                * possible.
+                                */
+
+        again:
+                if (n_pollfds != 0) {
+                        pollfds[0].revents = pollfds[1].revents = 0;
+
+                        auto const r = g_poll(pollfds, n_pollfds, timeout);
+
+                        /* Update timeout */
+                        if (timeout >= 0) {
+                                timeout -= (g_get_monotonic_time () - start_time) / 1000;
+                                if (timeout < 0)
+                                        timeout = 0;
+                        }
+
+                        if (r < 0 && errno == EINTR)
+                                goto again;
+                        if (r < 0) {
+                                auto errsv = vte::libc::ErrnoSaver{};
+                                error.set(G_IO_ERROR, g_io_error_from_errno(errsv),
+                                          _("poll error: %s"), g_strerror(errsv));
+                                return false;
+                        }
+                        if (r == 0) {
+                                auto errsv = vte::libc::ErrnoSaver{};
+                                error.set_literal(G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+                                                  _("Operation timed out"));
+                                return false;
+                        }
+
+                        /* If the passed-in poll FD becomes readable, that's the signal
+                         * to cancel the operation. We do NOT actually read from its FD!
+                         */
+                        if (n_pollfds == 2 && pollfds[1].revents) {
+                                auto errsv = vte::libc::ErrnoSaver{};
+                                error.set_literal(G_IO_ERROR, G_IO_ERROR_CANCELLED,
+                                                  _("Operation was cancelled"));
+                                return false;
+                        }
+
+                        /* Now we know we can try to read from the child */
+                }
+
+                auto const chunk = read(fd,
+                                        ((char*)buf) + bytes,
+                                        sizeof(int) * n_ints_in_buf - bytes);
+                if (chunk < 0 && errno == EINTR)
+                        goto again;
+
+                if (chunk < 0) {
+                        auto errsv = vte::libc::ErrnoSaver{};
+
+                        /* Some weird shit happened, bail out */
+                        error.set(G_IO_ERROR, g_io_error_from_errno(errsv),
+                                  _("Failed to read from child pipe (%s)"),
+                                  g_strerror(errsv));
+
+                        return false;
+                } else if (chunk == 0)
+                        break; /* EOF */
+                else /* chunk > 0 */
+                        bytes += chunk;
+        }
+
+        *n_ints_read = int(bytes / sizeof(int));
+
+        return true;
+}
+
 static char**
 merge_environ(char** envp /* consumed */,
               char const* cwd,
@@ -437,11 +551,12 @@ SpawnOperation::run(vte::glib::Error& error) noexcept
         g_assert_cmpint(m_child_report_error_pipe_read.get(), !=, -1);
         assert(m_child_report_error_pipe_read);
 
-        if (!_vte_read_ints(m_child_report_error_pipe_read.get(),
-                            buf, 2, &n_read,
-                            m_timeout,
-                            &m_cancellable_pollfd,
-                            error))
+        if (!read_ints(m_child_report_error_pipe_read.get(),
+                       buf, 2,
+                       &n_read,
+                       m_timeout,
+                       &m_cancellable_pollfd,
+                       error))
                 return false;
 
         if (n_read >= 2) {
diff --git a/src/vtespawn.cc b/src/vtespawn.cc
index 662968be..2bb285a3 100644
--- a/src/vtespawn.cc
+++ b/src/vtespawn.cc
@@ -73,17 +73,6 @@ _vte_write_err (int fd,
         write_all(fd, data, sizeof(data));
 }
 
-static int
-fd_set_nonblocking(int fd)
-{
-        int flags = fcntl(fd, F_GETFL, 0);
-        if (flags < 0)
-                return -1;
-        if ((flags & O_NONBLOCK) != 0)
-                return 0;
-        return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-}
-
 G_GNUC_UNUSED static int
 close_func (void *data, int fd)
 {
@@ -93,129 +82,6 @@ close_func (void *data, int fd)
   return 0;
 }
 
-bool
-_vte_read_ints(int      fd,
-               int*    buf,
-               int     n_ints_in_buf,
-               int    *n_ints_read,
-               int     timeout,
-               GPollFD *cancellable_pollfd,
-               GError **error)
-{
-  gsize bytes = 0;
-  GPollFD pollfds[2];
-  guint n_pollfds;
-  int64_t start_time = 0;
-
-  if (timeout >= 0 || cancellable_pollfd != nullptr)
-    {
-      if (fd_set_nonblocking(fd) < 0)
-        {
-          int errsv = errno;
-          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
-                       _("Failed to set pipe nonblocking: %s"), g_strerror (errsv));
-          return false;
-        }
-
-      pollfds[0].fd = fd;
-      pollfds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
-      n_pollfds = 1;
-
-      if (cancellable_pollfd != NULL)
-        {
-          pollfds[1] = *cancellable_pollfd;
-          n_pollfds = 2;
-        }
-    }
-  else
-    n_pollfds = 0;
-
-  if (timeout >= 0)
-    start_time = g_get_monotonic_time ();
-
-  while (true)
-    {
-      gssize chunk;
-
-      if (bytes >= sizeof(int)*2)
-        break; /* give up, who knows what happened, should not be
-                * possible.
-                */
-
-    again:
-      if (n_pollfds != 0)
-        {
-          int r;
-
-          pollfds[0].revents = pollfds[1].revents = 0;
-
-          r = g_poll (pollfds, n_pollfds, timeout);
-
-          /* Update timeout */
-          if (timeout >= 0)
-            {
-              timeout -= (g_get_monotonic_time () - start_time) / 1000;
-              if (timeout < 0)
-                timeout = 0;
-            }
-
-          if (r < 0 && errno == EINTR)
-            goto again;
-          if (r < 0)
-            {
-              int errsv = errno;
-              g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
-                           _("poll error: %s"), g_strerror (errsv));
-              return false;
-            }
-          if (r == 0)
-            {
-              g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
-                                   _("Operation timed out"));
-              return false;
-            }
-
-          /* If the passed-in poll FD becomes readable, that's the signal
-           * to cancel the operation. We do NOT actually read from its FD!
-           */
-          if (n_pollfds == 2 && pollfds[1].revents)
-            {
-              g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
-                                   _("Operation was cancelled"));
-              return false;
-            }
-
-          /* Now we know we can try to read from the child */
-        }
-
-      chunk = read (fd,
-                    ((char*)buf) + bytes,
-                    sizeof(int) * n_ints_in_buf - bytes);
-      if (chunk < 0 && errno == EINTR)
-        goto again;
-
-      if (chunk < 0)
-        {
-          int errsv = errno;
-
-          /* Some weird shit happened, bail out */
-          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
-                       _("Failed to read from child pipe (%s)"),
-                       g_strerror (errsv));
-
-          return false;
-        }
-      else if (chunk == 0)
-        break; /* EOF */
-      else /* chunk > 0 */
-       bytes += chunk;
-    }
-
-  *n_ints_read = int(bytes / sizeof(int));
-
-  return true;
-}
-
 /* Based on execvp from GNU C Library */
 
 static void
diff --git a/src/vtespawn.hh b/src/vtespawn.hh
index 908fcbe9..481929cf 100644
--- a/src/vtespawn.hh
+++ b/src/vtespawn.hh
@@ -28,13 +28,5 @@ int _vte_execute(char const* file,
                  bool search_path,
                  bool search_path_from_envp);
 
-bool _vte_read_ints(int     fd,
-                    int*    buf,
-                    int     n_ints_in_buf,
-                    int    *n_ints_read,
-                    int     timeout,
-                    GPollFD *cancellable_pollfd,
-                    GError **error);
-
 void _vte_write_err (int fd,
                      int msg);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]