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 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 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 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