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