]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/file.c
Put remaining pieces of CODEC_FLAG_EMU_EDGE under FF_API_EMU_EDGE.
[ffmpeg] / libavformat / file.c
index c689e04e486d5e8a426fe92361326bb171144e5a..c4201d791834baf5baa7d67270eaeeec73ee69c1 100644 (file)
@@ -23,6 +23,9 @@
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
 #include "avformat.h"
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#endif
 #include <fcntl.h>
 #if HAVE_IO_H
 #include <io.h>
 #  endif
 #endif
 
+/* Not available in POSIX.1-1996 */
+#ifndef S_ISLNK
+#  ifdef S_IFLNK
+#    define S_ISLNK(m) (((m) & S_IFLNK) == S_IFLNK)
+#  else
+#    define S_ISLNK(m) 0
+#  endif
+#endif
+
+/* Not available in POSIX.1-1996 */
+#ifndef S_ISSOCK
+#  ifdef S_IFSOCK
+#    define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#  else
+#    define S_ISSOCK(m) 0
+#  endif
+#endif
+
 /* standard file protocol */
 
 typedef struct FileContext {
@@ -51,6 +72,9 @@ typedef struct FileContext {
     int fd;
     int trunc;
     int blocksize;
+#if HAVE_DIRENT_H
+    DIR *dir;
+#endif
 } FileContext;
 
 static const AVOption file_options[] = {
@@ -225,6 +249,90 @@ static int file_close(URLContext *h)
     return close(c->fd);
 }
 
+static int file_open_dir(URLContext *h)
+{
+#if HAVE_LSTAT
+    FileContext *c = h->priv_data;
+
+    c->dir = opendir(h->filename);
+    if (!c->dir)
+        return AVERROR(errno);
+
+    return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif /* HAVE_LSTAT */
+}
+
+static int file_read_dir(URLContext *h, AVIODirEntry **next)
+{
+#if HAVE_LSTAT
+    FileContext *c = h->priv_data;
+    struct dirent *dir;
+    char *fullpath = NULL;
+
+    *next = ff_alloc_dir_entry();
+    if (!*next)
+        return AVERROR(ENOMEM);
+    do {
+        errno = 0;
+        dir = readdir(c->dir);
+        if (!dir) {
+            av_freep(next);
+            return AVERROR(errno);
+        }
+    } while (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."));
+
+    fullpath = av_append_path_component(h->filename, dir->d_name);
+    if (fullpath) {
+        struct stat st;
+        if (!lstat(fullpath, &st)) {
+            if (S_ISDIR(st.st_mode))
+                (*next)->type = AVIO_ENTRY_DIRECTORY;
+            else if (S_ISFIFO(st.st_mode))
+                (*next)->type = AVIO_ENTRY_NAMED_PIPE;
+            else if (S_ISCHR(st.st_mode))
+                (*next)->type = AVIO_ENTRY_CHARACTER_DEVICE;
+            else if (S_ISBLK(st.st_mode))
+                (*next)->type = AVIO_ENTRY_BLOCK_DEVICE;
+            else if (S_ISLNK(st.st_mode))
+                (*next)->type = AVIO_ENTRY_SYMBOLIC_LINK;
+            else if (S_ISSOCK(st.st_mode))
+                (*next)->type = AVIO_ENTRY_SOCKET;
+            else if (S_ISREG(st.st_mode))
+                (*next)->type = AVIO_ENTRY_FILE;
+            else
+                (*next)->type = AVIO_ENTRY_UNKNOWN;
+
+            (*next)->group_id = st.st_gid;
+            (*next)->user_id = st.st_uid;
+            (*next)->size = st.st_size;
+            (*next)->filemode = st.st_mode & 0777;
+            (*next)->modification_timestamp = INT64_C(1000000) * st.st_mtime;
+            (*next)->access_timestamp =  INT64_C(1000000) * st.st_atime;
+            (*next)->status_change_timestamp = INT64_C(1000000) * st.st_ctime;
+        }
+        av_free(fullpath);
+    }
+
+    (*next)->name = av_strdup(dir->d_name);
+    return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif /* HAVE_LSTAT */
+}
+
+static int file_close_dir(URLContext *h)
+{
+#if HAVE_LSTAT
+    FileContext *c = h->priv_data;
+    closedir(c->dir);
+    return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif /* HAVE_LSTAT */
+}
+
 URLProtocol ff_file_protocol = {
     .name                = "file",
     .url_open            = file_open,
@@ -238,6 +346,9 @@ URLProtocol ff_file_protocol = {
     .url_move            = file_move,
     .priv_data_size      = sizeof(FileContext),
     .priv_data_class     = &file_class,
+    .url_open_dir        = file_open_dir,
+    .url_read_dir        = file_read_dir,
+    .url_close_dir       = file_close_dir,
 };
 
 #endif /* CONFIG_FILE_PROTOCOL */