OpenSolaris_b135/lib/lvm/libmeta/common/meta_patch_root.c

/*
 * 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 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

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

/*
 * patch /etc/system file for the root device
 */

#include <dlfcn.h>
#include <meta.h>


/*
 * set root device name in md.conf and vfstab, patch in mddb locations
 */
int
meta_patch_rootdev(
	mdname_t	*rootnp,	/* root device */
	char		*sname,		/* system file name */
	char		*vname,		/* vfstab file name */
	char		*cname,		/* mddb.cf file name */
	char		*dbname,	/* md.conf file name */
	int		doit,		/* really patch files */
	int		verbose,	/* show what we're doing */
	md_error_t	*ep		/* returned error */
)
{
	mdsetname_t	*sp;
	int		ismeta = metaismeta(rootnp);
	char		*tsname = NULL;
	FILE		*tsfp = NULL;
	char		*dbtname = NULL;
	FILE		*dbtfp = NULL;
	char		*tvname = NULL;
	int		rval = -1;

	/* check names */
	if (sname == NULL)
		sname = "/etc/system";
	if (vname == NULL)
		vname = "/etc/vfstab";
	if (cname == NULL)
		cname = META_DBCONF;
	if (dbname == NULL)
		dbname = "/kernel/drv/md.conf";

	/* make sure we have a local name */
	if ((sp = metagetset(rootnp, TRUE, ep)) == NULL)
		return (-1);

	if (! metaislocalset(sp)) {
		return (mddeverror(ep, MDE_NOT_LOCAL, rootnp->dev,
		    rootnp->cname));
	}

	/* replace forceload and rootdev lines in system */
	if (meta_systemfile_copy(sname, 1, 0, doit, verbose, &tsname, &tsfp,
	    ep) != 0) {
		goto out;
	}
	if (meta_systemfile_append_mdroot(rootnp, sname,
	    tsname, tsfp, ismeta, doit, verbose, ep) != 0) {
		goto out;
	}

	/* replace bootlist lines in /kernel/drv/md.conf */
	if (meta_systemfile_copy(dbname, 0, 1, doit, verbose, &dbtname,
	    &dbtfp, ep) != 0) {
		goto out;
	}
	if (meta_systemfile_append_mddb(cname, dbname, dbtname, dbtfp, doit,
	    verbose, 1, ep) != 0) {
		goto out;
	}

	/* force the file contents out to disk */
	if (doit) {
		if ((fflush(tsfp) != 0) ||
		    (fsync(fileno(tsfp)) != 0) ||
		    (fclose(tsfp) != 0)) {
			(void) mdsyserror(ep, errno, tsname);
			goto out;
		}
		tsfp = NULL;
		if ((fflush(dbtfp) != 0) ||
		    (fsync(fileno(dbtfp)) != 0) ||
		    (fclose(dbtfp) != 0)) {
			(void) mdsyserror(ep, errno, dbtname);
			goto out;
		}
		dbtfp = NULL;
	}

	/* replace lines in vfstab */
	if (meta_patch_vfstab("/", rootnp, vname, NULL, doit, verbose, &tvname,
	    ep) != 0) {
		goto out;
	}

	/* rename files, better hope both work */
	if (doit) {
		if (rename(tsname, sname) != 0) {
			(void) mdsyserror(ep, errno, sname);
			goto out;
		}
		Free(tsname);
		tsname = NULL;
		if (rename(dbtname, dbname) != 0) {
			(void) mdsyserror(ep, errno, dbname);
			goto out;
		}
		Free(dbtname);
		dbtname = NULL;
		if (rename(tvname, vname) != 0) {
			(void) mdsyserror(ep, errno, vname);
			goto out;
		}
		Free(tvname);
		tvname = NULL;
	}
	rval = 0;

	/* cleanup, return error */
out:
	if (tsfp != NULL)
		(void) fclose(tsfp);
	if (tsname != NULL) {
		if (doit)
			(void) unlink(tsname);
		Free(tsname);
	}
	if (tvname != NULL) {
		if (doit)
			(void) unlink(tvname);
		Free(tvname);
	}

	/* free the temporary files for md.conf */
	if (dbtfp != NULL)
		(void) fclose(dbtfp);
	if (dbtname != NULL) {
		if (doit)
			(void) unlink(dbtname);
		Free(dbtname);
	}
	return (rval);
}