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