📄 block-raw.c
字号:
int fd; if (flags || backing_file) return -ENOTSUP; fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd < 0) return -EIO; ftruncate(fd, total_size * 512); close(fd); return 0;}static void raw_flush(BlockDriverState *bs){ BDRVRawState *s = bs->opaque; fsync(s->fd);}BlockDriver bdrv_raw = { "raw", sizeof(BDRVRawState), NULL, /* no probe for protocols */ raw_open, NULL, NULL, raw_close, raw_create, raw_flush, .bdrv_aio_read = raw_aio_read, .bdrv_aio_write = raw_aio_write, .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), .protocol_name = "file", .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, .bdrv_truncate = raw_truncate, .bdrv_getlength = raw_getlength,};/***********************************************//* host device */#ifdef CONFIG_COCOAstatic kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator ){ kern_return_t kernResult; mach_port_t masterPort; CFMutableDictionaryRef classesToMatch; kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort ); if ( KERN_SUCCESS != kernResult ) { printf( "IOMasterPort returned %d\n", kernResult ); } classesToMatch = IOServiceMatching( kIOCDMediaClass ); if ( classesToMatch == NULL ) { printf( "IOServiceMatching returned a NULL dictionary.\n" ); } else { CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); } kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator ); if ( KERN_SUCCESS != kernResult ) { printf( "IOServiceGetMatchingServices returned %d\n", kernResult ); } return kernResult;}kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize ){ io_object_t nextMedia; kern_return_t kernResult = KERN_FAILURE; *bsdPath = '\0'; nextMedia = IOIteratorNext( mediaIterator ); if ( nextMedia ) { CFTypeRef bsdPathAsCFString; bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); if ( bsdPathAsCFString ) { size_t devPathLength; strcpy( bsdPath, _PATH_DEV ); strcat( bsdPath, "r" ); devPathLength = strlen( bsdPath ); if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) { kernResult = KERN_SUCCESS; } CFRelease( bsdPathAsCFString ); } IOObjectRelease( nextMedia ); } return kernResult;}#endifstatic int hdev_open(BlockDriverState *bs, const char *filename, int flags){ BDRVRawState *s = bs->opaque; int fd, open_flags, ret;#ifdef CONFIG_COCOA if (strstart(filename, "/dev/cdrom", NULL)) { kern_return_t kernResult; io_iterator_t mediaIterator; char bsdPath[ MAXPATHLEN ]; int fd; kernResult = FindEjectableCDMedia( &mediaIterator ); kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) ); if ( bsdPath[ 0 ] != '\0' ) { strcat(bsdPath,"s0"); /* some CDs don't have a partition 0 */ fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) { bsdPath[strlen(bsdPath)-1] = '1'; } else { close(fd); } filename = bsdPath; } if ( mediaIterator ) IOObjectRelease( mediaIterator ); }#endif open_flags = O_BINARY; if ((flags & BDRV_O_ACCESS) == O_RDWR) { open_flags |= O_RDWR; } else { open_flags |= O_RDONLY; bs->read_only = 1; } s->type = FTYPE_FILE;#if defined(__linux__) if (strstart(filename, "/dev/cd", NULL)) { /* open will not fail even if no CD is inserted */ open_flags |= O_NONBLOCK; s->type = FTYPE_CD; } else if (strstart(filename, "/dev/fd", NULL)) { s->type = FTYPE_FD; s->fd_open_flags = open_flags; /* open will not fail even if no floppy is inserted */ open_flags |= O_NONBLOCK; }#endif fd = open(filename, open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) ret = -EACCES; return ret; } s->fd = fd;#if defined(__linux__) /* close fd so that we can reopen it as needed */ if (s->type == FTYPE_FD) { close(s->fd); s->fd = -1; s->fd_media_changed = 1; }#endif return 0;}#if defined(__linux__) && !defined(QEMU_TOOL)/* Note: we do not have a reliable method to detect if the floppy is present. The current method is to try to open the floppy at every I/O and to keep it opened during a few hundreds of ms. */static int fd_open(BlockDriverState *bs){ BDRVRawState *s = bs->opaque; int last_media_present; if (s->type != FTYPE_FD) return 0; last_media_present = (s->fd >= 0); if (s->fd >= 0 && (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) { close(s->fd); s->fd = -1;#ifdef DEBUG_FLOPPY printf("Floppy closed\n");#endif } if (s->fd < 0) { if (s->fd_got_error && (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {#ifdef DEBUG_FLOPPY printf("No floppy (open delayed)\n");#endif return -EIO; } s->fd = open(bs->filename, s->fd_open_flags); if (s->fd < 0) { s->fd_error_time = qemu_get_clock(rt_clock); s->fd_got_error = 1; if (last_media_present) s->fd_media_changed = 1;#ifdef DEBUG_FLOPPY printf("No floppy\n");#endif return -EIO; }#ifdef DEBUG_FLOPPY printf("Floppy opened\n");#endif } if (!last_media_present) s->fd_media_changed = 1; s->fd_open_time = qemu_get_clock(rt_clock); s->fd_got_error = 0; return 0;}#elsestatic int fd_open(BlockDriverState *bs){ return 0;}#endif#if defined(__linux__)static int raw_is_inserted(BlockDriverState *bs){ BDRVRawState *s = bs->opaque; int ret; switch(s->type) { case FTYPE_CD: ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); if (ret == CDS_DISC_OK) return 1; else return 0; break; case FTYPE_FD: ret = fd_open(bs); return (ret >= 0); default: return 1; }}/* currently only used by fdc.c, but a CD version would be good too */static int raw_media_changed(BlockDriverState *bs){ BDRVRawState *s = bs->opaque; switch(s->type) { case FTYPE_FD: { int ret; /* XXX: we do not have a true media changed indication. It does not work if the floppy is changed without trying to read it */ fd_open(bs); ret = s->fd_media_changed; s->fd_media_changed = 0;#ifdef DEBUG_FLOPPY printf("Floppy changed=%d\n", ret);#endif return ret; } default: return -ENOTSUP; }}static int raw_eject(BlockDriverState *bs, int eject_flag){ BDRVRawState *s = bs->opaque; switch(s->type) { case FTYPE_CD: if (eject_flag) { if (ioctl (s->fd, CDROMEJECT, NULL) < 0) perror("CDROMEJECT"); } else { if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0) perror("CDROMEJECT"); } break; case FTYPE_FD: { int fd; if (s->fd >= 0) { close(s->fd); s->fd = -1; } fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK); if (fd >= 0) { if (ioctl(fd, FDEJECT, 0) < 0) perror("FDEJECT"); close(fd); } } break; default: return -ENOTSUP; } return 0;}static int raw_set_locked(BlockDriverState *bs, int locked){ BDRVRawState *s = bs->opaque; switch(s->type) { case FTYPE_CD: if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) { /* Note: an error can happen if the distribution automatically mounts the CD-ROM */ // perror("CDROM_LOCKDOOR"); } break; default: return -ENOTSUP; } return 0;}#elsestatic int raw_is_inserted(BlockDriverState *bs){ return 1;}static int raw_media_changed(BlockDriverState *bs){ return -ENOTSUP;}static int raw_eject(BlockDriverState *bs, int eject_flag){ return -ENOTSUP;}static int raw_set_locked(BlockDriverState *bs, int locked){ return -ENOTSUP;}#endif /* !linux */BlockDriver bdrv_host_device = { "host_device", sizeof(BDRVRawState), NULL, /* no probe for protocols */ hdev_open, NULL, NULL, raw_close, NULL, raw_flush, .bdrv_aio_read = raw_aio_read, .bdrv_aio_write = raw_aio_write, .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, .bdrv_getlength = raw_getlength, /* removable device support */ .bdrv_is_inserted = raw_is_inserted, .bdrv_media_changed = raw_media_changed, .bdrv_eject = raw_eject, .bdrv_set_locked = raw_set_locked,};#else /* _WIN32 *//* XXX: use another file ? */#include <winioctl.h>#define FTYPE_FILE 0#define FTYPE_CD 1#define FTYPE_HARDDISK 2typedef struct BDRVRawState { HANDLE hfile; int type; char drive_path[16]; /* format: "d:\" */} BDRVRawState;typedef struct RawAIOCB { BlockDriverAIOCB common; HANDLE hEvent; OVERLAPPED ov; int count;} RawAIOCB;int qemu_ftruncate64(int fd, int64_t length){ LARGE_INTEGER li; LONG high; HANDLE h; BOOL res; if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) return -1; h = (HANDLE)_get_osfhandle(fd); /* get current position, ftruncate do not change position */ li.HighPart = 0; li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT); if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) return -1; high = length >> 32; if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN)) return -1; res = SetEndOfFile(h); /* back to old position */ SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN); return res ? 0 : -1;}static int set_sparse(int fd){ DWORD returned; return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &returned, NULL);}static int raw_open(BlockDriverState *bs, const char *filename, int flags){ BDRVRawState *s = bs->opaque; int access_flags, create_flags; DWORD overlapped; s->type = FTYPE_FILE; if ((flags & BDRV_O_ACCESS) == O_RDWR) { access_flags = GENERIC_READ | GENERIC_WRITE; } else { access_flags = GENERIC_READ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -