]> err.no Git - util-linux/commitdiff
lib: blkdev.c clean up, non-linux support
authorSamuel Thibault <samuel.thibault@ens-lyon.org>
Wed, 23 Jul 2008 22:30:21 +0000 (00:30 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 23 Jul 2008 22:52:52 +0000 (00:52 +0200)
[kzak@redhat.com: split the original patch to small patches]

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
include/blkdev.h
lib/blkdev.c

index 1f0fe674e4d10cc265690c0f963fedd46e8a9ba8..1b10569b9d338978b7ef5fe6099b1351b3b56c79 100644 (file)
@@ -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 */
index 29c5d0bd46b564d7698a1d5f539e345a8f6f5ad1..79a366ca937d21cc33a081405edd4374fdbe3986 100644 (file)
@@ -1,30 +1,74 @@
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
+#include <unistd.h>
 
 #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
 }