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