xref: /titanic_44/usr/src/cmd/stmsboot/stmsboot_util.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
34*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
35*7c478bd9Sstevel@tonic-gate #include <errno.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <stropts.h>
38*7c478bd9Sstevel@tonic-gate #include <strings.h>
39*7c478bd9Sstevel@tonic-gate #include <dirent.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/scsi/adapters/scsi_vhci.h>
42*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
43*7c478bd9Sstevel@tonic-gate #include <libgen.h>
44*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
45*7c478bd9Sstevel@tonic-gate #include <link.h>
46*7c478bd9Sstevel@tonic-gate #include <locale.h>
47*7c478bd9Sstevel@tonic-gate #include <libintl.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/mount.h>
51*7c478bd9Sstevel@tonic-gate #include <devid.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/libdevid.h>
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define	VHCI_CTL_NODE	"/devices/scsi_vhci:devctl"
55*7c478bd9Sstevel@tonic-gate #define	SLASH_DEVICES	"/devices/"
56*7c478bd9Sstevel@tonic-gate #define	SLASH_SSD_AT	"/ssd@"
57*7c478bd9Sstevel@tonic-gate #define	SLASH_FP_AT	"/fp@"
58*7c478bd9Sstevel@tonic-gate #define	SLASH_SCSI_VHCI	"/scsi_vhci"
59*7c478bd9Sstevel@tonic-gate #define	DEV_DSK		"/dev/dsk/"
60*7c478bd9Sstevel@tonic-gate #define	DEV_RDSK	"/dev/rdsk/"
61*7c478bd9Sstevel@tonic-gate #define	SYS_FILENAME_LEN	256
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate /*
64*7c478bd9Sstevel@tonic-gate  * Save directory is the directory in which system files are saved.
65*7c478bd9Sstevel@tonic-gate  * Save directory must be under the root filesystem, as this program is
66*7c478bd9Sstevel@tonic-gate  * typically run before any other filesystems are mounted.
67*7c478bd9Sstevel@tonic-gate  */
68*7c478bd9Sstevel@tonic-gate #define	SAVE_DIR	"/etc/mpxio"
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /* fcp driver publishes this property */
71*7c478bd9Sstevel@tonic-gate #define	NODE_WWN_PROP	"node-wwn"
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate typedef enum {
74*7c478bd9Sstevel@tonic-gate 	CLIENT_TYPE_UNKNOWN,
75*7c478bd9Sstevel@tonic-gate 	CLIENT_TYPE_PHCI,
76*7c478bd9Sstevel@tonic-gate 	CLIENT_TYPE_VHCI
77*7c478bd9Sstevel@tonic-gate } client_type_t;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate struct devlink_cbarg {
80*7c478bd9Sstevel@tonic-gate 	char *devlink;
81*7c478bd9Sstevel@tonic-gate 	size_t len;
82*7c478bd9Sstevel@tonic-gate };
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate static di_node_t devinfo_root = DI_NODE_NIL;
85*7c478bd9Sstevel@tonic-gate static di_devlink_handle_t devlink_hdl = NULL;
86*7c478bd9Sstevel@tonic-gate static int vhci_fd = -1;
87*7c478bd9Sstevel@tonic-gate static int patch_vfstab, cap_m_option, debug;
88*7c478bd9Sstevel@tonic-gate static int list_option, list_guid_mappings, list_controllernum = -1;
89*7c478bd9Sstevel@tonic-gate static char *mapdev = "";
90*7c478bd9Sstevel@tonic-gate static char *stmsboot = "stmsboot";
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate static int make_temp(char *, char *, char *, size_t);
93*7c478bd9Sstevel@tonic-gate static void commit_change(char *, char *, char *, int);
94*7c478bd9Sstevel@tonic-gate static int map_devname(char *, char *, size_t, int);
95*7c478bd9Sstevel@tonic-gate static int update_vfstab(char *, char *);
96*7c478bd9Sstevel@tonic-gate static int list_mappings(int, int);
97*7c478bd9Sstevel@tonic-gate static int canopen(char *);
98*7c478bd9Sstevel@tonic-gate static void logerr(char *, ...);
99*7c478bd9Sstevel@tonic-gate static void logdmsg(char *, ...);
100*7c478bd9Sstevel@tonic-gate static void *s_malloc(const size_t);
101*7c478bd9Sstevel@tonic-gate static char *s_strdup(const char *);
102*7c478bd9Sstevel@tonic-gate static void s_strlcpy(char *, const char *, size_t);
103*7c478bd9Sstevel@tonic-gate static void clean_exit(int);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  * Print usage and exit.
107*7c478bd9Sstevel@tonic-gate  */
108*7c478bd9Sstevel@tonic-gate static void
109*7c478bd9Sstevel@tonic-gate usage(char *argv0)
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	char *progname;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	progname = strrchr(argv0, '/');
114*7c478bd9Sstevel@tonic-gate 	if (progname != NULL)
115*7c478bd9Sstevel@tonic-gate 		progname++;
116*7c478bd9Sstevel@tonic-gate 	else
117*7c478bd9Sstevel@tonic-gate 		progname = argv0;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	/*
120*7c478bd9Sstevel@tonic-gate 	 * -u	update /etc/vfstab
121*7c478bd9Sstevel@tonic-gate 	 * -m devname
122*7c478bd9Sstevel@tonic-gate 	 *	if devname is phci based name and not open-able, map it to
123*7c478bd9Sstevel@tonic-gate 	 *	vhci based /devices name.
124*7c478bd9Sstevel@tonic-gate 	 *	if devname is vhci based name and not open-able, map it to
125*7c478bd9Sstevel@tonic-gate 	 *	phci based /devices name.
126*7c478bd9Sstevel@tonic-gate 	 * -M devname
127*7c478bd9Sstevel@tonic-gate 	 *	same as -m except that /dev link is printed instead of
128*7c478bd9Sstevel@tonic-gate 	 *	/devices name.
129*7c478bd9Sstevel@tonic-gate 	 * -l controller
130*7c478bd9Sstevel@tonic-gate 	 *	list non-STMS to STMS device name mappings for the specific
131*7c478bd9Sstevel@tonic-gate 	 *	controller
132*7c478bd9Sstevel@tonic-gate 	 * -L	list non-STMS to STMS device name mappings for all controllers
133*7c478bd9Sstevel@tonic-gate 	 */
134*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("usage: %s -u | -m devname | "
135*7c478bd9Sstevel@tonic-gate 	    "-M devname | -l controller | -L\n"), progname);
136*7c478bd9Sstevel@tonic-gate 	exit(2);
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate /*
140*7c478bd9Sstevel@tonic-gate  * Parse command line arguments.
141*7c478bd9Sstevel@tonic-gate  */
142*7c478bd9Sstevel@tonic-gate static void
143*7c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[])
144*7c478bd9Sstevel@tonic-gate {
145*7c478bd9Sstevel@tonic-gate 	char opt;
146*7c478bd9Sstevel@tonic-gate 	int n = 0;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	if (argc == 1) {
149*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
150*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
151*7c478bd9Sstevel@tonic-gate 	}
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, "udm:M:Ll:g")) != EOF) {
154*7c478bd9Sstevel@tonic-gate 		switch (opt) {
155*7c478bd9Sstevel@tonic-gate 		case 'u':
156*7c478bd9Sstevel@tonic-gate 			patch_vfstab = 1;
157*7c478bd9Sstevel@tonic-gate 			n++;
158*7c478bd9Sstevel@tonic-gate 			break;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 		case 'd':
161*7c478bd9Sstevel@tonic-gate 			debug = 1;
162*7c478bd9Sstevel@tonic-gate 			break;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 		case 'm':
165*7c478bd9Sstevel@tonic-gate 			mapdev = s_strdup(optarg);
166*7c478bd9Sstevel@tonic-gate 			n++;
167*7c478bd9Sstevel@tonic-gate 			break;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 		case 'M':
170*7c478bd9Sstevel@tonic-gate 			mapdev = s_strdup(optarg);
171*7c478bd9Sstevel@tonic-gate 			cap_m_option = 1;
172*7c478bd9Sstevel@tonic-gate 			n++;
173*7c478bd9Sstevel@tonic-gate 			break;
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 		case 'L':
176*7c478bd9Sstevel@tonic-gate 			list_option = 1;
177*7c478bd9Sstevel@tonic-gate 			n++;
178*7c478bd9Sstevel@tonic-gate 			break;
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 		case 'l':
181*7c478bd9Sstevel@tonic-gate 			list_option = 1;
182*7c478bd9Sstevel@tonic-gate 			list_controllernum = (int)atol(optarg);
183*7c478bd9Sstevel@tonic-gate 			if (list_controllernum < 0) {
184*7c478bd9Sstevel@tonic-gate 				logerr(gettext("controller number %d is "
185*7c478bd9Sstevel@tonic-gate 				    "invalid\n"), list_controllernum);
186*7c478bd9Sstevel@tonic-gate 				clean_exit(1);
187*7c478bd9Sstevel@tonic-gate 			}
188*7c478bd9Sstevel@tonic-gate 			n++;
189*7c478bd9Sstevel@tonic-gate 			break;
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 		case 'g':
192*7c478bd9Sstevel@tonic-gate 			/*
193*7c478bd9Sstevel@tonic-gate 			 * private option to display non-STMS device name
194*7c478bd9Sstevel@tonic-gate 			 * to GUID mappings.
195*7c478bd9Sstevel@tonic-gate 			 */
196*7c478bd9Sstevel@tonic-gate 			list_guid_mappings = 1;
197*7c478bd9Sstevel@tonic-gate 			n++;
198*7c478bd9Sstevel@tonic-gate 			break;
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 		default:
201*7c478bd9Sstevel@tonic-gate 			usage(argv[0]);
202*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
203*7c478bd9Sstevel@tonic-gate 		}
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	if (n != 1)
207*7c478bd9Sstevel@tonic-gate 		usage(argv[0]);
208*7c478bd9Sstevel@tonic-gate 		/*NOTREACHED*/
209*7c478bd9Sstevel@tonic-gate }
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate void
212*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
213*7c478bd9Sstevel@tonic-gate {
214*7c478bd9Sstevel@tonic-gate 	char save_vfstab[SYS_FILENAME_LEN], tmp_vfstab[SYS_FILENAME_LEN];
215*7c478bd9Sstevel@tonic-gate 	int vfstab_updated;
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
218*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	if (getuid() != 0) {
221*7c478bd9Sstevel@tonic-gate 		logerr(gettext("must be super-user to run this program\n"));
222*7c478bd9Sstevel@tonic-gate 		clean_exit(1);
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	parse_args(argc, argv);
226*7c478bd9Sstevel@tonic-gate 	(void) umask(022);
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	/*
229*7c478bd9Sstevel@tonic-gate 	 * NOTE: The mpxio boot-up script executes this program with the
230*7c478bd9Sstevel@tonic-gate 	 * mapping (-m) option before the /usr is even mounted and when the
231*7c478bd9Sstevel@tonic-gate 	 * root filesystem is still mounted read-only.
232*7c478bd9Sstevel@tonic-gate 	 */
233*7c478bd9Sstevel@tonic-gate 	if (*mapdev != '\0') {
234*7c478bd9Sstevel@tonic-gate 		char newname[MAXPATHLEN];
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 		if (map_devname(mapdev, newname, sizeof (newname),
237*7c478bd9Sstevel@tonic-gate 		    cap_m_option) == 0) {
238*7c478bd9Sstevel@tonic-gate 			(void) printf("%s\n", newname);
239*7c478bd9Sstevel@tonic-gate 			clean_exit(0);
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 		clean_exit(1);
242*7c478bd9Sstevel@tonic-gate 	}
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	if (list_option || list_guid_mappings) {
245*7c478bd9Sstevel@tonic-gate 		if (list_mappings(list_controllernum, list_guid_mappings) == 0)
246*7c478bd9Sstevel@tonic-gate 			clean_exit(0);
247*7c478bd9Sstevel@tonic-gate 		clean_exit(1);
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/* create a directory where a copy of the system files are saved */
251*7c478bd9Sstevel@tonic-gate 	if (patch_vfstab) {
252*7c478bd9Sstevel@tonic-gate 		if (mkdirp(SAVE_DIR, 0755) != 0 && errno != EEXIST) {
253*7c478bd9Sstevel@tonic-gate 			logerr(gettext("mkdirp: failed to create %1$s: %2$s\n"),
254*7c478bd9Sstevel@tonic-gate 			    SAVE_DIR, strerror(errno));
255*7c478bd9Sstevel@tonic-gate 			clean_exit(1);
256*7c478bd9Sstevel@tonic-gate 		}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 		if (make_temp(VFSTAB, save_vfstab, tmp_vfstab,
259*7c478bd9Sstevel@tonic-gate 		    SYS_FILENAME_LEN) != 0)
260*7c478bd9Sstevel@tonic-gate 			clean_exit(1);
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 		/* build new vfstab without modifying the existing one */
263*7c478bd9Sstevel@tonic-gate 		if ((vfstab_updated = update_vfstab(VFSTAB, tmp_vfstab))
264*7c478bd9Sstevel@tonic-gate 		    == -1) {
265*7c478bd9Sstevel@tonic-gate 			logerr(gettext("failed to update %s\n"), VFSTAB);
266*7c478bd9Sstevel@tonic-gate 			clean_exit(1);
267*7c478bd9Sstevel@tonic-gate 		}
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 		commit_change(VFSTAB, save_vfstab, tmp_vfstab, vfstab_updated);
270*7c478bd9Sstevel@tonic-gate 	}
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	clean_exit(0);
273*7c478bd9Sstevel@tonic-gate }
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate /*
276*7c478bd9Sstevel@tonic-gate  * Make saved and temporary filenames in SAVE_DIR.
277*7c478bd9Sstevel@tonic-gate  *
278*7c478bd9Sstevel@tonic-gate  * ex: if the filename is /etc/vfstab then the save_filename and tmp_filename
279*7c478bd9Sstevel@tonic-gate  * would be SAVE_DIR/vfstab and SAVE_DIR/vfstab.tmp respectively.
280*7c478bd9Sstevel@tonic-gate  *
281*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
282*7c478bd9Sstevel@tonic-gate  */
283*7c478bd9Sstevel@tonic-gate static int
284*7c478bd9Sstevel@tonic-gate make_temp(char *filename, char *save_filename, char *tmp_filename, size_t len)
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate 	char *ptr;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	if ((ptr = strrchr(filename, '/')) == NULL) {
289*7c478bd9Sstevel@tonic-gate 		logdmsg("invalid file %s\n", filename);
290*7c478bd9Sstevel@tonic-gate 		return (-1);
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 	(void) snprintf(save_filename, len, "%s%s", SAVE_DIR, ptr);
293*7c478bd9Sstevel@tonic-gate 	(void) snprintf(tmp_filename, len, "%s%s.tmp", SAVE_DIR, ptr);
294*7c478bd9Sstevel@tonic-gate 	logdmsg("make_temp: %s: save = %s, temp = %s\n", filename,
295*7c478bd9Sstevel@tonic-gate 	    save_filename, tmp_filename);
296*7c478bd9Sstevel@tonic-gate 	return (0);
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate /*
300*7c478bd9Sstevel@tonic-gate  * Commit the changes made to the system file
301*7c478bd9Sstevel@tonic-gate  */
302*7c478bd9Sstevel@tonic-gate static void
303*7c478bd9Sstevel@tonic-gate commit_change(char *filename, char *save_filename, char *tmp_filename,
304*7c478bd9Sstevel@tonic-gate     int updated)
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 	int x;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	if (updated) {
309*7c478bd9Sstevel@tonic-gate 		/* save the original */
310*7c478bd9Sstevel@tonic-gate 		if ((x = rename(filename, save_filename)) != 0) {
311*7c478bd9Sstevel@tonic-gate 			logerr(gettext("rename %1$s to %2$s failed: %3$s\n"),
312*7c478bd9Sstevel@tonic-gate 			    filename, save_filename, strerror(errno));
313*7c478bd9Sstevel@tonic-gate 		}
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 		/* now rename the new file to the actual file */
316*7c478bd9Sstevel@tonic-gate 		if (rename(tmp_filename, filename) != 0) {
317*7c478bd9Sstevel@tonic-gate 			logerr(gettext("rename %1$s to %2$s failed: %3$s\n"),
318*7c478bd9Sstevel@tonic-gate 			    tmp_filename, filename, strerror(errno));
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 			/* restore the original */
321*7c478bd9Sstevel@tonic-gate 			if (x == 0 && rename(save_filename, filename) != 0) {
322*7c478bd9Sstevel@tonic-gate 				logerr(
323*7c478bd9Sstevel@tonic-gate 				    gettext("rename %1$s to %2$s failed: %3$s\n"
324*7c478bd9Sstevel@tonic-gate 				    "%4$s is a copy of the original %5$s file"
325*7c478bd9Sstevel@tonic-gate 				    "\n"),
326*7c478bd9Sstevel@tonic-gate 				    save_filename, filename, strerror(errno),
327*7c478bd9Sstevel@tonic-gate 				    save_filename, filename);
328*7c478bd9Sstevel@tonic-gate 			}
329*7c478bd9Sstevel@tonic-gate 		} else
330*7c478bd9Sstevel@tonic-gate 			(void) printf(gettext("%1$s: %2$s has been updated.\n"),
331*7c478bd9Sstevel@tonic-gate 			    stmsboot, filename);
332*7c478bd9Sstevel@tonic-gate 	} else {
333*7c478bd9Sstevel@tonic-gate 		/* remove the temp file */
334*7c478bd9Sstevel@tonic-gate 		(void) unlink(tmp_filename);
335*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext("%1$s: %2$s was not modified as no "
336*7c478bd9Sstevel@tonic-gate 		    "changes were needed.\n"), stmsboot, filename);
337*7c478bd9Sstevel@tonic-gate 	}
338*7c478bd9Sstevel@tonic-gate }
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate /*
341*7c478bd9Sstevel@tonic-gate  * Get the GUID of the device.
342*7c478bd9Sstevel@tonic-gate  *
343*7c478bd9Sstevel@tonic-gate  * physpath	/devices name without the /devices prefix and minor name
344*7c478bd9Sstevel@tonic-gate  *		component.
345*7c478bd9Sstevel@tonic-gate  * guid		caller supplied buffer where the GUID will be placed on return
346*7c478bd9Sstevel@tonic-gate  * guid_len	length of the caller supplied guid buffer.
347*7c478bd9Sstevel@tonic-gate  * no_dealy_flag if set open the device with O_NDELAY
348*7c478bd9Sstevel@tonic-gate  * node		di_node corresponding to physpath if already available,
349*7c478bd9Sstevel@tonic-gate  *		otherwise pass DI_NODE_NIL.
350*7c478bd9Sstevel@tonic-gate  *
351*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
352*7c478bd9Sstevel@tonic-gate  */
353*7c478bd9Sstevel@tonic-gate static int
354*7c478bd9Sstevel@tonic-gate get_guid(char *physpath, char *guid, int guid_len, int no_delay_flag,
355*7c478bd9Sstevel@tonic-gate 	di_node_t node)
356*7c478bd9Sstevel@tonic-gate {
357*7c478bd9Sstevel@tonic-gate 	int		fd;
358*7c478bd9Sstevel@tonic-gate 	ddi_devid_t	devid;
359*7c478bd9Sstevel@tonic-gate 	int		rv	= -1;
360*7c478bd9Sstevel@tonic-gate 	char		*i_guid	= NULL;
361*7c478bd9Sstevel@tonic-gate 	char		physpath_raw[MAXPATHLEN];
362*7c478bd9Sstevel@tonic-gate 	uchar_t		*wwnp;
363*7c478bd9Sstevel@tonic-gate 	int		i, n, snapshot_taken = 0;
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	logdmsg("get_guid: physpath = %s\n", physpath);
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 	(void) snprintf(physpath_raw, MAXPATHLEN,
368*7c478bd9Sstevel@tonic-gate 	    "/devices%s:a,raw", physpath);
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	*guid = '\0';
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	if (no_delay_flag)
373*7c478bd9Sstevel@tonic-gate 		no_delay_flag = O_NDELAY;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	/*
376*7c478bd9Sstevel@tonic-gate 	 * Open the raw device
377*7c478bd9Sstevel@tonic-gate 	 * Without the O_DELAY flag, the open will fail on standby paths of
378*7c478bd9Sstevel@tonic-gate 	 * T3 if its mp_support mode is "mpxio".
379*7c478bd9Sstevel@tonic-gate 	 */
380*7c478bd9Sstevel@tonic-gate 	if ((fd = open(physpath_raw, O_RDONLY | no_delay_flag)) == -1) {
381*7c478bd9Sstevel@tonic-gate 		logdmsg("get_guid: failed to open %s: %s\n", physpath_raw,
382*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
383*7c478bd9Sstevel@tonic-gate 		return (-1);
384*7c478bd9Sstevel@tonic-gate 	}
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	if (devid_get(fd, &devid) == 0) {
387*7c478bd9Sstevel@tonic-gate 		i_guid = devid_to_guid(devid);
388*7c478bd9Sstevel@tonic-gate 		devid_free(devid);
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 		if (i_guid != NULL) {
391*7c478bd9Sstevel@tonic-gate 			s_strlcpy(guid, i_guid, guid_len);
392*7c478bd9Sstevel@tonic-gate 			devid_free_guid(i_guid);
393*7c478bd9Sstevel@tonic-gate 			rv = 0;
394*7c478bd9Sstevel@tonic-gate 			goto out;
395*7c478bd9Sstevel@tonic-gate 		} else
396*7c478bd9Sstevel@tonic-gate 			logdmsg("get_guid: devid_to_guid() failed\n");
397*7c478bd9Sstevel@tonic-gate 	} else
398*7c478bd9Sstevel@tonic-gate 		logdmsg("get_guid: devid_get() failed: %s\n", strerror(errno));
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	/* fallback to node name as the guid as this is what fcp driver does */
401*7c478bd9Sstevel@tonic-gate 	if (node == DI_NODE_NIL) {
402*7c478bd9Sstevel@tonic-gate 		if ((node = di_init(physpath, DINFOCPYALL | DINFOFORCE))
403*7c478bd9Sstevel@tonic-gate 		    == DI_NODE_NIL) {
404*7c478bd9Sstevel@tonic-gate 			logdmsg("get_guid: di_init on %s failed: %s\n",
405*7c478bd9Sstevel@tonic-gate 			    physpath, strerror(errno));
406*7c478bd9Sstevel@tonic-gate 			goto out;
407*7c478bd9Sstevel@tonic-gate 		}
408*7c478bd9Sstevel@tonic-gate 		snapshot_taken = 1;
409*7c478bd9Sstevel@tonic-gate 	}
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	if ((n = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, NODE_WWN_PROP,
412*7c478bd9Sstevel@tonic-gate 	    &wwnp)) == -1) {
413*7c478bd9Sstevel@tonic-gate 		logdmsg("get_guid: di_prop_lookup_bytes() failed to lookup "
414*7c478bd9Sstevel@tonic-gate 		    "%s: %s\n", NODE_WWN_PROP, strerror(errno));
415*7c478bd9Sstevel@tonic-gate 		goto out;
416*7c478bd9Sstevel@tonic-gate 	}
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	if (guid_len >= ((n * 2) + 1)) {
419*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < n; i++) {
420*7c478bd9Sstevel@tonic-gate 			(void) sprintf(guid + (i * 2), "%02x", (uint_t)(*wwnp));
421*7c478bd9Sstevel@tonic-gate 			wwnp++;
422*7c478bd9Sstevel@tonic-gate 		}
423*7c478bd9Sstevel@tonic-gate 		rv = 0;
424*7c478bd9Sstevel@tonic-gate 	} else
425*7c478bd9Sstevel@tonic-gate 		logerr(gettext("insufficient buffer size: need %1$d "
426*7c478bd9Sstevel@tonic-gate 		    "bytes, passed %2$d bytes\n"), (n * 2) + 1, guid_len);
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate out:
429*7c478bd9Sstevel@tonic-gate 	if (snapshot_taken)
430*7c478bd9Sstevel@tonic-gate 		di_fini(node);
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
433*7c478bd9Sstevel@tonic-gate 	logdmsg("get_guid: GUID = %s\n", guid);
434*7c478bd9Sstevel@tonic-gate 	return (rv);
435*7c478bd9Sstevel@tonic-gate }
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate /*
438*7c478bd9Sstevel@tonic-gate  * Given client_name return whether it is a phci or vhci based name.
439*7c478bd9Sstevel@tonic-gate  * client_name is /devices name of a client without the /devices prefix.
440*7c478bd9Sstevel@tonic-gate  *
441*7c478bd9Sstevel@tonic-gate  * client_name			Return value
442*7c478bd9Sstevel@tonic-gate  * .../fp@xxx/ssd@yyy		CLIENT_TYPE_PHCI
443*7c478bd9Sstevel@tonic-gate  * .../scsi_vhci/ssd@yyy	CLIENT_TYPE_VHCI
444*7c478bd9Sstevel@tonic-gate  * other			CLIENT_TYPE_UNKNOWN
445*7c478bd9Sstevel@tonic-gate  */
446*7c478bd9Sstevel@tonic-gate static client_type_t
447*7c478bd9Sstevel@tonic-gate client_name_type(char *client_name)
448*7c478bd9Sstevel@tonic-gate {
449*7c478bd9Sstevel@tonic-gate 	client_type_t client_type = CLIENT_TYPE_UNKNOWN;
450*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	if (*client_name != '/')
453*7c478bd9Sstevel@tonic-gate 		return (CLIENT_TYPE_UNKNOWN);
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	/* we only care for ssd devices */
456*7c478bd9Sstevel@tonic-gate 	if ((p1 = strrchr(client_name, '/')) == NULL ||
457*7c478bd9Sstevel@tonic-gate 	    strncmp(p1, SLASH_SSD_AT, sizeof (SLASH_SSD_AT) - 1) != 0)
458*7c478bd9Sstevel@tonic-gate 		return (CLIENT_TYPE_UNKNOWN);
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	*p1 = '\0';
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	if ((p2 = strrchr(client_name, '/')) != NULL) {
463*7c478bd9Sstevel@tonic-gate 		if (strncmp(p2, SLASH_FP_AT, sizeof (SLASH_FP_AT) - 1) == 0)
464*7c478bd9Sstevel@tonic-gate 			client_type = CLIENT_TYPE_PHCI;
465*7c478bd9Sstevel@tonic-gate 		else if (strncmp(p2, SLASH_SCSI_VHCI,
466*7c478bd9Sstevel@tonic-gate 		    sizeof (SLASH_SCSI_VHCI) - 1) == 0)
467*7c478bd9Sstevel@tonic-gate 			client_type = CLIENT_TYPE_VHCI;
468*7c478bd9Sstevel@tonic-gate 	}
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 	*p1 = '/';
471*7c478bd9Sstevel@tonic-gate 	return (client_type);
472*7c478bd9Sstevel@tonic-gate }
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate /*
475*7c478bd9Sstevel@tonic-gate  * Map phci based client name to vhci based client name.
476*7c478bd9Sstevel@tonic-gate  *
477*7c478bd9Sstevel@tonic-gate  * phci_name
478*7c478bd9Sstevel@tonic-gate  *	phci based client /devices name without the /devices prefix and
479*7c478bd9Sstevel@tonic-gate  *	minor name component.
480*7c478bd9Sstevel@tonic-gate  *	ex: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0
481*7c478bd9Sstevel@tonic-gate  *
482*7c478bd9Sstevel@tonic-gate  * vhci_name
483*7c478bd9Sstevel@tonic-gate  *	Caller supplied buffer where vhci /devices name will be placed on
484*7c478bd9Sstevel@tonic-gate  *	return (without the /devices prefix and minor name component).
485*7c478bd9Sstevel@tonic-gate  *	ex: /scsi_vhci/ssd@g2000002037cd9f72
486*7c478bd9Sstevel@tonic-gate  *
487*7c478bd9Sstevel@tonic-gate  * vhci_name_len
488*7c478bd9Sstevel@tonic-gate  *	Length of the caller supplied vhci_name buffer.
489*7c478bd9Sstevel@tonic-gate  *
490*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
491*7c478bd9Sstevel@tonic-gate  */
492*7c478bd9Sstevel@tonic-gate static int
493*7c478bd9Sstevel@tonic-gate phci_to_vhci(char *phci_name, char *vhci_name, size_t vhci_name_len)
494*7c478bd9Sstevel@tonic-gate {
495*7c478bd9Sstevel@tonic-gate 	sv_iocdata_t ioc;
496*7c478bd9Sstevel@tonic-gate 	char *slash;
497*7c478bd9Sstevel@tonic-gate 	char vhci_name_buf[MAXPATHLEN];
498*7c478bd9Sstevel@tonic-gate 	char phci_name_buf[MAXPATHLEN];
499*7c478bd9Sstevel@tonic-gate 	char addr_buf[MAXNAMELEN];
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	logdmsg("phci_to_vhci: client = %s\n", phci_name);
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	s_strlcpy(phci_name_buf, phci_name, MAXPATHLEN);
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	if (client_name_type(phci_name_buf) != CLIENT_TYPE_PHCI ||
506*7c478bd9Sstevel@tonic-gate 	    (slash = strrchr(phci_name_buf, '/')) == NULL ||
507*7c478bd9Sstevel@tonic-gate 	    strncmp(slash, SLASH_SSD_AT, sizeof (SLASH_SSD_AT) - 1) != 0) {
508*7c478bd9Sstevel@tonic-gate 		logdmsg("phci_to_vhci: %s is not of CLIENT_TYPE_PHCI\n",
509*7c478bd9Sstevel@tonic-gate 		    phci_name);
510*7c478bd9Sstevel@tonic-gate 		return (-1);
511*7c478bd9Sstevel@tonic-gate 	}
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 	if (vhci_fd < 0) {
514*7c478bd9Sstevel@tonic-gate 		if ((vhci_fd = open(VHCI_CTL_NODE, O_RDWR)) < 0)
515*7c478bd9Sstevel@tonic-gate 			return (-1);
516*7c478bd9Sstevel@tonic-gate 	}
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	*slash = '\0';
519*7c478bd9Sstevel@tonic-gate 	s_strlcpy(addr_buf, slash + sizeof (SLASH_SSD_AT) - 1, MAXNAMELEN);
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 	bzero(&ioc, sizeof (sv_iocdata_t));
522*7c478bd9Sstevel@tonic-gate 	ioc.client = vhci_name_buf;
523*7c478bd9Sstevel@tonic-gate 	ioc.phci = phci_name_buf;
524*7c478bd9Sstevel@tonic-gate 	ioc.addr = addr_buf;
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	if (ioctl(vhci_fd, SCSI_VHCI_GET_CLIENT_NAME, &ioc) != 0) {
527*7c478bd9Sstevel@tonic-gate 		logdmsg("SCSI_VHCI_GET_CLIENT_NAME on %s "
528*7c478bd9Sstevel@tonic-gate 		    "failed: %s\n", phci_name, strerror(errno));
529*7c478bd9Sstevel@tonic-gate 		return (-1);
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	s_strlcpy(vhci_name, vhci_name_buf, vhci_name_len);
533*7c478bd9Sstevel@tonic-gate 	logdmsg("phci_to_vhci: %s maps to %s\n", phci_name, vhci_name);
534*7c478bd9Sstevel@tonic-gate 	return (0);
535*7c478bd9Sstevel@tonic-gate }
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate /*
538*7c478bd9Sstevel@tonic-gate  * Map vhci based client name to phci based client name.
539*7c478bd9Sstevel@tonic-gate  * If the client has multiple paths, only one of the paths with which client
540*7c478bd9Sstevel@tonic-gate  * can be accessed is returned. This function does not use SCSI_VHCI ioctls
541*7c478bd9Sstevel@tonic-gate  * as it is called on mpxio disabled paths.
542*7c478bd9Sstevel@tonic-gate  *
543*7c478bd9Sstevel@tonic-gate  * vhci_name
544*7c478bd9Sstevel@tonic-gate  *	vhci based client /devices name without the /devices prefix and
545*7c478bd9Sstevel@tonic-gate  *	minor name component.
546*7c478bd9Sstevel@tonic-gate  *	ex: /scsi_vhci/ssd@g2000002037cd9f72
547*7c478bd9Sstevel@tonic-gate  *
548*7c478bd9Sstevel@tonic-gate  * phci_name
549*7c478bd9Sstevel@tonic-gate  *	Caller supplied buffer where phci /devices name will be placed on
550*7c478bd9Sstevel@tonic-gate  *	return (without the /devices prefix and minor name component).
551*7c478bd9Sstevel@tonic-gate  *	ex: /pci@8,600000/SUNW,qlc@4/fp@0,0/ssd@w2100002037cd9f72,0
552*7c478bd9Sstevel@tonic-gate  *
553*7c478bd9Sstevel@tonic-gate  * phci_name_len
554*7c478bd9Sstevel@tonic-gate  *	Length of the caller supplied phci_name buffer.
555*7c478bd9Sstevel@tonic-gate  *
556*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
557*7c478bd9Sstevel@tonic-gate  */
558*7c478bd9Sstevel@tonic-gate static int
559*7c478bd9Sstevel@tonic-gate vhci_to_phci(char *vhci_name, char *phci_name, size_t phci_name_len)
560*7c478bd9Sstevel@tonic-gate {
561*7c478bd9Sstevel@tonic-gate 	di_node_t node, parent;
562*7c478bd9Sstevel@tonic-gate 	char *vhci_guid, *devfspath;
563*7c478bd9Sstevel@tonic-gate 	char phci_guid[MAXPATHLEN];
564*7c478bd9Sstevel@tonic-gate 	char *parent_name, *node_name;
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	logdmsg("vhci_to_phci: client = %s\n", vhci_name);
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	if (client_name_type(vhci_name) != CLIENT_TYPE_VHCI) {
569*7c478bd9Sstevel@tonic-gate 		logdmsg("vhci_to_phci: %s is not of CLIENT_TYPE_VHCI\n",
570*7c478bd9Sstevel@tonic-gate 		    vhci_name);
571*7c478bd9Sstevel@tonic-gate 		return (-1);
572*7c478bd9Sstevel@tonic-gate 	}
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate 	if ((vhci_guid = strrchr(vhci_name, '@')) == NULL ||
575*7c478bd9Sstevel@tonic-gate 	    *(++vhci_guid) != 'g') {
576*7c478bd9Sstevel@tonic-gate 		logerr(gettext("couldn't get guid from %s\n"), vhci_name);
577*7c478bd9Sstevel@tonic-gate 		return (-1);
578*7c478bd9Sstevel@tonic-gate 	}
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 	/* point to guid */
581*7c478bd9Sstevel@tonic-gate 	++vhci_guid;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	/*
584*7c478bd9Sstevel@tonic-gate 	 * Get devinfo snapshot and walk all ssd nodes whose parent is fp.
585*7c478bd9Sstevel@tonic-gate 	 * For each node get the guid and match it with vhci_guid.
586*7c478bd9Sstevel@tonic-gate 	 */
587*7c478bd9Sstevel@tonic-gate 	if (devinfo_root == DI_NODE_NIL) {
588*7c478bd9Sstevel@tonic-gate 		logdmsg("vhci_to_phci: taking devinfo snapshot\n");
589*7c478bd9Sstevel@tonic-gate 		if ((devinfo_root = di_init("/", DINFOCPYALL | DINFOFORCE))
590*7c478bd9Sstevel@tonic-gate 		    == DI_NODE_NIL) {
591*7c478bd9Sstevel@tonic-gate 			logerr(gettext("di_init failed: %s\n"),
592*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
593*7c478bd9Sstevel@tonic-gate 			return (-1);
594*7c478bd9Sstevel@tonic-gate 		}
595*7c478bd9Sstevel@tonic-gate 		logdmsg("vhci_to_phci: done taking devinfo snapshot\n");
596*7c478bd9Sstevel@tonic-gate 	}
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	for (node = di_drv_first_node("ssd", devinfo_root);
599*7c478bd9Sstevel@tonic-gate 	    node != DI_NODE_NIL; node = di_drv_next_node(node)) {
600*7c478bd9Sstevel@tonic-gate 		if ((node_name = di_node_name(node)) == NULL ||
601*7c478bd9Sstevel@tonic-gate 		    strcmp(node_name, "ssd") != 0 ||
602*7c478bd9Sstevel@tonic-gate 		    (parent = di_parent_node(node)) == DI_NODE_NIL ||
603*7c478bd9Sstevel@tonic-gate 		    (parent_name = di_node_name(parent)) == NULL ||
604*7c478bd9Sstevel@tonic-gate 		    strcmp(parent_name, "fp") != 0 ||
605*7c478bd9Sstevel@tonic-gate 		    (devfspath = di_devfs_path(node)) == NULL)
606*7c478bd9Sstevel@tonic-gate 			continue;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		/*
609*7c478bd9Sstevel@tonic-gate 		 * Don't set no_delay_flag to have get_guid() fail on
610*7c478bd9Sstevel@tonic-gate 		 * standby paths of T3. So we'll find the preferred paths.
611*7c478bd9Sstevel@tonic-gate 		 */
612*7c478bd9Sstevel@tonic-gate 		if (get_guid(devfspath, phci_guid,
613*7c478bd9Sstevel@tonic-gate 		    sizeof (phci_guid), 0, node) == 0 &&
614*7c478bd9Sstevel@tonic-gate 		    strcmp(phci_guid, vhci_guid) == 0) {
615*7c478bd9Sstevel@tonic-gate 			s_strlcpy(phci_name, devfspath, phci_name_len);
616*7c478bd9Sstevel@tonic-gate 			di_devfs_path_free(devfspath);
617*7c478bd9Sstevel@tonic-gate 			logdmsg("vhci_to_phci: %s maps to %s\n", vhci_name,
618*7c478bd9Sstevel@tonic-gate 			    phci_name);
619*7c478bd9Sstevel@tonic-gate 			return (0);
620*7c478bd9Sstevel@tonic-gate 		}
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 		di_devfs_path_free(devfspath);
623*7c478bd9Sstevel@tonic-gate 	}
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	logdmsg("vhci_to_phci: couldn't get phci name for %s\n", vhci_name);
626*7c478bd9Sstevel@tonic-gate 	return (-1);
627*7c478bd9Sstevel@tonic-gate }
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate /*
630*7c478bd9Sstevel@tonic-gate  * Map physname from phci name space to vhci name space or vice-versa
631*7c478bd9Sstevel@tonic-gate  *
632*7c478bd9Sstevel@tonic-gate  * physname
633*7c478bd9Sstevel@tonic-gate  *	phci or vhci based client /devices name without the /devices prefix and
634*7c478bd9Sstevel@tonic-gate  *	minor name component.
635*7c478bd9Sstevel@tonic-gate  *
636*7c478bd9Sstevel@tonic-gate  * new_physname
637*7c478bd9Sstevel@tonic-gate  *	Caller supplied buffer where the mapped physical name is stored on
638*7c478bd9Sstevel@tonic-gate  *	return (without the /devices prefix and minor name component).
639*7c478bd9Sstevel@tonic-gate  *
640*7c478bd9Sstevel@tonic-gate  * len
641*7c478bd9Sstevel@tonic-gate  *	Length of the caller supplied new_physname buffer.
642*7c478bd9Sstevel@tonic-gate  *
643*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
644*7c478bd9Sstevel@tonic-gate  */
645*7c478bd9Sstevel@tonic-gate static int
646*7c478bd9Sstevel@tonic-gate map_physname(char *physname, char *new_physname, size_t len)
647*7c478bd9Sstevel@tonic-gate {
648*7c478bd9Sstevel@tonic-gate 	int type;
649*7c478bd9Sstevel@tonic-gate 	int rv;
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	if ((type = client_name_type(physname)) == CLIENT_TYPE_VHCI)
652*7c478bd9Sstevel@tonic-gate 		rv = vhci_to_phci(physname, new_physname, len);
653*7c478bd9Sstevel@tonic-gate 	else if (type == CLIENT_TYPE_PHCI)
654*7c478bd9Sstevel@tonic-gate 		rv = phci_to_vhci(physname, new_physname, len);
655*7c478bd9Sstevel@tonic-gate 	else
656*7c478bd9Sstevel@tonic-gate 		rv = -1;
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate 	return (rv);
659*7c478bd9Sstevel@tonic-gate }
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate /*
662*7c478bd9Sstevel@tonic-gate  * Given a phci or vhci devname which is either a /dev link or /devices name
663*7c478bd9Sstevel@tonic-gate  * get the corresponding physical node path (without the /devices prefix)
664*7c478bd9Sstevel@tonic-gate  * and minor name.
665*7c478bd9Sstevel@tonic-gate  *
666*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
667*7c478bd9Sstevel@tonic-gate  */
668*7c478bd9Sstevel@tonic-gate static int
669*7c478bd9Sstevel@tonic-gate get_physname_minor(char *devname, char *physname, int physname_len,
670*7c478bd9Sstevel@tonic-gate     char *minorname, int minorname_len)
671*7c478bd9Sstevel@tonic-gate {
672*7c478bd9Sstevel@tonic-gate 	int linksize;
673*7c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
674*7c478bd9Sstevel@tonic-gate 	char *p, *m;
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	if (strncmp(devname, DEV_DSK, sizeof (DEV_DSK) - 1) == 0 ||
677*7c478bd9Sstevel@tonic-gate 	    strncmp(devname, DEV_RDSK, sizeof (DEV_RDSK) - 1) == 0) {
678*7c478bd9Sstevel@tonic-gate 		if ((linksize = readlink(devname, buf, MAXPATHLEN))
679*7c478bd9Sstevel@tonic-gate 		    > 0 && linksize <= (MAXPATHLEN - 1)) {
680*7c478bd9Sstevel@tonic-gate 			buf[linksize] = '\0';
681*7c478bd9Sstevel@tonic-gate 		} else
682*7c478bd9Sstevel@tonic-gate 			return (-1);
683*7c478bd9Sstevel@tonic-gate 	} else
684*7c478bd9Sstevel@tonic-gate 		s_strlcpy(buf, devname, MAXPATHLEN);
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	if ((p = strstr(buf, SLASH_DEVICES)) == NULL)
687*7c478bd9Sstevel@tonic-gate 		return (-1);
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	/* point to '/' after /devices */
690*7c478bd9Sstevel@tonic-gate 	p += sizeof (SLASH_DEVICES) - 2;
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate 	if ((m = strrchr(p, ':')) == NULL) {
693*7c478bd9Sstevel@tonic-gate 		logdmsg("get_physname_minor: no minor name component in %s\n",
694*7c478bd9Sstevel@tonic-gate 		    buf);
695*7c478bd9Sstevel@tonic-gate 		return (-1);
696*7c478bd9Sstevel@tonic-gate 	}
697*7c478bd9Sstevel@tonic-gate 
698*7c478bd9Sstevel@tonic-gate 	*m = '\0';
699*7c478bd9Sstevel@tonic-gate 	m++;
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	if (client_name_type(p) == CLIENT_TYPE_UNKNOWN)
702*7c478bd9Sstevel@tonic-gate 		return (-1);
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	s_strlcpy(physname, p, physname_len);
705*7c478bd9Sstevel@tonic-gate 	s_strlcpy(minorname, m, minorname_len);
706*7c478bd9Sstevel@tonic-gate 	logdmsg("get_physname_minor: %s: physname = %s, minor = %s\n",
707*7c478bd9Sstevel@tonic-gate 	    devname, physname, minorname);
708*7c478bd9Sstevel@tonic-gate 	return (0);
709*7c478bd9Sstevel@tonic-gate }
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate static int
712*7c478bd9Sstevel@tonic-gate devlink_callback(di_devlink_t devlink, void *argptr)
713*7c478bd9Sstevel@tonic-gate {
714*7c478bd9Sstevel@tonic-gate 	const char *link;
715*7c478bd9Sstevel@tonic-gate 	struct devlink_cbarg *argp = argptr;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	if ((link = di_devlink_path(devlink)) != NULL) {
718*7c478bd9Sstevel@tonic-gate 		s_strlcpy(argp->devlink, link, argp->len);
719*7c478bd9Sstevel@tonic-gate 		return (DI_WALK_TERMINATE);
720*7c478bd9Sstevel@tonic-gate 	}
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	return (DI_WALK_CONTINUE);
723*7c478bd9Sstevel@tonic-gate }
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate /*
726*7c478bd9Sstevel@tonic-gate  * Lookup the /dev link corresponding to physname and minorname.
727*7c478bd9Sstevel@tonic-gate  *
728*7c478bd9Sstevel@tonic-gate  * physname	client /devices path without the /devices prefix and minor
729*7c478bd9Sstevel@tonic-gate  *		name component.
730*7c478bd9Sstevel@tonic-gate  * minorname	client minor name.
731*7c478bd9Sstevel@tonic-gate  * devlink	caller supplied buffer where the /dev link is placed on return.
732*7c478bd9Sstevel@tonic-gate  * len		caller supplied devlink buffer length
733*7c478bd9Sstevel@tonic-gate  *
734*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
735*7c478bd9Sstevel@tonic-gate  */
736*7c478bd9Sstevel@tonic-gate static int
737*7c478bd9Sstevel@tonic-gate lookup_devlink(char *physname, char *minorname, char *devlink, size_t len)
738*7c478bd9Sstevel@tonic-gate {
739*7c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
740*7c478bd9Sstevel@tonic-gate 	struct devlink_cbarg arg;
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	if (devlink_hdl == NULL) {
743*7c478bd9Sstevel@tonic-gate 		logdmsg("lookup_devlink: taking devlink snapshot\n");
744*7c478bd9Sstevel@tonic-gate 		if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
745*7c478bd9Sstevel@tonic-gate 			logerr(gettext("di_devlink_init failed: %s\n"),
746*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
747*7c478bd9Sstevel@tonic-gate 			clean_exit(1);
748*7c478bd9Sstevel@tonic-gate 		}
749*7c478bd9Sstevel@tonic-gate 	}
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 	*devlink = '\0';
752*7c478bd9Sstevel@tonic-gate 	(void) snprintf(buf, MAXPATHLEN, "%s:%s", physname, minorname);
753*7c478bd9Sstevel@tonic-gate 	arg.devlink = devlink;
754*7c478bd9Sstevel@tonic-gate 	arg.len = len;
755*7c478bd9Sstevel@tonic-gate 	if (di_devlink_walk(devlink_hdl, NULL, buf, DI_PRIMARY_LINK, &arg,
756*7c478bd9Sstevel@tonic-gate 	    devlink_callback) != 0) {
757*7c478bd9Sstevel@tonic-gate 		logdmsg("lookup_devlink: di_devlink_walk on %s failed: %s\n",
758*7c478bd9Sstevel@tonic-gate 		    buf, strerror(errno));
759*7c478bd9Sstevel@tonic-gate 		return (-1);
760*7c478bd9Sstevel@tonic-gate 	}
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate 	if (*devlink == '\0') {
763*7c478bd9Sstevel@tonic-gate 		logdmsg("lookup_devlink: failed to lookup devlink for %s\n",
764*7c478bd9Sstevel@tonic-gate 		    buf);
765*7c478bd9Sstevel@tonic-gate 		return (-1);
766*7c478bd9Sstevel@tonic-gate 	}
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 	logdmsg("lookup_devlink: /dev link for %s:%s = %s\n", physname,
769*7c478bd9Sstevel@tonic-gate 	    minorname, devlink);
770*7c478bd9Sstevel@tonic-gate 	return (0);
771*7c478bd9Sstevel@tonic-gate }
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate /*
774*7c478bd9Sstevel@tonic-gate  * open infile for reading and return its file pointer in *fp_in.
775*7c478bd9Sstevel@tonic-gate  * open outfile for writing and return its file pointer in *fp_out.
776*7c478bd9Sstevel@tonic-gate  *
777*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
778*7c478bd9Sstevel@tonic-gate  */
779*7c478bd9Sstevel@tonic-gate static int
780*7c478bd9Sstevel@tonic-gate open_in_out_files(char *infile, char *outfile, FILE **fp_in, FILE **fp_out)
781*7c478bd9Sstevel@tonic-gate {
782*7c478bd9Sstevel@tonic-gate 	FILE *fin = NULL;
783*7c478bd9Sstevel@tonic-gate 	FILE *fout = NULL;
784*7c478bd9Sstevel@tonic-gate 	struct stat sbuf;
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	if ((fin = fopen(infile, "r")) == NULL) {
787*7c478bd9Sstevel@tonic-gate 		logerr(gettext("failed to fopen %1$s: %2$s\n"),
788*7c478bd9Sstevel@tonic-gate 		    infile, strerror(errno));
789*7c478bd9Sstevel@tonic-gate 		goto out;
790*7c478bd9Sstevel@tonic-gate 	}
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	if (fstat(fileno(fin), &sbuf) != 0) {
793*7c478bd9Sstevel@tonic-gate 		logerr(gettext("fstat failed on %1$s: %2$s\n"),
794*7c478bd9Sstevel@tonic-gate 		    infile, strerror(errno));
795*7c478bd9Sstevel@tonic-gate 		goto out;
796*7c478bd9Sstevel@tonic-gate 	}
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 	if ((fout = fopen(outfile, "w")) == NULL) {
799*7c478bd9Sstevel@tonic-gate 		logerr(gettext("failed to fopen %1$s: %2$s\n"),
800*7c478bd9Sstevel@tonic-gate 		    outfile, strerror(errno));
801*7c478bd9Sstevel@tonic-gate 		goto out;
802*7c478bd9Sstevel@tonic-gate 	}
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	if (fchmod(fileno(fout), (sbuf.st_mode & 0777)) != 0) {
805*7c478bd9Sstevel@tonic-gate 		logerr(gettext("failed to fchmod %1$s to 0%2$o: %3$s\n"),
806*7c478bd9Sstevel@tonic-gate 		    outfile, sbuf.st_mode & 0777, strerror(errno));
807*7c478bd9Sstevel@tonic-gate 		goto out;
808*7c478bd9Sstevel@tonic-gate 	}
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 	if (fchown(fileno(fout), sbuf.st_uid, sbuf.st_gid) != 0) {
811*7c478bd9Sstevel@tonic-gate 		logerr(gettext("failed to fchown %1$s to uid %2$d and "
812*7c478bd9Sstevel@tonic-gate 		    "gid %3$d: %4$s\n"),
813*7c478bd9Sstevel@tonic-gate 		    outfile, sbuf.st_uid, sbuf.st_gid, strerror(errno));
814*7c478bd9Sstevel@tonic-gate 		goto out;
815*7c478bd9Sstevel@tonic-gate 	}
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	*fp_in = fin;
818*7c478bd9Sstevel@tonic-gate 	*fp_out = fout;
819*7c478bd9Sstevel@tonic-gate 	return (0);
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate out:
822*7c478bd9Sstevel@tonic-gate 	if (fin != NULL)
823*7c478bd9Sstevel@tonic-gate 		(void) fclose(fin);
824*7c478bd9Sstevel@tonic-gate 	if (fout != NULL)
825*7c478bd9Sstevel@tonic-gate 		(void) fclose(fout);
826*7c478bd9Sstevel@tonic-gate 	return (-1);
827*7c478bd9Sstevel@tonic-gate }
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate /*
830*7c478bd9Sstevel@tonic-gate  * If the devname is a phci based name and not open-able, map it to vhci
831*7c478bd9Sstevel@tonic-gate  * based name. If the devname is a vhci based name and not open-able, map it
832*7c478bd9Sstevel@tonic-gate  * to phci based name.
833*7c478bd9Sstevel@tonic-gate  *
834*7c478bd9Sstevel@tonic-gate  * devname	either a /dev link or /devices name to client device
835*7c478bd9Sstevel@tonic-gate  * new_devname	caller supplied buffer where the mapped device name is
836*7c478bd9Sstevel@tonic-gate  *		placed on return.
837*7c478bd9Sstevel@tonic-gate  * len		caller supplied new_devname buffer length
838*7c478bd9Sstevel@tonic-gate  * devlink_flag	pass 1 if requesting the /dev link to the mapped device.
839*7c478bd9Sstevel@tonic-gate  *		pass 0 if requesting the /devices name of the mapped device.
840*7c478bd9Sstevel@tonic-gate  *
841*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
842*7c478bd9Sstevel@tonic-gate  */
843*7c478bd9Sstevel@tonic-gate static int
844*7c478bd9Sstevel@tonic-gate map_devname(char *devname, char *new_devname, size_t len, int devlink_flag)
845*7c478bd9Sstevel@tonic-gate {
846*7c478bd9Sstevel@tonic-gate 	char physname[MAXPATHLEN];
847*7c478bd9Sstevel@tonic-gate 	char minor[MAXNAMELEN];
848*7c478bd9Sstevel@tonic-gate 	char new_physname[MAXNAMELEN];
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	if (get_physname_minor(devname, physname, sizeof (physname),
851*7c478bd9Sstevel@tonic-gate 	    minor, sizeof (minor)) == 0 &&
852*7c478bd9Sstevel@tonic-gate 	    canopen(devname) == 0 &&
853*7c478bd9Sstevel@tonic-gate 	    map_physname(physname, new_physname, sizeof (new_physname)) == 0) {
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate 		if (devlink_flag) {
856*7c478bd9Sstevel@tonic-gate 			if (lookup_devlink(new_physname, minor, new_devname,
857*7c478bd9Sstevel@tonic-gate 			    len) == 0)
858*7c478bd9Sstevel@tonic-gate 				return (0);
859*7c478bd9Sstevel@tonic-gate 		} else {
860*7c478bd9Sstevel@tonic-gate 			(void) snprintf(new_devname, len, "/devices%s:%s",
861*7c478bd9Sstevel@tonic-gate 			    new_physname, minor);
862*7c478bd9Sstevel@tonic-gate 			return (0);
863*7c478bd9Sstevel@tonic-gate 		}
864*7c478bd9Sstevel@tonic-gate 	}
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	return (-1);
867*7c478bd9Sstevel@tonic-gate }
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate /*
870*7c478bd9Sstevel@tonic-gate  * Make a new /etc/vfstab:
871*7c478bd9Sstevel@tonic-gate  * Read vfstab_in, convert the device name entries to appropriate vhci or phci
872*7c478bd9Sstevel@tonic-gate  * based names, and write to vfstab_out. Only device names whose physical
873*7c478bd9Sstevel@tonic-gate  * paths are either phci or vhci based names and not open-able are considered
874*7c478bd9Sstevel@tonic-gate  * for conversion. Open-able device name entries are not converted as it
875*7c478bd9Sstevel@tonic-gate  * means that the device is already accessible; hence no need to convert.
876*7c478bd9Sstevel@tonic-gate  *
877*7c478bd9Sstevel@tonic-gate  * Returns:
878*7c478bd9Sstevel@tonic-gate  * 	0	successful but vfstab_out contents are the same as vfstab_in
879*7c478bd9Sstevel@tonic-gate  *	1	successful and vfstab_out changed from vfstab_in
880*7c478bd9Sstevel@tonic-gate  *	-1	failed
881*7c478bd9Sstevel@tonic-gate  */
882*7c478bd9Sstevel@tonic-gate static int
883*7c478bd9Sstevel@tonic-gate update_vfstab(char *vfstab_in, char *vfstab_out)
884*7c478bd9Sstevel@tonic-gate {
885*7c478bd9Sstevel@tonic-gate 	FILE *fp_in, *fp_out;
886*7c478bd9Sstevel@tonic-gate 	char *buf, *tmpbuf;
887*7c478bd9Sstevel@tonic-gate 	char *vfs_cache[2];
888*7c478bd9Sstevel@tonic-gate 	int idx = 0, count = 0;
889*7c478bd9Sstevel@tonic-gate 	int rv = -1;
890*7c478bd9Sstevel@tonic-gate 	int vfstab_updated = 0;
891*7c478bd9Sstevel@tonic-gate 	int i;
892*7c478bd9Sstevel@tonic-gate 	char cdev[MAXPATHLEN];
893*7c478bd9Sstevel@tonic-gate 	char bdev[MAXPATHLEN];
894*7c478bd9Sstevel@tonic-gate 	char mntpt[MAXPATHLEN];
895*7c478bd9Sstevel@tonic-gate 	char fstype[512];
896*7c478bd9Sstevel@tonic-gate 	char fsckpass[512];
897*7c478bd9Sstevel@tonic-gate 	char mntboot[512];
898*7c478bd9Sstevel@tonic-gate 	char mntopt[MAX_MNTOPT_STR];
899*7c478bd9Sstevel@tonic-gate 	char phys_bdev[MAXPATHLEN], phys_cdev[MAXPATHLEN];
900*7c478bd9Sstevel@tonic-gate 	char bdev_minor[MAXNAMELEN], cdev_minor[MAXNAMELEN];
901*7c478bd9Sstevel@tonic-gate 	char new_physname[MAXPATHLEN];
902*7c478bd9Sstevel@tonic-gate 	char new_bdevlink[MAXPATHLEN], new_cdevlink[MAXPATHLEN];
903*7c478bd9Sstevel@tonic-gate 	char fmt[80];
904*7c478bd9Sstevel@tonic-gate 
905*7c478bd9Sstevel@tonic-gate 	if (open_in_out_files(vfstab_in, vfstab_out, &fp_in, &fp_out) != 0)
906*7c478bd9Sstevel@tonic-gate 		return (-1);
907*7c478bd9Sstevel@tonic-gate 
908*7c478bd9Sstevel@tonic-gate 	/*
909*7c478bd9Sstevel@tonic-gate 	 * Read one line at time from vfstab_in. If no conversion is needed
910*7c478bd9Sstevel@tonic-gate 	 * for the line simply write the line to vfstab_out. If conversion is
911*7c478bd9Sstevel@tonic-gate 	 * needed, first write the existing line as a comment to vfstab_out
912*7c478bd9Sstevel@tonic-gate 	 * and then write the converted line.
913*7c478bd9Sstevel@tonic-gate 	 *
914*7c478bd9Sstevel@tonic-gate 	 * To avoid commented entries piling up in vfstab in case if the
915*7c478bd9Sstevel@tonic-gate 	 * user runs stmsboot multiple times to switch on and off from mpxio,
916*7c478bd9Sstevel@tonic-gate 	 * add the commented line only if not already there. To do this
917*7c478bd9Sstevel@tonic-gate 	 * cache the last two vfstab lines processed and add the commented
918*7c478bd9Sstevel@tonic-gate 	 * entry only if it is not found in the cache. We only need to cache
919*7c478bd9Sstevel@tonic-gate 	 * the last two lines because a device can have at most two names -
920*7c478bd9Sstevel@tonic-gate 	 * one mpxio and one non-mpxio name. Therefore for any device name
921*7c478bd9Sstevel@tonic-gate 	 * entry we at most add two comments - one with mpxio name and one
922*7c478bd9Sstevel@tonic-gate 	 * with non-mpxio name - no matter how many times stmsboot is run.
923*7c478bd9Sstevel@tonic-gate 	 */
924*7c478bd9Sstevel@tonic-gate 	buf = (char *)s_malloc(VFS_LINE_MAX);
925*7c478bd9Sstevel@tonic-gate 	tmpbuf = (char *)s_malloc(VFS_LINE_MAX);
926*7c478bd9Sstevel@tonic-gate 	vfs_cache[0] = (char *)s_malloc(VFS_LINE_MAX);
927*7c478bd9Sstevel@tonic-gate 	vfs_cache[1] = (char *)s_malloc(VFS_LINE_MAX);
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	(void) snprintf(fmt, sizeof (fmt),
930*7c478bd9Sstevel@tonic-gate 	    "%%%ds %%%ds %%%ds %%%ds %%%ds %%%ds %%%ds", sizeof (bdev) - 1,
931*7c478bd9Sstevel@tonic-gate 	    sizeof (cdev) - 1, sizeof (mntpt) - 1, sizeof (fstype) - 1,
932*7c478bd9Sstevel@tonic-gate 	    sizeof (fsckpass) - 1, sizeof (mntboot) - 1, sizeof (mntopt) - 1);
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, VFS_LINE_MAX, fp_in) != NULL) {
935*7c478bd9Sstevel@tonic-gate 		if (strlen(buf) == (VFS_LINE_MAX - 1) &&
936*7c478bd9Sstevel@tonic-gate 		    buf[VFS_LINE_MAX-2] != '\n') {
937*7c478bd9Sstevel@tonic-gate 			logerr(gettext("%1$s line size too long, "
938*7c478bd9Sstevel@tonic-gate 			    "exceeded %2$d: \"%3$s\"\n"),
939*7c478bd9Sstevel@tonic-gate 			    VFSTAB, VFS_LINE_MAX - 2, buf);
940*7c478bd9Sstevel@tonic-gate 			goto out;
941*7c478bd9Sstevel@tonic-gate 		}
942*7c478bd9Sstevel@tonic-gate 
943*7c478bd9Sstevel@tonic-gate 		/* LINTED - format specifier */
944*7c478bd9Sstevel@tonic-gate 		if ((sscanf(buf, fmt, bdev, cdev, mntpt,
945*7c478bd9Sstevel@tonic-gate 		    fstype, fsckpass, mntboot, mntopt) != 7) ||
946*7c478bd9Sstevel@tonic-gate 		    (bdev[0] == '#') ||
947*7c478bd9Sstevel@tonic-gate 		    (get_physname_minor(bdev, phys_bdev, sizeof (phys_bdev),
948*7c478bd9Sstevel@tonic-gate 		    bdev_minor, sizeof (bdev_minor)) != 0) ||
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 		    (strcmp(fstype, "swap") != 0 &&
951*7c478bd9Sstevel@tonic-gate 		    ((get_physname_minor(cdev, phys_cdev, sizeof (phys_cdev),
952*7c478bd9Sstevel@tonic-gate 		    cdev_minor, sizeof (cdev_minor)) != 0) ||
953*7c478bd9Sstevel@tonic-gate 		    (strcmp(phys_bdev, phys_cdev) != 0))) ||
954*7c478bd9Sstevel@tonic-gate 
955*7c478bd9Sstevel@tonic-gate 		    canopen(bdev) ||
956*7c478bd9Sstevel@tonic-gate 		    (map_physname(phys_bdev, new_physname,
957*7c478bd9Sstevel@tonic-gate 		    sizeof (new_physname)) != 0) ||
958*7c478bd9Sstevel@tonic-gate 		    (lookup_devlink(new_physname, bdev_minor, new_bdevlink,
959*7c478bd9Sstevel@tonic-gate 		    sizeof (new_bdevlink)) != 0) ||
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate 		    (strcmp(fstype, "swap") != 0 &&
962*7c478bd9Sstevel@tonic-gate 		    (lookup_devlink(new_physname, cdev_minor, new_cdevlink,
963*7c478bd9Sstevel@tonic-gate 		    sizeof (new_cdevlink)) != 0))) {
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 			/* cache the last two entries */
966*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(vfs_cache[idx], buf, VFS_LINE_MAX);
967*7c478bd9Sstevel@tonic-gate 			idx = (idx == 0) ? 1 : 0;
968*7c478bd9Sstevel@tonic-gate 			if (count < 2)
969*7c478bd9Sstevel@tonic-gate 				count++;
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 			if (fputs(buf, fp_out) == EOF) {
972*7c478bd9Sstevel@tonic-gate 				logerr(gettext("fputs \"%1$s\" to %2$s "
973*7c478bd9Sstevel@tonic-gate 				    "failed: %3$s\n"),
974*7c478bd9Sstevel@tonic-gate 				    buf, vfstab_out, strerror(errno));
975*7c478bd9Sstevel@tonic-gate 				goto out;
976*7c478bd9Sstevel@tonic-gate 			}
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 		} else {
979*7c478bd9Sstevel@tonic-gate 			/*
980*7c478bd9Sstevel@tonic-gate 			 * comment the entry in vfstab only if it is not
981*7c478bd9Sstevel@tonic-gate 			 * already in the cache.
982*7c478bd9Sstevel@tonic-gate 			 */
983*7c478bd9Sstevel@tonic-gate 			if (client_name_type(phys_bdev) == CLIENT_TYPE_VHCI)
984*7c478bd9Sstevel@tonic-gate 				(void) snprintf(tmpbuf, VFS_LINE_MAX,
985*7c478bd9Sstevel@tonic-gate 				    "# mpxio: %s", buf);
986*7c478bd9Sstevel@tonic-gate 			else
987*7c478bd9Sstevel@tonic-gate 				(void) snprintf(tmpbuf, VFS_LINE_MAX,
988*7c478bd9Sstevel@tonic-gate 				    "# non-mpxio: %s", buf);
989*7c478bd9Sstevel@tonic-gate 
990*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < count; i++) {
991*7c478bd9Sstevel@tonic-gate 				if (strcmp(vfs_cache[i], tmpbuf) == 0)
992*7c478bd9Sstevel@tonic-gate 					break;
993*7c478bd9Sstevel@tonic-gate 			}
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 			if (i == count) {
996*7c478bd9Sstevel@tonic-gate 				if (fputs(tmpbuf, fp_out) == EOF) {
997*7c478bd9Sstevel@tonic-gate 					logerr(gettext("fputs \"%1$s\" to %2$s "
998*7c478bd9Sstevel@tonic-gate 					    "failed: %3$s\n"), tmpbuf,
999*7c478bd9Sstevel@tonic-gate 					    vfstab_out, strerror(errno));
1000*7c478bd9Sstevel@tonic-gate 					goto out;
1001*7c478bd9Sstevel@tonic-gate 				}
1002*7c478bd9Sstevel@tonic-gate 			}
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 			count = 0;
1005*7c478bd9Sstevel@tonic-gate 			idx = 0;
1006*7c478bd9Sstevel@tonic-gate 
1007*7c478bd9Sstevel@tonic-gate 			if (fprintf(fp_out, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
1008*7c478bd9Sstevel@tonic-gate 			    new_bdevlink,
1009*7c478bd9Sstevel@tonic-gate 			    (strcmp(fstype, "swap") != 0) ? new_cdevlink : cdev,
1010*7c478bd9Sstevel@tonic-gate 			    mntpt, fstype, fsckpass, mntboot, mntopt) < 0) {
1011*7c478bd9Sstevel@tonic-gate 				logerr(gettext("fprintf failed to write to "
1012*7c478bd9Sstevel@tonic-gate 				    "%1$s: %2$s\n"),
1013*7c478bd9Sstevel@tonic-gate 				    vfstab_out, strerror(errno));
1014*7c478bd9Sstevel@tonic-gate 				goto out;
1015*7c478bd9Sstevel@tonic-gate 			}
1016*7c478bd9Sstevel@tonic-gate 			vfstab_updated = 1;
1017*7c478bd9Sstevel@tonic-gate 		}
1018*7c478bd9Sstevel@tonic-gate 	}
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	rv = vfstab_updated;
1021*7c478bd9Sstevel@tonic-gate out:
1022*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp_in);
1023*7c478bd9Sstevel@tonic-gate 	(void) fclose(fp_out);
1024*7c478bd9Sstevel@tonic-gate 	free(buf);
1025*7c478bd9Sstevel@tonic-gate 	free(tmpbuf);
1026*7c478bd9Sstevel@tonic-gate 	free(vfs_cache[0]);
1027*7c478bd9Sstevel@tonic-gate 	free(vfs_cache[1]);
1028*7c478bd9Sstevel@tonic-gate 	return (rv);
1029*7c478bd9Sstevel@tonic-gate }
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate /*
1032*7c478bd9Sstevel@tonic-gate  * if guidmap is 0, list non-STMS to STMS device name mappings for the
1033*7c478bd9Sstevel@tonic-gate  * specified controller.
1034*7c478bd9Sstevel@tonic-gate  * if guidmap is 1, list non-STMS to GUID mappings for the specified controller.
1035*7c478bd9Sstevel@tonic-gate  * If controller is -1 list mappings for all controllers.
1036*7c478bd9Sstevel@tonic-gate  *
1037*7c478bd9Sstevel@tonic-gate  * Returns 0 on success, -1 on failure.
1038*7c478bd9Sstevel@tonic-gate  */
1039*7c478bd9Sstevel@tonic-gate static int
1040*7c478bd9Sstevel@tonic-gate list_mappings(int controller, int guidmap)
1041*7c478bd9Sstevel@tonic-gate {
1042*7c478bd9Sstevel@tonic-gate 	int cnum, len, mapped;
1043*7c478bd9Sstevel@tonic-gate 	int header = 1;
1044*7c478bd9Sstevel@tonic-gate 	char *p1, *p2;
1045*7c478bd9Sstevel@tonic-gate 	DIR *dirp;
1046*7c478bd9Sstevel@tonic-gate 	struct dirent *direntry;
1047*7c478bd9Sstevel@tonic-gate 	char devname[MAXPATHLEN];
1048*7c478bd9Sstevel@tonic-gate 	char physname[MAXPATHLEN];
1049*7c478bd9Sstevel@tonic-gate 	char new_devname[MAXPATHLEN];
1050*7c478bd9Sstevel@tonic-gate 	char new_physname[MAXPATHLEN];
1051*7c478bd9Sstevel@tonic-gate 	char guid[MAXPATHLEN];
1052*7c478bd9Sstevel@tonic-gate 	char minor[MAXNAMELEN];
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 	if ((dirp = opendir("/dev/rdsk")) == NULL)
1055*7c478bd9Sstevel@tonic-gate 		return (-1);
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 	while ((direntry = readdir(dirp)) != NULL) {
1058*7c478bd9Sstevel@tonic-gate 		if (strcmp(direntry->d_name, ".") == 0 ||
1059*7c478bd9Sstevel@tonic-gate 		    strcmp(direntry->d_name, "..") == 0 ||
1060*7c478bd9Sstevel@tonic-gate 		    (len = strlen(direntry->d_name)) < 2 ||
1061*7c478bd9Sstevel@tonic-gate 		    strcmp(direntry->d_name + len - 2, "s0") != 0 ||
1062*7c478bd9Sstevel@tonic-gate 		    sscanf(direntry->d_name, "c%dt", &cnum) != 1 ||
1063*7c478bd9Sstevel@tonic-gate 		    (controller != -1 && controller != cnum))
1064*7c478bd9Sstevel@tonic-gate 			continue;
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate 		(void) snprintf(devname, MAXPATHLEN, "/dev/rdsk/%s",
1067*7c478bd9Sstevel@tonic-gate 		    direntry->d_name);
1068*7c478bd9Sstevel@tonic-gate 
1069*7c478bd9Sstevel@tonic-gate 		if (get_physname_minor(devname, physname, sizeof (physname),
1070*7c478bd9Sstevel@tonic-gate 		    minor, sizeof (minor)) != 0 ||
1071*7c478bd9Sstevel@tonic-gate 		    client_name_type(physname) != CLIENT_TYPE_PHCI)
1072*7c478bd9Sstevel@tonic-gate 			continue;
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 		/*
1075*7c478bd9Sstevel@tonic-gate 		 * First try phci_to_vhci() mapping. It will work if the
1076*7c478bd9Sstevel@tonic-gate 		 * device is under MPxIO control. If the device is not under
1077*7c478bd9Sstevel@tonic-gate 		 * MPxIO, phci_to_vhci() will fail in which case try to lookup
1078*7c478bd9Sstevel@tonic-gate 		 * if an old mapping exists using guid lookup.
1079*7c478bd9Sstevel@tonic-gate 		 */
1080*7c478bd9Sstevel@tonic-gate 		mapped = 1;
1081*7c478bd9Sstevel@tonic-gate 		if (phci_to_vhci(physname, new_physname,
1082*7c478bd9Sstevel@tonic-gate 		    sizeof (new_physname)) != 0) {
1083*7c478bd9Sstevel@tonic-gate 			if (get_guid(physname, guid, sizeof (guid), 1,
1084*7c478bd9Sstevel@tonic-gate 			    DI_NODE_NIL) == 0)
1085*7c478bd9Sstevel@tonic-gate 				(void) snprintf(new_physname, MAXPATHLEN,
1086*7c478bd9Sstevel@tonic-gate 				    "/scsi_vhci/ssd@g%s", guid);
1087*7c478bd9Sstevel@tonic-gate 			else
1088*7c478bd9Sstevel@tonic-gate 				mapped = 0;
1089*7c478bd9Sstevel@tonic-gate 		}
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate 		if (mapped == 0)
1092*7c478bd9Sstevel@tonic-gate 			continue;
1093*7c478bd9Sstevel@tonic-gate 
1094*7c478bd9Sstevel@tonic-gate 		/* strip the slice number part */
1095*7c478bd9Sstevel@tonic-gate 		devname[strlen(devname) - 2] = '\0';
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 		if (guidmap == 0) {
1098*7c478bd9Sstevel@tonic-gate 			if (lookup_devlink(new_physname, minor,
1099*7c478bd9Sstevel@tonic-gate 			    new_devname, sizeof (new_devname)) != 0)
1100*7c478bd9Sstevel@tonic-gate 				continue;
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 			/* strip the slice number part */
1103*7c478bd9Sstevel@tonic-gate 			new_devname[strlen(new_devname) - 2] = '\0';
1104*7c478bd9Sstevel@tonic-gate 
1105*7c478bd9Sstevel@tonic-gate 			if (header) {
1106*7c478bd9Sstevel@tonic-gate 				(void) printf(
1107*7c478bd9Sstevel@tonic-gate 				    gettext("non-STMS device name\t\t\t"
1108*7c478bd9Sstevel@tonic-gate 				    "STMS device name\n"
1109*7c478bd9Sstevel@tonic-gate 				    "------------------------------------------"
1110*7c478bd9Sstevel@tonic-gate 				    "------------------------\n"));
1111*7c478bd9Sstevel@tonic-gate 				header = 0;
1112*7c478bd9Sstevel@tonic-gate 			}
1113*7c478bd9Sstevel@tonic-gate 			(void) printf("%s\t\t%s\n", devname, new_devname);
1114*7c478bd9Sstevel@tonic-gate 		} else {
1115*7c478bd9Sstevel@tonic-gate 			/* extract guid part */
1116*7c478bd9Sstevel@tonic-gate 			if ((p1 = strstr(new_physname, "ssd@g")) == NULL) {
1117*7c478bd9Sstevel@tonic-gate 				logdmsg("invalid vhci: %s\n", new_physname);
1118*7c478bd9Sstevel@tonic-gate 				continue;
1119*7c478bd9Sstevel@tonic-gate 			}
1120*7c478bd9Sstevel@tonic-gate 			p1 += sizeof ("ssd@g") - 1;
1121*7c478bd9Sstevel@tonic-gate 			if ((p2 = strrchr(p1, ':')) != NULL)
1122*7c478bd9Sstevel@tonic-gate 				*p2 = '\0';
1123*7c478bd9Sstevel@tonic-gate 
1124*7c478bd9Sstevel@tonic-gate 			if (header) {
1125*7c478bd9Sstevel@tonic-gate 				(void) printf(
1126*7c478bd9Sstevel@tonic-gate 				    gettext("non-STMS device name\t\t\tGUID\n"
1127*7c478bd9Sstevel@tonic-gate 				    "------------------------------------------"
1128*7c478bd9Sstevel@tonic-gate 				    "------------------------\n"));
1129*7c478bd9Sstevel@tonic-gate 				header = 0;
1130*7c478bd9Sstevel@tonic-gate 			}
1131*7c478bd9Sstevel@tonic-gate 			(void) printf("%s\t\t%s\n", devname, p1);
1132*7c478bd9Sstevel@tonic-gate 		}
1133*7c478bd9Sstevel@tonic-gate 	}
1134*7c478bd9Sstevel@tonic-gate 
1135*7c478bd9Sstevel@tonic-gate 	(void) closedir(dirp);
1136*7c478bd9Sstevel@tonic-gate 	return (0);
1137*7c478bd9Sstevel@tonic-gate }
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate /*
1140*7c478bd9Sstevel@tonic-gate  * Check if the file can be opened.
1141*7c478bd9Sstevel@tonic-gate  *
1142*7c478bd9Sstevel@tonic-gate  * Return 1 if the file can be opened, 0 otherwise.
1143*7c478bd9Sstevel@tonic-gate  */
1144*7c478bd9Sstevel@tonic-gate static int
1145*7c478bd9Sstevel@tonic-gate canopen(char *filename)
1146*7c478bd9Sstevel@tonic-gate {
1147*7c478bd9Sstevel@tonic-gate 	int fd;
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate 	if ((fd = open(filename, O_RDONLY)) == -1)
1150*7c478bd9Sstevel@tonic-gate 		return (0);
1151*7c478bd9Sstevel@tonic-gate 
1152*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
1153*7c478bd9Sstevel@tonic-gate 	return (1);
1154*7c478bd9Sstevel@tonic-gate }
1155*7c478bd9Sstevel@tonic-gate 
1156*7c478bd9Sstevel@tonic-gate static void
1157*7c478bd9Sstevel@tonic-gate logerr(char *msg, ...)
1158*7c478bd9Sstevel@tonic-gate {
1159*7c478bd9Sstevel@tonic-gate 	va_list ap;
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", stmsboot);
1162*7c478bd9Sstevel@tonic-gate 	va_start(ap, msg);
1163*7c478bd9Sstevel@tonic-gate 	/* LINTED - format specifier */
1164*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, msg, ap);
1165*7c478bd9Sstevel@tonic-gate 	va_end(ap);
1166*7c478bd9Sstevel@tonic-gate }
1167*7c478bd9Sstevel@tonic-gate 
1168*7c478bd9Sstevel@tonic-gate /* log debug message */
1169*7c478bd9Sstevel@tonic-gate static void
1170*7c478bd9Sstevel@tonic-gate logdmsg(char *msg, ...)
1171*7c478bd9Sstevel@tonic-gate {
1172*7c478bd9Sstevel@tonic-gate 	va_list ap;
1173*7c478bd9Sstevel@tonic-gate 
1174*7c478bd9Sstevel@tonic-gate 	if (debug) {
1175*7c478bd9Sstevel@tonic-gate 		va_start(ap, msg);
1176*7c478bd9Sstevel@tonic-gate 		/* LINTED - format specifier */
1177*7c478bd9Sstevel@tonic-gate 		(void) vprintf(msg, ap);
1178*7c478bd9Sstevel@tonic-gate 		va_end(ap);
1179*7c478bd9Sstevel@tonic-gate 	}
1180*7c478bd9Sstevel@tonic-gate }
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate static void *
1183*7c478bd9Sstevel@tonic-gate s_malloc(const size_t size)
1184*7c478bd9Sstevel@tonic-gate {
1185*7c478bd9Sstevel@tonic-gate 	void *rp;
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate 	if ((rp = malloc(size)) == NULL) {
1188*7c478bd9Sstevel@tonic-gate 		logerr(gettext("malloc failed to allocate %d bytes\n"), size);
1189*7c478bd9Sstevel@tonic-gate 		clean_exit(1);
1190*7c478bd9Sstevel@tonic-gate 	}
1191*7c478bd9Sstevel@tonic-gate 	return (rp);
1192*7c478bd9Sstevel@tonic-gate }
1193*7c478bd9Sstevel@tonic-gate 
1194*7c478bd9Sstevel@tonic-gate static char *
1195*7c478bd9Sstevel@tonic-gate s_strdup(const char *ptr)
1196*7c478bd9Sstevel@tonic-gate {
1197*7c478bd9Sstevel@tonic-gate 	void *rp;
1198*7c478bd9Sstevel@tonic-gate 
1199*7c478bd9Sstevel@tonic-gate 	if ((rp = strdup(ptr)) == NULL) {
1200*7c478bd9Sstevel@tonic-gate 		logerr(gettext("strdup failed to dup %s\n"), ptr);
1201*7c478bd9Sstevel@tonic-gate 		clean_exit(1);
1202*7c478bd9Sstevel@tonic-gate 	}
1203*7c478bd9Sstevel@tonic-gate 	return (rp);
1204*7c478bd9Sstevel@tonic-gate }
1205*7c478bd9Sstevel@tonic-gate 
1206*7c478bd9Sstevel@tonic-gate static void
1207*7c478bd9Sstevel@tonic-gate s_strlcpy(char *dst, const char *src, size_t dstsize)
1208*7c478bd9Sstevel@tonic-gate {
1209*7c478bd9Sstevel@tonic-gate 	int n;
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate 	if ((n = strlcpy(dst, src, dstsize)) >= dstsize) {
1212*7c478bd9Sstevel@tonic-gate 		logerr(gettext("strlcpy: destination buffer size is %1$d "
1213*7c478bd9Sstevel@tonic-gate 		    "bytes, need to at least %2$d bytes\n"), dstsize, n + 1);
1214*7c478bd9Sstevel@tonic-gate 		clean_exit(1);
1215*7c478bd9Sstevel@tonic-gate 	}
1216*7c478bd9Sstevel@tonic-gate }
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate static void
1219*7c478bd9Sstevel@tonic-gate clean_exit(int status)
1220*7c478bd9Sstevel@tonic-gate {
1221*7c478bd9Sstevel@tonic-gate 	if (devinfo_root != DI_NODE_NIL)
1222*7c478bd9Sstevel@tonic-gate 		di_fini(devinfo_root);
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate 	if (devlink_hdl != NULL)
1225*7c478bd9Sstevel@tonic-gate 		(void) di_devlink_fini(&devlink_hdl);
1226*7c478bd9Sstevel@tonic-gate 
1227*7c478bd9Sstevel@tonic-gate 	if (vhci_fd != -1)
1228*7c478bd9Sstevel@tonic-gate 		(void) close(vhci_fd);
1229*7c478bd9Sstevel@tonic-gate 
1230*7c478bd9Sstevel@tonic-gate 	exit(status);
1231*7c478bd9Sstevel@tonic-gate }
1232