2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <fcntl.h>
2N/A#include <libdevinfo.h>
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <sys/sunddi.h>
2N/A#include <sys/types.h>
2N/A#include <sys/stat.h>
2N/A#include <dirent.h>
2N/A#include <unistd.h>
2N/A#include <sys/dkio.h>
2N/A
2N/A#if defined(i386) || defined(__amd64)
2N/A#include <sys/dktp/fdisk.h>
2N/A#include <libfdisk.h>
2N/A#endif
2N/A
2N/A#include "libdiskmgt.h"
2N/A#include "disks_private.h"
2N/A#include "partition.h"
2N/A
2N/A#ifdef sparc
2N/A#define les(val) ((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
2N/A#define lel(val) (((unsigned)(les((val)&0x0000FFFF))<<16) | \
2N/A (les((unsigned)((val)&0xffff0000)>>16)))
2N/A#else
2N/A#define les(val) (val)
2N/A#define lel(val) (val)
2N/A#endif
2N/A
2N/A#define TOTAL_NUMPART (FD_NUMPART + MAX_EXT_PARTS)
2N/A
2N/A#define ISIZE FD_NUMPART * sizeof (struct ipart)
2N/A
2N/Astatic int desc_ok(descriptor_t *dp);
2N/Astatic int get_attrs(descriptor_t *dp, struct ipart *iparts,
2N/A nvlist_t *attrs);
2N/Astatic int get_parts(disk_t *disk, struct ipart *iparts, char *opath,
2N/A int opath_len);
2N/Astatic int open_disk(disk_t *diskp, char *opath, int len);
2N/Astatic int has_slices(descriptor_t *desc, int *errp);
2N/A
2N/Adescriptor_t **
2N/Apartition_get_assoc_descriptors(descriptor_t *desc, dm_desc_type_t type,
2N/A int *errp)
2N/A{
2N/A if (!desc_ok(desc)) {
2N/A *errp = ENODEV;
2N/A return (NULL);
2N/A }
2N/A
2N/A switch (type) {
2N/A case DM_MEDIA:
2N/A return (media_get_assocs(desc, errp));
2N/A case DM_SLICE:
2N/A if (!has_slices(desc, errp)) {
2N/A if (*errp != 0) {
2N/A return (NULL);
2N/A }
2N/A return (libdiskmgt_empty_desc_array(errp));
2N/A }
2N/A return (slice_get_assocs(desc, errp));
2N/A }
2N/A
2N/A *errp = EINVAL;
2N/A return (NULL);
2N/A}
2N/A
2N/A/*
2N/A * This is called by media/slice to get the associated partitions.
2N/A * For a media desc. we just get all the partitions, but for a slice desc.
2N/A * we just get the active solaris partition.
2N/A */
2N/Adescriptor_t **
2N/Apartition_get_assocs(descriptor_t *desc, int *errp)
2N/A{
2N/A descriptor_t **partitions;
2N/A int pos;
2N/A int i;
2N/A struct ipart iparts[TOTAL_NUMPART];
2N/A char pname[MAXPATHLEN];
2N/A int conv_flag = 0;
2N/A#if defined(i386) || defined(__amd64)
2N/A int len;
2N/A#endif
2N/A
2N/A if (get_parts(desc->p.disk, iparts, pname, sizeof (pname)) != 0) {
2N/A return (libdiskmgt_empty_desc_array(errp));
2N/A }
2N/A
2N/A /* allocate the array for the descriptors */
2N/A partitions = (descriptor_t **)calloc(TOTAL_NUMPART + 1,
2N/A sizeof (descriptor_t *));
2N/A if (partitions == NULL) {
2N/A *errp = ENOMEM;
2N/A return (NULL);
2N/A }
2N/A
2N/A#if defined(i386) || defined(__amd64)
2N/A /* convert part. name (e.g. c0d0p1) */
2N/A len = strlen(pname);
2N/A if (len > 1 && *(pname + (len - 2)) == 'p') {
2N/A conv_flag = 1;
2N/A *(pname + (len - 1)) = 0;
2N/A }
2N/A#endif
2N/A
2N/A /*
2N/A * If this is a slice desc. we need the first active solaris partition
2N/A * and if there isn't one then we need the first solaris partition.
2N/A */
2N/A if (desc->type == DM_SLICE) {
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A if (iparts[i].bootid == ACTIVE &&
2N/A (iparts[i].systid == SUNIXOS ||
2N/A iparts[i].systid == SUNIXOS2)) {
2N/A break;
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * no active solaris part.,*try to get the first solaris part.
2N/A */
2N/A if (i >= TOTAL_NUMPART) {
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A if (iparts[i].systid == SUNIXOS ||
2N/A iparts[i].systid == SUNIXOS2) {
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (i < TOTAL_NUMPART) {
2N/A /* we found a solaris partition to use */
2N/A char part_name[MAXPATHLEN];
2N/A
2N/A if (conv_flag) {
2N/A /* convert part. name (e.g. c0d0p1) */
2N/A (void) snprintf(part_name, sizeof (part_name),
2N/A "%s%d", pname, i+1);
2N/A } else {
2N/A (void) snprintf(part_name, sizeof (part_name),
2N/A "%d", i+1);
2N/A }
2N/A
2N/A /* the media name comes from the slice desc. */
2N/A partitions[0] = cache_get_desc(DM_PARTITION,
2N/A desc->p.disk, part_name, desc->secondary_name,
2N/A errp);
2N/A if (*errp != 0) {
2N/A cache_free_descriptors(partitions);
2N/A return (NULL);
2N/A }
2N/A partitions[1] = NULL;
2N/A
2N/A return (partitions);
2N/A }
2N/A
2N/A return (libdiskmgt_empty_desc_array(errp));
2N/A }
2N/A
2N/A /* Must be for media, so get all the parts. */
2N/A
2N/A pos = 0;
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A if (iparts[i].systid != UNUSED) {
2N/A char part_name[MAXPATHLEN];
2N/A
2N/A /*
2N/A * Process the descriptors and modify the cxdxpx
2N/A * format so that it refers to the fdisk partition
2N/A * number and not to the physical disk. This is
2N/A * achieved by i+1, where i is the number of the
2N/A * physical disk partition.
2N/A */
2N/A if (conv_flag) {
2N/A /* convert part. name (e.g. c0d0p1) */
2N/A (void) snprintf(part_name, sizeof (part_name),
2N/A "%s%d", pname, i+1);
2N/A } else {
2N/A (void) snprintf(part_name, sizeof (part_name),
2N/A "%d", i+1);
2N/A }
2N/A
2N/A /* the media name comes from the media desc. */
2N/A partitions[pos] = cache_get_desc(DM_PARTITION,
2N/A desc->p.disk, part_name, desc->name, errp);
2N/A if (*errp != 0) {
2N/A cache_free_descriptors(partitions);
2N/A return (NULL);
2N/A }
2N/A
2N/A pos++;
2N/A }
2N/A }
2N/A partitions[pos] = NULL;
2N/A
2N/A *errp = 0;
2N/A return (partitions);
2N/A}
2N/A
2N/Anvlist_t *
2N/Apartition_get_attributes(descriptor_t *dp, int *errp)
2N/A{
2N/A nvlist_t *attrs = NULL;
2N/A struct ipart iparts[TOTAL_NUMPART];
2N/A
2N/A if (!desc_ok(dp)) {
2N/A *errp = ENODEV;
2N/A return (NULL);
2N/A }
2N/A
2N/A if ((*errp = get_parts(dp->p.disk, iparts, NULL, 0)) != 0) {
2N/A return (NULL);
2N/A }
2N/A
2N/A if (nvlist_alloc(&attrs, NVATTRS, 0) != 0) {
2N/A *errp = ENOMEM;
2N/A return (NULL);
2N/A }
2N/A
2N/A if ((*errp = get_attrs(dp, iparts, attrs)) != 0) {
2N/A nvlist_free(attrs);
2N/A attrs = NULL;
2N/A }
2N/A
2N/A return (attrs);
2N/A}
2N/A
2N/A/*
2N/A * Look for the partition by the partition number (which is not too useful).
2N/A */
2N/Adescriptor_t *
2N/Apartition_get_descriptor_by_name(char *name, int *errp)
2N/A{
2N/A descriptor_t **partitions;
2N/A int i;
2N/A descriptor_t *partition = NULL;
2N/A
2N/A partitions = cache_get_descriptors(DM_PARTITION, errp);
2N/A if (*errp != 0) {
2N/A return (NULL);
2N/A }
2N/A
2N/A for (i = 0; partitions[i]; i++) {
2N/A if (libdiskmgt_str_eq(name, partitions[i]->name)) {
2N/A partition = partitions[i];
2N/A } else {
2N/A /* clean up the unused descriptors */
2N/A cache_free_descriptor(partitions[i]);
2N/A }
2N/A }
2N/A free(partitions);
2N/A
2N/A if (partition == NULL) {
2N/A *errp = ENODEV;
2N/A }
2N/A
2N/A return (partition);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Adescriptor_t **
2N/Apartition_get_descriptors(int filter[], int *errp)
2N/A{
2N/A return (cache_get_descriptors(DM_PARTITION, errp));
2N/A}
2N/A
2N/Achar *
2N/Apartition_get_name(descriptor_t *desc)
2N/A{
2N/A return (desc->name);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Anvlist_t *
2N/Apartition_get_stats(descriptor_t *dp, int stat_type, int *errp)
2N/A{
2N/A /* There are no stat types defined for partitions */
2N/A *errp = EINVAL;
2N/A return (NULL);
2N/A}
2N/A
2N/A/* ARGSUSED */
2N/Aint
2N/Apartition_has_fdisk(disk_t *dp, int fd)
2N/A{
2N/A char bootsect[512 * 3]; /* 3 sectors to be safe */
2N/A
2N/A#ifdef sparc
2N/A if (dp->drv_type == DM_DT_FIXED) {
2N/A /* on sparc, only removable media can have fdisk parts. */
2N/A return (0);
2N/A }
2N/A#endif
2N/A
2N/A /*
2N/A * We assume the caller already made sure media was inserted and
2N/A * spun up.
2N/A */
2N/A
2N/A if ((ioctl(fd, DKIOCGMBOOT, bootsect) < 0) && (errno != ENOTTY)) {
2N/A return (0);
2N/A }
2N/A
2N/A return (1);
2N/A}
2N/A
2N/A/*
2N/A * partition_make_descriptors
2N/A *
2N/A * A partition descriptor points to a disk, the name is the partition number
2N/A * and the secondary name is the media name. The iparts parameter returned
2N/A * by the get_parts function contains the structures of all of the identified
2N/A * partitions found on each disk on a system. These are processed into an array
2N/A * of descriptors. A descriptor contains all of the information about a
2N/A * specific partition.
2N/A *
2N/A * Parameters: none
2N/A *
2N/A * Returns: 0 on success
2N/A * Error value on failure
2N/A *
2N/A */
2N/A
2N/Aint
2N/Apartition_make_descriptors()
2N/A{
2N/A disk_t *dp;
2N/A int error = 0;
2N/A int locked;
2N/A
2N/A cache_rlock(&locked);
2N/A dp = cache_get_disklist();
2N/A while ((error == 0) && (dp != NULL)) {
2N/A struct ipart iparts[TOTAL_NUMPART];
2N/A char pname[MAXPATHLEN];
2N/A
2N/A if (get_parts(dp, iparts, pname, sizeof (pname)) == 0) {
2N/A int i;
2N/A char mname[MAXPATHLEN];
2N/A int conv_flag = 0;
2N/A#if defined(i386) || defined(__amd64)
2N/A /* convert part. name (e.g. c0d0p1) */
2N/A int len;
2N/A
2N/A len = strlen(pname);
2N/A if (len > 1 && *(pname + (len - 2)) == 'p') {
2N/A conv_flag = 1;
2N/A *(pname + (len - 1)) = 0;
2N/A }
2N/A#endif
2N/A
2N/A mname[0] = 0;
2N/A (void) media_read_name(dp, mname, sizeof (mname));
2N/A
2N/A /*
2N/A * Process the descriptors and modify the cxdxpx
2N/A * format so that it refers to the fdisk partition
2N/A * number and not to the physical disk. This is
2N/A * achieved by i+1, where i is the number of the
2N/A * physical disk partition.
2N/A */
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A if (iparts[i].systid != UNUSED) {
2N/A char part_name[MAXPATHLEN];
2N/A
2N/A if (conv_flag) {
2N/A /*
2N/A * convert partition name
2N/A * (e.g. c0d0p1)
2N/A */
2N/A (void) snprintf(part_name,
2N/A sizeof (part_name),
2N/A "%s%d", pname, i+1);
2N/A } else {
2N/A (void) snprintf(part_name,
2N/A sizeof (part_name),
2N/A "%d", i+1);
2N/A }
2N/A
2N/A cache_load_desc(DM_PARTITION, dp,
2N/A part_name, mname, &error);
2N/A if (error != 0)
2N/A break;
2N/A }
2N/A }
2N/A }
2N/A dp = dp->next;
2N/A }
2N/A cache_unlock(&locked);
2N/A
2N/A return (error);
2N/A}
2N/A
2N/Astatic int
2N/Aget_attrs(descriptor_t *dp, struct ipart *iparts, nvlist_t *attrs)
2N/A{
2N/A char *p;
2N/A int part_num;
2N/A
2N/A /*
2N/A * We already made sure the media was loaded and ready in the
2N/A * get_parts call within partition_get_attributes.
2N/A */
2N/A
2N/A p = strrchr(dp->name, 'p');
2N/A if (p == NULL) {
2N/A p = dp->name;
2N/A } else {
2N/A p++;
2N/A }
2N/A part_num = atoi(p);
2N/A if (part_num > TOTAL_NUMPART ||
2N/A iparts[part_num - 1].systid == UNUSED) {
2N/A return (ENODEV);
2N/A }
2N/A
2N/A /*
2N/A * A partition has been found. Determine what type of
2N/A * partition it is: logical, extended, or primary.
2N/A * Collect the information for the partition.
2N/A */
2N/A#if defined(i386) || defined(__amd64)
2N/A if (part_num > FD_NUMPART) {
2N/A if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
2N/A DM_LOGICAL) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A } else if (fdisk_is_dos_extended(iparts[part_num - 1].systid)) {
2N/A if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
2N/A DM_EXTENDED) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A } else {
2N/A if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
2N/A DM_PRIMARY) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A }
2N/A#endif
2N/A
2N/A#ifdef sparc
2N/A if (nvlist_add_uint32(attrs, DM_PARTITION_TYPE,
2N/A DM_PRIMARY) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A#endif
2N/A
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_BOOTID,
2N/A (unsigned int)iparts[part_num - 1].bootid) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_PTYPE,
2N/A (unsigned int)iparts[part_num - 1].systid) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_BHEAD,
2N/A (unsigned int)iparts[part_num - 1].beghead) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_BSECT,
2N/A (unsigned int)((iparts[part_num - 1].begsect) & 0x3f)) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_BCYL, (unsigned int)
2N/A ((iparts[part_num - 1].begcyl & 0xff) |
2N/A ((iparts[part_num - 1].begsect & 0xc0) << 2))) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_EHEAD,
2N/A (unsigned int)iparts[part_num - 1].endhead) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_ESECT,
2N/A (unsigned int)((iparts[part_num - 1].endsect) & 0x3f)) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_ECYL, (unsigned int)
2N/A ((iparts[part_num - 1].endcyl & 0xff) |
2N/A ((iparts[part_num - 1].endsect & 0xc0) << 2))) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_RELSECT,
2N/A (unsigned int)iparts[part_num - 1].relsect) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A if (nvlist_add_uint32(attrs, DM_NSECTORS,
2N/A (unsigned int)iparts[part_num - 1].numsect) != 0) {
2N/A return (ENOMEM);
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/*
2N/A * get_parts
2N/A * Discovers the primary, extended, and logical partitions that have
2N/A * been created on a disk. get_parts loops through the partitions,
2N/A * collects the information on each partition and stores it in a
2N/A * partition table.
2N/A *
2N/A * Parameters;
2N/A * disk -The disk device to be evaluated for partitions
2N/A * iparts -The structure that holds information about
2N/A * the partitions
2N/A * opath -The device path
2N/A * opath_len -Buffer size used with opath
2N/A * Returns:
2N/A * 0 on Successful completion
2N/A * Error Value on failure
2N/A *
2N/A */
2N/Astatic int
2N/Aget_parts(disk_t *disk, struct ipart *iparts, char *opath, int opath_len)
2N/A{
2N/A int fd;
2N/A struct dk_minfo minfo;
2N/A struct mboot bootblk;
2N/A char bootsect[512];
2N/A int i;
2N/A
2N/A#if defined(i386) || defined(__amd64)
2N/A int j, ret;
2N/A ext_part_t *epp; /* extended partition structure */
2N/A char *device; /* name of fixed disk drive */
2N/A size_t len;
2N/A logical_drive_t *log_drv; /* logical drive structure */
2N/A uint64_t tmpsect;
2N/A#endif
2N/A
2N/A /* Can't use drive_open_disk since we need the partition dev name. */
2N/A if ((fd = open_disk(disk, opath, opath_len)) < 0) {
2N/A return (ENODEV);
2N/A }
2N/A
2N/A /* First make sure media is inserted and spun up. */
2N/A if (!media_read_info(fd, &minfo)) {
2N/A (void) close(fd);
2N/A return (ENODEV);
2N/A }
2N/A
2N/A if (!partition_has_fdisk(disk, fd)) {
2N/A (void) close(fd);
2N/A return (ENOTTY);
2N/A }
2N/A
2N/A if (lseek(fd, 0, 0) == -1) {
2N/A (void) close(fd);
2N/A return (ENODEV);
2N/A }
2N/A
2N/A if (read(fd, bootsect, 512) != 512) {
2N/A (void) close(fd);
2N/A return (ENODEV);
2N/A }
2N/A (void) close(fd);
2N/A
2N/A (void) memcpy(&bootblk, bootsect, sizeof (bootblk));
2N/A
2N/A if (les(bootblk.signature) != MBB_MAGIC) {
2N/A return (ENOTTY);
2N/A }
2N/A
2N/A /*
2N/A * Initialize the memory space to clear unknown garbage
2N/A * that might create confusing results.
2N/A */
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A (void) memset(&iparts[i], 0, sizeof (struct ipart));
2N/A iparts[i].systid = UNUSED;
2N/A }
2N/A
2N/A (void) memcpy(iparts, bootblk.parts, ISIZE);
2N/A
2N/A /*
2N/A * Check to see if a valid partition exists. If a valid partition
2N/A * exists, check to see if it is an extended partition.
2N/A * If an extended partition exists, collect the logical partition
2N/A * data.
2N/A */
2N/A for (i = 0; i < FD_NUMPART; i++) {
2N/A if (iparts[i].systid == UNUSED)
2N/A continue;
2N/A
2N/A iparts[i].relsect = lel(iparts[i].relsect);
2N/A iparts[i].numsect = lel(iparts[i].numsect);
2N/A
2N/A#if defined(i386) || defined(__amd64)
2N/A if (!fdisk_is_dos_extended(iparts[i].systid))
2N/A continue;
2N/A
2N/A len = strlen(disk->aliases->alias_cxtydz) + 1;
2N/A if ((device = malloc(len)) == NULL)
2N/A continue;
2N/A
2N/A (void) snprintf(device, len, "%s",
2N/A disk->aliases->alias_cxtydz);
2N/A
2N/A if ((ret = libfdisk_init(&epp, device, &iparts[i],
2N/A FDISK_READ_DISK)) != FDISK_SUCCESS) {
2N/A
2N/A switch (ret) {
2N/A /*
2N/A * The first 2 error cases indicate that
2N/A * there is no Solaris logical partition,
2N/A * which is a valid condition,
2N/A * so iterating through the disk continues.
2N/A * Any other error cases indicate there is
2N/A * a potential problem with the disk, so
2N/A * don't continue iterating through the disk
2N/A * and return an error.
2N/A */
2N/A case FDISK_EBADLOGDRIVE:
2N/A case FDISK_ENOLOGDRIVE:
2N/A free(device);
2N/A libfdisk_fini(&epp);
2N/A continue;
2N/A case FDISK_EBADMAGIC:
2N/A free(device);
2N/A libfdisk_fini(&epp);
2N/A return (ENOTTY);
2N/A default:
2N/A free(device);
2N/A libfdisk_fini(&epp);
2N/A return (ENODEV);
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * Collect logical drive information
2N/A */
2N/A for (log_drv = fdisk_get_ld_head(epp), j = FD_NUMPART,
2N/A tmpsect = 0; (j < TOTAL_NUMPART) && (log_drv != NULL);
2N/A log_drv = log_drv->next, j++) {
2N/A iparts[j].bootid = log_drv->parts[0].bootid;
2N/A iparts[j].beghead = log_drv->parts[0].beghead;
2N/A iparts[j].begsect = log_drv->parts[0].begsect;
2N/A iparts[j].begcyl = log_drv->parts[0].begcyl;
2N/A iparts[j].systid = log_drv->parts[0].systid;
2N/A iparts[j].endhead = log_drv->parts[0].endhead;
2N/A iparts[j].endsect = log_drv->parts[0].endsect;
2N/A iparts[j].endcyl = log_drv->parts[0].endcyl;
2N/A iparts[j].relsect = (tmpsect +
2N/A lel(log_drv->parts[0].relsect) + epp->ext_beg_sec);
2N/A iparts[j].numsect = lel(log_drv->parts[0].numsect);
2N/A tmpsect = lel(log_drv->parts[1].relsect);
2N/A }
2N/A
2N/A /* free the device and the epp memory. */
2N/A free(device);
2N/A libfdisk_fini(&epp);
2N/A#endif
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/A/* return 1 if the partition descriptor is still valid, 0 if not. */
2N/Astatic int
2N/Adesc_ok(descriptor_t *dp)
2N/A{
2N/A /* First verify the media name for removable media */
2N/A if (dp->p.disk->removable) {
2N/A char mname[MAXPATHLEN];
2N/A
2N/A if (!media_read_name(dp->p.disk, mname, sizeof (mname))) {
2N/A return (0);
2N/A }
2N/A
2N/A if (mname[0] == 0) {
2N/A return (libdiskmgt_str_eq(dp->secondary_name, NULL));
2N/A } else {
2N/A return (libdiskmgt_str_eq(dp->secondary_name, mname));
2N/A }
2N/A }
2N/A
2N/A /*
2N/A * We could verify the partition is still there but this is kind of
2N/A * expensive and other code down the line will do that (e.g. see
2N/A * get_attrs).
2N/A */
2N/A
2N/A return (1);
2N/A}
2N/A
2N/A/*
2N/A * Return 1 if partition has slices, 0 if not.
2N/A */
2N/Astatic int
2N/Ahas_slices(descriptor_t *desc, int *errp)
2N/A{
2N/A int pnum;
2N/A int i;
2N/A char *p;
2N/A struct ipart iparts[TOTAL_NUMPART];
2N/A
2N/A if (get_parts(desc->p.disk, iparts, NULL, 0) != 0) {
2N/A *errp = ENODEV;
2N/A return (0);
2N/A }
2N/A
2N/A p = strrchr(desc->name, 'p');
2N/A if (p == NULL) {
2N/A p = desc->name;
2N/A } else {
2N/A p++;
2N/A }
2N/A pnum = atoi(p);
2N/A
2N/A /*
2N/A * Slices are associated with the active solaris partition or if there
2N/A * is no active solaris partition, then the first solaris partition.
2N/A */
2N/A
2N/A *errp = 0;
2N/A if (iparts[pnum].bootid == ACTIVE &&
2N/A (iparts[pnum].systid == SUNIXOS ||
2N/A iparts[pnum].systid == SUNIXOS2)) {
2N/A return (1);
2N/A } else {
2N/A int active = 0;
2N/A
2N/A /* Check if there are no active solaris partitions. */
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A if (iparts[i].bootid == ACTIVE &&
2N/A (iparts[i].systid == SUNIXOS ||
2N/A iparts[i].systid == SUNIXOS2)) {
2N/A active = 1;
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (!active) {
2N/A /* Check if this is the first solaris partition. */
2N/A for (i = 0; i < TOTAL_NUMPART; i++) {
2N/A if (iparts[i].systid == SUNIXOS ||
2N/A iparts[i].systid == SUNIXOS2) {
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (i < TOTAL_NUMPART && i == pnum) {
2N/A return (1);
2N/A }
2N/A }
2N/A }
2N/A
2N/A return (0);
2N/A}
2N/A
2N/Astatic int
2N/Aopen_disk(disk_t *diskp, char *opath, int len)
2N/A{
2N/A /*
2N/A * Just open the first devpath.
2N/A */
2N/A if (diskp->aliases != NULL && diskp->aliases->devpaths != NULL) {
2N/A#ifdef sparc
2N/A if (opath != NULL) {
2N/A (void) strlcpy(opath, diskp->aliases->devpaths->devpath, len);
2N/A }
2N/A return (open(diskp->aliases->devpaths->devpath, O_RDONLY|O_NDELAY));
2N/A#else
2N/A /* On intel we need to open partition device (e.g. c0d0p1). */
2N/A char part_dev[MAXPATHLEN];
2N/A char *p;
2N/A
2N/A (void) strlcpy(part_dev, diskp->aliases->devpaths->devpath,
2N/A sizeof (part_dev));
2N/A p = strrchr(part_dev, '/');
2N/A if (p == NULL) {
2N/A p = strrchr(part_dev, 's');
2N/A if (p != NULL) {
2N/A *p = 'p';
2N/A }
2N/A } else {
2N/A char *ps;
2N/A
2N/A *p = 0;
2N/A ps = strrchr((p + 1), 's');
2N/A if (ps != NULL) {
2N/A *ps = 'p';
2N/A }
2N/A *p = '/';
2N/A }
2N/A
2N/A if (opath != NULL) {
2N/A (void) strlcpy(opath, part_dev, len);
2N/A }
2N/A return (open(part_dev, O_RDONLY|O_NDELAY));
2N/A#endif
2N/A }
2N/A
2N/A return (-1);
2N/A}