aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2011-08-20 10:51:53 +0200
committerAnton Khirnov <anton@khirnov.net>2011-10-11 08:35:03 +0200
commitb724bea92128cb18749eeadffb67c5852ebb2598 (patch)
treef291c14791a625c98e383970dc1b9a58b484e74c
parent8e9959a28e6ef92e30d4f185a4573590ff6651a1 (diff)
file protocol: support for opening dirs.
-rw-r--r--libavformat/avio.h5
-rw-r--r--libavformat/file.c43
2 files changed, 48 insertions, 0 deletions
diff --git a/libavformat/avio.h b/libavformat/avio.h
index be14e3c89d..9adf517325 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -541,6 +541,11 @@ int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
*/
#define AVIO_FLAG_NONBLOCK 8
+/*
+ * Indicate that the URL to open is a directory.
+ */
+#define AVIO_FLAG_DIR 16
+
/**
* Create and initialize a AVIOContext for accessing the
* resource indicated by url.
diff --git a/libavformat/file.c b/libavformat/file.c
index 649640a927..76c9c3845a 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -21,6 +21,7 @@
#include "libavutil/avstring.h"
#include "avformat.h"
+#include <dirent.h>
#include <fcntl.h>
#if HAVE_SETMODE
#include <io.h>
@@ -34,15 +35,51 @@
/* standard file protocol */
+static int file_opendir(URLContext *h, const char *path, int flags)
+{
+ DIR *dir;
+
+ if (!(dir = opendir(path)))
+ return AVERROR(ENOENT);
+ h->priv_data = dir;
+ return 0;
+}
+
+static int file_readdir(URLContext *h, char *filename, int size)
+{
+ DIR *dir = h->priv_data;
+ struct dirent *file = readdir(dir);
+
+ if (!file)
+ return AVERROR(EOF);
+ if (strlen(h->filename)+strlen(file->d_name) + 2 > size)
+ return AVERROR(EINVAL);
+ strcpy(filename, h->filename);
+ av_strlcat(filename, "/", size);
+ av_strlcat(filename, file->d_name, size);
+ return 0;
+}
+
+static int file_closedir(URLContext *h)
+{
+ DIR *dir = h->priv_data;
+ closedir(dir);
+ return 0;
+}
+
static int file_read(URLContext *h, unsigned char *buf, int size)
{
int fd = (intptr_t) h->priv_data;
+ if (h->flags & AVIO_FLAG_DIR)
+ return file_readdir(h, buf, size);
return read(fd, buf, size);
}
static int file_write(URLContext *h, const unsigned char *buf, int size)
{
int fd = (intptr_t) h->priv_data;
+ if (h->flags & AVIO_FLAG_DIR)
+ return AVERROR(EIO);
return write(fd, buf, size);
}
@@ -73,6 +110,8 @@ static int file_open(URLContext *h, const char *filename, int flags)
av_strstart(filename, "file:", &filename);
+ if (flags & AVIO_FLAG_DIR)
+ return file_opendir(h, filename, flags);
if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {
access = O_CREAT | O_TRUNC | O_RDWR;
} else if (flags & AVIO_FLAG_WRITE) {
@@ -99,12 +138,16 @@ static int64_t file_seek(URLContext *h, int64_t pos, int whence)
int ret = fstat(fd, &st);
return ret < 0 ? AVERROR(errno) : st.st_size;
}
+ if (h->flags & AVIO_FLAG_DIR)
+ return AVERROR(EPIPE);
return lseek(fd, pos, whence);
}
static int file_close(URLContext *h)
{
int fd = (intptr_t) h->priv_data;
+ if(h->flags & AVIO_FLAG_DIR)
+ return file_closedir(h);
return close(fd);
}