]> git.sesse.net Git - vlc/blobdiff - modules/stream_filter/decomp.c
decomp: inclde spawn.h only if used
[vlc] / modules / stream_filter / decomp.c
index aa183e5c71b4c4fb85974becdbe460f45ec48035..2466b47150ef36f5e7678c60b747b51e82bdb2ca 100644 (file)
 #include <vlc_stream.h>
 #include <vlc_network.h>
 #include <unistd.h>
+#ifndef _POSIX_SPAWN
+# define _POSIX_SPAWN (-1)
+#endif
 #include <fcntl.h>
-#include <spawn.h>
+#if (_POSIX_SPAWN >= 0)
+# include <spawn.h>
+#endif
 #include <sys/wait.h>
 #include <sys/ioctl.h>
-#ifdef __linux__
+#if defined (__linux__) && defined (HAVE_VMSPLICE)
 # include <sys/uio.h>
 # include <sys/mman.h>
+#else
+# undef HAVE_VMSPLICE
 #endif
 
-#include <assert.h>
-
 static int  OpenGzip (vlc_object_t *);
 static int  OpenBzip2 (vlc_object_t *);
 static void Close (vlc_object_t *);
@@ -72,16 +77,20 @@ static void cloexec (int fd)
 extern char **environ;
 
 static const size_t bufsize = 65536;
+#ifdef HAVE_VMSPLICE
 static void cleanup_mmap (void *addr)
 {
     munmap (addr, bufsize);
 }
-
+#endif
 
 static void *Thread (void *data)
 {
     stream_t *stream = data;
     stream_sys_t *p_sys = stream->p_sys;
+#ifdef HAVE_VMSPLICE
+    ssize_t page_mask = sysconf (_SC_PAGE_SIZE) - 1;
+#endif
     int fd = p_sys->write_fd;
     bool error = false;
 
@@ -89,7 +98,7 @@ static void *Thread (void *data)
     {
         ssize_t len;
         int canc = vlc_savecancel ();
-#ifdef __linux__
+#ifdef HAVE_VMSPLICE
         unsigned char *buf = mmap (NULL, bufsize, PROT_READ|PROT_WRITE,
                                    MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
         vlc_cleanup_push (cleanup_mmap, buf);
@@ -99,18 +108,20 @@ static void *Thread (void *data)
 
         len = stream_Read (stream->p_source, buf, bufsize);
         vlc_restorecancel (canc);
+        error = len <= 0;
 
-        if (len <= 0)
-            break;
-
-        for (ssize_t i = 0, j = 0; i < len; i += j)
+        for (ssize_t i = 0, j; i < len; i += j)
         {
-            struct iovec iov[1] = { { buf + i, len - i, } };
-
-#ifdef __linux__
-            j = vmsplice (fd, iov, 1, SPLICE_F_GIFT);
+#ifdef HAVE_VMSPLICE
+            if ((len - i) <= page_mask) /* incomplete last page */
+                j = write (fd, buf + i, len - i);
+            else
+            {
+                struct iovec iov = { buf + i, (len - i) & ~page_mask, };
+                j = vmsplice (fd, &iov, 1, SPLICE_F_GIFT);
+            }
 #else
-            j = writev (fd, iov, 1);
+            j = write (fd, buf + i, len - i);
 #endif
             if (j <= 0)
             {
@@ -121,7 +132,7 @@ static void *Thread (void *data)
                 break;
             }
         }
-#ifdef __linux__
+#ifdef HAVE_VMSPLICE
         vlc_cleanup_run (); /* munmap (buf, bufsize) */
 #endif
     }
@@ -249,6 +260,8 @@ static int Open (stream_t *stream, const char *path)
     int ret = VLC_EGENERIC;
     int comp[2];
 
+    /* We use two pipes rather than one stream socket pair, so that we can
+     * use vmsplice() on Linux. */
     if (pipe (comp) == 0)
     {
         cloexec (comp[1]);
@@ -260,6 +273,7 @@ static int Open (stream_t *stream, const char *path)
             cloexec (uncomp[0]);
             p_sys->read_fd = uncomp[0];
 
+#if (_POSIX_SPAWN >= 0)
             posix_spawn_file_actions_t actions;
             if (posix_spawn_file_actions_init (&actions) == 0)
             {
@@ -283,6 +297,25 @@ static int Open (stream_t *stream, const char *path)
                 }
                 posix_spawn_file_actions_destroy (&actions);
             }
+#else /* _POSIX_SPAWN */
+            switch (p_sys->pid = fork ())
+            {
+                case -1:
+                    msg_Err (stream, "Cannot fork (%m)");
+                    break;
+                case 0:
+                    dup2 (comp[0], 0);
+                    close (comp[0]);
+                    dup2 (uncomp[1], 1);
+                    close (uncomp[1]);
+                    execlp (path, path, (char *)NULL);
+                    exit (1); /* if we get, execlp() failed! */
+                default:
+                    if (vlc_clone (&p_sys->thread, Thread, stream,
+                                   VLC_THREAD_PRIORITY_INPUT) == 0)
+                        ret = VLC_SUCCESS;
+            }
+#endif /* _POSIX_SPAWN < 0 */
             close (uncomp[1]);
             if (ret != VLC_SUCCESS)
                 close (uncomp[0]);