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