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