xref: /illumos-gate/usr/src/cmd/fs.d/ufs/labelit/labelit.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*
43  * Label a file system volume.
44  */
45 
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <sys/param.h>
51 #include <sys/types.h>
52 #include <sys/mntent.h>
53 #include <locale.h>
54 
55 #define	bcopy(f, t, n)    (void) memcpy(t, f, n)
56 #define	bzero(s, n)	memset(s, 0, n)
57 #define	bcmp(s, d, n)	memcmp(s, d, n)
58 
59 #define	index(s, r)	strchr(s, r)
60 #define	rindex(s, r)	strrchr(s, r)
61 
62 #include <sys/vnode.h>
63 #include <fcntl.h>
64 #include <sys/fs/ufs_inode.h>
65 #include <sys/fs/ufs_fs.h>
66 
67 static void usage();
68 static void label();
69 
70 static union sbtag {
71 	char		dummy[SBSIZE];
72 	struct fs	sblk;
73 } sb_un, altsb_un;
74 
75 #define	sblock sb_un.sblk
76 #define	altsblock altsb_un.sblk
77 
78 extern int	optind;
79 extern char	*optarg;
80 
81 void
82 main(argc, argv)
83 	int	argc;
84 	char	*argv[];
85 {
86 	int		opt;
87 	char		*special = NULL;
88 	char		*fsname = NULL;
89 	char		*volume = NULL;
90 
91 	while ((opt = getopt(argc, argv, "o:")) != EOF) {
92 		switch (opt) {
93 
94 		case 'o':	/* specific options (none defined yet) */
95 			break;
96 
97 		case '?':
98 			usage();
99 		}
100 	}
101 	if (optind > (argc - 1)) {
102 		usage();
103 	}
104 	argc -= optind;
105 	argv = &argv[optind];
106 	special = argv[0];
107 	if (argc > 1) {
108 		fsname = argv[1];
109 		if (strlen(fsname) > 6) {
110 			(void) fprintf(stderr, gettext("labelit: "));
111 			(void) fprintf(stderr,
112 		gettext("fsname can not be longer than 6 characters\n"));
113 			exit(31+1);
114 		}
115 	}
116 	if (argc > 2) {
117 		volume = argv[2];
118 		if (strlen(volume) > 6) {
119 			(void) fprintf(stderr, gettext("labelit: "));
120 			(void) fprintf(stderr,
121 		gettext("volume can not be longer than 6 characters\n"));
122 			exit(31+1);
123 		}
124 	}
125 	label(special, fsname, volume);
126 	exit(0);
127 }
128 
129 void
130 usage()
131 {
132 
133 	(void) fprintf(stderr, gettext(
134 	"ufs usage: labelit [-F ufs] [gen opts] special [fsname volume]\n"));
135 	exit(31+1);
136 }
137 
138 void
139 label(special, fsname, volume)
140 	char		*special;
141 	char		*fsname;
142 	char		*volume;
143 {
144 	int	f;
145 	int	blk;
146 	int	i;
147 	char	*p;
148 	offset_t offset;
149 	struct	fs	*fsp, *altfsp;
150 
151 	if (fsname == NULL) {
152 		f = open64(special, O_RDONLY);
153 	} else {
154 		f = open64(special, O_RDWR);
155 	}
156 	if (f < 0) {
157 		(void) fprintf(stderr, gettext("labelit: "));
158 		perror("open");
159 		exit(31+1);
160 	}
161 	if (llseek(f, (offset_t)SBLOCK * DEV_BSIZE, 0) < 0) {
162 		(void) fprintf(stderr, gettext("labelit: "));
163 		perror("llseek");
164 		exit(31+1);
165 	}
166 	if (read(f, &sblock, SBSIZE) != SBSIZE) {
167 		(void) fprintf(stderr, gettext("labelit: "));
168 		perror("read");
169 		exit(31+1);
170 	}
171 	if ((sblock.fs_magic != FS_MAGIC) &&
172 	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
173 		(void) fprintf(stderr, gettext("labelit: "));
174 		(void) fprintf(stderr,
175 			gettext("bad super block magic number\n"));
176 		exit(31+1);
177 	}
178 	if ((sblock.fs_magic == FS_MAGIC) &&
179 	    ((sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2) &&
180 	    (sblock.fs_version != UFS_VERSION_MIN))) {
181 		(void) fprintf(stderr, gettext("labelit: "));
182 		(void) fprintf(stderr,
183 			gettext("unrecognized UFS format version: %d\n"),
184 			    sblock.fs_version);
185 		exit(31+1);
186 	}
187 	if ((sblock.fs_magic == MTB_UFS_MAGIC) &&
188 	    ((sblock.fs_version > MTB_UFS_VERSION_1) ||
189 	    (sblock.fs_version < MTB_UFS_VERSION_MIN))) {
190 		(void) fprintf(stderr, gettext("labelit: "));
191 		(void) fprintf(stderr,
192 			gettext("unrecognized UFS format version: %d\n"),
193 			    sblock.fs_version);
194 		exit(31+1);
195 	}
196 	fsp = &sblock;
197 
198 	/*
199 	 * Is block layout available?
200 	 */
201 
202 	if (sblock.fs_cpc <= 0 && (fsname || volume)) {
203 		(void) fprintf(stderr, gettext("labelit: "));
204 		(void) fprintf(stderr,
205 	gettext("insufficient superblock space for file system label\n"));
206 		return;
207 	}
208 
209 	/*
210 	 * calculate the available blocks for each rotational position
211 	 */
212 	blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock);
213 	for (i = 0; i < blk; i += sblock.fs_frag)
214 		/* void */;
215 	i -= sblock.fs_frag;
216 	blk = i / sblock.fs_frag;
217 	p = (char *)&(fs_rotbl(fsp)[blk]);
218 
219 	if (fsname != NULL) {
220 		for (i = 0; i < 14; i++)
221 			p[i] = '\0';
222 		for (i = 0; (i < 6) && (fsname[i]); i++, p++)
223 			*p = fsname[i];
224 		p++;
225 	}
226 	if (volume != NULL) {
227 		for (i = 0; (i < 6) && (volume[i]); i++, p++)
228 			*p = volume[i];
229 	}
230 	if (fsname != NULL) {
231 		if (llseek(f, (offset_t)SBLOCK * DEV_BSIZE, 0) < 0) {
232 			(void) fprintf(stderr, gettext("labelit: "));
233 			perror("llseek");
234 			exit(31+1);
235 		}
236 		if (write(f, &sblock, SBSIZE) != SBSIZE) {
237 			(void) fprintf(stderr, gettext("labelit: "));
238 			perror("write");
239 			exit(31+1);
240 		}
241 		for (i = 0; i < sblock.fs_ncg; i++) {
242 			/*
243 			 * In the case of multi-terabyte ufs file
244 			 * systems, only the first ten and last ten
245 			 * cylinder groups have copies of the superblock.
246 			 */
247 			if (sblock.fs_magic == MTB_UFS_MAGIC &&
248 			    sblock.fs_ncg > 20 &&
249 			    (i >= 10 && i < sblock.fs_ncg - 10))
250 				continue;
251 			offset =
252 			    (offset_t)cgsblock(&sblock, i) * sblock.fs_fsize;
253 			if (llseek(f, offset, 0) < 0) {
254 				(void) fprintf(stderr, gettext("labelit: "));
255 				perror("lseek");
256 				exit(31+1);
257 			}
258 			altfsp = &altsblock;
259 			if (read(f, &altsblock, SBSIZE) != SBSIZE) {
260 				(void) fprintf(stderr, gettext("labelit: "));
261 				perror("read");
262 				exit(31+1);
263 			}
264 			if ((altsblock.fs_magic != FS_MAGIC) &&
265 			    (altsblock.fs_magic != MTB_UFS_MAGIC)) {
266 			    (void) fprintf(stderr, gettext("labelit: "));
267 			    (void) fprintf(stderr,
268 		gettext("bad alternate super block(%i) magic number\n"), i);
269 				exit(31+1);
270 			}
271 			if ((altsblock.fs_magic == FS_MAGIC) &&
272 			    ((altsblock.fs_version !=
273 				UFS_EFISTYLE4NONEFI_VERSION_2) &&
274 			    (altsblock.fs_version != UFS_VERSION_MIN))) {
275 				(void) fprintf(stderr, gettext("labelit: "));
276 				(void) fprintf(stderr,
277 		gettext("bad alternate super block UFS format version: %d\n"),
278 					    altsblock.fs_version);
279 				exit(31+1);
280 			}
281 			if ((altsblock.fs_magic == MTB_UFS_MAGIC) &&
282 			    ((altsblock.fs_version > MTB_UFS_VERSION_1) ||
283 			    (altsblock.fs_version < MTB_UFS_VERSION_MIN))) {
284 				(void) fprintf(stderr, gettext("labelit: "));
285 				(void) fprintf(stderr,
286 		gettext("bad alternate super block UFS format version: %d\n"),
287 					    altsblock.fs_version);
288 				exit(31+1);
289 			}
290 			bcopy((char *)&(fs_rotbl(fsp)[blk]),
291 				(char *)&(fs_rotbl(altfsp)[blk]), 14);
292 
293 			if (llseek(f, offset, 0) < 0) {
294 				(void) fprintf(stderr, gettext("labelit: "));
295 				perror("llseek");
296 			exit(31+1);
297 			}
298 			if (write(f, &altsblock, SBSIZE) != SBSIZE) {
299 				(void) fprintf(stderr, gettext("labelit: "));
300 				perror("write");
301 				exit(31+1);
302 			}
303 		}
304 	}
305 	p = (char *)&(fs_rotbl(fsp)[blk]);
306 	(void) fprintf(stderr, gettext("fsname: "));
307 	for (i = 0; (i < 6) && (*p); i++, p++) {
308 		(void) fprintf(stderr, "%c", *p);
309 	}
310 	(void) fprintf(stderr, "\n");
311 	(void) fprintf(stderr, gettext("volume: "));
312 	p++;
313 	for (i = 0; (i < 6); i++, p++) {
314 		(void) fprintf(stderr, "%c", *p);
315 	}
316 	(void) fprintf(stderr, "\n");
317 }
318