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 <address@hidden>
---
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;