From 268cefe6cb34fb8799b34187677154071ad45eb7 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 24 Jul 2008 00:30:21 +0200 Subject: [PATCH] lib: blkdev.c clean up, non-linux support [kzak@redhat.com: split the original patch to small patches] Signed-off-by: Samuel Thibault Signed-off-by: Karel Zak --- include/blkdev.h | 10 +++++--- lib/blkdev.c | 67 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/include/blkdev.h b/include/blkdev.h index 1f0fe674..1b10569b 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -6,7 +6,7 @@ #define DEFAULT_SECTOR_SIZE 512 -#ifndef BLKROSET +#if !defined(BLKROSET) && defined(__linux__) #define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */ #define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */ @@ -34,7 +34,9 @@ #endif /* BLKROSET */ #ifndef HDIO_GETGEO -#define HDIO_GETGEO 0x0301 +# ifdef __linux__ +# define HDIO_GETGEO 0x0301 +# endif struct hd_geometry { unsigned char heads; unsigned char sectors; @@ -43,6 +45,9 @@ struct hd_geometry { }; #endif +/* Determine size in bytes */ +off_t blkdev_find_size (int fd); + /* get size in bytes */ int blkdev_get_size(int fd, unsigned long long *bytes); @@ -52,5 +57,4 @@ int blkdev_get_sectors(int fd, unsigned long long *sectors); /* get hardware sector size */ int blkdev_get_sector_size(int fd, int *sector_size); - #endif /* BLKDEV_H */ diff --git a/lib/blkdev.c b/lib/blkdev.c index 29c5d0bd..79a366ca 100644 --- a/lib/blkdev.c +++ b/lib/blkdev.c @@ -1,30 +1,74 @@ #include #include +#include #include "blkdev.h" #include "linux_version.h" +static long +blkdev_valid_offset (int fd, off_t offset) { + char ch; + + if (lseek (fd, offset, 0) < 0) + return 0; + if (read (fd, &ch, 1) < 1) + return 0; + return 1; +} + +off_t +blkdev_find_size (int fd) { + off_t high, low; + + low = 0; + for (high = 1; high > 0 && blkdev_valid_offset (fd, high); high *= 2) + low = high; + while (low < high - 1) + { + const off_t mid = (low + high) / 2; + + if (blkdev_valid_offset (fd, mid)) + low = mid; + else + high = mid; + } + blkdev_valid_offset (fd, 0); + return (low + 1); +} + /* get size in bytes */ int blkdev_get_size(int fd, unsigned long long *bytes) { - unsigned long size; - int ver = get_linux_version(); + /* TODO: use stat as well */ +#ifdef BLKGETSIZE64 +#ifdef __linux__ + int ver = get_linux_version(); /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */ if (ver >= KERNEL_VERSION (2,6,0) || - (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0))) { - + (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0))) +#endif if (ioctl(fd, BLKGETSIZE64, bytes) >= 0) return 0; - } - if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - *bytes = ((unsigned long long)size << 9); - return 0; +#endif /* BLKGETSIZE64 */ + +#ifdef BLKGETSIZE + { + unsigned long size; + + if (ioctl(fd, BLKGETSIZE, &size) >= 0) { + *bytes = ((unsigned long long)size << 9); + return 0; + } } return -1; +#endif /* BLKGETSIZE */ + + *bytes = blkdev_find_size(fd); + return 0; } /* get 512-byte sector count */ @@ -45,14 +89,21 @@ blkdev_get_sectors(int fd, unsigned long long *sectors) int blkdev_get_sector_size(int fd, int *sector_size) { +#ifdef BLKSSZGET +#ifdef __linux__ if (get_linux_version() < KERNEL_VERSION(2,3,3)) { *sector_size = DEFAULT_SECTOR_SIZE; return 0; } +#endif if (ioctl(fd, BLKSSZGET, sector_size) >= 0) return 0; return -1; +#else + *sector_size = DEFAULT_SECTOR_SIZE; + return 0; +#endif } -- 2.39.5