[vlc-commits] block: add read-only shared file mappings (fixes #17544)

Rémi Denis-Courmont git at videolan.org
Wed Oct 26 10:01:37 CEST 2016


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Oct 26 11:01:14 2016 +0300| [cdf1d460ae461b06e15f71804fbdbf09fd61e5cd] | committer: Rémi Denis-Courmont

block: add read-only shared file mappings (fixes #17544)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=cdf1d460ae461b06e15f71804fbdbf09fd61e5cd
---

 include/vlc_block.h             |  9 +++++++--
 modules/access/screen/wayland.c |  2 +-
 modules/access/shm.c            |  2 +-
 modules/misc/gnutls.c           |  4 ++--
 src/misc/block.c                | 13 ++++++++-----
 src/modules/cache.c             |  2 +-
 src/test/block_test.c           |  9 ++++++---
 7 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/include/vlc_block.h b/include/vlc_block.h
index 0d11c38..53ed91e 100644
--- a/include/vlc_block.h
+++ b/include/vlc_block.h
@@ -271,19 +271,24 @@ VLC_API block_t * block_shm_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC
  * due to memory space constraints.
  *
  * @param fd file descriptor to load from
+ * @param write If true, request a read/write private mapping.
+ *              If false, request a read-only potentially shared mapping.
  *
  * @return a new block with the file content at p_buffer, and file length at
  * i_buffer (release it with block_Release()), or NULL upon error (see errno).
  */
-VLC_API block_t *block_File(int fd, bool) VLC_USED VLC_MALLOC;
+VLC_API block_t *block_File(int fd, bool write) VLC_USED VLC_MALLOC;
 
 /**
  * Maps a file in memory.
  *
  * Loads a file into a block of memory from a path to the file.
  * See also block_File().
+ *
+ * @param write If true, request a read/write private mapping.
+ *              If false, request a read-only potentially shared mapping.
  */
-VLC_API block_t *block_FilePath(const char *, bool) VLC_USED VLC_MALLOC;
+VLC_API block_t *block_FilePath(const char *, bool write) VLC_USED VLC_MALLOC;
 
 static inline void block_Cleanup (void *block)
 {
diff --git a/modules/access/screen/wayland.c b/modules/access/screen/wayland.c
index 02f023a..f6b300d 100644
--- a/modules/access/screen/wayland.c
+++ b/modules/access/screen/wayland.c
@@ -208,7 +208,7 @@ static block_t *Shoot(demux_t *demux)
         wl_display_roundtrip(sys->display);
 
     wl_buffer_destroy(buffer);
-    block = block_File(fd);
+    block = block_File(fd, true);
 
     if (block != NULL)
     {
diff --git a/modules/access/shm.c b/modules/access/shm.c
index cbfd60a..0d9369e 100644
--- a/modules/access/shm.c
+++ b/modules/access/shm.c
@@ -329,7 +329,7 @@ static void DemuxFile (void *data)
     demux_sys_t *sys = demux->p_sys;
 
     /* Copy frame */
-    block_t *block = block_File (sys->fd);
+    block_t *block = block_File(sys->fd, true);
     if (block == NULL)
         return;
     block->i_pts = block->i_dts = mdate ();
diff --git a/modules/misc/gnutls.c b/modules/misc/gnutls.c
index 1b9c315..4bb3ddf 100644
--- a/modules/misc/gnutls.c
+++ b/modules/misc/gnutls.c
@@ -643,7 +643,7 @@ static int OpenServer (vlc_tls_creds_t *crd, const char *cert, const char *key)
         return VLC_ENOMEM;
     }
 
-    block_t *certblock = block_FilePath (cert);
+    block_t *certblock = block_FilePath(cert, false);
     if (certblock == NULL)
     {
         msg_Err (crd, "cannot read certificate chain from %s: %s", cert,
@@ -651,7 +651,7 @@ static int OpenServer (vlc_tls_creds_t *crd, const char *cert, const char *key)
         goto error;
     }
 
-    block_t *keyblock = block_FilePath (key);
+    block_t *keyblock = block_FilePath(key, false);
     if (keyblock == NULL)
     {
         msg_Err (crd, "cannot read private key from %s: %s", key,
diff --git a/src/misc/block.c b/src/misc/block.c
index 4ec2053..950f406 100644
--- a/src/misc/block.c
+++ b/src/misc/block.c
@@ -359,7 +359,7 @@ ssize_t pread (int fd, void *buf, size_t count, off_t offset)
 }
 #endif
 
-block_t *block_File (int fd)
+block_t *block_File(int fd, bool write)
 {
     size_t length;
     struct stat st;
@@ -396,9 +396,10 @@ block_t *block_File (int fd)
 #ifdef HAVE_MMAP
     if (length > 0)
     {
-        void *addr;
+        int prot = PROT_READ | (write ? PROT_WRITE : 0);
+        int flags = write ? MAP_PRIVATE : MAP_SHARED;
+        void *addr = mmap(NULL, length, prot, flags, fd, 0);
 
-        addr = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
         if (addr != MAP_FAILED)
             return block_mmap_Alloc (addr, length);
     }
@@ -425,13 +426,15 @@ block_t *block_File (int fd)
     return block;
 }
 
-block_t *block_FilePath (const char *path)
+block_t *block_FilePath(const char *path, bool write)
 {
+    /* NOTE: Writeable shared mappings are not supported here. So there are no
+     * needs to open the file for writing (even if the mapping is writable). */
     int fd = vlc_open (path, O_RDONLY);
     if (fd == -1)
         return NULL;
 
-    block_t *block = block_File (fd);
+    block_t *block = block_File(fd, write);
     vlc_close (fd);
     return block;
 }
diff --git a/src/modules/cache.c b/src/modules/cache.c
index c523566..7aebb7f 100644
--- a/src/modules/cache.c
+++ b/src/modules/cache.c
@@ -376,7 +376,7 @@ size_t CacheLoad(vlc_object_t *p_this, const char *dir, module_cache_t **r,
 
     msg_Dbg( p_this, "loading plugins cache file %s", psz_filename );
 
-    block_t *file = block_FilePath(psz_filename);
+    block_t *file = block_FilePath(psz_filename, false);
     if (file == NULL)
         msg_Warn(p_this, "cannot read %s: %s", psz_filename,
                  vlc_strerror_c(errno));
diff --git a/src/test/block_test.c b/src/test/block_test.c
index f11ea2f..5c1a6b0 100644
--- a/src/test/block_test.c
+++ b/src/test/block_test.c
@@ -34,7 +34,7 @@ static const char text[] =
     "This is a test!\n"
     "This file can be deleted safely!\n";
 
-static void test_block_File (void)
+static void test_block_File(bool write)
 {
     FILE *stream;
     int res;
@@ -47,12 +47,14 @@ static void test_block_File (void)
     res = fflush (stream);
     assert (res != EOF);
 
-    block_t *block = block_File (fileno (stream));
+    block_t *block = block_File(fileno(stream), write);
     fclose (stream);
 
     assert (block != NULL);
     assert (block->i_buffer == strlen (text));
     assert (!memcmp (block->p_buffer, text, block->i_buffer));
+    if (write)
+        memset(block->p_buffer, 'A', block->i_buffer);
     block_Release (block);
 
     remove ("testfile.txt");
@@ -86,7 +88,8 @@ static void test_block (void)
 
 int main (void)
 {
-    test_block_File ();
+    test_block_File(false);
+    test_block_File(true);
     test_block ();
     return 0;
 }



More information about the vlc-commits mailing list