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