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