getsize.c revision df3e159870beae4b02f1f59bf2a28e3e0fdd6519
150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * getsize.c --- get the size of a partition.
350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore 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.
8c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o *
919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header%
1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public
1119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License.
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
85c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o	dev = CreateFile(file, GENERIC_READ,
86c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o			 FILE_SHARE_READ | FILE_SHARE_WRITE ,
87c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o                	 NULL,  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  NULL);
88c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore 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;
97c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore 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 */
14150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'oerrcode_t ext2fs_get_device_size(const char *file, int blocksize,
14250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o				 blk_t *retblocks)
14350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
1449b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	int	fd, rc = 0;
1452c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	int valid_blkgetsize64 = 1;
1462c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#ifdef __linux__
1472c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	struct 		utsname ut;
1482c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#endif
14985b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o	unsigned long long size64;
150954a683dd0353d280d56b3d70b5e8f24e88b3d2fTheodore Ts'o	unsigned long	size;
15150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	ext2_loff_t high, low;
15250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef FDGETPRM
15350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct floppy_struct this_floppy;
15450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
15550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_SYS_DISKLABEL_H
15619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	int part;
15750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct disklabel lab;
15850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct partition *pp;
15950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char ch;
16050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif /* HAVE_SYS_DISKLABEL_H */
16150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
162dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#ifdef HAVE_OPEN64
163dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o	fd = open64(file, O_RDONLY);
164dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#else
1657f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o	fd = open(file, O_RDONLY);
166dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#endif
16750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (fd < 0)
16850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return errno;
16950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
17085b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#ifdef DKIOCGETBLOCKCOUNT	/* For Apple Darwin */
1712c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
17285b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o		if ((sizeof(*retblocks) < sizeof(unsigned long long))
17385b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o		    && ((size64 / (blocksize / 512)) > 0xFFFFFFFF))
17485b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o			return EFBIG;
17585b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o		*retblocks = size64 / (blocksize / 512);
1769b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		goto out;
17785b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o	}
17885b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#endif
17985b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
18085b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#ifdef BLKGETSIZE64
1812c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#ifdef __linux__
1822c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	if ((uname(&ut) == 0) &&
1832c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
1842c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	     (ut.release[2] < '6') && (ut.release[3] == '.')))
1852c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o		valid_blkgetsize64 = 0;
1862c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o#endif
1872c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	if (valid_blkgetsize64 &&
1882c5cfbcb99f70d90f8e679bd2994b263ca6d11d6Theodore Ts'o	    ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
1899b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		if ((sizeof(*retblocks) < sizeof(unsigned long long)) &&
1909b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		    ((size64 / blocksize) > 0xFFFFFFFF)) {
1919b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			rc = EFBIG;
1929b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			goto out;
1939b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		}
19485b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o		*retblocks = size64 / blocksize;
1959b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		goto out;
19685b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o	}
19785b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o#endif
19885b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
19950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef BLKGETSIZE
20050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
20150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		*retblocks = size / (blocksize / 512);
2029b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		goto out;
20350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
20450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
20585b870034437e590e4aca77e325f3f5d6815eb39Theodore Ts'o
20650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef FDGETPRM
20750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
20850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		*retblocks = this_floppy.size / (blocksize / 512);
2099b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		goto out;
21050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
21150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
212289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree
21350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_SYS_DISKLABEL_H
214289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree#if defined(DIOCGMEDIASIZE)
215289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree	{
216289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree	    off_t ms;
217289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree	    u_int bs;
218289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree	    if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
219289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree		*retblocks = ms / blocksize;
2209b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		goto out;
221289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree	    }
222289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree	}
223289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree#elif defined(DIOCGDINFO)
224b34cbddbd66baedc163d36dd281b63ef478f547aMatthias Andree	/* old disklabel interface */
22519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	part = strlen(file) - 1;
22619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	if (part >= 0) {
22719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o		ch = file[part];
22850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (isdigit(ch))
22919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o			part = 0;
23050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		else if (ch >= 'a' && ch <= 'h')
23119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o			part = ch - 'a';
23250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		else
23319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o			part = -1;
23450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
23519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
23619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o		pp = &lab.d_partitions[part];
23750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (pp->p_size) {
23850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			*retblocks = pp->p_size / (blocksize / 512);
2399b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			goto out;
24050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		}
24150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
242289e0557c24c68290b6d9b73b09674447801fdacMatthias Andree#endif /* defined(DIOCG*) */
24350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif /* HAVE_SYS_DISKLABEL_H */
24450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
2459b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	{
2469b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger#ifdef HAVE_FSTAT64
2479b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		struct stat64   st;
2489b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		if (fstat64(fd, &st) == 0)
2499b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger#else
2509b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		struct stat	st;
2519b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger		if (fstat(fd, &st) == 0)
2529b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger#endif
2539b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			if (S_ISREG(st.st_mode)) {
2549b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger				*retblocks = st.st_size / blocksize;
2559b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger				goto out;
2569b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger			}
2579b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	}
2589b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger
25950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	/*
26050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * OK, we couldn't figure it out by using a specialized ioctl,
26119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	 * which is generally the best way.  So do binary search to
26250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 * find the size of the partition.
26350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	 */
26450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	low = 0;
26550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	for (high = 1024; valid_offset (fd, high); high *= 2)
26650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		low = high;
26750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	while (low < high - 1)
26850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	{
26950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		const ext2_loff_t mid = (low + high) / 2;
27050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
27150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		if (valid_offset (fd, mid))
27250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			low = mid;
27350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		else
27450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			high = mid;
27550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
27650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	valid_offset (fd, 0);
277283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o	size64 = low + 1;
278283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o	if ((sizeof(*retblocks) < sizeof(unsigned long long))
279283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o	    && ((size64 / blocksize) > 0xFFFFFFFF))
280283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o		return EFBIG;
281283df83e7e2559f7190bb7a1dab759ccedac27abTheodore Ts'o	*retblocks = size64 / blocksize;
2829b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilgerout:
2839b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	close(fd);
2849b7d811ddad946e728d9348a78cb06dee159df96Andreas Dilger	return rc;
28550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
286abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o
287c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o#endif /* WIN32 */
288c6928406b3d8b1437a379ab66da2b8fa389febbcTheodore Ts'o
289abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o#ifdef DEBUG
290abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'oint main(int argc, char **argv)
291abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o{
292abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	blk_t	blocks;
293abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	int	retval;
294abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o
295abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	if (argc < 2) {
296abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		fprintf(stderr, "Usage: %s device\n", argv[0]);
297abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		exit(1);
298abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	}
299abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o
300abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
301abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	if (retval) {
302abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		com_err(argv[0], retval,
303abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o			"while calling ext2fs_get_device_size");
304abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o		exit(1);
305abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	}
306abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	printf("Device %s has %d 1k blocks.\n", argv[1], blocks);
307abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o	exit(0);
308abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o}
309abf7d3880b84994783437e291bd4e7950c4b0fe7Theodore Ts'o#endif
310