diff options
author | Karel Zak | 2010-03-10 15:41:40 +0100 |
---|---|---|
committer | Karel Zak | 2010-03-10 15:41:40 +0100 |
commit | 3069624180bac35f1cd468249ddb9dfc91d1b7b1 (patch) | |
tree | 7bc8f8ed5fa6ca4bd95530156b1073072c894a0b /lib/blkdev.c | |
parent | libblkid: reset BLKID_TINY_DEV flag in blkid_probe_set_device (diff) | |
download | kernel-qcow2-util-linux-3069624180bac35f1cd468249ddb9dfc91d1b7b1.tar.gz kernel-qcow2-util-linux-3069624180bac35f1cd468249ddb9dfc91d1b7b1.tar.xz kernel-qcow2-util-linux-3069624180bac35f1cd468249ddb9dfc91d1b7b1.zip |
liblkid: move getsize.c code to lib/
.. and cleanup blkdev_get_size() usage in libblkid.
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/blkdev.c')
-rw-r--r-- | lib/blkdev.c | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/lib/blkdev.c b/lib/blkdev.c index 1ca4548bb..824a87c40 100644 --- a/lib/blkdev.c +++ b/lib/blkdev.c @@ -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; } |