[vlc-devel] [PATCH 1/3] file: fix directory subitems type

Thomas Guillem thomas at gllm.fr
Wed Nov 4 19:35:49 CET 2015


---
 modules/access/directory.c | 77 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 76 insertions(+), 1 deletion(-)

diff --git a/modules/access/directory.c b/modules/access/directory.c
index 4985855..72d33ee 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -31,6 +31,11 @@
 # include "config.h"
 #endif
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
 #include <vlc_common.h>
 #include "fs.h"
 #include <vlc_access.h>
@@ -43,6 +48,7 @@ struct access_sys_t
 {
     char *psz_base_uri;
     DIR *p_dir;
+    int fd;
 };
 
 /*****************************************************************************
@@ -51,11 +57,14 @@ struct access_sys_t
 int DirInit (access_t *p_access, DIR *p_dir)
 {
     char *psz_base_uri;
+    int fd = -1;
 
     if (!strcmp (p_access->psz_access, "fd"))
     {
         if (asprintf (&psz_base_uri, "fd://%s", p_access->psz_location) == -1)
             psz_base_uri = NULL;
+
+        fd = dirfd (p_dir);
     }
     else
         psz_base_uri = vlc_path2uri (p_access->psz_filepath, "file");
@@ -73,6 +82,7 @@ int DirInit (access_t *p_access, DIR *p_dir)
         return VLC_ENOMEM;
     }
     p_access->p_sys->p_dir = p_dir;
+    p_access->p_sys->fd = fd;
     p_access->p_sys->psz_base_uri = psz_base_uri;
     p_access->pf_readdir = DirRead;
     p_access->pf_control = access_vaDirectoryControlHelper;
@@ -111,6 +121,38 @@ void DirClose( vlc_object_t * p_this )
     free (p_sys);
 }
 
+static bool DirIsLooping (access_t *p_access, const char *uri)
+{
+#ifdef S_ISLNK
+    struct stat st;
+    bool looping = false;
+
+    if (vlc_lstat (uri, &st) != 0)
+        return false;
+    if (S_ISLNK (st.st_mode))
+    {
+        char *link = malloc (st.st_size + 1);
+
+        if (link)
+        {
+            ssize_t ret = readlink (uri, link, st.st_size + 1);
+            if (ret > 0 && ret <= st.st_size)
+            {
+                link[ret] = '\0';
+                if (strstr (p_access->psz_filepath, link))
+                    looping = true;
+            }
+            free (link);
+        }
+    }
+    return looping;
+#else
+    VLC_UNUSED (p_access);
+    VLC_UNUSED (uri);
+    return false;
+#endif
+}
+
 input_item_t* DirRead (access_t *p_access)
 {
     access_sys_t *p_sys = p_access->p_sys;
@@ -118,6 +160,39 @@ input_item_t* DirRead (access_t *p_access)
 
     while ((entry = vlc_readdir (p_sys->p_dir)) != NULL)
     {
+        /* Check if the current entry is a directory */
+        int i_type = ITEM_TYPE_FILE;
+        if (p_sys->fd != -1)
+        {
+            int fd = vlc_openat (p_sys->fd, entry, O_RDONLY);
+            if (fd != -1)
+            {
+                struct stat st;
+                if (fstat(fd, &st) == 0 && S_ISDIR (st.st_mode))
+                    i_type = ITEM_TYPE_DIRECTORY;
+                close(fd);
+            }
+        }
+        else
+        {
+            char *uri;
+            if (unlikely(asprintf (&uri, "%s/%s", p_access->psz_filepath,
+                                   entry) == -1))
+                return NULL;
+
+            struct stat st;
+            if (vlc_stat (uri, &st) == 0 && S_ISDIR (st.st_mode))
+                i_type = ITEM_TYPE_DIRECTORY;
+
+            if (i_type == ITEM_TYPE_DIRECTORY && DirIsLooping (p_access, uri))
+            {
+                free (uri);
+                continue;
+            }
+
+            free (uri);
+        }
+
         /* Create an input item for the current entry */
         char *encoded_entry = encode_URI_component (entry);
         if (unlikely(entry == NULL))
@@ -132,7 +207,7 @@ input_item_t* DirRead (access_t *p_access)
             return NULL;
 
         input_item_t *item = input_item_NewWithType (uri, entry, 0, NULL, 0, 0,
-                                                     ITEM_TYPE_FILE);
+                                                     i_type);
         free (uri);
         if (likely(item != NULL))
             return item;
-- 
2.1.4



More information about the vlc-devel mailing list