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