/*
 * disku.c -- gpart disk util routines
 *
 * gpart (c) 1999-2001 Michail Brzitwa <mb@ichabod.han.de>
 * Guess PC-type hard disk partitions.
 *
 * gpart is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2, or (at your
 * option) any later version.
 *
 * Created:   04.01.1999 <mb@ichabod.han.de>
 * Modified:  13.12.2000 <mb@ichabod.han.de>
 *            Calculation of disk cylinder count changed for Linux.
 *
 */


#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include "gpart.h"

#if defined(__linux__)
#include <sys/mount.h>
#include <linux/hdreg.h>
#endif

#if defined(__FreeBSD__)
#include <errno.h>
#include <sys/param.h>
#include <sys/disklabel.h>
#if __FreeBSD_version >= 500040
#include <sys/disk.h>
#endif
#endif



/*
 * get disk geometry. The medium is opened for reading,
 * descriptor in d_fd.
 */

struct disk_geom *disk_geometry(disk_desc *d)
{
	static struct disk_geom	g;

#if defined(__linux__)
	struct hd_geometry	hg;
	long			nsects;

	if (ioctl(d->d_fd,HDIO_GETGEO,&hg) == -1)
		pr(FATAL,EM_IOCTLFAILED,"HDIO_GETGEO",strerror(errno));
#ifdef BLKGETSIZE
	if (ioctl(d->d_fd,BLKGETSIZE,&nsects) == -1)
		pr(FATAL,EM_IOCTLFAILED,"BLKGETSIZE",strerror(errno));
	g.d_c = nsects / (hg.heads * hg.sectors);
#else
	g.d_c = hg.cylinders;
#endif
	g.d_h = hg.heads;
	g.d_s = hg.sectors;

#endif

#if defined(__FreeBSD__)
#if __FreeBSD_version < 500040
	struct disklabel	dl;
	if (ioctl(d->d_fd,DIOCGDINFO,&dl) == -1)
		pr(FATAL,EM_IOCTLFAILED,"DIOCGDINFO",strerror(errno));
	g.d_c = dl.d_ncylinders;
	g.d_h = dl.d_ntracks;
	g.d_s = dl.d_nsectors;
#else
	struct disklabel	loclab;
	u_int    u;

	if (ioctl(d->d_fd, DIOCGFWSECTORS, &u) == 0)
		loclab.d_nsectors = u;
	else
		loclab.d_nsectors = 63;
	if (ioctl(d->d_fd, DIOCGFWHEADS, &u) == 0)
		loclab.d_ntracks = u;
	else if (loclab.d_secperunit <= 63*1*1024)
		loclab.d_ntracks = 1;
	else if (loclab.d_secperunit <= 63*16*1024)
		loclab.d_ntracks = 16;
	else
		loclab.d_ntracks = 255;
	loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors;
	loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl;

        g.d_c = loclab.d_ncylinders;
	g.d_h = loclab.d_ntracks;
	g.d_s = loclab.d_nsectors;
#endif
#endif

	return (&g);
}


/*
 * tell the OS to reread a changed partition table. Do
 * nothing if there is no such possibility.
 */

int reread_partition_table(int fd)
{
#if defined(__linux__) && defined(BLKRRPART)
	if (ioctl(fd,BLKRRPART) == -1)
	{
		pr(ERROR,"rereading partition table: %s",strerror(errno));
		return (0);
	}
#endif

	return (1);
}


syntax highlighted by Code2HTML, v. 0.9.1