summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdscfg/common/cfg_vols.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdscfg/common/cfg_vols.c')
-rw-r--r--usr/src/lib/libdscfg/common/cfg_vols.c1286
1 files changed, 0 insertions, 1286 deletions
diff --git a/usr/src/lib/libdscfg/common/cfg_vols.c b/usr/src/lib/libdscfg/common/cfg_vols.c
deleted file mode 100644
index 6f0f8bb447..0000000000
--- a/usr/src/lib/libdscfg/common/cfg_vols.c
+++ /dev/null
@@ -1,1286 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/mkdev.h>
-#include <strings.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <errno.h>
-
-#include <sys/nsctl/cfg.h>
-
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_s_u.h>
-#include <sys/unistat/spcs_errors.h>
-#include <sys/unistat/spcs_s_impl.h>
-
-#include <sys/nsctl/sv.h>
-#include <sys/nsctl/nsc_hash.h>
-
-#define DEV_EXPAND 32
-
-#define DO_DISABLE 0
-#define DO_ENABLE 1
-
-/*
- * Utility functions for iiadm and rdcadm/sndradm.
- */
-
-typedef struct hash_data_s {
- union {
- char *users;
- char *mode;
- } u;
- char *path;
- char *node;
- int setno;
-} hash_data_t;
-
-typedef struct {
- dev_t rdev;
- mode_t mode;
- char *path;
-} device_t;
-
-static hash_data_t *make_svol_data(char *, char *, char *, int);
-static hash_data_t *make_dsvol_data(char *, char *, char *, int);
-static void delete_svol_data(void *);
-static void delete_dsvol_data(void *);
-static int sv_action(char *, CFGFILE *, char *, int);
-
-static int add_dev_entry(const char *);
-static int compare(const void *, const void *);
-static char *find_devid(const char *);
-static void free_dev_entries();
-static void rebuild_devhash();
-
-static hash_node_t **dsvol;
-static int dsvol_loaded = 0;
-
-static hash_node_t **svol;
-static int svol_loaded = 0;
-
-static hash_node_t **shadowvol;
-
-static hash_node_t **devhash;
-static device_t *devlist;
-static int devcount = 0;
-static int devalloc = 0;
-
-/*
- * cfg_add_user
- *
- * Description:
- * Adds the calling tool as a user of the volume.
- *
- * Inputs:
- * char *path: The pathname of the volume to be enabled.
- * char *cnode: The device group name, or NULL if -C local or not cluster
- * CFGFILE *cfg: A pointer to the current config file, or NULL if this
- * function is to open/write/commit/close the change itself.
- *
- * Return values:
- * CFG_USER_FIRST: Indicates that this is the first user of this
- * particular volume.
- * CFG_USER_OK: Indicates that the volume has already been entered into
- * the config file.
- * CFG_USER_ERR: Indicates that some failure has occurred and no changes
- * to the config file have been made.
- * CFG_USER_REPEAT: Indicates that this user has already registered for
- * the volume.
- */
-int
-cfg_add_user(CFGFILE* cfg, char *path, char *cnode, char *user)
-{
- int self_open, self_loaded, change_made;
- char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ];
- int retval, rc;
- hash_data_t *data;
-
- self_open = (cfg == NULL);
- self_loaded = 0;
- change_made = 0;
-
- if (self_open) {
- cfg = cfg_open(NULL);
- if (cfg == NULL) {
- return (CFG_USER_ERR);
- }
-
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- /* oops */
- cfg_close(cfg);
- return (CFG_USER_ERR);
- }
- }
-
- /* Check cnode */
- ctag = cfg_get_resource(cfg);
- if (cnode) {
- if (ctag) {
- if (strcmp(cnode, ctag))
- return (CFG_USER_ERR);
- } else
- cfg_resource(cfg, cnode);
- } else
- cnode = ctag;
-
- if (!dsvol_loaded) {
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- self_loaded = 1;
- }
-
- /* find the volume */
- (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode);
- data = nsc_lookup(dsvol, search_key);
-
- if (!data) {
- /* whoops, not found. Add as new user */
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(buf, CFG_MAX_BUF, "%s %s %s", path, cnode,
- user);
- rc = cfg_put_cstring(cfg, "dsvol", buf, strlen(buf));
- if (rc < 0) {
- if (self_loaded) {
- cfg_unload_dsvols();
- }
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- /* reload hash, if we need to */
- if (!self_loaded) {
- cfg_unload_dsvols();
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- }
- retval = CFG_USER_FIRST;
- change_made = 1;
- } else {
- /* Check to ensure we're not already listed */
- char *p = strdup(data->u.users);
- char *q = strtok(p, ",");
- while (q && (strcmp(q, user) != 0)) {
- q = strtok(0, ",");
- }
- free(p); /* not using data; only testing 'q' ptr */
-
- if (!q) {
- /* not listed as a user */
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(buf, CFG_MAX_BUF, "%s %s %s,%s",
- data->path, data->node, data->u.users, user);
- (void) snprintf(search_key, CFG_MAX_KEY, "dsvol.set%d",
- data->setno);
- if (cfg_put_cstring(cfg, search_key, buf,
- strlen(buf)) < 0) {
- if (self_loaded) {
- cfg_unload_dsvols();
- }
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
-
- /*
- * Since we deleted an entry from the config
- * file, we don't know what all the new
- * set numbers are. We need to reload
- * everything
- */
- if (!self_loaded) {
- cfg_unload_dsvols();
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- }
- change_made = 1;
- retval = CFG_USER_OK;
- } else {
- retval = CFG_USER_REPEAT;
- }
- }
-
- if (self_loaded) {
- cfg_unload_dsvols();
- }
-
- if (self_open) {
- if (change_made)
- (void) cfg_commit(cfg);
- cfg_close(cfg);
- }
-
- return (retval);
-}
-
-/*
- * cfg_rem_user
- *
- * Description:
- * Removes a user from the config file.
- *
- * Inputs:
- * char *path: The pathname of the volume to be enabled.
- * char *cnode: The device group name, or NULL if -C local or not cluster
- * char *user: The subsystem that is adding this tag (sv, ii, sndr)
- * CFGFILE *cfg: A pointer to the current config file, or NULL if this
- * function is to open/write/commit/close the change itself.
- * Return values:
- * CFG_USER_ERR: An error occurred during the processing of this
- * directive.
- * CFG_USER_OK: User successfully removed; volume in use by other(s).
- * CFG_USER_LAST: User successfuly removed; no other users registered
- * CFG_USER_GONE: The volume is no longer listed in the dsvol section,
- * indicating some sort of application-level error.
- *
- */
-int
-cfg_rem_user(CFGFILE *cfg, char *path, char *cnode, char *user)
-{
- int self_open, self_loaded, change_made;
- char *ctag, search_key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ];
- char cfg_key[ CFG_MAX_KEY ];
- hash_data_t *data;
- int retval;
- int force_remove;
-
- self_open = (cfg == NULL);
- self_loaded = 0;
- change_made = 0;
- force_remove = (strcmp(user, "sv") == 0);
-
- if ('-' == *user) {
- ++user;
- }
-
- /* Check cnode */
- ctag = cfg_get_resource(cfg);
- if (cnode) {
- if (ctag) {
- if (strcmp(cnode, ctag))
- return (CFG_USER_ERR);
- } else
- cfg_resource(cfg, cnode);
- } else
- cnode = ctag;
-
- if (self_open) {
- cfg = cfg_open(NULL);
- if (cfg == NULL) {
- return (CFG_USER_ERR);
- }
-
- if (!cfg_lock(cfg, CFG_WRLOCK)) {
- /* oops */
- cfg_close(cfg);
- return (CFG_USER_ERR);
- }
- }
-
-
- change_made = 0;
- if (!dsvol_loaded) {
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- self_loaded = 1;
- }
-
- /* find the volume */
- (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode);
- data = nsc_lookup(dsvol, search_key);
-
- if (!data) {
- /* yipes */
- retval = CFG_USER_GONE;
- } else if (force_remove) {
- retval = CFG_USER_LAST;
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(cfg_key, CFG_MAX_KEY, "dsvol.set%d",
- data->setno);
- if (cfg_put_cstring(cfg, cfg_key, NULL, 0) < 0) {
- if (self_loaded) {
- cfg_unload_dsvols();
- }
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- if (!self_loaded) {
- cfg_unload_dsvols();
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- }
- } else {
- char *p = strdup(data->u.users);
- char *q = strtok(p, ",");
- int appended = 0;
-
- (void) snprintf(buf, CFG_MAX_BUF, "%s %s ", data->path,
- data->node);
- while (q && (strcmp(q, user) != 0)) {
- if (appended) {
- strcat(buf, ",");
- strcat(buf, q);
- } else {
- strcat(buf, q);
- appended = 1;
- }
- q = strtok(0, ",");
- }
-
- if (!q) {
- /* uh-oh */
- retval = CFG_USER_GONE;
- } else {
- /* old user skipped; add in remaining users */
- while (q = strtok(0, ", ")) {
- if (appended) {
- strcat(buf, ",");
- strcat(buf, q);
- } else {
- strcat(buf, q);
- appended = 1;
- }
- }
-
- if (appended) {
- retval = CFG_USER_OK;
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(cfg_key, CFG_MAX_KEY,
- "dsvol.set%d", data->setno);
- if (cfg_put_cstring(cfg, cfg_key, buf,
- strlen(buf)) < 0) {
- if (self_loaded) {
- cfg_unload_dsvols();
- }
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- if (!self_loaded) {
- cfg_unload_dsvols();
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- }
- } else {
- retval = CFG_USER_LAST;
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(cfg_key, CFG_MAX_KEY,
- "dsvol.set%d", data->setno);
- if (cfg_put_cstring(cfg, cfg_key, NULL,
- 0) < 0) {
- if (self_loaded) {
- cfg_unload_dsvols();
- }
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- /*
- * Since we deleted an entry from the config
- * file, we don't know what all the new
- * set numbers are. We need to reload
- * everything
- */
- if (!self_loaded) {
- cfg_unload_dsvols();
- if (cfg_load_dsvols(cfg) < 0) {
- if (self_open) {
- cfg_close(cfg);
- }
- return (CFG_USER_ERR);
- }
- }
- }
- change_made = 1;
- }
- }
-
- if (self_loaded) {
- cfg_unload_dsvols();
- }
-
- if (self_open) {
- if (change_made)
- (void) cfg_commit(cfg);
- cfg_close(cfg);
- }
-
- return (retval);
-}
-
-/*
- * Enable a volume under SV control (or add this char *user to the list
- * of users of that volume).
- *
- * Parameters:
- * cfg - The config file to use.
- * path - The pathname of the volume
- * ctag - The cluster tag for this volume (if any)
- * user - The user (sv, ii, sndr) of the volume.
- */
-int
-cfg_vol_enable(CFGFILE *cfg, char *path, char *ctag, char *user)
-{
- int rc;
- int retval;
-
- if (!ctag || *ctag == '\0') {
- ctag = "-";
- }
-
- retval = -1;
- rc = cfg_add_user(cfg, path, ctag, user);
- switch (rc) {
- case CFG_USER_ERR:
- spcs_log("dsvol", NULL,
- gettext("unable to set up dsvol section of config for %s"),
- path);
- break;
- case CFG_USER_OK:
- retval = 0;
- break;
- case CFG_USER_FIRST:
- /* enable sv! */
- retval = sv_action(path, cfg, ctag, DO_ENABLE);
- if (retval < 0) {
- (void) cfg_rem_user(cfg, path, ctag, user);
- }
- break;
- default:
- spcs_log("dsvol", NULL,
- gettext("unexpected return from cfg_add_user(%d)"), rc);
- break;
- }
-
- return (retval);
-}
-
-/*
- * Disable a volume from SV control (or remove this char *user from the list
- * of users of that volume).
- *
- * Parameters:
- * cfg - The config file to use.
- * path - The pathname of the volume
- * ctag - The cluster tag for this volume (if any)
- * user - The user (sv, ii, sndr) of the volume.
- */
-int
-cfg_vol_disable(CFGFILE *cfg, char *path, char *ctag, char *user)
-{
- int rc;
- int retval;
-
- if (!ctag || *ctag == '\0') {
- ctag = "-";
- }
-
- retval = -1;
- rc = cfg_rem_user(cfg, path, ctag, user);
- switch (rc) {
- case CFG_USER_ERR:
- spcs_log("dsvol", NULL,
- gettext("unable to set up dsvol section of config for %s"),
- path);
- break;
- case CFG_USER_OK:
- retval = 0;
- break;
- case CFG_USER_GONE:
- spcs_log("dsvol", NULL,
- gettext("%s tried to remove non-existent tag for %s"),
- user, path);
- break;
- case CFG_USER_LAST:
- /* diable sv! */
- retval = sv_action(path, cfg, ctag, DO_DISABLE);
- break;
- default:
- spcs_log("dsvol", NULL,
- gettext("unexpected return from cfg_rem_user(%d)"), rc);
- break;
- }
-
- return (retval);
-}
-
-/*
- * cfg_load_dsvols
- *
- * Description:
- * Loads the dsvol section of the config file into a giant hash, to
- * make searching faster. The important bit to remember is to not
- * release the write lock between calling cfg_load_dsvols() and the
- * cfg_*_user() functions.
- *
- * Assumptions:
- * 1/ cfg file is open
- * 2/ cfg file has been write-locked
- * 3/ user of this routine may already be using hcreate/hsearch
- *
- * Return value:
- * -1 if error, or total number of sets found
- */
-int
-cfg_load_dsvols(CFGFILE *cfg)
-{
- int set, rc, entries;
- char search_key[ CFG_MAX_KEY ];
- char *buf;
- char **entry, *path, *cnode, *users;
- hash_data_t *data;
- int devs_added = 0;
- int offset = 0;
- char *ctag = cfg_get_resource(cfg);
- if (!ctag || *ctag == '\0') {
- ctag = "-";
- }
-
- dsvol = nsc_create_hash();
- if (!dsvol) {
- return (-1);
- }
-
- rc = 0;
- cfg_rewind(cfg, CFG_SEC_CONF);
- entries = cfg_get_section(cfg, &entry, "dsvol");
- for (set = 1; set <= entries; set++) {
- buf = entry[set - 1];
-
- /* split up the line */
- if (!(path = strtok(buf, " "))) {
- /* oops, now what? */
- free(buf);
- break;
- }
- if (!(cnode = strtok(0, " "))) {
- free(buf);
- break;
- }
- if (ctag && (strcmp(cnode, ctag) != 0)) {
- ++offset;
- free(buf);
- continue;
- }
-
- if (!(users = strtok(0, " "))) {
- free(buf);
- break;
- }
-
- data = make_dsvol_data(path, cnode, users, set - offset);
- if (!data) {
- free(buf);
- break;
- }
- (void) snprintf(search_key, CFG_MAX_KEY, "%s:%s", path, cnode);
- rc = nsc_insert_node(dsvol, data, search_key);
- if (rc < 0) {
- free(buf);
- break;
- }
-
- /* we also need to keep track of node information */
- rc = add_dev_entry(path);
- if (rc < 0) {
- free(buf);
- break;
- } else if (rc)
- ++devs_added;
-
- free(buf);
- rc = 0;
- }
-
- while (set < entries)
- free(entry[set++]);
- if (entries)
- free(entry);
-
- if (devs_added) {
- qsort(devlist, devcount, sizeof (device_t), compare);
- rebuild_devhash();
- }
-
- dsvol_loaded = 1;
- return (rc < 0? rc : entries);
-}
-
-/*
- * cfg_unload_dsvols
- *
- * Description:
- * Free all memory allocated with cfg_load_dsvols.
- */
-void
-cfg_unload_dsvols()
-{
- if (dsvol) {
- nsc_remove_all(dsvol, delete_dsvol_data);
- dsvol = 0;
- dsvol_loaded = 0;
- }
-}
-
-/*
- * cfg_load_svols
- *
- * Description:
- * Loads the sv section of the config file into a giant hash, to make
- * searching faster. The important bit to remember is to not release
- * the write lock between calling cfg_load_svols() and the cfg_*_user()
- * functions.
- *
- * Assumptions:
- * 1/ cfg file is open
- * 2/ cfg file has been write-locked
- * 3/ user of this routine may already be using builtin hcreate/hsearch
- */
-int
-cfg_load_svols(CFGFILE *cfg)
-{
- int set, entries, offset = 0;
- char *buf, **entry;
- char *path, *mode, *cnode;
- hash_data_t *data;
- char *ctag = cfg_get_resource(cfg);
- if (!ctag || *ctag == '\0') {
- ctag = "-";
- }
-
- svol = nsc_create_hash();
- if (!svol) {
- return (-1);
- }
-
- cfg_rewind(cfg, CFG_SEC_CONF);
- entries = cfg_get_section(cfg, &entry, "sv");
- for (set = 1; set <= entries; set++) {
- buf = entry[set - 1];
-
- /* split up the line */
- if (!(path = strtok(buf, " "))) {
- free(buf);
- break;
- }
- if (!(mode = strtok(0, " "))) {
- free(buf);
- break;
- }
- if (!(cnode = strtok(0, " "))) {
- cnode = "";
- }
-
- if (ctag && (strcmp(cnode, ctag) != 0)) {
- ++offset;
- free(buf);
- continue;
- }
-
- data = make_svol_data(path, mode, cnode, set - offset);
- if (!data) {
- free(buf);
- break;
- }
- if (nsc_insert_node(svol, data, path) < 0) {
- free(buf);
- break;
- }
- free(buf);
- }
- while (set < entries)
- free(entry[set++]);
- if (entries)
- free(entry);
-
- svol_loaded = 1;
- return (0);
-}
-
-/*
- * cfg_unload_svols
- *
- * Description:
- * Frees all memory allocated with cfg_load_dsvols
- */
-void
-cfg_unload_svols()
-{
- if (svol) {
- nsc_remove_all(svol, delete_svol_data);
- svol = 0;
- svol_loaded = 0;
- }
-}
-
-/*
- * cfg_get_canonical_name
- *
- * Description:
- * Find out whether a device is already known by another name in
- * the config file.
- *
- * Parameters:
- * cfg - The config file to use
- * path - The pathname of the device
- * result - (output) The name it is otherwise known as. This parameter
- * must be freed by the caller.
- *
- * Return values:
- * -1: error
- * 0: name is as expected, or is not known
- * 1: Name is known by different name (stored in 'result')
- */
-int
-cfg_get_canonical_name(CFGFILE *cfg, const char *path, char **result)
-{
- int self_loaded;
- char *alt_path;
- int retval;
-
- if (devlist) {
- self_loaded = 0;
- } else {
- if (cfg_load_shadows(cfg) < 0) {
- return (-1);
- }
- self_loaded = 1;
- }
-
- /* see if it exists under a different name */
- alt_path = find_devid(path);
- if (!alt_path || strcmp(path, alt_path) == 0) {
- *result = NULL;
- retval = 0;
- } else {
- /* a-ha */
- *result = strdup(alt_path);
- retval = 1;
- }
-
- if (self_loaded) {
- free_dev_entries();
- }
-
- return (retval);
-}
-
-/*
- * cfg_load_shadows
- *
- * Description:
- * Load in shadow and bitmap volumes from the II section of the
- * config file. SNDR's volumes are handled already by cfg_load_dsvols.
- * Not all shadow volumes are listed under dsvol: they can be exported.
- *
- * Parameters:
- * cfg - The config file to use
- *
- * Return values:
- * -1: error
- * 0: success
- */
-int
-cfg_load_shadows(CFGFILE *cfg)
-{
- int set, self_loaded, rc, entries;
- char *buf, **entry, *ptr;
- int devs_added = 0;
-
- if (dsvol_loaded) {
- self_loaded = 0;
- } else {
- if (cfg_load_dsvols(cfg) < 0) {
- return (-1);
- }
- self_loaded = 1;
- }
-
- shadowvol = nsc_create_hash();
- if (!shadowvol) {
- return (-1);
- }
-
- rc = 0;
- cfg_rewind(cfg, CFG_SEC_CONF);
- entries = cfg_get_section(cfg, &entry, "ii");
- for (set = 1; set <= entries; set++) {
- buf = entry[set - 1];
-
- /* skip the master vol */
- ptr = strtok(buf, " ");
-
- /* shadow is next */
- ptr = strtok(NULL, " ");
-
- rc = add_dev_entry(ptr);
- if (rc < 0) {
- free(buf);
- break;
- } else if (rc)
- ++devs_added;
-
- /* and next is bitmap */
- ptr = strtok(NULL, " ");
-
- rc = add_dev_entry(ptr);
- if (rc < 0) {
- free(buf);
- break;
- } else if (rc)
- ++devs_added;
- rc = 0;
- free(buf);
- }
- while (set < entries)
- free(entry[set++]);
- if (entries)
- free(entry);
-
- if (self_loaded) {
- cfg_unload_dsvols();
- }
-
- if (devs_added) {
- /* sort it, in preparation for lookups */
- qsort(devlist, devcount, sizeof (device_t), compare);
- rebuild_devhash();
- }
-
- return (rc);
-}
-
-void
-cfg_unload_shadows()
-{
- /* do nothing */
-}
-
-/* ---------------------------------------------------------------------- */
-
-static hash_data_t *
-make_dsvol_data(char *path, char *cnode, char *users, int set)
-{
- hash_data_t *data;
-
- data = (hash_data_t *)malloc(sizeof (hash_data_t));
- if (!data) {
- return (0);
- }
-
- data->u.users = strdup(users);
- data->path = strdup(path);
- data->node = strdup(cnode);
- data->setno = set;
-
- return (data);
-}
-
-static void
-delete_dsvol_data(void *data)
-{
- hash_data_t *p = (hash_data_t *)data;
-
- free(p->u.users);
- free(p->path);
- free(p->node);
- free(p);
-}
-
-static hash_data_t *
-make_svol_data(char *path, char *mode, char *cnode, int set)
-{
- hash_data_t *data;
-
- data = (hash_data_t *)malloc(sizeof (hash_data_t));
- if (!data) {
- return (0);
- }
-
- data->u.mode = strdup(mode);
- data->path = strdup(path);
- data->node = strdup(cnode);
- data->setno = set;
-
- return (data);
-}
-
-
-static void
-delete_svol_data(void *data)
-{
- hash_data_t *p = (hash_data_t *)data;
-
- free(p->u.mode);
- free(p->path);
- free(p->node);
- free(p);
-}
-
-static int
-sv_action(char *path, CFGFILE *caller_cfg, char *ctag, int enable)
-{
- struct stat stb;
- sv_conf_t svc;
- int fd = -1;
- int cfg_changed = 0;
- CFGFILE *cfg;
- int print_log = 0;
- int err = 0, rc;
- int sv_ioctl, spcs_err, self_loaded;
- char *log_str1, *log_str2;
- char key[ CFG_MAX_KEY ];
- char buf[ CFG_MAX_BUF ];
- hash_data_t *node;
- device_t *statinfo = 0;
-
- if (caller_cfg == NULL) {
- cfg = cfg_open(NULL);
- if (cfg == NULL)
- return (-1);
-
- if (ctag)
- cfg_resource(cfg, ctag);
- } else
- cfg = caller_cfg;
-
-
- self_loaded = 0;
- sv_ioctl = (enable? SVIOC_ENABLE : SVIOC_DISABLE);
- log_str1 = (enable? gettext("enabled %s") : gettext("disabled %s"));
- log_str2 = (enable? gettext("unable to enable %s") :
- gettext("unable to disable %s"));
- spcs_err = (enable? SV_EENABLED : SV_EDISABLED);
- bzero(&svc, sizeof (svc));
-
- if (devhash)
- statinfo = nsc_lookup(devhash, path);
-
- if (statinfo) {
- if (!S_ISCHR(statinfo->mode))
- goto error;
- svc.svc_major = major(statinfo->rdev);
- svc.svc_minor = minor(statinfo->rdev);
- } else {
- if (stat(path, &stb) != 0)
- goto error;
-
- if (!S_ISCHR(stb.st_mode))
- goto error;
- svc.svc_major = major(stb.st_rdev);
- svc.svc_minor = minor(stb.st_rdev);
- }
-
- strncpy(svc.svc_path, path, sizeof (svc.svc_path));
-
- fd = open(SV_DEVICE, O_RDONLY);
- if (fd < 0)
- goto error;
-
- svc.svc_flag = (NSC_DEVICE | NSC_CACHE);
- svc.svc_error = spcs_s_ucreate();
-
- do {
- rc = ioctl(fd, sv_ioctl, &svc);
- } while (rc < 0 && errno == EINTR);
-
- if (rc < 0) {
- if (errno != spcs_err) {
- spcs_log("sv", &svc.svc_error, log_str2, svc.svc_path);
- if (enable)
- goto error;
- else
- err = errno;
- } else
- err = spcs_err;
- }
-
- spcs_log("sv", NULL, log_str1, svc.svc_path);
-
- /* SV enable succeeded */
- if (caller_cfg == NULL) /* was not previously locked */
- if (!cfg_lock(cfg, CFG_WRLOCK))
- goto error;
-
- if (err != spcs_err) { /* already enabled, already in config */
- if (enable) {
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(buf, CFG_MAX_BUF, "%s - %s", path,
- ctag? ctag : "-");
- if (cfg_put_cstring(cfg, "sv", buf, CFG_MAX_BUF) < 0) {
- /* SV config not updated, so SV disable again */
- (void) ioctl(fd, SVIOC_DISABLE, &svc);
- print_log++;
- } else
- cfg_changed = 1;
- } else {
- /* pull it out of the config */
- if (!svol_loaded) {
- if (cfg_load_svols(cfg) < 0) {
- if (NULL == caller_cfg) {
- cfg_close(cfg);
- }
- return (-1);
- }
- self_loaded = 1;
- }
- node = nsc_lookup(svol, svc.svc_path);
- if (node) {
- cfg_rewind(cfg, CFG_SEC_CONF);
- (void) snprintf(key, CFG_MAX_KEY, "sv.set%d",
- node->setno);
- if (cfg_put_cstring(cfg, key, NULL, NULL) < 0) {
- spcs_log("sv", NULL,
- gettext("failed to remove %s from "
- "sv config"), svc.svc_path);
- }
- /*
- * Since we deleted an entry from the config
- * file, we don't know what all the new
- * set numbers are. We need to reload
- * everything
- */
- if (!self_loaded) {
- cfg_unload_svols();
- if (cfg_load_svols(cfg) < 0) {
- if (NULL == caller_cfg) {
- cfg_close(cfg);
- }
- return (-1);
- }
- }
- cfg_changed = 1;
- }
- if (self_loaded) {
- cfg_unload_svols();
- self_loaded = 0;
- }
- }
- }
-
-#ifdef lint
- (void) printf("extra line to shut lint up %s\n", module_names[0]);
-#endif
-
-error:
- if (fd >= 0)
- (void) close(fd);
-
- if (cfg == NULL)
- return (-1);
-
- if (cfg_changed)
- if (caller_cfg == NULL) /* we opened config */
- (void) cfg_commit(cfg);
-
- if (caller_cfg == NULL)
- cfg_close(cfg);
- if ((cfg_changed) || (err == spcs_err))
- return (1);
- if (print_log)
- spcs_log("sv", NULL,
- gettext("unable to add to configuration, disabled %s"),
- svc.svc_path);
- spcs_s_ufree(&svc.svc_error);
-
- return (-1);
-}
-
-/*
- * add_dev_entry
- *
- * Add an entry into the devlist and the devhash for future lookups.
- *
- * Return values:
- * -1 An error occurred.
- * 0 Entry added
- * 1 Entry already exists.
- */
-static int
-add_dev_entry(const char *path)
-{
- struct stat buf;
- device_t *newmem;
- hash_data_t *data;
-
- if (!devhash) {
- devhash = nsc_create_hash();
- if (!devhash) {
- return (-1);
- }
- } else {
- data = nsc_lookup(devhash, path);
- if (data) {
- return (1);
- }
- }
-
- if (stat(path, &buf) < 0) {
- /* ignore error, we are most likely deleting entry anyway */
- buf.st_rdev = 0;
- }
-
- if (devcount >= devalloc) {
- /* make some room */
- devalloc += DEV_EXPAND;
- newmem = (device_t *)realloc(devlist, devalloc *
- sizeof (device_t));
- if (!newmem) {
- free_dev_entries();
- return (-1);
- } else {
- devlist = newmem;
- }
- }
-
- devlist[ devcount ].path = strdup(path);
- devlist[ devcount ].rdev = buf.st_rdev;
- devlist[ devcount ].mode = buf.st_mode;
-
- if (nsc_insert_node(devhash, &devlist[devcount], path) < 0) {
- return (-1);
- }
-
- ++devcount;
- return (0);
-}
-
-static void
-rebuild_devhash()
-{
- int i;
-
- if (!devhash)
- nsc_remove_all(devhash, 0);
-
- devhash = nsc_create_hash();
- if (!devhash)
- return;
-
- for (i = 0; i < devcount; i++) {
- nsc_insert_node(devhash, &devlist[i], devlist[i].path);
- }
-}
-
-static int
-compare(const void *va, const void *vb)
-{
- device_t *a = (device_t *)va;
- device_t *b = (device_t *)vb;
-
- return (b->rdev - a->rdev);
-}
-
-static char *
-find_devid(const char *path)
-{
- device_t key;
- device_t *result;
- struct stat buf;
-
- if (!devlist || !devhash)
- return (NULL);
-
- /* See if we already know the device id by this name */
- result = (device_t *)nsc_lookup(devhash, path);
- if (result) {
- return (NULL);
- }
-
- /* try to find it by another name */
- if (stat(path, &buf) < 0)
- return (NULL);
-
- key.rdev = buf.st_rdev;
-
- /* it's storted, so we use the binary-chop method to find it */
- result = bsearch(&key, devlist, devcount, sizeof (device_t), compare);
-
- if (result) {
- return (result->path);
- }
-
- return (NULL);
-}
-
-static void
-free_dev_entries()
-{
- int i;
- device_t *p;
-
- if (!devlist) {
- return;
- }
- for (i = 0, p = devlist; i < devcount; i++, p++) {
- free(p->path);
- }
- free(devlist);
- devlist = NULL;
- devcount = 0;
- devalloc = 0;
-
- if (devhash) {
- nsc_remove_all(devhash, 0);
- devhash = NULL;
- }
-}