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