xref: /qemu/block/curl.c (revision 814bb12a)
1 /*
2  * QEMU Block driver for CURL images
3  *
4  * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "qemu/osdep.h"
25 #include "qapi/error.h"
26 #include "qemu-common.h"
27 #include "qemu/error-report.h"
28 #include "block/block_int.h"
29 #include "qapi/qmp/qbool.h"
30 #include "qapi/qmp/qstring.h"
31 #include "crypto/secret.h"
32 #include <curl/curl.h>
33 #include "qemu/cutils.h"
34 
35 // #define DEBUG_CURL
36 // #define DEBUG_VERBOSE
37 
38 #ifdef DEBUG_CURL
39 #define DEBUG_CURL_PRINT 1
40 #else
41 #define DEBUG_CURL_PRINT 0
42 #endif
43 #define DPRINTF(fmt, ...)                                            \
44     do {                                                             \
45         if (DEBUG_CURL_PRINT) {                                      \
46             fprintf(stderr, fmt, ## __VA_ARGS__);                    \
47         }                                                            \
48     } while (0)
49 
50 #if LIBCURL_VERSION_NUM >= 0x071000
51 /* The multi interface timer callback was introduced in 7.16.0 */
52 #define NEED_CURL_TIMER_CALLBACK
53 #define HAVE_SOCKET_ACTION
54 #endif
55 
56 #ifndef HAVE_SOCKET_ACTION
57 /* If curl_multi_socket_action isn't available, define it statically here in
58  * terms of curl_multi_socket. Note that ev_bitmask will be ignored, which is
59  * less efficient but still safe. */
60 static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
61                                             curl_socket_t sockfd,
62                                             int ev_bitmask,
63                                             int *running_handles)
64 {
65     return curl_multi_socket(multi_handle, sockfd, running_handles);
66 }
67 #define curl_multi_socket_action __curl_multi_socket_action
68 #endif
69 
70 #define PROTOCOLS (CURLPROTO_HTTP | CURLPROTO_HTTPS | \
71                    CURLPROTO_FTP | CURLPROTO_FTPS | \
72                    CURLPROTO_TFTP)
73 
74 #define CURL_NUM_STATES 8
75 #define CURL_NUM_ACB    8
76 #define SECTOR_SIZE     512
77 #define READ_AHEAD_DEFAULT (256 * 1024)
78 #define CURL_TIMEOUT_DEFAULT 5
79 #define CURL_TIMEOUT_MAX 10000
80 
81 #define FIND_RET_NONE   0
82 #define FIND_RET_OK     1
83 #define FIND_RET_WAIT   2
84 
85 #define CURL_BLOCK_OPT_URL       "url"
86 #define CURL_BLOCK_OPT_READAHEAD "readahead"
87 #define CURL_BLOCK_OPT_SSLVERIFY "sslverify"
88 #define CURL_BLOCK_OPT_TIMEOUT "timeout"
89 #define CURL_BLOCK_OPT_COOKIE    "cookie"
90 #define CURL_BLOCK_OPT_USERNAME "username"
91 #define CURL_BLOCK_OPT_PASSWORD_SECRET "password-secret"
92 #define CURL_BLOCK_OPT_PROXY_USERNAME "proxy-username"
93 #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret"
94 
95 struct BDRVCURLState;
96 
97 typedef struct CURLAIOCB {
98     BlockAIOCB common;
99     QEMUIOVector *qiov;
100 
101     int64_t sector_num;
102     int nb_sectors;
103 
104     size_t start;
105     size_t end;
106 } CURLAIOCB;
107 
108 typedef struct CURLState
109 {
110     struct BDRVCURLState *s;
111     CURLAIOCB *acb[CURL_NUM_ACB];
112     CURL *curl;
113     curl_socket_t sock_fd;
114     char *orig_buf;
115     size_t buf_start;
116     size_t buf_off;
117     size_t buf_len;
118     char range[128];
119     char errmsg[CURL_ERROR_SIZE];
120     char in_use;
121 } CURLState;
122 
123 typedef struct BDRVCURLState {
124     CURLM *multi;
125     QEMUTimer timer;
126     size_t len;
127     CURLState states[CURL_NUM_STATES];
128     char *url;
129     size_t readahead_size;
130     bool sslverify;
131     uint64_t timeout;
132     char *cookie;
133     bool accept_range;
134     AioContext *aio_context;
135     char *username;
136     char *password;
137     char *proxyusername;
138     char *proxypassword;
139 } BDRVCURLState;
140 
141 static void curl_clean_state(CURLState *s);
142 static void curl_multi_do(void *arg);
143 static void curl_multi_read(void *arg);
144 
145 #ifdef NEED_CURL_TIMER_CALLBACK
146 static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
147 {
148     BDRVCURLState *s = opaque;
149 
150     DPRINTF("CURL: timer callback timeout_ms %ld\n", timeout_ms);
151     if (timeout_ms == -1) {
152         timer_del(&s->timer);
153     } else {
154         int64_t timeout_ns = (int64_t)timeout_ms * 1000 * 1000;
155         timer_mod(&s->timer,
156                   qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + timeout_ns);
157     }
158     return 0;
159 }
160 #endif
161 
162 static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
163                         void *userp, void *sp)
164 {
165     BDRVCURLState *s;
166     CURLState *state = NULL;
167     curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
168     state->sock_fd = fd;
169     s = state->s;
170 
171     DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd);
172     switch (action) {
173         case CURL_POLL_IN:
174             aio_set_fd_handler(s->aio_context, fd, false,
175                                curl_multi_read, NULL, state);
176             break;
177         case CURL_POLL_OUT:
178             aio_set_fd_handler(s->aio_context, fd, false,
179                                NULL, curl_multi_do, state);
180             break;
181         case CURL_POLL_INOUT:
182             aio_set_fd_handler(s->aio_context, fd, false,
183                                curl_multi_read, curl_multi_do, state);
184             break;
185         case CURL_POLL_REMOVE:
186             aio_set_fd_handler(s->aio_context, fd, false,
187                                NULL, NULL, NULL);
188             break;
189     }
190 
191     return 0;
192 }
193 
194 static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
195 {
196     BDRVCURLState *s = opaque;
197     size_t realsize = size * nmemb;
198     const char *accept_line = "Accept-Ranges: bytes";
199 
200     if (realsize >= strlen(accept_line)
201         && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) {
202         s->accept_range = true;
203     }
204 
205     return realsize;
206 }
207 
208 static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
209 {
210     CURLState *s = ((CURLState*)opaque);
211     size_t realsize = size * nmemb;
212     int i;
213 
214     DPRINTF("CURL: Just reading %zd bytes\n", realsize);
215 
216     if (!s || !s->orig_buf)
217         return 0;
218 
219     if (s->buf_off >= s->buf_len) {
220         /* buffer full, read nothing */
221         return 0;
222     }
223     realsize = MIN(realsize, s->buf_len - s->buf_off);
224     memcpy(s->orig_buf + s->buf_off, ptr, realsize);
225     s->buf_off += realsize;
226 
227     for(i=0; i<CURL_NUM_ACB; i++) {
228         CURLAIOCB *acb = s->acb[i];
229 
230         if (!acb)
231             continue;
232 
233         if ((s->buf_off >= acb->end)) {
234             qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start,
235                                 acb->end - acb->start);
236             acb->common.cb(acb->common.opaque, 0);
237             qemu_aio_unref(acb);
238             s->acb[i] = NULL;
239         }
240     }
241 
242     return realsize;
243 }
244 
245 static int curl_find_buf(BDRVCURLState *s, size_t start, size_t len,
246                          CURLAIOCB *acb)
247 {
248     int i;
249     size_t end = start + len;
250 
251     for (i=0; i<CURL_NUM_STATES; i++) {
252         CURLState *state = &s->states[i];
253         size_t buf_end = (state->buf_start + state->buf_off);
254         size_t buf_fend = (state->buf_start + state->buf_len);
255 
256         if (!state->orig_buf)
257             continue;
258         if (!state->buf_off)
259             continue;
260 
261         // Does the existing buffer cover our section?
262         if ((start >= state->buf_start) &&
263             (start <= buf_end) &&
264             (end >= state->buf_start) &&
265             (end <= buf_end))
266         {
267             char *buf = state->orig_buf + (start - state->buf_start);
268 
269             qemu_iovec_from_buf(acb->qiov, 0, buf, len);
270             acb->common.cb(acb->common.opaque, 0);
271 
272             return FIND_RET_OK;
273         }
274 
275         // Wait for unfinished chunks
276         if (state->in_use &&
277             (start >= state->buf_start) &&
278             (start <= buf_fend) &&
279             (end >= state->buf_start) &&
280             (end <= buf_fend))
281         {
282             int j;
283 
284             acb->start = start - state->buf_start;
285             acb->end = acb->start + len;
286 
287             for (j=0; j<CURL_NUM_ACB; j++) {
288                 if (!state->acb[j]) {
289                     state->acb[j] = acb;
290                     return FIND_RET_WAIT;
291                 }
292             }
293         }
294     }
295 
296     return FIND_RET_NONE;
297 }
298 
299 static void curl_multi_check_completion(BDRVCURLState *s)
300 {
301     int msgs_in_queue;
302 
303     /* Try to find done transfers, so we can free the easy
304      * handle again. */
305     for (;;) {
306         CURLMsg *msg;
307         msg = curl_multi_info_read(s->multi, &msgs_in_queue);
308 
309         /* Quit when there are no more completions */
310         if (!msg)
311             break;
312 
313         if (msg->msg == CURLMSG_DONE) {
314             CURLState *state = NULL;
315             curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE,
316                               (char **)&state);
317 
318             /* ACBs for successful messages get completed in curl_read_cb */
319             if (msg->data.result != CURLE_OK) {
320                 int i;
321                 static int errcount = 100;
322 
323                 /* Don't lose the original error message from curl, since
324                  * it contains extra data.
325                  */
326                 if (errcount > 0) {
327                     error_report("curl: %s", state->errmsg);
328                     if (--errcount == 0) {
329                         error_report("curl: further errors suppressed");
330                     }
331                 }
332 
333                 for (i = 0; i < CURL_NUM_ACB; i++) {
334                     CURLAIOCB *acb = state->acb[i];
335 
336                     if (acb == NULL) {
337                         continue;
338                     }
339 
340                     acb->common.cb(acb->common.opaque, -EPROTO);
341                     qemu_aio_unref(acb);
342                     state->acb[i] = NULL;
343                 }
344             }
345 
346             curl_clean_state(state);
347             break;
348         }
349     }
350 }
351 
352 static void curl_multi_do(void *arg)
353 {
354     CURLState *s = (CURLState *)arg;
355     int running;
356     int r;
357 
358     if (!s->s->multi) {
359         return;
360     }
361 
362     do {
363         r = curl_multi_socket_action(s->s->multi, s->sock_fd, 0, &running);
364     } while(r == CURLM_CALL_MULTI_PERFORM);
365 
366 }
367 
368 static void curl_multi_read(void *arg)
369 {
370     CURLState *s = (CURLState *)arg;
371 
372     curl_multi_do(arg);
373     curl_multi_check_completion(s->s);
374 }
375 
376 static void curl_multi_timeout_do(void *arg)
377 {
378 #ifdef NEED_CURL_TIMER_CALLBACK
379     BDRVCURLState *s = (BDRVCURLState *)arg;
380     int running;
381 
382     if (!s->multi) {
383         return;
384     }
385 
386     curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
387 
388     curl_multi_check_completion(s);
389 #else
390     abort();
391 #endif
392 }
393 
394 static CURLState *curl_init_state(BlockDriverState *bs, BDRVCURLState *s)
395 {
396     CURLState *state = NULL;
397     int i, j;
398 
399     do {
400         for (i=0; i<CURL_NUM_STATES; i++) {
401             for (j=0; j<CURL_NUM_ACB; j++)
402                 if (s->states[i].acb[j])
403                     continue;
404             if (s->states[i].in_use)
405                 continue;
406 
407             state = &s->states[i];
408             state->in_use = 1;
409             break;
410         }
411         if (!state) {
412             aio_poll(bdrv_get_aio_context(bs), true);
413         }
414     } while(!state);
415 
416     if (!state->curl) {
417         state->curl = curl_easy_init();
418         if (!state->curl) {
419             return NULL;
420         }
421         curl_easy_setopt(state->curl, CURLOPT_URL, s->url);
422         curl_easy_setopt(state->curl, CURLOPT_SSL_VERIFYPEER,
423                          (long) s->sslverify);
424         if (s->cookie) {
425             curl_easy_setopt(state->curl, CURLOPT_COOKIE, s->cookie);
426         }
427         curl_easy_setopt(state->curl, CURLOPT_TIMEOUT, (long)s->timeout);
428         curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION,
429                          (void *)curl_read_cb);
430         curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state);
431         curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state);
432         curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1);
433         curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1);
434         curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1);
435         curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg);
436         curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1);
437 
438         if (s->username) {
439             curl_easy_setopt(state->curl, CURLOPT_USERNAME, s->username);
440         }
441         if (s->password) {
442             curl_easy_setopt(state->curl, CURLOPT_PASSWORD, s->password);
443         }
444         if (s->proxyusername) {
445             curl_easy_setopt(state->curl,
446                              CURLOPT_PROXYUSERNAME, s->proxyusername);
447         }
448         if (s->proxypassword) {
449             curl_easy_setopt(state->curl,
450                              CURLOPT_PROXYPASSWORD, s->proxypassword);
451         }
452 
453         /* Restrict supported protocols to avoid security issues in the more
454          * obscure protocols.  For example, do not allow POP3/SMTP/IMAP see
455          * CVE-2013-0249.
456          *
457          * Restricting protocols is only supported from 7.19.4 upwards.
458          */
459 #if LIBCURL_VERSION_NUM >= 0x071304
460         curl_easy_setopt(state->curl, CURLOPT_PROTOCOLS, PROTOCOLS);
461         curl_easy_setopt(state->curl, CURLOPT_REDIR_PROTOCOLS, PROTOCOLS);
462 #endif
463 
464 #ifdef DEBUG_VERBOSE
465         curl_easy_setopt(state->curl, CURLOPT_VERBOSE, 1);
466 #endif
467     }
468 
469     state->s = s;
470 
471     return state;
472 }
473 
474 static void curl_clean_state(CURLState *s)
475 {
476     if (s->s->multi)
477         curl_multi_remove_handle(s->s->multi, s->curl);
478     s->in_use = 0;
479 }
480 
481 static void curl_parse_filename(const char *filename, QDict *options,
482                                 Error **errp)
483 {
484     qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
485 }
486 
487 static void curl_detach_aio_context(BlockDriverState *bs)
488 {
489     BDRVCURLState *s = bs->opaque;
490     int i;
491 
492     for (i = 0; i < CURL_NUM_STATES; i++) {
493         if (s->states[i].in_use) {
494             curl_clean_state(&s->states[i]);
495         }
496         if (s->states[i].curl) {
497             curl_easy_cleanup(s->states[i].curl);
498             s->states[i].curl = NULL;
499         }
500         g_free(s->states[i].orig_buf);
501         s->states[i].orig_buf = NULL;
502     }
503     if (s->multi) {
504         curl_multi_cleanup(s->multi);
505         s->multi = NULL;
506     }
507 
508     timer_del(&s->timer);
509 }
510 
511 static void curl_attach_aio_context(BlockDriverState *bs,
512                                     AioContext *new_context)
513 {
514     BDRVCURLState *s = bs->opaque;
515 
516     aio_timer_init(new_context, &s->timer,
517                    QEMU_CLOCK_REALTIME, SCALE_NS,
518                    curl_multi_timeout_do, s);
519 
520     assert(!s->multi);
521     s->multi = curl_multi_init();
522     s->aio_context = new_context;
523     curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
524 #ifdef NEED_CURL_TIMER_CALLBACK
525     curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
526     curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
527 #endif
528 }
529 
530 static QemuOptsList runtime_opts = {
531     .name = "curl",
532     .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
533     .desc = {
534         {
535             .name = CURL_BLOCK_OPT_URL,
536             .type = QEMU_OPT_STRING,
537             .help = "URL to open",
538         },
539         {
540             .name = CURL_BLOCK_OPT_READAHEAD,
541             .type = QEMU_OPT_SIZE,
542             .help = "Readahead size",
543         },
544         {
545             .name = CURL_BLOCK_OPT_SSLVERIFY,
546             .type = QEMU_OPT_BOOL,
547             .help = "Verify SSL certificate"
548         },
549         {
550             .name = CURL_BLOCK_OPT_TIMEOUT,
551             .type = QEMU_OPT_NUMBER,
552             .help = "Curl timeout"
553         },
554         {
555             .name = CURL_BLOCK_OPT_COOKIE,
556             .type = QEMU_OPT_STRING,
557             .help = "Pass the cookie or list of cookies with each request"
558         },
559         {
560             .name = CURL_BLOCK_OPT_USERNAME,
561             .type = QEMU_OPT_STRING,
562             .help = "Username for HTTP auth"
563         },
564         {
565             .name = CURL_BLOCK_OPT_PASSWORD_SECRET,
566             .type = QEMU_OPT_STRING,
567             .help = "ID of secret used as password for HTTP auth",
568         },
569         {
570             .name = CURL_BLOCK_OPT_PROXY_USERNAME,
571             .type = QEMU_OPT_STRING,
572             .help = "Username for HTTP proxy auth"
573         },
574         {
575             .name = CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET,
576             .type = QEMU_OPT_STRING,
577             .help = "ID of secret used as password for HTTP proxy auth",
578         },
579         { /* end of list */ }
580     },
581 };
582 
583 
584 static int curl_open(BlockDriverState *bs, QDict *options, int flags,
585                      Error **errp)
586 {
587     BDRVCURLState *s = bs->opaque;
588     CURLState *state = NULL;
589     QemuOpts *opts;
590     Error *local_err = NULL;
591     const char *file;
592     const char *cookie;
593     double d;
594     const char *secretid;
595 
596     static int inited = 0;
597 
598     if (flags & BDRV_O_RDWR) {
599         error_setg(errp, "curl block device does not support writes");
600         return -EROFS;
601     }
602 
603     opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
604     qemu_opts_absorb_qdict(opts, options, &local_err);
605     if (local_err) {
606         error_propagate(errp, local_err);
607         goto out_noclean;
608     }
609 
610     s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD,
611                                           READ_AHEAD_DEFAULT);
612     if ((s->readahead_size & 0x1ff) != 0) {
613         error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512",
614                    s->readahead_size);
615         goto out_noclean;
616     }
617 
618     s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT,
619                                      CURL_TIMEOUT_DEFAULT);
620     if (s->timeout > CURL_TIMEOUT_MAX) {
621         error_setg(errp, "timeout parameter is too large or negative");
622         goto out_noclean;
623     }
624 
625     s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true);
626 
627     cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE);
628     s->cookie = g_strdup(cookie);
629 
630     file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL);
631     if (file == NULL) {
632         error_setg(errp, "curl block driver requires an 'url' option");
633         goto out_noclean;
634     }
635 
636     s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME));
637     secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET);
638 
639     if (secretid) {
640         s->password = qcrypto_secret_lookup_as_utf8(secretid, errp);
641         if (!s->password) {
642             goto out_noclean;
643         }
644     }
645 
646     s->proxyusername = g_strdup(
647         qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_USERNAME));
648     secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET);
649     if (secretid) {
650         s->proxypassword = qcrypto_secret_lookup_as_utf8(secretid, errp);
651         if (!s->proxypassword) {
652             goto out_noclean;
653         }
654     }
655 
656     if (!inited) {
657         curl_global_init(CURL_GLOBAL_ALL);
658         inited = 1;
659     }
660 
661     DPRINTF("CURL: Opening %s\n", file);
662     s->aio_context = bdrv_get_aio_context(bs);
663     s->url = g_strdup(file);
664     state = curl_init_state(bs, s);
665     if (!state)
666         goto out_noclean;
667 
668     // Get file size
669 
670     s->accept_range = false;
671     curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1);
672     curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION,
673                      curl_header_cb);
674     curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s);
675     if (curl_easy_perform(state->curl))
676         goto out;
677     if (curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
678         goto out;
679     }
680     /* Prior CURL 7.19.4 return value of 0 could mean that the file size is not
681      * know or the size is zero. From 7.19.4 CURL returns -1 if size is not
682      * known and zero if it is realy zero-length file. */
683 #if LIBCURL_VERSION_NUM >= 0x071304
684     if (d < 0) {
685         pstrcpy(state->errmsg, CURL_ERROR_SIZE,
686                 "Server didn't report file size.");
687         goto out;
688     }
689 #else
690     if (d <= 0) {
691         pstrcpy(state->errmsg, CURL_ERROR_SIZE,
692                 "Unknown file size or zero-length file.");
693         goto out;
694     }
695 #endif
696 
697     s->len = (size_t)d;
698 
699     if ((!strncasecmp(s->url, "http://", strlen("http://"))
700         || !strncasecmp(s->url, "https://", strlen("https://")))
701         && !s->accept_range) {
702         pstrcpy(state->errmsg, CURL_ERROR_SIZE,
703                 "Server does not support 'range' (byte ranges).");
704         goto out;
705     }
706     DPRINTF("CURL: Size = %zd\n", s->len);
707 
708     curl_clean_state(state);
709     curl_easy_cleanup(state->curl);
710     state->curl = NULL;
711 
712     curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
713 
714     qemu_opts_del(opts);
715     return 0;
716 
717 out:
718     error_setg(errp, "CURL: Error opening file: %s", state->errmsg);
719     curl_easy_cleanup(state->curl);
720     state->curl = NULL;
721 out_noclean:
722     g_free(s->cookie);
723     g_free(s->url);
724     qemu_opts_del(opts);
725     return -EINVAL;
726 }
727 
728 static const AIOCBInfo curl_aiocb_info = {
729     .aiocb_size         = sizeof(CURLAIOCB),
730 };
731 
732 
733 static void curl_readv_bh_cb(void *p)
734 {
735     CURLState *state;
736     int running;
737 
738     CURLAIOCB *acb = p;
739     BDRVCURLState *s = acb->common.bs->opaque;
740 
741     size_t start = acb->sector_num * SECTOR_SIZE;
742     size_t end;
743 
744     // In case we have the requested data already (e.g. read-ahead),
745     // we can just call the callback and be done.
746     switch (curl_find_buf(s, start, acb->nb_sectors * SECTOR_SIZE, acb)) {
747         case FIND_RET_OK:
748             qemu_aio_unref(acb);
749             // fall through
750         case FIND_RET_WAIT:
751             return;
752         default:
753             break;
754     }
755 
756     // No cache found, so let's start a new request
757     state = curl_init_state(acb->common.bs, s);
758     if (!state) {
759         acb->common.cb(acb->common.opaque, -EIO);
760         qemu_aio_unref(acb);
761         return;
762     }
763 
764     acb->start = 0;
765     acb->end = (acb->nb_sectors * SECTOR_SIZE);
766 
767     state->buf_off = 0;
768     g_free(state->orig_buf);
769     state->buf_start = start;
770     state->buf_len = acb->end + s->readahead_size;
771     end = MIN(start + state->buf_len, s->len) - 1;
772     state->orig_buf = g_try_malloc(state->buf_len);
773     if (state->buf_len && state->orig_buf == NULL) {
774         curl_clean_state(state);
775         acb->common.cb(acb->common.opaque, -ENOMEM);
776         qemu_aio_unref(acb);
777         return;
778     }
779     state->acb[0] = acb;
780 
781     snprintf(state->range, 127, "%zd-%zd", start, end);
782     DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n",
783             (acb->nb_sectors * SECTOR_SIZE), start, state->range);
784     curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
785 
786     curl_multi_add_handle(s->multi, state->curl);
787 
788     /* Tell curl it needs to kick things off */
789     curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
790 }
791 
792 static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
793         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
794         BlockCompletionFunc *cb, void *opaque)
795 {
796     CURLAIOCB *acb;
797 
798     acb = qemu_aio_get(&curl_aiocb_info, bs, cb, opaque);
799 
800     acb->qiov = qiov;
801     acb->sector_num = sector_num;
802     acb->nb_sectors = nb_sectors;
803 
804     aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
805     return &acb->common;
806 }
807 
808 static void curl_close(BlockDriverState *bs)
809 {
810     BDRVCURLState *s = bs->opaque;
811 
812     DPRINTF("CURL: Close\n");
813     curl_detach_aio_context(bs);
814 
815     g_free(s->cookie);
816     g_free(s->url);
817 }
818 
819 static int64_t curl_getlength(BlockDriverState *bs)
820 {
821     BDRVCURLState *s = bs->opaque;
822     return s->len;
823 }
824 
825 static BlockDriver bdrv_http = {
826     .format_name                = "http",
827     .protocol_name              = "http",
828 
829     .instance_size              = sizeof(BDRVCURLState),
830     .bdrv_parse_filename        = curl_parse_filename,
831     .bdrv_file_open             = curl_open,
832     .bdrv_close                 = curl_close,
833     .bdrv_getlength             = curl_getlength,
834 
835     .bdrv_aio_readv             = curl_aio_readv,
836 
837     .bdrv_detach_aio_context    = curl_detach_aio_context,
838     .bdrv_attach_aio_context    = curl_attach_aio_context,
839 };
840 
841 static BlockDriver bdrv_https = {
842     .format_name                = "https",
843     .protocol_name              = "https",
844 
845     .instance_size              = sizeof(BDRVCURLState),
846     .bdrv_parse_filename        = curl_parse_filename,
847     .bdrv_file_open             = curl_open,
848     .bdrv_close                 = curl_close,
849     .bdrv_getlength             = curl_getlength,
850 
851     .bdrv_aio_readv             = curl_aio_readv,
852 
853     .bdrv_detach_aio_context    = curl_detach_aio_context,
854     .bdrv_attach_aio_context    = curl_attach_aio_context,
855 };
856 
857 static BlockDriver bdrv_ftp = {
858     .format_name                = "ftp",
859     .protocol_name              = "ftp",
860 
861     .instance_size              = sizeof(BDRVCURLState),
862     .bdrv_parse_filename        = curl_parse_filename,
863     .bdrv_file_open             = curl_open,
864     .bdrv_close                 = curl_close,
865     .bdrv_getlength             = curl_getlength,
866 
867     .bdrv_aio_readv             = curl_aio_readv,
868 
869     .bdrv_detach_aio_context    = curl_detach_aio_context,
870     .bdrv_attach_aio_context    = curl_attach_aio_context,
871 };
872 
873 static BlockDriver bdrv_ftps = {
874     .format_name                = "ftps",
875     .protocol_name              = "ftps",
876 
877     .instance_size              = sizeof(BDRVCURLState),
878     .bdrv_parse_filename        = curl_parse_filename,
879     .bdrv_file_open             = curl_open,
880     .bdrv_close                 = curl_close,
881     .bdrv_getlength             = curl_getlength,
882 
883     .bdrv_aio_readv             = curl_aio_readv,
884 
885     .bdrv_detach_aio_context    = curl_detach_aio_context,
886     .bdrv_attach_aio_context    = curl_attach_aio_context,
887 };
888 
889 static BlockDriver bdrv_tftp = {
890     .format_name                = "tftp",
891     .protocol_name              = "tftp",
892 
893     .instance_size              = sizeof(BDRVCURLState),
894     .bdrv_parse_filename        = curl_parse_filename,
895     .bdrv_file_open             = curl_open,
896     .bdrv_close                 = curl_close,
897     .bdrv_getlength             = curl_getlength,
898 
899     .bdrv_aio_readv             = curl_aio_readv,
900 
901     .bdrv_detach_aio_context    = curl_detach_aio_context,
902     .bdrv_attach_aio_context    = curl_attach_aio_context,
903 };
904 
905 static void curl_block_init(void)
906 {
907     bdrv_register(&bdrv_http);
908     bdrv_register(&bdrv_https);
909     bdrv_register(&bdrv_ftp);
910     bdrv_register(&bdrv_ftps);
911     bdrv_register(&bdrv_tftp);
912 }
913 
914 block_init(curl_block_init);
915