Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <libgen.h>
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <sys/nvpair.h>
     30 #include <door.h>
     31 #include <fcntl.h>
     32 
     33 #include "mms_mgmt.h"
     34 #include "mgmt_acsls.h"
     35 #include "mmp_defs.h"
     36 #include "mgmt_media.h"
     37 #include "mgmt_sym.h"
     38 #include "mgmt_util.h"
     39 
     40 static char *_SrcFile = __FILE__;
     41 #define	HERE _SrcFile, __LINE__
     42 
     43 static char *mmsmntdoor = "/var/run/mmsmnt_door";
     44 
     45 static int voltype_in_use(void *session, char *voltype);
     46 static int
     47 mgmt_show_mmvols(void *session, char *pcl, char *library, nvlist_t **vols);
     48 static int
     49 mgmt_show_partition(void *session, char *pcl, char *library, nvlist_t **parts);
     50 static int call_mmsmnt(door_arg_t *arg);
     51 
     52 static char *label_fname = "                 ";
     53 static mms_mgmt_setopt_t cartridgegrpopts[] = {
     54 	{O_NAME, "CartridgeGroupName", NULL, B_TRUE, NULL},
     55 	{NULL, NULL, NULL, B_FALSE, NULL}
     56 };
     57 #define	CGOPT_COUNT	sizeof (cartridgegrpopts) / sizeof (mms_mgmt_setopt_t)
     58 
     59 /*
     60  * Note that O_APPS (string array) is required for CartridgeGroupApplication.
     61  * Add a CGA for each application specified in the array.
     62  */
     63 static mms_mgmt_setopt_t cgappopts[] = {
     64 	{O_NAME, "CartridgeGroupName", NULL, B_TRUE, NULL},
     65 	{O_APPS, "ApplicationName", NULL, B_TRUE, NULL},
     66 	{NULL, NULL, NULL, B_FALSE, NULL}
     67 };
     68 #define	CGAOPT_COUNT	sizeof (cgappopts) / sizeof (mms_mgmt_setopt_t)
     69 
     70 /*
     71  * mms_mgmt_discover_media()
     72  *
     73  *  Finds ACSLS media, optionally filtered by library acs & lsm.
     74  *  Those already configured for use with MMS are filtered out unless
     75  *  'showall' is TRUE.
     76  *
     77  *  Required opts are:
     78  *    acshost
     79  *    acsport (if not the default)
     80  *      -- or --
     81  *    library
     82  *  If library specified, get ACS information from LIBRARY object.
     83  */
     84 int
     85 mms_mgmt_discover_media(
     86     void *session, boolean_t showall, nvlist_t *opts, mms_list_t *vol_list,
     87     nvlist_t *errs)
     88 {
     89 	int		st;
     90 	mms_acslib_t	*lsm = NULL;
     91 	mms_acslib_t	*nlsm = NULL;
     92 	mms_acscart_t	*vol = NULL;
     93 	mms_acscart_t	*nvol = NULL;
     94 	mms_list_t	lib_list;
     95 	char		*acshost = NULL;
     96 	char		*val = NULL;
     97 	char		**in_libs = NULL;
     98 	int		count = 0;
     99 	void		*sess = NULL;
    100 	void		*sessp = session;
    101 	boolean_t	found;
    102 	int		i;
    103 	char		tid[64];
    104 	char		cmd[8192];
    105 	void		*response;
    106 	nvlist_t	*volattrs = NULL;
    107 	nvlist_t	*avl = NULL;
    108 	int		ost;
    109 
    110 	if (!opts || !vol_list) {
    111 		return (MMS_MGMT_NOARG);
    112 	}
    113 
    114 	(void) memset(vol_list, 0, sizeof (mms_list_t));
    115 
    116 	/*
    117 	 * we need either the ACSLS host or one or more libraries to
    118 	 * proceed.
    119 	 */
    120 	(void) nvlist_lookup_string(opts, O_ACSHOST, &acshost);
    121 	in_libs = mgmt_var_to_array(opts, O_MMSLIB, &count);
    122 
    123 	if (!acshost && !in_libs) {
    124 		st = ENOENT;
    125 		MGMT_ADD_OPTERR(errs, O_ACSHOST, st);
    126 		MGMT_ADD_OPTERR(errs, O_MMSLIB, st);
    127 
    128 		return (st);
    129 	}
    130 
    131 	if (session == NULL) {
    132 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
    133 		if (st == 0) {
    134 			sessp = sess;
    135 		} else {
    136 			return (st);
    137 		}
    138 	}
    139 
    140 	/* get list of libs MMS knows about */
    141 	st = mms_get_library(sessp, B_FALSE, &lib_list);
    142 	if (st != 0) {
    143 		goto done;
    144 	}
    145 
    146 	if (!acshost) {
    147 		/* only supporting a single ACSLS server for V1 */
    148 		lsm = mms_list_head(&lib_list);
    149 		if (lsm == NULL) {
    150 			st = ENOENT;
    151 			MGMT_ADD_OPTERR(errs, O_ACSHOST, st);
    152 			goto done;
    153 		}
    154 		acshost = lsm->acshost;
    155 	}
    156 
    157 	if (count > 0) {
    158 		/* remove libraries not in our list */
    159 		lsm = mms_list_head(&lib_list);
    160 		while (lsm != NULL) {
    161 			nlsm = mms_list_next(&lib_list, lsm);
    162 			found = B_FALSE;
    163 
    164 			for (i = 0; i < count; i++) {
    165 				if (strcmp(in_libs[i], lsm->name) == 0) {
    166 					found = B_TRUE;
    167 					break;
    168 				}
    169 			}
    170 			if (!found) {
    171 				/* remove */
    172 				mms_list_remove(&lib_list, lsm);
    173 				free(lsm);
    174 			}
    175 			lsm = nlsm;
    176 		}
    177 	}
    178 
    179 	/* all of the volumes from the ACSLS server */
    180 	st = get_acs_volumes(acshost, NULL, vol_list);
    181 	if (st != 0) {
    182 		goto done;
    183 	}
    184 
    185 	/* weed out volumes for libraries we're not interested in */
    186 	vol = mms_list_head(vol_list);
    187 	while (vol != NULL) {
    188 		nvol = mms_list_next(vol_list, vol);
    189 		found = B_FALSE;
    190 
    191 		mms_list_foreach(&lib_list, lsm) {
    192 			if (strcmp(lsm->type, "DISK") == 0) {
    193 				continue;
    194 			}
    195 			if ((lsm->acs == vol->libacs) &&
    196 			    (lsm->lsm == vol->liblsm)) {
    197 				found = B_TRUE;
    198 				break;
    199 			}
    200 		}
    201 		if (!found) {
    202 			mms_list_remove(vol_list, vol);
    203 			free(vol);
    204 		} else {
    205 			if (lsm->name[0] != '\0') {
    206 				(void) strlcpy(vol->libname, lsm->name,
    207 				    sizeof (vol->libname));
    208 			}
    209 		}
    210 		vol = nvol;
    211 	}
    212 
    213 	/* fetch the list of cartridges MMS knows about */
    214 	(void) mms_gen_taskid(tid);
    215 
    216 	(void) snprintf(cmd, sizeof (cmd),
    217 	    "show task['%s'] reportmode[namevalue] "
    218 	    "report[CARTRIDGE.'CartridgePCL' CARTRIDGE.'CartridgeTypeName' "
    219 	    "CARTRIDGE.'LibraryName' CARTRIDGE.'CartridgeGroupName'] ", tid);
    220 
    221 	if (count > 0) {
    222 		(void) strlcat(cmd, "match [or ", sizeof (cmd));
    223 		for (i = 0; i < count; i++) {
    224 			if (in_libs[i] == NULL) {
    225 				continue;
    226 			}
    227 			(void) strlcat(cmd, "streq(LIBRARY.'LibraryName' ",
    228 			    sizeof (cmd));
    229 			(void) strlcat(cmd, "'", sizeof (cmd));
    230 			(void) strlcat(cmd, in_libs[i], sizeof (cmd));
    231 			(void) strlcat(cmd, "') ", sizeof (cmd));
    232 		}
    233 		(void) strlcat(cmd, "]", sizeof (cmd));
    234 	}
    235 	(void) strlcat(cmd, ";", sizeof (cmd));
    236 
    237 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "list volumes", &response);
    238 	if (st == 0) {
    239 		st = mmp_get_nvattrs("volid", B_TRUE, response, &volattrs);
    240 		mms_free_rsp(response);
    241 	}
    242 
    243 	if (st != 0) {
    244 		goto done;
    245 	}
    246 
    247 	/*
    248 	 * TODO:  this will break horribly if barcodes are not unique for
    249 	 * all libs.  Fix this to be more library-aware.
    250 	 */
    251 	vol = mms_list_head(vol_list);
    252 	while (vol != NULL) {
    253 		nvol = mms_list_next(vol_list, vol);
    254 
    255 		ost = nvlist_lookup_nvlist(volattrs, vol->label, &avl);
    256 		if (ost == 0) {
    257 			if (!showall) {
    258 				mms_list_remove(vol_list, vol);
    259 			} else {
    260 				ost = nvlist_lookup_string(avl,
    261 				    O_MPOOL, &val);
    262 				if (ost == 0) {
    263 					(void) strlcpy(vol->groupname, val,
    264 					    sizeof (vol->groupname));
    265 				}
    266 			}
    267 		}
    268 		vol = nvol;
    269 	}
    270 
    271 done:
    272 	mgmt_free_str_arr(in_libs, count);
    273 
    274 	if (volattrs) {
    275 		nvlist_free(volattrs);
    276 	}
    277 
    278 	free_acslib_list(&lib_list);
    279 
    280 	if (st != 0) {
    281 		mms_list_free_and_destroy(vol_list, free);
    282 		vol_list = NULL;
    283 	}
    284 
    285 	return (st);
    286 }
    287 
    288 int
    289 mms_mgmt_add_mpool(void *session, nvlist_t *nvl, nvlist_t *errs)
    290 {
    291 	int		st;
    292 	char		**varray = NULL;
    293 	int		count = 0;
    294 	int		i;
    295 
    296 	if (!nvl) {
    297 		return (MMS_MGMT_NOARG);
    298 	}
    299 
    300 	if (!mgmt_chk_auth("solaris.mms.create")) {
    301 		return (EACCES);
    302 	}
    303 
    304 	st = mms_add_object(session, "CARTRIDGEGROUP", cartridgegrpopts,
    305 	    nvl, errs);
    306 
    307 	if (st == 0) {
    308 		/* save original values */
    309 		varray = mgmt_var_to_array(nvl, O_APPS, &count);
    310 
    311 		for (i = 0; i < count; i++) {
    312 			if (!varray[i] || (strlen(varray[i]) == 0) ||
    313 			    (strcasecmp(varray[i], "none") == 0) ||
    314 			    (strcasecmp(varray[i], "all") == 0)) {
    315 				continue;
    316 			}
    317 
    318 			/* put back a single value */
    319 			(void) nvlist_add_string(nvl, O_APPS, varray[i]);
    320 			st = mms_add_object(session,
    321 			    "CARTRIDGEGROUPAPPLICATION", cgappopts, nvl, errs);
    322 			if (st != 0) {
    323 				break;
    324 			}
    325 		}
    326 
    327 		/* put back original values */
    328 		if (varray) {
    329 			(void) nvlist_add_string_array(nvl, O_APPS, varray,
    330 			    count);
    331 			mgmt_free_str_arr(varray, count);
    332 		}
    333 	}
    334 
    335 	return (st);
    336 }
    337 
    338 int
    339 mms_mgmt_modify_mpool(void *session, nvlist_t *nvl, nvlist_t *errs)
    340 {
    341 	int		st;
    342 	char		**varray = NULL;
    343 	int		count = 0;
    344 	int		i;
    345 	char		cmd[8192];
    346 	char		tid[64];
    347 	void		*sess = NULL;
    348 	void		*sessp = session;
    349 	void		*response;
    350 	char		*mpool;
    351 	nvlist_t	*cgattrs = NULL;
    352 	nvlist_t	*new = NULL;
    353 	nvpair_t	*nvp;
    354 	char		*val;
    355 	boolean_t	found;
    356 
    357 	/* get list of apps, if new list != old list, update */
    358 
    359 	if (!mgmt_chk_auth("solaris.mms.modify")) {
    360 		return (EACCES);
    361 	}
    362 
    363 	if (!nvl) {
    364 		return (MMS_MGMT_NOARG);
    365 	}
    366 
    367 	st = nvlist_lookup_string(nvl, O_NAME, &mpool);
    368 	if (st != 0) {
    369 		MGMT_ADD_OPTERR(errs, O_NAME, st);
    370 		return (st);
    371 	}
    372 
    373 	varray = mgmt_var_to_array(nvl, O_APPS, &count);
    374 	if (varray == NULL) {
    375 		/* error or nothing to do? */
    376 		return (0);
    377 	}
    378 
    379 	/* get list of already-established apps */
    380 	(void) mms_gen_taskid(tid);
    381 
    382 	(void) snprintf(cmd, sizeof (cmd),
    383 	    "show task['%s'] reportmode[namevalue] "
    384 	    "match[streq(CARTRIDGEGROUPAPPLICATION.'CartridgeGroupName' '%s')] "
    385 	    "report[CARTRIDGEGROUPAPPLICATION.'ApplicationName'];",
    386 	    tid, mpool);
    387 
    388 	if (session == NULL) {
    389 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
    390 		if (st != 0) {
    391 			goto done;
    392 		}
    393 		sessp = sess;
    394 	}
    395 
    396 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "modify cartridgegroup",
    397 	    &response);
    398 	if (st == 0) {
    399 		st = mmp_get_nvattrs("ApplicationName", B_FALSE, response,
    400 		    &cgattrs);
    401 		mms_free_rsp(response);
    402 	}
    403 	if (st != 0) {
    404 		goto done;
    405 	}
    406 
    407 	/* see if we need to add any apps */
    408 	for (i = 0; i < count; i++) {
    409 		if (!varray[i] || (strlen(varray[i]) == 0) ||
    410 		    (strcasecmp(varray[i], "none") == 0) ||
    411 		    (strcasecmp(varray[i], "all") == 0)) {
    412 			continue;
    413 		}
    414 
    415 		if (!nvlist_exists(cgattrs, varray[i])) {
    416 			if (!new) {
    417 				(void) nvlist_alloc(&new, NV_UNIQUE_NAME, 0);
    418 				(void) nvlist_add_string(new, O_NAME, mpool);
    419 			}
    420 
    421 			(void) nvlist_add_string(new, O_APPS, varray[i]);
    422 			st = mms_add_object(sessp, "CARTRIDGEGROUPAPPLICATION",
    423 			    cgappopts, new, errs);
    424 			if (st != 0) {
    425 				break;
    426 			}
    427 		}
    428 	}
    429 
    430 	/* and if we need to remove any */
    431 	nvp = NULL;
    432 	while ((nvp = nvlist_next_nvpair(cgattrs, nvp)) != NULL) {
    433 		val = nvpair_name(nvp);
    434 		if (!val) {
    435 			/* can't happen? */
    436 			continue;
    437 		}
    438 
    439 		found = B_FALSE;
    440 
    441 		for (i = 0; i < count; i++) {
    442 			if (strcmp(val, varray[i]) == 0) {
    443 				found = B_TRUE;
    444 				break;
    445 			}
    446 		}
    447 
    448 		if (found) {
    449 			continue;
    450 		}
    451 
    452 		(void) mms_gen_taskid(tid);
    453 		(void) snprintf(cmd, sizeof (cmd),
    454 		    "delete task['%s'] type[CARTRIDGEGROUPAPPLICATION] "
    455 		    "match[and "
    456 		    "(streq(CARTRIDGEGROUPAPPLICATION.'CartridgeGroupName' "
    457 		    "'%s') "
    458 		    "streq(CARTRIDGEGROUPAPPLICATION.'ApplicationName' "
    459 		    "'%s'))];",
    460 		    tid, mpool, val);
    461 
    462 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "modify cartridgegroup",
    463 		    &response);
    464 		if (st != 0) {
    465 			break;
    466 		}
    467 	}
    468 
    469 done:
    470 
    471 	if (new) {
    472 		nvlist_free(new);
    473 	}
    474 
    475 	if (cgattrs) {
    476 		nvlist_free(cgattrs);
    477 	}
    478 
    479 	mgmt_free_str_arr(varray, count);
    480 
    481 	if (sess) {
    482 		(void) mms_goodbye(sess, 0);
    483 	}
    484 
    485 	return (st);
    486 }
    487 
    488 /*
    489  * verify no cartridges 'allocated'
    490  *   force?  remove cart anyway
    491  * remove all carts
    492  * remove cartridgegroupapplications
    493  * remove cartridgegroup
    494  */
    495 int
    496 mms_mgmt_remove_mpool(void *session, char *mpool, boolean_t force,
    497     nvlist_t *errs)
    498 {
    499 	int		st;
    500 	nvlist_t	*nvl = NULL;
    501 	void		*sess = NULL;
    502 	void		*sessp = session;
    503 	void		*response;
    504 	char		tid[64];
    505 	char		cmd[8192];
    506 
    507 	if (!mpool) {
    508 		return (MMS_MGMT_NOARG);
    509 	}
    510 
    511 	if (!mgmt_chk_auth("solaris.mms.delete")) {
    512 		return (EACCES);
    513 	}
    514 
    515 	st = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
    516 	if (st != 0) {
    517 		return (st);
    518 	}
    519 
    520 	(void) nvlist_add_string(nvl, O_NAME, mpool);
    521 	(void) nvlist_add_boolean_value(nvl, O_FORCE, force);
    522 	(void) nvlist_add_string(nvl, O_VOLUMES, "*");
    523 
    524 	if (!session) {
    525 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
    526 		if (st != 0) {
    527 			nvlist_free(nvl);
    528 			return (st);
    529 		}
    530 		sessp = sess;
    531 	}
    532 
    533 	st = mms_mgmt_remove_cartridges(sessp, nvl, errs);
    534 
    535 	if (st != 0) {
    536 		goto done;
    537 	}
    538 
    539 	(void) mms_gen_taskid(tid);
    540 	(void) snprintf(cmd, sizeof (cmd),
    541 	    "delete task['%s'] type[CARTRIDGEGROUPAPPLICATION] "
    542 	    "match[streq"
    543 	    "(CARTRIDGEGROUPAPPLICATION.'CartridgeGroupName' '%s')];",
    544 	    tid, mpool);
    545 
    546 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove cartridgegroup",
    547 	    &response);
    548 	if (st != 0) {
    549 		goto done;
    550 	}
    551 
    552 	(void) mms_gen_taskid(tid);
    553 	(void) snprintf(cmd, sizeof (cmd),
    554 	    "delete task['%s'] type[CARTRIDGEGROUP] "
    555 	    "match[streq(CARTRIDGEGROUP.'CartridgeGroupName' '%s')];",
    556 	    tid, mpool);
    557 
    558 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove cartridgegroup",
    559 	    &response);
    560 	if (st != 0) {
    561 		goto done;
    562 	}
    563 
    564 done:
    565 	if (nvl) {
    566 		nvlist_free(nvl);
    567 	}
    568 
    569 	return (st);
    570 }
    571 
    572 /* ARGSUSED */
    573 int
    574 mms_mgmt_remove_dpool(void *session, char *dpool, boolean_t force,
    575     nvlist_t *errs)
    576 {
    577 	int		st;
    578 	nvlist_t	*nvl = NULL;
    579 	void		*sess = NULL;
    580 	void		*sessp = session;
    581 	void		*response;
    582 	char		tid[64];
    583 	char		cmd[8192];
    584 
    585 	if (!dpool) {
    586 		return (MMS_MGMT_NOARG);
    587 	}
    588 
    589 	if (!mgmt_chk_auth("solaris.mms.delete")) {
    590 		return (EACCES);
    591 	}
    592 
    593 	st = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
    594 	if (st != 0) {
    595 		return (st);
    596 	}
    597 
    598 	(void) nvlist_add_string(nvl, O_NAME, dpool);
    599 	(void) nvlist_add_boolean_value(nvl, O_FORCE, force);
    600 
    601 	if (!session) {
    602 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
    603 		if (st != 0) {
    604 			nvlist_free(nvl);
    605 			return (st);
    606 		}
    607 		sessp = sess;
    608 	}
    609 
    610 	(void) mms_gen_taskid(tid);
    611 	(void) snprintf(cmd, sizeof (cmd),
    612 	    "delete task['%s'] type[DRIVEGROUPAPPLICATION] "
    613 	    "match[streq"
    614 	    "(DRIVEGROUPAPPLICATION.'DriveGroupName' '%s')];",
    615 	    tid, dpool);
    616 
    617 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove drivegroup",
    618 	    &response);
    619 	if (st != 0) {
    620 		goto done;
    621 	}
    622 
    623 	(void) mms_gen_taskid(tid);
    624 	(void) snprintf(cmd, sizeof (cmd),
    625 	    "delete task['%s'] type[DRIVEGROUP] "
    626 	    "match[streq(DRIVEGROUP.'DriveGroupName' '%s')];",
    627 	    tid, dpool);
    628 
    629 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "remove drivegroup",
    630 	    &response);
    631 	if (st != 0) {
    632 		goto done;
    633 	}
    634 
    635 done:
    636 	if (nvl) {
    637 		nvlist_free(nvl);
    638 	}
    639 
    640 	return (st);
    641 }
    642 
    643 int
    644 mms_mgmt_add_cartridges(void *session, nvlist_t *nvl, nvlist_t *errs)
    645 {
    646 	int		st;
    647 	char		*mpool;
    648 	char		**volarr = NULL;
    649 	char		*libname;
    650 	char		*mtype = NULL;
    651 	int		count;
    652 	int		i;
    653 	char		tid[64];
    654 	char		cmd[8192];
    655 	void		*sess = NULL;
    656 	void		*sessp = session;
    657 	mms_list_t	lib_list;
    658 	mms_acslib_t	*lsm;
    659 	char		*volstr;
    660 	mms_list_t	vol_list;
    661 	mms_acscart_t	*vol;
    662 	size_t		len = 0;
    663 	void		*response;
    664 	nvlist_t	*cart = NULL;
    665 	char		*volxml = "</token><token>volume</token><token>";
    666 	int		st_save = 0;
    667 	char		*rwmode = "readwrite";
    668 
    669 	if (!nvl) {
    670 		return (MMS_MGMT_NOARG);
    671 	}
    672 
    673 	if (!mgmt_chk_auth("solaris.mms.media")) {
    674 		return (EACCES);
    675 	}
    676 
    677 	(void) memset(&vol_list, 0, sizeof (mms_list_t));
    678 
    679 	st = nvlist_lookup_string(nvl, O_NAME, &mpool);
    680 	if (st != 0) {
    681 		MGMT_ADD_OPTERR(errs, O_NAME, st);
    682 		return (st);
    683 	}
    684 
    685 	st = nvlist_lookup_string(nvl, O_MMSLIB, &libname);
    686 	if (st != 0) {
    687 		MGMT_ADD_OPTERR(errs, O_MMSLIB, st);
    688 		return (st);
    689 	}
    690 
    691 	st = nvlist_lookup_string(nvl, O_VOLTYPE, &mtype);
    692 	if (st != 0) {
    693 		MGMT_ADD_OPTERR(errs, O_MTYPE, st);
    694 		return (st);
    695 	}
    696 
    697 	st = nvlist_lookup_string(nvl, "readonly", &rwmode);
    698 	if (st == 0) {
    699 		if (strcmp(rwmode, "true") == 0) {
    700 			rwmode = "readonly";
    701 		} else if (strcmp(rwmode, "false") == 0) {
    702 			rwmode = "readwrite";
    703 		} else {
    704 			st = MMS_MGMT_INVALID_READONLY;
    705 			MGMT_ADD_OPTERR(errs, "readonly", st);
    706 			return (st);
    707 		}
    708 	}
    709 
    710 	volarr = mgmt_var_to_array(nvl, O_VOLUMES, &count);
    711 	if (volarr == NULL) {
    712 		st = ENOENT;
    713 		MGMT_ADD_OPTERR(errs, O_VOLUMES, st);
    714 		return (st);
    715 	}
    716 
    717 	if (session == NULL) {
    718 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
    719 		if (st != 0) {
    720 			mgmt_free_str_arr(volarr, count);
    721 			return (st);
    722 		}
    723 		sessp = sess;
    724 	}
    725 
    726 	/* get the library information */
    727 	st = mms_get_library(sessp, B_FALSE, &lib_list);
    728 	if (st != 0) {
    729 		goto done;
    730 	}
    731 
    732 	mms_list_foreach(&lib_list, lsm) {
    733 		if (strcmp(lsm->name, libname) == 0) {
    734 			break;
    735 		}
    736 	}
    737 	if (lsm == NULL) {
    738 		st = EINVAL;
    739 		MGMT_ADD_ERR(errs, O_MMSLIB, st);
    740 		goto done;
    741 	}
    742 
    743 	/* get the volume info from the ACSLS server */
    744 	for (i = 0; i < count; i++) {
    745 		len += strlen(volarr[i]) + strlen(volxml);
    746 
    747 	}
    748 	len++;	/* include trailing nul */
    749 	volstr = malloc(len);
    750 	if (volstr == NULL) {
    751 		st = ENOMEM;
    752 		goto done;
    753 	}
    754 	volstr[0] = '\0';
    755 	for (i = 0; i < count; i++) {
    756 		if (i > 0) {
    757 			(void) strlcat(volstr, volxml, len);
    758 		}
    759 		(void) strlcat(volstr, volarr[i], len);
    760 	}
    761 
    762 	st = get_acs_volumes(lsm->acshost, volstr, &vol_list);
    763 	free(volstr);
    764 
    765 	if (st != 0) {
    766 		goto done;
    767 	}
    768 
    769 	/* requested volumes don't appear in the returned list */
    770 	if (vol_list.list_size == 0) {
    771 		st = ENOENT;
    772 		for (i = 0; i < count; i++) {
    773 			if (volarr[i]) {
    774 				MGMT_ADD_ERR(errs, volarr[i], st);
    775 			}
    776 		}
    777 		goto done;
    778 	}
    779 
    780 	/* list to be used when creating PARTITIONs */
    781 	st = nvlist_alloc(&cart, NV_UNIQUE_NAME, 0);
    782 	if (st != 0) {
    783 		goto done;
    784 	}
    785 	/* pre-populate with constant values */
    786 	(void) nvlist_add_string(cart, O_MMSLIB, libname);
    787 
    788 	for (i = 0; i < count; i++) {
    789 		mms_list_foreach(&vol_list, vol) {
    790 			if (strcmp(vol->label, volarr[i]) == 0) {
    791 				break;
    792 			}
    793 		}
    794 		if (vol == NULL) {
    795 			/* should never happen */
    796 			continue;
    797 		}
    798 
    799 		(void) mms_gen_taskid(tid);
    800 		(void) snprintf(cmd, sizeof (cmd),
    801 		    "create task['%s'] type[CARTRIDGE] "
    802 		    "set[CARTRIDGE.'CartridgePCL' '%s'] "
    803 		    "set[CARTRIDGE.'CartridgeTypeName' '%s'] "
    804 		    "set[CARTRIDGE.'CartridgeGroupName' '%s'] "
    805 		    "set[CARTRIDGE.'LibraryName' '%s']; ",
    806 		    tid, vol->label, mtype, mpool, libname);
    807 
    808 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "add volume",
    809 		    &response);
    810 		if (st != 0) {
    811 			MGMT_ADD_ERR(errs, vol->label, st);
    812 			st_save = MMS_MGMT_CREATE_CART_ERR;
    813 			continue;
    814 		}
    815 		/* create the PARTITION */
    816 		(void) nvlist_add_string(cart, O_NAME, vol->label);
    817 		st = mms_mgmt_create_partition(sessp,
    818 		    vol->label, -1, libname, rwmode, errs);
    819 		if (st != 0) {
    820 			MGMT_ADD_ERR(errs, vol->label, st);
    821 			st_save = MMS_MGMT_CREATE_PART_ERR;
    822 			mms_mgmt_add_vol_cleanup(sessp, vol->label, libname);
    823 			break;
    824 		}
    825 	}
    826 
    827 done:
    828 	if (sess) {
    829 		(void) mms_goodbye(sess, 0);
    830 	}
    831 
    832 	free_acslib_list(&lib_list);
    833 	mms_list_free_and_destroy(&vol_list, free);
    834 	mgmt_free_str_arr(volarr, count);
    835 
    836 	if (cart) {
    837 		nvlist_free(cart);
    838 	}
    839 
    840 	return (st_save == 0 ? st : st_save);
    841 }
    842 
    843 int
    844 mms_mgmt_add_voltype(void *session, nvlist_t *nvl, nvlist_t *errs)
    845 {
    846 	int		st;
    847 	void		*sessp = session;
    848 	void		*sess = NULL;
    849 	void		*response = NULL;
    850 	char		tid[64];
    851 	char		cmd[8192];
    852 	nvlist_t	*stypes = NULL;
    853 	nvlist_t	*ctypes = NULL;
    854 	nvlist_t	*mnvl = NULL;
    855 	char		*in_ty = NULL;
    856 	char		*in_sz = NULL;
    857 	char		*in_media = NULL;
    858 	char		*val;
    859 
    860 	if (!nvl) {
    861 		return (MMS_MGMT_NOARG);
    862 	}
    863 
    864 	if (!mgmt_chk_auth("solaris.mms.media")) {
    865 		return (EACCES);
    866 	}
    867 
    868 	st = nvlist_lookup_string(nvl, O_NAME, &in_ty);
    869 	if (st != 0) {
    870 		MGMT_ADD_OPTERR(errs, O_NAME, st);
    871 		return (st);
    872 	}
    873 
    874 	st = nvlist_lookup_string(nvl, O_SIZE, &in_sz);
    875 	if (st != 0) {
    876 		MGMT_ADD_OPTERR(errs, O_SIZE, st);
    877 		return (st);
    878 	}
    879 
    880 	st = nvlist_lookup_string(nvl, O_MTYPE, &in_media);
    881 	if (st != 0) {
    882 		MGMT_ADD_OPTERR(errs, O_MTYPE, st);
    883 		return (st);
    884 	}
    885 
    886 	if (!sessp) {
    887 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
    888 		if (st != 0) {
    889 			return (st);
    890 		}
    891 		sessp = sess;
    892 	}
    893 
    894 	/* see if we've already got this type */
    895 	st = mms_mgmt_show_cartridge_type(sessp, in_ty, &stypes);
    896 	if (st != 0) {
    897 		goto done;
    898 	}
    899 
    900 	/* we'll get an empty list if it isn't already defined */
    901 	st = nvlist_lookup_nvlist(stypes, in_ty, &mnvl);
    902 	if (st == 0) {
    903 		/* make sure all attributes match */
    904 		val = NULL;
    905 		(void) nvlist_lookup_string(mnvl, "CartridgeTypeMediaLength",
    906 		    &val);
    907 		if ((!val) || (strcmp(val, in_sz) != 0)) {
    908 			st = EINVAL;
    909 			MGMT_ADD_OPTERR(errs, O_SIZE, st);
    910 			goto done;
    911 		}
    912 
    913 		val = NULL;
    914 		(void) nvlist_lookup_string(mnvl, "CartridgeShapeName", &val);
    915 		if ((!val) || (strcmp(val, in_media) != 0)) {
    916 			st = EINVAL;
    917 			MGMT_ADD_OPTERR(errs, O_MTYPE, st);
    918 			goto done;
    919 		}
    920 
    921 		/* all matched, nothing to do */
    922 		goto done;
    923 	}
    924 
    925 	nvlist_free(stypes);
    926 	stypes = NULL;
    927 
    928 	st = mms_mgmt_list_supported_types(sessp, &stypes);
    929 	if (st != 0) {
    930 		MGMT_ADD_ERR(errs, "internal error", st);
    931 		goto done;
    932 	}
    933 
    934 	st = nvlist_lookup_nvlist(stypes, "CARTRIDGE", &ctypes);
    935 	if (st != 0) {
    936 		MGMT_ADD_ERR(errs, "internal error", st);
    937 		goto done;
    938 	}
    939 
    940 	/* make sure requested media type is supported */
    941 	st = nvlist_lookup_nvlist(ctypes, in_media, &mnvl);
    942 	if (st != 0) {
    943 		if (st == ENOENT) {
    944 			st = EOPNOTSUPP;
    945 		}
    946 		MGMT_ADD_ERR(errs, in_media, st);
    947 		goto done;
    948 	}
    949 
    950 	/* DISK type may be any size, so set in_sz = 0 */
    951 	if (strcmp(in_media, "DISK") == 0) {
    952 		in_sz = "0";
    953 	}
    954 
    955 	/* create the new type */
    956 	(void) mms_gen_taskid(tid);
    957 	(void) snprintf(cmd, sizeof (cmd),
    958 	    "create task['%s'] type[CARTRIDGETYPE] "
    959 	    "set[CARTRIDGETYPE.'CartridgeTypeName' '%s'] "
    960 	    "set[CARTRIDGETYPE.'CartridgeTypeNumberSides' '1'] "
    961 	    "set[CARTRIDGETYPE.'CartridgeTypeMediaType' 'data'] "
    962 	    "set[CARTRIDGETYPE.'CartridgeTypeMediaLength' '%s'] "
    963 	    "set[CARTRIDGETYPE.'CartridgeShapeName' '%s'];",
    964 	    tid, in_ty, in_sz, in_media);
    965 
    966 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "create cartridge type",
    967 	    &response);
    968 
    969 done:
    970 	if (sess) {
    971 		(void) mms_goodbye(sess, 0);
    972 	}
    973 
    974 	if (stypes) {
    975 		nvlist_free(stypes);
    976 	}
    977 
    978 	return (st);
    979 }
    980 
    981 static int
    982 voltype_in_use(void *session, char *voltype)
    983 {
    984 	int		st;
    985 	void		*sessp = session;
    986 	void		*sess = NULL;
    987 	void		*response = NULL;
    988 	char		tid[64];
    989 	char		cmd[8192];
    990 	nvlist_t	*clist = NULL;
    991 
    992 	if (!voltype) {
    993 		return (MMS_MGMT_NOARG);
    994 	}
    995 
    996 	/* first, check to see if any cartridges are using this type */
    997 	(void) mms_gen_taskid(tid);
    998 	(void) snprintf(cmd, sizeof (cmd),
    999 	    "show task['%s'] reportmode[namevalue unique] "
   1000 	    "report[CARTRIDGE.'CartridgeTypeName'] "
   1001 	    "match[streq(CARTRIDGETYPE.'CartridgeTypeName' '%s')];",
   1002 	    tid, voltype);
   1003 
   1004 	if (!sessp) {
   1005 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1006 		if (st != 0) {
   1007 			return (st);
   1008 		}
   1009 		sessp = sess;
   1010 	}
   1011 
   1012 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "check voltype", &response);
   1013 	if (st == 0) {
   1014 		st = mmp_get_nvattrs("CartridgeTypeName", B_FALSE,
   1015 		    response, &clist);
   1016 		mms_free_rsp(response);
   1017 	}
   1018 
   1019 	if (st == 0) {
   1020 		if (nvlist_exists(clist, voltype)) {
   1021 			st = EBUSY;
   1022 		}
   1023 	}
   1024 
   1025 	if (sess) {
   1026 		(void) mms_goodbye(sess, 0);
   1027 	}
   1028 
   1029 	if (clist) {
   1030 		nvlist_free(clist);
   1031 	}
   1032 
   1033 	return (st);
   1034 }
   1035 
   1036 int
   1037 mms_mgmt_remove_voltype(void *session, char *voltype)
   1038 {
   1039 	int		st;
   1040 	void		*sessp = session;
   1041 	void		*sess = NULL;
   1042 	void		*response = NULL;
   1043 	char		tid[64];
   1044 	char		cmd[8192];
   1045 
   1046 	if (!voltype) {
   1047 		return (MMS_MGMT_NOARG);
   1048 	}
   1049 
   1050 	if (!mgmt_chk_auth("solaris.mms.media")) {
   1051 		return (EACCES);
   1052 	}
   1053 
   1054 	if (!sessp) {
   1055 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1056 		if (st != 0) {
   1057 			return (st);
   1058 		}
   1059 		sessp = sess;
   1060 	}
   1061 
   1062 	/* first, check to see if any cartridges are using this type */
   1063 	st = voltype_in_use(sessp, voltype);
   1064 
   1065 	if (st == 0) {
   1066 		(void) mms_gen_taskid(tid);
   1067 		(void) snprintf(cmd, sizeof (cmd),
   1068 		    "delete task['%s'] type[CARTRIDGETYPE] "
   1069 		    "match[streq(CARTRIDGETYPE.'CartridgeTypeName' '%s')];",
   1070 		    tid, voltype);
   1071 
   1072 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete voltype",
   1073 		    &response);
   1074 	}
   1075 
   1076 	if (sess) {
   1077 		(void) mms_goodbye(sess, 0);
   1078 	}
   1079 
   1080 	return (st);
   1081 }
   1082 
   1083 int
   1084 mms_mgmt_modify_voltype(void *session, nvlist_t *nvl, nvlist_t *errs)
   1085 {
   1086 	int		st;
   1087 	void		*sessp = session;
   1088 	void		*sess = NULL;
   1089 	void		*response = NULL;
   1090 	char		tid[64];
   1091 	char		cmd[8192];
   1092 	char		buf[1024];
   1093 	char		*vtype = NULL;
   1094 	char		*sz = NULL;
   1095 	char		*mtype = NULL;
   1096 
   1097 	if (!nvl) {
   1098 		return (MMS_MGMT_NOARG);
   1099 	}
   1100 
   1101 	if (!mgmt_chk_auth("solaris.mms.media")) {
   1102 		return (EACCES);
   1103 	}
   1104 
   1105 	st = nvlist_lookup_string(nvl, O_NAME, &vtype);
   1106 	if (st != 0) {
   1107 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   1108 		return (st);
   1109 	}
   1110 
   1111 	if (!sessp) {
   1112 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1113 		if (st != 0) {
   1114 			return (st);
   1115 		}
   1116 		sessp = sess;
   1117 	}
   1118 
   1119 	/* first, check to see if any cartridges are using this type */
   1120 	st = voltype_in_use(sessp, vtype);
   1121 	if (st != 0) {
   1122 		goto done;
   1123 	}
   1124 
   1125 	(void) nvlist_lookup_string(nvl, O_MTYPE, &mtype);
   1126 	(void) nvlist_lookup_string(nvl, O_SIZE, &sz);
   1127 
   1128 	if (!sz && !mtype) {
   1129 		goto done;
   1130 	}
   1131 
   1132 	(void) mms_gen_taskid(tid);
   1133 	(void) snprintf(cmd, sizeof (cmd),
   1134 	    "attribute task['%s'] type[CARTRIDGETYPE] "
   1135 	    "match[streq(CARTRIDGETYPE.'CartridgeTypeName' '%s')]",
   1136 	    tid);
   1137 
   1138 	if (sz) {
   1139 		(void) snprintf(buf, sizeof (buf),
   1140 		    " set[CARTRIDGETYPE.'CartridgeTypeMediaLength' '%s']",
   1141 		    sz);
   1142 		(void) strlcat(cmd, buf, sizeof (cmd));
   1143 	}
   1144 
   1145 	if (mtype) {
   1146 		(void) snprintf(buf, sizeof (buf),
   1147 		    "set[CARTRIDGETYPE.'CartridgeShapeName' '%s'];",
   1148 		    mtype);
   1149 		(void) strlcat(cmd, buf, sizeof (cmd));
   1150 	}
   1151 
   1152 	(void) strlcat(cmd, ";", sizeof (cmd));
   1153 
   1154 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete voltype", &response);
   1155 
   1156 done:
   1157 	if (sess) {
   1158 		(void) mms_goodbye(sess, 0);
   1159 	}
   1160 
   1161 	return (st);
   1162 }
   1163 
   1164 int
   1165 mms_mgmt_show_cartridge_type(void *session, char *voltype, nvlist_t **nvl)
   1166 {
   1167 	int		st;
   1168 	void		*sessp = session;
   1169 	void		*sess = NULL;
   1170 	void		*response = NULL;
   1171 	char		tid[64];
   1172 	char		cmd[8192];
   1173 	char		buf[1024];
   1174 
   1175 	if (!nvl) {
   1176 		return (MMS_MGMT_NOARG);
   1177 	}
   1178 
   1179 	/* if voltype is NULL, return a list of all found */
   1180 	(void) mms_gen_taskid(tid);
   1181 	(void) snprintf(cmd, sizeof (cmd),
   1182 	    "show task['%s'] reportmode[namevalue] "
   1183 	    "report[CARTRIDGETYPE]", tid);
   1184 
   1185 	if (voltype != NULL) {
   1186 		(void) snprintf(buf, sizeof (buf),
   1187 		    " match[streq (CARTRIDGETYPE.'CartridgeTypeName' '%s')]",
   1188 		    voltype);
   1189 		(void) strlcat(cmd, buf, sizeof (cmd));
   1190 	}
   1191 
   1192 	(void) strlcat(cmd, ";", sizeof (cmd));
   1193 
   1194 	if (!sessp) {
   1195 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1196 		if (st != 0) {
   1197 			return (st);
   1198 		}
   1199 		sessp = sess;
   1200 	}
   1201 
   1202 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "list cartridgetype",
   1203 	    &response);
   1204 	if (st == 0) {
   1205 		st = mmp_get_nvattrs("voltype", B_TRUE, response, nvl);
   1206 		mms_free_rsp(response);
   1207 	}
   1208 
   1209 	if (sess) {
   1210 		(void) mms_goodbye(sess, 0);
   1211 	}
   1212 
   1213 	return (st);
   1214 }
   1215 
   1216 
   1217 int
   1218 mms_mgmt_remove_cartridges(void *session, nvlist_t *nvl, nvlist_t *errs)
   1219 {
   1220 	int		st;
   1221 	char		*mpool;
   1222 	boolean_t	force = B_FALSE;
   1223 	nvlist_t	*vols = NULL;
   1224 	void		*sess = NULL;
   1225 	void		*sessp = session;
   1226 	void		*response;
   1227 	nvpair_t	*nvp;
   1228 	nvlist_t	*vlist;
   1229 	char		*val;
   1230 	char		*vname;
   1231 	boolean_t	skip = B_FALSE;
   1232 	char		tid[64];
   1233 	char		cmd[8192];
   1234 	int		skipped = 0;
   1235 	nvlist_t	*pclnv = NULL;
   1236 	char		*lib = NULL;
   1237 
   1238 	if (!mgmt_chk_auth("solaris.mms.media")) {
   1239 		return (EACCES);
   1240 	}
   1241 
   1242 	st = nvlist_lookup_string(nvl, O_NAME, &mpool);
   1243 	if (st != 0) {
   1244 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   1245 		return (st);
   1246 	}
   1247 
   1248 	if (!nvlist_exists(nvl, O_VOLUMES)) {
   1249 		/* nothing to remove */
   1250 		return (0);
   1251 	}
   1252 
   1253 	(void) nvlist_lookup_string(nvl, O_MMSLIB, &lib);
   1254 
   1255 	(void) nvlist_lookup_boolean_value(nvl, O_FORCE, &force);
   1256 
   1257 	if (!session) {
   1258 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1259 		if (st != 0) {
   1260 			return (st);
   1261 		}
   1262 		sessp = sess;
   1263 	}
   1264 
   1265 	/* tell the list function not to translate the var names */
   1266 	(void) nvlist_add_boolean_value(nvl, "cvt_mmp", B_FALSE);
   1267 
   1268 	st = mms_mgmt_list_vols(sessp, nvl, &vols);
   1269 	if (st != 0) {
   1270 		goto done;
   1271 	}
   1272 
   1273 	/* Create a temporary nvlist to store PCL & Library */
   1274 	st = nvlist_alloc(&pclnv, NV_UNIQUE_NAME, 0);
   1275 	if (st != 0) {
   1276 		goto done;
   1277 	}
   1278 	(void) nvlist_add_string(pclnv, O_MMSLIB, lib);
   1279 
   1280 	/* vols is now a list of the volumes we're supposed to remove */
   1281 	nvp = NULL;
   1282 
   1283 	while ((nvp = nvlist_next_nvpair(vols, nvp)) != NULL) {
   1284 		st = nvpair_value_nvlist(nvp, &vlist);
   1285 		if (st != 0) {
   1286 			continue;
   1287 		}
   1288 		st = nvlist_lookup_string(vlist, "CartridgePCL", &vname);
   1289 		if (st != 0) {
   1290 			continue;
   1291 		}
   1292 
   1293 		skip = B_FALSE;
   1294 
   1295 		if (!force) {
   1296 			st = nvlist_lookup_string(vlist, "CartridgeState",
   1297 			    &val);
   1298 			if (st != 0) {
   1299 				/* don't remove it if we can't tell state */
   1300 				continue;
   1301 			}
   1302 			if (strcmp(val, "allocated") == 0) {
   1303 				/* fail */
   1304 				MGMT_ADD_ERR(errs, vname, EBUSY);
   1305 				skipped++;
   1306 				skip = B_TRUE;
   1307 			}
   1308 		}
   1309 
   1310 		if (skip) {
   1311 			continue;
   1312 		}
   1313 
   1314 		(void) nvlist_add_string(pclnv, O_NAME, vname);
   1315 
   1316 		/* remove partitions and vols if necessary */
   1317 		st = mms_mgmt_remove_partition(sessp, pclnv, errs);
   1318 		if (st != 0) {
   1319 			MGMT_ADD_ERR(errs, vname, st);
   1320 			continue;
   1321 		}
   1322 
   1323 		(void) mms_gen_taskid(tid);
   1324 		(void) snprintf(cmd, sizeof (cmd),
   1325 		    "delete task['%s'] type[CARTRIDGE] "
   1326 		    "match[and (streq(CARTRIDGE.'CartridgeGroupName' '%s') "
   1327 		    "streq(CARTRIDGE.'CartridgePCL' '%s'))];",
   1328 		    tid, mpool, vname);
   1329 
   1330 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete cartridge",
   1331 		    &response);
   1332 		if (st != 0) {
   1333 			MGMT_ADD_ERR(errs, vname, st);
   1334 			continue;
   1335 		}
   1336 
   1337 		/* check for disk cartridges, remove the on-disk files if yes */
   1338 		st = nvlist_lookup_string(vlist, "CartridgeTypeName", &val);
   1339 		if (st == 0) {
   1340 			if (strcmp(val, "DISK") == 0) {
   1341 				char	*mntp = NULL;
   1342 				char	*rpath = NULL;
   1343 
   1344 				(void) nvlist_lookup_string(vlist,
   1345 				    "CartridgeMountPoint", &mntp);
   1346 				(void) nvlist_lookup_string(vlist,
   1347 				    "CartridgePath", &rpath);
   1348 				if (!mntp || !rpath) {
   1349 					MGMT_ADD_ERR(errs, "bad cartridge path",
   1350 					    ENOENT);
   1351 					continue;
   1352 				}
   1353 				(void) snprintf(cmd, sizeof (cmd), "%s/%s",
   1354 				    mntp, rpath);
   1355 				st = mgmt_delete_dkvol(cmd, errs);
   1356 				if (st != 0) {
   1357 					MGMT_ADD_ERR(errs, cmd, st);
   1358 				}
   1359 			}
   1360 		}
   1361 	}
   1362 
   1363 	if (pclnv) {
   1364 		nvlist_free(pclnv);
   1365 	}
   1366 
   1367 
   1368 done:
   1369 	if (sess) {
   1370 		(void) mms_goodbye(sess, 0);
   1371 	}
   1372 
   1373 	if (vols) {
   1374 		nvlist_free(vols);
   1375 	}
   1376 
   1377 	if ((st == 0) && skipped) {
   1378 		st = MMS_MGMT_CARTRIDGE_INUSE;
   1379 	}
   1380 
   1381 	return (st);
   1382 }
   1383 
   1384 /*
   1385  *  list by mpool, by mpool&cartridge id or all
   1386  */
   1387 int
   1388 mms_mgmt_list_vols(void *session, nvlist_t *nvl, nvlist_t **vol_list)
   1389 {
   1390 	int		st;
   1391 	char		*mpool = NULL;
   1392 	char		**volarr = NULL;
   1393 	int		count;
   1394 	char		tid[64];
   1395 	char		cmd[8192];
   1396 	void		*sess = NULL;
   1397 	void		*sessp = session;
   1398 	void		*response;
   1399 	boolean_t	all = B_TRUE;
   1400 	int		i;
   1401 	boolean_t	cvt_mmp = B_TRUE;
   1402 	char		*key = "volid";
   1403 
   1404 	if (!nvl) {
   1405 		return (MMS_MGMT_NOARG);
   1406 	}
   1407 
   1408 	(void) nvlist_lookup_string(nvl, O_NAME, &mpool);
   1409 
   1410 	st = nvlist_lookup_boolean_value(nvl, "cvt_mmp", &cvt_mmp);
   1411 	if (st == ENOENT) {
   1412 		cvt_mmp = B_TRUE;
   1413 	} else if (cvt_mmp == B_FALSE) {
   1414 		key = "CartridgePCL";
   1415 	}
   1416 	st = 0;
   1417 
   1418 	volarr = mgmt_var_to_array(nvl, O_VOLUMES, &count);
   1419 	if (volarr != NULL) {
   1420 		/* special case for all volumes */
   1421 		if (strcmp(volarr[0], "*") != 0) {
   1422 			all = B_FALSE;
   1423 		}
   1424 	}
   1425 
   1426 	if (*vol_list == NULL) {
   1427 		st = nvlist_alloc(vol_list, NV_UNIQUE_NAME, 0);
   1428 		if (st != 0) {
   1429 			goto done;
   1430 		}
   1431 
   1432 	}
   1433 
   1434 	if (!session) {
   1435 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1436 		if (st != 0) {
   1437 			return (st);
   1438 		}
   1439 		sessp = sess;
   1440 	}
   1441 
   1442 	/*
   1443 	 * get the cartridges from MMS.
   1444 	 */
   1445 	if (all) {
   1446 		(void) mms_gen_taskid(tid);
   1447 		(void) snprintf(cmd, sizeof (cmd),
   1448 		    "show task['%s'] reportmode[namevalue] "
   1449 		    "report[CARTRIDGE] ", tid);
   1450 
   1451 		if (!mpool) {
   1452 			(void) strlcat(cmd, ";", sizeof (cmd));
   1453 		} else {
   1454 			(void) strlcat(cmd,
   1455 			    "match[streq(CARTRIDGE.'CartridgeGroupName' '",
   1456 			    sizeof (cmd));
   1457 			(void) strlcat(cmd, mpool, sizeof (cmd));
   1458 			(void) strlcat(cmd, "')];", sizeof (cmd));
   1459 		}
   1460 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "show cartridges",
   1461 		    &response);
   1462 		if (st == 0) {
   1463 			st = mmp_get_nvattrs(key, cvt_mmp, response,
   1464 			    vol_list);
   1465 			mms_free_rsp(response);
   1466 		}
   1467 	} else {
   1468 		for (i = 0; i < count; i++) {
   1469 			(void) mms_gen_taskid(tid);
   1470 			(void) snprintf(cmd, sizeof (cmd),
   1471 			    "show task['%s'] reportmode[namevalue] "
   1472 			    "report[CARTRIDGE] ", tid);
   1473 
   1474 			if (mpool) {
   1475 				(void) strlcat(cmd, "match[and (streq(",
   1476 				    sizeof (cmd));
   1477 				(void) strlcat(cmd,
   1478 				    "CARTRIDGE.'CartridgeGroupName' '",
   1479 				    sizeof (cmd));
   1480 				(void) strlcat(cmd, mpool, sizeof (cmd));
   1481 				(void) strlcat(cmd, "') ", sizeof (cmd));
   1482 			}
   1483 			(void) strlcat(cmd, "streq(CARTRIDGE.'CartridgePCL' '",
   1484 			    sizeof (cmd));
   1485 			(void) strlcat(cmd, volarr[i], sizeof (cmd));
   1486 			(void) strlcat(cmd, "')", sizeof (cmd));
   1487 			if (mpool) {
   1488 				(void) strlcat(cmd, ")", sizeof (cmd));
   1489 			}
   1490 			(void) strlcat(cmd, "];", sizeof (cmd));
   1491 
   1492 			st = mms_mgmt_send_cmd(sessp, tid, cmd,
   1493 			    "show cartridges", &response);
   1494 			if (st == 0) {
   1495 				st = mmp_get_nvattrs(key, cvt_mmp,
   1496 				    response, vol_list);
   1497 				mms_free_rsp(response);
   1498 			} else {
   1499 				break;
   1500 			}
   1501 		}
   1502 	}
   1503 
   1504 	if (st == 0) {
   1505 		mgmt_filter_results(nvl, *vol_list);
   1506 	}
   1507 
   1508 done:
   1509 	if (sess) {
   1510 		(void) mms_goodbye(sess, 0);
   1511 	}
   1512 
   1513 	mgmt_free_str_arr(volarr, count);
   1514 
   1515 	return (st);
   1516 }
   1517 
   1518 int
   1519 mms_mgmt_show_dpool(void *session, nvlist_t *nvl, nvlist_t **pools)
   1520 {
   1521 	int		st;
   1522 	char		**names = NULL;
   1523 	int		count;
   1524 	char		tid[64];
   1525 	char		cmd[8192];
   1526 	char		buf[1024];
   1527 	void		*sess = NULL;
   1528 	void		*sessp = session;
   1529 	void		*response;
   1530 	int		i;
   1531 	char		*key = O_DPOOL;
   1532 	nvlist_t	*nva = NULL;
   1533 	nvpair_t	*nvp = NULL;
   1534 	char		*dpname = NULL;
   1535 
   1536 	if (!nvl || !pools) {
   1537 		return (MMS_MGMT_NOARG);
   1538 	}
   1539 
   1540 	if (!session) {
   1541 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1542 		if (st != 0) {
   1543 			return (st);
   1544 		}
   1545 		sessp = sess;
   1546 	}
   1547 
   1548 	names = mgmt_var_to_array(nvl, O_NAME, &count);
   1549 
   1550 	(void) mms_gen_taskid(tid);
   1551 	(void) snprintf(cmd, sizeof (cmd),
   1552 	    "show task['%s'] reportmode[namevalue] "
   1553 	    "report[DRIVEGROUP]",
   1554 	    tid);
   1555 
   1556 	if (count > 1) {
   1557 		(void) strlcat(cmd, "match[or(", sizeof (cmd));
   1558 	} else if (count == 1) {
   1559 		(void) strlcat(cmd, "match[", sizeof (cmd));
   1560 	}
   1561 	for (i = 0; i < count; i++) {
   1562 		(void) snprintf(buf, sizeof (buf),
   1563 		    " streq (DRIVEGROUP.'DriveGroupName' '%s')",
   1564 		    names[i]);
   1565 		(void) strlcat(cmd, buf, sizeof (cmd));
   1566 	}
   1567 	if (count > 1) {
   1568 		(void) strlcat(cmd, ")];", sizeof (cmd));
   1569 	} else if (count == 1) {
   1570 		(void) strlcat(cmd, "];", sizeof (cmd));
   1571 	} else {
   1572 		(void) strlcat(cmd, ";", sizeof (cmd));
   1573 	}
   1574 
   1575 	*pools = NULL;
   1576 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show dpool", &response);
   1577 	if (st == 0) {
   1578 		st = mmp_get_nvattrs(key, B_TRUE, response, pools);
   1579 		mms_free_rsp(response);
   1580 	}
   1581 
   1582 	if (st != 0) {
   1583 		goto done;
   1584 	}
   1585 
   1586 	while ((nvp = nvlist_next_nvpair(*pools, nvp)) != NULL) {
   1587 		st = nvpair_value_nvlist(nvp, &nva);
   1588 		if (st != 0) {
   1589 			continue;
   1590 		}
   1591 		dpname = nvpair_name(nvp);
   1592 
   1593 		(void) mms_gen_taskid(tid);
   1594 		(void) snprintf(cmd, sizeof (cmd),
   1595 		    "show task['%s'] reportmode[namevalue] "
   1596 		    "report[DRIVEGROUPAPPLICATION.'ApplicationName' ] "
   1597 		    "match[streq(DRIVEGROUP.'DriveGroupName' '%s')];",
   1598 		    tid, dpname);
   1599 
   1600 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "dpool apps",
   1601 		    &response);
   1602 		if (st == 0) {
   1603 			st = mmp_get_nvattrs_array("application", B_TRUE,
   1604 			    response, nva);
   1605 			mms_free_rsp(response);
   1606 		}
   1607 		if (st != 0) {
   1608 			continue;
   1609 		}
   1610 
   1611 		/*
   1612 		 * Get drives in this dpool
   1613 		 */
   1614 		(void) mms_gen_taskid(tid);
   1615 		(void) snprintf(cmd, sizeof (cmd),
   1616 		    "show task['%s'] reportmode[namevalue] "
   1617 		    "report[DRIVE.'DriveName' ] "
   1618 		    "match[streq(DRIVEGROUP.'DriveGroupName' '%s')];",
   1619 		    tid, dpname);
   1620 
   1621 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "dpool apps",
   1622 		    &response);
   1623 		if (st == 0) {
   1624 			st = mmp_get_nvattrs_array("drive", B_TRUE,
   1625 			    response, nva);
   1626 			mms_free_rsp(response);
   1627 		}
   1628 		if (st != 0) {
   1629 			continue;
   1630 		}
   1631 	}
   1632 
   1633 	mgmt_filter_results(nvl, *pools);
   1634 
   1635 done:
   1636 	if (sess) {
   1637 		(void) mms_goodbye(sess, 0);
   1638 	}
   1639 
   1640 	if (names) {
   1641 		mgmt_free_str_arr(names, count);
   1642 	}
   1643 
   1644 	return (st);
   1645 }
   1646 
   1647 int
   1648 mms_mgmt_show_mpool(void *session, nvlist_t *nvl, nvlist_t **pools)
   1649 {
   1650 	int		st;
   1651 	char		**names = NULL;
   1652 	int		count;
   1653 	char		tid[64];
   1654 	char		cmd[8192];
   1655 	char		buf[1024];
   1656 	void		*sess = NULL;
   1657 	void		*sessp = session;
   1658 	void		*response;
   1659 	int		i;
   1660 	char		*key = O_MPOOL;
   1661 	int		vcount = 0;
   1662 	uint64_t	poolsz = 0;
   1663 	uint64_t	vsz = 0;
   1664 	nvlist_t	*vols = NULL;
   1665 	nvlist_t	*nva = NULL;
   1666 	nvpair_t	*nvp = NULL;
   1667 	nvlist_t	*nvav = NULL;
   1668 	nvpair_t	*nvpv = NULL;
   1669 	char		*val;
   1670 
   1671 	if (!nvl || !pools) {
   1672 		return (MMS_MGMT_NOARG);
   1673 	}
   1674 
   1675 	if (!session) {
   1676 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1677 		if (st != 0) {
   1678 			return (st);
   1679 		}
   1680 		sessp = sess;
   1681 	}
   1682 
   1683 	names = mgmt_var_to_array(nvl, O_NAME, &count);
   1684 
   1685 	(void) mms_gen_taskid(tid);
   1686 	(void) snprintf(cmd, sizeof (cmd),
   1687 	    "show task['%s'] reportmode[namevalue] "
   1688 	    "report[CARTRIDGEGROUP]",
   1689 	    tid);
   1690 
   1691 	if (count > 1) {
   1692 		(void) strlcat(cmd, "match[or(", sizeof (cmd));
   1693 	} else if (count == 1) {
   1694 		(void) strlcat(cmd, "match[", sizeof (cmd));
   1695 	}
   1696 	for (i = 0; i < count; i++) {
   1697 		(void) snprintf(buf, sizeof (buf),
   1698 		    " streq (CARTRIDGEGROUP.'CartridgeGroupName' '%s')",
   1699 		    names[i]);
   1700 		(void) strlcat(cmd, buf, sizeof (cmd));
   1701 	}
   1702 	if (count > 1) {
   1703 		(void) strlcat(cmd, ")];", sizeof (cmd));
   1704 	} else if (count == 1) {
   1705 		(void) strlcat(cmd, "];", sizeof (cmd));
   1706 	} else {
   1707 		(void) strlcat(cmd, ";", sizeof (cmd));
   1708 	}
   1709 
   1710 	*pools = NULL;
   1711 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show mpool", &response);
   1712 	if (st == 0) {
   1713 		st = mmp_get_nvattrs(key, B_TRUE, response, pools);
   1714 		mms_free_rsp(response);
   1715 	}
   1716 
   1717 	if (st != 0) {
   1718 		goto done;
   1719 	}
   1720 
   1721 	while ((nvp = nvlist_next_nvpair(*pools, nvp)) != NULL) {
   1722 		st = nvpair_value_nvlist(nvp, &nva);
   1723 		if (st != 0) {
   1724 			continue;
   1725 		}
   1726 		val = nvpair_name(nvp);
   1727 
   1728 		(void) mms_gen_taskid(tid);
   1729 		(void) snprintf(cmd, sizeof (cmd),
   1730 		    "show task['%s'] reportmode[namevalue] "
   1731 		    "report[CARTRIDGE.'CartridgePCL' "
   1732 		    "CARTRIDGETYPE.'CartridgeShapeName' "
   1733 		    "CARTRIDGETYPE.'CartridgeTypeMediaLength' "
   1734 		    "PARTITION.'PartitionSize'] "
   1735 		    "match[streq(CARTRIDGEGROUP.'CartridgeGroupName' '%s')];",
   1736 		    tid, val);
   1737 
   1738 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "mpool vols",
   1739 		    &response);
   1740 		if (st == 0) {
   1741 			st = mmp_get_nvattrs("CartridgePCL", B_FALSE,
   1742 			    response, &vols);
   1743 			mms_free_rsp(response);
   1744 		}
   1745 		if (st != 0) {
   1746 			continue;
   1747 		}
   1748 
   1749 		nvpv = NULL;
   1750 		cmd[0] = '\0';
   1751 		poolsz = 0;
   1752 		vcount = 0;
   1753 
   1754 		while ((nvpv = nvlist_next_nvpair(vols, nvpv)) != NULL) {
   1755 			st = nvpair_value_nvlist(nvpv, &nvav);
   1756 			if (st != 0) {
   1757 				continue;
   1758 			}
   1759 			vcount++;
   1760 
   1761 			st = nvlist_lookup_string(nvav, "CartridgeShapeName",
   1762 			    &val);
   1763 			if (st == 0) {
   1764 				(void) snprintf(buf, sizeof (buf), "%s,", val);
   1765 				if (strstr(cmd, buf) == NULL) {
   1766 					(void) strlcat(cmd, buf, sizeof (cmd));
   1767 				}
   1768 			}
   1769 			st = nvlist_lookup_string(nvav, "PartitionSize",
   1770 			    &val);
   1771 			if (st == 0) {
   1772 				(void) do_val_mms_size(val, &vsz);
   1773 				poolsz += vsz;
   1774 			} else {
   1775 				st = nvlist_lookup_string(nvav,
   1776 				    "CartridgeTypeMediaLength", &val);
   1777 				if (st == 0) {
   1778 					(void) do_val_mms_size(val, &vsz);
   1779 					poolsz += vsz;
   1780 				}
   1781 			}
   1782 
   1783 		}
   1784 		nvlist_free(vols);
   1785 		vols = NULL;
   1786 		(void) snprintf(buf, sizeof (buf), "%lu", poolsz);
   1787 		(void) nvlist_add_string(nva, "total size", buf);
   1788 		(void) snprintf(buf, sizeof (buf), "%d", vcount);
   1789 		(void) nvlist_add_string(nva, "total volumes", buf);
   1790 		val = strrchr(cmd, ',');
   1791 		if (val != NULL) {
   1792 			*val = NULL;
   1793 		}
   1794 		(void) nvlist_add_string(nva, "voltype", cmd);
   1795 	}
   1796 
   1797 	mgmt_filter_results(nvl, *pools);
   1798 
   1799 	/* TODO:  list of cartridges + sum space used/free/avail */
   1800 
   1801 done:
   1802 	if (sess) {
   1803 		(void) mms_goodbye(sess, 0);
   1804 	}
   1805 
   1806 	if (names) {
   1807 		mgmt_free_str_arr(names, count);
   1808 	}
   1809 
   1810 	return (st);
   1811 }
   1812 
   1813 /* ARGSUSED */
   1814 int
   1815 mms_mgmt_create_partition(void *session, char *pcl, int64_t size, char *lib,
   1816     char *rwmode, nvlist_t *errs)
   1817 {
   1818 	int		st;
   1819 	void		*sess = NULL;
   1820 	void		*sessp = session;
   1821 	void		*response;
   1822 	char		tid[64];
   1823 	char		cmd[8192];
   1824 	nvlist_t	*carts = NULL;
   1825 
   1826 	if (!mgmt_chk_auth("solaris.mms.media")) {
   1827 		return (EACCES);
   1828 	}
   1829 
   1830 	if (!session) {
   1831 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1832 		if (st != 0) {
   1833 			return (st);
   1834 		}
   1835 		sessp = sess;
   1836 	}
   1837 
   1838 	if (size > 0) {
   1839 		size /= (1024 * 1024);		/* convert to mega bytes */
   1840 	}
   1841 
   1842 	(void) mms_gen_taskid(tid);
   1843 	(void) snprintf(cmd, sizeof (cmd),
   1844 	    "create task['%s'] type[PARTITION] "
   1845 	    "set[PARTITION.'PartitionName' 'part1'] "
   1846 	    "set[PARTITION.'SideName' 'side 1'] "
   1847 	    "set[PARTITION.'CartridgePCL' '%s'] "
   1848 	    "set[PARTITION.'PartitionAvailable' '%lld'] "
   1849 	    "set[PARTITION.'PartitionSize' '%lld'] "
   1850 	    "set[PARTITION.'PartitionPercentAvailable' '%d'] "
   1851 	    "set[PARTITION.'PartitionRWMode' '%s'] "
   1852 	    "set[PARTITION.'LibraryName' '%s'];",
   1853 	    tid, pcl, size, size, size == -1 ? -1 : 100, rwmode, lib);
   1854 
   1855 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "create partition", &response);
   1856 
   1857 done:
   1858 	if (sess) {
   1859 		(void) mms_goodbye(sess, 0);
   1860 	}
   1861 
   1862 	if (carts) {
   1863 		nvlist_free(carts);
   1864 	}
   1865 
   1866 	return (st);
   1867 }
   1868 
   1869 int
   1870 mms_mgmt_remove_partition(void *session, nvlist_t *nvl, nvlist_t *errs)
   1871 {
   1872 	int		st;
   1873 	void		*sess = NULL;
   1874 	void		*sessp = session;
   1875 	void		*response;
   1876 	char		tid[64];
   1877 	char		cmd[8192];
   1878 	char		*pcl = NULL;
   1879 	char		*lib = NULL;
   1880 	nvlist_t	*carts = NULL;
   1881 	nvlist_t	*vols = NULL;
   1882 
   1883 	if (!mgmt_chk_auth("solaris.mms.media")) {
   1884 		return (EACCES);
   1885 	}
   1886 
   1887 	if (!nvl) {
   1888 		return (MMS_MGMT_NOARG);
   1889 	}
   1890 
   1891 	st = nvlist_lookup_string(nvl, O_NAME, &pcl);
   1892 	if (st != 0) {
   1893 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   1894 		return (st);
   1895 	}
   1896 
   1897 	st = nvlist_lookup_string(nvl, O_MMSLIB, &lib);
   1898 	if (st != 0) {
   1899 		MGMT_ADD_OPTERR(errs, O_MMSLIB, st);
   1900 	}
   1901 
   1902 	if (!session) {
   1903 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   1904 		if (st != 0) {
   1905 			return (st);
   1906 		}
   1907 		sessp = sess;
   1908 	}
   1909 
   1910 	/* check for existing volumes */
   1911 	st = mgmt_show_mmvols(sessp, pcl, lib, &vols);
   1912 	if (st != 0) {
   1913 		goto done;
   1914 	}
   1915 
   1916 	if (vols) {
   1917 		(void) mms_gen_taskid(tid);
   1918 		(void) snprintf(cmd, sizeof (cmd),
   1919 		    "delete task['%s'] type[VOLUME] "
   1920 		    "match[and (streq(PARTITION.'CartridgePCL' '%s') "
   1921 		    "streq(PARTITION.'LibraryName' '%s'))];",
   1922 		    tid, pcl, lib);
   1923 
   1924 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete volume",
   1925 		    &response);
   1926 		if (st != 0) {
   1927 			goto done;
   1928 		}
   1929 	}
   1930 
   1931 	/* now the partitions */
   1932 	(void) mms_gen_taskid(tid);
   1933 	(void) snprintf(cmd, sizeof (cmd),
   1934 	    "delete task['%s'] type[PARTITION] "
   1935 	    "match[and (streq (PARTITION.'LibraryName' '%s') "
   1936 	    "streq(PARTITION.'CartridgePCL' '%s'))];",
   1937 	    tid, lib, pcl);
   1938 
   1939 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "delete partition",
   1940 	    &response);
   1941 
   1942 done:
   1943 	if (sess) {
   1944 		(void) mms_goodbye(sess, 0);
   1945 	}
   1946 
   1947 	if (carts) {
   1948 		nvlist_free(carts);
   1949 	}
   1950 
   1951 	if (vols) {
   1952 		nvlist_free(vols);
   1953 	}
   1954 
   1955 	return (st);
   1956 }
   1957 
   1958 int
   1959 mms_mgmt_label_multi(void *session, nvlist_t *nvl, nvlist_t *errs)
   1960 {
   1961 	int		st;
   1962 	int		rst = 0;
   1963 	void		*sess = NULL;
   1964 	void		*sessp = session;
   1965 	char		*pass = NULL;
   1966 	char		*app = NULL;
   1967 	char		*inst = NULL;
   1968 	char		**varr = NULL;
   1969 	int		count = 0;
   1970 	int		i;
   1971 
   1972 	if (!mgmt_chk_auth("solaris.mms.media")) {
   1973 		return (EACCES);
   1974 	}
   1975 
   1976 	if (!nvl) {
   1977 		return (MMS_MGMT_NOARG);
   1978 	}
   1979 
   1980 	varr = mgmt_var_to_array(nvl, O_NAME, &count);
   1981 	if (!varr) {
   1982 		st = ENOENT;
   1983 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   1984 		return (st);
   1985 	}
   1986 
   1987 	if (!session) {
   1988 		(void) nvlist_lookup_string(nvl, O_APPS, &app);
   1989 		(void) nvlist_lookup_string(nvl, "instance", &inst);
   1990 		(void) nvlist_lookup_string(nvl, O_MMPASS, &pass);
   1991 
   1992 		st = create_mm_clnt(app, inst, pass, NULL, &sess);
   1993 		if (st != 0) {
   1994 			return (st);
   1995 		}
   1996 		sessp = sess;
   1997 	}
   1998 
   1999 	for (i = 0; i < count; i++) {
   2000 		(void) nvlist_add_string(nvl, O_NAME, varr[i]);
   2001 
   2002 		st = mms_mgmt_label_vol(sessp, nvl, errs);
   2003 		if (st != 0) {
   2004 			/* save return status */
   2005 			if (rst == 0) {
   2006 				rst = st;
   2007 			}
   2008 		}
   2009 	}
   2010 
   2011 	/* set 'name' back to the way it started */
   2012 	(void) nvlist_add_string_array(nvl, O_NAME, varr, count);
   2013 
   2014 	mgmt_free_str_arr(varr, count);
   2015 
   2016 	if (sess) {
   2017 		(void) mms_goodbye(sess, 0);
   2018 	}
   2019 
   2020 	return (rst);
   2021 }
   2022 
   2023 int
   2024 mms_mgmt_label_vol(void *session, nvlist_t *nvl, nvlist_t *errs)
   2025 {
   2026 	int		st;
   2027 	void		*sess = NULL;
   2028 	void		*sessp = session;
   2029 	void		*response;
   2030 	char		tid[64];
   2031 	char		cmd[8192];
   2032 	char		buf[1024];
   2033 	char		*pcl;
   2034 	char		*lib;
   2035 	char		*app;
   2036 	char		*inst = NULL;
   2037 	char		*pass = NULL;
   2038 	nvlist_t	*attrs = NULL;
   2039 	nvlist_t	*carts = NULL;
   2040 	nvpair_t	*nva;
   2041 	boolean_t	force = B_FALSE;
   2042 	boolean_t	nomount = B_FALSE;
   2043 
   2044 	if (!mgmt_chk_auth("solaris.mms.media")) {
   2045 		return (EACCES);
   2046 	}
   2047 
   2048 	if (!nvl) {
   2049 		return (MMS_MGMT_NOARG);
   2050 	}
   2051 
   2052 	st = nvlist_lookup_string(nvl, O_NAME, &pcl);
   2053 	if (st != 0) {
   2054 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   2055 		return (st);
   2056 	}
   2057 
   2058 	st = nvlist_lookup_string(nvl, O_MMSLIB, &lib);
   2059 	if (st != 0) {
   2060 		MGMT_ADD_OPTERR(errs, O_MMSLIB, st);
   2061 		return (st);
   2062 	}
   2063 
   2064 	st = nvlist_lookup_string(nvl, O_APPS, &app);
   2065 	if (st != 0) {
   2066 		MGMT_ADD_OPTERR(errs, O_APPS, st);
   2067 		return (st);
   2068 	}
   2069 
   2070 	(void) nvlist_lookup_boolean_value(nvl, O_FORCE, &force);
   2071 
   2072 	if (!session) {
   2073 		(void) nvlist_lookup_string(nvl, "instance", &inst);
   2074 		(void) nvlist_lookup_string(nvl, O_MMPASS, &pass);
   2075 
   2076 		st = create_mm_clnt(app, inst, pass, NULL, &sess);
   2077 		if (st != 0) {
   2078 			return (st);
   2079 		}
   2080 		sessp = sess;
   2081 	}
   2082 
   2083 	/*
   2084 	 * Check if cartridge exists.
   2085 	 */
   2086 	(void) mms_gen_taskid(tid);
   2087 	(void) snprintf(cmd, sizeof (cmd),
   2088 	    "show task['%s'] reportmode[namevalue] report[CARTRIDGE] "
   2089 	    "match[and (streq(CARTRIDGE.'LibraryName' '%s') "
   2090 	    "streq(CARTRIDGE.'CartridgePCL' '%s'))];",
   2091 	    tid, lib, pcl);
   2092 
   2093 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show cartridge", &response);
   2094 	if (st == 0) {
   2095 		st = mmp_get_nvattrs("CartridgePCL", B_FALSE, response, &carts);
   2096 		mms_free_rsp(response);
   2097 	}
   2098 
   2099 	if (!nvlist_exists(carts, pcl)) {
   2100 		MGMT_ADD_OPTERR(errs, pcl, st);
   2101 		goto done;
   2102 	}
   2103 
   2104 	/* check if partition for cartridge exists.  if no, create */
   2105 	st = mgmt_show_partition(sessp, pcl, lib, &attrs);
   2106 
   2107 	if (st != 0) {
   2108 		goto done;
   2109 	}
   2110 
   2111 	if (attrs == NULL) {
   2112 		st = mms_mgmt_create_partition(sessp, pcl, -1, lib,
   2113 		    "readwrite", errs);
   2114 	} else {
   2115 		nva = nvlist_next_nvpair(attrs, NULL);
   2116 		if (nva) {
   2117 			if (nvlist_next_nvpair(attrs, nva)) {
   2118 				/* got more than 1, not supported */
   2119 				st = MMS_MGMT_ERR_PARTITION_NOT_UNIQUE;
   2120 				MGMT_ADD_ERR(errs, pcl, st);
   2121 				goto done;
   2122 			}
   2123 		}
   2124 	}
   2125 
   2126 	nvlist_free(attrs);
   2127 	attrs = NULL;
   2128 
   2129 	/* check for existing volumes */
   2130 	st = mgmt_show_mmvols(sessp, pcl, lib, &attrs);
   2131 	if (st != 0) {
   2132 		goto done;
   2133 	}
   2134 
   2135 	if (!attrs) {
   2136 		/* create a volume */
   2137 		(void) snprintf(buf, sizeof (buf), "%s_%s", lib, pcl);
   2138 		(void) mms_gen_taskid(tid);
   2139 		(void) snprintf(cmd, sizeof (cmd),
   2140 		    "allocate task['%s'] newvolname['%s'] "
   2141 		    "who['%s'] "
   2142 		    "match[and (streq(CARTRIDGE.'CartridgePCL' '%s') "
   2143 		    "streq(CARTRIDGE.'LibraryName' '%s'))];",
   2144 		    tid, buf, app, pcl, lib);
   2145 
   2146 		st = mms_mgmt_send_cmd(sessp, tid, cmd, "create volume",
   2147 		    &response);
   2148 		if (st != 0) {
   2149 			MGMT_ADD_ERR(errs, pcl, st);
   2150 			goto done;
   2151 		}
   2152 	} else if (!force) {
   2153 		st = MMS_MGMT_CARTRIDGE_INUSE;
   2154 		MGMT_ADD_ERR(errs, pcl, st);
   2155 		goto done;
   2156 	}
   2157 
   2158 	/* filename is 17 spaces - tells MM to re-init volume */
   2159 	(void) nvlist_add_string(nvl, "filename", label_fname);
   2160 
   2161 	/*
   2162 	 * If '-n' is not specified, them mount and label the cartridge
   2163 	 */
   2164 	st = nvlist_lookup_boolean_value(nvl, O_NOMOUNT, &nomount);
   2165 	if (st != 0 || nomount != B_TRUE) {
   2166 		/* ok, mount with appropriate options */
   2167 		st = mms_mgmt_mount_vol(sessp, nvl, errs);
   2168 
   2169 		if (st == 0) {
   2170 			/* label is a quick mount/unmount */
   2171 			st = mms_mgmt_unmount_vol(nvl, errs);
   2172 		}
   2173 	}
   2174 
   2175 done:
   2176 	if (sess) {
   2177 		(void) mms_goodbye(sess, 0);
   2178 	}
   2179 
   2180 	if (attrs) {
   2181 		nvlist_free(attrs);
   2182 	}
   2183 	if (carts) {
   2184 		nvlist_free(carts);
   2185 	}
   2186 
   2187 	return (st);
   2188 }
   2189 
   2190 static int
   2191 mgmt_show_partition(void *session, char *pcl, char *library, nvlist_t **parts)
   2192 {
   2193 	int		st;
   2194 	void		*sess = NULL;
   2195 	void		*sessp = session;
   2196 	void		*response;
   2197 	char		tid[64];
   2198 	char		cmd[8192];
   2199 	nvlist_t	*plist = NULL;
   2200 	nvpair_t	*nvp = NULL;
   2201 
   2202 	if (!pcl || !library || !parts) {
   2203 		return (MMS_MGMT_NOARG);
   2204 	}
   2205 
   2206 	st = nvlist_alloc(&plist, NV_UNIQUE_NAME, 0);
   2207 	if (st != 0) {
   2208 		return (st);
   2209 	}
   2210 
   2211 	if (!session) {
   2212 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   2213 		if (st != 0) {
   2214 			return (st);
   2215 		}
   2216 		sessp = sess;
   2217 	}
   2218 
   2219 	*parts = NULL;
   2220 
   2221 	(void) mms_gen_taskid(tid);
   2222 	(void) snprintf(cmd, sizeof (cmd),
   2223 	    "show task['%s'] report[PARTITION] reportmode[namevalue] "
   2224 	    "match[and (streq(PARTITION.'CartridgePCL' '%s') "
   2225 	    "streq(PARTITION.'LibraryName' '%s'))];",
   2226 	    tid, pcl, library);
   2227 
   2228 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show partition", &response);
   2229 	if (st == 0) {
   2230 		st = mmp_get_nvattrs("PartitionName", B_FALSE, response,
   2231 		    &plist);
   2232 		mms_free_rsp(response);
   2233 	}
   2234 
   2235 	if (st == 0) {
   2236 		nvp = nvlist_next_nvpair(plist, NULL);
   2237 		if (nvp) {
   2238 			*parts = plist;
   2239 		} else {
   2240 			nvlist_free(plist);
   2241 		}
   2242 	}
   2243 
   2244 	return (st);
   2245 }
   2246 
   2247 static int
   2248 mgmt_show_mmvols(void *session, char *pcl, char *library, nvlist_t **vols)
   2249 {
   2250 	int		st;
   2251 	void		*sess = NULL;
   2252 	void		*sessp = session;
   2253 	void		*response;
   2254 	char		tid[64];
   2255 	char		cmd[8192];
   2256 	nvlist_t	*vlist = NULL;
   2257 	nvpair_t	*nvp = NULL;
   2258 
   2259 	if (!pcl || !library || !vols) {
   2260 		return (MMS_MGMT_NOARG);
   2261 	}
   2262 
   2263 	st = nvlist_alloc(&vlist, NV_UNIQUE_NAME, 0);
   2264 	if (st != 0) {
   2265 		return (st);
   2266 	}
   2267 
   2268 	if (!session) {
   2269 		st = create_mm_clnt(NULL, NULL, NULL, NULL, &sess);
   2270 		if (st != 0) {
   2271 			return (st);
   2272 		}
   2273 		sessp = sess;
   2274 	}
   2275 
   2276 	(void) mms_gen_taskid(tid);
   2277 	(void) snprintf(cmd, sizeof (cmd),
   2278 	    "show task['%s'] report[VOLUME] reportmode[namevalue] "
   2279 	    "match[and (streq(PARTITION.'CartridgePCL' '%s') "
   2280 	    "streq(PARTITION.'LibraryName' '%s'))];",
   2281 	    tid, pcl, library);
   2282 
   2283 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "show volume", &response);
   2284 	if (st == 0) {
   2285 		st = mmp_get_nvattrs("VolumeName", B_FALSE, response, &vlist);
   2286 		mms_free_rsp(response);
   2287 	}
   2288 
   2289 	if (st == 0) {
   2290 		nvp = nvlist_next_nvpair(vlist, NULL);
   2291 		if (!nvp) {
   2292 			/* nothing there */
   2293 			nvlist_free(vlist);
   2294 			*vols = NULL;
   2295 		} else {
   2296 			*vols = vlist;
   2297 		}
   2298 	}
   2299 
   2300 	return (st);
   2301 }
   2302 
   2303 static int
   2304 call_mmsmnt(door_arg_t *arg)
   2305 {
   2306 	int		st;
   2307 	int		doorfd = -1;
   2308 	int		count;
   2309 	/* LINTED [warning: pointer cast may result in improper alignment] */
   2310 	mmsmnt_arg_t	*mntarg = (mmsmnt_arg_t *)arg->rbuf;
   2311 	int		saverr;
   2312 	timespec_t	sleepfor = {5, 0};	/* 5 seconds */
   2313 	char		*cmd[2];
   2314 
   2315 	if (arg == NULL) {
   2316 		return (MMS_MGMT_NOARG);
   2317 	}
   2318 
   2319 	cmd[0] = MMSSBINDIR"/mmsmnt";
   2320 	cmd[1] = NULL;
   2321 
   2322 	/* will get overwritten with correct status as appropriate */
   2323 	st = ENOTCONN;
   2324 
   2325 	/* try 5 times to get connected, then give up */
   2326 	for (count = 0; count < 5; count++) {
   2327 		doorfd = open(mmsmntdoor, O_RDWR);
   2328 		if (doorfd == -1) {
   2329 			if (errno == ENOENT) {
   2330 			/* server is not running.  Try to start it */
   2331 				(void) exec_mgmt_cmd(NULL, NULL, 0, 0, B_TRUE,
   2332 				    cmd);
   2333 				mms_trace(MMS_DEBUG,
   2334 				    "exec_mgmt_cmd: %s", cmd[0]);
   2335 			} else {
   2336 				st = errno;
   2337 				return (st);
   2338 			}
   2339 		}
   2340 
   2341 		/*
   2342 		 * try to contact the server - if door_call successful,
   2343 		 * status will be set by the server
   2344 		 */
   2345 		st = door_call(doorfd, arg);
   2346 		saverr = errno;
   2347 
   2348 		if (st == 0) {
   2349 			/* connected ok, return error from daemon */
   2350 			st = mntarg->st;
   2351 			break;
   2352 		}
   2353 
   2354 		(void) close(doorfd);
   2355 		doorfd = -1;
   2356 
   2357 		if (saverr == EBADF) {
   2358 			/*
   2359 			 * server was not running when we opened
   2360 			 * the door file
   2361 			 */
   2362 			(void) exec_mgmt_cmd(NULL, NULL, 0, 0, B_TRUE, cmd);
   2363 			mms_trace(MMS_DEBUG, "exec_mgmt_cmd: %s", cmd[0]);
   2364 			/* give the server a chance to start */
   2365 			(void) nanosleep(&sleepfor, NULL);
   2366 		} else if ((saverr != EAGAIN) && (saverr != EINTR)) {
   2367 			/* A non-recoverable error occurred */
   2368 			st = saverr;
   2369 			mms_trace(MMS_ERR,
   2370 			    "Could not contact the mmsmnt process, %d", st);
   2371 			return (st);
   2372 		}
   2373 	}
   2374 
   2375 	if (doorfd != -1) {
   2376 		(void) close(doorfd);
   2377 	}
   2378 
   2379 	return (st);
   2380 }
   2381 
   2382 int
   2383 mms_mgmt_mount_vol(void *session, nvlist_t *nvl, nvlist_t *errs)
   2384 {
   2385 	int		st;
   2386 	void		*sess = NULL;
   2387 	void		*sessp = session;
   2388 	void		*response = NULL;
   2389 	char		tid[64];
   2390 	char		cmd[8192];
   2391 	char		mbuf[7168];
   2392 	char		buf[1024];
   2393 	char		*pcl;
   2394 	char		*lib;
   2395 	char		*mfile = NULL;
   2396 	char		*val;
   2397 	char		*app = NULL;
   2398 	char		*vname;
   2399 	nvlist_t	*attrs = NULL;
   2400 	nvpair_t	*nvp;
   2401 	nvlist_t	*nva;
   2402 	nvlist_t	*mntattrs = NULL;
   2403 	mmsmnt_arg_t	arg;
   2404 	door_arg_t	d_arg;
   2405 	int		others = 0;
   2406 	struct passwd	*pwd = NULL;
   2407 	char		*usernm = NULL;
   2408 	nvlist_t	*cattrs = NULL;
   2409 	boolean_t	isdsk = B_FALSE;
   2410 	char		**varray = NULL;
   2411 	int		count = 0;
   2412 	boolean_t	vbool = B_FALSE;
   2413 	int		i;
   2414 	char		*inst = NULL;
   2415 	char		*pass = NULL;
   2416 
   2417 	if (!mgmt_chk_auth("solaris.mms.io.read")) {
   2418 		return (EACCES);
   2419 	}
   2420 
   2421 	/* this function is unique, in that it returns the session */
   2422 	if (!nvl) {
   2423 		return (MMS_MGMT_NOARG);
   2424 	}
   2425 
   2426 	st = nvlist_lookup_string(nvl, O_NAME, &pcl);
   2427 	if (st != 0) {
   2428 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   2429 		return (st);
   2430 	}
   2431 
   2432 	st = nvlist_lookup_string(nvl, O_MMSLIB, &lib);
   2433 	if (st != 0) {
   2434 		MGMT_ADD_OPTERR(errs, O_MMSLIB, st);
   2435 		return (st);
   2436 	}
   2437 
   2438 	st = nvlist_lookup_string(nvl, O_APPS, &app);
   2439 	if (st != 0) {
   2440 		/* if not specified, see if we can mount as admin */
   2441 		if (st == ENOENT) {
   2442 			st = 0;
   2443 			app = "MMS";
   2444 			(void) nvlist_add_string(nvl, O_APPS, app);
   2445 		} else {
   2446 			MGMT_ADD_OPTERR(errs, O_APPS, st);
   2447 			return (st);
   2448 		}
   2449 	}
   2450 
   2451 	(void) nvlist_lookup_string(nvl, "filename", &mfile);
   2452 	(void) nvlist_lookup_string(nvl, "instance", &inst);
   2453 	(void) nvlist_lookup_string(nvl, O_MMPASS, &pass);
   2454 
   2455 	if (!sessp) {
   2456 		st = create_mm_clnt(app, inst, pass, NULL, &sess);
   2457 		if (st != 0) {
   2458 			return (st);
   2459 		}
   2460 		sessp = sess;
   2461 	}
   2462 
   2463 	/* check for volumes.  If one doesn't exist, fail */
   2464 	st = mgmt_show_mmvols(sessp, pcl, lib, &attrs);
   2465 	if (st == 0) {
   2466 		if (!attrs) {
   2467 			st = MMS_MGMT_VOL_NOT_INIT;
   2468 		}
   2469 	}
   2470 	if (st != 0) {
   2471 		MGMT_ADD_ERR(errs, pcl, st);
   2472 		goto done;
   2473 	}
   2474 
   2475 	nvp = NULL;
   2476 	while ((nvp = nvlist_next_nvpair(attrs, nvp)) != NULL) {
   2477 		st = nvpair_value_nvlist(nvp, &nva);
   2478 		if (st != 0) {
   2479 			goto done;
   2480 		}
   2481 		st = nvlist_lookup_string(nva, "ApplicationName", &val);
   2482 		if (st != 0) {
   2483 			continue;
   2484 		}
   2485 
   2486 		if (strcasecmp(val, app) != 0) {
   2487 			continue;
   2488 		}
   2489 
   2490 		/* found a valid volume */
   2491 		break;
   2492 	}
   2493 
   2494 	if ((st != 0) || (nvp == NULL)) {
   2495 		st = MMS_MGMT_NO_USABLE_VOL;
   2496 		MGMT_ADD_ERR(errs, pcl, st);
   2497 		goto done;
   2498 	}
   2499 
   2500 	st = nvlist_lookup_string(nva, "VolumeName", &vname);
   2501 	if (st != 0) {
   2502 		goto done;
   2503 	}
   2504 
   2505 	/* see what type of cartridge this is */
   2506 	(void) mms_gen_taskid(tid);
   2507 	(void) snprintf(cmd, sizeof (cmd),
   2508 	    "show task['%s'] report[CARTRIDGETYPE.'CartridgeShapeName'] "
   2509 	    "reportmode[namevalue] "
   2510 	    "match[and (streq(CARTRIDGE.'CartridgePCL' '%s') "
   2511 	    "streq(LIBRARY.'LibraryName' '%s'))];",
   2512 	    tid, pcl, lib);
   2513 
   2514 	st = mms_mgmt_send_cmd(sessp, tid, cmd, "get cartridge type",
   2515 	    &response);
   2516 	if (st == 0) {
   2517 		st = mmp_get_nvattrs("CartridgeShapeName", B_FALSE, response,
   2518 		    &cattrs);
   2519 		mms_free_rsp(response);
   2520 	}
   2521 	if (st == 0) {
   2522 		if (nvlist_exists(cattrs, "DISK")) {
   2523 			isdsk = B_TRUE;
   2524 		}
   2525 	}
   2526 	/* reset */
   2527 	if (cattrs) {
   2528 		nvlist_free(cattrs);
   2529 	}
   2530 	st = 0;
   2531 
   2532 	st = nvlist_lookup_string(nvl, "user", &usernm);
   2533 	if ((st != 0) || (usernm == NULL)) {
   2534 		pwd = getpwuid(getuid());
   2535 		if (pwd != NULL) {
   2536 			usernm = pwd->pw_name;
   2537 		}
   2538 		if (usernm == NULL) {
   2539 			usernm = "root";
   2540 		}
   2541 	}
   2542 
   2543 	/* at last, create the mount command */
   2544 	(void) mms_gen_taskid(tid);
   2545 	(void) snprintf(cmd, sizeof (cmd),
   2546 	    "mount task['%s'] user['%s'] type[VOLUME] "
   2547 	    "match[and (streq(LIBRARY.'LibraryName' '%s') "
   2548 	    "streq(CARTRIDGE.'CartridgePCL' '%s'))] "
   2549 	    "report[MOUNTLOGICAL] reportmode[namevalue] ",
   2550 	    tid, usernm, lib, pcl);
   2551 
   2552 	if (mfile) {
   2553 		(void) snprintf(buf, sizeof (buf), "filename['%s'] ",
   2554 		    mfile);
   2555 		(void) strlcat(cmd, buf, sizeof (cmd));
   2556 	}
   2557 
   2558 	st = nvlist_lookup_string(nvl, "blocksize", &val);
   2559 	if (st == 0) {
   2560 		(void) snprintf(buf, sizeof (buf), "blocksize['%s'] ", val);
   2561 		(void) strlcat(cmd, buf, sizeof (cmd));
   2562 	}
   2563 
   2564 	st = nvlist_lookup_boolean_value(nvl, O_NOWAIT, &vbool);
   2565 	if ((st == 0) && (vbool)) {
   2566 		(void) strlcat(cmd, "when[immediate] ", sizeof (cmd));
   2567 	} else {
   2568 		(void) strlcat(cmd, "when[blocking] ", sizeof (cmd));
   2569 	}
   2570 	st = 0;
   2571 
   2572 	/* get the firstmount and accessmodes */
   2573 	mbuf[0] = '\0';
   2574 
   2575 	if (mfile && (strcmp(mfile, label_fname) == 0)) {
   2576 		/* The 17-space filename indicates we're labeling */
   2577 		(void) strlcat(cmd, "accessmode['creat'] ", sizeof (cmd));
   2578 		(void) strlcat(mbuf, "firstmount[", sizeof (mbuf));
   2579 	} else {
   2580 		/* all options go into accessmode otherwise */
   2581 		(void) strlcat(mbuf, "accessmode[", sizeof (mbuf));
   2582 	}
   2583 
   2584 	/* get the rest of the options */
   2585 	if (isdsk) {
   2586 		others++;
   2587 		(void) strlcat(mbuf, "'st_bsd' ", sizeof (mbuf));
   2588 	}
   2589 
   2590 	st = nvlist_lookup_string(nvl, O_MMSDRV, &val);
   2591 	if (st == 0) {
   2592 		others++;
   2593 		(void) snprintf(buf, sizeof (buf), "'%s' ", val);
   2594 		(void) strlcat(mbuf, buf, sizeof (mbuf));
   2595 	}
   2596 
   2597 	st = nvlist_lookup_boolean_value(nvl, O_NOREWIND, &vbool);
   2598 	if ((st == 0) && (vbool)) {
   2599 		others++;
   2600 		(void) strlcat(mbuf, "'norewind' ", sizeof (mbuf));
   2601 	}
   2602 
   2603 	st = nvlist_lookup_string(nvl, O_DENSITY, &val);
   2604 	if (st == 0) {
   2605 		others++;
   2606 		(void) snprintf(buf, sizeof (buf), "'%s' ", val);
   2607 		(void) strlcat(mbuf, buf, sizeof (mbuf));
   2608 	}
   2609 
   2610 	varray = mgmt_var_to_array(nvl, "mode", &count);
   2611 	for (i = 0; i < count; i++) {
   2612 		if (!varray[i]) {
   2613 			continue;
   2614 		}
   2615 		others++;
   2616 		(void) snprintf(buf, sizeof (buf), "'%s' ", varray[i]);
   2617 		(void) strlcat(mbuf, buf, sizeof (mbuf));
   2618 	}
   2619 	mgmt_free_str_arr(varray, count);
   2620 	varray = NULL;
   2621 	count = 0;
   2622 
   2623 	st = nvlist_lookup_string(nvl, "readonly", &val);
   2624 	if (st == 0) {
   2625 		if (strcasecmp(val, "true") == 0) {
   2626 			(void) snprintf(buf, sizeof (buf), "'readonly' ");
   2627 		} else {
   2628 			(void) snprintf(buf, sizeof (buf), "'readwrite' ");
   2629 		}
   2630 		others++;
   2631 		(void) strlcat(mbuf, buf, sizeof (mbuf));
   2632 	}
   2633 
   2634 	if (others > 0) {
   2635 		(void) strlcat(mbuf, "]", sizeof (mbuf));
   2636 		(void) strlcat(cmd, mbuf, sizeof (cmd));
   2637 	}
   2638 
   2639 	(void) strlcat(cmd, ";", sizeof (cmd));
   2640 
   2641 	/*
   2642 	 *  Call the mount daemon.  If successful, the handle will be
   2643 	 *  returned.
   2644 	 */
   2645 
   2646 	(void) memset(&arg, 0, sizeof (mmsmnt_arg_t));
   2647 	(void) memset(&d_arg, 0, sizeof (door_arg_t));
   2648 
   2649 	arg.op = 1;
   2650 	(void) strlcpy(arg.cartridge, pcl, sizeof (arg.cartridge));
   2651 	(void) strlcpy(arg.library, lib, sizeof (arg.library));
   2652 	(void) strlcpy(arg.volname, vname, sizeof (arg.volname));
   2653 	(void) strlcpy(arg.cmd, cmd, sizeof (arg.cmd));
   2654 	if (pass) {
   2655 		(void) strlcpy(arg.pass, pass, sizeof (arg.pass));
   2656 	}
   2657 	if (inst) {
   2658 		(void) strlcpy(arg.inst, inst, sizeof (arg.inst));
   2659 	}
   2660 	if (app) {
   2661 		(void) strlcpy(arg.app, app, sizeof (arg.app));
   2662 	}
   2663 	d_arg.data_ptr = (char *)&arg;
   2664 	d_arg.data_size = sizeof (mmsmnt_arg_t);
   2665 	d_arg.desc_ptr = NULL;
   2666 	d_arg.desc_num = 0;
   2667 	d_arg.rbuf = (char *)&arg;
   2668 	d_arg.rsize = d_arg.data_size;
   2669 
   2670 	st = call_mmsmnt(&d_arg);
   2671 
   2672 	if (st == 0) {
   2673 		(void) nvlist_add_string(nvl, "mountdev", arg.devname);
   2674 	}
   2675 
   2676 done:
   2677 	if (sess) {
   2678 		(void) mms_goodbye(sess, 0);
   2679 	}
   2680 
   2681 	if (attrs) {
   2682 		nvlist_free(attrs);
   2683 	}
   2684 
   2685 	if (mntattrs) {
   2686 		nvlist_free(mntattrs);
   2687 	}
   2688 
   2689 	return (st);
   2690 }
   2691 
   2692 int
   2693 mms_mgmt_unmount_vol(nvlist_t *nvl, nvlist_t *errs)
   2694 {
   2695 	int		st;
   2696 	char		*lib = NULL;
   2697 	char		*pcl = NULL;
   2698 	char		*dev = NULL;
   2699 	char		*app = NULL;
   2700 	char		*inst = NULL;
   2701 	char		*pass = NULL;
   2702 	void		*sess = NULL;
   2703 	void		*resp = NULL;
   2704 	char		tid[64];
   2705 	char		cmd[8192];
   2706 	nvlist_t	*attrs = NULL;
   2707 	boolean_t	phys = B_FALSE;
   2708 	mmsmnt_arg_t	arg;
   2709 	door_arg_t	d_arg;
   2710 
   2711 	if (!mgmt_chk_auth("solaris.mms.io.read")) {
   2712 		return (EACCES);
   2713 	}
   2714 
   2715 	(void) memset(&arg, 0, sizeof (mmsmnt_arg_t));
   2716 	(void) memset(&d_arg, 0, sizeof (d_arg));
   2717 
   2718 	/* requires either the pseudodevice name, *or* library/volume */
   2719 	st = nvlist_lookup_string(nvl, O_NAME, &pcl);
   2720 	if (st != 0) {
   2721 		MGMT_ADD_OPTERR(errs, O_NAME, st);
   2722 		return (st);
   2723 	}
   2724 
   2725 	if (pcl[0] == '/') {
   2726 		(void) strlcpy(arg.devname, pcl, sizeof (arg.devname));
   2727 	} else {
   2728 		(void) strlcpy(arg.cartridge, pcl, sizeof (arg.cartridge));
   2729 	}
   2730 
   2731 	st = nvlist_lookup_string(nvl, O_MMSLIB, &lib);
   2732 	if ((st != 0) && (arg.cartridge[0] != '\0')) {
   2733 		MGMT_ADD_OPTERR(errs, O_MMSLIB, st);
   2734 		return (st);
   2735 	}
   2736 
   2737 	if (lib) {
   2738 		(void) strlcpy(arg.library, lib, sizeof (arg.library));
   2739 	}
   2740 
   2741 	/* could specify all the options, but unlikely */
   2742 	st = nvlist_lookup_string(nvl, "mountdev", &dev);
   2743 	if (st == 0) {
   2744 		(void) strlcpy(arg.devname, dev, sizeof (arg.devname));
   2745 	}
   2746 
   2747 	(void) nvlist_lookup_string(nvl, O_APPS, &app);
   2748 	if (!app) {
   2749 		app = "MMS";
   2750 	}
   2751 	(void) nvlist_lookup_string(nvl, "instance", &inst);
   2752 	(void) nvlist_lookup_string(nvl, O_MMPASS, &pass);
   2753 
   2754 	/* make sure user is permitted to unmount this volume */
   2755 	if (strcasecmp(app, "MMS") != 0) {
   2756 		st = create_mm_clnt(app, inst, pass, NULL, &sess);
   2757 		if (st != 0) {
   2758 			return (st);
   2759 		}
   2760 
   2761 		(void) mms_gen_taskid(tid);
   2762 
   2763 		if (pcl[0] == '/') {
   2764 			(void) snprintf(cmd, sizeof (cmd),
   2765 			    "show task['%s'] report[MOUNTPHYSICAL] "
   2766 			    "reportmode[namevalue] "
   2767 			    "match[and "
   2768 			    "(streq(MOUNTPHYSICAL.'ApplicationName' '%s') "
   2769 			    "streq(MOUNTLOGICAL.'MountLogicalHandle' '%s'))];",
   2770 			    tid, app, pcl);
   2771 		} else {
   2772 			(void) snprintf(cmd, sizeof (cmd),
   2773 			    "show task['%s'] report[MOUNTPHYSICAL] "
   2774 			    "reportmode[namevalue] "
   2775 			    "match[and "
   2776 			    "(streq(MOUNTPHYSICAL.'ApplicationName' '%s') "
   2777 			    "streq(MOUNTPHYSICAL.'CartridgePCL' '%s'))];",
   2778 			    tid, app, pcl);
   2779 		}
   2780 
   2781 		st = mms_mgmt_send_cmd(sess, tid, cmd, "check mounted vol",
   2782 		    &resp);
   2783 		if (st == 0) {
   2784 			st = mmp_get_nvattrs("ApplicationName", B_FALSE,
   2785 			    resp, &attrs);
   2786 			mms_free_rsp(resp);
   2787 		}
   2788 		if (st == 0) {
   2789 			if (!nvlist_exists(attrs, app)) {
   2790 				st = MMS_MGMT_VOL_NOT_MOUNTED;
   2791 			}
   2792 			nvlist_free(attrs);
   2793 		}
   2794 
   2795 		(void) mms_goodbye(sess, 0);
   2796 
   2797 		if (st != 0) {
   2798 			return (st);
   2799 		}
   2800 	}
   2801 
   2802 	arg.op = 2;
   2803 
   2804 	/* see if they want the cartridge physically unloaded */
   2805 	st = nvlist_lookup_boolean_value(nvl, "unload", &phys);
   2806 	if (phys) {
   2807 		(void) strlcpy(arg.cmd, "physicalunmount", sizeof (arg.cmd));
   2808 	}
   2809 
   2810 	d_arg.data_ptr = (char *)&arg;
   2811 	d_arg.data_size = sizeof (mmsmnt_arg_t);
   2812 	d_arg.desc_ptr = NULL;
   2813 	d_arg.desc_num = 0;
   2814 	d_arg.rbuf = (char *)&arg;
   2815 	d_arg.rsize = d_arg.data_size;
   2816 
   2817 	st = call_mmsmnt(&d_arg);
   2818 
   2819 	return (st);
   2820 }
   2821