block.c revision 55f4e4a5ec657a017e3bf75299ad71fd1c968dd3
1/* 2 * QEMU System Emulator block driver 3 * 4 * Copyright (c) 2003 Fabrice Bellard 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 "vl.h" 25#include "block_int.h" 26 27#ifdef _BSD 28#include <sys/types.h> 29#include <sys/stat.h> 30#include <sys/ioctl.h> 31#include <sys/queue.h> 32#include <sys/disk.h> 33#endif 34 35#ifdef CONFIG_COCOA 36#include <paths.h> 37#include <sys/param.h> 38#include <IOKit/IOKitLib.h> 39#include <IOKit/IOBSD.h> 40#include <IOKit/storage/IOMediaBSDClient.h> 41#include <IOKit/storage/IOMedia.h> 42#include <IOKit/storage/IOCDMedia.h> 43//#include <IOKit/storage/IOCDTypes.h> 44#include <CoreFoundation/CoreFoundation.h> 45#endif 46 47#ifdef __sun__ 48#include <sys/dkio.h> 49#endif 50 51static BlockDriverState *bdrv_first; 52static BlockDriver *first_drv; 53 54#ifdef CONFIG_COCOA 55static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ); 56static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ); 57 58kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ) 59{ 60 kern_return_t kernResult; 61 mach_port_t masterPort; 62 CFMutableDictionaryRef classesToMatch; 63 64 kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); 65 if ( KERN_SUCCESS != kernResult ) { 66 printf( "IOMasterPort returned %d\n", kernResult ); 67 } 68 69 classesToMatch = IOServiceMatching( kIOCDMediaClass ); 70 if ( classesToMatch == NULL ) { 71 printf( "IOServiceMatching returned a NULL dictionary.\n" ); 72 } else { 73 CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); 74 } 75 kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator ); 76 if ( KERN_SUCCESS != kernResult ) 77 { 78 printf( "IOServiceGetMatchingServices returned %d\n", kernResult ); 79 } 80 81 return kernResult; 82} 83 84kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ) 85{ 86 io_object_t nextMedia; 87 kern_return_t kernResult = KERN_FAILURE; 88 *bsdPath = '\0'; 89 nextMedia = IOIteratorNext( mediaIterator ); 90 if ( nextMedia ) 91 { 92 CFTypeRef bsdPathAsCFString; 93 bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); 94 if ( bsdPathAsCFString ) { 95 size_t devPathLength; 96 strcpy( bsdPath, _PATH_DEV ); 97 strcat( bsdPath, "r" ); 98 devPathLength = strlen( bsdPath ); 99 if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { 100 kernResult = KERN_SUCCESS; 101 } 102 CFRelease( bsdPathAsCFString ); 103 } 104 IOObjectRelease( nextMedia ); 105 } 106 107 return kernResult; 108} 109 110#endif 111 112void bdrv_register(BlockDriver *bdrv) 113{ 114 bdrv->next = first_drv; 115 first_drv = bdrv; 116} 117 118/* create a new block device (by default it is empty) */ 119BlockDriverState *bdrv_new(const char *device_name) 120{ 121 BlockDriverState **pbs, *bs; 122 123 bs = qemu_mallocz(sizeof(BlockDriverState)); 124 if(!bs) 125 return NULL; 126 pstrcpy(bs->device_name, sizeof(bs->device_name), device_name); 127 if (device_name[0] != '\0') { 128 /* insert at the end */ 129 pbs = &bdrv_first; 130 while (*pbs != NULL) 131 pbs = &(*pbs)->next; 132 *pbs = bs; 133 } 134 return bs; 135} 136 137BlockDriver *bdrv_find_format(const char *format_name) 138{ 139 BlockDriver *drv1; 140 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { 141 if (!strcmp(drv1->format_name, format_name)) 142 return drv1; 143 } 144 return NULL; 145} 146 147int bdrv_create(BlockDriver *drv, 148 const char *filename, int64_t size_in_sectors, 149 const char *backing_file, int flags) 150{ 151 if (!drv->bdrv_create) 152 return -ENOTSUP; 153 return drv->bdrv_create(filename, size_in_sectors, backing_file, flags); 154} 155 156#ifdef _WIN32 157void get_tmp_filename(char *filename, int size) 158{ 159 char* p = strrchr(filename, '/'); 160 161 if (p == NULL) 162 return; 163 164 /* XXX: find a better function */ 165 tmpnam(p); 166 *p = '/'; 167} 168#else 169void get_tmp_filename(char *filename, int size) 170{ 171 int fd; 172 /* XXX: race condition possible */ 173 pstrcpy(filename, size, "/tmp/vl.XXXXXX"); 174 fd = mkstemp(filename); 175 close(fd); 176} 177#endif 178 179/* XXX: force raw format if block or character device ? It would 180 simplify the BSD case */ 181static BlockDriver *find_image_format(const char *filename) 182{ 183 int fd, ret, score, score_max; 184 BlockDriver *drv1, *drv; 185 uint8_t *buf; 186 size_t bufsize = 1024; 187 188 fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); 189 if (fd < 0) { 190 buf = NULL; 191 ret = 0; 192 } else { 193#ifdef DIOCGSECTORSIZE 194 { 195 unsigned int sectorsize = 512; 196 if (!ioctl(fd, DIOCGSECTORSIZE, §orsize) && 197 sectorsize > bufsize) 198 bufsize = sectorsize; 199 } 200#endif 201#ifdef CONFIG_COCOA 202 u_int32_t blockSize = 512; 203 if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) { 204 bufsize = blockSize; 205 } 206#endif 207 buf = qemu_malloc(bufsize); 208 if (!buf) 209 return NULL; 210 ret = read(fd, buf, bufsize); 211 if (ret < 0) { 212 close(fd); 213 qemu_free(buf); 214 return NULL; 215 } 216 close(fd); 217 } 218 219 drv = NULL; 220 score_max = 0; 221 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { 222 score = drv1->bdrv_probe(buf, ret, filename); 223 if (score > score_max) { 224 score_max = score; 225 drv = drv1; 226 } 227 } 228 qemu_free(buf); 229 return drv; 230} 231 232int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot) 233{ 234#ifdef CONFIG_COCOA 235 if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) { 236 kern_return_t kernResult; 237 io_iterator_t mediaIterator; 238 char bsdPath[ MAXPATHLEN ]; 239 int fd; 240 241 kernResult = FindEjectableCDMedia( &mediaIterator ); 242 kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) ); 243 244 if ( bsdPath[ 0 ] != '\0' ) { 245 strcat(bsdPath,"s0"); 246 /* some CDs don't have a partition 0 */ 247 fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); 248 if (fd < 0) { 249 bsdPath[strlen(bsdPath)-1] = '1'; 250 } else { 251 close(fd); 252 } 253 filename = bsdPath; 254 } 255 256 if ( mediaIterator ) 257 IOObjectRelease( mediaIterator ); 258 } 259#endif 260 return bdrv_open2(bs, filename, snapshot, NULL); 261} 262 263int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, 264 BlockDriver *drv) 265{ 266 int ret; 267 char tmp_filename[1024]; 268 269 bs->read_only = 0; 270 bs->is_temporary = 0; 271 bs->encrypted = 0; 272 273 if (snapshot) { 274 BlockDriverState *bs1; 275 int64_t total_size; 276 277 /* if snapshot, we create a temporary backing file and open it 278 instead of opening 'filename' directly */ 279 280 /* if there is a backing file, use it */ 281 bs1 = bdrv_new(""); 282 if (!bs1) { 283 return -1; 284 } 285 if (bdrv_open(bs1, filename, 0) < 0) { 286 bdrv_delete(bs1); 287 return -1; 288 } 289 total_size = bs1->total_sectors; 290 bdrv_delete(bs1); 291 292 get_tmp_filename(tmp_filename, sizeof(tmp_filename)); 293 /* XXX: use cow for linux as it is more efficient ? */ 294 if (bdrv_create(&bdrv_qcow, tmp_filename, 295 total_size, filename, 0) < 0) { 296 return -1; 297 } 298 filename = tmp_filename; 299 bs->is_temporary = 1; 300 } 301 302 pstrcpy(bs->filename, sizeof(bs->filename), filename); 303 if (!drv) { 304 drv = find_image_format(filename); 305 if (!drv) 306 return -1; 307 } 308 bs->drv = drv; 309 bs->opaque = qemu_mallocz(drv->instance_size); 310 if (bs->opaque == NULL && drv->instance_size > 0) 311 return -1; 312 313 ret = drv->bdrv_open(bs, filename); 314 if (ret < 0) { 315 qemu_free(bs->opaque); 316 return -1; 317 } 318#ifndef _WIN32 319 if (bs->is_temporary) { 320 unlink(filename); 321 } 322#endif 323 if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) { 324 /* if there is a backing file, use it */ 325 bs->backing_hd = bdrv_new(""); 326 if (!bs->backing_hd) { 327 fail: 328 bdrv_close(bs); 329 return -1; 330 } 331 if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0) 332 goto fail; 333 } 334 335 bs->inserted = 1; 336 337 /* call the change callback */ 338 if (bs->change_cb) 339 bs->change_cb(bs->change_opaque); 340 341 return 0; 342} 343 344void bdrv_close(BlockDriverState *bs) 345{ 346 if (bs->inserted) { 347 if (bs->backing_hd) 348 bdrv_delete(bs->backing_hd); 349 bs->drv->bdrv_close(bs); 350 qemu_free(bs->opaque); 351#ifdef _WIN32 352 if (bs->is_temporary) { 353 unlink(bs->filename); 354 } 355#endif 356 bs->opaque = NULL; 357 bs->drv = NULL; 358 bs->inserted = 0; 359 360 /* call the change callback */ 361 if (bs->change_cb) 362 bs->change_cb(bs->change_opaque); 363 } 364} 365 366void bdrv_delete(BlockDriverState *bs) 367{ 368 /* XXX: remove the driver list */ 369 bdrv_close(bs); 370 qemu_free(bs); 371} 372 373/* commit COW file into the raw image */ 374int bdrv_commit(BlockDriverState *bs) 375{ 376 int64_t i; 377 int n, j; 378 unsigned char sector[512]; 379 380 if (!bs->inserted) 381 return -ENOENT; 382 383 if (bs->read_only) { 384 return -EACCES; 385 } 386 387 if (!bs->backing_hd) { 388 return -ENOTSUP; 389 } 390 391 for (i = 0; i < bs->total_sectors;) { 392 if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) { 393 for(j = 0; j < n; j++) { 394 if (bdrv_read(bs, i, sector, 1) != 0) { 395 return -EIO; 396 } 397 398 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) { 399 return -EIO; 400 } 401 i++; 402 } 403 } else { 404 i += n; 405 } 406 } 407 408 if (bs->drv->bdrv_make_empty) 409 return bs->drv->bdrv_make_empty(bs); 410 411 return 0; 412} 413 414/* return -1 if error */ 415int bdrv_read(BlockDriverState *bs, int64_t sector_num, 416 uint8_t *buf, int nb_sectors) 417{ 418 int ret, n; 419 BlockDriver *drv = bs->drv; 420 421 if (!bs->inserted) 422 return -1; 423 424 while (nb_sectors > 0) { 425 if (sector_num == 0 && bs->boot_sector_enabled) { 426 memcpy(buf, bs->boot_sector_data, 512); 427 n = 1; 428 } else if (bs->backing_hd) { 429 if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) { 430 ret = drv->bdrv_read(bs, sector_num, buf, n); 431 if (ret < 0) 432 return -1; 433 } else { 434 /* read from the base image */ 435 ret = bdrv_read(bs->backing_hd, sector_num, buf, n); 436 if (ret < 0) 437 return -1; 438 } 439 } else { 440 ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors); 441 if (ret < 0) 442 return -1; 443 /* no need to loop */ 444 break; 445 } 446 nb_sectors -= n; 447 sector_num += n; 448 buf += n * 512; 449 } 450 return 0; 451} 452 453/* return -1 if error */ 454int bdrv_write(BlockDriverState *bs, int64_t sector_num, 455 const uint8_t *buf, int nb_sectors) 456{ 457 if (!bs->inserted) 458 return -1; 459 if (bs->read_only) 460 return -1; 461 if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) { 462 memcpy(bs->boot_sector_data, buf, 512); 463 } 464 return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors); 465} 466 467void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr) 468{ 469 *nb_sectors_ptr = bs->total_sectors; 470} 471 472/* force a given boot sector. */ 473void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size) 474{ 475 bs->boot_sector_enabled = 1; 476 if (size > 512) 477 size = 512; 478 memcpy(bs->boot_sector_data, data, size); 479 memset(bs->boot_sector_data + size, 0, 512 - size); 480} 481 482void bdrv_set_geometry_hint(BlockDriverState *bs, 483 int cyls, int heads, int secs) 484{ 485 bs->cyls = cyls; 486 bs->heads = heads; 487 bs->secs = secs; 488} 489 490void bdrv_set_type_hint(BlockDriverState *bs, int type) 491{ 492 bs->type = type; 493 bs->removable = ((type == BDRV_TYPE_CDROM || 494 type == BDRV_TYPE_FLOPPY)); 495} 496 497void bdrv_set_translation_hint(BlockDriverState *bs, int translation) 498{ 499 bs->translation = translation; 500} 501 502void bdrv_get_geometry_hint(BlockDriverState *bs, 503 int *pcyls, int *pheads, int *psecs) 504{ 505 *pcyls = bs->cyls; 506 *pheads = bs->heads; 507 *psecs = bs->secs; 508} 509 510int bdrv_get_type_hint(BlockDriverState *bs) 511{ 512 return bs->type; 513} 514 515int bdrv_get_translation_hint(BlockDriverState *bs) 516{ 517 return bs->translation; 518} 519 520int bdrv_is_removable(BlockDriverState *bs) 521{ 522 return bs->removable; 523} 524 525int bdrv_is_read_only(BlockDriverState *bs) 526{ 527 return bs->read_only; 528} 529 530int bdrv_is_inserted(BlockDriverState *bs) 531{ 532 return bs->inserted; 533} 534 535int bdrv_is_locked(BlockDriverState *bs) 536{ 537 return bs->locked; 538} 539 540void bdrv_set_locked(BlockDriverState *bs, int locked) 541{ 542 bs->locked = locked; 543} 544 545void bdrv_set_change_cb(BlockDriverState *bs, 546 void (*change_cb)(void *opaque), void *opaque) 547{ 548 bs->change_cb = change_cb; 549 bs->change_opaque = opaque; 550} 551 552int bdrv_is_encrypted(BlockDriverState *bs) 553{ 554 if (bs->backing_hd && bs->backing_hd->encrypted) 555 return 1; 556 return bs->encrypted; 557} 558 559int bdrv_set_key(BlockDriverState *bs, const char *key) 560{ 561 int ret; 562 if (bs->backing_hd && bs->backing_hd->encrypted) { 563 ret = bdrv_set_key(bs->backing_hd, key); 564 if (ret < 0) 565 return ret; 566 if (!bs->encrypted) 567 return 0; 568 } 569 if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) 570 return -1; 571 return bs->drv->bdrv_set_key(bs, key); 572} 573 574void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size) 575{ 576 if (!bs->inserted || !bs->drv) { 577 buf[0] = '\0'; 578 } else { 579 pstrcpy(buf, buf_size, bs->drv->format_name); 580 } 581} 582 583void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 584 void *opaque) 585{ 586 BlockDriver *drv; 587 588 for (drv = first_drv; drv != NULL; drv = drv->next) { 589 it(opaque, drv->format_name); 590 } 591} 592 593BlockDriverState *bdrv_find(const char *name) 594{ 595 BlockDriverState *bs; 596 597 for (bs = bdrv_first; bs != NULL; bs = bs->next) { 598 if (!strcmp(name, bs->device_name)) 599 return bs; 600 } 601 return NULL; 602} 603 604void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque) 605{ 606 BlockDriverState *bs; 607 608 for (bs = bdrv_first; bs != NULL; bs = bs->next) { 609 it(opaque, bs->device_name); 610 } 611} 612 613const char *bdrv_get_device_name(BlockDriverState *bs) 614{ 615 return bs->device_name; 616} 617 618void bdrv_flush(BlockDriverState *bs) 619{ 620 if (bs->drv->bdrv_flush) 621 bs->drv->bdrv_flush(bs); 622 if (bs->backing_hd) 623 bdrv_flush(bs->backing_hd); 624} 625 626void bdrv_info(void) 627{ 628 BlockDriverState *bs; 629 630 for (bs = bdrv_first; bs != NULL; bs = bs->next) { 631 term_printf("%s:", bs->device_name); 632 term_printf(" type="); 633 switch(bs->type) { 634 case BDRV_TYPE_HD: 635 term_printf("hd"); 636 break; 637 case BDRV_TYPE_CDROM: 638 term_printf("cdrom"); 639 break; 640 case BDRV_TYPE_FLOPPY: 641 term_printf("floppy"); 642 break; 643 } 644 term_printf(" removable=%d", bs->removable); 645 if (bs->removable) { 646 term_printf(" locked=%d", bs->locked); 647 } 648 if (bs->inserted) { 649 term_printf(" file=%s", bs->filename); 650 if (bs->backing_file[0] != '\0') 651 term_printf(" backing_file=%s", bs->backing_file); 652 term_printf(" ro=%d", bs->read_only); 653 term_printf(" drv=%s", bs->drv->format_name); 654 if (bs->encrypted) 655 term_printf(" encrypted"); 656 } else { 657 term_printf(" [not inserted]"); 658 } 659 term_printf("\n"); 660 } 661} 662 663/**************************************************************/ 664/* RAW block driver */ 665 666typedef struct BDRVRawState { 667 int fd; 668} BDRVRawState; 669 670static int raw_probe(const uint8_t *buf, int buf_size, const char *filename) 671{ 672 return 1; /* maybe */ 673} 674 675static int raw_open(BlockDriverState *bs, const char *filename) 676{ 677 BDRVRawState *s = bs->opaque; 678 int fd; 679 int64_t size; 680#ifdef _BSD 681 struct stat sb; 682#endif 683#ifdef __sun__ 684 struct dk_minfo minfo; 685 int rv; 686#endif 687 688 fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); 689 if (fd < 0) { 690 fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); 691 if (fd < 0) 692 return -1; 693 bs->read_only = 1; 694 } 695#ifdef _BSD 696 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { 697#ifdef DIOCGMEDIASIZE 698 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) 699#endif 700#ifdef CONFIG_COCOA 701 size = LONG_LONG_MAX; 702#else 703 size = lseek(fd, 0LL, SEEK_END); 704#endif 705 } else 706#endif 707#ifdef __sun__ 708 /* 709 * use the DKIOCGMEDIAINFO ioctl to read the size. 710 */ 711 rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo ); 712 if ( rv != -1 ) { 713 size = minfo.dki_lbsize * minfo.dki_capacity; 714 } else /* there are reports that lseek on some devices 715 fails, but irc discussion said that contingency 716 on contingency was overkill */ 717#endif 718 { 719 size = lseek(fd, 0, SEEK_END); 720 } 721#ifdef _WIN32 722 /* On Windows hosts it can happen that we're unable to get file size 723 for CD-ROM raw device (it's inherent limitation of the CDFS driver). */ 724 if (size == -1) 725 size = LONG_LONG_MAX; 726#endif 727 bs->total_sectors = size / 512; 728 s->fd = fd; 729 return 0; 730} 731 732static int raw_read(BlockDriverState *bs, int64_t sector_num, 733 uint8_t *buf, int nb_sectors) 734{ 735 BDRVRawState *s = bs->opaque; 736 int ret; 737 738 lseek(s->fd, sector_num * 512, SEEK_SET); 739 ret = read(s->fd, buf, nb_sectors * 512); 740 if (ret != nb_sectors * 512) 741 return -1; 742 return 0; 743} 744 745static int raw_write(BlockDriverState *bs, int64_t sector_num, 746 const uint8_t *buf, int nb_sectors) 747{ 748 BDRVRawState *s = bs->opaque; 749 int ret; 750 751 lseek(s->fd, sector_num * 512, SEEK_SET); 752 ret = write(s->fd, buf, nb_sectors * 512); 753 if (ret != nb_sectors * 512) 754 return -1; 755 return 0; 756} 757 758static void raw_close(BlockDriverState *bs) 759{ 760 BDRVRawState *s = bs->opaque; 761 close(s->fd); 762} 763 764#ifdef _WIN32 765#include <windows.h> 766#include <winioctl.h> 767 768int qemu_ftruncate64(int fd, int64_t length) 769{ 770 LARGE_INTEGER li; 771 LONG high; 772 HANDLE h; 773 BOOL res; 774 775 if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) 776 return -1; 777 778 h = (HANDLE)_get_osfhandle(fd); 779 780 /* get current position, ftruncate do not change position */ 781 li.HighPart = 0; 782 li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT); 783 if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) 784 return -1; 785 786 high = length >> 32; 787 if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN)) 788 return -1; 789 res = SetEndOfFile(h); 790 791 /* back to old position */ 792 SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN); 793 return res ? 0 : -1; 794} 795 796static int set_sparse(int fd) 797{ 798 DWORD returned; 799 return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, 800 NULL, 0, NULL, 0, &returned, NULL); 801} 802#else 803static inline int set_sparse(int fd) 804{ 805 return 1; 806} 807#endif 808 809static int raw_create(const char *filename, int64_t total_size, 810 const char *backing_file, int flags) 811{ 812 int fd; 813 814 if (flags || backing_file) 815 return -ENOTSUP; 816 817 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 818 0644); 819 if (fd < 0) 820 return -EIO; 821 set_sparse(fd); 822 ftruncate(fd, total_size * 512); 823 close(fd); 824 return 0; 825} 826 827static void raw_flush(BlockDriverState *bs) 828{ 829 BDRVRawState *s = bs->opaque; 830 fsync(s->fd); 831} 832 833BlockDriver bdrv_raw = { 834 "raw", 835 sizeof(BDRVRawState), 836 raw_probe, 837 raw_open, 838 raw_read, 839 raw_write, 840 raw_close, 841 raw_create, 842 raw_flush, 843}; 844 845void bdrv_init(void) 846{ 847 bdrv_register(&bdrv_raw); 848 bdrv_register(&bdrv_cloop); 849 bdrv_register(&bdrv_qcow); 850 bdrv_register(&bdrv_dmg); 851} 852