summaryrefslogtreecommitdiff
path: root/libavformat/file.c
diff options
context:
space:
mode:
authorLukasz Marek <lukasz.m.luki2@gmail.com>2015-06-22 00:01:32 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2015-08-25 02:04:34 +0200
commitd39a9b01e28500356fc83c277b00bcf83e17a3a3 (patch)
tree2435624f38fdbed39db048d9e8b41804d0b94c11 /libavformat/file.c
parent060102389e572abb2beaed3b9f5e1036aeea43f1 (diff)
downloadffmpeg-d39a9b01e28500356fc83c277b00bcf83e17a3a3.tar.gz
lavf/file: implement directory listing callbacks
Signed-off-by: Lukasz Marek <lukasz.m.luki2 at gmail.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavformat/file.c')
-rw-r--r--libavformat/file.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/libavformat/file.c b/libavformat/file.c
index c689e04e48..407540c706 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -23,6 +23,7 @@
#include "libavutil/internal.h"
#include "libavutil/opt.h"
#include "avformat.h"
+#include <dirent.h>
#include <fcntl.h>
#if HAVE_IO_H
#include <io.h>
@@ -51,6 +52,7 @@ typedef struct FileContext {
int fd;
int trunc;
int blocksize;
+ DIR *dir;
} FileContext;
static const AVOption file_options[] = {
@@ -225,6 +227,88 @@ static int file_close(URLContext *h)
return close(c->fd);
}
+static int file_open_dir(URLContext *h)
+{
+ FileContext *c = h->priv_data;
+
+ c->dir = opendir(h->filename);
+ if (!c->dir)
+ return AVERROR(errno);
+
+ return 0;
+}
+
+static int file_read_dir(URLContext *h, AVIODirEntry **next)
+{
+ 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 (!stat(fullpath, &st)) {
+ (*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);
+ switch (dir->d_type) {
+ case DT_FIFO:
+ (*next)->type = AVIO_ENTRY_NAMED_PIPE;
+ break;
+ case DT_CHR:
+ (*next)->type = AVIO_ENTRY_CHARACTER_DEVICE;
+ break;
+ case DT_DIR:
+ (*next)->type = AVIO_ENTRY_DIRECTORY;
+ break;
+ case DT_BLK:
+ (*next)->type = AVIO_ENTRY_BLOCK_DEVICE;
+ break;
+ case DT_REG:
+ (*next)->type = AVIO_ENTRY_FILE;
+ break;
+ case DT_LNK:
+ (*next)->type = AVIO_ENTRY_SYMBOLIC_LINK;
+ break;
+ case DT_SOCK:
+ (*next)->type = AVIO_ENTRY_SOCKET;
+ break;
+ case DT_UNKNOWN:
+ default:
+ (*next)->type = AVIO_ENTRY_UNKNOWN;
+ break;
+ }
+ return 0;
+}
+
+static int file_close_dir(URLContext *h)
+{
+ FileContext *c = h->priv_data;
+ closedir(c->dir);
+ return 0;
+}
+
URLProtocol ff_file_protocol = {
.name = "file",
.url_open = file_open,
@@ -238,6 +322,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 */