diff options
author | Anton Khirnov <anton@khirnov.net> | 2011-08-20 10:51:53 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2011-10-11 08:35:03 +0200 |
commit | b724bea92128cb18749eeadffb67c5852ebb2598 (patch) | |
tree | f291c14791a625c98e383970dc1b9a58b484e74c | |
parent | 8e9959a28e6ef92e30d4f185a4573590ff6651a1 (diff) |
file protocol: support for opening dirs.
-rw-r--r-- | libavformat/avio.h | 5 | ||||
-rw-r--r-- | libavformat/file.c | 43 |
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); } |