xref: /titanic_51/usr/src/cmd/avs/dscfg/dscfg.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <sys/vtoc.h>
30 #include <sys/stat.h>
31 #include <stdio.h>
32 #include <sys/mnttab.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <time.h>
41 
42 #include <locale.h>
43 #include <langinfo.h>
44 #include <libintl.h>
45 #include <stdarg.h>
46 #include <netdb.h>
47 #include <ctype.h>
48 #include <assert.h>
49 
50 #include <sys/nsctl/cfg_impl.h>
51 #include <sys/nsctl/cfg.h>
52 
53 #include <sys/unistat/spcs_s.h>
54 #include <sys/unistat/spcs_s_u.h>
55 #include <sys/unistat/spcs_errors.h>
56 
57 #ifdef DEBUG
58 #include <sys/nsctl/dsw.h>
59 #endif
60 
61 #define	DEFAULT_PARSER_LOC "/etc/dscfg_format"
62 
63 int Cflg;
64 int Dflg;
65 int Lflg;
66 int aflg;
67 int iflg;
68 int lflg;
69 int nflg;
70 int pflg;
71 int rflg;
72 int sflg;
73 int uflg;
74 
75 int verbose;
76 int noflags;
77 int errflg;
78 int mustcommit;
79 char *locname;		/* config location  from cfg_location */
80 char *cmdname;
81 
82 #define	MAX_FILENAME	80
83 
84 char output_file[MAX_FILENAME];	/* specified output file */
85 char altroot[MAX_FILENAME];	/* specifed root location */
86 char config_file[MAX_FILENAME];	/* specified configuration file */
87 char input_file[MAX_FILENAME];	/* specified input file */
88 char logical_host[MAX_FILENAME]; /* specified  cluster node */
89 char device_group[MAX_FILENAME]; /* specified device group name */
90 
91 #define	IS_NOT_CLUSTER	1
92 #define	IS_CLUSTER	2
93 
94 void cfg_invalidate_hsizes(int, const char *);
95 static int check_cluster();
96 
97 void
98 usage(char *errmsg)
99 {
100 	if (errmsg)
101 		(void) fprintf(stderr, "%s: %s\n", cmdname, errmsg);
102 	(void) fprintf(stderr,
103 	    gettext("dscfg \t\t\t\tDisplay location of "
104 		"local configuration database\n"));
105 	(void) fprintf(stderr, gettext("dscfg -l -s path\t\t"
106 		"List contents of configuration database\n"));
107 	(void) fprintf(stderr, gettext(
108 		"\t\t\t\tlocated at path specified\n"));
109 	(void) fprintf(stderr, gettext("dscfg -i\t\t\t"
110 		"Initialize configuration database\n"));
111 	(void) fprintf(stderr,
112 	    gettext("dscfg -i -p "
113 #ifdef DEBUG
114 "[-n] "
115 #endif
116 	    "/etc/dscfg_format\tFormat configuration database\n"));
117 	(void) fprintf(stderr,
118 	    gettext("dscfg -a file\t\t\tRestore configuration "
119 	    "database from file\n"));
120 	(void) fprintf(stderr, gettext("\t\t\t\tspecified\n"));
121 	(void) fprintf(stderr,
122 		gettext("dscfg -l\t\t\tList contents of configuration database"
123 		"\n"));
124 	(void) fprintf(stderr,
125 		gettext("dscfg -L\t\t\tDisplay configuration database's\n"));
126 	(void) fprintf(stderr, gettext("\t\t\t\tlock status\n"));
127 	(void) fprintf(stderr, gettext("dscfg -h\t\t\tUsage message\n"));
128 	if (check_cluster() != IS_NOT_CLUSTER) {
129 	(void) fprintf(stderr, gettext("\nSun Cluster Usage\n"));
130 	(void) fprintf(stderr, gettext("******************\n"));
131 	(void) fprintf(stderr,
132 		gettext("dscfg -s path\t\t\tSet cluster "
133 		"configuration database at DID\n"));
134 	(void) fprintf(stderr, gettext("\t\t\t\tpath specified\n"));
135 	(void) fprintf(stderr, gettext("dscfg -D device_group\t\t"
136 		"Check status of cluster device group\n"));
137 	(void) fprintf(stderr, gettext("dscfg -C -\t\t\t"
138 		"Display location of cluster configuration\n"));
139 	(void) fprintf(stderr, gettext("\t\t\t\tdatabase\n"));
140 	(void) fprintf(stderr, gettext("dscfg -l -s DID_device\t\tList "
141 		"the contents of cluster configuration\n"));
142 	(void) fprintf(stderr, gettext("\t\t\t\tdatabase\n"));
143 	(void) fprintf(stderr, gettext("dscfg -C - -i\t\t\tInitialize "
144 		"cluster configuration database\n"));
145 	(void) fprintf(stderr, gettext("dscfg -C - -i -p "
146 		"/etc/dscfg_format Format cluster configuration database\n"));
147 	(void) fprintf(stderr, gettext("dscfg -C - -a file\t\t"
148 		"Restore cluster configuration database from\n"));
149 	(void) fprintf(stderr, gettext("\t\t\t\tfile specified\n"));
150 	(void) fprintf(stderr, gettext("dscfg -C - -l\t\t\t"
151 		"List contents of local configuration database\n"));
152 	(void) fprintf(stderr, gettext("dscfg -C device_group -l\t"
153 		"List configuration database by device group\n"));
154 	(void) fprintf(stderr, gettext("dscfg -C \"-\" -l\t\t\t"
155 		"List configuration database excluding\n"));
156 	(void) fprintf(stderr, gettext("\t\t\t\tdevice groups\n"));
157 	}
158 }
159 
160 int
161 parse_parse_config(CFGFILE *cfg)
162 {
163 	FILE *fp;
164 	char	inbuf[CFG_MAX_BUF];
165 	char	*buff;
166 	int	rc;
167 
168 	/*
169 	 * Open parser config file, use default if none specified
170 	 */
171 	buff = (input_file[0]) ? input_file : DEFAULT_PARSER_LOC;
172 	if ((fp = fopen(buff, "r")) == NULL) {
173 		(void) fprintf(stderr,
174 			gettext("parser config file (%s) not found\n"), buff);
175 		return (-1);
176 	}
177 
178 	/*
179 	 * start at begining of configration database
180 	 */
181 	cfg_rewind(cfg, CFG_SEC_ALL);
182 
183 	while (((buff = fgets(inbuf, (sizeof (inbuf) - 1), fp)) != NULL)) {
184 		if (*buff == '#' || *buff == '%')
185 			continue;
186 		/* overwrite newline */
187 		buff[strlen(buff) - 1] = '\0';
188 		rc = cfg_update_parser_config(cfg, buff, CFG_PARSE_CONF);
189 		if (rc < 0) {
190 			(void) fprintf(stderr,
191 			    gettext("update parser config rc %d key %s\n"),
192 			    rc, buff);
193 			(void) fclose(fp);
194 			return (-1);
195 		}
196 	}
197 	(void) fclose(fp);
198 	return (1);
199 }
200 
201 void
202 parse_text_config(CFGFILE *cfg)
203 {
204 	FILE *fp;
205 	char	inbuf[CFG_MAX_BUF];
206 	char	*buff;
207 	char	*key;
208 	char	*p;
209 	int	rc;
210 
211 	if ((fp = fopen(input_file, "r")) == NULL) {
212 		(void) fprintf(stderr,
213 			    gettext("Unable to open text config %s\n"),
214 				input_file);
215 		exit(2);
216 	}
217 	bzero(inbuf, sizeof (inbuf));
218 	cfg_rewind(cfg, CFG_SEC_CONF);
219 	while (((buff = fgets(inbuf, (sizeof (inbuf) - 1), fp)) != NULL)) {
220 		if (*buff == '#')
221 			continue;
222 		/* overwrite newline */
223 		buff[strlen(buff) - 1] = '\0';
224 		key = strtok(buff, ":");
225 		if (!key) {
226 			continue;
227 		}
228 		p = &buff[strlen(key)+2];
229 		while (*p && isspace(*p)) {
230 			++p;
231 		}
232 		if (!*p) {
233 			continue;
234 		}
235 		rc = cfg_put_cstring(cfg, key, p, strlen(p));
236 		if (rc < 0) {
237 			(void) fprintf(stderr,
238 			    gettext("update text config failed rc %d key %s"),
239 			    rc, buff);
240 			return;
241 		}
242 		bzero(inbuf, sizeof (inbuf));
243 	}
244 	(void) fclose(fp);
245 }
246 void
247 dump_status(CFGFILE *cfg)
248 {
249 	cfp_t *cfp = FP_SUN_CLUSTER(cfg);
250 
251 	/*
252 	 * WARNING will robinson
253 	 * The following is using a non-exported internal interface
254 	 * to libcfg
255 	 * You may not use any of the following fields in MS software
256 	 */
257 	if (!locname)
258 		exit(2);
259 	if (!verbose)
260 		(void) printf("%s\n", locname);
261 	else {
262 #ifdef DEBUG
263 		(void) printf(gettext("Configuration location: %s\n"), locname);
264 		(void) printf(
265 		    gettext("Header info:\n\t\t\tmagic: %x\tstate: %x\n"),
266 		    cfp->cf_head->h_magic, cfp->cf_head->h_state);
267 		(void) printf(
268 		    gettext("Parser section:\t\t"
269 		    "Start: %x\tsize: %d offset: %d\n"),
270 		    cfp->cf_mapped, cfp->cf_head->h_parsesize,
271 		    cfp->cf_head->h_parseoff);
272 		(void) printf(
273 		    gettext("Config section:\t\t"
274 		    "Start: %x\tsize:%d\tacsize: %d\n"),
275 		    cfp->cf_head->h_cparse, cfp->cf_head->h_csize,
276 		    cfp->cf_head->h_acsize);
277 		(void) printf("\t\t\tccopy1: %s\tccopy2: %s\n",
278 			cfp->cf_head->h_ccopy1,
279 			cfp->cf_head->h_ccopy2);
280 		(void) printf(
281 		    gettext("Sequence:\t\tseq1: %d\t\tseq2: %d\n"),
282 			cfp->cf_head->h_seq1, cfp->cf_head->h_seq2);
283 #endif
284 	}
285 }
286 
287 void
288 dump_lockstat(CFGFILE *cfg)
289 {
290 	pid_t pid;
291 	CFGLOCK lock;
292 	char	ps_str[1024];
293 
294 	if (cfg_get_lock(cfg, &lock, &pid) == TRUE) {
295 		(void) printf("%s %ld\n",
296 		    lock == CFG_RDLOCK ?
297 			    gettext("Read locked by process id") :
298 			    gettext("Write locked by process id"),
299 		    pid);
300 		(void) sprintf(ps_str, "ps -p %ld", pid);
301 		system(ps_str);
302 	} else
303 		(void) printf("%s\n", gettext("Not locked."));
304 }
305 
306 
307 /*
308  * dump current configuration section to stdout
309  */
310 
311 void
312 print_config(CFGFILE *cfg)
313 {
314 	time_t tloc = 0;
315 	int set = 0;
316 	char pconfig[CFG_MAX_BUF];
317 	char key[CFG_MAX_KEY];
318 	char buf[CFG_MAX_BUF];
319 	char *cp, pbuf[CFG_MAX_BUF];
320 	FILE *fp;
321 	int rc;
322 	int end;
323 
324 	(void) snprintf(pconfig, sizeof (pconfig),
325 	    "%s%s", altroot, DEFAULT_PARSER_LOC);
326 	if ((fp = fopen(pconfig, "r")) == NULL) {
327 		(void) fprintf(stderr,
328 		    gettext("dscfg: unable to open "
329 		    "parser configuration (%s): %s\n"),
330 		    pconfig, strerror(errno));
331 		exit(1);
332 	}
333 
334 	(void) time(&tloc);
335 	(void) printf(gettext("# Consolidated Dataservice Configuration\n"));
336 	(void) printf(gettext("# Do not edit out whitespace or dashes\n"));
337 	(void) printf(gettext("# File created on: %s"), ctime(&tloc));
338 
339 	while (fgets(pbuf, (sizeof (pbuf) - 1), fp) != NULL) {
340 		if (pbuf[0] == '#') {
341 			/* comment */
342 			continue;
343 		}
344 		/* force a NULL terminator */
345 		pbuf[sizeof (pbuf) - 1] = '\0';
346 
347 		if (pbuf[0] == '%') {
348 			/*
349 			 * descriptive text
350 			 * - print it (with comment leader) and move on
351 			 */
352 			(void) printf("#%s", &pbuf[1]);
353 			continue;
354 		}
355 
356 		/*
357 		 * truncate the parser config in pbuf[] to just the tag
358 		 */
359 		cp = strchr(pbuf, '.');
360 		if (cp != NULL) {
361 			*cp = '\0';
362 		}
363 
364 		set = 1;
365 		/*CONSTCOND*/
366 		while (1) {
367 			bzero(buf, CFG_MAX_BUF);
368 			(void) snprintf(key,
369 			    sizeof (key), "%s.set%d", pbuf, set);
370 			rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF);
371 			if (rc < 0) {
372 				break;
373 			}
374 			/* trim trailing space if necessary */
375 			end = strlen(buf) - 1;
376 			if (buf[end] == ' ')
377 				buf[end] = '\0';
378 
379 			(void) printf("%s:%s\n", pbuf, buf);
380 			set++;
381 		}
382 	}
383 
384 	(void) fclose(fp);
385 }
386 
387 int
388 make_new_config(const char *fileloc)
389 {
390 	int fd;
391 	int rc;
392 	int skip;
393 
394 	char buf[CFG_MAX_BUF];
395 	/*CONSTCOND*/
396 	assert((sizeof (buf) % 512) == 0);
397 
398 	bzero(buf, CFG_MAX_BUF);
399 
400 	if ((fd = open(fileloc, O_RDWR | O_CREAT, 0640)) == -1) {
401 		return (-1);
402 	}
403 
404 	/* if this is a device, we may have to skip the vtoc */
405 	if ((skip = cfg_shldskip_vtoc(fd, fileloc)) == -1) {
406 		(void) fprintf(stderr,
407 			gettext("dscfg: unable to read vtoc on (%s)\n"),
408 				fileloc);
409 		return (-1);
410 	} else if (skip) {
411 		do {
412 			rc = lseek(fd, CFG_VTOC_SKIP, SEEK_SET);
413 		} while (rc == -1 && errno == EINTR);
414 
415 		if (rc == -1) {
416 			(void) fprintf(stderr, gettext("dscfg: seek error"));
417 			return (-1);
418 		}
419 	}
420 
421 	do {
422 		rc = write(fd, buf, sizeof (buf));
423 	} while (rc == -1 && errno == EINTR);
424 
425 	close(fd);
426 
427 	return ((rc < 0) ? 0 : 1);
428 }
429 
430 /*
431  * dscfg
432  * configure or return dataservice persistent configuration
433  *
434  * options
435  *		-i initialize file for first time
436  *		-l dump current configuration to stdout in ascii
437  *		-a add
438  *		-C node	Set resource filter
439  *		-p parser config specified input file
440  *		-s set partition location or filename in default location
441  *		-L print configuration lock status
442  *		-u upgrade
443  *		-r prepend bootdir to beginning of path for cfg_open
444  *	no options    status
445  *
446  *
447  */
448 #ifdef lint
449 int
450 dscfg_lintmain(int argc, char *argv[])
451 #else
452 int
453 main(int argc, char *argv[])
454 #endif
455 {
456 	CFGFILE *cfg;
457 	extern char *optarg;
458 	char *loc;
459 	int offset = 0;
460 	int rc;
461 	char c;
462 	int local;
463 	int action_counts = 0;
464 
465 	bzero(input_file, sizeof (input_file));
466 	(void) setlocale(LC_ALL, "");
467 	(void) textdomain("dscfg");
468 	logical_host[0] = '\0';
469 	cmdname = argv[0];
470 #ifdef DEBUG
471 	while ((c = getopt(argc, argv, "a:C:dD:ilLp:r:s:hvn")) != EOF) {
472 #else
473 	while ((c = getopt(argc, argv, "a:C:dD:ilLp:r:s:h")) != EOF) {
474 #endif
475 		switch (c) {
476 			case 'a':
477 				aflg++;
478 				strcpy(input_file, optarg);
479 				mustcommit++;
480 				action_counts++;
481 				break;
482 			case 'C':
483 				Cflg++;
484 				strcpy(logical_host, optarg);
485 				if (logical_host && *logical_host == '-')
486 				    if (argc == 3)
487 					action_counts++;
488 				break;
489 			case 'D':
490 				Dflg++;
491 				strcpy(device_group, optarg);
492 				action_counts++;
493 				break;
494 			case 'i':
495 				iflg++;
496 				mustcommit++;
497 				action_counts++;
498 				break;
499 			case 'l':
500 				lflg++;
501 				action_counts++;
502 				break;
503 			case 'L':
504 				Lflg++;
505 				action_counts++;
506 				break;
507 			case 'p':
508 				pflg++;
509 				strcpy(input_file, optarg);
510 				mustcommit++;
511 				break;
512 			case 's':
513 				sflg++;
514 				strcpy(config_file, optarg);
515 				action_counts++;
516 				break;
517 			case 'h':
518 				usage(NULL);
519 				exit(0);
520 			/*NOTREACHED*/
521 #ifdef DEBUG
522 			case 'v':
523 				verbose++;
524 				action_counts++;
525 				break;
526 #endif
527 #ifdef UPGRADE
528 			case 'u':
529 				uflg++;
530 				action_counts++;
531 				break;
532 #endif
533 
534 			case 'r':
535 				rflg++;
536 				strcpy(altroot, optarg);
537 				break;
538 
539 			case 'n':
540 				nflg++;
541 				break;
542 
543 			default:
544 				usage(NULL);
545 				exit(1);
546 				break;
547 		};
548 	}
549 
550 	switch (action_counts) {
551 	    case 0:
552 		if (argc > 1) {
553 		    if (pflg)
554 			usage(gettext(
555 			    "-p option must be used in conjunction with -i"));
556 		    else
557 			usage(gettext("must specify an action flag"));
558 		    exit(1);
559 		}
560 		break;
561 	    case 1:
562 		break;
563 	    case 2:
564 		if (lflg && sflg)
565 			break;
566 		else {
567 		    usage(gettext("too many action flags"));
568 		    exit(1);
569 		    break;
570 		}
571 	    default:
572 		usage(gettext("too many action flags"));
573 		exit(1);
574 		break;
575 	}
576 
577 	if (argc == 1 || (argc == 2 && verbose) || (argc == 3 && (rflg|Cflg)))
578 		noflags++;
579 
580 	if (Dflg) {
581 		/*
582 		 * Determine if the value specified is a device group
583 		 * that is active on this node
584 		 */
585 		char *other_node;
586 		if ((cfg_issuncluster() > 0) && (strlen(device_group) > 0)) {
587 		    local = cfg_dgname_islocal(device_group, &other_node);
588 		    if (local == 0)
589 			(void) fprintf(stderr, gettext(
590 			    "Device group %s active on %s\n"),
591 			    device_group, other_node);
592 		    else if (local == 1)
593 			(void) fprintf(stderr, gettext(
594 			    "Device group %s active on this node\n"),
595 			    device_group);
596 		    else
597 			(void) fprintf(stderr, gettext(
598 			    "Device group %s not found\n"), device_group);
599 		    return (local);
600 		} else {
601 			(void) fprintf(stderr, gettext(
602 			    "dscfg -D is only allowed in "
603 			    "Sun Cluster OE\n"));
604 			return (0);
605 		}
606 	}
607 
608 	if (sflg && !lflg) {
609 		/*
610 		 * Only allow setting location on a non-sun cluster system
611 		 * if the cluster reference file is already present.
612 		 */
613 		struct stat dscfg_stat = {0};
614 		if (cfg_issuncluster() <= 0) {
615 			if (stat(CFG_CLUSTER_LOCATION, &dscfg_stat) != 0) {
616 				if (dscfg_stat.st_blocks == 0) {
617 					(void) fprintf(stderr, gettext(
618 						"dscfg -s is only allowed in "
619 						"Sun Cluster OE\n"));
620 					exit(1);
621 				}
622 			}
623 		}
624 
625 		spcs_log("dscfg", NULL, gettext("dscfg -s %s"), config_file);
626 		locname = cfg_location(config_file, CFG_LOC_SET_CLUSTER,
627 		    rflg ? altroot : NULL);
628 		if (locname == NULL) {
629 			(void) fprintf(stderr, gettext("dscfg: %s\n"),
630 			    cfg_error(NULL));
631 			exit(1);
632 		} else
633 			exit(0);
634 
635 	} else if (sflg && lflg) {
636 		/* s used with l for temporarily peeking at a dscfg database */
637 		loc = config_file;
638 	} else {
639 		locname = cfg_location(NULL,
640 			Cflg ? CFG_LOC_GET_CLUSTER : CFG_LOC_GET_LOCAL,
641 			rflg ? altroot : NULL);
642 		if (Cflg && (locname == NULL)) {
643 			(void) fprintf(stderr, gettext(
644 			    "dscfg: cluster config not set: %s\n"),
645 			    cfg_error(NULL));
646 			return (1);
647 		}
648 		loc = rflg ? locname : NULL;
649 	}
650 
651 	/*
652 	 * the following hack forces the configuration file to initialize
653 	 */
654 	if (iflg && !pflg) {
655 		int fild;
656 		int c;
657 		char buf[CFG_MAX_BUF] = {0};
658 		cfp_t *cfp;
659 
660 		if (!nflg) {
661 			(void) printf(
662 			    gettext("WARNING: This option will erase your "
663 				"Availability Suite configuration\n"));
664 			(void) printf(
665 			    gettext("Do you want to continue? (Y/N) [N] "));
666 
667 			c = getchar();
668 			switch (c) {
669 			case 'y':
670 			case 'Y': break;
671 			case 'n':
672 			case 'N':
673 			case '\n':
674 				(void) fprintf(stderr, gettext(
675 				"dscfg: configuration not initialized\n"));
676 				exit(1);
677 			default:
678 				(void) fprintf(stderr, gettext(
679 				"dscfg: %d is not a valid response\n"), c);
680 				exit(1);
681 			}
682 		}
683 
684 		spcs_log("dscfg", NULL, gettext("dscfg -i"));
685 
686 		if ((cfg = cfg_open(loc)) == NULL) {
687 			/* this is not a good config, or non-existent so.. */
688 			if (!make_new_config(locname)) {
689 				(void) fprintf(stderr, gettext("dscfg: %s\n"),
690 				    cfg_error(NULL));
691 				exit(1);
692 			}
693 			if ((cfg = cfg_open(loc)) == NULL) {
694 				(void) fprintf(stderr, gettext("dscfg: %s\n"),
695 				    cfg_error(NULL));
696 				exit(1);
697 			}
698 		}
699 
700 		/*
701 		 * Set cluster node if specified
702 		 */
703 		if (Cflg)
704 			cfg_resource(cfg, logical_host);
705 
706 		if (cfg_is_cfg(cfg) != 1) {
707 			if (!make_new_config(locname)) {
708 				(void) fprintf(stderr, gettext("dscfg: unable "
709 				    " to create new config \n"));
710 				exit(1);
711 			}
712 		}
713 
714 		if (!cfg_lock(cfg, CFG_WRLOCK)) {
715 			(void) fprintf(stderr, gettext("dscfg: %s\n"),
716 			    cfg_error(NULL));
717 			exit(1);
718 		}
719 
720 		cfp = FP_SUN_CLUSTER(cfg);
721 		if ((fild = cfp->cf_fd) == 0) {
722 			(void) fprintf(stderr,
723 				gettext("dscfg: failure to access %s "
724 				"configuration database: %s\n"),
725 				(Cflg) ? gettext("cluster") : gettext("local"),
726 			cfg_error(NULL));
727 			exit(1);
728 		}
729 
730 		if (cfg_shldskip_vtoc(fild, locname) > 0)
731 			offset += CFG_VTOC_SKIP;
732 
733 		lseek(fild, offset, SEEK_SET);
734 		write(fild, buf, sizeof (buf));
735 		cfg_invalidate_hsizes(fild, locname);
736 
737 		cfg_close(cfg);
738 		exit(0);
739 	}
740 
741 	if (pflg && !iflg) {
742 		usage(gettext("-p option must be used in conjunction with -i"));
743 		exit(1);
744 
745 	}
746 
747 	if (uflg) {
748 		char cmd[CFG_MAX_BUF];
749 		if (rflg)
750 			(void) snprintf(cmd, sizeof (cmd),
751 			    "%s/usr/sbin/dscfg -r %s -l >"
752 			    " %s/var/tmp/.dscfg.bak", altroot,
753 			    altroot, altroot);
754 		else
755 			(void) snprintf(cmd, sizeof (cmd),
756 			    "/usr/sbin/dscfg -l >"
757 			    " /var/tmp/.dscfg.bak");
758 
759 		if (system(cmd) != 0) {
760 			(void) fprintf(stderr,
761 			    "dscfg: unable to create backup\n");
762 			exit(1);
763 		}
764 
765 		if ((cfg = cfg_open(loc)) == NULL) {
766 			(void) fprintf(stderr, gettext("dscfg: %s\n"),
767 			    cfg_error(NULL));
768 			exit(2);
769 		}
770 
771 		if (!cfg_lock(cfg, CFG_UPGRADE)) {
772 			(void) fprintf(stderr,
773 			    gettext("dscfg: upgrade failed\n"));
774 			cfg_close(cfg);
775 			exit(1);
776 		}
777 
778 		cfg_close(cfg);
779 		exit(0);
780 	}
781 
782 	if ((cfg = cfg_open(loc)) == NULL) {
783 		(void) fprintf(stderr, gettext("dscfg: %s\n"), cfg_error(NULL));
784 		exit(2);
785 	}
786 
787 	/*
788 	 * Set cluster node if specified
789 	 */
790 	if (Cflg)
791 		cfg_resource(cfg, logical_host);
792 
793 	if ((!pflg) && (!noflags)) {
794 		if (cfg_is_cfg(cfg) != 1) {
795 			(void) fprintf(stderr,
796 				gettext("dscfg: %s\n"), cfg_error(NULL));
797 			cfg_close(cfg);
798 			exit(1);
799 		}
800 	}
801 
802 	if (Lflg) {
803 		dump_lockstat(cfg);
804 		cfg_close(cfg);
805 		exit(0);
806 	}
807 
808 	if (noflags) {
809 		dump_status(cfg);
810 		cfg_close(cfg);
811 		exit(0);
812 	}
813 
814 	if (!cfg_lock(cfg, mustcommit? CFG_WRLOCK : CFG_RDLOCK)) {
815 		(void) fprintf(stderr, gettext("cfg_lock: lock failed\n"));
816 		cfg_close(cfg);
817 		exit(1);
818 	}
819 
820 	if (lflg) {
821 		print_config(cfg);
822 		cfg_close(cfg);
823 		exit(0);
824 	}
825 
826 	/*
827 	 * initialize configuration
828 	 */
829 	if (iflg) {
830 		spcs_log("dscfg", NULL, gettext("dscfg -i -p %s"), input_file);
831 
832 		if (!pflg) {
833 			(void) fprintf(stderr,
834 			    gettext("dscfg: cannot init without "
835 			    "parser configuration file\n"));
836 			cfg_close(cfg);
837 			exit(1);
838 		} else if (parse_parse_config(cfg) < 0) {
839 			(void) fprintf(stderr, gettext("dscfg: cannot load "
840 				    "parser configuration file\n"));
841 			cfg_close(cfg);
842 			exit(1);
843 		}
844 	}
845 
846 	/*
847 	 * read asci config file and write
848 	 */
849 	if (aflg) {
850 		spcs_log("dscfg", NULL, gettext("dscfg -a %s"), input_file);
851 		parse_text_config(cfg);
852 	}
853 
854 	if (mustcommit) {
855 		rc = cfg_commit(cfg);
856 		if (rc < 0) {
857 			int sev = 0;
858 			(void) fprintf(stderr, gettext("dscfg: %s\n"),
859 			    cfg_error(&sev));
860 			if (sev == CFG_EFATAL) {
861 				cfg_close(cfg);
862 				exit(2);
863 			}
864 		}
865 	}
866 
867 	cfg_close(cfg);
868 	return (0);
869 }
870 
871 static int
872 check_cluster()
873 {
874 	static int is_cluster = -1;
875 	int rc;
876 
877 	if (is_cluster != -1)
878 	    return (is_cluster);
879 	rc = cfg_iscluster();
880 	if (rc > 0) {
881 	    is_cluster = IS_CLUSTER;
882 	    return (is_cluster);
883 	} else if (rc == 0) {
884 	    is_cluster = IS_NOT_CLUSTER;
885 	    return (is_cluster);
886 	} else {
887 	    (void) fprintf(stderr,
888 		gettext("dscfg: unable to determin environment\n"));
889 	    /*NOTREACHED*/
890 	}
891 
892 	/* gcc */
893 	return (is_cluster);
894 }
895