xref: /titanic_52/usr/src/lib/libdscfg/common/cfg_vols.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <sys/types.h>
27*fcf3ce44SJohn Forte #include <stdio.h>
28*fcf3ce44SJohn Forte #include <fcntl.h>
29*fcf3ce44SJohn Forte #include <unistd.h>
30*fcf3ce44SJohn Forte #include <sys/stat.h>
31*fcf3ce44SJohn Forte #include <sys/mkdev.h>
32*fcf3ce44SJohn Forte #include <strings.h>
33*fcf3ce44SJohn Forte #include <stdarg.h>
34*fcf3ce44SJohn Forte #include <stdlib.h>
35*fcf3ce44SJohn Forte #include <locale.h>
36*fcf3ce44SJohn Forte #include <errno.h>
37*fcf3ce44SJohn Forte 
38*fcf3ce44SJohn Forte #include <sys/nsctl/cfg.h>
39*fcf3ce44SJohn Forte 
40*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s.h>
41*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_u.h>
42*fcf3ce44SJohn Forte #include <sys/unistat/spcs_errors.h>
43*fcf3ce44SJohn Forte #include <sys/unistat/spcs_s_impl.h>
44*fcf3ce44SJohn Forte 
45*fcf3ce44SJohn Forte #include <sys/nsctl/sv.h>
46*fcf3ce44SJohn Forte #include <sys/nsctl/nsc_hash.h>
47*fcf3ce44SJohn Forte 
48*fcf3ce44SJohn Forte #define	DEV_EXPAND 32
49*fcf3ce44SJohn Forte 
50*fcf3ce44SJohn Forte #define	DO_DISABLE 0
51*fcf3ce44SJohn Forte #define	DO_ENABLE 1
52*fcf3ce44SJohn Forte 
53*fcf3ce44SJohn Forte /*
54*fcf3ce44SJohn Forte  * Utility functions for iiadm and rdcadm/sndradm.
55*fcf3ce44SJohn Forte  */
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte typedef struct hash_data_s {
58*fcf3ce44SJohn Forte 	union {
59*fcf3ce44SJohn Forte 		char *users;
60*fcf3ce44SJohn Forte 		char *mode;
61*fcf3ce44SJohn Forte 	} u;
62*fcf3ce44SJohn Forte 	char *path;
63*fcf3ce44SJohn Forte 	char *node;
64*fcf3ce44SJohn Forte 	int setno;
65*fcf3ce44SJohn Forte } hash_data_t;
66*fcf3ce44SJohn Forte 
67*fcf3ce44SJohn Forte typedef struct {
68*fcf3ce44SJohn Forte 	dev_t	rdev;
69*fcf3ce44SJohn Forte 	mode_t  mode;
70*fcf3ce44SJohn Forte 	char	*path;
71*fcf3ce44SJohn Forte } device_t;
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte static hash_data_t *make_svol_data(char *, char *, char *, int);
74*fcf3ce44SJohn Forte static hash_data_t *make_dsvol_data(char *, char *, char *, int);
75*fcf3ce44SJohn Forte static void delete_svol_data(void *);
76*fcf3ce44SJohn Forte static void delete_dsvol_data(void *);
77*fcf3ce44SJohn Forte static int sv_action(char *, CFGFILE *, char *, int);
78*fcf3ce44SJohn Forte 
79*fcf3ce44SJohn Forte static int add_dev_entry(const char *);
80*fcf3ce44SJohn Forte static int compare(const void *, const void *);
81*fcf3ce44SJohn Forte static char *find_devid(const char *);
82*fcf3ce44SJohn Forte static void free_dev_entries();
83*fcf3ce44SJohn Forte static void rebuild_devhash();
84*fcf3ce44SJohn Forte 
85*fcf3ce44SJohn Forte static hash_node_t **dsvol;
86*fcf3ce44SJohn Forte static int dsvol_loaded = 0;
87*fcf3ce44SJohn Forte 
88*fcf3ce44SJohn Forte static hash_node_t **svol;
89*fcf3ce44SJohn Forte static int svol_loaded = 0;
90*fcf3ce44SJohn Forte 
91*fcf3ce44SJohn Forte static hash_node_t **shadowvol;
92*fcf3ce44SJohn Forte 
93*fcf3ce44SJohn Forte static hash_node_t **devhash;
94*fcf3ce44SJohn Forte static device_t *devlist;
95*fcf3ce44SJohn Forte static int devcount = 0;
96*fcf3ce44SJohn Forte static int devalloc = 0;
97*fcf3ce44SJohn Forte 
98*fcf3ce44SJohn Forte /*
99*fcf3ce44SJohn Forte  * cfg_add_user
100*fcf3ce44SJohn Forte  *
101*fcf3ce44SJohn Forte  * Description:
102*fcf3ce44SJohn Forte  *	Adds the calling tool as a user of the volume.
103*fcf3ce44SJohn Forte  *
104*fcf3ce44SJohn Forte  * Inputs:
105*fcf3ce44SJohn Forte  *	char *path: The pathname of the volume to be enabled.
106*fcf3ce44SJohn Forte  *	char *cnode: The device group name, or NULL if -C local or not cluster
107*fcf3ce44SJohn Forte  *	CFGFILE *cfg: A pointer to the current config file, or NULL if this
108*fcf3ce44SJohn Forte  *		function is to open/write/commit/close the change itself.
109*fcf3ce44SJohn Forte  *
110*fcf3ce44SJohn Forte  * Return values:
111*fcf3ce44SJohn Forte  *	CFG_USER_FIRST: Indicates that this is the first user of this
112*fcf3ce44SJohn Forte  *		particular volume.
113*fcf3ce44SJohn Forte  *	CFG_USER_OK: Indicates that the volume has already been entered into
114*fcf3ce44SJohn Forte  *		the config file.
115*fcf3ce44SJohn Forte  *	CFG_USER_ERR: Indicates that some failure has occurred and no changes
116*fcf3ce44SJohn Forte  *		to the config file have been made.
117*fcf3ce44SJohn Forte  *	CFG_USER_REPEAT: Indicates that this user has already registered for
118*fcf3ce44SJohn Forte  *		the volume.
119*fcf3ce44SJohn Forte  */
120*fcf3ce44SJohn Forte int
121*fcf3ce44SJohn Forte cfg_add_user(CFGFILE* cfg, char *path, char *cnode, char *user)
122*fcf3ce44SJohn Forte {
123*fcf3ce44SJohn Forte 	int self_open, self_loaded, change_made;
124*fcf3ce44SJohn Forte 	char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ];
125*fcf3ce44SJohn Forte 	int retval, rc;
126*fcf3ce44SJohn Forte 	hash_data_t *data;
127*fcf3ce44SJohn Forte 
128*fcf3ce44SJohn Forte 	self_open = (cfg == NULL);
129*fcf3ce44SJohn Forte 	self_loaded = 0;
130*fcf3ce44SJohn Forte 	change_made = 0;
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte 	if (self_open) {
133*fcf3ce44SJohn Forte 		cfg = cfg_open(NULL);
134*fcf3ce44SJohn Forte 		if (cfg == NULL) {
135*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
136*fcf3ce44SJohn Forte 		}
137*fcf3ce44SJohn Forte 
138*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_WRLOCK)) {
139*fcf3ce44SJohn Forte 			/* oops */
140*fcf3ce44SJohn Forte 			cfg_close(cfg);
141*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
142*fcf3ce44SJohn Forte 		}
143*fcf3ce44SJohn Forte 	}
144*fcf3ce44SJohn Forte 
145*fcf3ce44SJohn Forte 	/* Check cnode */
146*fcf3ce44SJohn Forte 	ctag = cfg_get_resource(cfg);
147*fcf3ce44SJohn Forte 	if (cnode) {
148*fcf3ce44SJohn Forte 		if (ctag) {
149*fcf3ce44SJohn Forte 			if (strcmp(cnode, ctag))
150*fcf3ce44SJohn Forte 				return (CFG_USER_ERR);
151*fcf3ce44SJohn Forte 		} else
152*fcf3ce44SJohn Forte 			cfg_resource(cfg, cnode);
153*fcf3ce44SJohn Forte 	} else
154*fcf3ce44SJohn Forte 		cnode = ctag;
155*fcf3ce44SJohn Forte 
156*fcf3ce44SJohn Forte 	if (!dsvol_loaded) {
157*fcf3ce44SJohn Forte 		if (cfg_load_dsvols(cfg) < 0) {
158*fcf3ce44SJohn Forte 			if (self_open) {
159*fcf3ce44SJohn Forte 				cfg_close(cfg);
160*fcf3ce44SJohn Forte 			}
161*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
162*fcf3ce44SJohn Forte 		}
163*fcf3ce44SJohn Forte 		self_loaded = 1;
164*fcf3ce44SJohn Forte 	}
165*fcf3ce44SJohn Forte 
166*fcf3ce44SJohn Forte 	/* find the volume */
167*fcf3ce44SJohn Forte 	(void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode);
168*fcf3ce44SJohn Forte 	data = nsc_lookup(dsvol, search_key);
169*fcf3ce44SJohn Forte 
170*fcf3ce44SJohn Forte 	if (!data) {
171*fcf3ce44SJohn Forte 		/* whoops, not found.  Add as new user */
172*fcf3ce44SJohn Forte 		cfg_rewind(cfg, CFG_SEC_CONF);
173*fcf3ce44SJohn Forte 		(void) snprintf(buf, CFG_MAX_BUF, "%s %s %s", path, cnode,
174*fcf3ce44SJohn Forte 		    user);
175*fcf3ce44SJohn Forte 		rc = cfg_put_cstring(cfg, "dsvol", buf, strlen(buf));
176*fcf3ce44SJohn Forte 		if (rc < 0) {
177*fcf3ce44SJohn Forte 			if (self_loaded) {
178*fcf3ce44SJohn Forte 				cfg_unload_dsvols();
179*fcf3ce44SJohn Forte 			}
180*fcf3ce44SJohn Forte 			if (self_open) {
181*fcf3ce44SJohn Forte 				cfg_close(cfg);
182*fcf3ce44SJohn Forte 			}
183*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
184*fcf3ce44SJohn Forte 		}
185*fcf3ce44SJohn Forte 		/* reload hash, if we need to */
186*fcf3ce44SJohn Forte 		if (!self_loaded) {
187*fcf3ce44SJohn Forte 			cfg_unload_dsvols();
188*fcf3ce44SJohn Forte 			if (cfg_load_dsvols(cfg) < 0) {
189*fcf3ce44SJohn Forte 				if (self_open) {
190*fcf3ce44SJohn Forte 					cfg_close(cfg);
191*fcf3ce44SJohn Forte 				}
192*fcf3ce44SJohn Forte 				return (CFG_USER_ERR);
193*fcf3ce44SJohn Forte 			}
194*fcf3ce44SJohn Forte 		}
195*fcf3ce44SJohn Forte 		retval = CFG_USER_FIRST;
196*fcf3ce44SJohn Forte 		change_made = 1;
197*fcf3ce44SJohn Forte 	} else {
198*fcf3ce44SJohn Forte 		/* Check to ensure we're not already listed */
199*fcf3ce44SJohn Forte 		char *p = strdup(data->u.users);
200*fcf3ce44SJohn Forte 		char *q = strtok(p, ",");
201*fcf3ce44SJohn Forte 		while (q && (strcmp(q, user) != 0)) {
202*fcf3ce44SJohn Forte 			q = strtok(0, ",");
203*fcf3ce44SJohn Forte 		}
204*fcf3ce44SJohn Forte 		free(p);	/* not using data; only testing 'q' ptr */
205*fcf3ce44SJohn Forte 
206*fcf3ce44SJohn Forte 		if (!q) {
207*fcf3ce44SJohn Forte 			/* not listed as a user */
208*fcf3ce44SJohn Forte 			cfg_rewind(cfg, CFG_SEC_CONF);
209*fcf3ce44SJohn Forte 			(void) snprintf(buf, CFG_MAX_BUF, "%s %s %s,%s",
210*fcf3ce44SJohn Forte 			    data->path, data->node, data->u.users, user);
211*fcf3ce44SJohn Forte 			(void) snprintf(search_key, CFG_MAX_KEY, "dsvol.set%d",
212*fcf3ce44SJohn Forte 			    data->setno);
213*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, search_key, buf,
214*fcf3ce44SJohn Forte 			    strlen(buf)) < 0) {
215*fcf3ce44SJohn Forte 				if (self_loaded) {
216*fcf3ce44SJohn Forte 					cfg_unload_dsvols();
217*fcf3ce44SJohn Forte 				}
218*fcf3ce44SJohn Forte 				if (self_open) {
219*fcf3ce44SJohn Forte 					cfg_close(cfg);
220*fcf3ce44SJohn Forte 				}
221*fcf3ce44SJohn Forte 				return (CFG_USER_ERR);
222*fcf3ce44SJohn Forte 			}
223*fcf3ce44SJohn Forte 
224*fcf3ce44SJohn Forte 			/*
225*fcf3ce44SJohn Forte 			 * Since we deleted an entry from the config
226*fcf3ce44SJohn Forte 			 * file, we don't know what all the new
227*fcf3ce44SJohn Forte 			 * set numbers are.  We need to reload
228*fcf3ce44SJohn Forte 			 * everything
229*fcf3ce44SJohn Forte 			 */
230*fcf3ce44SJohn Forte 			if (!self_loaded) {
231*fcf3ce44SJohn Forte 				cfg_unload_dsvols();
232*fcf3ce44SJohn Forte 				if (cfg_load_dsvols(cfg) < 0) {
233*fcf3ce44SJohn Forte 					if (self_open) {
234*fcf3ce44SJohn Forte 						cfg_close(cfg);
235*fcf3ce44SJohn Forte 					}
236*fcf3ce44SJohn Forte 					return (CFG_USER_ERR);
237*fcf3ce44SJohn Forte 				}
238*fcf3ce44SJohn Forte 			}
239*fcf3ce44SJohn Forte 			change_made = 1;
240*fcf3ce44SJohn Forte 			retval = CFG_USER_OK;
241*fcf3ce44SJohn Forte 		} else {
242*fcf3ce44SJohn Forte 			retval = CFG_USER_REPEAT;
243*fcf3ce44SJohn Forte 		}
244*fcf3ce44SJohn Forte 	}
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte 	if (self_loaded) {
247*fcf3ce44SJohn Forte 		cfg_unload_dsvols();
248*fcf3ce44SJohn Forte 	}
249*fcf3ce44SJohn Forte 
250*fcf3ce44SJohn Forte 	if (self_open) {
251*fcf3ce44SJohn Forte 		if (change_made)
252*fcf3ce44SJohn Forte 			(void) cfg_commit(cfg);
253*fcf3ce44SJohn Forte 		cfg_close(cfg);
254*fcf3ce44SJohn Forte 	}
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte 	return (retval);
257*fcf3ce44SJohn Forte }
258*fcf3ce44SJohn Forte 
259*fcf3ce44SJohn Forte /*
260*fcf3ce44SJohn Forte  * cfg_rem_user
261*fcf3ce44SJohn Forte  *
262*fcf3ce44SJohn Forte  * Description:
263*fcf3ce44SJohn Forte  *	Removes a user from the config file.
264*fcf3ce44SJohn Forte  *
265*fcf3ce44SJohn Forte  * Inputs:
266*fcf3ce44SJohn Forte  *	char *path: The pathname of the volume to be enabled.
267*fcf3ce44SJohn Forte  *	char *cnode: The device group name, or NULL if -C local or not cluster
268*fcf3ce44SJohn Forte  *	char *user: The subsystem that is adding this tag (sv, ii, sndr)
269*fcf3ce44SJohn Forte  *	CFGFILE *cfg: A pointer to the current config file, or NULL if this
270*fcf3ce44SJohn Forte  *		function is to open/write/commit/close the change itself.
271*fcf3ce44SJohn Forte  * Return values:
272*fcf3ce44SJohn Forte  *	CFG_USER_ERR: An error occurred during the processing of this
273*fcf3ce44SJohn Forte  *		directive.
274*fcf3ce44SJohn Forte  *	CFG_USER_OK: User successfully removed; volume in use by other(s).
275*fcf3ce44SJohn Forte  *	CFG_USER_LAST: User successfuly removed; no other users registered
276*fcf3ce44SJohn Forte  *	CFG_USER_GONE: The volume is no longer listed in the dsvol section,
277*fcf3ce44SJohn Forte  *		indicating some sort of application-level error.
278*fcf3ce44SJohn Forte  *
279*fcf3ce44SJohn Forte  */
280*fcf3ce44SJohn Forte int
281*fcf3ce44SJohn Forte cfg_rem_user(CFGFILE *cfg, char *path, char *cnode, char *user)
282*fcf3ce44SJohn Forte {
283*fcf3ce44SJohn Forte 	int self_open, self_loaded, change_made;
284*fcf3ce44SJohn Forte 	char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ];
285*fcf3ce44SJohn Forte 	char cfg_key[ CFG_MAX_KEY ];
286*fcf3ce44SJohn Forte 	hash_data_t *data;
287*fcf3ce44SJohn Forte 	int retval;
288*fcf3ce44SJohn Forte 	int force_remove;
289*fcf3ce44SJohn Forte 
290*fcf3ce44SJohn Forte 	self_open = (cfg == NULL);
291*fcf3ce44SJohn Forte 	self_loaded = 0;
292*fcf3ce44SJohn Forte 	change_made = 0;
293*fcf3ce44SJohn Forte 	force_remove = (strcmp(user, "sv") == 0);
294*fcf3ce44SJohn Forte 
295*fcf3ce44SJohn Forte 	if ('-' == *user) {
296*fcf3ce44SJohn Forte 		++user;
297*fcf3ce44SJohn Forte 	}
298*fcf3ce44SJohn Forte 
299*fcf3ce44SJohn Forte 	/* Check cnode */
300*fcf3ce44SJohn Forte 	ctag = cfg_get_resource(cfg);
301*fcf3ce44SJohn Forte 	if (cnode) {
302*fcf3ce44SJohn Forte 		if (ctag) {
303*fcf3ce44SJohn Forte 			if (strcmp(cnode, ctag))
304*fcf3ce44SJohn Forte 				return (CFG_USER_ERR);
305*fcf3ce44SJohn Forte 		} else
306*fcf3ce44SJohn Forte 			cfg_resource(cfg, cnode);
307*fcf3ce44SJohn Forte 	} else
308*fcf3ce44SJohn Forte 		cnode = ctag;
309*fcf3ce44SJohn Forte 
310*fcf3ce44SJohn Forte 	if (self_open) {
311*fcf3ce44SJohn Forte 		cfg = cfg_open(NULL);
312*fcf3ce44SJohn Forte 		if (cfg == NULL) {
313*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
314*fcf3ce44SJohn Forte 		}
315*fcf3ce44SJohn Forte 
316*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_WRLOCK)) {
317*fcf3ce44SJohn Forte 			/* oops */
318*fcf3ce44SJohn Forte 			cfg_close(cfg);
319*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
320*fcf3ce44SJohn Forte 		}
321*fcf3ce44SJohn Forte 	}
322*fcf3ce44SJohn Forte 
323*fcf3ce44SJohn Forte 
324*fcf3ce44SJohn Forte 	change_made = 0;
325*fcf3ce44SJohn Forte 	if (!dsvol_loaded) {
326*fcf3ce44SJohn Forte 		if (cfg_load_dsvols(cfg) < 0) {
327*fcf3ce44SJohn Forte 			if (self_open) {
328*fcf3ce44SJohn Forte 				cfg_close(cfg);
329*fcf3ce44SJohn Forte 			}
330*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
331*fcf3ce44SJohn Forte 		}
332*fcf3ce44SJohn Forte 		self_loaded = 1;
333*fcf3ce44SJohn Forte 	}
334*fcf3ce44SJohn Forte 
335*fcf3ce44SJohn Forte 	/* find the volume */
336*fcf3ce44SJohn Forte 	(void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode);
337*fcf3ce44SJohn Forte 	data = nsc_lookup(dsvol, search_key);
338*fcf3ce44SJohn Forte 
339*fcf3ce44SJohn Forte 	if (!data) {
340*fcf3ce44SJohn Forte 		/* yipes */
341*fcf3ce44SJohn Forte 		retval = CFG_USER_GONE;
342*fcf3ce44SJohn Forte 	} else if (force_remove) {
343*fcf3ce44SJohn Forte 		retval = CFG_USER_LAST;
344*fcf3ce44SJohn Forte 		cfg_rewind(cfg, CFG_SEC_CONF);
345*fcf3ce44SJohn Forte 		(void) snprintf(cfg_key, CFG_MAX_KEY, "dsvol.set%d",
346*fcf3ce44SJohn Forte 		    data->setno);
347*fcf3ce44SJohn Forte 		if (cfg_put_cstring(cfg, cfg_key, NULL, 0) < 0) {
348*fcf3ce44SJohn Forte 			if (self_loaded) {
349*fcf3ce44SJohn Forte 				cfg_unload_dsvols();
350*fcf3ce44SJohn Forte 			}
351*fcf3ce44SJohn Forte 			if (self_open) {
352*fcf3ce44SJohn Forte 				cfg_close(cfg);
353*fcf3ce44SJohn Forte 			}
354*fcf3ce44SJohn Forte 			return (CFG_USER_ERR);
355*fcf3ce44SJohn Forte 		}
356*fcf3ce44SJohn Forte 		if (!self_loaded) {
357*fcf3ce44SJohn Forte 			cfg_unload_dsvols();
358*fcf3ce44SJohn Forte 			if (cfg_load_dsvols(cfg) < 0) {
359*fcf3ce44SJohn Forte 				if (self_open) {
360*fcf3ce44SJohn Forte 					cfg_close(cfg);
361*fcf3ce44SJohn Forte 				}
362*fcf3ce44SJohn Forte 				return (CFG_USER_ERR);
363*fcf3ce44SJohn Forte 			}
364*fcf3ce44SJohn Forte 		}
365*fcf3ce44SJohn Forte 	} else {
366*fcf3ce44SJohn Forte 		char *p = strdup(data->u.users);
367*fcf3ce44SJohn Forte 		char *q = strtok(p, ",");
368*fcf3ce44SJohn Forte 		int appended = 0;
369*fcf3ce44SJohn Forte 
370*fcf3ce44SJohn Forte 		(void) snprintf(buf, CFG_MAX_BUF, "%s %s ", data->path,
371*fcf3ce44SJohn Forte 		    data->node);
372*fcf3ce44SJohn Forte 		while (q && (strcmp(q, user) != 0)) {
373*fcf3ce44SJohn Forte 			if (appended) {
374*fcf3ce44SJohn Forte 				strcat(buf, ",");
375*fcf3ce44SJohn Forte 				strcat(buf, q);
376*fcf3ce44SJohn Forte 			} else {
377*fcf3ce44SJohn Forte 				strcat(buf, q);
378*fcf3ce44SJohn Forte 				appended = 1;
379*fcf3ce44SJohn Forte 			}
380*fcf3ce44SJohn Forte 			q = strtok(0, ",");
381*fcf3ce44SJohn Forte 		}
382*fcf3ce44SJohn Forte 
383*fcf3ce44SJohn Forte 		if (!q) {
384*fcf3ce44SJohn Forte 			/* uh-oh */
385*fcf3ce44SJohn Forte 			retval = CFG_USER_GONE;
386*fcf3ce44SJohn Forte 		} else {
387*fcf3ce44SJohn Forte 			/* old user skipped; add in remaining users */
388*fcf3ce44SJohn Forte 			while (q = strtok(0, ", ")) {
389*fcf3ce44SJohn Forte 				if (appended) {
390*fcf3ce44SJohn Forte 					strcat(buf, ",");
391*fcf3ce44SJohn Forte 					strcat(buf, q);
392*fcf3ce44SJohn Forte 				} else {
393*fcf3ce44SJohn Forte 					strcat(buf, q);
394*fcf3ce44SJohn Forte 					appended = 1;
395*fcf3ce44SJohn Forte 				}
396*fcf3ce44SJohn Forte 			}
397*fcf3ce44SJohn Forte 
398*fcf3ce44SJohn Forte 			if (appended) {
399*fcf3ce44SJohn Forte 				retval = CFG_USER_OK;
400*fcf3ce44SJohn Forte 				cfg_rewind(cfg, CFG_SEC_CONF);
401*fcf3ce44SJohn Forte 				(void) snprintf(cfg_key, CFG_MAX_KEY,
402*fcf3ce44SJohn Forte 				    "dsvol.set%d", data->setno);
403*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, cfg_key, buf,
404*fcf3ce44SJohn Forte 				    strlen(buf)) < 0) {
405*fcf3ce44SJohn Forte 					if (self_loaded) {
406*fcf3ce44SJohn Forte 						cfg_unload_dsvols();
407*fcf3ce44SJohn Forte 					}
408*fcf3ce44SJohn Forte 					if (self_open) {
409*fcf3ce44SJohn Forte 						cfg_close(cfg);
410*fcf3ce44SJohn Forte 					}
411*fcf3ce44SJohn Forte 					return (CFG_USER_ERR);
412*fcf3ce44SJohn Forte 				}
413*fcf3ce44SJohn Forte 				if (!self_loaded) {
414*fcf3ce44SJohn Forte 					cfg_unload_dsvols();
415*fcf3ce44SJohn Forte 					if (cfg_load_dsvols(cfg) < 0) {
416*fcf3ce44SJohn Forte 						if (self_open) {
417*fcf3ce44SJohn Forte 							cfg_close(cfg);
418*fcf3ce44SJohn Forte 						}
419*fcf3ce44SJohn Forte 						return (CFG_USER_ERR);
420*fcf3ce44SJohn Forte 					}
421*fcf3ce44SJohn Forte 				}
422*fcf3ce44SJohn Forte 			} else {
423*fcf3ce44SJohn Forte 				retval = CFG_USER_LAST;
424*fcf3ce44SJohn Forte 				cfg_rewind(cfg, CFG_SEC_CONF);
425*fcf3ce44SJohn Forte 				(void) snprintf(cfg_key, CFG_MAX_KEY,
426*fcf3ce44SJohn Forte 				    "dsvol.set%d", data->setno);
427*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, cfg_key, NULL,
428*fcf3ce44SJohn Forte 				    0) < 0) {
429*fcf3ce44SJohn Forte 					if (self_loaded) {
430*fcf3ce44SJohn Forte 						cfg_unload_dsvols();
431*fcf3ce44SJohn Forte 					}
432*fcf3ce44SJohn Forte 					if (self_open) {
433*fcf3ce44SJohn Forte 						cfg_close(cfg);
434*fcf3ce44SJohn Forte 					}
435*fcf3ce44SJohn Forte 					return (CFG_USER_ERR);
436*fcf3ce44SJohn Forte 				}
437*fcf3ce44SJohn Forte 				/*
438*fcf3ce44SJohn Forte 				 * Since we deleted an entry from the config
439*fcf3ce44SJohn Forte 				 * file, we don't know what all the new
440*fcf3ce44SJohn Forte 				 * set numbers are.  We need to reload
441*fcf3ce44SJohn Forte 				 * everything
442*fcf3ce44SJohn Forte 				 */
443*fcf3ce44SJohn Forte 				if (!self_loaded) {
444*fcf3ce44SJohn Forte 					cfg_unload_dsvols();
445*fcf3ce44SJohn Forte 					if (cfg_load_dsvols(cfg) < 0) {
446*fcf3ce44SJohn Forte 						if (self_open) {
447*fcf3ce44SJohn Forte 							cfg_close(cfg);
448*fcf3ce44SJohn Forte 						}
449*fcf3ce44SJohn Forte 						return (CFG_USER_ERR);
450*fcf3ce44SJohn Forte 					}
451*fcf3ce44SJohn Forte 				}
452*fcf3ce44SJohn Forte 			}
453*fcf3ce44SJohn Forte 			change_made = 1;
454*fcf3ce44SJohn Forte 		}
455*fcf3ce44SJohn Forte 	}
456*fcf3ce44SJohn Forte 
457*fcf3ce44SJohn Forte 	if (self_loaded) {
458*fcf3ce44SJohn Forte 		cfg_unload_dsvols();
459*fcf3ce44SJohn Forte 	}
460*fcf3ce44SJohn Forte 
461*fcf3ce44SJohn Forte 	if (self_open) {
462*fcf3ce44SJohn Forte 		if (change_made)
463*fcf3ce44SJohn Forte 			(void) cfg_commit(cfg);
464*fcf3ce44SJohn Forte 		cfg_close(cfg);
465*fcf3ce44SJohn Forte 	}
466*fcf3ce44SJohn Forte 
467*fcf3ce44SJohn Forte 	return (retval);
468*fcf3ce44SJohn Forte }
469*fcf3ce44SJohn Forte 
470*fcf3ce44SJohn Forte /*
471*fcf3ce44SJohn Forte  * Enable a volume under SV control (or add this char *user to the list
472*fcf3ce44SJohn Forte  * of users of that volume).
473*fcf3ce44SJohn Forte  *
474*fcf3ce44SJohn Forte  * Parameters:
475*fcf3ce44SJohn Forte  *	cfg	- The config file to use.
476*fcf3ce44SJohn Forte  *	path	- The pathname of the volume
477*fcf3ce44SJohn Forte  *	ctag	- The cluster tag for this volume (if any)
478*fcf3ce44SJohn Forte  *	user	- The user (sv, ii, sndr) of the volume.
479*fcf3ce44SJohn Forte  */
480*fcf3ce44SJohn Forte int
481*fcf3ce44SJohn Forte cfg_vol_enable(CFGFILE *cfg, char *path, char *ctag, char *user)
482*fcf3ce44SJohn Forte {
483*fcf3ce44SJohn Forte 	int rc;
484*fcf3ce44SJohn Forte 	int retval;
485*fcf3ce44SJohn Forte 
486*fcf3ce44SJohn Forte 	if (!ctag || *ctag == '\0') {
487*fcf3ce44SJohn Forte 		ctag = "-";
488*fcf3ce44SJohn Forte 	}
489*fcf3ce44SJohn Forte 
490*fcf3ce44SJohn Forte 	retval = -1;
491*fcf3ce44SJohn Forte 	rc = cfg_add_user(cfg, path, ctag, user);
492*fcf3ce44SJohn Forte 	switch (rc) {
493*fcf3ce44SJohn Forte 	case CFG_USER_ERR:
494*fcf3ce44SJohn Forte 		spcs_log("dsvol", NULL,
495*fcf3ce44SJohn Forte 		    gettext("unable to set up dsvol section of config for %s"),
496*fcf3ce44SJohn Forte 		    path);
497*fcf3ce44SJohn Forte 		break;
498*fcf3ce44SJohn Forte 	case CFG_USER_OK:
499*fcf3ce44SJohn Forte 		retval = 0;
500*fcf3ce44SJohn Forte 		break;
501*fcf3ce44SJohn Forte 	case CFG_USER_FIRST:
502*fcf3ce44SJohn Forte 		/* enable sv! */
503*fcf3ce44SJohn Forte 		retval = sv_action(path, cfg, ctag, DO_ENABLE);
504*fcf3ce44SJohn Forte 		if (retval < 0) {
505*fcf3ce44SJohn Forte 			(void) cfg_rem_user(cfg, path, ctag, user);
506*fcf3ce44SJohn Forte 		}
507*fcf3ce44SJohn Forte 		break;
508*fcf3ce44SJohn Forte 	default:
509*fcf3ce44SJohn Forte 		spcs_log("dsvol", NULL,
510*fcf3ce44SJohn Forte 		    gettext("unexpected return from cfg_add_user(%d)"), rc);
511*fcf3ce44SJohn Forte 		break;
512*fcf3ce44SJohn Forte 	}
513*fcf3ce44SJohn Forte 
514*fcf3ce44SJohn Forte 	return (retval);
515*fcf3ce44SJohn Forte }
516*fcf3ce44SJohn Forte 
517*fcf3ce44SJohn Forte /*
518*fcf3ce44SJohn Forte  * Disable a volume from SV control (or remove this char *user from the list
519*fcf3ce44SJohn Forte  * of users of that volume).
520*fcf3ce44SJohn Forte  *
521*fcf3ce44SJohn Forte  * Parameters:
522*fcf3ce44SJohn Forte  *	cfg	- The config file to use.
523*fcf3ce44SJohn Forte  *	path	- The pathname of the volume
524*fcf3ce44SJohn Forte  *	ctag	- The cluster tag for this volume (if any)
525*fcf3ce44SJohn Forte  *	user	- The user (sv, ii, sndr) of the volume.
526*fcf3ce44SJohn Forte  */
527*fcf3ce44SJohn Forte int
528*fcf3ce44SJohn Forte cfg_vol_disable(CFGFILE *cfg, char *path, char *ctag, char *user)
529*fcf3ce44SJohn Forte {
530*fcf3ce44SJohn Forte 	int rc;
531*fcf3ce44SJohn Forte 	int retval;
532*fcf3ce44SJohn Forte 
533*fcf3ce44SJohn Forte 	if (!ctag || *ctag == '\0') {
534*fcf3ce44SJohn Forte 		ctag = "-";
535*fcf3ce44SJohn Forte 	}
536*fcf3ce44SJohn Forte 
537*fcf3ce44SJohn Forte 	retval = -1;
538*fcf3ce44SJohn Forte 	rc = cfg_rem_user(cfg, path, ctag, user);
539*fcf3ce44SJohn Forte 	switch (rc) {
540*fcf3ce44SJohn Forte 	case CFG_USER_ERR:
541*fcf3ce44SJohn Forte 		spcs_log("dsvol", NULL,
542*fcf3ce44SJohn Forte 		    gettext("unable to set up dsvol section of config for %s"),
543*fcf3ce44SJohn Forte 		    path);
544*fcf3ce44SJohn Forte 		break;
545*fcf3ce44SJohn Forte 	case CFG_USER_OK:
546*fcf3ce44SJohn Forte 		retval = 0;
547*fcf3ce44SJohn Forte 		break;
548*fcf3ce44SJohn Forte 	case CFG_USER_GONE:
549*fcf3ce44SJohn Forte 		spcs_log("dsvol", NULL,
550*fcf3ce44SJohn Forte 		    gettext("%s tried to remove non-existent tag for %s"),
551*fcf3ce44SJohn Forte 		    user, path);
552*fcf3ce44SJohn Forte 		break;
553*fcf3ce44SJohn Forte 	case CFG_USER_LAST:
554*fcf3ce44SJohn Forte 		/* diable sv! */
555*fcf3ce44SJohn Forte 		retval = sv_action(path, cfg, ctag, DO_DISABLE);
556*fcf3ce44SJohn Forte 		break;
557*fcf3ce44SJohn Forte 	default:
558*fcf3ce44SJohn Forte 		spcs_log("dsvol", NULL,
559*fcf3ce44SJohn Forte 		    gettext("unexpected return from cfg_rem_user(%d)"), rc);
560*fcf3ce44SJohn Forte 		break;
561*fcf3ce44SJohn Forte 	}
562*fcf3ce44SJohn Forte 
563*fcf3ce44SJohn Forte 	return (retval);
564*fcf3ce44SJohn Forte }
565*fcf3ce44SJohn Forte 
566*fcf3ce44SJohn Forte /*
567*fcf3ce44SJohn Forte  * cfg_load_dsvols
568*fcf3ce44SJohn Forte  *
569*fcf3ce44SJohn Forte  * Description:
570*fcf3ce44SJohn Forte  *	Loads the dsvol section of the config file into a giant hash, to
571*fcf3ce44SJohn Forte  *	make searching faster.  The important bit to remember is to not
572*fcf3ce44SJohn Forte  *	release the write lock between calling cfg_load_dsvols() and the
573*fcf3ce44SJohn Forte  *	cfg_*_user() functions.
574*fcf3ce44SJohn Forte  *
575*fcf3ce44SJohn Forte  * Assumptions:
576*fcf3ce44SJohn Forte  *	1/ cfg file is open
577*fcf3ce44SJohn Forte  *	2/ cfg file has been write-locked
578*fcf3ce44SJohn Forte  *	3/ user of this routine may already be using hcreate/hsearch
579*fcf3ce44SJohn Forte  *
580*fcf3ce44SJohn Forte  * Return value:
581*fcf3ce44SJohn Forte  *	-1 if error, or total number of sets found
582*fcf3ce44SJohn Forte  */
583*fcf3ce44SJohn Forte int
584*fcf3ce44SJohn Forte cfg_load_dsvols(CFGFILE *cfg)
585*fcf3ce44SJohn Forte {
586*fcf3ce44SJohn Forte 	int set, rc, entries;
587*fcf3ce44SJohn Forte 	char search_key[ CFG_MAX_KEY ];
588*fcf3ce44SJohn Forte 	char *buf;
589*fcf3ce44SJohn Forte 	char **entry, *path, *cnode, *users;
590*fcf3ce44SJohn Forte 	hash_data_t *data;
591*fcf3ce44SJohn Forte 	int devs_added = 0;
592*fcf3ce44SJohn Forte 	int offset = 0;
593*fcf3ce44SJohn Forte 	char *ctag = cfg_get_resource(cfg);
594*fcf3ce44SJohn Forte 	if (!ctag || *ctag == '\0') {
595*fcf3ce44SJohn Forte 		ctag = "-";
596*fcf3ce44SJohn Forte 	}
597*fcf3ce44SJohn Forte 
598*fcf3ce44SJohn Forte 	dsvol = nsc_create_hash();
599*fcf3ce44SJohn Forte 	if (!dsvol) {
600*fcf3ce44SJohn Forte 		return (-1);
601*fcf3ce44SJohn Forte 	}
602*fcf3ce44SJohn Forte 
603*fcf3ce44SJohn Forte 	rc = 0;
604*fcf3ce44SJohn Forte 	cfg_rewind(cfg, CFG_SEC_CONF);
605*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "dsvol");
606*fcf3ce44SJohn Forte 	for (set = 1; set <= entries; set++) {
607*fcf3ce44SJohn Forte 		buf = entry[set - 1];
608*fcf3ce44SJohn Forte 
609*fcf3ce44SJohn Forte 		/* split up the line */
610*fcf3ce44SJohn Forte 		if (!(path = strtok(buf, " "))) {
611*fcf3ce44SJohn Forte 			/* oops, now what? */
612*fcf3ce44SJohn Forte 			free(buf);
613*fcf3ce44SJohn Forte 			break;
614*fcf3ce44SJohn Forte 		}
615*fcf3ce44SJohn Forte 		if (!(cnode = strtok(0, " "))) {
616*fcf3ce44SJohn Forte 			free(buf);
617*fcf3ce44SJohn Forte 			break;
618*fcf3ce44SJohn Forte 		}
619*fcf3ce44SJohn Forte 		if (ctag && (strcmp(cnode, ctag) != 0)) {
620*fcf3ce44SJohn Forte 			++offset;
621*fcf3ce44SJohn Forte 			free(buf);
622*fcf3ce44SJohn Forte 			continue;
623*fcf3ce44SJohn Forte 		}
624*fcf3ce44SJohn Forte 
625*fcf3ce44SJohn Forte 		if (!(users = strtok(0, " "))) {
626*fcf3ce44SJohn Forte 			free(buf);
627*fcf3ce44SJohn Forte 			break;
628*fcf3ce44SJohn Forte 		}
629*fcf3ce44SJohn Forte 
630*fcf3ce44SJohn Forte 		data = make_dsvol_data(path, cnode, users, set - offset);
631*fcf3ce44SJohn Forte 		if (!data) {
632*fcf3ce44SJohn Forte 			free(buf);
633*fcf3ce44SJohn Forte 			break;
634*fcf3ce44SJohn Forte 		}
635*fcf3ce44SJohn Forte 		(void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode);
636*fcf3ce44SJohn Forte 		rc = nsc_insert_node(dsvol, data, search_key);
637*fcf3ce44SJohn Forte 		if (rc < 0) {
638*fcf3ce44SJohn Forte 			free(buf);
639*fcf3ce44SJohn Forte 			break;
640*fcf3ce44SJohn Forte 		}
641*fcf3ce44SJohn Forte 
642*fcf3ce44SJohn Forte 		/* we also need to keep track of node information */
643*fcf3ce44SJohn Forte 		rc = add_dev_entry(path);
644*fcf3ce44SJohn Forte 		if (rc < 0) {
645*fcf3ce44SJohn Forte 			free(buf);
646*fcf3ce44SJohn Forte 			break;
647*fcf3ce44SJohn Forte 		} else if (rc)
648*fcf3ce44SJohn Forte 			++devs_added;
649*fcf3ce44SJohn Forte 
650*fcf3ce44SJohn Forte 		free(buf);
651*fcf3ce44SJohn Forte 		rc = 0;
652*fcf3ce44SJohn Forte 	}
653*fcf3ce44SJohn Forte 
654*fcf3ce44SJohn Forte 	while (set < entries)
655*fcf3ce44SJohn Forte 		free(entry[set++]);
656*fcf3ce44SJohn Forte 	if (entries)
657*fcf3ce44SJohn Forte 		free(entry);
658*fcf3ce44SJohn Forte 
659*fcf3ce44SJohn Forte 	if (devs_added) {
660*fcf3ce44SJohn Forte 		qsort(devlist, devcount, sizeof (device_t), compare);
661*fcf3ce44SJohn Forte 		rebuild_devhash();
662*fcf3ce44SJohn Forte 	}
663*fcf3ce44SJohn Forte 
664*fcf3ce44SJohn Forte 	dsvol_loaded = 1;
665*fcf3ce44SJohn Forte 	return (rc < 0? rc : entries);
666*fcf3ce44SJohn Forte }
667*fcf3ce44SJohn Forte 
668*fcf3ce44SJohn Forte /*
669*fcf3ce44SJohn Forte  * cfg_unload_dsvols
670*fcf3ce44SJohn Forte  *
671*fcf3ce44SJohn Forte  * Description:
672*fcf3ce44SJohn Forte  *	Free all memory allocated with cfg_load_dsvols.
673*fcf3ce44SJohn Forte  */
674*fcf3ce44SJohn Forte void
675*fcf3ce44SJohn Forte cfg_unload_dsvols()
676*fcf3ce44SJohn Forte {
677*fcf3ce44SJohn Forte 	if (dsvol) {
678*fcf3ce44SJohn Forte 		nsc_remove_all(dsvol, delete_dsvol_data);
679*fcf3ce44SJohn Forte 		dsvol = 0;
680*fcf3ce44SJohn Forte 		dsvol_loaded = 0;
681*fcf3ce44SJohn Forte 	}
682*fcf3ce44SJohn Forte }
683*fcf3ce44SJohn Forte 
684*fcf3ce44SJohn Forte /*
685*fcf3ce44SJohn Forte  * cfg_load_svols
686*fcf3ce44SJohn Forte  *
687*fcf3ce44SJohn Forte  * Description:
688*fcf3ce44SJohn Forte  *	Loads the sv section of the config file into a giant hash, to make
689*fcf3ce44SJohn Forte  *	searching faster.  The important bit to remember is to not release
690*fcf3ce44SJohn Forte  *	the write lock between calling cfg_load_svols() and the cfg_*_user()
691*fcf3ce44SJohn Forte  *	functions.
692*fcf3ce44SJohn Forte  *
693*fcf3ce44SJohn Forte  * Assumptions:
694*fcf3ce44SJohn Forte  *	1/ cfg file is open
695*fcf3ce44SJohn Forte  *	2/ cfg file has been write-locked
696*fcf3ce44SJohn Forte  *	3/ user of this routine may already be using builtin hcreate/hsearch
697*fcf3ce44SJohn Forte  */
698*fcf3ce44SJohn Forte int
699*fcf3ce44SJohn Forte cfg_load_svols(CFGFILE *cfg)
700*fcf3ce44SJohn Forte {
701*fcf3ce44SJohn Forte 	int set, entries, offset = 0;
702*fcf3ce44SJohn Forte 	char *buf, **entry;
703*fcf3ce44SJohn Forte 	char *path, *mode, *cnode;
704*fcf3ce44SJohn Forte 	hash_data_t *data;
705*fcf3ce44SJohn Forte 	char *ctag = cfg_get_resource(cfg);
706*fcf3ce44SJohn Forte 	if (!ctag || *ctag == '\0') {
707*fcf3ce44SJohn Forte 		ctag = "-";
708*fcf3ce44SJohn Forte 	}
709*fcf3ce44SJohn Forte 
710*fcf3ce44SJohn Forte 	svol = nsc_create_hash();
711*fcf3ce44SJohn Forte 	if (!svol) {
712*fcf3ce44SJohn Forte 		return (-1);
713*fcf3ce44SJohn Forte 	}
714*fcf3ce44SJohn Forte 
715*fcf3ce44SJohn Forte 	cfg_rewind(cfg, CFG_SEC_CONF);
716*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "sv");
717*fcf3ce44SJohn Forte 	for (set = 1; set <= entries; set++) {
718*fcf3ce44SJohn Forte 		buf = entry[set - 1];
719*fcf3ce44SJohn Forte 
720*fcf3ce44SJohn Forte 		/* split up the line */
721*fcf3ce44SJohn Forte 		if (!(path = strtok(buf, " "))) {
722*fcf3ce44SJohn Forte 			free(buf);
723*fcf3ce44SJohn Forte 			break;
724*fcf3ce44SJohn Forte 		}
725*fcf3ce44SJohn Forte 		if (!(mode = strtok(0, " "))) {
726*fcf3ce44SJohn Forte 			free(buf);
727*fcf3ce44SJohn Forte 			break;
728*fcf3ce44SJohn Forte 		}
729*fcf3ce44SJohn Forte 		if (!(cnode = strtok(0, " "))) {
730*fcf3ce44SJohn Forte 			cnode = "";
731*fcf3ce44SJohn Forte 		}
732*fcf3ce44SJohn Forte 
733*fcf3ce44SJohn Forte 		if (ctag && (strcmp(cnode, ctag) != 0)) {
734*fcf3ce44SJohn Forte 			++offset;
735*fcf3ce44SJohn Forte 			free(buf);
736*fcf3ce44SJohn Forte 			continue;
737*fcf3ce44SJohn Forte 		}
738*fcf3ce44SJohn Forte 
739*fcf3ce44SJohn Forte 		data = make_svol_data(path, mode, cnode, set - offset);
740*fcf3ce44SJohn Forte 		if (!data) {
741*fcf3ce44SJohn Forte 			free(buf);
742*fcf3ce44SJohn Forte 			break;
743*fcf3ce44SJohn Forte 		}
744*fcf3ce44SJohn Forte 		if (nsc_insert_node(svol, data, path) < 0) {
745*fcf3ce44SJohn Forte 			free(buf);
746*fcf3ce44SJohn Forte 			break;
747*fcf3ce44SJohn Forte 		}
748*fcf3ce44SJohn Forte 		free(buf);
749*fcf3ce44SJohn Forte 	}
750*fcf3ce44SJohn Forte 	while (set < entries)
751*fcf3ce44SJohn Forte 		free(entry[set++]);
752*fcf3ce44SJohn Forte 	if (entries)
753*fcf3ce44SJohn Forte 		free(entry);
754*fcf3ce44SJohn Forte 
755*fcf3ce44SJohn Forte 	svol_loaded = 1;
756*fcf3ce44SJohn Forte 	return (0);
757*fcf3ce44SJohn Forte }
758*fcf3ce44SJohn Forte 
759*fcf3ce44SJohn Forte /*
760*fcf3ce44SJohn Forte  * cfg_unload_svols
761*fcf3ce44SJohn Forte  *
762*fcf3ce44SJohn Forte  * Description:
763*fcf3ce44SJohn Forte  *	Frees all memory allocated with cfg_load_dsvols
764*fcf3ce44SJohn Forte  */
765*fcf3ce44SJohn Forte void
766*fcf3ce44SJohn Forte cfg_unload_svols()
767*fcf3ce44SJohn Forte {
768*fcf3ce44SJohn Forte 	if (svol) {
769*fcf3ce44SJohn Forte 		nsc_remove_all(svol, delete_svol_data);
770*fcf3ce44SJohn Forte 		svol = 0;
771*fcf3ce44SJohn Forte 		svol_loaded = 0;
772*fcf3ce44SJohn Forte 	}
773*fcf3ce44SJohn Forte }
774*fcf3ce44SJohn Forte 
775*fcf3ce44SJohn Forte /*
776*fcf3ce44SJohn Forte  * cfg_get_canonical_name
777*fcf3ce44SJohn Forte  *
778*fcf3ce44SJohn Forte  * Description:
779*fcf3ce44SJohn Forte  *	Find out whether a device is already known by another name in
780*fcf3ce44SJohn Forte  *	the config file.
781*fcf3ce44SJohn Forte  *
782*fcf3ce44SJohn Forte  * Parameters:
783*fcf3ce44SJohn Forte  *	cfg - The config file to use
784*fcf3ce44SJohn Forte  *	path - The pathname of the device
785*fcf3ce44SJohn Forte  *	result - (output) The name it is otherwise known as.  This parameter
786*fcf3ce44SJohn Forte  *			must be freed by the caller.
787*fcf3ce44SJohn Forte  *
788*fcf3ce44SJohn Forte  * Return values:
789*fcf3ce44SJohn Forte  *	-1: error
790*fcf3ce44SJohn Forte  *	0: name is as expected, or is not known
791*fcf3ce44SJohn Forte  *	1: Name is known by different name (stored in 'result')
792*fcf3ce44SJohn Forte  */
793*fcf3ce44SJohn Forte int
794*fcf3ce44SJohn Forte cfg_get_canonical_name(CFGFILE *cfg, const char *path, char **result)
795*fcf3ce44SJohn Forte {
796*fcf3ce44SJohn Forte 	int self_loaded;
797*fcf3ce44SJohn Forte 	char *alt_path;
798*fcf3ce44SJohn Forte 	int retval;
799*fcf3ce44SJohn Forte 
800*fcf3ce44SJohn Forte 	if (devlist) {
801*fcf3ce44SJohn Forte 		self_loaded = 0;
802*fcf3ce44SJohn Forte 	} else {
803*fcf3ce44SJohn Forte 		if (cfg_load_shadows(cfg) < 0) {
804*fcf3ce44SJohn Forte 			return (-1);
805*fcf3ce44SJohn Forte 		}
806*fcf3ce44SJohn Forte 		self_loaded = 1;
807*fcf3ce44SJohn Forte 	}
808*fcf3ce44SJohn Forte 
809*fcf3ce44SJohn Forte 	/* see if it exists under a different name */
810*fcf3ce44SJohn Forte 	alt_path = find_devid(path);
811*fcf3ce44SJohn Forte 	if (!alt_path || strcmp(path, alt_path) == 0) {
812*fcf3ce44SJohn Forte 		*result = NULL;
813*fcf3ce44SJohn Forte 		retval = 0;
814*fcf3ce44SJohn Forte 	} else {
815*fcf3ce44SJohn Forte 		/* a-ha */
816*fcf3ce44SJohn Forte 		*result = strdup(alt_path);
817*fcf3ce44SJohn Forte 		retval = 1;
818*fcf3ce44SJohn Forte 	}
819*fcf3ce44SJohn Forte 
820*fcf3ce44SJohn Forte 	if (self_loaded) {
821*fcf3ce44SJohn Forte 		free_dev_entries();
822*fcf3ce44SJohn Forte 	}
823*fcf3ce44SJohn Forte 
824*fcf3ce44SJohn Forte 	return (retval);
825*fcf3ce44SJohn Forte }
826*fcf3ce44SJohn Forte 
827*fcf3ce44SJohn Forte /*
828*fcf3ce44SJohn Forte  * cfg_load_shadows
829*fcf3ce44SJohn Forte  *
830*fcf3ce44SJohn Forte  * Description:
831*fcf3ce44SJohn Forte  *	Load in shadow and bitmap volumes from the II section of the
832*fcf3ce44SJohn Forte  *	config file.  SNDR's volumes are handled already by cfg_load_dsvols.
833*fcf3ce44SJohn Forte  *	Not all shadow volumes are listed under dsvol: they can be exported.
834*fcf3ce44SJohn Forte  *
835*fcf3ce44SJohn Forte  * Parameters:
836*fcf3ce44SJohn Forte  *	cfg - The config file to use
837*fcf3ce44SJohn Forte  *
838*fcf3ce44SJohn Forte  * Return values:
839*fcf3ce44SJohn Forte  *	-1: error
840*fcf3ce44SJohn Forte  *	0: success
841*fcf3ce44SJohn Forte  */
842*fcf3ce44SJohn Forte int
843*fcf3ce44SJohn Forte cfg_load_shadows(CFGFILE *cfg)
844*fcf3ce44SJohn Forte {
845*fcf3ce44SJohn Forte 	int set, self_loaded, rc, entries;
846*fcf3ce44SJohn Forte 	char *buf, **entry, *ptr;
847*fcf3ce44SJohn Forte 	int devs_added = 0;
848*fcf3ce44SJohn Forte 
849*fcf3ce44SJohn Forte 	if (dsvol_loaded) {
850*fcf3ce44SJohn Forte 		self_loaded = 0;
851*fcf3ce44SJohn Forte 	} else {
852*fcf3ce44SJohn Forte 		if (cfg_load_dsvols(cfg) < 0) {
853*fcf3ce44SJohn Forte 			return (-1);
854*fcf3ce44SJohn Forte 		}
855*fcf3ce44SJohn Forte 		self_loaded = 1;
856*fcf3ce44SJohn Forte 	}
857*fcf3ce44SJohn Forte 
858*fcf3ce44SJohn Forte 	shadowvol = nsc_create_hash();
859*fcf3ce44SJohn Forte 	if (!shadowvol) {
860*fcf3ce44SJohn Forte 		return (-1);
861*fcf3ce44SJohn Forte 	}
862*fcf3ce44SJohn Forte 
863*fcf3ce44SJohn Forte 	rc = 0;
864*fcf3ce44SJohn Forte 	cfg_rewind(cfg, CFG_SEC_CONF);
865*fcf3ce44SJohn Forte 	entries = cfg_get_section(cfg, &entry, "ii");
866*fcf3ce44SJohn Forte 	for (set = 1; set <= entries; set++) {
867*fcf3ce44SJohn Forte 		buf = entry[set - 1];
868*fcf3ce44SJohn Forte 
869*fcf3ce44SJohn Forte 		/* skip the master vol */
870*fcf3ce44SJohn Forte 		ptr = strtok(buf, " ");
871*fcf3ce44SJohn Forte 
872*fcf3ce44SJohn Forte 		/* shadow is next */
873*fcf3ce44SJohn Forte 		ptr = strtok(NULL, " ");
874*fcf3ce44SJohn Forte 
875*fcf3ce44SJohn Forte 		rc = add_dev_entry(ptr);
876*fcf3ce44SJohn Forte 		if (rc < 0) {
877*fcf3ce44SJohn Forte 			free(buf);
878*fcf3ce44SJohn Forte 			break;
879*fcf3ce44SJohn Forte 		} else if (rc)
880*fcf3ce44SJohn Forte 			++devs_added;
881*fcf3ce44SJohn Forte 
882*fcf3ce44SJohn Forte 		/* and next is bitmap */
883*fcf3ce44SJohn Forte 		ptr = strtok(NULL, " ");
884*fcf3ce44SJohn Forte 
885*fcf3ce44SJohn Forte 		rc = add_dev_entry(ptr);
886*fcf3ce44SJohn Forte 		if (rc < 0) {
887*fcf3ce44SJohn Forte 			free(buf);
888*fcf3ce44SJohn Forte 			break;
889*fcf3ce44SJohn Forte 		} else if (rc)
890*fcf3ce44SJohn Forte 			++devs_added;
891*fcf3ce44SJohn Forte 		rc = 0;
892*fcf3ce44SJohn Forte 		free(buf);
893*fcf3ce44SJohn Forte 	}
894*fcf3ce44SJohn Forte 	while (set < entries)
895*fcf3ce44SJohn Forte 		free(entry[set++]);
896*fcf3ce44SJohn Forte 	if (entries)
897*fcf3ce44SJohn Forte 		free(entry);
898*fcf3ce44SJohn Forte 
899*fcf3ce44SJohn Forte 	if (self_loaded) {
900*fcf3ce44SJohn Forte 		cfg_unload_dsvols();
901*fcf3ce44SJohn Forte 	}
902*fcf3ce44SJohn Forte 
903*fcf3ce44SJohn Forte 	if (devs_added) {
904*fcf3ce44SJohn Forte 		/* sort it, in preparation for lookups */
905*fcf3ce44SJohn Forte 		qsort(devlist, devcount, sizeof (device_t), compare);
906*fcf3ce44SJohn Forte 		rebuild_devhash();
907*fcf3ce44SJohn Forte 	}
908*fcf3ce44SJohn Forte 
909*fcf3ce44SJohn Forte 	return (rc);
910*fcf3ce44SJohn Forte }
911*fcf3ce44SJohn Forte 
912*fcf3ce44SJohn Forte void
913*fcf3ce44SJohn Forte cfg_unload_shadows()
914*fcf3ce44SJohn Forte {
915*fcf3ce44SJohn Forte 	/* do nothing */
916*fcf3ce44SJohn Forte }
917*fcf3ce44SJohn Forte 
918*fcf3ce44SJohn Forte /* ---------------------------------------------------------------------- */
919*fcf3ce44SJohn Forte 
920*fcf3ce44SJohn Forte static hash_data_t *
921*fcf3ce44SJohn Forte make_dsvol_data(char *path, char *cnode, char *users, int set)
922*fcf3ce44SJohn Forte {
923*fcf3ce44SJohn Forte 	hash_data_t *data;
924*fcf3ce44SJohn Forte 
925*fcf3ce44SJohn Forte 	data = (hash_data_t *)malloc(sizeof (hash_data_t));
926*fcf3ce44SJohn Forte 	if (!data) {
927*fcf3ce44SJohn Forte 		return (0);
928*fcf3ce44SJohn Forte 	}
929*fcf3ce44SJohn Forte 
930*fcf3ce44SJohn Forte 	data->u.users = strdup(users);
931*fcf3ce44SJohn Forte 	data->path = strdup(path);
932*fcf3ce44SJohn Forte 	data->node = strdup(cnode);
933*fcf3ce44SJohn Forte 	data->setno = set;
934*fcf3ce44SJohn Forte 
935*fcf3ce44SJohn Forte 	return (data);
936*fcf3ce44SJohn Forte }
937*fcf3ce44SJohn Forte 
938*fcf3ce44SJohn Forte static void
939*fcf3ce44SJohn Forte delete_dsvol_data(void *data)
940*fcf3ce44SJohn Forte {
941*fcf3ce44SJohn Forte 	hash_data_t *p = (hash_data_t *)data;
942*fcf3ce44SJohn Forte 
943*fcf3ce44SJohn Forte 	free(p->u.users);
944*fcf3ce44SJohn Forte 	free(p->path);
945*fcf3ce44SJohn Forte 	free(p->node);
946*fcf3ce44SJohn Forte 	free(p);
947*fcf3ce44SJohn Forte }
948*fcf3ce44SJohn Forte 
949*fcf3ce44SJohn Forte static hash_data_t *
950*fcf3ce44SJohn Forte make_svol_data(char *path, char *mode, char *cnode, int set)
951*fcf3ce44SJohn Forte {
952*fcf3ce44SJohn Forte 	hash_data_t *data;
953*fcf3ce44SJohn Forte 
954*fcf3ce44SJohn Forte 	data = (hash_data_t *)malloc(sizeof (hash_data_t));
955*fcf3ce44SJohn Forte 	if (!data) {
956*fcf3ce44SJohn Forte 		return (0);
957*fcf3ce44SJohn Forte 	}
958*fcf3ce44SJohn Forte 
959*fcf3ce44SJohn Forte 	data->u.mode = strdup(mode);
960*fcf3ce44SJohn Forte 	data->path = strdup(path);
961*fcf3ce44SJohn Forte 	data->node = strdup(cnode);
962*fcf3ce44SJohn Forte 	data->setno = set;
963*fcf3ce44SJohn Forte 
964*fcf3ce44SJohn Forte 	return (data);
965*fcf3ce44SJohn Forte }
966*fcf3ce44SJohn Forte 
967*fcf3ce44SJohn Forte 
968*fcf3ce44SJohn Forte static void
969*fcf3ce44SJohn Forte delete_svol_data(void *data)
970*fcf3ce44SJohn Forte {
971*fcf3ce44SJohn Forte 	hash_data_t *p = (hash_data_t *)data;
972*fcf3ce44SJohn Forte 
973*fcf3ce44SJohn Forte 	free(p->u.mode);
974*fcf3ce44SJohn Forte 	free(p->path);
975*fcf3ce44SJohn Forte 	free(p->node);
976*fcf3ce44SJohn Forte 	free(p);
977*fcf3ce44SJohn Forte }
978*fcf3ce44SJohn Forte 
979*fcf3ce44SJohn Forte static int
980*fcf3ce44SJohn Forte sv_action(char *path, CFGFILE *caller_cfg, char *ctag, int enable)
981*fcf3ce44SJohn Forte {
982*fcf3ce44SJohn Forte 	struct stat stb;
983*fcf3ce44SJohn Forte 	sv_conf_t svc;
984*fcf3ce44SJohn Forte 	int fd = -1;
985*fcf3ce44SJohn Forte 	int cfg_changed = 0;
986*fcf3ce44SJohn Forte 	CFGFILE *cfg;
987*fcf3ce44SJohn Forte 	int print_log = 0;
988*fcf3ce44SJohn Forte 	int err = 0, rc;
989*fcf3ce44SJohn Forte 	int sv_ioctl, spcs_err, self_loaded;
990*fcf3ce44SJohn Forte 	char *log_str1, *log_str2;
991*fcf3ce44SJohn Forte 	char key[ CFG_MAX_KEY ];
992*fcf3ce44SJohn Forte 	char buf[ CFG_MAX_BUF ];
993*fcf3ce44SJohn Forte 	hash_data_t *node;
994*fcf3ce44SJohn Forte 	device_t *statinfo = 0;
995*fcf3ce44SJohn Forte 
996*fcf3ce44SJohn Forte 	if (caller_cfg == NULL) {
997*fcf3ce44SJohn Forte 		cfg = cfg_open(NULL);
998*fcf3ce44SJohn Forte 		if (cfg == NULL)
999*fcf3ce44SJohn Forte 			return (-1);
1000*fcf3ce44SJohn Forte 
1001*fcf3ce44SJohn Forte 		if (ctag)
1002*fcf3ce44SJohn Forte 			cfg_resource(cfg, ctag);
1003*fcf3ce44SJohn Forte 	} else
1004*fcf3ce44SJohn Forte 		cfg = caller_cfg;
1005*fcf3ce44SJohn Forte 
1006*fcf3ce44SJohn Forte 
1007*fcf3ce44SJohn Forte 	self_loaded = 0;
1008*fcf3ce44SJohn Forte 	sv_ioctl = (enable? SVIOC_ENABLE : SVIOC_DISABLE);
1009*fcf3ce44SJohn Forte 	log_str1 = (enable? gettext("enabled %s") : gettext("disabled %s"));
1010*fcf3ce44SJohn Forte 	log_str2 = (enable? gettext("unable to enable %s") :
1011*fcf3ce44SJohn Forte 	    gettext("unable to disable %s"));
1012*fcf3ce44SJohn Forte 	spcs_err = (enable? SV_EENABLED : SV_EDISABLED);
1013*fcf3ce44SJohn Forte 	bzero(&svc, sizeof (svc));
1014*fcf3ce44SJohn Forte 
1015*fcf3ce44SJohn Forte 	if (devhash)
1016*fcf3ce44SJohn Forte 		statinfo = nsc_lookup(devhash, path);
1017*fcf3ce44SJohn Forte 
1018*fcf3ce44SJohn Forte 	if (statinfo) {
1019*fcf3ce44SJohn Forte 		if (!S_ISCHR(statinfo->mode))
1020*fcf3ce44SJohn Forte 			goto error;
1021*fcf3ce44SJohn Forte 		svc.svc_major = major(statinfo->rdev);
1022*fcf3ce44SJohn Forte 		svc.svc_minor = minor(statinfo->rdev);
1023*fcf3ce44SJohn Forte 	} else {
1024*fcf3ce44SJohn Forte 		if (stat(path, &stb) != 0)
1025*fcf3ce44SJohn Forte 			goto error;
1026*fcf3ce44SJohn Forte 
1027*fcf3ce44SJohn Forte 		if (!S_ISCHR(stb.st_mode))
1028*fcf3ce44SJohn Forte 			goto error;
1029*fcf3ce44SJohn Forte 		svc.svc_major = major(stb.st_rdev);
1030*fcf3ce44SJohn Forte 		svc.svc_minor = minor(stb.st_rdev);
1031*fcf3ce44SJohn Forte 	}
1032*fcf3ce44SJohn Forte 
1033*fcf3ce44SJohn Forte 	strncpy(svc.svc_path, path, sizeof (svc.svc_path));
1034*fcf3ce44SJohn Forte 
1035*fcf3ce44SJohn Forte 	fd = open(SV_DEVICE, O_RDONLY);
1036*fcf3ce44SJohn Forte 	if (fd < 0)
1037*fcf3ce44SJohn Forte 		goto error;
1038*fcf3ce44SJohn Forte 
1039*fcf3ce44SJohn Forte 	svc.svc_flag = (NSC_DEVICE | NSC_CACHE);
1040*fcf3ce44SJohn Forte 	svc.svc_error = spcs_s_ucreate();
1041*fcf3ce44SJohn Forte 
1042*fcf3ce44SJohn Forte 	do {
1043*fcf3ce44SJohn Forte 		rc = ioctl(fd, sv_ioctl, &svc);
1044*fcf3ce44SJohn Forte 	} while (rc < 0 && errno == EINTR);
1045*fcf3ce44SJohn Forte 
1046*fcf3ce44SJohn Forte 	if (rc < 0) {
1047*fcf3ce44SJohn Forte 		if (errno != spcs_err) {
1048*fcf3ce44SJohn Forte 			spcs_log("sv", &svc.svc_error, log_str2, svc.svc_path);
1049*fcf3ce44SJohn Forte 			if (enable)
1050*fcf3ce44SJohn Forte 				goto error;
1051*fcf3ce44SJohn Forte 			else
1052*fcf3ce44SJohn Forte 				err = errno;
1053*fcf3ce44SJohn Forte 		} else
1054*fcf3ce44SJohn Forte 			err = spcs_err;
1055*fcf3ce44SJohn Forte 	}
1056*fcf3ce44SJohn Forte 
1057*fcf3ce44SJohn Forte 	spcs_log("sv", NULL, log_str1, svc.svc_path);
1058*fcf3ce44SJohn Forte 
1059*fcf3ce44SJohn Forte 	/* SV enable succeeded */
1060*fcf3ce44SJohn Forte 	if (caller_cfg == NULL)	 /* was not previously locked */
1061*fcf3ce44SJohn Forte 		if (!cfg_lock(cfg, CFG_WRLOCK))
1062*fcf3ce44SJohn Forte 			goto error;
1063*fcf3ce44SJohn Forte 
1064*fcf3ce44SJohn Forte 	if (err != spcs_err) { /* already enabled, already in config */
1065*fcf3ce44SJohn Forte 		if (enable) {
1066*fcf3ce44SJohn Forte 			cfg_rewind(cfg, CFG_SEC_CONF);
1067*fcf3ce44SJohn Forte 			(void) snprintf(buf, CFG_MAX_BUF, "%s - %s", path,
1068*fcf3ce44SJohn Forte 			    ctag? ctag : "-");
1069*fcf3ce44SJohn Forte 			if (cfg_put_cstring(cfg, "sv", buf, CFG_MAX_BUF) < 0) {
1070*fcf3ce44SJohn Forte 				/* SV config not updated, so SV disable again */
1071*fcf3ce44SJohn Forte 				(void) ioctl(fd, SVIOC_DISABLE, &svc);
1072*fcf3ce44SJohn Forte 				print_log++;
1073*fcf3ce44SJohn Forte 			} else
1074*fcf3ce44SJohn Forte 				cfg_changed = 1;
1075*fcf3ce44SJohn Forte 		} else {
1076*fcf3ce44SJohn Forte 			/* pull it out of the config */
1077*fcf3ce44SJohn Forte 			if (!svol_loaded) {
1078*fcf3ce44SJohn Forte 				if (cfg_load_svols(cfg) < 0) {
1079*fcf3ce44SJohn Forte 					if (NULL == caller_cfg) {
1080*fcf3ce44SJohn Forte 						cfg_close(cfg);
1081*fcf3ce44SJohn Forte 					}
1082*fcf3ce44SJohn Forte 					return (-1);
1083*fcf3ce44SJohn Forte 				}
1084*fcf3ce44SJohn Forte 				self_loaded = 1;
1085*fcf3ce44SJohn Forte 			}
1086*fcf3ce44SJohn Forte 			node = nsc_lookup(svol, svc.svc_path);
1087*fcf3ce44SJohn Forte 			if (node) {
1088*fcf3ce44SJohn Forte 				cfg_rewind(cfg, CFG_SEC_CONF);
1089*fcf3ce44SJohn Forte 				(void) snprintf(key, CFG_MAX_KEY, "sv.set%d",
1090*fcf3ce44SJohn Forte 				    node->setno);
1091*fcf3ce44SJohn Forte 				if (cfg_put_cstring(cfg, key, NULL, NULL) < 0) {
1092*fcf3ce44SJohn Forte 					spcs_log("sv", NULL,
1093*fcf3ce44SJohn Forte 					    gettext("failed to remove %s from "
1094*fcf3ce44SJohn Forte 					    "sv config"), svc.svc_path);
1095*fcf3ce44SJohn Forte 				}
1096*fcf3ce44SJohn Forte 				/*
1097*fcf3ce44SJohn Forte 				 * Since we deleted an entry from the config
1098*fcf3ce44SJohn Forte 				 * file, we don't know what all the new
1099*fcf3ce44SJohn Forte 				 * set numbers are.  We need to reload
1100*fcf3ce44SJohn Forte 				 * everything
1101*fcf3ce44SJohn Forte 				 */
1102*fcf3ce44SJohn Forte 				if (!self_loaded) {
1103*fcf3ce44SJohn Forte 					cfg_unload_svols();
1104*fcf3ce44SJohn Forte 					if (cfg_load_svols(cfg) < 0) {
1105*fcf3ce44SJohn Forte 						if (NULL == caller_cfg) {
1106*fcf3ce44SJohn Forte 							cfg_close(cfg);
1107*fcf3ce44SJohn Forte 						}
1108*fcf3ce44SJohn Forte 						return (-1);
1109*fcf3ce44SJohn Forte 					}
1110*fcf3ce44SJohn Forte 				}
1111*fcf3ce44SJohn Forte 				cfg_changed = 1;
1112*fcf3ce44SJohn Forte 			}
1113*fcf3ce44SJohn Forte 			if (self_loaded) {
1114*fcf3ce44SJohn Forte 				cfg_unload_svols();
1115*fcf3ce44SJohn Forte 				self_loaded = 0;
1116*fcf3ce44SJohn Forte 			}
1117*fcf3ce44SJohn Forte 		}
1118*fcf3ce44SJohn Forte 	}
1119*fcf3ce44SJohn Forte 
1120*fcf3ce44SJohn Forte #ifdef lint
1121*fcf3ce44SJohn Forte 	(void) printf("extra line to shut lint up %s\n", module_names[0]);
1122*fcf3ce44SJohn Forte #endif
1123*fcf3ce44SJohn Forte 
1124*fcf3ce44SJohn Forte error:
1125*fcf3ce44SJohn Forte 	if (fd >= 0)
1126*fcf3ce44SJohn Forte 		(void) close(fd);
1127*fcf3ce44SJohn Forte 
1128*fcf3ce44SJohn Forte 	if (cfg == NULL)
1129*fcf3ce44SJohn Forte 		return (-1);
1130*fcf3ce44SJohn Forte 
1131*fcf3ce44SJohn Forte 	if (cfg_changed)
1132*fcf3ce44SJohn Forte 		if (caller_cfg == NULL) /* we opened config */
1133*fcf3ce44SJohn Forte 			(void) cfg_commit(cfg);
1134*fcf3ce44SJohn Forte 
1135*fcf3ce44SJohn Forte 	if (caller_cfg == NULL)
1136*fcf3ce44SJohn Forte 		cfg_close(cfg);
1137*fcf3ce44SJohn Forte 	if ((cfg_changed) || (err == spcs_err))
1138*fcf3ce44SJohn Forte 		return (1);
1139*fcf3ce44SJohn Forte 	if (print_log)
1140*fcf3ce44SJohn Forte 		spcs_log("sv", NULL,
1141*fcf3ce44SJohn Forte 			gettext("unable to add to configuration, disabled %s"),
1142*fcf3ce44SJohn Forte 			svc.svc_path);
1143*fcf3ce44SJohn Forte 	spcs_s_ufree(&svc.svc_error);
1144*fcf3ce44SJohn Forte 
1145*fcf3ce44SJohn Forte 	return (-1);
1146*fcf3ce44SJohn Forte }
1147*fcf3ce44SJohn Forte 
1148*fcf3ce44SJohn Forte /*
1149*fcf3ce44SJohn Forte  * add_dev_entry
1150*fcf3ce44SJohn Forte  *
1151*fcf3ce44SJohn Forte  * Add an entry into the devlist and the devhash for future lookups.
1152*fcf3ce44SJohn Forte  *
1153*fcf3ce44SJohn Forte  * Return values:
1154*fcf3ce44SJohn Forte  *  -1  An error occurred.
1155*fcf3ce44SJohn Forte  *   0  Entry added
1156*fcf3ce44SJohn Forte  *   1  Entry already exists.
1157*fcf3ce44SJohn Forte  */
1158*fcf3ce44SJohn Forte static int
1159*fcf3ce44SJohn Forte add_dev_entry(const char *path)
1160*fcf3ce44SJohn Forte {
1161*fcf3ce44SJohn Forte 	struct stat buf;
1162*fcf3ce44SJohn Forte 	device_t *newmem;
1163*fcf3ce44SJohn Forte 	hash_data_t *data;
1164*fcf3ce44SJohn Forte 
1165*fcf3ce44SJohn Forte 	if (!devhash) {
1166*fcf3ce44SJohn Forte 		devhash = nsc_create_hash();
1167*fcf3ce44SJohn Forte 		if (!devhash) {
1168*fcf3ce44SJohn Forte 			return (-1);
1169*fcf3ce44SJohn Forte 		}
1170*fcf3ce44SJohn Forte 	} else {
1171*fcf3ce44SJohn Forte 		data = nsc_lookup(devhash, path);
1172*fcf3ce44SJohn Forte 		if (data) {
1173*fcf3ce44SJohn Forte 			return (1);
1174*fcf3ce44SJohn Forte 		}
1175*fcf3ce44SJohn Forte 	}
1176*fcf3ce44SJohn Forte 
1177*fcf3ce44SJohn Forte 	if (stat(path, &buf) < 0) {
1178*fcf3ce44SJohn Forte 		/* ignore error, we are most likely deleting entry anyway */
1179*fcf3ce44SJohn Forte 		buf.st_rdev = 0;
1180*fcf3ce44SJohn Forte 	}
1181*fcf3ce44SJohn Forte 
1182*fcf3ce44SJohn Forte 	if (devcount >= devalloc) {
1183*fcf3ce44SJohn Forte 		/* make some room */
1184*fcf3ce44SJohn Forte 		devalloc += DEV_EXPAND;
1185*fcf3ce44SJohn Forte 		newmem = (device_t *)realloc(devlist, devalloc *
1186*fcf3ce44SJohn Forte 		    sizeof (device_t));
1187*fcf3ce44SJohn Forte 		if (!newmem) {
1188*fcf3ce44SJohn Forte 			free_dev_entries();
1189*fcf3ce44SJohn Forte 			return (-1);
1190*fcf3ce44SJohn Forte 		} else {
1191*fcf3ce44SJohn Forte 			devlist = newmem;
1192*fcf3ce44SJohn Forte 		}
1193*fcf3ce44SJohn Forte 	}
1194*fcf3ce44SJohn Forte 
1195*fcf3ce44SJohn Forte 	devlist[ devcount ].path = strdup(path);
1196*fcf3ce44SJohn Forte 	devlist[ devcount ].rdev = buf.st_rdev;
1197*fcf3ce44SJohn Forte 	devlist[ devcount ].mode = buf.st_mode;
1198*fcf3ce44SJohn Forte 
1199*fcf3ce44SJohn Forte 	if (nsc_insert_node(devhash, &devlist[devcount], path) < 0) {
1200*fcf3ce44SJohn Forte 		return (-1);
1201*fcf3ce44SJohn Forte 	}
1202*fcf3ce44SJohn Forte 
1203*fcf3ce44SJohn Forte 	++devcount;
1204*fcf3ce44SJohn Forte 	return (0);
1205*fcf3ce44SJohn Forte }
1206*fcf3ce44SJohn Forte 
1207*fcf3ce44SJohn Forte static void
1208*fcf3ce44SJohn Forte rebuild_devhash()
1209*fcf3ce44SJohn Forte {
1210*fcf3ce44SJohn Forte 	int i;
1211*fcf3ce44SJohn Forte 
1212*fcf3ce44SJohn Forte 	if (!devhash)
1213*fcf3ce44SJohn Forte 		nsc_remove_all(devhash, 0);
1214*fcf3ce44SJohn Forte 
1215*fcf3ce44SJohn Forte 	devhash = nsc_create_hash();
1216*fcf3ce44SJohn Forte 	if (!devhash)
1217*fcf3ce44SJohn Forte 		return;
1218*fcf3ce44SJohn Forte 
1219*fcf3ce44SJohn Forte 	for (i = 0; i < devcount; i++) {
1220*fcf3ce44SJohn Forte 		nsc_insert_node(devhash, &devlist[i], devlist[i].path);
1221*fcf3ce44SJohn Forte 	}
1222*fcf3ce44SJohn Forte }
1223*fcf3ce44SJohn Forte 
1224*fcf3ce44SJohn Forte static int
1225*fcf3ce44SJohn Forte compare(const void *va, const void *vb)
1226*fcf3ce44SJohn Forte {
1227*fcf3ce44SJohn Forte 	device_t *a = (device_t *)va;
1228*fcf3ce44SJohn Forte 	device_t *b = (device_t *)vb;
1229*fcf3ce44SJohn Forte 
1230*fcf3ce44SJohn Forte 	return (b->rdev - a->rdev);
1231*fcf3ce44SJohn Forte }
1232*fcf3ce44SJohn Forte 
1233*fcf3ce44SJohn Forte static char *
1234*fcf3ce44SJohn Forte find_devid(const char *path)
1235*fcf3ce44SJohn Forte {
1236*fcf3ce44SJohn Forte 	device_t key;
1237*fcf3ce44SJohn Forte 	device_t *result;
1238*fcf3ce44SJohn Forte 	struct stat buf;
1239*fcf3ce44SJohn Forte 
1240*fcf3ce44SJohn Forte 	if (!devlist || !devhash)
1241*fcf3ce44SJohn Forte 		return (NULL);
1242*fcf3ce44SJohn Forte 
1243*fcf3ce44SJohn Forte 	/* See if we already know the device id by this name */
1244*fcf3ce44SJohn Forte 	result = (device_t *)nsc_lookup(devhash, path);
1245*fcf3ce44SJohn Forte 	if (result) {
1246*fcf3ce44SJohn Forte 		return (NULL);
1247*fcf3ce44SJohn Forte 	}
1248*fcf3ce44SJohn Forte 
1249*fcf3ce44SJohn Forte 	/* try to find it by another name */
1250*fcf3ce44SJohn Forte 	if (stat(path, &buf) < 0)
1251*fcf3ce44SJohn Forte 		return (NULL);
1252*fcf3ce44SJohn Forte 
1253*fcf3ce44SJohn Forte 	key.rdev = buf.st_rdev;
1254*fcf3ce44SJohn Forte 
1255*fcf3ce44SJohn Forte 	/* it's storted, so we use the binary-chop method to find it */
1256*fcf3ce44SJohn Forte 	result = bsearch(&key, devlist, devcount, sizeof (device_t), compare);
1257*fcf3ce44SJohn Forte 
1258*fcf3ce44SJohn Forte 	if (result) {
1259*fcf3ce44SJohn Forte 		return (result->path);
1260*fcf3ce44SJohn Forte 	}
1261*fcf3ce44SJohn Forte 
1262*fcf3ce44SJohn Forte 	return (NULL);
1263*fcf3ce44SJohn Forte }
1264*fcf3ce44SJohn Forte 
1265*fcf3ce44SJohn Forte static void
1266*fcf3ce44SJohn Forte free_dev_entries()
1267*fcf3ce44SJohn Forte {
1268*fcf3ce44SJohn Forte 	int i;
1269*fcf3ce44SJohn Forte 	device_t *p;
1270*fcf3ce44SJohn Forte 
1271*fcf3ce44SJohn Forte 	if (!devlist) {
1272*fcf3ce44SJohn Forte 		return;
1273*fcf3ce44SJohn Forte 	}
1274*fcf3ce44SJohn Forte 	for (i = 0, p = devlist; i < devcount; i++, p++) {
1275*fcf3ce44SJohn Forte 		free(p->path);
1276*fcf3ce44SJohn Forte 	}
1277*fcf3ce44SJohn Forte 	free(devlist);
1278*fcf3ce44SJohn Forte 	devlist = NULL;
1279*fcf3ce44SJohn Forte 	devcount = 0;
1280*fcf3ce44SJohn Forte 	devalloc = 0;
1281*fcf3ce44SJohn Forte 
1282*fcf3ce44SJohn Forte 	if (devhash) {
1283*fcf3ce44SJohn Forte 		nsc_remove_all(devhash, 0);
1284*fcf3ce44SJohn Forte 		devhash = NULL;
1285*fcf3ce44SJohn Forte 	}
1286*fcf3ce44SJohn Forte }
1287