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