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