/** * ntfs_device_size_get - return the size of a device in blocks * @dev: open device * @block_size: block size in bytes in which to return the result * * Return the number of @block_size sized blocks in the device described by the * open device @dev. * * Adapted from e2fsutils-1.19, Copyright (C) 1995 Theodore Ts'o. * * On error return -1 with errno set to the error code. */ s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size) { s64 high, low; if (!dev || block_size <= 0 || (block_size - 1) & block_size) { errno = EINVAL; return -1; } #ifdef BLKGETSIZE64 { u64 size; if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) { ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n", (unsigned long long)size, (unsigned long long)size); return (s64)size / block_size; } } #endif #ifdef BLKGETSIZE { unsigned long size; if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) { ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n", size, size); return (s64)size * 512 / block_size; } } #endif #ifdef FDGETPRM { struct floppy_struct this_floppy; if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) { ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n", (unsigned long)this_floppy.size, (unsigned long)this_floppy.size); return (s64)this_floppy.size * 512 / block_size; } } #endif /* * We couldn't figure it out by using a specialized ioctl, * so do binary search to find the size of the device. */ low = 0LL; for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1) low = high; while (low < high - 1LL) { const s64 mid = (low + high) / 2; if (!ntfs_device_offset_valid(dev, mid)) low = mid; else high = mid; } dev->d_ops->seek(dev, 0LL, SEEK_SET); return (low + 1LL) / block_size; }
/** * ntfs_device_size_get - return the size of a device in blocks * @dev: open device * @block_size: block size in bytes in which to return the result * * Return the number of @block_size sized blocks in the device described by the * open device @dev. * * Adapted from e2fsutils-1.19, Copyright (C) 1995 Theodore Ts'o. * * On error return -1 with errno set to the error code. */ s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size) { s64 high, low; if (!dev || block_size <= 0 || (block_size - 1) & block_size) { errno = EINVAL; return -1; } #ifdef BLKGETSIZE64 { u64 size; if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) { ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n", (unsigned long long)size, (unsigned long long)size); return (s64)size / block_size; } } #endif #ifdef BLKGETSIZE { unsigned long size; if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) { ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n", size, size); return (s64)size * 512 / block_size; } } #endif #ifdef FDGETPRM { struct floppy_struct this_floppy; if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) { ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n", (unsigned long)this_floppy.size, (unsigned long)this_floppy.size); return (s64)this_floppy.size * 512 / block_size; } } #endif #ifdef DIOCGMEDIASIZE { /* FreeBSD */ off_t size; if (dev->d_ops->ioctl(dev, DIOCGMEDIASIZE, &size) >= 0) { ntfs_log_debug("DIOCGMEDIASIZE nr bytes = %llu (0x%llx)\n", (unsigned long long)size, (unsigned long long)size); return (s64)size / block_size; } } #endif #ifdef DKIOCGETBLOCKCOUNT { /* Mac OS X */ uint64_t blocks; int sector_size; sector_size = ntfs_device_sector_size_get(dev); if (sector_size >= 0 && dev->d_ops->ioctl(dev, DKIOCGETBLOCKCOUNT, &blocks) >= 0) { ntfs_log_debug("DKIOCGETBLOCKCOUNT nr blocks = %llu (0x%llx)\n", (unsigned long long) blocks, (unsigned long long) blocks); return blocks * sector_size / block_size; } } #endif #ifdef __HAIKU__ { off_t size = 0; partition_info partitionInfo; device_geometry geometry; if (dev->d_ops->ioctl(dev, B_GET_PARTITION_INFO, &partitionInfo) == 0) size = partitionInfo.size; else if (dev->d_ops->ioctl(dev, B_GET_GEOMETRY, &geometry) == 0) { size = (off_t)geometry.cylinder_count * geometry.sectors_per_track * geometry.head_count * geometry.bytes_per_sector; } if (size > 0) return (s64)size / block_size; } #endif /* * We couldn't figure it out by using a specialized ioctl, * so do binary search to find the size of the device. */ low = 0LL; for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1) low = high; while (low < high - 1LL) { const s64 mid = (low + high) / 2; if (!ntfs_device_offset_valid(dev, mid)) low = mid; else high = mid; } dev->d_ops->seek(dev, 0LL, SEEK_SET); return (low + 1LL) / block_size; }