From: Karel Zak Date: Wed, 10 Mar 2010 14:41:40 +0000 (+0100) Subject: liblkid: move getsize.c code to lib/ X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3069624180bac35f1cd468249ddb9dfc91d1b7b1;p=util-linux liblkid: move getsize.c code to lib/ .. and cleanup blkdev_get_size() usage in libblkid. Signed-off-by: Karel Zak --- diff --git a/include/blkdev.h b/include/blkdev.h index 56a9c1f4..98efad68 100644 --- a/include/blkdev.h +++ b/include/blkdev.h @@ -34,7 +34,11 @@ #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 diff --git a/lib/blkdev.c b/lib/blkdev.c index 1ca4548b..824a87c4 100644 --- a/lib/blkdev.c +++ b/lib/blkdev.c @@ -3,6 +3,21 @@ #include #include +#ifdef HAVE_LINUX_FD_H +#include +#endif + +#ifdef HAVE_SYS_DISKLABEL_H +#include +#endif + +#ifdef HAVE_SYS_DISK_H +#ifdef HAVE_SYS_QUEUE_H +#include /* for LIST_HEAD */ +#endif +#include +#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; } diff --git a/shlibs/blkid/src/getsize.c b/shlibs/blkid/src/getsize.c index 10ba7ecf..43b9195b 100644 --- a/shlibs/blkid/src/getsize.c +++ b/shlibs/blkid/src/getsize.c @@ -2,6 +2,7 @@ * getsize.c --- get the size of a partition. * * Copyright (C) 1995, 1995 Theodore Ts'o. + * Copyright (C) 2010 Karel Zak * * %Begin-Header% * This file may be redistributed under the terms of the @@ -9,199 +10,30 @@ * %End-Header% */ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE - -/* include this before sys/queues.h! */ -#include "blkidP.h" - #include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_LINUX_FD_H -#include -#endif -#ifdef HAVE_SYS_DISKLABEL_H -#include -#endif -#ifdef HAVE_SYS_DISK_H -#ifdef HAVE_SYS_QUEUE_H -#include /* for LIST_HEAD */ -#endif -#include -#endif -#ifdef __linux__ -#include -#endif -#if HAVE_SYS_STAT_H #include -#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 -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 diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 6e8513d2..4ca215b0 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -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) {