summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2010-03-16 17:31:39 +0100
committerKarel Zak <kzak@redhat.com>2010-03-16 17:31:39 +0100
commitabbd79ac35ca4ad65f2bba55288652db907a514e (patch)
tree69fdc8f21d8b9530da05f4cbf704f21657becd68
parentb8d22034f1b393a48ce7af9e15d910bf0e29df0b (diff)
downloadutil-linux-old-abbd79ac35ca4ad65f2bba55288652db907a514e.tar.gz
lib: fix blkdev_find_size()
echo l | fdisk/fdisk /dev/zero FYI that however now spins forever doing: offset=3074457345618258603) at ../lib/blkdev.c:31 at ../lib/blkdev.c:151 at ../lib/blkdev.c:161 Reported-by: Pádraig Brady <P@draigBrady.com> Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--lib/blkdev.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/lib/blkdev.c b/lib/blkdev.c
index 4b9e6fc6..7d00324d 100644
--- a/lib/blkdev.c
+++ b/lib/blkdev.c
@@ -3,6 +3,7 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
+#include <stdint.h>
#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
@@ -35,14 +36,23 @@ blkdev_valid_offset (int fd, off_t offset) {
off_t
blkdev_find_size (int fd) {
- off_t high, low;
+ uintmax_t high, low = 0;
+
+ for (high = 1024; blkdev_valid_offset (fd, high); ) {
+ if (high == UINTMAX_MAX)
+ return -1;
- low = 0;
- for (high = 1; high > 0 && blkdev_valid_offset (fd, high); high *= 2)
low = high;
+
+ if (high >= UINTMAX_MAX/2)
+ high = UINTMAX_MAX;
+ else
+ high *= 2;
+ }
+
while (low < high - 1)
{
- const off_t mid = (low + high) / 2;
+ uintmax_t mid = (low + high) / 2;
if (blkdev_valid_offset (fd, mid))
low = mid;
@@ -146,6 +156,8 @@ blkdev_get_size(int fd, unsigned long long *bytes)
*bytes = st.st_size;
return 0;
}
+ if (!S_ISBLK(st.st_mode))
+ return -1;
}
*bytes = blkdev_find_size(fd);