[FFmpeg-devel] [PATCH 5/6] lavf/file: implement directory listing callbacks

wm4 nfxjfg at googlemail.com
Sat Jul 5 18:59:30 CEST 2014


On Sat,  5 Jul 2014 18:12:03 +0200
Lukasz Marek <lukasz.m.luki2 at gmail.com> wrote:

> Signed-off-by: Lukasz Marek <lukasz.m.luki2 at gmail.com>
> ---
>  libavformat/file.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
> 
> diff --git a/libavformat/file.c b/libavformat/file.c
> index 6511328..238ae85 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[] = {
> @@ -189,6 +191,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);

This obviously fails when trying to pass utf-8 filenames to it on
Windows.

> +    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 = av_mallocz(sizeof(AVIODirEntry));

malloc for every entry seems like a waste; same for fullpath etc. below.

> +    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, ".."));

It should probably be documented that . and .. are not included.

> +
> +    fullpath = av_append_path_component(h->filename, dir->d_name);
> +    if (fullpath) {
> +        struct stat st;
> +        if (!stat(fullpath, &st)) {

Same here, about utf-8 paths on windows.

> +            (*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;
> +    }

IMO it would be nice to compress this code a bit. E.g. move mapping
the values into a separate function, and use 1 line per case.

> +    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,
> @@ -200,6 +284,9 @@ URLProtocol ff_file_protocol = {
>      .url_check           = file_check,
>      .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 */



More information about the ffmpeg-devel mailing list