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 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*
29 * patch /etc/system file for the root device
30 */
31
32#include <dlfcn.h>
33#include <meta.h>
34
35
36/*
37 * set root device name in md.conf and vfstab, patch in mddb locations
38 */
39int
40meta_patch_rootdev(
41	mdname_t	*rootnp,	/* root device */
42	char		*sname,		/* system file name */
43	char		*vname,		/* vfstab file name */
44	char		*cname,		/* mddb.cf file name */
45	char		*dbname,	/* md.conf file name */
46	int		doit,		/* really patch files */
47	int		verbose,	/* show what we're doing */
48	md_error_t	*ep		/* returned error */
49)
50{
51	mdsetname_t	*sp;
52	int		ismeta = metaismeta(rootnp);
53	char		*tsname = NULL;
54	FILE		*tsfp = NULL;
55	char		*dbtname = NULL;
56	FILE		*dbtfp = NULL;
57	char		*tvname = NULL;
58	int		rval = -1;
59
60	/* check names */
61	if (sname == NULL)
62		sname = "/etc/system";
63	if (vname == NULL)
64		vname = "/etc/vfstab";
65	if (cname == NULL)
66		cname = META_DBCONF;
67	if (dbname == NULL)
68		dbname = "/kernel/drv/md.conf";
69
70	/* make sure we have a local name */
71	if ((sp = metagetset(rootnp, TRUE, ep)) == NULL)
72		return (-1);
73
74	if (! metaislocalset(sp)) {
75		return (mddeverror(ep, MDE_NOT_LOCAL, rootnp->dev,
76		    rootnp->cname));
77	}
78
79	/* replace forceload and rootdev lines in system */
80	if (meta_systemfile_copy(sname, 1, 0, doit, verbose, &tsname, &tsfp,
81	    ep) != 0) {
82		goto out;
83	}
84	if (meta_systemfile_append_mdroot(rootnp, sname,
85	    tsname, tsfp, ismeta, doit, verbose, ep) != 0) {
86		goto out;
87	}
88
89	/* replace bootlist lines in /kernel/drv/md.conf */
90	if (meta_systemfile_copy(dbname, 0, 1, doit, verbose, &dbtname,
91	    &dbtfp, ep) != 0) {
92		goto out;
93	}
94	if (meta_systemfile_append_mddb(cname, dbname, dbtname, dbtfp, doit,
95	    verbose, 1, ep) != 0) {
96		goto out;
97	}
98
99	/* force the file contents out to disk */
100	if (doit) {
101		if ((fflush(tsfp) != 0) ||
102		    (fsync(fileno(tsfp)) != 0) ||
103		    (fclose(tsfp) != 0)) {
104			(void) mdsyserror(ep, errno, tsname);
105			goto out;
106		}
107		tsfp = NULL;
108		if ((fflush(dbtfp) != 0) ||
109		    (fsync(fileno(dbtfp)) != 0) ||
110		    (fclose(dbtfp) != 0)) {
111			(void) mdsyserror(ep, errno, dbtname);
112			goto out;
113		}
114		dbtfp = NULL;
115	}
116
117	/* replace lines in vfstab */
118	if (meta_patch_vfstab("/", rootnp, vname, NULL, doit, verbose, &tvname,
119	    ep) != 0) {
120		goto out;
121	}
122
123	/* rename files, better hope both work */
124	if (doit) {
125		if (rename(tsname, sname) != 0) {
126			(void) mdsyserror(ep, errno, sname);
127			goto out;
128		}
129		Free(tsname);
130		tsname = NULL;
131		if (rename(dbtname, dbname) != 0) {
132			(void) mdsyserror(ep, errno, dbname);
133			goto out;
134		}
135		Free(dbtname);
136		dbtname = NULL;
137		if (rename(tvname, vname) != 0) {
138			(void) mdsyserror(ep, errno, vname);
139			goto out;
140		}
141		Free(tvname);
142		tvname = NULL;
143	}
144	rval = 0;
145
146	/* cleanup, return error */
147out:
148	if (tsfp != NULL)
149		(void) fclose(tsfp);
150	if (tsname != NULL) {
151		if (doit)
152			(void) unlink(tsname);
153		Free(tsname);
154	}
155	if (tvname != NULL) {
156		if (doit)
157			(void) unlink(tvname);
158		Free(tvname);
159	}
160
161	/* free the temporary files for md.conf */
162	if (dbtfp != NULL)
163		(void) fclose(dbtfp);
164	if (dbtname != NULL) {
165		if (doit)
166			(void) unlink(dbtname);
167		Free(dbtname);
168	}
169	return (rval);
170}
171