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