diff options
author | Mariusz SzczepaĆczyk | 2015-04-03 03:54:10 +0200 |
---|---|---|
committer | Michael Niedermayer | 2015-04-06 01:59:04 +0200 |
commit | 428675227908a4d1f32829214289234dc9b3659d (patch) | |
tree | 68e670eca1118c2320f913e401a5f877b5ab8599 /libavformat/libsmbclient.c | |
parent | 99a567cbe24aba1efe65d3cfc44b7dbdebe2aab1 (diff) |
lavf/libsmbclient: implement directory listing callbacks
Reviewed-by: Lukasz Marek <lukasz.m.luki2@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/libsmbclient.c')
-rw-r--r-- | libavformat/libsmbclient.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/libavformat/libsmbclient.c b/libavformat/libsmbclient.c index 8290d75927..1af8163674 100644 --- a/libavformat/libsmbclient.c +++ b/libavformat/libsmbclient.c @@ -28,6 +28,7 @@ typedef struct { const AVClass *class; SMBCCTX *ctx; + int dh; int fd; int64_t filesize; int trunc; @@ -182,6 +183,110 @@ static int libsmbc_write(URLContext *h, const unsigned char *buf, int size) return bytes_written; } +static int libsmbc_open_dir(URLContext *h) +{ + LIBSMBContext *libsmbc = h->priv_data; + int ret; + + if ((ret = libsmbc_connect(h)) < 0) + goto fail; + + if ((libsmbc->dh = smbc_opendir(h->filename)) < 0) { + ret = AVERROR(errno); + av_log(h, AV_LOG_ERROR, "Error opening dir: %s\n", strerror(errno)); + goto fail; + } + + return 0; + + fail: + libsmbc_close(h); + return ret; +} + +static int libsmbc_read_dir(URLContext *h, AVIODirEntry **next) +{ + LIBSMBContext *libsmbc = h->priv_data; + AVIODirEntry *entry; + struct smbc_dirent *dirent = NULL; + char *url = NULL; + int skip_entry; + + *next = entry = ff_alloc_dir_entry(); + if (!entry) + return AVERROR(ENOMEM); + + do { + skip_entry = 0; + dirent = smbc_readdir(libsmbc->dh); + if (!dirent) { + av_freep(next); + return 0; + } + switch (dirent->smbc_type) { + case SMBC_DIR: + entry->type = AVIO_ENTRY_DIRECTORY; + break; + case SMBC_FILE: + entry->type = AVIO_ENTRY_FILE; + break; + case SMBC_FILE_SHARE: + entry->type = AVIO_ENTRY_SHARE; + break; + case SMBC_SERVER: + entry->type = AVIO_ENTRY_SERVER; + break; + case SMBC_WORKGROUP: + entry->type = AVIO_ENTRY_WORKGROUP; + break; + case SMBC_COMMS_SHARE: + case SMBC_IPC_SHARE: + case SMBC_PRINTER_SHARE: + skip_entry = 1; + break; + case SMBC_LINK: + default: + entry->type = AVIO_ENTRY_UNKNOWN; + break; + } + } while (skip_entry || !strcmp(dirent->name, ".") || + !strcmp(dirent->name, "..")); + + entry->name = av_strdup(dirent->name); + if (!entry->name) { + av_freep(next); + return AVERROR(ENOMEM); + } + + url = av_append_path_component(h->filename, dirent->name); + if (url) { + struct stat st; + if (!smbc_stat(url, &st)) { + entry->group_id = st.st_gid; + entry->user_id = st.st_uid; + entry->size = st.st_size; + entry->filemode = st.st_mode & 0777; + entry->modification_timestamp = INT64_C(1000000) * st.st_mtime; + entry->access_timestamp = INT64_C(1000000) * st.st_atime; + entry->status_change_timestamp = INT64_C(1000000) * st.st_ctime; + } + av_free(url); + } + + return 0; +} + +static int libsmbc_close_dir(URLContext *h) +{ + LIBSMBContext *libsmbc = h->priv_data; + if (libsmbc->dh >= 0) { + smbc_closedir(libsmbc->dh); + libsmbc->dh = -1; + } + libsmbc_close(h); + return 0; +} + #define OFFSET(x) offsetof(LIBSMBContext, x) #define D AV_OPT_FLAG_DECODING_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM @@ -206,6 +311,9 @@ URLProtocol ff_libsmbclient_protocol = { .url_write = libsmbc_write, .url_seek = libsmbc_seek, .url_close = libsmbc_close, + .url_open_dir = libsmbc_open_dir, + .url_read_dir = libsmbc_read_dir, + .url_close_dir = libsmbc_close_dir, .priv_data_size = sizeof(LIBSMBContext), .priv_data_class = &libsmbclient_context_class, .flags = URL_PROTOCOL_FLAG_NETWORK, |