Line | Branch | Exec | Source |
---|---|---|---|
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/mem.h" | ||
25 | #include "libavutil/opt.h" | ||
26 | #include "libavutil/time.h" | ||
27 | #include "libavutil/avassert.h" | ||
28 | #include "avio_internal.h" | ||
29 | #include "os_support.h" | ||
30 | #include "internal.h" | ||
31 | #if CONFIG_NETWORK | ||
32 | #include "network.h" | ||
33 | #endif | ||
34 | #include "url.h" | ||
35 | |||
36 | #define IO_BUFFER_SIZE 32768 | ||
37 | |||
38 | /** @name Logging context. */ | ||
39 | /*@{*/ | ||
40 | 6 | static const char *urlcontext_to_name(void *ptr) | |
41 | { | ||
42 | 6 | URLContext *h = (URLContext *)ptr; | |
43 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (h->prot) |
44 | 6 | return h->prot->name; | |
45 | else | ||
46 | ✗ | return "NULL"; | |
47 | } | ||
48 | |||
49 | 35328 | static void *urlcontext_child_next(void *obj, void *prev) | |
50 | { | ||
51 | 35328 | URLContext *h = obj; | |
52 |
5/6✓ Branch 0 taken 17666 times.
✓ Branch 1 taken 17662 times.
✓ Branch 2 taken 17666 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17662 times.
✓ Branch 5 taken 4 times.
|
35328 | if (!prev && h->priv_data && h->prot->priv_data_class) |
53 | 17662 | return h->priv_data; | |
54 | 17666 | return NULL; | |
55 | } | ||
56 | |||
57 | #define OFFSET(x) offsetof(URLContext,x) | ||
58 | #define E AV_OPT_FLAG_ENCODING_PARAM | ||
59 | #define D AV_OPT_FLAG_DECODING_PARAM | ||
60 | static const AVOption options[] = { | ||
61 | {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, | ||
62 | {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, | ||
63 | {"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 }, | ||
64 | { NULL } | ||
65 | }; | ||
66 | |||
67 | static const AVClass url_context_class = { | ||
68 | .class_name = "URLContext", | ||
69 | .item_name = urlcontext_to_name, | ||
70 | .option = options, | ||
71 | .version = LIBAVUTIL_VERSION_INT, | ||
72 | .child_next = urlcontext_child_next, | ||
73 | .child_class_iterate = ff_urlcontext_child_class_iterate, | ||
74 | }; | ||
75 | /*@}*/ | ||
76 | |||
77 | 35320 | static void *avio_child_next(void *obj, void *prev) | |
78 | { | ||
79 | 35320 | AVIOContext *s = obj; | |
80 |
2/2✓ Branch 0 taken 17666 times.
✓ Branch 1 taken 17654 times.
|
35320 | return prev ? NULL : s->opaque; |
81 | } | ||
82 | |||
83 | 220125 | static const AVClass *child_class_iterate(void **iter) | |
84 | { | ||
85 |
2/2✓ Branch 0 taken 110065 times.
✓ Branch 1 taken 110060 times.
|
220125 | const AVClass *c = *iter ? NULL : &url_context_class; |
86 | 220125 | *iter = (void*)(uintptr_t)c; | |
87 | 220125 | return c; | |
88 | } | ||
89 | |||
90 | #define AVIOOFFSET(x) offsetof(AVIOContext,x) | ||
91 | #define E AV_OPT_FLAG_ENCODING_PARAM | ||
92 | #define D AV_OPT_FLAG_DECODING_PARAM | ||
93 | static const AVOption avio_options[] = { | ||
94 | {"protocol_whitelist", "List of protocols that are allowed to be used", AVIOOFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, | ||
95 | { NULL }, | ||
96 | }; | ||
97 | |||
98 | const AVClass ff_avio_class = { | ||
99 | .class_name = "AVIOContext", | ||
100 | .item_name = av_default_item_name, | ||
101 | .version = LIBAVUTIL_VERSION_INT, | ||
102 | .option = avio_options, | ||
103 | .child_next = avio_child_next, | ||
104 | .child_class_iterate = child_class_iterate, | ||
105 | }; | ||
106 | |||
107 | ✗ | URLContext *ffio_geturlcontext(AVIOContext *s) | |
108 | { | ||
109 | ✗ | if (!s) | |
110 | ✗ | return NULL; | |
111 | |||
112 | ✗ | if (s->opaque && s->read_packet == ffurl_read2) | |
113 | ✗ | return s->opaque; | |
114 | else | ||
115 | ✗ | return NULL; | |
116 | } | ||
117 | |||
118 | 163105 | static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up, | |
119 | const char *filename, int flags, | ||
120 | const AVIOInterruptCB *int_cb) | ||
121 | { | ||
122 | URLContext *uc; | ||
123 | int err; | ||
124 | |||
125 | #if CONFIG_NETWORK | ||
126 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 163105 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
163105 | if (up->flags & URL_PROTOCOL_FLAG_NETWORK && !ff_network_init()) |
127 | ✗ | return AVERROR(EIO); | |
128 | #endif | ||
129 |
3/4✓ Branch 0 taken 153975 times.
✓ Branch 1 taken 9130 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 153975 times.
|
163105 | if ((flags & AVIO_FLAG_READ) && !up->url_read) { |
130 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
131 | ✗ | "Impossible to open the '%s' protocol for reading\n", up->name); | |
132 | ✗ | return AVERROR(EIO); | |
133 | } | ||
134 |
3/4✓ Branch 0 taken 9208 times.
✓ Branch 1 taken 153897 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9208 times.
|
163105 | if ((flags & AVIO_FLAG_WRITE) && !up->url_write) { |
135 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
136 | ✗ | "Impossible to open the '%s' protocol for writing\n", up->name); | |
137 | ✗ | return AVERROR(EIO); | |
138 | } | ||
139 | 163105 | uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1); | |
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163105 times.
|
163105 | if (!uc) { |
141 | ✗ | err = AVERROR(ENOMEM); | |
142 | ✗ | goto fail; | |
143 | } | ||
144 | 163105 | uc->av_class = &url_context_class; | |
145 | 163105 | uc->filename = (char *)&uc[1]; | |
146 | 163105 | strcpy(uc->filename, filename); | |
147 | 163105 | uc->prot = up; | |
148 | 163105 | uc->flags = flags; | |
149 | 163105 | uc->is_streamed = 0; /* default = not streamed */ | |
150 | 163105 | uc->max_packet_size = 0; /* default: stream file */ | |
151 |
1/2✓ Branch 0 taken 163105 times.
✗ Branch 1 not taken.
|
163105 | if (up->priv_data_size) { |
152 | 163105 | uc->priv_data = av_mallocz(up->priv_data_size); | |
153 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163105 times.
|
163105 | if (!uc->priv_data) { |
154 | ✗ | err = AVERROR(ENOMEM); | |
155 | ✗ | goto fail; | |
156 | } | ||
157 |
2/2✓ Branch 0 taken 160421 times.
✓ Branch 1 taken 2684 times.
|
163105 | if (up->priv_data_class) { |
158 | char *start; | ||
159 | 160421 | *(const AVClass **)uc->priv_data = up->priv_data_class; | |
160 | 160421 | av_opt_set_defaults(uc->priv_data); | |
161 |
3/4✓ Branch 1 taken 2659 times.
✓ Branch 2 taken 157762 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2659 times.
|
160421 | if (av_strstart(uc->filename, up->name, (const char**)&start) && *start == ',') { |
162 | ✗ | int ret= 0; | |
163 | ✗ | char *p= start; | |
164 | ✗ | char sep= *++p; | |
165 | char *key, *val; | ||
166 | ✗ | p++; | |
167 | |||
168 | ✗ | if (strcmp(up->name, "subfile")) | |
169 | ✗ | ret = AVERROR(EINVAL); | |
170 | |||
171 | ✗ | while(ret >= 0 && (key= strchr(p, sep)) && p<key && (val = strchr(key+1, sep))){ | |
172 | ✗ | *val= *key= 0; | |
173 | ✗ | ret = av_opt_set(uc->priv_data, p, key+1, 0); | |
174 | ✗ | if (ret == AVERROR_OPTION_NOT_FOUND) | |
175 | ✗ | av_log(uc, AV_LOG_ERROR, "Key '%s' not found.\n", p); | |
176 | ✗ | *val= *key= sep; | |
177 | ✗ | p= val+1; | |
178 | } | ||
179 | ✗ | if(ret<0 || p!=key){ | |
180 | ✗ | av_log(uc, AV_LOG_ERROR, "Error parsing options string %s\n", start); | |
181 | ✗ | err = AVERROR(EINVAL); | |
182 | ✗ | goto fail; | |
183 | } | ||
184 | ✗ | memmove(start, key+1, strlen(key)); | |
185 | } | ||
186 | } | ||
187 | } | ||
188 |
2/2✓ Branch 0 taken 112436 times.
✓ Branch 1 taken 50669 times.
|
163105 | if (int_cb) |
189 | 112436 | uc->interrupt_callback = *int_cb; | |
190 | |||
191 | 163105 | *puc = uc; | |
192 | 163105 | return 0; | |
193 | ✗ | fail: | |
194 | ✗ | *puc = NULL; | |
195 | ✗ | if (uc) | |
196 | ✗ | av_freep(&uc->priv_data); | |
197 | ✗ | av_freep(&uc); | |
198 | #if CONFIG_NETWORK | ||
199 | ✗ | if (up->flags & URL_PROTOCOL_FLAG_NETWORK) | |
200 | ✗ | ff_network_close(); | |
201 | #endif | ||
202 | ✗ | return err; | |
203 | } | ||
204 | |||
205 | 112531 | int ffurl_connect(URLContext *uc, AVDictionary **options) | |
206 | { | ||
207 | int err; | ||
208 | 112531 | AVDictionary *tmp_opts = NULL; | |
209 | AVDictionaryEntry *e; | ||
210 | |||
211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112531 times.
|
112531 | if (!options) |
212 | ✗ | options = &tmp_opts; | |
213 | |||
214 | // Check that URLContext was initialized correctly and lists are matching if set | ||
215 |
1/6✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
112531 | av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) || |
216 | (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value))); | ||
217 |
1/6✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
112531 | av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) || |
218 | (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value))); | ||
219 | |||
220 |
3/4✓ Branch 0 taken 137 times.
✓ Branch 1 taken 112394 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
|
112531 | if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) { |
221 | ✗ | av_log(uc, AV_LOG_ERROR, "Protocol '%s' not on whitelist '%s'!\n", uc->prot->name, uc->protocol_whitelist); | |
222 | ✗ | return AVERROR(EINVAL); | |
223 | } | ||
224 | |||
225 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 112531 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
112531 | if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) { |
226 | ✗ | av_log(uc, AV_LOG_ERROR, "Protocol '%s' on blacklist '%s'!\n", uc->prot->name, uc->protocol_blacklist); | |
227 | ✗ | return AVERROR(EINVAL); | |
228 | } | ||
229 | |||
230 |
4/4✓ Branch 0 taken 112394 times.
✓ Branch 1 taken 137 times.
✓ Branch 2 taken 109710 times.
✓ Branch 3 taken 2684 times.
|
112531 | if (!uc->protocol_whitelist && uc->prot->default_whitelist) { |
231 | 109710 | av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist); | |
232 | 109710 | uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist); | |
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109710 times.
|
109710 | if (!uc->protocol_whitelist) { |
234 | ✗ | return AVERROR(ENOMEM); | |
235 | } | ||
236 |
2/2✓ Branch 0 taken 2684 times.
✓ Branch 1 taken 137 times.
|
2821 | } else if (!uc->protocol_whitelist) |
237 | 2684 | av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should be an error once all declare a default whitelist | |
238 | |||
239 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
|
112531 | if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0) |
240 | ✗ | return err; | |
241 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
|
112531 | if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0) |
242 | ✗ | return err; | |
243 | |||
244 | 112531 | err = | |
245 | 112532 | uc->prot->url_open2 ? uc->prot->url_open2(uc, | |
246 | 1 | uc->filename, | |
247 | uc->flags, | ||
248 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 112530 times.
|
112531 | options) : |
249 | 112530 | uc->prot->url_open(uc, uc->filename, uc->flags); | |
250 | |||
251 | 112531 | av_dict_set(options, "protocol_whitelist", NULL, 0); | |
252 | 112531 | av_dict_set(options, "protocol_blacklist", NULL, 0); | |
253 | |||
254 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 112530 times.
|
112531 | if (err) |
255 | 1 | return err; | |
256 | 112530 | uc->is_connected = 1; | |
257 | /* We must be careful here as ffurl_seek() could be slow, | ||
258 | * for example for http */ | ||
259 |
4/4✓ Branch 0 taken 103478 times.
✓ Branch 1 taken 9052 times.
✓ Branch 2 taken 103475 times.
✓ Branch 3 taken 3 times.
|
112530 | if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file")) |
260 |
4/4✓ Branch 0 taken 109870 times.
✓ Branch 1 taken 2657 times.
✓ Branch 3 taken 2683 times.
✓ Branch 4 taken 107187 times.
|
112527 | if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0) |
261 | 2683 | uc->is_streamed = 1; | |
262 | 112530 | return 0; | |
263 | } | ||
264 | |||
265 | ✗ | int ffurl_accept(URLContext *s, URLContext **c) | |
266 | { | ||
267 | ✗ | av_assert0(!*c); | |
268 | ✗ | if (s->prot->url_accept) | |
269 | ✗ | return s->prot->url_accept(s, c); | |
270 | ✗ | return AVERROR(EBADF); | |
271 | } | ||
272 | |||
273 | ✗ | int avio_accept(AVIOContext *s, AVIOContext **c) | |
274 | { | ||
275 | int ret; | ||
276 | ✗ | URLContext *sc = s->opaque; | |
277 | ✗ | URLContext *cc = NULL; | |
278 | ✗ | ret = ffurl_accept(sc, &cc); | |
279 | ✗ | if (ret < 0) | |
280 | ✗ | return ret; | |
281 | ✗ | return ffio_fdopen(c, cc); | |
282 | } | ||
283 | |||
284 | ✗ | int ffurl_handshake(URLContext *c) | |
285 | { | ||
286 | int ret; | ||
287 | ✗ | if (c->prot->url_handshake) { | |
288 | ✗ | ret = c->prot->url_handshake(c); | |
289 | ✗ | if (ret) | |
290 | ✗ | return ret; | |
291 | } | ||
292 | ✗ | c->is_connected = 1; | |
293 | ✗ | return 0; | |
294 | } | ||
295 | |||
296 | ✗ | int avio_handshake(AVIOContext *c) | |
297 | { | ||
298 | ✗ | URLContext *cc = c->opaque; | |
299 | ✗ | return ffurl_handshake(cc); | |
300 | } | ||
301 | |||
302 | #define URL_SCHEME_CHARS \ | ||
303 | "abcdefghijklmnopqrstuvwxyz" \ | ||
304 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ | ||
305 | "0123456789+-." | ||
306 | |||
307 | 172100 | static const struct URLProtocol *url_find_protocol(const char *filename) | |
308 | { | ||
309 | const URLProtocol **protocols; | ||
310 | char proto_str[128], proto_nested[128], *ptr; | ||
311 | 172100 | size_t proto_len = strspn(filename, URL_SCHEME_CHARS); | |
312 | int i; | ||
313 | |||
314 |
2/2✓ Branch 0 taken 161445 times.
✓ Branch 1 taken 10655 times.
|
172100 | if (filename[proto_len] != ':' && |
315 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 161445 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10655 times.
|
172100 | (strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) || |
316 | 10655 | is_dos_path(filename)) | |
317 | 161445 | strcpy(proto_str, "file"); | |
318 | else | ||
319 | 10655 | av_strlcpy(proto_str, filename, | |
320 | 10655 | FFMIN(proto_len + 1, sizeof(proto_str))); | |
321 | |||
322 | 172100 | av_strlcpy(proto_nested, proto_str, sizeof(proto_nested)); | |
323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 172100 times.
|
172100 | if ((ptr = strchr(proto_nested, '+'))) |
324 | ✗ | *ptr = '\0'; | |
325 | |||
326 | 172100 | protocols = ffurl_get_protocols(NULL, NULL); | |
327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 172100 times.
|
172100 | if (!protocols) |
328 | ✗ | return NULL; | |
329 |
1/2✓ Branch 0 taken 1650052 times.
✗ Branch 1 not taken.
|
1650052 | for (i = 0; protocols[i]; i++) { |
330 | 1650052 | const URLProtocol *up = protocols[i]; | |
331 |
2/2✓ Branch 0 taken 172100 times.
✓ Branch 1 taken 1477952 times.
|
1650052 | if (!strcmp(proto_str, up->name)) { |
332 | 172100 | av_freep(&protocols); | |
333 | 172100 | return up; | |
334 | } | ||
335 |
2/2✓ Branch 0 taken 182751 times.
✓ Branch 1 taken 1295201 times.
|
1477952 | if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && |
336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 182751 times.
|
182751 | !strcmp(proto_nested, up->name)) { |
337 | ✗ | av_freep(&protocols); | |
338 | ✗ | return up; | |
339 | } | ||
340 | } | ||
341 | ✗ | av_freep(&protocols); | |
342 | ✗ | if (av_strstart(filename, "https:", NULL) || av_strstart(filename, "tls:", NULL)) | |
343 | ✗ | av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with " | |
344 | "openssl, gnutls or securetransport enabled.\n"); | ||
345 | |||
346 | ✗ | return NULL; | |
347 | } | ||
348 | |||
349 | 163105 | int ffurl_alloc(URLContext **puc, const char *filename, int flags, | |
350 | const AVIOInterruptCB *int_cb) | ||
351 | { | ||
352 | 163105 | const URLProtocol *p = NULL; | |
353 | |||
354 | 163105 | p = url_find_protocol(filename); | |
355 |
1/2✓ Branch 0 taken 163105 times.
✗ Branch 1 not taken.
|
163105 | if (p) |
356 | 163105 | return url_alloc_for_protocol(puc, p, filename, flags, int_cb); | |
357 | |||
358 | ✗ | *puc = NULL; | |
359 | ✗ | return AVERROR_PROTOCOL_NOT_FOUND; | |
360 | } | ||
361 | |||
362 | 112531 | int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, | |
363 | const AVIOInterruptCB *int_cb, AVDictionary **options, | ||
364 | const char *whitelist, const char* blacklist, | ||
365 | URLContext *parent) | ||
366 | { | ||
367 | 112531 | AVDictionary *tmp_opts = NULL; | |
368 | AVDictionaryEntry *e; | ||
369 | 112531 | int ret = ffurl_alloc(puc, filename, flags, int_cb); | |
370 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112531 times.
|
112531 | if (ret < 0) |
371 | ✗ | return ret; | |
372 |
2/2✓ Branch 0 taken 389 times.
✓ Branch 1 taken 112142 times.
|
112531 | if (parent) { |
373 | 389 | ret = av_opt_copy(*puc, parent); | |
374 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
|
389 | if (ret < 0) |
375 | ✗ | goto fail; | |
376 | } | ||
377 |
3/4✓ Branch 0 taken 13174 times.
✓ Branch 1 taken 99357 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13174 times.
|
125705 | if (options && |
378 | 13174 | (ret = av_opt_set_dict(*puc, options)) < 0) | |
379 | ✗ | goto fail; | |
380 |
5/6✓ Branch 0 taken 13174 times.
✓ Branch 1 taken 99357 times.
✓ Branch 2 taken 10490 times.
✓ Branch 3 taken 2684 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10490 times.
|
123021 | if (options && (*puc)->prot->priv_data_class && |
381 | 10490 | (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0) | |
382 | ✗ | goto fail; | |
383 | |||
384 |
2/2✓ Branch 0 taken 99357 times.
✓ Branch 1 taken 13174 times.
|
112531 | if (!options) |
385 | 99357 | options = &tmp_opts; | |
386 | |||
387 |
3/6✓ Branch 0 taken 137 times.
✓ Branch 1 taken 112394 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
112531 | av_assert0(!whitelist || |
388 | !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) || | ||
389 | !strcmp(whitelist, e->value)); | ||
390 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 112531 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
112531 | av_assert0(!blacklist || |
391 | !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) || | ||
392 | !strcmp(blacklist, e->value)); | ||
393 | |||
394 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
|
112531 | if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0) |
395 | ✗ | goto fail; | |
396 | |||
397 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
|
112531 | if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0) |
398 | ✗ | goto fail; | |
399 | |||
400 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 112531 times.
|
112531 | if ((ret = av_opt_set_dict(*puc, options)) < 0) |
401 | ✗ | goto fail; | |
402 | |||
403 | 112531 | ret = ffurl_connect(*puc, options); | |
404 | |||
405 |
2/2✓ Branch 0 taken 112530 times.
✓ Branch 1 taken 1 times.
|
112531 | if (!ret) |
406 | 112530 | return 0; | |
407 | 1 | fail: | |
408 | 1 | ffurl_closep(puc); | |
409 | 1 | return ret; | |
410 | } | ||
411 | |||
412 | 112141 | int ffio_fdopen(AVIOContext **sp, URLContext *h) | |
413 | { | ||
414 | AVIOContext *s; | ||
415 | 112141 | uint8_t *buffer = NULL; | |
416 | int buffer_size, max_packet_size; | ||
417 | |||
418 | 112141 | max_packet_size = h->max_packet_size; | |
419 |
2/2✓ Branch 0 taken 3328 times.
✓ Branch 1 taken 108813 times.
|
112141 | if (max_packet_size) { |
420 | 3328 | buffer_size = max_packet_size; /* no need to bufferize more than one packet */ | |
421 | } else { | ||
422 | 108813 | buffer_size = IO_BUFFER_SIZE; | |
423 | } | ||
424 |
3/4✓ Branch 0 taken 103473 times.
✓ Branch 1 taken 8668 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 103473 times.
|
112141 | if (!(h->flags & AVIO_FLAG_WRITE) && h->is_streamed) { |
425 | ✗ | if (buffer_size > INT_MAX/2) | |
426 | ✗ | return AVERROR(EINVAL); | |
427 | ✗ | buffer_size *= 2; | |
428 | } | ||
429 | 112141 | buffer = av_malloc(buffer_size); | |
430 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112141 times.
|
112141 | if (!buffer) |
431 | ✗ | return AVERROR(ENOMEM); | |
432 | |||
433 | 112141 | *sp = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h, | |
434 | ffurl_read2, ffurl_write2, ffurl_seek2); | ||
435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112141 times.
|
112141 | if (!*sp) { |
436 | ✗ | av_freep(&buffer); | |
437 | ✗ | return AVERROR(ENOMEM); | |
438 | } | ||
439 | 112141 | s = *sp; | |
440 |
2/2✓ Branch 0 taken 109457 times.
✓ Branch 1 taken 2684 times.
|
112141 | if (h->protocol_whitelist) { |
441 | 109457 | s->protocol_whitelist = av_strdup(h->protocol_whitelist); | |
442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109457 times.
|
109457 | if (!s->protocol_whitelist) { |
443 | ✗ | avio_closep(sp); | |
444 | ✗ | return AVERROR(ENOMEM); | |
445 | } | ||
446 | } | ||
447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112141 times.
|
112141 | if (h->protocol_blacklist) { |
448 | ✗ | s->protocol_blacklist = av_strdup(h->protocol_blacklist); | |
449 | ✗ | if (!s->protocol_blacklist) { | |
450 | ✗ | avio_closep(sp); | |
451 | ✗ | return AVERROR(ENOMEM); | |
452 | } | ||
453 | } | ||
454 | 112141 | s->direct = h->flags & AVIO_FLAG_DIRECT; | |
455 | |||
456 | 112141 | s->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL; | |
457 | 112141 | s->max_packet_size = max_packet_size; | |
458 | 112141 | s->min_packet_size = h->min_packet_size; | |
459 |
1/2✓ Branch 0 taken 112141 times.
✗ Branch 1 not taken.
|
112141 | if(h->prot) { |
460 | 112141 | s->read_pause = h->prot->url_read_pause; | |
461 | 112141 | s->read_seek = h->prot->url_read_seek; | |
462 | |||
463 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112141 times.
|
112141 | if (h->prot->url_read_seek) |
464 | ✗ | s->seekable |= AVIO_SEEKABLE_TIME; | |
465 | } | ||
466 | 112141 | ((FFIOContext*)s)->short_seek_get = ffurl_get_short_seek; | |
467 | 112141 | s->av_class = &ff_avio_class; | |
468 | 112141 | return 0; | |
469 | } | ||
470 | |||
471 | 112142 | int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags, | |
472 | const AVIOInterruptCB *int_cb, AVDictionary **options, | ||
473 | const char *whitelist, const char *blacklist) | ||
474 | { | ||
475 | URLContext *h; | ||
476 | int err; | ||
477 | |||
478 | 112142 | *s = NULL; | |
479 | |||
480 | 112142 | err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL); | |
481 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 112141 times.
|
112142 | if (err < 0) |
482 | 1 | return err; | |
483 | 112141 | err = ffio_fdopen(s, h); | |
484 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112141 times.
|
112141 | if (err < 0) { |
485 | ✗ | ffurl_close(h); | |
486 | ✗ | return err; | |
487 | } | ||
488 | 112141 | return 0; | |
489 | } | ||
490 | |||
491 | 7920 | int avio_open2(AVIOContext **s, const char *filename, int flags, | |
492 | const AVIOInterruptCB *int_cb, AVDictionary **options) | ||
493 | { | ||
494 | 7920 | return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL); | |
495 | } | ||
496 | |||
497 | 95 | int avio_open(AVIOContext **s, const char *filename, int flags) | |
498 | { | ||
499 | 95 | return avio_open2(s, filename, flags, NULL, NULL); | |
500 | } | ||
501 | |||
502 | |||
503 | 595416 | static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, | |
504 | const uint8_t *cbuf, | ||
505 | int size, int size_min, | ||
506 | int read) | ||
507 | { | ||
508 | int ret, len; | ||
509 | 595416 | int fast_retries = 5; | |
510 | 595416 | int64_t wait_since = 0; | |
511 | |||
512 | 595416 | len = 0; | |
513 |
2/2✓ Branch 0 taken 595416 times.
✓ Branch 1 taken 583266 times.
|
1178682 | while (len < size_min) { |
514 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 595416 times.
|
595416 | if (ff_check_interrupt(&h->interrupt_callback)) |
515 | ✗ | return AVERROR_EXIT; | |
516 |
2/2✓ Branch 0 taken 218605 times.
✓ Branch 1 taken 376811 times.
|
595416 | ret = read ? h->prot->url_read (h, buf + len, size - len): |
517 | 376811 | h->prot->url_write(h, cbuf + len, size - len); | |
518 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 595416 times.
|
595416 | if (ret == AVERROR(EINTR)) |
519 | ✗ | continue; | |
520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 595416 times.
|
595416 | if (h->flags & AVIO_FLAG_NONBLOCK) |
521 | ✗ | return ret; | |
522 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 595416 times.
|
595416 | if (ret == AVERROR(EAGAIN)) { |
523 | ✗ | ret = 0; | |
524 | ✗ | if (fast_retries) { | |
525 | ✗ | fast_retries--; | |
526 | } else { | ||
527 | ✗ | if (h->rw_timeout) { | |
528 | ✗ | if (!wait_since) | |
529 | ✗ | wait_since = av_gettime_relative(); | |
530 | ✗ | else if (av_gettime_relative() > wait_since + h->rw_timeout) | |
531 | ✗ | return AVERROR(EIO); | |
532 | } | ||
533 | ✗ | av_usleep(1000); | |
534 | } | ||
535 |
2/2✓ Branch 0 taken 12150 times.
✓ Branch 1 taken 583266 times.
|
595416 | } else if (ret == AVERROR_EOF) |
536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12150 times.
|
12150 | return (len > 0) ? len : AVERROR_EOF; |
537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 583266 times.
|
583266 | else if (ret < 0) |
538 | ✗ | return ret; | |
539 |
1/2✓ Branch 0 taken 583266 times.
✗ Branch 1 not taken.
|
583266 | if (ret) { |
540 | 583266 | fast_retries = FFMAX(fast_retries, 2); | |
541 | 583266 | wait_since = 0; | |
542 | } | ||
543 | 583266 | len += ret; | |
544 | } | ||
545 | 583266 | return len; | |
546 | } | ||
547 | |||
548 | 218605 | int ffurl_read2(void *urlcontext, uint8_t *buf, int size) | |
549 | { | ||
550 | 218605 | URLContext *h = urlcontext; | |
551 | |||
552 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 218605 times.
|
218605 | if (!(h->flags & AVIO_FLAG_READ)) |
553 | ✗ | return AVERROR(EIO); | |
554 | 218605 | return retry_transfer_wrapper(h, buf, NULL, size, 1, 1); | |
555 | } | ||
556 | |||
557 | ✗ | int ffurl_read_complete(URLContext *h, unsigned char *buf, int size) | |
558 | { | ||
559 | ✗ | if (!(h->flags & AVIO_FLAG_READ)) | |
560 | ✗ | return AVERROR(EIO); | |
561 | ✗ | return retry_transfer_wrapper(h, buf, NULL, size, size, 1); | |
562 | } | ||
563 | |||
564 | 376811 | int ffurl_write2(void *urlcontext, const uint8_t *buf, int size) | |
565 | { | ||
566 | 376811 | URLContext *h = urlcontext; | |
567 | |||
568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 376811 times.
|
376811 | if (!(h->flags & AVIO_FLAG_WRITE)) |
569 | ✗ | return AVERROR(EIO); | |
570 | /* avoid sending too big packets */ | ||
571 |
3/4✓ Branch 0 taken 64070 times.
✓ Branch 1 taken 312741 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 64070 times.
|
376811 | if (h->max_packet_size && size > h->max_packet_size) |
572 | ✗ | return AVERROR(EIO); | |
573 | |||
574 | 376811 | return retry_transfer_wrapper(h, NULL, buf, size, size, 0); | |
575 | } | ||
576 | |||
577 | 358507 | int64_t ffurl_seek2(void *urlcontext, int64_t pos, int whence) | |
578 | { | ||
579 | 358507 | URLContext *h = urlcontext; | |
580 | int64_t ret; | ||
581 | |||
582 |
2/2✓ Branch 0 taken 32127 times.
✓ Branch 1 taken 326380 times.
|
358507 | if (!h->prot->url_seek) |
583 | 32127 | return AVERROR(ENOSYS); | |
584 | 326380 | ret = h->prot->url_seek(h, pos, whence & ~AVSEEK_FORCE); | |
585 | 326380 | return ret; | |
586 | } | ||
587 | |||
588 | 163105 | int ffurl_closep(URLContext **hh) | |
589 | { | ||
590 | 163105 | URLContext *h= *hh; | |
591 | 163105 | int ret = 0; | |
592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163105 times.
|
163105 | if (!h) |
593 | ✗ | return 0; /* can happen when ffurl_open fails */ | |
594 | |||
595 |
3/4✓ Branch 0 taken 112530 times.
✓ Branch 1 taken 50575 times.
✓ Branch 2 taken 112530 times.
✗ Branch 3 not taken.
|
163105 | if (h->is_connected && h->prot->url_close) |
596 | 112530 | ret = h->prot->url_close(h); | |
597 | #if CONFIG_NETWORK | ||
598 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 163105 times.
|
163105 | if (h->prot->flags & URL_PROTOCOL_FLAG_NETWORK) |
599 | ✗ | ff_network_close(); | |
600 | #endif | ||
601 |
1/2✓ Branch 0 taken 163105 times.
✗ Branch 1 not taken.
|
163105 | if (h->prot->priv_data_size) { |
602 |
2/2✓ Branch 0 taken 160421 times.
✓ Branch 1 taken 2684 times.
|
163105 | if (h->prot->priv_data_class) |
603 | 160421 | av_opt_free(h->priv_data); | |
604 | 163105 | av_freep(&h->priv_data); | |
605 | } | ||
606 | 163105 | av_opt_free(h); | |
607 | 163105 | av_freep(hh); | |
608 | 163105 | return ret; | |
609 | } | ||
610 | |||
611 | 163099 | int ffurl_close(URLContext *h) | |
612 | { | ||
613 | 163099 | return ffurl_closep(&h); | |
614 | } | ||
615 | |||
616 | 123012 | int avio_close(AVIOContext *s) | |
617 | { | ||
618 | 123012 | FFIOContext *const ctx = ffiocontext(s); | |
619 | URLContext *h; | ||
620 | int ret, error; | ||
621 | |||
622 |
2/2✓ Branch 0 taken 10871 times.
✓ Branch 1 taken 112141 times.
|
123012 | if (!s) |
623 | 10871 | return 0; | |
624 | |||
625 | 112141 | avio_flush(s); | |
626 | 112141 | h = s->opaque; | |
627 | 112141 | s->opaque = NULL; | |
628 | |||
629 | 112141 | av_freep(&s->buffer); | |
630 |
2/2✓ Branch 0 taken 8668 times.
✓ Branch 1 taken 103473 times.
|
112141 | if (s->write_flag) |
631 | 8668 | av_log(s, AV_LOG_VERBOSE, | |
632 | "Statistics: %"PRId64" bytes written, %d seeks, %d writeouts\n", | ||
633 | ctx->bytes_written, ctx->seek_count, ctx->writeout_count); | ||
634 | else | ||
635 | 103473 | av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n", | |
636 | ctx->bytes_read, ctx->seek_count); | ||
637 | 112141 | av_opt_free(s); | |
638 | |||
639 | 112141 | error = s->error; | |
640 | 112141 | avio_context_free(&s); | |
641 | |||
642 | 112141 | ret = ffurl_close(h); | |
643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112141 times.
|
112141 | if (ret < 0) |
644 | ✗ | return ret; | |
645 | |||
646 | 112141 | return error; | |
647 | } | ||
648 | |||
649 | 15743 | int avio_closep(AVIOContext **s) | |
650 | { | ||
651 | 15743 | int ret = avio_close(*s); | |
652 | 15743 | *s = NULL; | |
653 | 15743 | return ret; | |
654 | } | ||
655 | |||
656 | |||
657 | 8995 | const char *avio_find_protocol_name(const char *url) | |
658 | { | ||
659 | 8995 | const URLProtocol *p = url_find_protocol(url); | |
660 | |||
661 |
1/2✓ Branch 0 taken 8995 times.
✗ Branch 1 not taken.
|
8995 | return p ? p->name : NULL; |
662 | } | ||
663 | |||
664 | 50418 | int avio_check(const char *url, int flags) | |
665 | { | ||
666 | URLContext *h; | ||
667 | 50418 | int ret = ffurl_alloc(&h, url, flags, NULL); | |
668 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50418 times.
|
50418 | if (ret < 0) |
669 | ✗ | return ret; | |
670 | |||
671 |
1/2✓ Branch 0 taken 50418 times.
✗ Branch 1 not taken.
|
50418 | if (h->prot->url_check) { |
672 | 50418 | ret = h->prot->url_check(h, flags); | |
673 | } else { | ||
674 | ✗ | ret = ffurl_connect(h, NULL); | |
675 | ✗ | if (ret >= 0) | |
676 | ✗ | ret = flags; | |
677 | } | ||
678 | |||
679 | 50418 | ffurl_close(h); | |
680 | 50418 | return ret; | |
681 | } | ||
682 | |||
683 | 78 | int ffurl_move(const char *url_src, const char *url_dst) | |
684 | { | ||
685 | URLContext *h_src, *h_dst; | ||
686 | 78 | int ret = ffurl_alloc(&h_src, url_src, AVIO_FLAG_READ_WRITE, NULL); | |
687 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
|
78 | if (ret < 0) |
688 | ✗ | return ret; | |
689 | 78 | ret = ffurl_alloc(&h_dst, url_dst, AVIO_FLAG_WRITE, NULL); | |
690 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
|
78 | if (ret < 0) { |
691 | ✗ | ffurl_close(h_src); | |
692 | ✗ | return ret; | |
693 | } | ||
694 | |||
695 |
2/4✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
|
78 | if (h_src->prot == h_dst->prot && h_src->prot->url_move) |
696 | 78 | ret = h_src->prot->url_move(h_src, h_dst); | |
697 | else | ||
698 | ✗ | ret = AVERROR(ENOSYS); | |
699 | |||
700 | 78 | ffurl_close(h_src); | |
701 | 78 | ffurl_close(h_dst); | |
702 | 78 | return ret; | |
703 | } | ||
704 | |||
705 | ✗ | int ffurl_delete(const char *url) | |
706 | { | ||
707 | URLContext *h; | ||
708 | ✗ | int ret = ffurl_alloc(&h, url, AVIO_FLAG_WRITE, NULL); | |
709 | ✗ | if (ret < 0) | |
710 | ✗ | return ret; | |
711 | |||
712 | ✗ | if (h->prot->url_delete) | |
713 | ✗ | ret = h->prot->url_delete(h); | |
714 | else | ||
715 | ✗ | ret = AVERROR(ENOSYS); | |
716 | |||
717 | ✗ | ffurl_close(h); | |
718 | ✗ | return ret; | |
719 | } | ||
720 | |||
721 | struct AVIODirContext { | ||
722 | struct URLContext *url_context; | ||
723 | }; | ||
724 | |||
725 | ✗ | int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options) | |
726 | { | ||
727 | ✗ | URLContext *h = NULL; | |
728 | ✗ | AVIODirContext *ctx = NULL; | |
729 | int ret; | ||
730 | ✗ | av_assert0(s); | |
731 | |||
732 | ✗ | ctx = av_mallocz(sizeof(*ctx)); | |
733 | ✗ | if (!ctx) { | |
734 | ✗ | ret = AVERROR(ENOMEM); | |
735 | ✗ | goto fail; | |
736 | } | ||
737 | |||
738 | ✗ | if ((ret = ffurl_alloc(&h, url, AVIO_FLAG_READ, NULL)) < 0) | |
739 | ✗ | goto fail; | |
740 | |||
741 | ✗ | if (h->prot->url_open_dir && h->prot->url_read_dir && h->prot->url_close_dir) { | |
742 | ✗ | if (options && h->prot->priv_data_class && | |
743 | ✗ | (ret = av_opt_set_dict(h->priv_data, options)) < 0) | |
744 | ✗ | goto fail; | |
745 | ✗ | ret = h->prot->url_open_dir(h); | |
746 | } else | ||
747 | ✗ | ret = AVERROR(ENOSYS); | |
748 | ✗ | if (ret < 0) | |
749 | ✗ | goto fail; | |
750 | |||
751 | ✗ | h->is_connected = 1; | |
752 | ✗ | ctx->url_context = h; | |
753 | ✗ | *s = ctx; | |
754 | ✗ | return 0; | |
755 | |||
756 | ✗ | fail: | |
757 | ✗ | av_free(ctx); | |
758 | ✗ | *s = NULL; | |
759 | ✗ | ffurl_close(h); | |
760 | ✗ | return ret; | |
761 | } | ||
762 | |||
763 | ✗ | int avio_read_dir(AVIODirContext *s, AVIODirEntry **next) | |
764 | { | ||
765 | URLContext *h; | ||
766 | int ret; | ||
767 | |||
768 | ✗ | if (!s || !s->url_context) | |
769 | ✗ | return AVERROR(EINVAL); | |
770 | ✗ | h = s->url_context; | |
771 | ✗ | if ((ret = h->prot->url_read_dir(h, next)) < 0) | |
772 | ✗ | avio_free_directory_entry(next); | |
773 | ✗ | return ret; | |
774 | } | ||
775 | |||
776 | ✗ | int avio_close_dir(AVIODirContext **s) | |
777 | { | ||
778 | URLContext *h; | ||
779 | |||
780 | ✗ | av_assert0(s); | |
781 | ✗ | if (!(*s) || !(*s)->url_context) | |
782 | ✗ | return AVERROR(EINVAL); | |
783 | ✗ | h = (*s)->url_context; | |
784 | ✗ | h->prot->url_close_dir(h); | |
785 | ✗ | ffurl_close(h); | |
786 | ✗ | av_freep(s); | |
787 | ✗ | *s = NULL; | |
788 | ✗ | return 0; | |
789 | } | ||
790 | |||
791 | ✗ | void avio_free_directory_entry(AVIODirEntry **entry) | |
792 | { | ||
793 | ✗ | if (!entry || !*entry) | |
794 | ✗ | return; | |
795 | ✗ | av_free((*entry)->name); | |
796 | ✗ | av_freep(entry); | |
797 | } | ||
798 | |||
799 | 4 | int64_t ffurl_size(URLContext *h) | |
800 | { | ||
801 | int64_t pos, size; | ||
802 | |||
803 | 4 | size = ffurl_seek(h, 0, AVSEEK_SIZE); | |
804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (size < 0) { |
805 | ✗ | pos = ffurl_seek(h, 0, SEEK_CUR); | |
806 | ✗ | if ((size = ffurl_seek(h, -1, SEEK_END)) < 0) | |
807 | ✗ | return size; | |
808 | ✗ | size++; | |
809 | ✗ | ffurl_seek(h, pos, SEEK_SET); | |
810 | } | ||
811 | 4 | return size; | |
812 | } | ||
813 | |||
814 | ✗ | int ffurl_get_file_handle(URLContext *h) | |
815 | { | ||
816 | ✗ | if (!h || !h->prot || !h->prot->url_get_file_handle) | |
817 | ✗ | return -1; | |
818 | ✗ | return h->prot->url_get_file_handle(h); | |
819 | } | ||
820 | |||
821 | ✗ | int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles) | |
822 | { | ||
823 | ✗ | if (!h || !h->prot) | |
824 | ✗ | return AVERROR(ENOSYS); | |
825 | ✗ | if (!h->prot->url_get_multi_file_handle) { | |
826 | ✗ | if (!h->prot->url_get_file_handle) | |
827 | ✗ | return AVERROR(ENOSYS); | |
828 | ✗ | *handles = av_malloc(sizeof(**handles)); | |
829 | ✗ | if (!*handles) | |
830 | ✗ | return AVERROR(ENOMEM); | |
831 | ✗ | *numhandles = 1; | |
832 | ✗ | *handles[0] = h->prot->url_get_file_handle(h); | |
833 | ✗ | return 0; | |
834 | } | ||
835 | ✗ | return h->prot->url_get_multi_file_handle(h, handles, numhandles); | |
836 | } | ||
837 | |||
838 | 322651 | int ffurl_get_short_seek(void *urlcontext) | |
839 | { | ||
840 | 322651 | URLContext *h = urlcontext; | |
841 | |||
842 |
3/6✓ Branch 0 taken 322651 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 322651 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 322651 times.
✗ Branch 5 not taken.
|
322651 | if (!h || !h->prot || !h->prot->url_get_short_seek) |
843 | 322651 | return AVERROR(ENOSYS); | |
844 | ✗ | return h->prot->url_get_short_seek(h); | |
845 | } | ||
846 | |||
847 | ✗ | int ffurl_shutdown(URLContext *h, int flags) | |
848 | { | ||
849 | ✗ | if (!h || !h->prot || !h->prot->url_shutdown) | |
850 | ✗ | return AVERROR(ENOSYS); | |
851 | ✗ | return h->prot->url_shutdown(h, flags); | |
852 | } | ||
853 | |||
854 | 794873 | int ff_check_interrupt(AVIOInterruptCB *cb) | |
855 | { | ||
856 |
3/4✓ Branch 0 taken 794873 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 768041 times.
✓ Branch 3 taken 26832 times.
|
794873 | if (cb && cb->callback) |
857 | 768041 | return cb->callback(cb->opaque); | |
858 | 26832 | return 0; | |
859 | } | ||
860 | |||
861 | 78 | int ff_rename(const char *url_src, const char *url_dst, void *logctx) | |
862 | { | ||
863 | 78 | int ret = ffurl_move(url_src, url_dst); | |
864 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
|
78 | if (ret < 0) |
865 | ✗ | av_log(logctx, AV_LOG_ERROR, "failed to rename file %s to %s: %s\n", url_src, url_dst, av_err2str(ret)); | |
866 | 78 | return ret; | |
867 | } | ||
868 |