10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*2063Shshaw * Common Development and Distribution License (the "License").
6*2063Shshaw * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*2063Shshaw * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that
300Sstevel@tonic-gate * TEXT_DOMAIN gets set to something.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
330Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
340Sstevel@tonic-gate #endif
350Sstevel@tonic-gate
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate * patch /kernel/drv/md.conf file
380Sstevel@tonic-gate */
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <sys/stat.h>
410Sstevel@tonic-gate #include <meta.h>
420Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate /*
450Sstevel@tonic-gate * magic strings in system
460Sstevel@tonic-gate */
470Sstevel@tonic-gate #define BEGROOTSTR "* Begin MDD root info (do not edit)\n"
480Sstevel@tonic-gate #define ENDROOTSTR "* End MDD root info (do not edit)\n"
490Sstevel@tonic-gate #define BEGMDDBSTR "# Begin MDD database info (do not edit)\n"
500Sstevel@tonic-gate #define ENDMDDBSTR "# End MDD database info (do not edit)\n"
510Sstevel@tonic-gate
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate * copy system file, yank root and database lines
540Sstevel@tonic-gate */
550Sstevel@tonic-gate int
meta_systemfile_copy(char * sname,int doroot,int domddb,int doit,int verbose,char ** tname,FILE ** tfp,md_error_t * ep)560Sstevel@tonic-gate meta_systemfile_copy(
570Sstevel@tonic-gate char *sname, /* system file name */
580Sstevel@tonic-gate int doroot, /* remove mdd root stuff */
590Sstevel@tonic-gate int domddb, /* remove mdd database stuff */
600Sstevel@tonic-gate int doit, /* really copy file */
610Sstevel@tonic-gate int verbose, /* show what we're doing */
620Sstevel@tonic-gate char **tname, /* returned temp file name */
630Sstevel@tonic-gate FILE **tfp, /* returned open FILE */
640Sstevel@tonic-gate md_error_t *ep /* returned error */
650Sstevel@tonic-gate )
660Sstevel@tonic-gate {
670Sstevel@tonic-gate FILE *fp;
680Sstevel@tonic-gate struct stat sbuf;
690Sstevel@tonic-gate char buf[MDDB_BOOTLIST_MAX_LEN];
700Sstevel@tonic-gate int delroot = 0;
710Sstevel@tonic-gate int delmddb = 0;
720Sstevel@tonic-gate
730Sstevel@tonic-gate /* check names */
740Sstevel@tonic-gate assert(sname != NULL);
750Sstevel@tonic-gate assert(tname != NULL);
760Sstevel@tonic-gate assert(tfp != NULL);
770Sstevel@tonic-gate
780Sstevel@tonic-gate /* get temp name */
790Sstevel@tonic-gate *tfp = NULL;
800Sstevel@tonic-gate *tname = Malloc(strlen(sname) + strlen(".tmp") + 1);
810Sstevel@tonic-gate (void) strcpy(*tname, sname);
820Sstevel@tonic-gate (void) strcat(*tname, ".tmp");
830Sstevel@tonic-gate
840Sstevel@tonic-gate /* copy system file, yank stuff */
850Sstevel@tonic-gate if (((fp = fopen(sname, "r")) == NULL) ||
860Sstevel@tonic-gate (fstat(fileno(fp), &sbuf) != 0)) {
870Sstevel@tonic-gate if (errno != ENOENT) {
880Sstevel@tonic-gate (void) mdsyserror(ep, errno, sname);
890Sstevel@tonic-gate goto out;
900Sstevel@tonic-gate }
910Sstevel@tonic-gate }
920Sstevel@tonic-gate if (doit) {
930Sstevel@tonic-gate if ((*tfp = fopen(*tname, "w")) == NULL) {
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate * If we are on the miniroot we need to create
960Sstevel@tonic-gate * files in /var/tmp. Opening a writable file
970Sstevel@tonic-gate * in the miniroot result is EROFS error.
980Sstevel@tonic-gate */
990Sstevel@tonic-gate if (errno != EROFS) {
1000Sstevel@tonic-gate (void) mdsyserror(ep, errno, *tname);
1010Sstevel@tonic-gate goto out;
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate Free(*tname);
1040Sstevel@tonic-gate *tname = tempnam("/var/tmp", "svm_");
1050Sstevel@tonic-gate if (*tname == NULL) {
1060Sstevel@tonic-gate (void) mdsyserror(ep, errno, NULL);
1070Sstevel@tonic-gate goto out;
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate if ((*tfp = fopen(*tname, "w")) == NULL) {
1100Sstevel@tonic-gate (void) mdsyserror(ep, errno, *tname);
1110Sstevel@tonic-gate goto out;
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate if (fp != NULL) {
1150Sstevel@tonic-gate if ((fchmod(fileno(*tfp), (sbuf.st_mode & 0777))
1160Sstevel@tonic-gate != 0) ||
1170Sstevel@tonic-gate (fchown(fileno(*tfp), sbuf.st_uid, sbuf.st_gid)
1180Sstevel@tonic-gate != 0)) {
1190Sstevel@tonic-gate (void) mdsyserror(ep, errno, *tname);
1200Sstevel@tonic-gate goto out;
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate if (verbose) {
1250Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
1260Sstevel@tonic-gate "Delete the following lines from %s:\n\n"), sname);
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate while ((fp != NULL) && (fgets(buf, sizeof (buf), fp) != NULL)) {
1290Sstevel@tonic-gate if ((doroot) && (strcmp(buf, BEGROOTSTR) == 0)) {
1300Sstevel@tonic-gate delroot = 1;
1310Sstevel@tonic-gate if (verbose)
1320Sstevel@tonic-gate (void) printf("%s", buf);
1330Sstevel@tonic-gate continue;
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate if (delroot) {
1360Sstevel@tonic-gate if (strcmp(buf, ENDROOTSTR) == 0)
1370Sstevel@tonic-gate delroot = 0;
1380Sstevel@tonic-gate if (verbose)
1390Sstevel@tonic-gate (void) printf("%s", buf);
1400Sstevel@tonic-gate continue;
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate if ((domddb) && (strcmp(buf, BEGMDDBSTR) == 0)) {
1430Sstevel@tonic-gate delmddb = 1;
1440Sstevel@tonic-gate if (verbose)
1450Sstevel@tonic-gate (void) printf("%s", buf);
1460Sstevel@tonic-gate continue;
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate if (delmddb) {
1490Sstevel@tonic-gate if (strcmp(buf, ENDMDDBSTR) == 0)
1500Sstevel@tonic-gate delmddb = 0;
1510Sstevel@tonic-gate if (verbose)
1520Sstevel@tonic-gate (void) printf("%s", buf);
1530Sstevel@tonic-gate continue;
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate if (doit) {
1560Sstevel@tonic-gate if (fputs(buf, *tfp) == EOF) {
1570Sstevel@tonic-gate (void) mdsyserror(ep, errno, *tname);
1580Sstevel@tonic-gate goto out;
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate if (fp != NULL) {
1630Sstevel@tonic-gate if ((! feof(fp)) ||
1640Sstevel@tonic-gate (fclose(fp) != 0)) {
1650Sstevel@tonic-gate (void) mdsyserror(ep, errno, sname);
1660Sstevel@tonic-gate goto out;
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate fp = NULL;
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate if (verbose)
1710Sstevel@tonic-gate (void) printf("\n");
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate /* make sure we didn't stop mid-delete */
1740Sstevel@tonic-gate if ((delroot) || (delmddb)) {
1750Sstevel@tonic-gate (void) mderror(ep, MDE_SYSTEM_FILE, sname);
1760Sstevel@tonic-gate goto out;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate /* flush stuff */
1800Sstevel@tonic-gate if (doit) {
1810Sstevel@tonic-gate if ((fflush(*tfp) != 0) ||
1820Sstevel@tonic-gate (fsync(fileno(*tfp)) != 0)) {
1830Sstevel@tonic-gate (void) mdsyserror(ep, errno, *tname);
1840Sstevel@tonic-gate goto out;
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /* return success */
1890Sstevel@tonic-gate return (0);
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /* cleanup, return error */
1920Sstevel@tonic-gate out:
1930Sstevel@tonic-gate if (fp != NULL)
1940Sstevel@tonic-gate (void) fclose(fp);
1950Sstevel@tonic-gate if (*tname != NULL) {
1960Sstevel@tonic-gate (void) unlink(*tname);
1970Sstevel@tonic-gate Free(*tname);
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate if (*tfp != NULL)
2000Sstevel@tonic-gate (void) fclose(*tfp);
2010Sstevel@tonic-gate return (-1);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * append root on MD lines to system
2060Sstevel@tonic-gate */
2070Sstevel@tonic-gate int
meta_systemfile_append_mdroot(mdname_t * rootnp,char * sname,char * tname,FILE * tfp,int ismeta,int doit,int verbose,md_error_t * ep)2080Sstevel@tonic-gate meta_systemfile_append_mdroot(
2090Sstevel@tonic-gate mdname_t *rootnp, /* root device name */
2100Sstevel@tonic-gate char *sname, /* system file name */
2110Sstevel@tonic-gate char *tname, /* temp file name */
2120Sstevel@tonic-gate FILE *tfp, /* temp FILE */
2130Sstevel@tonic-gate int ismeta, /* is a metadevice */
2140Sstevel@tonic-gate int doit, /* really patch file */
2150Sstevel@tonic-gate int verbose, /* show what we're doing */
2160Sstevel@tonic-gate md_error_t *ep
2170Sstevel@tonic-gate )
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate char *longblkname;
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /* check names */
2220Sstevel@tonic-gate assert(sname != NULL);
2230Sstevel@tonic-gate assert(tname != NULL);
2240Sstevel@tonic-gate assert(!doit || tfp != NULL);
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /* get root /devices name */
2270Sstevel@tonic-gate if ((longblkname = metagetdevicesname(rootnp, ep)) == NULL)
2280Sstevel@tonic-gate return (-1);
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /* add header */
2310Sstevel@tonic-gate if (verbose) {
2320Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
2330Sstevel@tonic-gate "Add the following lines to %s:\n\n"), sname);
2340Sstevel@tonic-gate (void) printf("%s", BEGROOTSTR);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate if (doit) {
2370Sstevel@tonic-gate if (fprintf(tfp, "%s", BEGROOTSTR) == EOF) {
2380Sstevel@tonic-gate return (mdsyserror(ep, errno, tname));
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate /* add rootdev */
2430Sstevel@tonic-gate if (ismeta) {
2440Sstevel@tonic-gate if (verbose)
2450Sstevel@tonic-gate (void) printf("rootdev:%s\n", longblkname);
2460Sstevel@tonic-gate if (doit) {
2470Sstevel@tonic-gate if (fprintf(tfp, "rootdev:%s\n", longblkname) == EOF) {
2480Sstevel@tonic-gate return (mdsyserror(ep, errno, tname));
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate /* add trailer */
2540Sstevel@tonic-gate if (verbose) {
2550Sstevel@tonic-gate (void) printf("%s\n", ENDROOTSTR);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate if (doit) {
2580Sstevel@tonic-gate if (fprintf(tfp, "%s", ENDROOTSTR) == EOF) {
2590Sstevel@tonic-gate return (mdsyserror(ep, errno, tname));
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /* flush stuff */
2640Sstevel@tonic-gate if (doit) {
2650Sstevel@tonic-gate if ((fflush(tfp) != 0) ||
2660Sstevel@tonic-gate (fsync(fileno(tfp)) != 0)) {
2670Sstevel@tonic-gate return (mdsyserror(ep, errno, tname));
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate /* return success */
2720Sstevel@tonic-gate return (0);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate /*
2760Sstevel@tonic-gate * parse mddb.cf line
2770Sstevel@tonic-gate *
2780Sstevel@tonic-gate * Caller of this routine needs to free the device id string that
2790Sstevel@tonic-gate * is passed back during a successful return.
2800Sstevel@tonic-gate */
2810Sstevel@tonic-gate static int
confline(char * line,char ** driver,minor_t * mnump,daddr_t * block,char ** devid_char_pp)2820Sstevel@tonic-gate confline(
2830Sstevel@tonic-gate char *line, /* line in file */
2840Sstevel@tonic-gate char **driver, /* returned driver name */
2850Sstevel@tonic-gate minor_t *mnump, /* returned minor number */
2860Sstevel@tonic-gate daddr_t *block, /* returned block offset */
2870Sstevel@tonic-gate char **devid_char_pp /* returned device id string */
2880Sstevel@tonic-gate )
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate char *p = line;
2910Sstevel@tonic-gate int chksum = 0;
2920Sstevel@tonic-gate int i;
2930Sstevel@tonic-gate uint_t devid_size;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate if (*p == '#') {
2960Sstevel@tonic-gate return (-1);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate *driver = p;
2990Sstevel@tonic-gate while ((*p != ' ') && (*p != '\t'))
3000Sstevel@tonic-gate chksum += *p++;
3010Sstevel@tonic-gate if (*driver == p) {
3020Sstevel@tonic-gate return (-1);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate *p++ = '\0';
3050Sstevel@tonic-gate *mnump = strtoul(p, &p, 10);
3060Sstevel@tonic-gate chksum += *mnump;
3070Sstevel@tonic-gate *block = strtol(p, &p, 10);
3080Sstevel@tonic-gate chksum += *block;
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate /* parse out devid */
3110Sstevel@tonic-gate while ((*p == ' ') || (*p == '\t')) {
3120Sstevel@tonic-gate p++;
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate i = strcspn(p, " \t");
3150Sstevel@tonic-gate *devid_char_pp = Malloc(i+1);
3160Sstevel@tonic-gate (void) strncpy(*devid_char_pp, p, i);
3170Sstevel@tonic-gate (*devid_char_pp)[i] = '\0';
3180Sstevel@tonic-gate devid_size = i;
3190Sstevel@tonic-gate p += devid_size;
3200Sstevel@tonic-gate for (i = 0; i < devid_size; i++) {
3210Sstevel@tonic-gate chksum += (*devid_char_pp)[i];
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate chksum += strtol(p, &p, 10);
3250Sstevel@tonic-gate if (chksum != 42) {
3260Sstevel@tonic-gate Free (*devid_char_pp);
3270Sstevel@tonic-gate devid_char_pp = NULL;
3280Sstevel@tonic-gate return (-1);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate return (0);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate * append MDDB lines to system
3350Sstevel@tonic-gate */
3360Sstevel@tonic-gate int
meta_systemfile_append_mddb(char * cname,char * sname,char * tname,FILE * tfp,int doit,int verbose,int check,md_error_t * ep)3370Sstevel@tonic-gate meta_systemfile_append_mddb(
3380Sstevel@tonic-gate char *cname, /* mddb.cf file name */
3390Sstevel@tonic-gate char *sname, /* system file name */
3400Sstevel@tonic-gate char *tname, /* temp file name */
3410Sstevel@tonic-gate FILE *tfp, /* temp FILE */
3420Sstevel@tonic-gate int doit, /* really patch file */
3430Sstevel@tonic-gate int verbose, /* show what we're doing */
344*2063Shshaw int check, /* if set check that mddb.cf is not */
345*2063Shshaw /* empty before updating md.conf */
3460Sstevel@tonic-gate md_error_t *ep /* returned error */
3470Sstevel@tonic-gate )
3480Sstevel@tonic-gate {
3490Sstevel@tonic-gate FILE *cfp = NULL;
3500Sstevel@tonic-gate char buf[1024];
3510Sstevel@tonic-gate char *p;
3520Sstevel@tonic-gate int i;
3530Sstevel@tonic-gate char *driver;
3540Sstevel@tonic-gate minor_t mnum;
3550Sstevel@tonic-gate daddr_t block;
3560Sstevel@tonic-gate char line[MDDB_BOOTLIST_MAX_LEN];
3570Sstevel@tonic-gate char entry[MDDB_BOOTLIST_MAX_LEN];
3580Sstevel@tonic-gate char *devid_char_p = NULL;
3590Sstevel@tonic-gate struct stat statbuf;
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate /* check names */
3620Sstevel@tonic-gate assert(cname != NULL);
3630Sstevel@tonic-gate assert(sname != NULL);
3640Sstevel@tonic-gate assert(tname != NULL);
3650Sstevel@tonic-gate assert(!doit || tfp != NULL);
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate /* open database conf file */
3680Sstevel@tonic-gate if ((cfp = fopen(cname, "r")) == NULL) {
3690Sstevel@tonic-gate (void) mdsyserror(ep, errno, cname);
3700Sstevel@tonic-gate goto out;
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate /* Check that it is an ordinary file */
3730Sstevel@tonic-gate if (stat(cname, &statbuf) != 0) {
3740Sstevel@tonic-gate (void) mdsyserror(ep, errno, cname);
3750Sstevel@tonic-gate goto out;
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
3780Sstevel@tonic-gate (void) mderror(ep, MDE_MDDB_FILE, cname);
3790Sstevel@tonic-gate goto out;
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate /* add header */
3830Sstevel@tonic-gate if (verbose) {
3840Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
3850Sstevel@tonic-gate "Add the following lines to %s:\n\n"), sname);
3860Sstevel@tonic-gate (void) printf("%s", BEGMDDBSTR);
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate if (doit) {
3890Sstevel@tonic-gate if (fprintf(tfp, "%s", BEGMDDBSTR) == EOF) {
3900Sstevel@tonic-gate (void) mdsyserror(ep, errno, tname);
3910Sstevel@tonic-gate goto out;
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /* append database lines */
3960Sstevel@tonic-gate while (((p = fgets(buf, sizeof (buf), cfp)) != NULL) &&
3970Sstevel@tonic-gate (confline(buf, &driver, &mnum, &block, &devid_char_p) != 0))
3980Sstevel@tonic-gate ;
399*2063Shshaw /*
400*2063Shshaw * It is possible to be in a state where the md_devid_destroy flag
401*2063Shshaw * has been set and the mdmonitor service not be enabled on reboot
402*2063Shshaw * such that metadevadm doesn't get run and the entries in mddb.cf
403*2063Shshaw * recreated. The following checks for this condition and will not
404*2063Shshaw * allow an empty mddb.cf to overwrite md.conf and lose the users
405*2063Shshaw * configuration
406*2063Shshaw */
407*2063Shshaw if (check && p == NULL) {
408*2063Shshaw (void) mderror(ep, MDE_MDDB_FILE, cname);
409*2063Shshaw goto out;
410*2063Shshaw }
411*2063Shshaw
4120Sstevel@tonic-gate for (i = 1; ((p != NULL) && (i <= MDDB_MAX_PATCH)); ++i) {
4130Sstevel@tonic-gate (void) snprintf(line, sizeof (line),
4140Sstevel@tonic-gate "mddb_bootlist%d=\"%s:%lu:%ld:%s",
4150Sstevel@tonic-gate i, driver, mnum, block, devid_char_p);
4160Sstevel@tonic-gate if (devid_char_p != NULL) {
4170Sstevel@tonic-gate free(devid_char_p);
4180Sstevel@tonic-gate devid_char_p = NULL;
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate while ((p = fgets(buf, sizeof (buf), cfp)) != NULL) {
4220Sstevel@tonic-gate if (confline(buf, &driver, &mnum, &block,
4230Sstevel@tonic-gate &devid_char_p) != 0) {
4240Sstevel@tonic-gate continue;
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate (void) snprintf(entry, sizeof (entry), " %s:%lu:%ld:%s",
4270Sstevel@tonic-gate driver, mnum, block, devid_char_p);
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate if ((strlen(line) + strlen(entry) + 4) > sizeof (line))
4300Sstevel@tonic-gate break;
4310Sstevel@tonic-gate (void) strcat(line, entry);
4320Sstevel@tonic-gate if (devid_char_p != NULL) {
4330Sstevel@tonic-gate free(devid_char_p);
4340Sstevel@tonic-gate devid_char_p = NULL;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate if (verbose)
4380Sstevel@tonic-gate /* CSTYLED */
4390Sstevel@tonic-gate (void) printf("%s\";\n", line);
4400Sstevel@tonic-gate if (doit) {
4410Sstevel@tonic-gate /* CSTYLED */
4420Sstevel@tonic-gate if (fprintf(tfp, "%s\";\n", line) <= 0) {
4430Sstevel@tonic-gate (void) mdsyserror(ep, errno, tname);
4440Sstevel@tonic-gate goto out;
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate
4490Sstevel@tonic-gate if (devid_char_p != NULL) {
4500Sstevel@tonic-gate free(devid_char_p);
4510Sstevel@tonic-gate devid_char_p = NULL;
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate /* add trailer */
4550Sstevel@tonic-gate if (verbose)
4560Sstevel@tonic-gate (void) printf("%s\n", ENDMDDBSTR);
4570Sstevel@tonic-gate if (doit) {
4580Sstevel@tonic-gate if (fprintf(tfp, "%s", ENDMDDBSTR) == EOF) {
4590Sstevel@tonic-gate (void) mdsyserror(ep, errno, tname);
4600Sstevel@tonic-gate goto out;
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate /* close database conf file */
4650Sstevel@tonic-gate if (fclose(cfp) != 0) {
4660Sstevel@tonic-gate cfp = NULL;
4670Sstevel@tonic-gate (void) mdsyserror(ep, errno, cname);
4680Sstevel@tonic-gate goto out;
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate cfp = NULL;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate /* flush stuff */
4730Sstevel@tonic-gate if (doit) {
4740Sstevel@tonic-gate if ((fflush(tfp) != 0) ||
4750Sstevel@tonic-gate (fsync(fileno(tfp)) != 0)) {
4760Sstevel@tonic-gate (void) mdsyserror(ep, errno, tname);
4770Sstevel@tonic-gate goto out;
4780Sstevel@tonic-gate }
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate /* return success */
4820Sstevel@tonic-gate return (0);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate /* cleanup, return error */
4850Sstevel@tonic-gate out:
4860Sstevel@tonic-gate if (cfp != NULL)
4870Sstevel@tonic-gate (void) fclose(cfp);
4880Sstevel@tonic-gate return (-1);
4890Sstevel@tonic-gate }
490