]> err.no Git - util-linux/commitdiff
liblkid: move getsize.c code to lib/
authorKarel Zak <kzak@redhat.com>
Wed, 10 Mar 2010 14:41:40 +0000 (15:41 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 10 Mar 2010 14:41:40 +0000 (15:41 +0100)
.. and cleanup blkdev_get_size() usage in libblkid.

Signed-off-by: Karel Zak <kzak@redhat.com>
include/blkdev.h
lib/blkdev.c
shlibs/blkid/src/getsize.c
shlibs/blkid/src/probe.c

index 56a9c1f473fdcb032a6b5f5bb8dc198c5fc5db48..98efad681d96d97e26613dae9872bdf554398531 100644 (file)
 #define BLKBSZSET  _IOW(0x12,113,size_t)
 #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
 
-#endif /* BLKROSET */
+#endif /* BLKROSET && __linux__ */
+
+#ifdef APPLE_DARWIN
+#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
+#endif
 
 /* block device topology ioctls, introduced in 2.6.32 */
 #ifndef BLKIOMIN
index 1ca4548bb8488cc2353d5bf07ed9cbd974de8577..824a87c40530b324030a13bf3eef6bc6faf2ab48 100644 (file)
@@ -3,6 +3,21 @@
 #include <sys/ioctl.h>
 #include <unistd.h>
 
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+
+#ifdef HAVE_SYS_DISKLABEL_H
+#include <sys/disklabel.h>
+#endif
+
+#ifdef HAVE_SYS_DISK_H
+#ifdef HAVE_SYS_QUEUE_H
+#include <sys/queue.h> /* for LIST_HEAD */
+#endif
+#include <sys/disk.h>
+#endif
+
 #include "blkdev.h"
 #include "linux_version.h"
 
@@ -41,17 +56,26 @@ blkdev_find_size (int fd) {
 int
 blkdev_get_size(int fd, unsigned long long *bytes)
 {
-       /* TODO: use stat as well */
+#ifdef DKIOCGETBLOCKCOUNT
+       /* Apple Darwin */
+       if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
+               *bytes <<= 9;
+               return 0;
+       }
+#endif
 
 #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)))
+               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)))
 #endif
-               if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
-                       return 0;
+                       if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
+                               return 0;
+       }
 #endif /* BLKGETSIZE64 */
 
 #ifdef BLKGETSIZE
@@ -64,9 +88,56 @@ blkdev_get_size(int fd, unsigned long long *bytes)
                }
        }
 
-       return -1;
 #endif /* BLKGETSIZE */
 
+#ifdef DIOCGMEDIASIZE
+       /* FreeBSD */
+       if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
+               return 0
+#endif
+
+#ifdef FDGETPRM
+       {
+               struct floppy_struct this_floppy;
+
+               if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
+                       *bytes = this_floppy.size << 9;
+                       return 0;
+               }
+       }
+#endif /* FDGETPRM */
+
+#ifdef HAVE_SYS_DISKLABEL_H
+       {
+               /*
+                * This code works for FreeBSD 4.11 i386, except for the full device
+                * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
+                * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
+                * above however.
+                *
+                * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
+                * character) devices, so we need to check for S_ISCHR, too.
+                */
+               int part = -1;
+               struct disklabel lab;
+               struct partition *pp;
+               char ch;
+               struct stat st;
+
+               if ((fstat(fd, &st) >= 0) &&
+                   (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
+                       part = st.st_rdev & 7;
+
+               if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
+                       pp = &lab.d_partitions[part];
+                       if (pp->p_size) {
+                                *bytes = pp->p_size << 9;
+                                return 0;
+                       }
+               }
+       }
+#endif /* HAVE_SYS_DISKLABEL_H */
+
        *bytes = blkdev_find_size(fd);
        return 0;
 }
index 10ba7ecf305516683529faa6c3a97ae51fcc1b37..43b9195b1d7a8bffae88130a34d374db312e2a1c 100644 (file)
@@ -2,6 +2,7 @@
  * getsize.c --- get the size of a partition.
  *
  * Copyright (C) 1995, 1995 Theodore Ts'o.
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
  *
  * %Begin-Header%
  * This file may be redistributed under the terms of the
  * %End-Header%
  */
 
-#define _LARGEFILE_SOURCE
-#define _LARGEFILE64_SOURCE
-
-/* include this before sys/queues.h! */
-#include "blkidP.h"
-
 #include <stdio.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#include <fcntl.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-#include <sys/disklabel.h>
-#endif
-#ifdef HAVE_SYS_DISK_H
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h> /* for LIST_HEAD */
-#endif
-#include <sys/disk.h>
-#endif
-#ifdef __linux__
-#include <sys/utsname.h>
-#endif
-#if HAVE_SYS_STAT_H
 #include <sys/stat.h>
-#endif
-
-
-#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
-#define BLKGETSIZE _IO(0x12,96)        /* return device size */
-#endif
-
-#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
-#define BLKGETSIZE64 _IOR(0x12,114,size_t)     /* return device size in bytes (u64 *arg) */
-#endif
-
-#ifdef APPLE_DARWIN
-#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
-#endif /* APPLE_DARWIN */
+#include <sys/types.h>
 
-static int valid_offset(int fd, blkid_loff_t offset)
-{
-       char ch;
-
-       if (blkid_llseek(fd, offset, 0) < 0)
-               return 0;
-       if (read(fd, &ch, 1) < 1)
-               return 0;
-       return 1;
-}
+#include "blkdev.h"
+#include "blkidP.h"
 
