xref: /titanic_51/usr/src/cmd/fs.d/ufs/labelit/labelit.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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 /*	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 == MTB_UFS_MAGIC) &&
179 	    ((sblock.fs_version > MTB_UFS_VERSION_1) ||
180 	    (sblock.fs_version < MTB_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 	fsp = &sblock;
188 
189 	/*
190 	 * Is block layout available?
191 	 */
192 
193 	if (sblock.fs_cpc <= 0 && (fsname || volume)) {
194 		(void) fprintf(stderr, gettext("labelit: "));
195 		(void) fprintf(stderr,
196 	gettext("insufficient superblock space for file system label\n"));
197 		return;
198 	}
199 
200 	/*
201 	 * calculate the available blocks for each rotational position
202 	 */
203 	blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock);
204 	for (i = 0; i < blk; i += sblock.fs_frag)
205 		/* void */;
206 	i -= sblock.fs_frag;
207 	blk = i / sblock.fs_frag;
208 	p = (char *)&(fs_rotbl(fsp)[blk]);
209 
210 	if (fsname != NULL) {
211 		for (i = 0; i < 14; i++)
212 			p[i] = '\0';
213 		for (i = 0; (i < 6) && (fsname[i]); i++, p++)
214 			*p = fsname[i];
215 		p++;
216 	}
217 	if (volume != NULL) {
218 		for (i = 0; (i < 6) && (volume[i]); i++, p++)
219 			*p = volume[i];
220 	}
221 	if (fsname != NULL) {
222 		if (llseek(f, (offset_t)SBLOCK * DEV_BSIZE, 0) < 0) {
223 			(void) fprintf(stderr, gettext("labelit: "));
224 			perror("llseek");
225 			exit(31+1);
226 		}
227 		if (write(f, &sblock, SBSIZE) != SBSIZE) {
228 			(void) fprintf(stderr, gettext("labelit: "));
229 			perror("write");
230 			exit(31+1);
231 		}
232 		for (i = 0; i < sblock.fs_ncg; i++) {
233 			/*
234 			 * In the case of multi-terabyte ufs file
235 			 * systems, only the first ten and last ten
236 			 * cylinder groups have copies of the superblock.
237 			 */
238 			if (sblock.fs_magic == MTB_UFS_MAGIC &&
239 			    sblock.fs_ncg > 20 &&
240 			    (i >= 10 && i < sblock.fs_ncg - 10))
241 				continue;
242 			offset =
243 			    (offset_t)cgsblock(&sblock, i) * sblock.fs_fsize;
244 			if (llseek(f, offset, 0) < 0) {
245 				(void) fprintf(stderr, gettext("labelit: "));
246 				perror("lseek");
247 				exit(31+1);
248 			}
249 			altfsp = &altsblock;
250 			if (read(f, &altsblock, SBSIZE) != SBSIZE) {
251 				(void) fprintf(stderr, gettext("labelit: "));
252 				perror("read");
253 				exit(31+1);
254 			}
255 			if ((altsblock.fs_magic != FS_MAGIC) &&
256 			    (altsblock.fs_magic != MTB_UFS_MAGIC)) {
257 			    (void) fprintf(stderr, gettext("labelit: "));
258 			    (void) fprintf(stderr,
259 		gettext("bad alternate super block(%i) magic number\n"), i);
260 				exit(31+1);
261 			}
262 			if ((altsblock.fs_magic == MTB_UFS_MAGIC) &&
263 			    ((altsblock.fs_version > MTB_UFS_VERSION_1) ||
264 			    (altsblock.fs_version < MTB_UFS_VERSION_MIN))) {
265 				(void) fprintf(stderr, gettext("labelit: "));
266 				(void) fprintf(stderr,
267 		gettext("bad alternate super block UFS format version: %d\n"),
268 					    altsblock.fs_version);
269 				exit(31+1);
270 			}
271 			bcopy((char *)&(fs_rotbl(fsp)[blk]),
272 				(char *)&(fs_rotbl(altfsp)[blk]), 14);
273 
274 			if (llseek(f, offset, 0) < 0) {
275 				(void) fprintf(stderr, gettext("labelit: "));
276 				perror("llseek");
277 			exit(31+1);
278 			}
279 			if (write(f, &altsblock, SBSIZE) != SBSIZE) {
280 				(void) fprintf(stderr, gettext("labelit: "));
281 				perror("write");
282 				exit(31+1);
283 			}
284 		}
285 	}
286 	p = (char *)&(fs_rotbl(fsp)[blk]);
287 	(void) fprintf(stderr, gettext("fsname: "));
288 	for (i = 0; (i < 6) && (*p); i++, p++) {
289 		(void) fprintf(stderr, "%c", *p);
290 	}
291 	(void) fprintf(stderr, "\n");
292 	(void) fprintf(stderr, gettext("volume: "));
293 	p++;
294 	for (i = 0; (i < 6); i++, p++) {
295 		(void) fprintf(stderr, "%c", *p);
296 	}
297 	(void) fprintf(stderr, "\n");
298 }
299