LCOV - code coverage report
Current view: top level - src/libavformat - avio.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 171 374 45.7 %
Date: 2017-01-23 11:54:22 Functions: 16 30 53.3 %

          Line data    Source code
       1             : /*
       2             :  * unbuffered I/O
       3             :  * Copyright (c) 2001 Fabrice Bellard
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include "libavutil/avstring.h"
      23             : #include "libavutil/dict.h"
      24             : #include "libavutil/opt.h"
      25             : #include "libavutil/time.h"
      26             : #include "libavutil/avassert.h"
      27             : #include "os_support.h"
      28             : #include "avformat.h"
      29             : #if CONFIG_NETWORK
      30             : #include "network.h"
      31             : #endif
      32             : #include "url.h"
      33             : 
      34             : /** @name Logging context. */
      35             : /*@{*/
      36           6 : static const char *urlcontext_to_name(void *ptr)
      37             : {
      38           6 :     URLContext *h = (URLContext *)ptr;
      39           6 :     if (h->prot)
      40           6 :         return h->prot->name;
      41             :     else
      42           0 :         return "NULL";
      43             : }
      44             : 
      45      843292 : static void *urlcontext_child_next(void *obj, void *prev)
      46             : {
      47      843292 :     URLContext *h = obj;
      48      843292 :     if (!prev && h->priv_data && h->prot->priv_data_class)
      49      421646 :         return h->priv_data;
      50      421646 :     return NULL;
      51             : }
      52             : 
      53             : #define OFFSET(x) offsetof(URLContext,x)
      54             : #define E AV_OPT_FLAG_ENCODING_PARAM
      55             : #define D AV_OPT_FLAG_DECODING_PARAM
      56             : static const AVOption options[] = {
      57             :     {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
      58             :     {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
      59             :     {"rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM },
      60             :     { NULL }
      61             : };
      62             : 
      63             : const AVClass ffurl_context_class = {
      64             :     .class_name       = "URLContext",
      65             :     .item_name        = urlcontext_to_name,
      66             :     .option           = options,
      67             :     .version          = LIBAVUTIL_VERSION_INT,
      68             :     .child_next       = urlcontext_child_next,
      69             :     .child_class_next = ff_urlcontext_child_class_next,
      70             : };
      71             : /*@}*/
      72             : 
      73      104734 : static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
      74             :                                   const char *filename, int flags,
      75             :                                   const AVIOInterruptCB *int_cb)
      76             : {
      77             :     URLContext *uc;
      78             :     int err;
      79             : 
      80             : #if CONFIG_NETWORK
      81      104734 :     if (up->flags & URL_PROTOCOL_FLAG_NETWORK && !ff_network_init())
      82           0 :         return AVERROR(EIO);
      83             : #endif
      84      104734 :     if ((flags & AVIO_FLAG_READ) && !up->url_read) {
      85           0 :         av_log(NULL, AV_LOG_ERROR,
      86             :                "Impossible to open the '%s' protocol for reading\n", up->name);
      87           0 :         return AVERROR(EIO);
      88             :     }
      89      104734 :     if ((flags & AVIO_FLAG_WRITE) && !up->url_write) {
      90           0 :         av_log(NULL, AV_LOG_ERROR,
      91             :                "Impossible to open the '%s' protocol for writing\n", up->name);
      92           0 :         return AVERROR(EIO);
      93             :     }
      94      104734 :     uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);
      95      104734 :     if (!uc) {
      96           0 :         err = AVERROR(ENOMEM);
      97           0 :         goto fail;
      98             :     }
      99      104734 :     uc->av_class = &ffurl_context_class;
     100      104734 :     uc->filename = (char *)&uc[1];
     101      104734 :     strcpy(uc->filename, filename);
     102      104734 :     uc->prot            = up;
     103      104734 :     uc->flags           = flags;
     104      104734 :     uc->is_streamed     = 0; /* default = not streamed */
     105      104734 :     uc->max_packet_size = 0; /* default: stream file */
     106      104734 :     if (up->priv_data_size) {
     107      104734 :         uc->priv_data = av_mallocz(up->priv_data_size);
     108      104734 :         if (!uc->priv_data) {
     109           0 :             err = AVERROR(ENOMEM);
     110           0 :             goto fail;
     111             :         }
     112      104734 :         if (up->priv_data_class) {
     113      102952 :             int proto_len= strlen(up->name);
     114      102952 :             char *start = strchr(uc->filename, ',');
     115      102952 :             *(const AVClass **)uc->priv_data = up->priv_data_class;
     116      102952 :             av_opt_set_defaults(uc->priv_data);
     117      102952 :             if(!strncmp(up->name, uc->filename, proto_len) && uc->filename + proto_len == start){
     118           0 :                 int ret= 0;
     119           0 :                 char *p= start;
     120           0 :                 char sep= *++p;
     121             :                 char *key, *val;
     122           0 :                 p++;
     123             : 
     124           0 :                 if (strcmp(up->name, "subfile"))
     125           0 :                     ret = AVERROR(EINVAL);
     126             : 
     127           0 :                 while(ret >= 0 && (key= strchr(p, sep)) && p<key && (val = strchr(key+1, sep))){
     128           0 :                     *val= *key= 0;
     129           0 :                     if (strcmp(p, "start") && strcmp(p, "end")) {
     130           0 :                         ret = AVERROR_OPTION_NOT_FOUND;
     131             :                     } else
     132           0 :                         ret= av_opt_set(uc->priv_data, p, key+1, 0);
     133           0 :                     if (ret == AVERROR_OPTION_NOT_FOUND)
     134           0 :                         av_log(uc, AV_LOG_ERROR, "Key '%s' not found.\n", p);
     135           0 :                     *val= *key= sep;
     136           0 :                     p= val+1;
     137             :                 }
     138           0 :                 if(ret<0 || p!=key){
     139           0 :                     av_log(uc, AV_LOG_ERROR, "Error parsing options string %s\n", start);
     140           0 :                     av_freep(&uc->priv_data);
     141           0 :                     av_freep(&uc);
     142           0 :                     err = AVERROR(EINVAL);
     143           0 :                     goto fail;
     144             :                 }
     145           0 :                 memmove(start, key+1, strlen(key));
     146             :             }
     147             :         }
     148             :     }
     149      104734 :     if (int_cb)
     150       72200 :         uc->interrupt_callback = *int_cb;
     151             : 
     152      104734 :     *puc = uc;
     153      104734 :     return 0;
     154             : fail:
     155           0 :     *puc = NULL;
     156           0 :     if (uc)
     157           0 :         av_freep(&uc->priv_data);
     158           0 :     av_freep(&uc);
     159             : #if CONFIG_NETWORK
     160           0 :     if (up->flags & URL_PROTOCOL_FLAG_NETWORK)
     161           0 :         ff_network_close();
     162             : #endif
     163           0 :     return err;
     164             : }
     165             : 
     166       72224 : int ffurl_connect(URLContext *uc, AVDictionary **options)
     167             : {
     168             :     int err;
     169       72224 :     AVDictionary *tmp_opts = NULL;
     170             :     AVDictionaryEntry *e;
     171             : 
     172       72224 :     if (!options)
     173           0 :         options = &tmp_opts;
     174             : 
     175             :     // Check that URLContext was initialized correctly and lists are matching if set
     176       72224 :     av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
     177             :                (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
     178       72224 :     av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
     179             :                (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value)));
     180             : 
     181       72224 :     if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
     182           0 :         av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist);
     183           0 :         return AVERROR(EINVAL);
     184             :     }
     185             : 
     186       72224 :     if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) {
     187           0 :         av_log(uc, AV_LOG_ERROR, "Protocol blacklisted \'%s\'!\n", uc->protocol_blacklist);
     188           0 :         return AVERROR(EINVAL);
     189             :     }
     190             : 
     191       72224 :     if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
     192       70355 :         av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
     193       70355 :         uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
     194      140710 :         if (!uc->protocol_whitelist) {
     195           0 :             return AVERROR(ENOMEM);
     196             :         }
     197        1869 :     } else if (!uc->protocol_whitelist)
     198        1783 :         av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should be an error once all declare a default whitelist
     199             : 
     200       72224 :     if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
     201           0 :         return err;
     202       72224 :     if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0)
     203           0 :         return err;
     204             : 
     205       72224 :     err =
     206       72225 :         uc->prot->url_open2 ? uc->prot->url_open2(uc,
     207           1 :                                                   uc->filename,
     208             :                                                   uc->flags,
     209      144448 :                                                   options) :
     210       72223 :         uc->prot->url_open(uc, uc->filename, uc->flags);
     211             : 
     212       72224 :     av_dict_set(options, "protocol_whitelist", NULL, 0);
     213       72224 :     av_dict_set(options, "protocol_blacklist", NULL, 0);
     214             : 
     215       72224 :     if (err)
     216           1 :         return err;
     217       72223 :     uc->is_connected = 1;
     218             :     /* We must be careful here as ffurl_seek() could be slow,
     219             :      * for example for http */
     220       72223 :     if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))
     221       72221 :         if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)
     222        1782 :             uc->is_streamed = 1;
     223       72223 :     return 0;
     224             : }
     225             : 
     226           0 : int ffurl_accept(URLContext *s, URLContext **c)
     227             : {
     228           0 :     av_assert0(!*c);
     229           0 :     if (s->prot->url_accept)
     230           0 :         return s->prot->url_accept(s, c);
     231           0 :     return AVERROR(EBADF);
     232             : }
     233             : 
     234           0 : int ffurl_handshake(URLContext *c)
     235             : {
     236             :     int ret;
     237           0 :     if (c->prot->url_handshake) {
     238           0 :         ret = c->prot->url_handshake(c);
     239           0 :         if (ret)
     240           0 :             return ret;
     241             :     }
     242           0 :     c->is_connected = 1;
     243           0 :     return 0;
     244             : }
     245             : 
     246             : #define URL_SCHEME_CHARS                        \
     247             :     "abcdefghijklmnopqrstuvwxyz"                \
     248             :     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                \
     249             :     "0123456789+-."
     250             : 
     251      108898 : static const struct URLProtocol *url_find_protocol(const char *filename)
     252             : {
     253             :     const URLProtocol **protocols;
     254             :     char proto_str[128], proto_nested[128], *ptr;
     255      108898 :     size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
     256             :     int i;
     257             : 
     258      210312 :     if (filename[proto_len] != ':' &&
     259      108898 :         (strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) ||
     260        7484 :         is_dos_path(filename))
     261      101414 :         strcpy(proto_str, "file");
     262             :     else
     263        7484 :         av_strlcpy(proto_str, filename,
     264        7484 :                    FFMIN(proto_len + 1, sizeof(proto_str)));
     265             : 
     266      108898 :     if ((ptr = strchr(proto_str, ',')))
     267           0 :         *ptr = '\0';
     268      108898 :     av_strlcpy(proto_nested, proto_str, sizeof(proto_nested));
     269      108898 :     if ((ptr = strchr(proto_nested, '+')))
     270           0 :         *ptr = '\0';
     271             : 
     272      108898 :     protocols = ffurl_get_protocols(NULL, NULL);
     273      108898 :     if (!protocols)
     274           0 :         return NULL;
     275      833548 :     for (i = 0; protocols[i]; i++) {
     276      833548 :             const URLProtocol *up = protocols[i];
     277      833548 :         if (!strcmp(proto_str, up->name)) {
     278      108898 :             av_freep(&protocols);
     279      108898 :             return up;
     280             :         }
     281      841030 :         if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
     282      116380 :             !strcmp(proto_nested, up->name)) {
     283           0 :             av_freep(&protocols);
     284           0 :             return up;
     285             :         }
     286             :     }
     287           0 :     av_freep(&protocols);
     288             : 
     289           0 :     return NULL;
     290             : }
     291             : 
     292      104734 : int ffurl_alloc(URLContext **puc, const char *filename, int flags,
     293             :                 const AVIOInterruptCB *int_cb)
     294             : {
     295      104734 :     const URLProtocol *p = NULL;
     296             : 
     297      104734 :     p = url_find_protocol(filename);
     298      104734 :     if (p)
     299      104734 :        return url_alloc_for_protocol(puc, p, filename, flags, int_cb);
     300             : 
     301           0 :     *puc = NULL;
     302           0 :     if (av_strstart(filename, "https:", NULL))
     303           0 :         av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with "
     304             :                                      "openssl, gnutls "
     305             :                                      "or securetransport enabled.\n");
     306           0 :     return AVERROR_PROTOCOL_NOT_FOUND;
     307             : }
     308             : 
     309       72224 : int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
     310             :                          const AVIOInterruptCB *int_cb, AVDictionary **options,
     311             :                          const char *whitelist, const char* blacklist,
     312             :                          URLContext *parent)
     313             : {
     314       72224 :     AVDictionary *tmp_opts = NULL;
     315             :     AVDictionaryEntry *e;
     316       72224 :     int ret = ffurl_alloc(puc, filename, flags, int_cb);
     317       72224 :     if (ret < 0)
     318           0 :         return ret;
     319       72224 :     if (parent)
     320           1 :         av_opt_copy(*puc, parent);
     321       80713 :     if (options &&
     322        8489 :         (ret = av_opt_set_dict(*puc, options)) < 0)
     323           0 :         goto fail;
     324       78931 :     if (options && (*puc)->prot->priv_data_class &&
     325        6707 :         (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
     326           0 :         goto fail;
     327             : 
     328       72224 :     if (!options)
     329       63735 :         options = &tmp_opts;
     330             : 
     331       72224 :     av_assert0(!whitelist ||
     332             :                !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
     333             :                !strcmp(whitelist, e->value));
     334       72224 :     av_assert0(!blacklist ||
     335             :                !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
     336             :                !strcmp(blacklist, e->value));
     337             : 
     338       72224 :     if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
     339           0 :         goto fail;
     340             : 
     341       72224 :     if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
     342           0 :         goto fail;
     343             : 
     344       72224 :     if ((ret = av_opt_set_dict(*puc, options)) < 0)
     345           0 :         goto fail;
     346             : 
     347       72224 :     ret = ffurl_connect(*puc, options);
     348             : 
     349       72224 :     if (!ret)
     350       72223 :         return 0;
     351             : fail:
     352           1 :     ffurl_close(*puc);
     353           1 :     *puc = NULL;
     354           1 :     return ret;
     355             : }
     356             : 
     357           0 : int ffurl_open(URLContext **puc, const char *filename, int flags,
     358             :                const AVIOInterruptCB *int_cb, AVDictionary **options)
     359             : {
     360           0 :     return ffurl_open_whitelist(puc, filename, flags,
     361             :                                 int_cb, options, NULL, NULL, NULL);
     362             : }
     363             : 
     364      711701 : static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
     365             :                                          int size, int size_min,
     366             :                                          int (*transfer_func)(URLContext *h,
     367             :                                                               uint8_t *buf,
     368             :                                                               int size))
     369             : {
     370             :     int ret, len;
     371      711701 :     int fast_retries = 5;
     372      711701 :     int64_t wait_since = 0;
     373             : 
     374      711701 :     len = 0;
     375     2124800 :     while (len < size_min) {
     376      711701 :         if (ff_check_interrupt(&h->interrupt_callback))
     377           0 :             return AVERROR_EXIT;
     378      711701 :         ret = transfer_func(h, buf + len, size - len);
     379      711701 :         if (ret == AVERROR(EINTR))
     380           0 :             continue;
     381      711701 :         if (h->flags & AVIO_FLAG_NONBLOCK)
     382           0 :             return ret;
     383      711701 :         if (ret == AVERROR(EAGAIN)) {
     384           0 :             ret = 0;
     385           0 :             if (fast_retries) {
     386           0 :                 fast_retries--;
     387             :             } else {
     388           0 :                 if (h->rw_timeout) {
     389           0 :                     if (!wait_since)
     390           0 :                         wait_since = av_gettime_relative();
     391           0 :                     else if (av_gettime_relative() > wait_since + h->rw_timeout)
     392           0 :                         return AVERROR(EIO);
     393             :                 }
     394           0 :                 av_usleep(1000);
     395             :             }
     396      711701 :         } else if (ret < 1)
     397       10303 :             return (ret < 0 && ret != AVERROR_EOF) ? ret : len;
     398      701398 :         if (ret) {
     399      701398 :             fast_retries = FFMAX(fast_retries, 2);
     400      701398 :             wait_since = 0;
     401             :         }
     402      701398 :         len += ret;
     403             :     }
     404      701398 :     return len;
     405             : }
     406             : 
     407      156846 : int ffurl_read(URLContext *h, unsigned char *buf, int size)
     408             : {
     409      156846 :     if (!(h->flags & AVIO_FLAG_READ))
     410           0 :         return AVERROR(EIO);
     411      156846 :     return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);
     412             : }
     413             : 
     414           0 : int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
     415             : {
     416           0 :     if (!(h->flags & AVIO_FLAG_READ))
     417           0 :         return AVERROR(EIO);
     418           0 :     return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read);
     419             : }
     420             : 
     421      554855 : int ffurl_write(URLContext *h, const unsigned char *buf, int size)
     422             : {
     423      554855 :     if (!(h->flags & AVIO_FLAG_WRITE))
     424           0 :         return AVERROR(EIO);
     425             :     /* avoid sending too big packets */
     426      554855 :     if (h->max_packet_size && size > h->max_packet_size)
     427           0 :         return AVERROR(EIO);
     428             : 
     429      554855 :     return retry_transfer_wrapper(h, (unsigned char *)buf, size, size,
     430             :                                   (int (*)(struct URLContext *, uint8_t *, int))
     431      554855 :                                   h->prot->url_write);
     432             : }
     433             : 
     434      173026 : int64_t ffurl_seek(URLContext *h, int64_t pos, int whence)
     435             : {
     436             :     int64_t ret;
     437             : 
     438      173026 :     if (!h->prot->url_seek)
     439        9281 :         return AVERROR(ENOSYS);
     440      163745 :     ret = h->prot->url_seek(h, pos, whence & ~AVSEEK_FORCE);
     441      163745 :     return ret;
     442             : }
     443             : 
     444      104734 : int ffurl_closep(URLContext **hh)
     445             : {
     446      104734 :     URLContext *h= *hh;
     447      104734 :     int ret = 0;
     448      104734 :     if (!h)
     449           0 :         return 0;     /* can happen when ffurl_open fails */
     450             : 
     451      104734 :     if (h->is_connected && h->prot->url_close)
     452       70262 :         ret = h->prot->url_close(h);
     453             : #if CONFIG_NETWORK
     454      104734 :     if (h->prot->flags & URL_PROTOCOL_FLAG_NETWORK)
     455           0 :         ff_network_close();
     456             : #endif
     457      104734 :     if (h->prot->priv_data_size) {
     458      104734 :         if (h->prot->priv_data_class)
     459      102952 :             av_opt_free(h->priv_data);
     460      104734 :         av_freep(&h->priv_data);
     461             :     }
     462      104734 :     av_opt_free(h);
     463      104734 :     av_freep(hh);
     464      104734 :     return ret;
     465             : }
     466             : 
     467      104734 : int ffurl_close(URLContext *h)
     468             : {
     469      104734 :     return ffurl_closep(&h);
     470             : }
     471             : 
     472             : 
     473        4164 : const char *avio_find_protocol_name(const char *url)
     474             : {
     475        4164 :     const URLProtocol *p = url_find_protocol(url);
     476             : 
     477        4164 :     return p ? p->name : NULL;
     478             : }
     479             : 
     480       32510 : int avio_check(const char *url, int flags)
     481             : {
     482             :     URLContext *h;
     483       32510 :     int ret = ffurl_alloc(&h, url, flags, NULL);
     484       32510 :     if (ret < 0)
     485           0 :         return ret;
     486             : 
     487       32510 :     if (h->prot->url_check) {
     488       32510 :         ret = h->prot->url_check(h, flags);
     489             :     } else {
     490           0 :         ret = ffurl_connect(h, NULL);
     491           0 :         if (ret >= 0)
     492           0 :             ret = flags;
     493             :     }
     494             : 
     495       32510 :     ffurl_close(h);
     496       32510 :     return ret;
     497             : }
     498             : 
     499           0 : int avpriv_io_move(const char *url_src, const char *url_dst)
     500             : {
     501             :     URLContext *h_src, *h_dst;
     502           0 :     int ret = ffurl_alloc(&h_src, url_src, AVIO_FLAG_READ_WRITE, NULL);
     503           0 :     if (ret < 0)
     504           0 :         return ret;
     505           0 :     ret = ffurl_alloc(&h_dst, url_dst, AVIO_FLAG_WRITE, NULL);
     506           0 :     if (ret < 0) {
     507           0 :         ffurl_close(h_src);
     508           0 :         return ret;
     509             :     }
     510             : 
     511           0 :     if (h_src->prot == h_dst->prot && h_src->prot->url_move)
     512           0 :         ret = h_src->prot->url_move(h_src, h_dst);
     513             :     else
     514           0 :         ret = AVERROR(ENOSYS);
     515             : 
     516           0 :     ffurl_close(h_src);
     517           0 :     ffurl_close(h_dst);
     518           0 :     return ret;
     519             : }
     520             : 
     521           0 : int avpriv_io_delete(const char *url)
     522             : {
     523             :     URLContext *h;
     524           0 :     int ret = ffurl_alloc(&h, url, AVIO_FLAG_WRITE, NULL);
     525           0 :     if (ret < 0)
     526           0 :         return ret;
     527             : 
     528           0 :     if (h->prot->url_delete)
     529           0 :         ret = h->prot->url_delete(h);
     530             :     else
     531           0 :         ret = AVERROR(ENOSYS);
     532             : 
     533           0 :     ffurl_close(h);
     534           0 :     return ret;
     535             : }
     536             : 
     537           0 : int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options)
     538             : {
     539           0 :     URLContext *h = NULL;
     540           0 :     AVIODirContext *ctx = NULL;
     541             :     int ret;
     542           0 :     av_assert0(s);
     543             : 
     544           0 :     ctx = av_mallocz(sizeof(*ctx));
     545           0 :     if (!ctx) {
     546           0 :         ret = AVERROR(ENOMEM);
     547           0 :         goto fail;
     548             :     }
     549             : 
     550           0 :     if ((ret = ffurl_alloc(&h, url, AVIO_FLAG_READ, NULL)) < 0)
     551           0 :         goto fail;
     552             : 
     553           0 :     if (h->prot->url_open_dir && h->prot->url_read_dir && h->prot->url_close_dir) {
     554           0 :         if (options && h->prot->priv_data_class &&
     555           0 :             (ret = av_opt_set_dict(h->priv_data, options)) < 0)
     556           0 :             goto fail;
     557           0 :         ret = h->prot->url_open_dir(h);
     558             :     } else
     559           0 :         ret = AVERROR(ENOSYS);
     560           0 :     if (ret < 0)
     561           0 :         goto fail;
     562             : 
     563           0 :     h->is_connected = 1;
     564           0 :     ctx->url_context = h;
     565           0 :     *s = ctx;
     566           0 :     return 0;
     567             : 
     568             :   fail:
     569           0 :     av_free(ctx);
     570           0 :     *s = NULL;
     571           0 :     ffurl_close(h);
     572           0 :     return ret;
     573             : }
     574             : 
     575           0 : int avio_read_dir(AVIODirContext *s, AVIODirEntry **next)
     576             : {
     577             :     URLContext *h;
     578             :     int ret;
     579             : 
     580           0 :     if (!s || !s->url_context)
     581           0 :         return AVERROR(EINVAL);
     582           0 :     h = s->url_context;
     583           0 :     if ((ret = h->prot->url_read_dir(h, next)) < 0)
     584           0 :         avio_free_directory_entry(next);
     585           0 :     return ret;
     586             : }
     587             : 
     588           0 : int avio_close_dir(AVIODirContext **s)
     589             : {
     590             :     URLContext *h;
     591             : 
     592           0 :     av_assert0(s);
     593           0 :     if (!(*s) || !(*s)->url_context)
     594           0 :         return AVERROR(EINVAL);
     595           0 :     h = (*s)->url_context;
     596           0 :     h->prot->url_close_dir(h);
     597           0 :     ffurl_close(h);
     598           0 :     av_freep(s);
     599           0 :     *s = NULL;
     600           0 :     return 0;
     601             : }
     602             : 
     603           0 : void avio_free_directory_entry(AVIODirEntry **entry)
     604             : {
     605           0 :     if (!entry || !*entry)
     606           0 :         return;
     607           0 :     av_free((*entry)->name);
     608           0 :     av_freep(entry);
     609             : }
     610             : 
     611           0 : int64_t ffurl_size(URLContext *h)
     612             : {
     613             :     int64_t pos, size;
     614             : 
     615           0 :     size = ffurl_seek(h, 0, AVSEEK_SIZE);
     616           0 :     if (size < 0) {
     617           0 :         pos = ffurl_seek(h, 0, SEEK_CUR);
     618           0 :         if ((size = ffurl_seek(h, -1, SEEK_END)) < 0)
     619           0 :             return size;
     620           0 :         size++;
     621           0 :         ffurl_seek(h, pos, SEEK_SET);
     622             :     }
     623           0 :     return size;
     624             : }
     625             : 
     626           0 : int ffurl_get_file_handle(URLContext *h)
     627             : {
     628           0 :     if (!h->prot->url_get_file_handle)
     629           0 :         return -1;
     630           0 :     return h->prot->url_get_file_handle(h);
     631             : }
     632             : 
     633           0 : int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles)
     634             : {
     635           0 :     if (!h->prot->url_get_multi_file_handle) {
     636           0 :         if (!h->prot->url_get_file_handle)
     637           0 :             return AVERROR(ENOSYS);
     638           0 :         *handles = av_malloc(sizeof(**handles));
     639           0 :         if (!*handles)
     640           0 :             return AVERROR(ENOMEM);
     641           0 :         *numhandles = 1;
     642           0 :         *handles[0] = h->prot->url_get_file_handle(h);
     643           0 :         return 0;
     644             :     }
     645           0 :     return h->prot->url_get_multi_file_handle(h, handles, numhandles);
     646             : }
     647             : 
     648           0 : int ffurl_shutdown(URLContext *h, int flags)
     649             : {
     650           0 :     if (!h->prot->url_shutdown)
     651           0 :         return AVERROR(EINVAL);
     652           0 :     return h->prot->url_shutdown(h, flags);
     653             : }
     654             : 
     655      853963 : int ff_check_interrupt(AVIOInterruptCB *cb)
     656             : {
     657             :     int ret;
     658      853963 :     if (cb && cb->callback && (ret = cb->callback(cb->opaque)))
     659           0 :         return ret;
     660      853963 :     return 0;
     661             : }

Generated by: LCOV version 1.12