150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * getsize.c --- get the size of a partition.
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1995, 1995 Theodore Ts'o.
5c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o * Copyright (C) 2003 VMware, Inc.
619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *
7c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o * Windows version of ext2fs_get_device_size by Chris Li, VMware.
8efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header%
10543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
11543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
1219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header%
1350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
1450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
15dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE_SOURCE
16dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE64_SOURCE
17dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
1850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <stdio.h>
1950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#if HAVE_UNISTD_H
2050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <unistd.h>
2150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
22c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#if HAVE_ERRNO_H
23c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#include <errno.h>
24c4e749abd8451f02418fe552b2af14f226f7bd1eTheodore Ts'o#endif
2550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <fcntl.h>
269845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#ifdef HAVE_SYS_IOCTL_H
2750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <sys/ioctl.h>
289845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#endif
299845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#ifdef HAVE_LINUX_FD_H
3050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <linux/fd.h>
3150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
3250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_SYS_DISKLABEL_H
3350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <sys/disklabel.h>
349845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#endif
35b34cbddbd66baedc163d36dd281b63ef478f547aMatthias Andree#ifdef HAVE_SYS_DISK_H
369845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#ifdef HAVE_SYS_QUEUE_H
37b34cbddbd66baedc163d36dd281b63ef478f547aMatthias Andree#include <sys/queue.h> /* for LIST_HEAD */
389845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#endif
39b34cbddbd66baedc163d36dd281b63ef478f547aMatthias Andree#include <sys/disk.h>
409845cf5dbd4d06ebc1fe0db99078d7a0be641e0aTheodore Ts'o#endif
412c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#ifdef __linux__
422c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#include <sys/utsname.h>
432c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#endif
449b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger#if HAVE_SYS_STAT_H
459b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger#include <sys/stat.h>
469b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger#endif
47df3e159870beae4b02f1f59bf2a28e3e0fdd6519Matthias Andree#include <ctype.h>
4850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
497fd86d396745cf38ed5a3b91d1570440a8e770a1Theodore Ts'o#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
507fd86d396745cf38ed5a3b91d1570440a8e770a1Theodore Ts'o#define BLKGETSIZE _IO(0x12,96)	/* return device size */
517fd86d396745cf38ed5a3b91d1570440a8e770a1Theodore Ts'o#endif
527fd86d396745cf38ed5a3b91d1570440a8e770a1Theodore Ts'o
5385b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
5485b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#define BLKGETSIZE64 _IOR(0x12,114,size_t)	/* return device size in bytes (u64 *arg) */
5585b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#endif
5685b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
57e71d87317ac095fa08079f0cc9040da16952eb93Theodore Ts'o#ifdef APPLE_DARWIN
58e71d87317ac095fa08079f0cc9040da16952eb93Theodore Ts'o#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
59e71d87317ac095fa08079f0cc9040da16952eb93Theodore Ts'o#endif /* APPLE_DARWIN */
60e71d87317ac095fa08079f0cc9040da16952eb93Theodore Ts'o
61b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h"
6250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include "ext2fs.h"
6350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
64c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o#if defined(__CYGWIN__) || defined (WIN32)
65c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o#include "windows.h"
66c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o#include "winioctl.h"
67c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
681a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#if (_WIN32_WINNT >= 0x0500)
691a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#define HAVE_GET_FILE_SIZE_EX 1
701a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#endif
711a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o
72c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'oerrcode_t ext2fs_get_device_size(const char *file, int blocksize,
73c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o				 blk_t *retblocks)
74c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o{
75c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	HANDLE dev;
76c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	PARTITION_INFORMATION pi;
77c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	DISK_GEOMETRY gi;
78c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	DWORD retbytes;
791a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#ifdef HAVE_GET_FILE_SIZE_EX
8005a27b1d34fc566a3f11b086a4f6e7b7888b5406Theodore Ts'o	LARGE_INTEGER filesize;
811a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#else
821a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o	DWORD filesize;
831a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#endif /* HAVE_GET_FILE_SIZE_EX */
84c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
85efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	dev = CreateFile(file, GENERIC_READ,
86c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			 FILE_SHARE_READ | FILE_SHARE_WRITE ,
87efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o                	 NULL,  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  NULL);
88efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
89c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	if (dev == INVALID_HANDLE_VALUE)
90c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o		return EBADF;
91c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
92c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			    &pi, sizeof(PARTITION_INFORMATION),
93c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			    &pi, sizeof(PARTITION_INFORMATION),
94c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			    &retbytes, NULL)) {
95c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
96c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o		*retblocks = pi.PartitionLength.QuadPart / blocksize;
97efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
98c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	} else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
99c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o				&gi, sizeof(DISK_GEOMETRY),
100c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o				&gi, sizeof(DISK_GEOMETRY),
101c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o				&retbytes, NULL)) {
102c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
103c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o		*retblocks = gi.BytesPerSector *
104c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			     gi.SectorsPerTrack *
105c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			     gi.TracksPerCylinder *
106c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			     gi.Cylinders.QuadPart / blocksize;
10705a27b1d34fc566a3f11b086a4f6e7b7888b5406Theodore Ts'o
1081a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#ifdef HAVE_GET_FILE_SIZE_EX
10905a27b1d34fc566a3f11b086a4f6e7b7888b5406Theodore Ts'o	} else if (GetFileSizeEx(dev, &filesize)) {
11005a27b1d34fc566a3f11b086a4f6e7b7888b5406Theodore Ts'o		*retblocks = filesize.QuadPart / blocksize;
111c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	}
1121a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#else
1131a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o	} else {
1141a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o		filesize = GetFileSize(dev, NULL);
1151a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o		if (INVALID_FILE_SIZE != filesize) {
1161a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o			*retblocks = filesize / blocksize;
1171a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o		}
1181a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o	}
1191a9c8c35ba148e55039bd04e0237085f7a3625d1Theodore Ts'o#endif /* HAVE_GET_FILE_SIZE_EX */
120c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
121c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	CloseHandle(dev);
122c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	return 0;
123c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o}
124c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
125c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o#else
126c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
12750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'ostatic int valid_offset (int fd, ext2_loff_t offset)
12850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
12950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char ch;
13050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
13119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	if (ext2fs_llseek (fd, offset, 0) < 0)
13250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 0;
13350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (read (fd, &ch, 1) < 1)
13450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return 0;
13550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return 1;
13650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
13750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
13850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
13950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * Returns the number of blocks in a partition
14050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
141beab8de477110970785077fb3204f171d3fcc485Jose R. Santoserrcode_t ext2fs_get_device_size2(const char *file, int blocksize,
142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				  blk64_t *retblocks)
14350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
1449b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	int	fd, rc = 0;
14585b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o	unsigned long long size64;
14650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	ext2_loff_t high, low;
14750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fd = ext2fs_open_file(file, O_RDONLY, 0);
14950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (fd < 0)
15050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return errno;
15150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
15285b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#ifdef DKIOCGETBLOCKCOUNT	/* For Apple Darwin */
1532c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
15485b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o		*retblocks = size64 / (blocksize / 512);
1559b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		goto out;
15685b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o	}
15785b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#endif
15885b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
15985b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#ifdef BLKGETSIZE64
160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	{
161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		int valid_blkgetsize64 = 1;
1622c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#ifdef __linux__
163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		struct utsname ut;
164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((uname(&ut) == 0) &&
166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     (ut.release[2] < '6') && (ut.release[3] == '.')))
168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			valid_blkgetsize64 = 0;
1692c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#endif
170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (valid_blkgetsize64 &&
171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			*retblocks = size64 / blocksize;
173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			goto out;
174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
17585b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o	}
176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif /* BLKGETSIZE64 */
17785b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
17850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef BLKGETSIZE
179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	{
180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		unsigned long	size;
181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			*retblocks = size / (blocksize / 512);
184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			goto out;
185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
18650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
18750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
18885b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
18950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef FDGETPRM
190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	{
191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		struct floppy_struct this_floppy;
192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			*retblocks = this_floppy.size / (blocksize / 512);
195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			goto out;
196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
19750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
19850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
199289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree
20050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_SYS_DISKLABEL_H
20165f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall	{
202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		int part;
203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		struct disklabel lab;
204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		struct partition *pp;
205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		char ch;
206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if defined(DIOCGMEDIASIZE)
208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		{
209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			off_t ms;
210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			u_int bs;
211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				*retblocks = ms / blocksize;
213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				goto out;
214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
216289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree#elif defined(DIOCGDINFO)
217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		/* old disklabel interface */
218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		part = strlen(file) - 1;
219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (part >= 0) {
220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ch = file[part];
221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (isdigit(ch))
222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				part = 0;
223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			else if (ch >= 'a' && ch <= 'h')
224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				part = ch - 'a';
225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			else
226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				part = -1;
227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pp = &lab.d_partitions[part];
230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (pp->p_size) {
231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				*retblocks = pp->p_size / (blocksize / 512);
232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				goto out;
233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
23450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		}
23565f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall#endif /* defined(DIOCG*) */
236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
23750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif /* HAVE_SYS_DISKLABEL_H */
23850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
2399b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	{
240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_struct_stat st;
241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_fstat(fd, &st) == 0)
2439b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			if (S_ISREG(st.st_mode)) {
2449b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger				*retblocks = st.st_size / blocksize;
2459b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger				goto out;
2469b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			}
2479b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	}
2489b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger
24950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
25050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * OK, we couldn't figure it out by using a specialized ioctl,
25119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	 * which is generally the best way.  So do binary search to
25250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * find the size of the partition.
25350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
25450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	low = 0;
255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (high = 1024; valid_offset(fd, high); high *= 2)
25650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		low = high;
257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	while (low < high - 1) {
25850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		const ext2_loff_t mid = (low + high) / 2;
25950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
26050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (valid_offset (fd, mid))
26150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			low = mid;
26250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		else
26350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			high = mid;
26450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	valid_offset(fd, 0);
266283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o	size64 = low + 1;
267283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o	*retblocks = size64 / blocksize;
2689b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilgerout:
2699b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	close(fd);
2709b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	return rc;
27150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
272abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o
273beab8de477110970785077fb3204f171d3fcc485Jose R. Santoserrcode_t ext2fs_get_device_size(const char *file, int blocksize,
274beab8de477110970785077fb3204f171d3fcc485Jose R. Santos				 blk_t *retblocks)
275beab8de477110970785077fb3204f171d3fcc485Jose R. Santos{
276beab8de477110970785077fb3204f171d3fcc485Jose R. Santos	errcode_t retval;
277beab8de477110970785077fb3204f171d3fcc485Jose R. Santos	blk64_t	blocks;
278beab8de477110970785077fb3204f171d3fcc485Jose R. Santos
2799f7a1fc936497d5ab1ebe88baa704e91880849ccTheodore Ts'o	retval = ext2fs_get_device_size2(file, blocksize, &blocks);
2809f7a1fc936497d5ab1ebe88baa704e91880849ccTheodore Ts'o	if (retval)
281beab8de477110970785077fb3204f171d3fcc485Jose R. Santos		return retval;
2829f7a1fc936497d5ab1ebe88baa704e91880849ccTheodore Ts'o	if (blocks >= (1ULL << 32))
2839f7a1fc936497d5ab1ebe88baa704e91880849ccTheodore Ts'o		return EFBIG;
2849f7a1fc936497d5ab1ebe88baa704e91880849ccTheodore Ts'o	*retblocks = (blk_t) blocks;
2859f7a1fc936497d5ab1ebe88baa704e91880849ccTheodore Ts'o	return 0;
286beab8de477110970785077fb3204f171d3fcc485Jose R. Santos}
287beab8de477110970785077fb3204f171d3fcc485Jose R. Santos
288c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o#endif /* WIN32 */
289c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
290abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o#ifdef DEBUG
291abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'oint main(int argc, char **argv)
292abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o{
293abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	blk_t	blocks;
294abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	int	retval;
295efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
296abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	if (argc < 2) {
297abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		fprintf(stderr, "Usage: %s device\n", argv[0]);
298abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		exit(1);
299abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	}
300abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o
301abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
302abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	if (retval) {
303abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		com_err(argv[0], retval,
304abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o			"while calling ext2fs_get_device_size");
305abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		exit(1);
306abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	}
307d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen	printf("Device %s has %u 1k blocks.\n", argv[1], blocks);
308abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	exit(0);
309abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o}
310abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o#endif
311