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