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