OpenSolaris_b135/cmd/devinfo/devinfo.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

/*
 *	Two output fields under the -i option will always be
 *	output as zero, since they are not supported by Sun:
 *		Software version, and
 *		Drive id number.
 *	AT&T filled these 2 fields with data from their "pdsector",
 *	which Sun doesn't support per se.
 */


#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dkio.h>
#include <sys/efi_partition.h>
#include <sys/vtoc.h>
#include <sys/mkdev.h>
#include <errno.h>

#define	DRERR	2
#define	OPENERR	2

/*
 * Standard I/O file descriptors.
 */
#define	STDOUT	1		/* Standard output */
#define	STDERR	2		/* Standard error */

static	void	partinfo(int fd, char *device);
static	void	devinfo(struct dk_geom *geom, int fd, char *device);
static	int	readvtoc(int fd, char *name, struct extvtoc *vtoc);
static	int	warn(char *what, char *why);
static	void	usage(void);

int
main(int argc, char **argv)
{
	struct dk_geom  geom;
	int errflg, iflg, pflg, fd, c;
	char *device;

	iflg = 0;
	pflg = 0;
	errflg = 0;
	while ((c = getopt(argc, argv, "i:p:")) != EOF) {
		switch (c) {
			case 'i':
				iflg++;
				device = optarg;
				break;
			case 'p':
				pflg++;
				device = optarg;
				break;
			case '?':
				errflg++;
				break;
			default:
				errflg++;
				break;
		}
		if (errflg)
			usage();
	}
	if ((optind > argc) || (optind == 1) || (pflg && iflg))
		usage();

	if ((fd = open(device, O_RDONLY)) < 0) {
		(void) fprintf(stderr, "devinfo: %s: %s\n",
			device, strerror(errno));
		exit(OPENERR);
	}

	if (iflg) {
		if (ioctl(fd, DKIOCGGEOM, &geom) == -1) {
			if (errno == ENOTSUP) {
				(void) warn(device,
"This operation is not supported on EFI labeled devices");
			} else {
				(void) warn(device,
"Unable to read Disk geometry");
			}
			(void) close(fd);
			exit(DRERR);
		}
		devinfo(&geom, fd, device);
	}
	if (pflg)
		partinfo(fd, device);
	(void) close(fd);
	return (0);
}

static void
partinfo(int fd, char *device)
{
	int i;
	int	slice;
	major_t maj;
	minor_t min;
	struct stat64 statbuf;
	struct extvtoc vtdata;
	struct dk_gpt *efi;

	i = stat64(device, &statbuf);
	if (i < 0)
		exit(DRERR);
	maj = major(statbuf.st_rdev);
	min = minor(statbuf.st_rdev);

	if ((slice = readvtoc(fd, device, &vtdata)) >= 0) {

		(void) printf("%s\t%0lx\t%0lx\t%llu\t%llu\t%x\t%x\n",
			device, maj, min,
			vtdata.v_part[slice].p_start,
			vtdata.v_part[slice].p_size,
			vtdata.v_part[slice].p_flag,
			vtdata.v_part[slice].p_tag);
	} else if ((slice == VT_ENOTSUP) &&
	    (slice = efi_alloc_and_read(fd, &efi)) >= 0) {
		(void) printf("%s\t%lx\t%lx\t%lld\t%lld\t%hx\t%hx\n",
			device, maj, min,
			efi->efi_parts[slice].p_start,
			efi->efi_parts[slice].p_size,
			efi->efi_parts[slice].p_flag,
			efi->efi_parts[slice].p_tag);
	} else {
		exit(DRERR);
	}
}

static void
devinfo(struct dk_geom *geom, int fd, char *device)
{
	int i;
	unsigned int nopartitions, sectorcyl, bytes;
	struct extvtoc vtdata;
/*
 *	unsigned int version = 0;
 *	unsigned int driveid = 0;
 */

	nopartitions = 0;
	sectorcyl = 0;
	bytes = 0;

	if (readvtoc(fd, device, &vtdata) < 0)
		exit(DRERR);
	sectorcyl = geom->dkg_nhead  *  geom->dkg_nsect;
	bytes = vtdata.v_sectorsz;
/*
 *	these are not supported by Sun.
 *
 *	driveid = osect0->newsect0.pdinfo.driveid;
 *	version = osect0->newsect0.pdinfo.version;
 */
	for (i = 0; i < V_NUMPAR; i++)	{
		if (vtdata.v_part[i].p_size != 0x00)
			nopartitions++;
	}
/*
 *	(void) printf("%s	%0x	%0x	%d	%d	%d\n",
 *		device, version, driveid, sectorcyl, bytes, nopartitions);
 */
	(void) printf("%s	%0x	%0x	%d	%d	%d\n",
		device, 0, 0, sectorcyl, bytes, nopartitions);
}


/*
 * readvtoc()
 *
 * Read a partition map.
 */
static int
readvtoc(int fd, char *name, struct extvtoc *vtoc)
{
	int	retval;

	retval = read_extvtoc(fd, vtoc);

	switch (retval) {
		case (VT_ERROR):
			return (warn(name, strerror(errno)));
		case (VT_EIO):
			return (warn(name, "I/O error accessing VTOC"));
		case (VT_EINVAL):
			return (warn(name, "Invalid field in VTOC"));
		}

	return (retval);
}


/*
 * warn()
 *
 * Print an error message. Always returns -1.
 */
static int
warn(char *what, char *why)
{
	static char	myname[]  = "devinfo";
	static char	between[] = ": ";
	static char	after[]   = "\n";

	(void) write(STDERR, myname, (uint_t)strlen(myname));
	(void) write(STDERR, between, (uint_t)strlen(between));
	(void) write(STDERR, what, (uint_t)strlen(what));
	(void) write(STDERR, between, (uint_t)strlen(between));
	(void) write(STDERR, why, (uint_t)strlen(why));
	(void) write(STDERR, after, (uint_t)strlen(after));
	return (-1);
}

static void
usage(void)
{
	(void) fprintf(stderr, "Usage: devinfo -p device\n"
		"       devinfo -i device \n");
	exit(2);
}