1 /* 2 * Copyright (c) 1983, 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)newfs.c 6.28 (Berkeley) 8/6/91"; 36 #endif /* not lint */ 37 38 #ifndef lint 39 char copyright[] = 40 "@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\ 41 All rights reserved.\n"; 42 #endif /* not lint */ 43 44 /* 45 * newfs: friendly front end to mkfs 46 */ 47 #include <sys/param.h> 48 #include <sys/ucred.h> 49 #include <sys/stat.h> 50 #include <sys/ioctl.h> 51 #include <sys/disklabel.h> 52 #include <sys/file.h> 53 #include <sys/mount.h> 54 55 #include <ufs/ufs/dir.h> 56 #include <ufs/ufs/dinode.h> 57 #include <ufs/ffs/fs.h> 58 59 #include <errno.h> 60 #include <unistd.h> 61 #include <stdio.h> 62 #include <stdlib.h> 63 #include <ctype.h> 64 #include <string.h> 65 #include <paths.h> 66 #include "config.h" 67 #include "extern.h" 68 69 #define COMPAT /* allow non-labeled disks */ 70 71 int mfs; /* run as the memory based filesystem */ 72 int Nflag; /* run without writing file system */ 73 int fssize; /* file system size */ 74 int ntracks; /* # tracks/cylinder */ 75 int nsectors; /* # sectors/track */ 76 int nphyssectors; /* # sectors/track including spares */ 77 int secpercyl; /* sectors per cylinder */ 78 int trackspares = -1; /* spare sectors per track */ 79 int cylspares = -1; /* spare sectors per cylinder */ 80 int sectorsize; /* bytes/sector */ 81 #ifdef tahoe 82 int realsectorsize; /* bytes/sector in hardware */ 83 #endif 84 int rpm; /* revolutions/minute of drive */ 85 int interleave; /* hardware sector interleave */ 86 int trackskew = -1; /* sector 0 skew, per track */ 87 int headswitch; /* head switch time, usec */ 88 int trackseek; /* track-to-track seek, usec */ 89 int fsize = 0; /* fragment size */ 90 int bsize = 0; /* block size */ 91 int cpg = DESCPG; /* cylinders/cylinder group */ 92 int cpgflg; /* cylinders/cylinder group flag was given */ 93 int minfree = MINFREE; /* free space threshold */ 94 int opt = DEFAULTOPT; /* optimization preference (space or time) */ 95 int density; /* number of bytes per inode */ 96 int maxcontig = MAXCONTIG; /* max contiguous blocks to allocate */ 97 int rotdelay = ROTDELAY; /* rotational delay between blocks */ 98 int maxbpg; /* maximum blocks per file in a cyl group */ 99 int nrpos = NRPOS; /* # of distinguished rotational positions */ 100 int bbsize = BBSIZE; /* boot block size */ 101 int sbsize = SBSIZE; /* superblock size */ 102 int mntflags; /* flags to be passed to mount */ 103 u_long memleft; /* virtual memory available */ 104 caddr_t membase; /* start address of memory based filesystem */ 105 #ifdef COMPAT 106 char *disktype; 107 int unlabeled; 108 #endif 109 110 char device[MAXPATHLEN]; 111 char *progname, *special; 112 113 static struct disklabel *getdisklabel __P((char *, int)); 114 static struct disklabel *debug_readlabel __P((int)); 115 static void rewritelabel __P((char *, int, struct disklabel *)); 116 static void usage __P((void)); 117 118 int 119 main(argc, argv) 120 int argc; 121 char *argv[]; 122 { 123 register int ch; 124 register struct partition *pp; 125 register struct disklabel *lp; 126 struct partition oldpartition; 127 struct stat st; 128 int debug, lfs, fsi, fso, segsize; 129 char *cp, *opstring; 130 131 if (progname = rindex(*argv, '/')) 132 ++progname; 133 else 134 progname = *argv; 135 136 if (strstr(progname, "mfs")) { 137 mfs = 1; 138 Nflag++; 139 } 140 141 /* -F is mfs only and MUST come first! */ 142 opstring = "F:B:DLNS:T:a:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:x:"; 143 if (!mfs) 144 opstring += 2; 145 146 debug = lfs = segsize = 0; 147 while ((ch = getopt(argc, argv, opstring)) != EOF) 148 switch(ch) { 149 case 'B': /* LFS segment size */ 150 if ((segsize = atoi(optarg)) < LFS_MINSEGSIZE) 151 fatal("%s: bad segment size", optarg); 152 break; 153 case 'D': 154 debug = 1; 155 break; 156 case 'F': 157 if ((mntflags = atoi(optarg)) == 0) 158 fatal("%s: bad mount flags", optarg); 159 break; 160 case 'L': /* Create lfs */ 161 lfs = 1; 162 break; 163 case 'N': 164 Nflag++; 165 break; 166 case 'S': 167 if ((sectorsize = atoi(optarg)) <= 0) 168 fatal("%s: bad sector size", optarg); 169 break; 170 #ifdef COMPAT 171 case 'T': 172 disktype = optarg; 173 break; 174 #endif 175 case 'a': 176 if ((maxcontig = atoi(optarg)) <= 0) 177 fatal("%s: bad max contiguous blocks\n", 178 optarg); 179 break; 180 case 'b': /* used for LFS */ 181 if ((bsize = atoi(optarg)) < MINBSIZE) 182 fatal("%s: bad block size", optarg); 183 break; 184 case 'c': 185 if ((cpg = atoi(optarg)) <= 0) 186 fatal("%s: bad cylinders/group", optarg); 187 cpgflg++; 188 break; 189 case 'd': 190 if ((rotdelay = atoi(optarg)) < 0) 191 fatal("%s: bad rotational delay\n", optarg); 192 break; 193 case 'e': 194 if ((maxbpg = atoi(optarg)) <= 0) 195 fatal("%s: bad blocks per file in a cyl group\n", 196 optarg); 197 break; 198 case 'f': 199 if ((fsize = atoi(optarg)) <= 0) 200 fatal("%s: bad frag size", optarg); 201 break; 202 case 'i': 203 if ((density = atoi(optarg)) <= 0) 204 fatal("%s: bad bytes per inode\n", optarg); 205 break; 206 case 'k': 207 if ((trackskew = atoi(optarg)) < 0) 208 fatal("%s: bad track skew", optarg); 209 break; 210 case 'l': 211 if ((interleave = atoi(optarg)) <= 0) 212 fatal("%s: bad interleave", optarg); 213 break; 214 case 'm': /* used for LFS */ 215 if ((minfree = atoi(optarg)) < 0 || minfree > 99) 216 fatal("%s: bad free space %%\n", optarg); 217 break; 218 case 'n': 219 if ((nrpos = atoi(optarg)) <= 0) 220 fatal("%s: bad rotational layout count\n", 221 optarg); 222 break; 223 case 'o': 224 if (strcmp(optarg, "space") == 0) 225 opt = FS_OPTSPACE; 226 else if (strcmp(optarg, "time") == 0) 227 opt = FS_OPTTIME; 228 else 229 fatal("%s: bad optimization preference %s", 230 optarg, "(options are `space' or `time')"); 231 break; 232 case 'p': 233 if ((trackspares = atoi(optarg)) < 0) 234 fatal("%s: bad spare sectors per track", 235 optarg); 236 break; 237 case 'r': 238 if ((rpm = atoi(optarg)) <= 0) 239 fatal("%s: bad revs/minute\n", optarg); 240 break; 241 case 's': /* used for LFS */ 242 if ((fssize = atoi(optarg)) <= 0) 243 fatal("%s: bad file system size", optarg); 244 break; 245 case 't': 246 if ((ntracks = atoi(optarg)) <= 0) 247 fatal("%s: bad total tracks", optarg); 248 break; 249 case 'u': 250 if ((nsectors = atoi(optarg)) <= 0) 251 fatal("%s: bad sectors/track", optarg); 252 break; 253 case 'x': 254 if ((cylspares = atoi(optarg)) < 0) 255 fatal("%s: bad spare sectors per cylinder", 256 optarg); 257 break; 258 case '?': 259 default: 260 usage(); 261 } 262 argc -= optind; 263 argv += optind; 264 265 if (argc != 2 && (mfs || argc != 1)) 266 usage(); 267 268 /* 269 * If the -N flag isn't specified, open the output file. If no path 270 * prefix, try /dev/r%s and then /dev/%s. 271 */ 272 special = argv[0]; 273 if (index(special, '/') == NULL) { 274 (void)sprintf(device, "%sr%s", _PATH_DEV, special); 275 if (stat(device, &st) == -1) 276 (void)sprintf(device, "%s%s", _PATH_DEV, special); 277 special = device; 278 } 279 if (!Nflag) { 280 fso = open(special, 281 (debug ? O_CREAT : 0) | O_WRONLY, DEFFILEMODE); 282 if (fso < 0) 283 fatal("%s: %s", special, strerror(errno)); 284 } else 285 fso = -1; 286 287 /* Open the input file. */ 288 fsi = open(special, O_RDONLY); 289 if (fsi < 0) 290 fatal("%s: %s", special, strerror(errno)); 291 if (fstat(fsi, &st) < 0) 292 fatal("%s: %s", special, strerror(errno)); 293 294 if (!debug && !mfs && !S_ISCHR(st.st_mode)) 295 (void)printf("%s: %s: not a character-special device\n", 296 progname, special); 297 cp = index(argv[0], '\0') - 1; 298 if (!debug && (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))) 299 fatal("%s: can't figure out file system partition", argv[0]); 300 301 #ifdef COMPAT 302 if (!mfs && disktype == NULL) 303 disktype = argv[1]; 304 #endif 305 if (debug) 306 lp = debug_readlabel(fsi); 307 else 308 lp = getdisklabel(special, fsi); 309 310 if (isdigit(*cp)) 311 pp = &lp->d_partitions[0]; 312 else 313 pp = &lp->d_partitions[*cp - 'a']; 314 if (pp->p_size == 0) 315 fatal("%s: `%c' partition is unavailable", argv[0], *cp); 316 317 /* If we're making a LFS, we break out here */ 318 exit(make_lfs(fso, lp, pp, minfree, bsize, segsize)); 319 } 320 321 #ifdef COMPAT 322 char lmsg[] = "%s: can't read disk label; disk type must be specified"; 323 #else 324 char lmsg[] = "%s: can't read disk label"; 325 #endif 326 327 static struct disklabel * 328 getdisklabel(s, fd) 329 char *s; 330 int fd; 331 { 332 static struct disklabel lab; 333 334 if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { 335 #ifdef COMPAT 336 if (disktype) { 337 struct disklabel *lp, *getdiskbyname(); 338 339 unlabeled++; 340 lp = getdiskbyname(disktype); 341 if (lp == NULL) 342 fatal("%s: unknown disk type", disktype); 343 return (lp); 344 } 345 #endif 346 (void)fprintf(stderr, 347 "%s: ioctl (GDINFO): %s\n", progname, strerror(errno)); 348 fatal(lmsg, s); 349 } 350 return (&lab); 351 } 352 353 354 static struct disklabel * 355 debug_readlabel(fd) 356 int fd; 357 { 358 static struct disklabel lab; 359 int n; 360 361 if ((n = read(fd, &lab, sizeof(struct disklabel))) < 0) 362 fatal("unable to read disk label: %s", strerror(errno)); 363 else if (n < sizeof(struct disklabel)) 364 fatal("short read of disklabel: %d of %d bytes", n, 365 sizeof(struct disklabel)); 366 return(&lab); 367 } 368 369 static void 370 rewritelabel(s, fd, lp) 371 char *s; 372 int fd; 373 register struct disklabel *lp; 374 { 375 #ifdef COMPAT 376 if (unlabeled) 377 return; 378 #endif 379 lp->d_checksum = 0; 380 lp->d_checksum = dkcksum(lp); 381 if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) { 382 (void)fprintf(stderr, 383 "%s: ioctl (WDINFO): %s\n", progname, strerror(errno)); 384 fatal("%s: can't rewrite disk label", s); 385 } 386 #if vax 387 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 388 register i; 389 int cfd; 390 daddr_t alt; 391 char specname[64]; 392 char blk[1024]; 393 char *cp; 394 395 /* 396 * Make name for 'c' partition. 397 */ 398 strcpy(specname, s); 399 cp = specname + strlen(specname) - 1; 400 if (!isdigit(*cp)) 401 *cp = 'c'; 402 cfd = open(specname, O_WRONLY); 403 if (cfd < 0) 404 fatal("%s: %s", specname, strerror(errno)); 405 bzero(blk, sizeof(blk)); 406 *(struct disklabel *)(blk + LABELOFFSET) = *lp; 407 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 408 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 409 if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, 410 L_SET) == -1) 411 fatal("lseek to badsector area: %s", 412 strerror(errno)); 413 if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) 414 fprintf(stderr, 415 "%s: alternate label %d write: %s\n", 416 progname, i/2, strerror(errno)); 417 } 418 close(cfd); 419 } 420 #endif 421 } 422 423 void 424 usage() 425 { 426 if (mfs) { 427 fprintf(stderr, 428 "usage: mfs [ -fsoptions ] special-device mount-point\n"); 429 } else 430 fprintf(stderr, 431 "usage: newfs [ -fsoptions ] special-device%s\n", 432 #ifdef COMPAT 433 " [device-type]"); 434 #else 435 ""); 436 #endif 437 fprintf(stderr, "where fsoptions are:\n"); 438 fprintf(stderr, "\t-B LFS segment size\n"); 439 fprintf(stderr, "\t-D debug\n"); 440 fprintf(stderr, "\t-F mount flags\n"); 441 fprintf(stderr, "\t-L create LFS file system\n"); 442 fprintf(stderr, 443 "\t-N do not create file system, just print out parameters\n"); 444 fprintf(stderr, "\t-S sector size\n"); 445 #ifdef COMPAT 446 fprintf(stderr, "\t-T disktype\n"); 447 #endif 448 fprintf(stderr, "\t-a maximum contiguous blocks\n"); 449 fprintf(stderr, "\t-b block size\n"); 450 fprintf(stderr, "\t-c cylinders/group\n"); 451 fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 452 fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 453 fprintf(stderr, "\t-f frag size\n"); 454 fprintf(stderr, "\t-i number of bytes per inode\n"); 455 fprintf(stderr, "\t-k sector 0 skew, per track\n"); 456 fprintf(stderr, "\t-l hardware sector interleave\n"); 457 fprintf(stderr, "\t-m minimum free space %%\n"); 458 fprintf(stderr, "\t-n number of distinguished rotational positions\n"); 459 fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 460 fprintf(stderr, "\t-p spare sectors per track\n"); 461 fprintf(stderr, "\t-r revolutions/minute\n"); 462 fprintf(stderr, "\t-s file system size (sectors)\n"); 463 fprintf(stderr, "\t-t tracks/cylinder\n"); 464 fprintf(stderr, "\t-u sectors/track\n"); 465 fprintf(stderr, "\t-x spare sectors per cylinder\n"); 466 exit(1); 467 } 468