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 2003 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 == MTB_UFS_MAGIC) && 179 ((sblock.fs_version > MTB_UFS_VERSION_1) || 180 (sblock.fs_version < MTB_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 fsp = &sblock; 188 189 /* 190 * Is block layout available? 191 */ 192 193 if (sblock.fs_cpc <= 0 && (fsname || volume)) { 194 (void) fprintf(stderr, gettext("labelit: ")); 195 (void) fprintf(stderr, 196 gettext("insufficient superblock space for file system label\n")); 197 return; 198 } 199 200 /* 201 * calculate the available blocks for each rotational position 202 */ 203 blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock); 204 for (i = 0; i < blk; i += sblock.fs_frag) 205 /* void */; 206 i -= sblock.fs_frag; 207 blk = i / sblock.fs_frag; 208 p = (char *)&(fs_rotbl(fsp)[blk]); 209 210 if (fsname != NULL) { 211 for (i = 0; i < 14; i++) 212 p[i] = '\0'; 213 for (i = 0; (i < 6) && (fsname[i]); i++, p++) 214 *p = fsname[i]; 215 p++; 216 } 217 if (volume != NULL) { 218 for (i = 0; (i < 6) && (volume[i]); i++, p++) 219 *p = volume[i]; 220 } 221 if (fsname != NULL) { 222 if (llseek(f, (offset_t)SBLOCK * DEV_BSIZE, 0) < 0) { 223 (void) fprintf(stderr, gettext("labelit: ")); 224 perror("llseek"); 225 exit(31+1); 226 } 227 if (write(f, &sblock, SBSIZE) != SBSIZE) { 228 (void) fprintf(stderr, gettext("labelit: ")); 229 perror("write"); 230 exit(31+1); 231 } 232 for (i = 0; i < sblock.fs_ncg; i++) { 233 /* 234 * In the case of multi-terabyte ufs file 235 * systems, only the first ten and last ten 236 * cylinder groups have copies of the superblock. 237 */ 238 if (sblock.fs_magic == MTB_UFS_MAGIC && 239 sblock.fs_ncg > 20 && 240 (i >= 10 && i < sblock.fs_ncg - 10)) 241 continue; 242 offset = 243 (offset_t)cgsblock(&sblock, i) * sblock.fs_fsize; 244 if (llseek(f, offset, 0) < 0) { 245 (void) fprintf(stderr, gettext("labelit: ")); 246 perror("lseek"); 247 exit(31+1); 248 } 249 altfsp = &altsblock; 250 if (read(f, &altsblock, SBSIZE) != SBSIZE) { 251 (void) fprintf(stderr, gettext("labelit: ")); 252 perror("read"); 253 exit(31+1); 254 } 255 if ((altsblock.fs_magic != FS_MAGIC) && 256 (altsblock.fs_magic != MTB_UFS_MAGIC)) { 257 (void) fprintf(stderr, gettext("labelit: ")); 258 (void) fprintf(stderr, 259 gettext("bad alternate super block(%i) magic number\n"), i); 260 exit(31+1); 261 } 262 if ((altsblock.fs_magic == MTB_UFS_MAGIC) && 263 ((altsblock.fs_version > MTB_UFS_VERSION_1) || 264 (altsblock.fs_version < MTB_UFS_VERSION_MIN))) { 265 (void) fprintf(stderr, gettext("labelit: ")); 266 (void) fprintf(stderr, 267 gettext("bad alternate super block UFS format version: %d\n"), 268 altsblock.fs_version); 269 exit(31+1); 270 } 271 bcopy((char *)&(fs_rotbl(fsp)[blk]), 272 (char *)&(fs_rotbl(altfsp)[blk]), 14); 273 274 if (llseek(f, offset, 0) < 0) { 275 (void) fprintf(stderr, gettext("labelit: ")); 276 perror("llseek"); 277 exit(31+1); 278 } 279 if (write(f, &altsblock, SBSIZE) != SBSIZE) { 280 (void) fprintf(stderr, gettext("labelit: ")); 281 perror("write"); 282 exit(31+1); 283 } 284 } 285 } 286 p = (char *)&(fs_rotbl(fsp)[blk]); 287 (void) fprintf(stderr, gettext("fsname: ")); 288 for (i = 0; (i < 6) && (*p); i++, p++) { 289 (void) fprintf(stderr, "%c", *p); 290 } 291 (void) fprintf(stderr, "\n"); 292 (void) fprintf(stderr, gettext("volume: ")); 293 p++; 294 for (i = 0; (i < 6); i++, p++) { 295 (void) fprintf(stderr, "%c", *p); 296 } 297 (void) fprintf(stderr, "\n"); 298 } 299