xref: /onnv-gate/usr/src/cmd/wbem/provider/c/wbem_disk/common/methods.c (revision 5331:3047ad28a67b)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/wait.h>
29 #include <errno.h>
30 #include <cimlogsvc.h>
31 #include <cimauthcheck.h>
32 #include <sys/param.h>
33 #include "libdiskmgt.h"
34 #include "messageStrings.h"
35 #include "providerNames.h"
36 #include "util.h"
37 #include "methods.h"
38 
39 static int		add_fdisk_props(ulong_t *ret_array, int part_num,
40 			    dm_descriptor_t d);
41 static CIMBool		build_fdisk_file(char *fdisk_file,
42 			    CCIMPropertyList *params);
43 static CIMBool		build_fmt_file(char *fmt_file,
44 			    CCIMPropertyList *params);
45 static CIMBool		execute_cmd(char *command_line, char *err_file);
46 static CIMBool		check_rights(char *provider);
47 static void		convert_flag(long flag, char *flag_buf, int len);
48 static CCIMProperty	*create_result(char *status);
49 static CCIMProperty 	*create_result_out(char *status,
50 			    CCIMPropertyList *outParams);
51 static int 		disk_geometry(char *media_name, ulong_t *geometry);
52 static CIMBool		get_devpath(CCIMObjectPath *op, char *devpath, int len);
53 static cimchar		*get_prop_val(CCIMProperty *prop);
54 static dm_descriptor_t	*get_partition_descs(CCIMObjectPath *op);
55 static void		make_fdisk_path(char *devpath);
56 
57 #define	DATALEN		256
58 #define	CMDLEN		2048
59 #define	NUM_GEOM_ELEMENTS 7
60 
61 /*
62  * This method formats the disk drive identified by CIMObjectPath
63  * based on the values in inParams
64  */
65 
66 CCIMProperty *
create_partitions(CCIMPropertyList * params,CCIMObjectPath * op)67 create_partitions(CCIMPropertyList *params, CCIMObjectPath *op)
68 {
69 	char		devpath[MAXPATHLEN];
70 	char		fmt_file[L_tmpnam];
71 	char		command_line[CMDLEN];
72 	int		len;
73 	int		error;
74 
75 	if (!check_rights("Solaris_Disk") || op == NULL || params == NULL) {
76 	    return (create_result(PROPFALSE));
77 	}
78 
79 	if (get_devpath(op, devpath, sizeof (devpath)) == cim_false) {
80 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
81 		NULL, NULL, &error);
82 	    return (create_result(PROPFALSE));
83 	}
84 
85 	/* Create a format data file to be used by the fmthard command. */
86 	if (build_fmt_file(fmt_file, params) == cim_false) {
87 	    /* last error is set in build_fmt_file function */
88 	    util_removeFile(fmt_file);
89 	    return (create_result(PROPFALSE));
90 	}
91 
92 	/* Create 'fmthard' command line */
93 	len = snprintf(command_line, sizeof (command_line),
94 	    "/usr/sbin/fmthard -s %s %s 2> /dev/null", fmt_file, devpath);
95 
96 	if (len < 0 || (len + 1) > sizeof (command_line)) {
97 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED,
98 		CIM_ERR_FAILED, NULL, &error);
99 	    util_removeFile(fmt_file);
100 	    return (create_result(PROPFALSE));
101 	}
102 
103 	/* Execute the command. */
104 	if (!execute_cmd(command_line, "/dev/null")) {
105 	    util_removeFile(fmt_file);
106 	    return (create_result(PROPFALSE));
107 	}
108 
109 	util_removeFile(fmt_file);
110 	return (create_result(PROPTRUE));
111 }
112 
113 CCIMProperty *
create_filesystem(CCIMObjectPath * op)114 create_filesystem(CCIMObjectPath *op)
115 {
116 	char			devpath[MAXPATHLEN];
117 	char			command_line[CMDLEN];
118 	int			len;
119 	int			error;
120 
121 	/* check to make sure caller has admin write rights */
122 	if (!check_rights("Solaris_DiskPartition")) {
123 	    return (create_result(PROPFALSE));
124 	}
125 
126 	if (get_devpath(op, devpath, sizeof (devpath)) == cim_false) {
127 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
128 		NULL, NULL, &error);
129 	    return (create_result(PROPFALSE));
130 	}
131 
132 	/* Create 'newfs' command line */
133 	len = snprintf(command_line, sizeof (command_line),
134 	    "echo y | /usr/sbin/newfs %s 2>/dev/null", devpath);
135 
136 	if (len < 0 || (len + 1) > sizeof (command_line)) {
137 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED,
138 		CIM_ERR_FAILED, NULL, &error);
139 	    return (create_result(PROPFALSE));
140 	}
141 
142 	/* Execute the command. */
143 	if (!execute_cmd(command_line, "/dev/null")) {
144 	    return (create_result(PROPFALSE));
145 	}
146 
147 	return (create_result(PROPTRUE));
148 }
149 
150 /*
151  * Function:	create_fdisk_partitions
152  *
153  * Parameters:  params - CCIMPropertyList pointer that dereferences
154  *		to a list of not less than 4 or more than 16 CCIMProperty
155  *		values.  Number of CCIMProperty values must be a multiple
156  * 		of 4.
157  *		op - CCIMObjectPath pointer that points to the object path
158  *		of the device to fdisk.
159  *
160  * Returns:	Returns a CCIMProperty pointer.  The CCIMProperty referenced
161  *		by the pointer will contain an mValue of cim_true for
162  *		success or cim_false on failure.
163  *
164  * Description:	Executes the fdisk command on the device pointed to my 'op'
165  *		with the parameters provided in 'params'.
166  *
167  * Notes:	The calling program is responsible for releasing the memory
168  *		used by the returned CCIMProperty.
169  */
170 CCIMProperty *
create_fdisk_partitions(CCIMPropertyList * params,CCIMObjectPath * op)171 create_fdisk_partitions(CCIMPropertyList *params, CCIMObjectPath *op)
172 {
173 	char		devpath[MAXPATHLEN];
174 	char		fdisk_file[L_tmpnam];
175 	char		err_file[L_tmpnam];
176 	char		command_line[CMDLEN];
177 	int		len;
178 	int		error;
179 
180 	if (!check_rights("Solaris_Disk") ||
181 	    op == NULL || params == NULL) {
182 	    return (create_result(PROPFALSE));
183 	}
184 
185 	if (get_devpath(op, devpath, sizeof (devpath)) == cim_false) {
186 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
187 		CIM_ERR_FAILED, NULL, &error);
188 	    return (create_result(PROPFALSE));
189 	}
190 	make_fdisk_path(devpath);
191 
192 	/* Create a fdisk data file to be used by the fdisk command. */
193 	if (build_fdisk_file(fdisk_file, params) == cim_false) {
194 	    /* last error is set in build_fdisk_file function */
195 	    util_removeFile(fdisk_file);
196 	    return (create_result(PROPFALSE));
197 	}
198 
199 	(void) tmpnam(err_file);
200 
201 	/*
202 	 * Build the fdisk command line.  Some combinations of
203 	 * parameters can cause fdisk to output a message and wait
204 	 * for a y/n response, echo'ing an 'n' and piping it to
205 	 * fdisk solves this problem.
206 	 *
207 	 * Using the form of fdisk (-F) that takes partition information
208 	 * from a disk file so that multiple partitions can be created
209 	 * by one request.
210 	 */
211 
212 	len = snprintf(command_line, sizeof (command_line),
213 	    "echo n | /usr/sbin/fdisk -F %s %s 2> %s",
214 	    fdisk_file, devpath, err_file);
215 
216 	if (len < 0 || (len + 1) > sizeof (command_line)) {
217 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED,
218 		NULL, NULL, &error);
219 	    util_removeFile(fdisk_file);
220 	    return (create_result(PROPFALSE));
221 	}
222 
223 	/* Execute the command. */
224 	if (!execute_cmd(command_line, err_file)) {
225 	    util_removeFile(fdisk_file);
226 	    return (create_result(PROPFALSE));
227 	}
228 
229 	util_removeFile(fdisk_file);
230 	return (create_result(PROPTRUE));
231 }
232 
233 /*
234  * Function:	create_default_fdisk_partition
235  *
236  * Parameters:  op - CCIMObjectPath pointer that points to the object path
237  *		of the device to fdisk.
238  *
239  * Returns:	Returns a CCIMProperty pointer.  The CCIMProperty referenced
240  *		by the pointer will contain an mValue of cim_true for
241  *		success or cim_false on failure.
242  *
243  * Description:	Executes the fdisk command on the device pointed to my 'op'
244  *		with the -B parameter.
245  *
246  * Notes:	The calling program is responsible for releasing the memory
247  *		used by the returned CCIMProperty.
248  */
249 CCIMProperty *
create_default_fdisk_partition(CCIMObjectPath * op)250 create_default_fdisk_partition(CCIMObjectPath *op)
251 {
252 	char		devpath[MAXPATHLEN];
253 	char		err_file[L_tmpnam];
254 	char		command_line[CMDLEN];
255 	int		len;
256 	int		error;
257 
258 	/* This function is called from Solaris_DiskDrive, not Solaris_Disk. */
259 	if (!check_rights("Solaris_DiskDrive") || op == NULL) {
260 	    return (create_result(PROPFALSE));
261 	}
262 
263 	if (get_devpath(op, devpath, sizeof (devpath)) == cim_false) {
264 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
265 		CIM_ERR_FAILED, NULL, &error);
266 	    return (create_result(PROPFALSE));
267 	}
268 	make_fdisk_path(devpath);
269 
270 	(void) tmpnam(err_file);
271 
272 	/*
273 	 * Build the fdisk command line.  Some combinations of
274 	 * parameters can cause fdisk to output a message and wait
275 	 * for a y/n response, echo'ing an 'n' and piping it to
276 	 * fdisk solves this problem.
277 	 *
278 	 * Using the form of fdisk (-F) that takes partition information
279 	 * from a disk file so that multiple partitions can be created
280 	 * by one request.
281 	 */
282 
283 	len = snprintf(command_line, sizeof (command_line),
284 	    "echo n | /usr/sbin/fdisk -B %s 2> %s",
285 	    devpath, err_file);
286 
287 	if (len < 0 || (len + 1) > sizeof (command_line)) {
288 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED,
289 		NULL, NULL, &error);
290 	    return (create_result(PROPFALSE));
291 	}
292 
293 	/* Execute the command. */
294 	if (!execute_cmd(command_line, err_file)) {
295 	    return (create_result(PROPFALSE));
296 	}
297 
298 	return (create_result(PROPTRUE));
299 }
300 
301 /*
302  * Function:	writeVolumeName
303  *
304  * Parameters:	params - CCIMPropertyList pointer.  Property list
305  *		containing the new disk label name.
306  *		op - CCIMObjectPath pointer.  Object path containing
307  *		the deviceId of the disk to label.
308  *
309  * Returns:	Returns a CCIMProperty pointer.  The CCIMProperty referenced
310  *		by the pointer will contain an mValue of cim_true for
311  *		success or cim_false on failure.
312  *
313  * Description:	Executes the fmthard -n volume_name command on the device
314  *		pointed to by 'op'.
315  */
316 CCIMProperty *
label_disk(CCIMPropertyList * params,CCIMObjectPath * op)317 label_disk(CCIMPropertyList *params, CCIMObjectPath *op)
318 {
319 	char		devpath[MAXPATHLEN];
320 	char		command_line[CMDLEN];
321 	int		len;
322 	cimchar		*label;
323 	int		error;
324 
325 	if (!check_rights("Solaris_Disk") ||
326 	    op == NULL || params == NULL) {
327 	    return (create_result(PROPFALSE));
328 	}
329 
330 	if (get_devpath(op, devpath, sizeof (devpath)) == cim_false) {
331 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
332 		NULL, NULL, &error);
333 	    return (create_result(PROPFALSE));
334 	}
335 
336 	/* Extract the label from the input parameters */
337 	if ((label = get_prop_val(params->mDataObject)) == NULL) {
338 	    return (create_result(PROPFALSE));
339 	}
340 	if (strlen(label) > 8) {
341 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
342 		NULL, NULL, &error);
343 	    return (create_result(PROPFALSE));
344 	}
345 
346 	/* Build the command line to execute */
347 
348 	len = snprintf(command_line, sizeof (command_line),
349 	    "/usr/sbin/fmthard -n '%s' %s 2> /dev/null", label, devpath);
350 
351 	if (len < 0 || (len + 1) > sizeof (command_line)) {
352 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
353 		NULL, NULL, &error);
354 	    return (create_result(PROPFALSE));
355 	}
356 
357 	/* Execute the command. */
358 	if (!execute_cmd(command_line, "/dev/null")) {
359 	    return (create_result(PROPFALSE));
360 	}
361 	return (create_result(PROPTRUE));
362 }
363 
364 CCIMProperty *
get_disk_geometry(CCIMPropertyList * out,CCIMObjectPath * op)365 get_disk_geometry(CCIMPropertyList *out, CCIMObjectPath *op)
366 {
367 	CCIMProperty		*prop = NULL;
368 	CCIMPropertyList	*prop_list = NULL;
369 	ulong_t			geometry[NUM_GEOM_ELEMENTS];
370 	char			*array_str;
371 	int			error;
372 
373 	/*
374 	 * Don't use get_devpath since we are going through the API.
375 	 * Parse the object path to get the media name to pass in.
376 	 */
377 	if (op != NULL) {
378 	    prop_list = op->mKeyProperties;
379 	}
380 
381 	for (; prop_list; prop_list = prop_list->mNext) {
382 
383 	    if (((prop = prop_list->mDataObject) != NULL &&
384 		prop->mName != NULL &&
385 		strcasecmp(prop->mName, "Tag")) == 0) {
386 		break;
387 	    }
388 	}
389 
390 	if (prop == NULL || prop->mValue == NULL) {
391 	    return (create_result(PROPFALSE));
392 	}
393 
394 	cim_logDebug("get_disk_geometry", "%s", prop->mValue);
395 	error = disk_geometry(prop->mValue, geometry);
396 	if (error != 0) {
397 	    /* We have to put something in the out params when we fail. */
398 	    ulong_t		dummy [] = {0};
399 	    char		*array_str;
400 	    CCIMProperty	*p;
401 
402 	    cim_logDebug("get_disk_geometry", "disk_geometry failed");
403 	    if ((array_str = cim_encodeUint32Array(dummy, 1)) == NULL) {
404 		util_handleError(DISK_DRIVE, CIM_ERR_FAILED, CIM_ERR_FAILED,
405 		    NULL, &error);
406 	    } else if ((p = cim_createProperty("geometry",
407 		sint32_array, array_str, NULL, cim_false)) == NULL) {
408 		free(array_str);
409 	    } else if ((cim_addPropertyToPropertyList(out, p)) == NULL) {
410 		cim_freeProperty(p);
411 	    }
412 
413 	    return (create_result(PROPFALSE));
414 	}
415 
416 	array_str = cim_encodeUint32Array(geometry, NUM_GEOM_ELEMENTS);
417 	if (array_str == NULL) {
418 	    util_handleError(DISK_DRIVE, CIM_ERR_FAILED, CIM_ERR_FAILED, NULL,
419 		&error);
420 	    return (create_result(PROPFALSE));
421 	}
422 
423 	if ((prop = cim_createProperty("geometry", sint32_array,
424 	    array_str, NULL, cim_false)) == NULL) {
425 	    free(array_str);
426 	    return (create_result(PROPFALSE));
427 	}
428 
429 	if ((cim_addPropertyToPropertyList(out, prop)) == NULL) {
430 	    cim_freeProperty(prop);
431 	    return (create_result(PROPFALSE));
432 	}
433 
434 	return (create_result(PROPTRUE));
435 }
436 
437 /*
438  * Function:	getFdisk
439  *
440  * Parameters:	outParams - CCIMPropertyList pointer.  The output from
441  *		the fdisk command is placed in this list.
442  *		op - CCIMObjectPath pointer.  The object path contains
443  *		deviceID of the device to fdisk.
444  *
445  * Returns:	Returns a CCIMProperty pointer.  The CCIMProperty referenced
446  *		by the pointer will contain an mValue of cim_true for
447  *		success or cim_false on failure.
448  *
449  * Notes:	The calling program is responsible for releasing the memory
450  *		used by the returned CCIMProperty and the CCIMPropertyList
451  *		pointed to by outParams.  I don't know why we return only
452  *		four of the possible values from fdisk.  That is the way
453  *		the Java provider worked and this provider was written to
454  *		mimic the Java provider.
455  */
456 CCIMProperty *
getFdisk(CCIMPropertyList * outParams,CCIMObjectPath * op)457 getFdisk(CCIMPropertyList *outParams, CCIMObjectPath *op)
458 {
459 	dm_descriptor_t		*da;
460 	int			i;
461 	int			cnt;
462 	ulong_t			*ret_array;
463 	int			error;
464 	char			*array_str;
465 	CCIMProperty		*prop;
466 
467 	if (cim_checkRights(DISK_DRIVE, DISK_READ_RIGHT, (void *) NULL) ==
468 	    cim_false || op == NULL) {
469 		return (create_result_out(PROPFALSE, outParams));
470 	}
471 
472 	if ((da = get_partition_descs(op)) == NULL) {
473 	    return (create_result_out(PROPFALSE, outParams));
474 	}
475 
476 	/* Count the number of fdisk partitions. */
477 	for (cnt = 0; da[cnt]; cnt++);
478 
479 	/* We return 4 values for each partition. */
480 	cnt = cnt * 4;
481 
482 	ret_array = (ulong_t *)calloc(cnt, sizeof (ulong_t));
483 	if (ret_array == NULL) {
484 	    dm_free_descriptors(da);
485 	    util_handleError(DISK_DRIVE, CIM_ERR_FAILED, CIM_ERR_FAILED, NULL,
486 		&error);
487 	    return (create_result_out(PROPFALSE, outParams));
488 	}
489 
490 	for (i = 0; da[i]; i++) {
491 	    if (!add_fdisk_props(ret_array, i, da[i])) {
492 		dm_free_descriptors(da);
493 		free(ret_array);
494 		return (create_result_out(PROPFALSE, outParams));
495 	    }
496 	}
497 
498 	dm_free_descriptors(da);
499 
500 	array_str = cim_encodeUint32Array(ret_array, cnt);
501 
502 	free(ret_array);
503 
504 	if (array_str == NULL) {
505 	    util_handleError(DISK_DRIVE, CIM_ERR_FAILED, CIM_ERR_FAILED, NULL,
506 		&error);
507 	    return (create_result_out(PROPFALSE, outParams));
508 	}
509 
510 	if ((prop = cim_createProperty("FDiskPartitions", sint32_array,
511 	    array_str, NULL, cim_false)) == NULL) {
512 	    free(array_str);
513 	    return (create_result_out(PROPFALSE, outParams));
514 	}
515 
516 	if ((cim_addPropertyToPropertyList(outParams, prop)) == NULL) {
517 	    cim_freeProperty(prop);
518 	    return (create_result_out(PROPFALSE, outParams));
519 	}
520 
521 	return (create_result_out(PROPTRUE, outParams));
522 }
523 
524 static int
add_fdisk_props(ulong_t * ret_array,int part_num,dm_descriptor_t d)525 add_fdisk_props(ulong_t *ret_array, int part_num, dm_descriptor_t d)
526 {
527 	int		error;
528 	nvlist_t	*attrs;
529 	int		i;
530 	int		result = 1;
531 	int		offset;
532 	static char	*attr_names[] = {
533 	    DM_PTYPE, DM_BOOTID, DM_RELSECT, DM_NSECTORS, NULL};
534 
535 	attrs = dm_get_attributes(d, &error);
536 	if (error != 0) {
537 	    return (0);
538 	}
539 
540 	/* figure out where in the array to put the values */
541 	offset = part_num * 4;
542 
543 	for (i = 0; attr_names[i]; i++) {
544 	    uint32_t	val32;
545 
546 	    if (nvlist_lookup_uint32(attrs, attr_names[i], &val32) != 0) {
547 		result = 0;
548 		break;
549 	    }
550 
551 	    ret_array[offset++] = val32;
552 	}
553 
554 	nvlist_free(attrs);
555 	return (result);
556 }
557 
558 /*
559  * inParams - CCIMPropertyList pointer that dereferences to a list of not less
560  * than 4 or more than 16 CCIMProperty values.  Number of CCIMProperty values
561  * must be a multiple of 4.
562  *
563  * The fdisk file will contain at least one line and not more than four lines
564  * in the following format:
565  *	id:act:0:0:0:0:0:0:rsect:numsect.
566  * Values for id, act, rsect and numsect are taken from inParams.
567  */
568 static CIMBool
build_fdisk_file(char * fdisk_file,CCIMPropertyList * params)569 build_fdisk_file(char *fdisk_file, CCIMPropertyList *params)
570 {
571 	FILE	*fp;
572 	int	i;
573 	int	error;
574 	ulong_t	*vals;
575 	int	cnt = 0;
576 
577 	if (params == NULL) {
578 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
579 		NULL, NULL, &error);
580 	    return (cim_false);
581 	}
582 
583 	vals = cim_decodeUint32Array(get_prop_val(params->mDataObject), &cnt);
584 
585 	if (cnt == 0 || cnt > 16 || (cnt % 4) != 0) {
586 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
587 		NULL, NULL, &error);
588 	    return (cim_false);
589 	}
590 
591 	(void) tmpnam(fdisk_file);
592 
593 	/* Open the temporary file for writing */
594 	if ((fp = util_openFile(fdisk_file, "w")) == NULL) {
595 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL,
596 		NULL, &error);
597 	    return (cim_false);
598 	}
599 
600 	/*
601 	 * Build a fdisk_file using 4 input parameters at a time.
602 	 * Check for all possible NULL parameters, parameter lists
603 	 * greater than 16 or not a multiple of 4.
604 	 */
605 	for (i = 0; i < cnt; i += 4) {
606 	    char	line_buf[DATALEN];
607 
608 	    (void) snprintf(line_buf, sizeof (line_buf),
609 		"%lu:%lu:0:0:0:0:0:0:%lu:%lu\n",
610 		vals[i], vals[i + 1], vals[i + 2], vals[i + 3]);
611 
612 	    /* Write the line of parameters to the fdisk_file */
613 	    if ((fputs(line_buf, fp)) == EOF) {
614 		util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
615 		    NULL, NULL, &error);
616 		(void) util_closeFile(fp, fdisk_file);
617 		return (cim_false);
618 	    }
619 	}
620 
621 	if ((util_closeFile(fp, fdisk_file)) == 0) {
622 	    return (cim_false);
623 	}
624 
625 	/* Caller must delete the temporary file */
626 	return (cim_true);
627 }
628 
629 /*
630  * inParams - CCIMPropertyList pointer that dereferences to a list of not less
631  * than 5 CCIMProperty values. The number of CCIMProperty values must be a
632  * multiple of 5.
633  *
634  * The file will contain at least one line in the following format:
635  *	part tag flag start_sect part_size
636  * Values for partition, tag, flag, starting sector and partition size are
637  * taken from inParams.
638  */
639 static CIMBool
build_fmt_file(char * fmt_file,CCIMPropertyList * params)640 build_fmt_file(char *fmt_file, CCIMPropertyList *params)
641 {
642 	ulong_t	*vals;
643 	int	cnt = 0;
644 	FILE	*fp;
645 	int	error;
646 	int	i;
647 
648 	if (params == NULL) {
649 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
650 		NULL, NULL, &error);
651 	    return (cim_false);
652 	}
653 
654 	vals = cim_decodeUint32Array(get_prop_val(params->mDataObject), &cnt);
655 
656 	if (cnt == 0 || (cnt % 5) != 0) {
657 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
658 		NULL, NULL, &error);
659 	    return (cim_false);
660 	}
661 
662 	(void) tmpnam(fmt_file);
663 
664 	/* Open the temporary file for writing */
665 	if ((fp = util_openFile(fmt_file, "w")) == NULL) {
666 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL,
667 		NULL, &error);
668 	    return (cim_false);
669 	}
670 
671 	/*
672 	 * Build a data file for the fmthard command.
673 	 * Each line of the file consists of:
674 	 *
675 	 * part_num tag flag start_sector partition_size
676 	 *
677 	 * The fmthard command requires the starting sector fall on
678 	 * a cylinder boundry.
679 	 */
680 	for (i = 0; i < cnt; i += 5) {
681 	    char	line_buf[DATALEN];
682 	    char	flag_buf[DATALEN];
683 
684 	    convert_flag(vals[i + 2], flag_buf, sizeof (flag_buf));
685 
686 	    (void) snprintf(line_buf, sizeof (line_buf),
687 		"%lu %lu %s %lu %lu\n",
688 		vals[i], vals[i + 1], flag_buf, vals[i + 3], vals[i + 4]);
689 
690 	    /* Write the line of parameters to the fdisk_file */
691 	    if ((fputs(line_buf, fp)) == EOF) {
692 		util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER,
693 		    NULL, NULL, &error);
694 		(void) util_closeFile(fp, fmt_file);
695 		return (cim_false);
696 	    }
697 	}
698 
699 	if ((util_closeFile(fp, fmt_file)) == 0) {
700 	    return (cim_false);
701 	}
702 
703 	/* Caller must delete the file */
704 	return (cim_true);
705 }
706 
707 /*
708  * check_rights
709  *
710  * Performs check for 'admin write' rights.  Handles error
711  * checking and reporting.  Returns cim_true on success and
712  * cim_false on failure.
713  */
714 static CIMBool
check_rights(char * provider)715 check_rights(char *provider)
716 {
717 
718 	int		error;
719 
720 	if ((cim_checkRights(provider, DISK_WRITE_RIGHT, (void *) NULL))
721 	    == cim_false) {
722 	    util_handleError(INVOKE_METHOD, CIM_ERR_ACCESS_DENIED, NULL,
723 		NULL, &error);
724 	    return (cim_false);
725 	}
726 	return (cim_true);
727 }
728 
729 /*
730  * Converts decimal flag value to hex string.
731  * Valid flag values are hex 00, 01, 10, 11.
732  * Places result in new cimchar array and returns
733  * pointer to array on success and NULL on failure.
734  */
735 static void
convert_flag(long flag,char * flag_buf,int len)736 convert_flag(long flag, char *flag_buf, int len)
737 {
738 	switch (flag) {
739 	case 1:
740 		(void) strlcpy(flag_buf, "0x01", len);
741 		break;
742 	case 16:
743 		(void) strlcpy(flag_buf, "0x10", len);
744 		break;
745 	case 17:
746 		(void) strlcpy(flag_buf, "0x11", len);
747 		break;
748 	default:
749 		(void) strlcpy(flag_buf, "0x00", len);
750 		break;
751 	}
752 }
753 
754 static CCIMProperty *
create_result(char * status)755 create_result(char *status)
756 {
757 	return (cim_createProperty("result", boolean, status, NULL, cim_false));
758 }
759 
760 static CCIMProperty *
create_result_out(char * status,CCIMPropertyList * outParams)761 create_result_out(char *status, CCIMPropertyList *outParams)
762 {
763 	if (strcmp(status, PROPFALSE) == 0) {
764 	    /* We have to put something in the out params when we fail. */
765 	    ulong_t		dummy [] = {0};
766 	    int			error;
767 	    char		*array_str;
768 	    CCIMProperty	*p;
769 
770 	    if ((array_str = cim_encodeUint32Array(dummy, 1)) == NULL) {
771 		util_handleError(DISK_DRIVE, CIM_ERR_FAILED, CIM_ERR_FAILED,
772 		    NULL, &error);
773 	    } else if ((p = cim_createProperty("FDiskPartitions",
774 		sint32_array, array_str, NULL, cim_false)) == NULL) {
775 		free(array_str);
776 	    } else if ((cim_addPropertyToPropertyList(outParams, p)) == NULL) {
777 		cim_freeProperty(p);
778 	    }
779 	}
780 
781 	return (create_result(status));
782 }
783 
784 /*
785  * Return: 1 if fails, 0 if ok.  geometry array contains:
786  *     0. SectorsPerCylinder
787  *     1. HeadsPerCylinder
788  *     2. BytesPerCylinder
789  *     3. PhysicalCylinders
790  *     4. DataCylinders
791  *     5. AlternateCylinders
792  *     6. ActualCylinders
793  */
794 static int
disk_geometry(char * media_name,ulong_t * geometry)795 disk_geometry(char *media_name, ulong_t *geometry)
796 {
797 	int		error;
798 	dm_descriptor_t d;
799 	nvlist_t	*attrs;
800 	uint32_t	val32;
801 
802 	d = dm_get_descriptor_by_name(DM_MEDIA, media_name, &error);
803 	if (error != 0) {
804 	    return (1);
805 	}
806 
807 	attrs = dm_get_attributes(d, &error);
808 	dm_free_descriptor(d);
809 	if (error != 0) {
810 	    return (1);
811 	}
812 
813 	/*
814 	 * If nsect is not in the attr list then we have media that does
815 	 * not have geometry info on it (e.g. EFI label).  So return a failure
816 	 * in this case.  Otherwise, just get the attrs we can and return
817 	 * their values.
818 	 */
819 	if (nvlist_lookup_uint32(attrs, DM_NSECTORS, &val32) != 0) {
820 	    nvlist_free(attrs);
821 	    return (1);
822 	}
823 	geometry[0] = val32;
824 	val32 = 0;
825 
826 	(void) nvlist_lookup_uint32(attrs, DM_NHEADS, &val32);
827 	geometry[1] = val32;
828 	val32 = 0;
829 	(void) nvlist_lookup_uint32(attrs, DM_BLOCKSIZE, &val32);
830 	geometry[2] = (geometry[1] * geometry[0]) * val32;
831 	val32 = 0;
832 	(void) nvlist_lookup_uint32(attrs, DM_NPHYSCYLINDERS, &val32);
833 	geometry[3] = val32;
834 	val32 = 0;
835 	(void) nvlist_lookup_uint32(attrs, DM_NCYLINDERS, &val32);
836 	geometry[4] = val32;
837 	val32 = 0;
838 	(void) nvlist_lookup_uint32(attrs, DM_NALTCYLINDERS, &val32);
839 	geometry[5] = val32;
840 	val32 = 0;
841 	/* This one is probably there only in x86 machines. */
842 	(void) nvlist_lookup_uint32(attrs, DM_NACTUALCYLINDERS, &val32);
843 	geometry[6] = val32;
844 
845 	nvlist_free(attrs);
846 
847 	return (0);
848 }
849 
850 /*
851  * Use popen to execute a command.  Check for failures and
852  * handle error reporting.
853  * params:
854  *   commandLine - the command to execute
855  *   err_file - file that receives the stderr output from the
856  *		command
857  *
858  * Returns cim_true on success, cim_false on failure.
859  *
860  * Note:  function removes the error file if it exists
861  */
862 static CIMBool
execute_cmd(char * command_line,char * err_file)863 execute_cmd(char *command_line, char *err_file)
864 {
865 	FILE	*cfp;
866 	char   	buf[BUFSIZ];
867 	int	result;
868 	int	error;
869 
870 	cim_logDebug("execute_cmd", "%s ", command_line);
871 
872 	/* Execute the fmthard command using popen */
873 	if ((cfp = popen(command_line, "r")) == NULL) {
874 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL,
875 		NULL, &error);
876 	    return (cim_false);
877 	}
878 
879 	/* Read the commands stdout and ignore it */
880 	while (fgets(buf, sizeof (buf), cfp) != NULL);
881 	result = pclose(cfp);
882 
883 	/* the buf will hold any error output */
884 	buf[0] = '\0';
885 	if (strcmp(err_file, "/dev/null") != 0) {
886 	    FILE	*efp;
887 
888 	    if ((efp = util_openFile(err_file, "r")) == NULL) {
889 		/*
890 		 * err_file should have been created when popen executed
891 		 * 'commandLine', so the openFile shouldn't fail.  Treating it
892 		 * as a failure.
893 		 */
894 		util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL,
895 		    NULL, &error);
896 		util_removeFile(err_file);
897 		return (cim_false);
898 	    }
899 
900 	    (void) fgets(buf, sizeof (buf), efp);
901 	    cim_logDebug("execute_cmd", "err output: %s", buf);
902 	    (void) util_closeFile(efp, err_file);
903 	    util_removeFile(err_file);
904 	}
905 
906 	if (strlen(buf) != 0 ||
907 	    (WIFEXITED(result) != 0 && WEXITSTATUS(result) != 0)) {
908 
909 	    cim_logDebug("execute_cmd", "exit: %d %d", WIFEXITED(result),
910 		WEXITSTATUS(result));
911 	    util_handleError(INVOKE_METHOD, CIM_ERR_FAILED, NULL, NULL, &error);
912 	    return (cim_false);
913 	}
914 
915 	return (cim_true);
916 }
917 
918 /*
919  * Take the deviceID property from the object path and get the raw devpath
920  * of the drive that corresponds to the given device ID.
921  */
922 static CIMBool
get_devpath(CCIMObjectPath * op,char * devpath,int len)923 get_devpath(CCIMObjectPath *op, char *devpath, int len)
924 {
925 	CCIMPropertyList	*prop_list = NULL;
926 	CCIMProperty		*prop = NULL;
927 	int			error;
928 	dm_descriptor_t		dp;
929 	dm_descriptor_t		*da;
930 	nvlist_t		*attrs;
931 	char			*opath;
932 	char			*keyprop;
933 	int			type = 0;
934 	char			*p;
935 
936 	if (strcasecmp(op->mName, "Solaris_Disk") == 0) {
937 	    keyprop = "Tag";
938 	    type = 1;
939 	} else if (strcasecmp(op->mName, "Solaris_DiskDrive") == 0) {
940 	    keyprop = "deviceid";
941 	    type = 2;
942 	} else if (strcasecmp(op->mName, "Solaris_DiskPartition") == 0) {
943 	    keyprop = "deviceid";
944 	    type = 3;
945 	} else {
946 	    return (cim_false);
947 	}
948 
949 	if (op != NULL) {
950 	    prop_list = op->mKeyProperties;
951 	}
952 
953 	for (; prop_list; prop_list = prop_list->mNext) {
954 
955 	    if (((prop = prop_list->mDataObject) != NULL &&
956 		prop->mName != NULL && strcasecmp(prop->mName, keyprop)) == 0) {
957 		break;
958 	    }
959 	}
960 
961 	if (prop == NULL || prop->mValue == NULL) {
962 	    return (cim_false);
963 	}
964 
965 	switch (type) {
966 	case 1:
967 	    dp = dm_get_descriptor_by_name(DM_MEDIA, prop->mValue, &error);
968 	    if (error != 0) {
969 		return (cim_false);
970 	    }
971 
972 	    da = dm_get_associated_descriptors(dp, DM_DRIVE, &error);
973 	    dm_free_descriptor(dp);
974 	    if (error != 0 || da == NULL) {
975 		return (cim_false);
976 	    }
977 
978 	    if (da[0] == NULL) {
979 		dm_free_descriptors(da);
980 		return (cim_false);
981 	    }
982 
983 	    attrs = dm_get_attributes(da[0], &error);
984 	    dm_free_descriptors(da);
985 	    if (error != 0) {
986 		return (cim_false);
987 	    }
988 
989 	    if (nvlist_lookup_string(attrs, DM_OPATH, &opath) != 0) {
990 		nvlist_free(attrs);
991 		return (cim_false);
992 	    }
993 	    (void) strlcpy(devpath, opath, len);
994 	    nvlist_free(attrs);
995 	    break;
996 
997 	case 2:
998 	    dp = dm_get_descriptor_by_name(DM_DRIVE, prop->mValue, &error);
999 	    if (error != 0) {
1000 		return (cim_false);
1001 	    }
1002 
1003 	    attrs = dm_get_attributes(dp, &error);
1004 	    dm_free_descriptor(dp);
1005 	    if (error != 0) {
1006 		return (cim_false);
1007 	    }
1008 
1009 	    if (nvlist_lookup_string(attrs, DM_OPATH, &opath) != 0) {
1010 		nvlist_free(attrs);
1011 		return (cim_false);
1012 	    }
1013 	    (void) strlcpy(devpath, opath, len);
1014 	    nvlist_free(attrs);
1015 	    break;
1016 
1017 	case 3:
1018 	    /* Convert the Solaris_DiskPartition value to rdsk. */
1019 	    p = strstr(prop->mValue, "/dsk/");
1020 	    if (p == NULL || (strlen(prop->mValue) + 2) > len) {
1021 		(void) strlcpy(devpath, prop->mValue, len);
1022 	    } else {
1023 		p++;
1024 		*p = 0;
1025 		(void) strcpy(devpath, prop->mValue);	/* copy up to dsk/ */
1026 		*p = 'd';
1027 		(void) strcat(devpath, "r");		/* prefix 'r' to dsk/ */
1028 		(void) strcat(devpath, p);		/* append the rest */
1029 	    }
1030 	    break;
1031 	}
1032 
1033 	return (cim_true);
1034 }
1035 
1036 /*
1037  * Take the deviceID property from the object path and get the raw devpath
1038  * of the drive that corresponds to the given device ID.
1039  */
1040 static dm_descriptor_t *
get_partition_descs(CCIMObjectPath * op)1041 get_partition_descs(CCIMObjectPath *op)
1042 {
1043 	CCIMPropertyList	*prop_list = NULL;
1044 	CCIMProperty		*prop = NULL;
1045 	int			error;
1046 	dm_descriptor_t		dp;
1047 	dm_descriptor_t		*da;
1048 	dm_descriptor_t		*dpa;
1049 
1050 	if (op != NULL) {
1051 	    prop_list = op->mKeyProperties;
1052 	}
1053 
1054 	for (; prop_list; prop_list = prop_list->mNext) {
1055 
1056 	    if (((prop = prop_list->mDataObject) != NULL &&
1057 		prop->mName != NULL &&
1058 		strcasecmp(prop->mName, "deviceid")) == 0) {
1059 		break;
1060 	    }
1061 	}
1062 
1063 	if (prop == NULL || prop->mValue == NULL) {
1064 	    return (NULL);
1065 	}
1066 
1067 	dp = dm_get_descriptor_by_name(DM_DRIVE, prop->mValue, &error);
1068 	if (error != 0) {
1069 	    return (NULL);
1070 	}
1071 
1072 	da = dm_get_associated_descriptors(dp, DM_MEDIA, &error);
1073 	dm_free_descriptor(dp);
1074 	if (error != 0 || da == NULL) {
1075 	    return (NULL);
1076 	}
1077 
1078 	if (da[0] == NULL) {
1079 	    dm_free_descriptors(da);
1080 	    return (NULL);
1081 	}
1082 
1083 	dpa = dm_get_associated_descriptors(da[0], DM_PARTITION, &error);
1084 	dm_free_descriptors(da);
1085 	if (error != 0 || dpa == NULL) {
1086 	    return (NULL);
1087 	}
1088 
1089 	if (dpa[0] == NULL) {
1090 	    dm_free_descriptors(dpa);
1091 	    return (NULL);
1092 	}
1093 
1094 	return (dpa);
1095 }
1096 
1097 static cimchar *
get_prop_val(CCIMProperty * prop)1098 get_prop_val(CCIMProperty *prop)
1099 {
1100 
1101 	int		error;
1102 
1103 	if (prop == NULL || prop->mValue == NULL) {
1104 	    util_handleError(INVOKE_METHOD, CIM_ERR_INVALID_PARAMETER, NULL,
1105 		NULL, &error);
1106 	    return ((cimchar *)NULL);
1107 	}
1108 	return (prop->mValue);
1109 }
1110 
1111 static void
make_fdisk_path(char * devpath)1112 make_fdisk_path(char *devpath)
1113 {
1114 	int len;
1115 
1116 	len = strlen(devpath) - 2;
1117 	if (len <= 0 || *(devpath + len) != 's') {
1118 	    return;
1119 	}
1120 
1121 	*(devpath + len) = 'p';
1122 }
1123