OpenSolaris_b135/lib/lvm/libsvm/common/update_mdconf.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <devid.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <meta.h>
#include <libsvm.h>
#include <svm.h>

/*
 * magic strings in system
 */
#define	BEGMDDBSTR	"* Begin MDD database info (do not edit)\n"
#define	ENDMDDBSTR	"* End MDD database info (do not edit)\n"
#define	NEW_BEGMDDBSTR	"# Begin MDD database info (do not edit)\n"
#define	NEW_ENDMDDBSTR	"# End MDD database info (do not edit)\n"

#define	MDDBBOOTLIST	"mddb_bootlist"

#define	SYS_COMMENTCHAR	'*'
#define	CONF_COMMENTCHAR '#'

typedef struct {
	char *prop_name;
	int  prop_val;
} md_prop_t;

typedef enum {
	MDDB_SYS_FILE,
	MDDB_MDCONF_FILE
} ftype_t;

static md_prop_t upgrade_props[] = {
		{ PROP_KEEP_REPL_STATE, 0 },
		{ PROP_DEVID_DESTROY, 0},
		{ NULL, 0}
};

/*
 * The following functions manage upgrade properties
 */

void
set_upgrade_prop(char *prop_name, int val)
{
	md_prop_t *upp;

	upp = &upgrade_props[0];

	for (; upp->prop_name != NULL; upp++) {
		if (strcmp(upp->prop_name, prop_name) == 0) {
			upp->prop_val = val;
			return;
		}
	}
}

int
is_upgrade_prop(char *prop_name)
{
	md_prop_t *upp;

	upp = &upgrade_props[0];

	for (; upp->prop_name != NULL; upp++) {
		if (strcmp(upp->prop_name, prop_name) == 0) {
			return (upp->prop_val == 1);
		}
	}
	return (0);
}

int
create_in_file_prop(char *prop_name, char *fname)
{
	FILE *fp;
	md_prop_t *upp;
	int rval = RET_ERROR;

	if ((fp = fopen(fname, "a")) == NULL) {
		return (errno);
	}

	upp = &upgrade_props[0];

	for (; upp->prop_name != NULL; upp++) {
		if (strcmp(upp->prop_name, prop_name) == 0) {
			(void) fprintf(fp, "%s = 1;\n", upp->prop_name);
			rval = RET_SUCCESS;
			break;
		}
	}
	(void) fclose(fp);
	return (rval);
}

static int
is_devid_added(char *str)
{
	int cnt = 0;
	char *cp;

	/* there are exactly 3 colons in the string for devid */
	for (cnt = 0; cnt < 4; cnt++) {
		if ((cp = strchr(str, ':')) == NULL)
			break;
		str = ++cp;
	}
	return (cnt == 3);
}

/*
 * FUNCTION: parse_bootlist
 *	Parse the bootlist and add the extra field to mddb_boolist entry to
 *	conform to devid changes.
 *
 * Old format: <drivername>:<minor_number>:<offset>
 * New format: <drivername>:<minor_number>:<offset>:<devid>
 * Devid of id0 implies no device id.
 *
 * INPUT: *line - contains the mddb_bootlist
 *	  *tfp - File pointer to the md.conf.tmp file.
 *
 * RETURN:
 *	  0	- Success
 *	  > 0	- Failure. Errno returned
 */

static int
parse_bootlist(char *line, FILE *tfp)
{
	char output[1024];
	char *cp;
	int retval = RET_SUCCESS;

	(void) memset(output, 0, sizeof (output));

	if (line[0] == SYS_COMMENTCHAR) {
		output[0] = CONF_COMMENTCHAR;
	}
	/* move the line start of mddbbootlist */
	cp = strstr(line, MDDBBOOTLIST);
	if (cp != NULL)
		line = cp;

	/* grab the "mddb_boolist" word */
	cp = strtok(line, "= ");
	(void) strcat(output, cp);
	(void) strcat(output, "=\042"); /* add back the EQUAL and QUOTE chars */

	/*
	 * The line passed in is for example,
	 * mddb_bootlist1="sd:7:16:id1,sd@SIBM_DDRS34560SUN4.2G2N9688_____/h";
	 * At this point mddb_bootlist and "=" have been parsed out.
	 * The remaining string consists of driver name, colon separator and
	 * the device id(if it exists) within quotes.
	 * The deviceid string can contain upper and lower letters, digits
	 * and +-.=_~. Quotes, spaces and \n and \t are not
	 * allowed. They are converted to either _ or their ascii value.
	 * So using space,\n,;and quotes as a separator is safe.
	 */

	while ((cp = strtok(NULL, " \n\042;")) != NULL) {
		(void) strcat(output, cp);
		if (!is_devid_added(cp)) {
			/* append :id0 for devid */
			(void) strcat(strcat(output, ":"),
						devid_str_encode(NULL, NULL));

			/* no devid => SDS->SLVM migration. Set the flag */
			set_upgrade_prop(PROP_DEVID_DESTROY, 1);
		}
		(void) strcat(output, " "); /* leave space between entries */
	}

	/* remove the extra space at the end */
	output[strlen(output) - 1] = 0;
	(void) strcat(output, "\042;\n");
	if (fprintf(tfp, "%s", output) < 0) {
		retval = errno;
	}
	return (retval);
}

