xref: /titanic_41/usr/src/lib/lvm/libmeta/common/meta_patch.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
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  */
46 int
47 meta_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 */
196 out:
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  */
212 int
213 meta_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 */
246 out:
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  */
259 int
260 meta_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 */
292 out:
293 	if (tvname != NULL) {
294 		if (doit)
295 			(void) unlink(tvname);
296 		Free(tvname);
297 	}
298 	return (rval);
299 }
300