[vlc-devel] [PATCH 07/12] access/directory: remove recursive code
Thomas Guillem
thomas at gllm.fr
Tue May 19 10:27:47 CEST 2015
Recursive parsing is not handled anymore by accesses.
---
modules/access/directory.c | 307 ++++++++++++---------------------------------
modules/access/file.c | 6 +-
modules/access/fs.h | 1 -
3 files changed, 85 insertions(+), 229 deletions(-)
diff --git a/modules/access/directory.c b/modules/access/directory.c
index 2b4f6a9..425ec40 100644
--- a/modules/access/directory.c
+++ b/modules/access/directory.c
@@ -1,7 +1,7 @@
/*****************************************************************************
* directory.c: expands a directory (directory: access_browser plug-in)
*****************************************************************************
- * Copyright (C) 2002-2008 VLC authors and VideoLAN
+ * Copyright (C) 2002-2015 VLC authors and VideoLAN
* $Id$
*
* Authors: Derk-Jan Hartman <hartman at videolan dot org>
@@ -47,225 +47,54 @@
#include <vlc_strings.h>
#include <vlc_charset.h>
-enum
-{
- ENTRY_DIR = 0,
- ENTRY_ENOTDIR = -1,
- ENTRY_EACCESS = -2,
-};
-
-enum
-{
- MODE_NONE,
- MODE_COLLAPSE,
- MODE_EXPAND,
-};
-
-typedef struct directory directory;
-struct directory
-{
- directory *parent;
- DIR *handle;
- char *uri;
- char **filev;
- int filec, i;
-#ifdef HAVE_OPENAT
- dev_t device;
- ino_t inode;
-#else
- char *path;
-#endif
-};
-
struct access_sys_t
{
- directory *current;
- char mode;
+ char *psz_base_uri;
+ DIR *p_dir;
};
-/* Select non-hidden files only */
-static int visible (const char *name)
-{
- return name[0] != '.';
-}
-
-#ifdef HAVE_OPENAT
-/* Detect directories that recurse into themselves. */
-static bool has_inode_loop (const directory *dir, dev_t dev, ino_t inode)
-{
- while (dir != NULL)
- {
- if ((dir->device == dev) && (dir->inode == inode))
- return true;
- dir = dir->parent;
- }
- return false;
-}
-#endif
-
-/* success -> returns ENTRY_DIR and the handle parameter is set to the handle,
- * error -> return ENTRY_ENOTDIR or ENTRY_EACCESS */
-static int directory_open (directory *p_dir, char *psz_entry, DIR **handle)
-{
- *handle = NULL;
-
-#ifdef HAVE_OPENAT
- int fd = vlc_openat (dirfd (p_dir->handle), psz_entry,
- O_RDONLY | O_DIRECTORY);
-
- if (fd == -1)
- {
- if (errno == ENOTDIR)
- return ENTRY_ENOTDIR;
- else
- return ENTRY_EACCESS;
- }
-
- struct stat st;
- if (fstat (fd, &st)
- || has_inode_loop (p_dir, st.st_dev, st.st_ino)
- || (*handle = fdopendir (fd)) == NULL)
- {
- close (fd);
- return ENTRY_EACCESS;
- }
-#else
- char *path;
- if (asprintf (&path, "%s/%s", p_dir->path, psz_entry) == -1)
- return ENTRY_EACCESS;
-
- *handle = vlc_opendir (path);
-
- free(path);
-
- if (*handle == NULL) {
- return ENTRY_ENOTDIR;
- }
-#endif
-
- return ENTRY_DIR;
-}
-
-static bool directory_push (access_sys_t *p_sys, DIR *handle, char *psz_uri)
-{
- directory *p_dir = malloc (sizeof (*p_dir));
-
- psz_uri = strdup (psz_uri);
- if (unlikely (p_dir == NULL || psz_uri == NULL))
- goto error;
-
- p_dir->parent = p_sys->current;
- p_dir->handle = handle;
- p_dir->uri = psz_uri;
- p_dir->filec = vlc_loaddir (handle, &p_dir->filev, visible, NULL);
- if (p_dir->filec < 0)
- p_dir->filev = NULL;
- p_dir->i = 0;
-
-#ifdef HAVE_OPENAT
- struct stat st;
- if (fstat (dirfd (handle), &st))
- goto error_filev;
- p_dir->device = st.st_dev;
- p_dir->inode = st.st_ino;
-#else
- p_dir->path = make_path (psz_uri);
- if (p_dir->path == NULL)
- goto error_filev;
-#endif
-
- p_sys->current = p_dir;
- return true;
-
-error_filev:
- for (int i = 0; i < p_dir->filec; i++)
- free (p_dir->filev[i]);
- free (p_dir->filev);
-
-error:
- closedir (handle);
- free (p_dir);
- free (psz_uri);
- return false;
-}
-
-static bool directory_pop (access_sys_t *p_sys)
-{
- directory *p_old = p_sys->current;
-
- if (p_old == NULL)
- return false;
-
- p_sys->current = p_old->parent;
- closedir (p_old->handle);
- free (p_old->uri);
- for (int i = 0; i < p_old->filec; i++)
- free (p_old->filev[i]);
- free (p_old->filev);
-#ifndef HAVE_OPENAT
- free (p_old->path);
-#endif
- free (p_old);
-
- return p_sys->current != NULL;
-}
-
-
/*****************************************************************************
* Open: open the directory
*****************************************************************************/
int DirOpen (vlc_object_t *p_this)
{
access_t *p_access = (access_t*)p_this;
+ DIR *p_dir;
+ char *psz_base_uri;
if (!p_access->psz_filepath)
return VLC_EGENERIC;
- DIR *handle = vlc_opendir (p_access->psz_filepath);
- if (handle == NULL)
+ p_dir = vlc_opendir (p_access->psz_filepath);
+ if (p_dir == NULL)
return VLC_EGENERIC;
- return DirInit (p_access, handle);
-}
-
-int DirInit (access_t *p_access, DIR *handle)
-{
- access_sys_t *p_sys = malloc (sizeof (*p_sys));
- if (unlikely (p_sys == NULL))
- goto error;
-
- char *uri;
if (!strcmp (p_access->psz_access, "fd"))
{
- if (asprintf (&uri, "fd://%s", p_access->psz_location) == -1)
- uri = NULL;
+ if (asprintf (&psz_base_uri, "fd://%s", p_access->psz_location) == -1)
+ psz_base_uri = NULL;
}
else
- uri = vlc_path2uri (p_access->psz_filepath, "file");
- if (unlikely (uri == NULL))
+ psz_base_uri = vlc_path2uri (p_access->psz_filepath, "file");
+ if (unlikely (psz_base_uri == NULL))
{
- closedir (handle);
- goto error;
+ closedir (p_dir);
+ return VLC_ENOMEM;
}
- /* "Open" the base directory */
- p_sys->current = NULL;
- if (!directory_push (p_sys, handle, uri))
+
+ p_access->p_sys = calloc (1, sizeof(access_sys_t));
+ if (!p_access->p_sys)
{
- free (uri);
- goto error;
+ closedir(p_dir);
+ free( psz_base_uri );
+ return VLC_ENOMEM;
}
- free (uri);
-
- p_access->p_sys = p_sys;
-
+ p_access->p_sys->p_dir = p_dir;
+ p_access->p_sys->psz_base_uri = psz_base_uri;
p_access->pf_readdir = DirRead;
return VLC_SUCCESS;
-
-error:
- free (p_sys);
- return VLC_EGENERIC;
}
/*****************************************************************************
@@ -276,57 +105,87 @@ void DirClose( vlc_object_t * p_this )
access_t *p_access = (access_t*)p_this;
access_sys_t *p_sys = p_access->p_sys;
- while (directory_pop (p_sys))
- ;
+ free (p_sys->psz_base_uri);
+ closedir (p_sys->p_dir);
free (p_sys);
}
-/* This function is a little bit too complex for what it seems to do, but the
- * point is to de-recursify directory recusion to avoid overruning the stack
- * in case there's a high directory depth */
+static bool is_looping(access_t *p_access, const char *psz_uri)
+{
+#ifdef S_ISLNK
+ struct stat st;
+ bool b_looping = false;
+
+ if (vlc_lstat (psz_uri, &st) != 0)
+ return false;
+ if (S_ISLNK (st.st_mode))
+ {
+ char *psz_link = malloc(st.st_size + 1);
+ ssize_t i_ret;
+
+ if (psz_link)
+ {
+ i_ret = readlink(psz_uri, psz_link, st.st_size + 1);
+ if (i_ret > 0 && i_ret <= st.st_size)
+ {
+ psz_link[i_ret] = '\0';
+ if (strstr(p_access->psz_filepath, psz_link))
+ b_looping = true;
+ }
+ free (psz_link);
+ }
+ }
+ return b_looping;
+#else
+ return false;
+#endif
+}
+
input_item_t* DirRead (access_t *p_access)
{
access_sys_t *p_sys = p_access->p_sys;
+ DIR *p_dir = p_sys->p_dir;
input_item_t *p_item = NULL;
+ const char *psz_entry;
- while (!p_item && p_sys->current != NULL
- && p_sys->current->i <= p_sys->current->filec)
+ while (!p_item && (psz_entry = vlc_readdir (p_dir)))
{
- directory *p_current = p_sys->current;
-
- char *psz_entry = p_current->filev[p_current->i++];
- char *psz_full_uri, *psz_uri;
- DIR *handle;
- int i_res;
+ char *psz_uri, *psz_encoded_entry;
+ struct stat st;
+ int i_type;
/* Check if it is a directory or even readable */
- i_res = directory_open (p_current, psz_entry, &handle);
-
- /* Create an input item for the current entry */
- psz_uri = encode_URI_component (psz_entry);
- if (psz_uri == NULL
- || asprintf (&psz_full_uri, "%s/%s", p_current->uri, psz_uri) == -1)
- psz_full_uri = NULL;
-
- free (psz_uri);
- if (psz_full_uri == NULL)
+ if (asprintf (&psz_uri, "%s/%s",
+ p_access->psz_filepath, psz_entry) == -1)
+ return NULL;
+ if (vlc_stat (psz_uri, &st) != 0)
{
- closedir (handle);
+ free (psz_uri);
continue;
}
-
- int i_type = i_res == ENTRY_DIR ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
- p_item = input_item_NewWithType (psz_full_uri, psz_entry,
- 0, NULL, 0, 0, i_type);
- if (p_item == NULL)
+ i_type = S_ISDIR (st.st_mode) ? ITEM_TYPE_DIRECTORY : ITEM_TYPE_FILE;
+ if (i_type == ITEM_TYPE_DIRECTORY && is_looping(p_access, psz_uri))
{
- free (psz_full_uri);
- closedir (handle);
+ free (psz_uri);
continue;
}
+ free (psz_uri);
+
+ /* Create an input item for the current entry */
+ psz_encoded_entry = encode_URI_component (psz_entry);
+ if (psz_encoded_entry == NULL)
+ continue;
+ if (asprintf (&psz_uri, "%s/%s",
+ p_sys->psz_base_uri, psz_encoded_entry) == -1)
+ return NULL;
+ free (psz_encoded_entry);
- free (psz_full_uri);
+ p_item = input_item_NewWithType (psz_uri, psz_entry,
+ 0, NULL, 0, 0, i_type);
+ free (psz_uri);
+ if (!p_item)
+ return NULL;
}
return p_item;
}
diff --git a/modules/access/file.c b/modules/access/file.c
index 5efa32f..16e91c8 100644
--- a/modules/access/file.c
+++ b/modules/access/file.c
@@ -205,10 +205,8 @@ int FileOpen( vlc_object_t *p_this )
if (S_ISDIR (st.st_mode))
{
#ifdef HAVE_FDOPENDIR
- DIR *handle = fdopendir (fd);
- if (handle == NULL)
- goto error; /* Uh? */
- return DirInit (p_access, handle);
+msg_Err(p_access, "DirOpen from FileOpen");
+ return DirOpen (VLC_OBJECT(p_access));
#else
msg_Dbg (p_access, "ignoring directory");
goto error;
diff --git a/modules/access/fs.h b/modules/access/fs.h
index e948ba2..eb67411 100644
--- a/modules/access/fs.h
+++ b/modules/access/fs.h
@@ -26,5 +26,4 @@ void FileClose (vlc_object_t *);
int DirOpen (vlc_object_t *);
int DirInit (access_t *p_access, DIR *handle);
input_item_t* DirRead (access_t *);
-int DirControl (access_t *, int, va_list);
void DirClose (vlc_object_t *);
--
2.1.4
More information about the vlc-devel
mailing list