Example #1
0
/**
 * 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;
}
Example #2
0
File: device.c Project: DonCN/haiku
/**
 * 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;
}