Annotation of qemu/block.c, revision 1.1.1.4
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.1.3 root 47: #ifdef __sun__
48: #include <sys/dkio.h>
49: #endif
50:
1.1 root 51: static BlockDriverState *bdrv_first;
52: static BlockDriver *first_drv;
53:
1.1.1.2 root 54: #ifdef CONFIG_COCOA
55: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
56: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
57:
58: kern_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:
84: kern_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:
1.1 root 112: void 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) */
119: BlockDriverState *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:
137: BlockDriver *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:
147: int 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
1.1.1.2 root 157: void get_tmp_filename(char *filename, int size)
1.1 root 158: {
1.1.1.2 root 159: char* p = strrchr(filename, '/');
160:
161: if (p == NULL)
162: return;
163:
1.1 root 164: /* XXX: find a better function */
1.1.1.2 root 165: tmpnam(p);
166: *p = '/';
1.1 root 167: }
168: #else
1.1.1.2 root 169: void get_tmp_filename(char *filename, int size)
1.1 root 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 */
181: static 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
1.1.1.2 root 201: #ifdef CONFIG_COCOA
202: u_int32_t blockSize = 512;
203: if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
204: bufsize = blockSize;
205: }
206: #endif
1.1 root 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:
232: int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
233: {
1.1.1.2 root 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
1.1 root 260: return bdrv_open2(bs, filename, snapshot, NULL);
261: }
262:
263: int 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:
344: void 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:
366: void 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 */
374: int 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: }
1.1.1.2 root 407:
408: if (bs->drv->bdrv_make_empty)
409: return bs->drv->bdrv_make_empty(bs);
410:
1.1 root 411: return 0;
412: }
413:
414: /* return -1 if error */
415: int 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 */
454: int 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;
1.1.1.2 root 461: if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
462: memcpy(bs->boot_sector_data, buf, 512);
463: }
1.1 root 464: return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
465: }
466:
467: void 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. */
473: void 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:
482: void 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:
490: void 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:
497: void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
498: {
499: bs->translation = translation;
500: }
501:
502: void 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:
510: int bdrv_get_type_hint(BlockDriverState *bs)
511: {
512: return bs->type;
513: }
514:
515: int bdrv_get_translation_hint(BlockDriverState *bs)
516: {
517: return bs->translation;
518: }
519:
520: int bdrv_is_removable(BlockDriverState *bs)
521: {
522: return bs->removable;
523: }
524:
525: int bdrv_is_read_only(BlockDriverState *bs)
526: {
527: return bs->read_only;
528: }
529:
530: int bdrv_is_inserted(BlockDriverState *bs)
531: {
532: return bs->inserted;
533: }
534:
535: int bdrv_is_locked(BlockDriverState *bs)
536: {
537: return bs->locked;
538: }
539:
540: void bdrv_set_locked(BlockDriverState *bs, int locked)
541: {
542: bs->locked = locked;
543: }
544:
545: void 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:
552: int bdrv_is_encrypted(BlockDriverState *bs)
553: {
554: if (bs->backing_hd && bs->backing_hd->encrypted)
555: return 1;
556: return bs->encrypted;
557: }
558:
559: int 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:
574: void 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:
583: void 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:
593: BlockDriverState *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:
604: void 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:
613: const char *bdrv_get_device_name(BlockDriverState *bs)
614: {
615: return bs->device_name;
616: }
617:
1.1.1.4 ! root 618: void 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:
1.1 root 626: void 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:
666: typedef struct BDRVRawState {
667: int fd;
668: } BDRVRawState;
669:
670: static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
671: {
672: return 1; /* maybe */
673: }
674:
675: static 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
1.1.1.3 root 683: #ifdef __sun__
684: struct dk_minfo minfo;
685: int rv;
686: #endif
1.1 root 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
1.1.1.2 root 700: #ifdef CONFIG_COCOA
701: size = LONG_LONG_MAX;
702: #else
703: size = lseek(fd, 0LL, SEEK_END);
704: #endif
1.1 root 705: } else
706: #endif
1.1.1.3 root 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
1.1 root 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:
732: static 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:
745: static 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:
758: static void raw_close(BlockDriverState *bs)
759: {
760: BDRVRawState *s = bs->opaque;
761: close(s->fd);
762: }
763:
1.1.1.4 ! root 764: #ifdef _WIN32
! 765: #include <windows.h>
! 766: #include <winioctl.h>
! 767:
! 768: int 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:
! 796: static 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
! 803: static inline int set_sparse(int fd)
! 804: {
! 805: return 1;
! 806: }
! 807: #endif
! 808:
1.1 root 809: static 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;
1.1.1.4 ! root 821: set_sparse(fd);
1.1 root 822: ftruncate(fd, total_size * 512);
823: close(fd);
824: return 0;
825: }
826:
1.1.1.4 ! root 827: static void raw_flush(BlockDriverState *bs)
! 828: {
! 829: BDRVRawState *s = bs->opaque;
! 830: fsync(s->fd);
! 831: }
! 832:
1.1 root 833: BlockDriver 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,
1.1.1.4 ! root 842: raw_flush,
1.1 root 843: };
844:
845: void bdrv_init(void)
846: {
847: bdrv_register(&bdrv_raw);
848: #ifndef _WIN32
849: bdrv_register(&bdrv_cow);
850: #endif
851: bdrv_register(&bdrv_qcow);
852: bdrv_register(&bdrv_vmdk);
853: bdrv_register(&bdrv_cloop);
854: bdrv_register(&bdrv_dmg);
855: bdrv_register(&bdrv_bochs);
856: bdrv_register(&bdrv_vpc);
857: bdrv_register(&bdrv_vvfat);
858: }
unix.superglobalmegacorp.com