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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * Just in case we're not in a build environment, make sure that
31 * TEXT_DOMAIN gets set to something.
32 */
33#if !defined(TEXT_DOMAIN)
34#define	TEXT_DOMAIN "SYS_TEST"
35#endif
36
37/*
38 * patch /etc/vfstab file
39 */
40#include <meta.h>
41#include <string.h>
42
43/*
44 * patch filesystem lines into vfstab file, return tempfilename
45 */
46int
47meta_patch_vfstab(
48	char		*cmpname,	/* filesystem mount point or */
49					/* "swap" if updating swap partition */
50	mdname_t	*fsnp,		/* filesystem device name */
51	char		*vname,		/* vfstab file name */
52	char		*old_bdevname,	/* old name of block device, needed */
53					/* for deciding which of multiple   */
54					/* swap file entries to change	    */
55					/* if NULL then not changing swap   */
56	int		doit,		/* really patch file */
57	int		verbose,	/* show what we're doing */
58	char		**tname,	/* returned temp file name */
59	md_error_t	*ep		/* returned error */
60)
61{
62	char		*chrname = fsnp->rname;
63	char		*blkname = fsnp->bname;
64	FILE		*fp = NULL;
65	FILE		*tfp = NULL;
66	struct stat	sbuf;
67	char		buf[512];
68	char		cdev[512];
69	char		bdev[512];
70	char		mntpt[512];
71	char		fstype[512];
72	char		fsckpass[512];
73	char		mntboot[512];
74	char		mntopt[512];
75	int		gotfs = 0;
76	char		*cmpstr = &mntpt[0]; /* compare against mntpnt if fs, */
77						/* or fstype if swap */
78	char		*char_device = chrname;
79
80	/* check names */
81	assert(vname != NULL);
82	assert(tname != NULL);
83
84	/* get temp names */
85	*tname = NULL;
86	*tname = Malloc(strlen(vname) + strlen(".tmp") + 1);
87	(void) strcpy(*tname, vname);
88	(void) strcat(*tname, ".tmp");
89
90	/* check if going to update swap entry in file */
91	/* if so then compare against file system type */
92	if ((old_bdevname != NULL) && (strcmp("swap", cmpname) == 0)) {
93	    cmpstr = &fstype[0];
94	    char_device = &cdev[0];
95	}
96
97	/* copy vfstab file, replace filesystem line */
98	if ((fp = fopen(vname, "r")) == NULL) {
99		(void) mdsyserror(ep, errno, vname);
100		goto out;
101	}
102	if (fstat(fileno(fp), &sbuf) != 0) {
103		(void) mdsyserror(ep, errno, vname);
104		goto out;
105	}
106	if (doit) {
107		if ((tfp = fopen(*tname, "w")) == NULL) {
108			(void) mdsyserror(ep, errno, *tname);
109			goto out;
110		}
111		if (fchmod(fileno(tfp), (sbuf.st_mode & 0777)) != 0) {
112			(void) mdsyserror(ep, errno, *tname);
113			goto out;
114		}
115		if (fchown(fileno(tfp), sbuf.st_uid, sbuf.st_gid) != 0) {
116			(void) mdsyserror(ep, errno, *tname);
117			goto out;
118		}
119	}
120	while (fgets(buf, sizeof (buf), fp) != NULL) {
121
122	    /* check that have all required params from vfstab file  */
123	    /* or that the line isnt a comment	*/
124	    /* or that the fstype/mntpoint match what was passed in  */
125	    /* or that the block device matches if changing swap */
126	    /* the last check is needed since there may be multiple  */
127	    /* entries of swap in the file, and so the fstype is not */
128	    /* a sufficient check */
129		if ((sscanf(buf, "%512s %512s %512s %512s %512s %512s %512s",
130		    bdev, cdev, mntpt, fstype, fsckpass,
131		    mntboot, mntopt) != 7) ||
132		    (bdev[0] == '#') || (strcmp(cmpstr, cmpname) != 0) ||
133		    ((old_bdevname != NULL) &&
134		    (strstr(bdev, old_bdevname) == NULL))) {
135			if (doit) {
136			    if (fputs(buf, tfp) == EOF) {
137				(void) mdsyserror(ep, errno, *tname);
138				goto out;
139			    }
140			}
141			continue;
142		}
143
144		if (verbose) {
145			(void) printf(dgettext(TEXT_DOMAIN,
146			    "Delete the following line from %s:\n\n"),
147			    vname);
148			(void) printf("%s\n", buf);
149			(void) printf(
150			    dgettext(TEXT_DOMAIN,
151			    "Add the following line to %s:\n\n"),
152			    vname);
153			(void) printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n\n",
154				blkname, char_device, mntpt, fstype, fsckpass,
155				mntboot, mntopt);
156		}
157		if (doit) {
158		    if (fprintf(tfp, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
159			blkname, char_device, mntpt, fstype, fsckpass,
160			mntboot, mntopt) == EOF) {
161			(void) mdsyserror(ep, errno, *tname);
162			goto out;
163		    }
164		}
165
166
167		gotfs = 1;
168	}
169	if (! feof(fp)) {
170		(void) mdsyserror(ep, errno, vname);
171		goto out;
172	}
173	if (! gotfs) {
174		(void) mderror(ep, MDE_VFSTAB_FILE, vname);
175		goto out;
176	}
177	if (fclose(fp) != 0) {
178		(void) mdsyserror(ep, errno, vname);
179		goto out;
180	}
181	fp = NULL;
182	if (doit) {
183		if ((fflush(tfp) != 0) ||
184		    (fsync(fileno(tfp)) != 0) ||
185		    (fclose(tfp) != 0)) {
186			(void) mdsyserror(ep, errno, *tname);
187			goto out;
188		}
189		tfp = NULL;
190	}
191
192	/* return success */
193	return (0);
194
195	/* cleanup, return error */
196out:
197	if (fp != NULL)
198		(void) fclose(fp);
199	if (tfp != NULL)
200		(void) fclose(tfp);
201	if (*tname != NULL) {
202		(void) unlink(*tname);
203		Free(*tname);
204	}
205	return (-1);
206}
207
208
209/*
210 * set filesystem device name in vfstab
211 */
212int
213meta_patch_fsdev(
214	char		*fsname,	/* filesystem mount point */
215	mdname_t	*fsnp,		/* filesystem device */
216	char		*vname,		/* vfstab file name */
217	md_error_t	*ep		/* returned error */
218)
219{
220	int		doit = 1;
221	int		verbose = 0;
222	char		*tvname = NULL;
223	int		rval = -1;
224
225	/* check names */
226	assert(fsname != NULL);
227	if (vname == NULL)
228		vname = "/etc/vfstab";
229
230	/* replace lines in vfstab */
231	if (meta_patch_vfstab(fsname, fsnp, vname, NULL, doit, verbose, &tvname,
232	    ep) != 0) {
233		goto out;
234	}
235
236	/* rename temp file on top of real one */
237	if (rename(tvname, vname) != 0) {
238		(void) mdsyserror(ep, errno, vname);
239		goto out;
240	}
241	Free(tvname);
242	tvname = NULL;
243	rval = 0;
244
245	/* cleanup, return error */
246out:
247	if (tvname != NULL) {
248		if (doit)
249			(void) unlink(tvname);
250		Free(tvname);
251	}
252	return (rval);
253}
254
255
256/*
257 * set filesystem device name in vfstab
258 */
259int
260meta_patch_swapdev(
261	mdname_t	*fsnp,		 /* filesystem device */
262	char		*vname,		 /* vfstab file name */
263	char		*old_bdevname,	 /* block device name to change */
264	md_error_t	*ep		 /* returned error */
265)
266{
267	int		doit = 1;
268	int		verbose = 0;
269	char		*tvname = NULL;
270	int		rval = -1;
271
272	/* check names */
273	if (vname == NULL)
274		vname = "/etc/vfstab";
275
276	/* replace lines in vfstab */
277	if (meta_patch_vfstab("swap", fsnp, vname, old_bdevname, doit,
278	    verbose, &tvname, ep) != 0) {
279		goto out;
280	}
281
282	/* rename temp file on top of real one */
283	if (rename(tvname, vname) != 0) {
284		(void) mdsyserror(ep, errno, vname);
285		goto out;
286	}
287	Free(tvname);
288	tvname = NULL;
289	rval = 0;
290
291	/* cleanup, return error */
292out:
293	if (tvname != NULL) {
294		if (doit)
295			(void) unlink(tvname);
296		Free(tvname);
297	}
298	return (rval);
299}
300