/*
 * FUNCTION: snarf_n_modify_bootlist
 *  This function stuffs the mddb_bootlist from either etc/system
 * or kernel/drv/md.conf of the target system into a temporary file tname.
 * The boolist in the temporary file is in device ID format.
 *
 * INPUT: *fp - file pointer that contains the mddb_bootlist.
 *	  *tname - file into which the modified bootlist will be written to.
 *	  * buf - buffer handed by upper level routine for reading in contents.
 *	  * bufsiz - size of the buffer.
 *	  mddb_file - flag
 *
 * RETURN:
 *	0	- Success
 *	> 0	- Failure. Errno returned.
 */

static int
snarf_n_modify_bootlist(
	FILE *fp,	/* File pointer to snarf from */
	char *tname,	/* name of the temporary file */
	char *buf,	/* Buffer to read into */
	int bufsz,	/* buffer size */
	ftype_t mddb_file /* flag to indicate if its /etc/system or md.conf */
)
{
	FILE *tfp;
	int rval = RET_SUCCESS;
	char *fname = SYSTEM_FILE;
	char *mddb_start = BEGMDDBSTR;
	char *mddb_end = ENDMDDBSTR;
	convflag_t cstatus = MD_STR_NOTFOUND;

	if (mddb_file == MDDB_MDCONF_FILE) {
		fname = MD_CONF;
		mddb_start = NEW_BEGMDDBSTR;
		mddb_end = NEW_ENDMDDBSTR;
	}

	if ((tfp = fopen(tname, "a")) == NULL)
		return (errno);
	debug_printf("Convert from %s\n", fname);

	rewind(fp);
	while (fgets(buf, bufsz, fp) != NULL) {
		if (strcmp(buf, mddb_start) == 0) {
			cstatus = MD_STR_START;
			if (fprintf(tfp, "%s", NEW_BEGMDDBSTR) < 0) {
				rval = errno;
				break;
			}
			continue;
		}
		if (cstatus == MD_STR_START) {
			if (strcmp(buf, mddb_end) == 0) {
				cstatus = MD_STR_DONE;
				if (fprintf(tfp, "%s", NEW_ENDMDDBSTR) < 0) {
					rval = errno;
					break;
				}

				if (mddb_file == MDDB_MDCONF_FILE)
					continue;
				else
					break;
			}

			rval = parse_bootlist(buf, tfp);
			if (rval == RET_SUCCESS)
				continue;
			else
				break;
		}
		if (mddb_file == MDDB_MDCONF_FILE) {
			if (fprintf(tfp, "%s\n", buf) < 0) {
				rval = errno;
				break;
			}
		}

	} /* while (fgets */

	if (cstatus == MD_STR_NOTFOUND || cstatus == MD_STR_START)
		rval = RET_ERROR;
	(void) fclose(tfp);
	return (rval);
}


/*
 * FUNCTION: convert_bootlist
 * Get the bootlist from $ROOT/etc/system and add modified bootlist to
 * md.conf.
 * The function converts the mddb_boolist format from that in /etc/system
 * to md.conf. Also new fields are added to handle the devid id format.
 * A copy of md.conf is created and the new entries are added to it.
 * The name of the new file is returned to the calling program.
 *
 * Input: system file name
 *	  md.conf file name
 *	  pointer to  temp file name.
 * RETURN:
 *	 *tname - name of the file that has md.conf + new mddb_boolist entries
 *	 0	- success
 *	 -1	- mddb_bootlist not found
 *	 > 0	- errno
 *
 */

int
convert_bootlist(
	char 	*sname, /* system file name */
	char	*mdconf, /* md.conf file name */
	char 	**tname /* temp file name */
)
{
	FILE	*fp;
	char	cmd_buf[MDDB_BOOTLIST_MAX_LEN];
	int	retval = RET_SUCCESS;

	/* check names */
	assert(sname != NULL);
	assert(tname != NULL);

	/* get temp name */
	*tname = tmpnam(NULL);

	if ((fp = fopen(sname, "r")) == NULL) {
		retval = errno;
		goto out;
	}
	if (valid_bootlist(fp, MDDB_BOOTLIST_MAX_LEN) == RET_SUCCESS) {
		if ((retval = copyfile(mdconf, *tname)) == RET_ERROR) {
			debug_printf("convert_bootlist: copy %s %s failed\n",
				mdconf, *tname);
			goto out;
		}
		retval = snarf_n_modify_bootlist(fp, *tname, cmd_buf,
				MDDB_BOOTLIST_MAX_LEN, MDDB_SYS_FILE);
	} else {
		(void) fclose(fp); /* close system file */
		if ((fp = fopen(mdconf, "r")) == NULL) {
			retval = errno;
			goto out;
		}
		if (valid_bootlist(fp, MDDB_BOOTLIST_MAX_LEN) == RET_ERROR) {
			retval = RET_ERROR;
			goto out;
		}
		retval = snarf_n_modify_bootlist(fp, *tname, cmd_buf,
			MDDB_BOOTLIST_MAX_LEN, MDDB_MDCONF_FILE);
	}
out:
	debug_printf("convert_bootlist: retval %d\n", retval);
	if (fp != NULL)
		(void) fclose(fp);

	if ((retval != RET_SUCCESS) && (*tname != NULL)) {
		(void) unlink(*tname);
		free(*tname);
	}
	return (retval);
}