lseek can not work for all block devices as the man page says: | Some devices are incapable of seeking and POSIX does not specify | which devices must support lseek().
This patch tries to add the support on Linux by using BLKGETSIZE64 ioctl Signed-off-by: Xiao Guangrong <guangrong.x...@linux.intel.com> --- util/osdep.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/util/osdep.c b/util/osdep.c index 5a61e19..b20c793 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -45,6 +45,11 @@ extern int madvise(caddr_t, size_t, int); #endif +#ifdef CONFIG_LINUX +#include <sys/ioctl.h> +#include <linux/fs.h> +#endif + #include "qemu-common.h" #include "qemu/sockets.h" #include "qemu/error-report.h" @@ -433,6 +438,21 @@ int64_t qemu_fd_getlength(int fd) { int64_t size; +#ifdef CONFIG_LINUX + struct stat stat_buf; + if (fstat(fd, &stat_buf) < 0) { + return -errno; + } + + if ((S_ISBLK(stat_buf.st_mode)) && !ioctl(fd, BLKGETSIZE64, &size)) { + /* The size of block device is larger than max int64_t? */ + if (size < 0) { + return -EOVERFLOW; + } + return size; + } +#endif + size = lseek(fd, 0, SEEK_END); if (size < 0) { return -errno; -- 1.8.3.1