usr/src/lib/liborchestrator/disk_info.c
author Alasdair Lumsden <al@everycity.co.uk>
Sat, 10 Sep 2011 02:50:50 +0000
branchoi_151a
changeset 1430 398513b48d4c
parent 679 2f04e6d1a235
permissions -rw-r--r--
1490 oi_151a installer Territory dropdown contains blank entries

/*
 * 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 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */


#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include "orchestrator_private.h"

/*
 * Local functions
 */
static boolean_t copy_disk_info_data(disk_info_t *dest, disk_info_t *src);

/*
 * om_get_disk_info
 * This function will return the disk information of the discovered disks.
 * Input:	om_handle_t handle - The handle returned by
 *		om_initiate_target_discovery()
 * Output:	int * total - Total number of disks returned.
 * Return:	The disk information will be returned as a pointer to
 *		disk_info_t. The space will be allocated by this function.
 *		NULL, if the disk data can't be returned.
 */
/*ARGSUSED*/
disk_info_t *
om_get_disk_info(om_handle_t handle, int *total)
{
	int		i;
	disk_target_t	*dt;
	disk_info_t	*di;
	disk_info_t	*disks;
	disk_info_t	*tmpdi;

	om_errno = 0;

	/*
	 * If the target discovery is not yet completed, set the
	 * error number and return NULL
	 */
	if (!disk_discovery_done) {
		om_set_error(OM_DISCOVERY_NEEDED);
		return (NULL);
	}

	if (system_disks  == NULL) {
		om_set_error(OM_NO_DISKS_FOUND);
		return (NULL);
	}

	tmpdi = NULL;
	disks = NULL;
	dt = system_disks;
	/*
	 * Copy the disk information from the orchestrator cache
	 */
	for (i = 0; (i < disks_total) && (dt != NULL); i++) {
		di = (disk_info_t *)calloc(1, sizeof (disk_info_t));
		if (di == NULL) {
			om_set_error(OM_NO_SPACE);
			return (NULL);
		}

		/*
		 * Copy only the diskinfo portion from the Disk Target
		 * The Partition Information is provided once a disk is
		 * selected.
		 */
		if (!copy_disk_info_data(di, &dt->dinfo)) {
			om_set_error(OM_NO_SPACE);
			free(di);
			om_free_disk_info(handle, disks);
			return (NULL);
		}

		dt = dt->next;
		/*
		 * Link the node to the end of the diskinfo list
		 */
		if (tmpdi == NULL) {
			tmpdi = di;
			disks = tmpdi;
		} else {
			tmpdi->next = di;
			tmpdi = tmpdi->next;
		}
	}

	if (i != disks_total) {
		/* Log the information that we can't find all disks */
		disks_found = i;
	}

	*total = disks_total;
	return (disks);
}

/*
 * om_free_disk_info
 * This function will free up the disk information data allocated during
 * om_get_disk_info().
 * Input:	om_handle_t handle - The handle returned by
 *		om_initiate_target_discovery()
 *		disk_info_t *dinfo - The pointer to disk_info_t. Usually
 *		returned by om_get_disk_info().
 * Output:	None.
 * Return:	None.
 */
/*ARGSUSED*/
void
om_free_disk_info(om_handle_t handle, disk_info_t *dinfo)
{
	boolean_t	follow_link = B_TRUE;

	om_errno = 0;
	if (dinfo == NULL) {
		return;
	}

	/*
	 * Traverse through link and delete all disk info
	 * if follow_link is set to true.
	 */
	local_free_disk_info(dinfo, follow_link);
}

/*
 * om_duplicate_disk_info
 * This function will allocate space and copy the disk_info_t structure
 * passed as a parameter.
 * Input:	om_handle_t handle - The handle returned by
 *		om_initiate_target_discovery()
 * 		disk_info_t * - Pointer to disk_info_t. Usually the return
 *		value from get_disk_info().
 * Return:	disk_info_t * - Pointer to disk_info_t. Space will be
 *		allocated and the data is copied and returned.
 *		NULL, if space cannot be allocated.
 */
/*ARGSUSED*/
disk_info_t *
om_duplicate_disk_info(om_handle_t handle, disk_info_t *dinfo)
{
	disk_info_t	*di;
	disk_info_t	*dip;
	disk_info_t	*disks;
	disk_info_t	*tmpdi;

	om_errno = 0;

	if (dinfo == NULL) {
		om_set_error(OM_BAD_INPUT);
		return (NULL);
	}

	disks = NULL;
	tmpdi = NULL;
	/*
	 * Allocate space and copy
	 */
	for (dip = dinfo; dip != NULL; dip = dip->next) {
		di = (disk_info_t *)calloc(1, sizeof (disk_info_t));
		if (di == NULL) {
			om_set_error(OM_NO_SPACE);
			om_free_disk_info(handle, disks);
			return (NULL);
		}

		if (!copy_disk_info_data(di, dip)) {
			om_set_error(OM_NO_SPACE);
			free(di);
			om_free_disk_info(handle, disks);
			return (NULL);
		}

		/*
		 * Add the new element to the end of the linked list.
		 * Create the linked list if there are no elements.
		 */
		if (tmpdi == NULL) {
			tmpdi = di;
			disks = tmpdi;
		} else {
			tmpdi->next = di;
			tmpdi = tmpdi->next;
		}
	}
	return (disks);
}