-/*
- * Returns the number of bytes in a partition
+/**
+ * blkid_get_dev_size:
+ * @fd: file descriptor
+ *
+ * Returns: size (in bytes) of the block device or size of the regular file or 0.
  */
 blkid_loff_t blkid_get_dev_size(int fd)
 {
-       int valid_blkgetsize64 = 1;
-#ifdef __linux__
-       struct          utsname ut;
-#endif
-       unsigned long long size64;
-       unsigned long size;
-       blkid_loff_t high, low;
-#ifdef FDGETPRM
-       struct floppy_struct this_floppy;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-       int part = -1;
-       struct disklabel lab;
-       struct partition *pp;
-       char ch;
        struct stat st;
-#endif /* HAVE_SYS_DISKLABEL_H */
-
-#ifdef DKIOCGETBLOCKCOUNT      /* For Apple Darwin */
-       if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
-               if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
-                   && (size64 << 9 > 0xFFFFFFFF))
-                       return 0; /* EFBIG */
-               return (blkid_loff_t) size64 << 9;
-       }
-#endif
-
-#ifdef BLKGETSIZE64
-#ifdef __linux__
-       if ((uname(&ut) == 0) &&
-           ((ut.release[0] == '2') && (ut.release[1] == '.') &&
-            (ut.release[2] < '6') && (ut.release[3] == '.')))
-               valid_blkgetsize64 = 0;
-#endif
-       if (valid_blkgetsize64 &&
-           ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
-               if ((sizeof(blkid_loff_t) < sizeof(unsigned long long))
-                   && ((size64) > 0xFFFFFFFF))
-                       return 0; /* EFBIG */
-               return size64;
-       }
-#endif
-
-#ifdef BLKGETSIZE
-       if (ioctl(fd, BLKGETSIZE, &size) >= 0)
-               return (blkid_loff_t)size << 9;
-#endif
+       unsigned long long bytes;
 
-/* tested on FreeBSD 6.1-RELEASE i386 */
-#ifdef DIOCGMEDIASIZE
-       if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0)
-               return (off_t)size64;
-#endif /* DIOCGMEDIASIZE */
+       if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode))
+               return st.st_size;
 
-#ifdef FDGETPRM
-       if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
-               return (blkid_loff_t)this_floppy.size << 9;
-#endif
-#ifdef HAVE_SYS_DISKLABEL_H
-       /*
-        * This code works for FreeBSD 4.11 i386, except for the full device
-        * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
-        * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
-        * above however.
-        *
-        * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
-        * character) devices, so we need to check for S_ISCHR, too.
-        */
-       if ((fstat(fd, &st) >= 0) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
-               part = st.st_rdev & 7;
-       if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
-               pp = &lab.d_partitions[part];
-               if (pp->p_size)
-                       return pp->p_size << 9;
-       }
-#endif /* HAVE_SYS_DISKLABEL_H */
-       {
-#ifdef HAVE_FSTAT64
-               struct stat64   st;
-               if (fstat64(fd, &st) == 0)
-#else
-               struct stat     st;
-               if (fstat(fd, &st) == 0)
-#endif
-                       if (S_ISREG(st.st_mode))
-                               return st.st_size;
-       }
-
-
-       /*
-        * OK, we couldn't figure it out by using a specialized ioctl,
-        * which is generally the best way.  So do binary search to
-        * find the size of the partition.
-        */
-       low = 0;
-       for (high = 1024; valid_offset(fd, high); high *= 2)
-               low = high;
-       while (low < high - 1)
-       {
-               const blkid_loff_t mid = (low + high) / 2;
+       if (blkdev_get_size(fd, &bytes))
+               return 0;
 
-               if (valid_offset(fd, mid))
-                       low = mid;
-               else
-                       high = mid;
-       }
-       return low + 1;
+       return bytes;
 }
 
-#ifdef TEST_PROGRAM
-int main(int argc, char **argv)
-{
-       long long bytes;
-       int     fd;
-
-       if (argc < 2) {
-               fprintf(stderr, "Usage: %s device\n"
-                       "Determine the size of a device\n", argv[0]);
-               return 1;
-       }
-
-       if ((fd = open(argv[1], O_RDONLY)) < 0)
-               perror(argv[0]);
-
-       bytes = blkid_get_dev_size(fd);
-       printf("Device %s has %Ld 1k blocks.\n", argv[1],
-              (unsigned long long) bytes >> 10);
-
-       return 0;
-}
-#endif
index 6e8513d2266078a1bc906724cd1dd7b11c222e4c..4ca215b083783dedc64d755e37b56742231ef221 100644 (file)
@@ -591,9 +591,13 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
 
                pr->mode = sb.st_mode;
 
-               if (S_ISBLK(sb.st_mode))
-                       blkdev_get_size(fd, (unsigned long long *) &pr->size);
-               else if (S_ISCHR(sb.st_mode))
+               if (S_ISBLK(sb.st_mode)) {
+                       if (blkdev_get_size(fd, (unsigned long long *) &pr->size)) {
+                               DBG(DEBUG_LOWPROBE, printf(
+                                       "failed to get device size\n"));
+                               goto err;
+                       }
+               } else if (S_ISCHR(sb.st_mode))
                        pr->size = 1;           /* UBI devices are char... */
                else if (S_ISREG(sb.st_mode))
                        pr->size = sb.st_size;  /* regular file */
@@ -975,7 +979,11 @@ dev_t blkid_probe_get_devno(blkid_probe pr)
  * blkid_probe_get_size:
  * @pr: probe
  *
- * Returns: block device (or file) size in bytes or -1 in case of error.
+ * This function returns size of probing area as defined by blkid_probe_set_device().
+ * If the size of the probing area is unrestricted then this function returns
+ * the real size of device. See also blkid_get_dev_size().
+ *
+ * Returns: size in bytes or -1 in case of error.
  */
 blkid_loff_t blkid_probe_get_size(blkid_probe pr)
 {