getsize.c revision 7270fbe7fa51cbce01a07d031f03872f314206d1
1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * getsize.c --- get the size of a partition.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 1995, 1995 Theodore Ts'o.
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Copyright (C) 2003 VMware, Inc.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Windows version of ext2fs_get_device_size by Chris Li, VMware.
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %Begin-Header%
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This file may be redistributed under the terms of the GNU Library
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * General Public License, version 2.
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %End-Header%
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#define _LARGEFILE_SOURCE
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define _LARGEFILE64_SOURCE
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "config.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if HAVE_UNISTD_H
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if HAVE_ERRNO_H
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_IOCTL_H
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ioctl.h>
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_LINUX_FD_H
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <linux/fd.h>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_DISKLABEL_H
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/disklabel.h>
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_DISK_H
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_QUEUE_H
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/queue.h> /* for LIST_HEAD */
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/disk.h>
415e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#endif
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifdef __linux__
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/utsname.h>
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_SYS_STAT_H
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <sys/stat.h>
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <ctype.h>
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define BLKGETSIZE _IO(0x12,96)	/* return device size */
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define BLKGETSIZE64 _IOR(0x12,114,size_t)	/* return device size in bytes (u64 *arg) */
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef APPLE_DARWIN
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* APPLE_DARWIN */
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ext2_fs.h"
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ext2fs.h"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(__CYGWIN__) || defined (WIN32)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "windows.h"
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "winioctl.h"
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if (_WIN32_WINNT >= 0x0500)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define HAVE_GET_FILE_SIZE_EX 1
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
72bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)errcode_t ext2fs_get_device_size(const char *file, int blocksize,
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)				 blk_t *retblocks)
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch{
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	HANDLE dev;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PARTITION_INFORMATION pi;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	DISK_GEOMETRY gi;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	DWORD retbytes;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GET_FILE_SIZE_EX
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	LARGE_INTEGER filesize;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	DWORD filesize;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HAVE_GET_FILE_SIZE_EX */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)	dev = CreateFile(file, GENERIC_READ,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 FILE_SHARE_READ | FILE_SHARE_WRITE ,
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                	 NULL,  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,  NULL);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)	if (dev == INVALID_HANDLE_VALUE)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return EBADF;
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    &pi, sizeof(PARTITION_INFORMATION),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    &pi, sizeof(PARTITION_INFORMATION),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    &retbytes, NULL)) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		*retblocks = pi.PartitionLength.QuadPart / blocksize;
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	} else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				&gi, sizeof(DISK_GEOMETRY),
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				&gi, sizeof(DISK_GEOMETRY),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				&retbytes, NULL)) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*retblocks = gi.BytesPerSector *
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			     gi.SectorsPerTrack *
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     gi.TracksPerCylinder *
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     gi.Cylinders.QuadPart / blocksize;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef HAVE_GET_FILE_SIZE_EX
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else if (GetFileSizeEx(dev, &filesize)) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		*retblocks = filesize.QuadPart / blocksize;
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	}
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
115bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch		filesize = GetFileSize(dev, NULL);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (INVALID_FILE_SIZE != filesize) {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)			*retblocks = filesize / blocksize;
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HAVE_GET_FILE_SIZE_EX */
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	CloseHandle(dev);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int valid_offset (int fd, ext2_loff_t offset)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	char ch;
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ext2fs_llseek (fd, offset, 0) < 0)
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		return 0;
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (read (fd, &ch, 1) < 1)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		return 0;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the number of blocks in a partition
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				 blk64_t *retblocks)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int	fd, rc = 0;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int valid_blkgetsize64 = 1;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef __linux__
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct 		utsname ut;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	unsigned long long size64;
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	unsigned long	size;
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch	ext2_loff_t high, low;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef FDGETPRM
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct floppy_struct this_floppy;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef HAVE_SYS_DISKLABEL_H
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	int part;
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	struct disklabel lab;
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	struct partition *pp;
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	char ch;
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* HAVE_SYS_DISKLABEL_H */
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	fd = ext2fs_open_file(file, O_RDONLY, 0);
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (fd < 0)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		return errno;
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef DKIOCGETBLOCKCOUNT	/* For Apple Darwin */
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) {
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		*retblocks = size64 / (blocksize / 512);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		goto out;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	}
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef BLKGETSIZE64
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef __linux__
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if ((uname(&ut) == 0) &&
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    ((ut.release[0] == '2') && (ut.release[1] == '.') &&
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	     (ut.release[2] < '6') && (ut.release[3] == '.')))
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		valid_blkgetsize64 = 0;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (valid_blkgetsize64 &&
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		*retblocks = size64 / blocksize;
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		goto out;
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	}
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif /* BLKGETSIZE64 */
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef BLKGETSIZE
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		*retblocks = size / (blocksize / 512);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		goto out;
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef FDGETPRM
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		*retblocks = this_floppy.size / (blocksize / 512);
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		goto out;
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_DISKLABEL_H
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(DIOCGMEDIASIZE)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    off_t ms;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    u_int bs;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*retblocks = ms / blocksize;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(DIOCGDINFO)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* old disklabel interface */
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	part = strlen(file) - 1;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (part >= 0) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		ch = file[part];
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (isdigit(ch))
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			part = 0;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		else if (ch >= 'a' && ch <= 'h')
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			part = ch - 'a';
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		else
222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			part = -1;
223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	}
224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)		pp = &lab.d_partitions[part];
2260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)		if (pp->p_size) {
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)			*retblocks = pp->p_size / (blocksize / 512);
2283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)			goto out;
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		}
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif /* defined(DIOCG*) */
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif /* HAVE_SYS_DISKLABEL_H */
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	{
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ext2fs_struct_stat st;
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (ext2fs_fstat(fd, &st) == 0)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (S_ISREG(st.st_mode)) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				*retblocks = st.st_size / blocksize;
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				goto out;
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			}
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/*
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * OK, we couldn't figure it out by using a specialized ioctl,
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * which is generally the best way.  So do binary search to
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * find the size of the partition.
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 */
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	low = 0;
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	for (high = 1024; valid_offset (fd, high); high *= 2)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		low = high;
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	while (low < high - 1)
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	{
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		const ext2_loff_t mid = (low + high) / 2;
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (valid_offset (fd, mid))
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			low = mid;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		else
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			high = mid;
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	valid_offset (fd, 0);
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	size64 = low + 1;
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	*retblocks = size64 / blocksize;
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)out:
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	close(fd);
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	return rc;
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)errcode_t ext2fs_get_device_size(const char *file, int blocksize,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				 blk_t *retblocks)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	errcode_t retval;
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	blk64_t	blocks;
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	retval = ext2fs_get_device_size2(file, blocksize, &blocks);
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (retval)
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return retval;
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (blocks >= (1ULL << 32))
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		return EFBIG;
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	*retblocks = (blk_t) blocks;
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	return 0;
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif /* WIN32 */
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int main(int argc, char **argv)
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles){
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	blk_t	blocks;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int	retval;
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (argc < 2) {
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		fprintf(stderr, "Usage: %s device\n", argv[0]);
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		exit(1);
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	retval = ext2fs_get_device_size(argv[1], 1024, &blocks);
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (retval) {
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		com_err(argv[0], retval,
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			"while calling ext2fs_get_device_size");
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		exit(1);
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	}
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	printf("Device %s has %u 1k blocks.\n", argv[1], blocks);
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	exit(0);
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)