/*
 * om_convert_linked_disk_info_to_array
 * This function converts the linked list of disks represented in disk_info_t to
 * an array of pointers so that each pointer will be pointed to the disk_info_t
 * of each disk.
 * Input:	disk_info_t * - The disk infomation structure represented by
 *		linked list of disk_info_t. It is the usually the value
 *		returned by om_get_disk_info().
 * 		int total - Total number of disks returned.
 * Return:	A array of pointers to disk_info_t
 */
/*ARGSUSED*/
disk_info_t **
om_convert_linked_disk_info_to_array(om_handle_t handle,
	disk_info_t *dinfo, int total)
{
	int		i = 0;
	disk_info_t	*di;
	disk_info_t	**di_array;

	om_errno = 0;

	if (dinfo  == NULL) {
		om_set_error(OM_BAD_INPUT);
		return (NULL);
	}

	/*
	 * Allocate an array of pointers so that each disk_info_t
	 * can be assigned to each element of the array
	 */
	di_array = (disk_info_t **)calloc(total, sizeof (disk_info_t *));
	if (di_array == NULL) {
		om_set_error(OM_NO_SPACE);
		return (NULL);
	}

	/*
	 * Assign each disk_info_t to an element of array of pointers
	 */
	for (i = 0, di = dinfo; di != NULL; di = di->next, i++) {
		di_array[i] = di;
	}

	return (di_array);
}

/*
 * om_free_disk_info_array
 * This function will free up the disk array allocated by
 * om_convert_linked_disk_info_to_array()
 * Input:	om_handle_t handle - The handle returned by
 *		om_initiate_target_discovery()
 *		disk_info_t **dinfo - The pointer to array of disk_info_t.
 *		Usually returned by om_convert_linked_disk_info_to_array().
 * Output:	None.
 * Return:	None.
 */
/*ARGSUSED*/
void
om_free_disk_info_array(om_handle_t handle, disk_info_t **di_array)
{
	if (di_array == NULL || *di_array == NULL) {
		return;
	}

	free(di_array);
}

/*
 * copy_disk_info_data
 * This function copies all the disk info data from source to destination
 */
/*ARGSUSED*/
static boolean_t
copy_disk_info_data(disk_info_t *dest, disk_info_t *src)
{
	if (src->disk_name) {
		dest->disk_name = strdup(src->disk_name);
	}

	if (src->disk_volname) {
		dest->disk_volname = strdup(src->disk_volname);
	}
	if (src->disk_devid) {
		dest->disk_devid = strdup(src->disk_devid);
	}
	if (src->disk_device_path) {
		dest->disk_device_path = strdup(src->disk_device_path);
	}

	dest->disk_size = src->disk_size;
	dest->disk_size_total =  src->disk_size_total;
	dest->disk_type = src->disk_type;
	if (src->vendor) {
		dest->vendor = strdup(src->vendor);
	}
	dest->boot_disk = src->boot_disk;
	dest->label = src->label;
	dest->removable = src->removable;
	if (src->serial_number) {
		dest->serial_number = strdup(src->serial_number);
	}

	/*
	 * Check whether any of the strdup call failed
	 */
	if (dest->disk_name == NULL || dest->vendor == NULL ||
	    dest->serial_number == NULL || dest->disk_devid == NULL ||
	    dest->disk_device_path == NULL) {
		free(dest->disk_name);
		free(dest->disk_volname);
		free(dest->disk_devid);
		free(dest->disk_device_path);
		free(dest->vendor);
		free(dest->serial_number);
		return (B_FALSE);
	}
	dest->next = NULL;
	return (B_TRUE);
}

/*
 * om_get_boot_disk
 *
 * Searches linked list of discovered disks for boot disk. It assumes that
 * target discovery was done.
 *
 * Input:	disk_list - linked list of discvovered disks
 *
 * Return:	NULL if boot disk was not found, otherwise pointer to
 *		boot disk disk_info_t structure
 */
disk_info_t *
om_get_boot_disk(disk_info_t *disk_list)
{
	disk_info_t	*di;

	/* Walk through the list of disks and search for boot disk */

	for (di = disk_list; di != NULL; di = di->next) {
		if (di->boot_disk)
			break;
	}

	return (di);
}

/*
 * om_find_disk_by_ctd_name
 *
 * Searches linked list of discovered disks for disk with given c#t#d# name.
 * It assumes that target discovery was done.
 *
 * Input:	disk_list - linked list of discvovered disks
 *
 * Return:	NULL if disk was not found, otherwise pointer to
 *		disk disk_info_t structure
 */
disk_info_t *
om_find_disk_by_ctd_name(disk_info_t *disk_list, char *ctd_name)
{
	disk_info_t	*di;

	/* Walk through the list of disks and search for required disk */

	for (di = disk_list; di != NULL; di = di->next) {
		if (strcmp(di->disk_name, ctd_name) == 0)
			break;
	}

	return (di);
}