155183Sbostic /*- 255183Sbostic * Copyright (c) 1989, 1992 The Regents of the University of California. 351151Sbostic * All rights reserved. 451151Sbostic * 555183Sbostic * %sccs.include.redist.c% 651151Sbostic */ 751151Sbostic 851151Sbostic #ifndef lint 955183Sbostic char copyright[] = 1055183Sbostic "@(#) Copyright (c) 1989, 1992 The Regents of the University of California.\n\ 1155183Sbostic All rights reserved.\n"; 1251151Sbostic #endif /* not lint */ 1351151Sbostic 1451151Sbostic #ifndef lint 15*57202Smargo static char sccsid[] = "@(#)newfs.c 5.7 (Berkeley) 12/18/92"; 1651151Sbostic #endif /* not lint */ 1751151Sbostic 1851151Sbostic /* 1951151Sbostic * newfs: friendly front end to mkfs 2051151Sbostic */ 2151151Sbostic #include <sys/param.h> 2251868Sbostic #include <sys/ucred.h> 2351151Sbostic #include <sys/stat.h> 2451151Sbostic #include <sys/ioctl.h> 2551151Sbostic #include <sys/disklabel.h> 2651151Sbostic #include <sys/file.h> 2751151Sbostic #include <sys/mount.h> 2851151Sbostic 2951866Sbostic #include <ufs/ufs/dir.h> 3051866Sbostic #include <ufs/ufs/dinode.h> 3151866Sbostic #include <ufs/ffs/fs.h> 3251866Sbostic 3351151Sbostic #include <errno.h> 3451151Sbostic #include <unistd.h> 3551151Sbostic #include <stdio.h> 3651151Sbostic #include <stdlib.h> 3751151Sbostic #include <ctype.h> 3851151Sbostic #include <string.h> 3951151Sbostic #include <paths.h> 4051151Sbostic #include "config.h" 4151151Sbostic #include "extern.h" 4251151Sbostic 4351151Sbostic #define COMPAT /* allow non-labeled disks */ 4451151Sbostic 4551151Sbostic int mfs; /* run as the memory based filesystem */ 4651151Sbostic int Nflag; /* run without writing file system */ 4751151Sbostic int fssize; /* file system size */ 4851151Sbostic int ntracks; /* # tracks/cylinder */ 4951151Sbostic int nsectors; /* # sectors/track */ 5051151Sbostic int nphyssectors; /* # sectors/track including spares */ 5151151Sbostic int secpercyl; /* sectors per cylinder */ 5251151Sbostic int trackspares = -1; /* spare sectors per track */ 5351151Sbostic int cylspares = -1; /* spare sectors per cylinder */ 5451151Sbostic int sectorsize; /* bytes/sector */ 5551151Sbostic #ifdef tahoe 5651151Sbostic int realsectorsize; /* bytes/sector in hardware */ 5751151Sbostic #endif 5851151Sbostic int rpm; /* revolutions/minute of drive */ 5951151Sbostic int interleave; /* hardware sector interleave */ 6051151Sbostic int trackskew = -1; /* sector 0 skew, per track */ 6151151Sbostic int headswitch; /* head switch time, usec */ 6251151Sbostic int trackseek; /* track-to-track seek, usec */ 6351151Sbostic int fsize = 0; /* fragment size */ 6451151Sbostic int bsize = 0; /* block size */ 6551151Sbostic int cpg = DESCPG; /* cylinders/cylinder group */ 6651151Sbostic int cpgflg; /* cylinders/cylinder group flag was given */ 6751151Sbostic int minfree = MINFREE; /* free space threshold */ 6851151Sbostic int opt = DEFAULTOPT; /* optimization preference (space or time) */ 6951151Sbostic int density; /* number of bytes per inode */ 7051151Sbostic int maxcontig = MAXCONTIG; /* max contiguous blocks to allocate */ 7151151Sbostic int rotdelay = ROTDELAY; /* rotational delay between blocks */ 7251151Sbostic int maxbpg; /* maximum blocks per file in a cyl group */ 7351151Sbostic int nrpos = NRPOS; /* # of distinguished rotational positions */ 7451151Sbostic int bbsize = BBSIZE; /* boot block size */ 7551151Sbostic int sbsize = SBSIZE; /* superblock size */ 7651151Sbostic int mntflags; /* flags to be passed to mount */ 7751151Sbostic u_long memleft; /* virtual memory available */ 7851151Sbostic caddr_t membase; /* start address of memory based filesystem */ 7951151Sbostic #ifdef COMPAT 8051151Sbostic char *disktype; 8151151Sbostic int unlabeled; 8251151Sbostic #endif 8351151Sbostic 8451151Sbostic char device[MAXPATHLEN]; 8551151Sbostic char *progname, *special; 8651151Sbostic 8751151Sbostic static struct disklabel *getdisklabel __P((char *, int)); 8851151Sbostic static struct disklabel *debug_readlabel __P((int)); 8951151Sbostic static void rewritelabel __P((char *, int, struct disklabel *)); 9051151Sbostic static void usage __P((void)); 9151151Sbostic 9251151Sbostic int 9351151Sbostic main(argc, argv) 9451151Sbostic int argc; 9551151Sbostic char *argv[]; 9651151Sbostic { 9751151Sbostic register int ch; 9851151Sbostic register struct partition *pp; 9951151Sbostic register struct disklabel *lp; 10051151Sbostic struct partition oldpartition; 10151151Sbostic struct stat st; 10251151Sbostic int debug, lfs, fsi, fso, segsize; 10351151Sbostic char *cp, *opstring; 10451151Sbostic 10551151Sbostic if (progname = rindex(*argv, '/')) 10651151Sbostic ++progname; 10751151Sbostic else 10851151Sbostic progname = *argv; 10951151Sbostic 11051151Sbostic if (strstr(progname, "mfs")) { 11151151Sbostic mfs = 1; 11251151Sbostic Nflag++; 11351151Sbostic } 11451151Sbostic 11551151Sbostic /* -F is mfs only and MUST come first! */ 11651151Sbostic opstring = "F:B:DLNS:T:a:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:x:"; 11751151Sbostic if (!mfs) 11851151Sbostic opstring += 2; 11951151Sbostic 12051151Sbostic debug = lfs = segsize = 0; 12151151Sbostic while ((ch = getopt(argc, argv, opstring)) != EOF) 12251151Sbostic switch(ch) { 12351151Sbostic case 'B': /* LFS segment size */ 12451151Sbostic if ((segsize = atoi(optarg)) < LFS_MINSEGSIZE) 12551151Sbostic fatal("%s: bad segment size", optarg); 12651151Sbostic break; 12751151Sbostic case 'D': 12851151Sbostic debug = 1; 12951151Sbostic break; 13051151Sbostic case 'F': 13151151Sbostic if ((mntflags = atoi(optarg)) == 0) 13251151Sbostic fatal("%s: bad mount flags", optarg); 13351151Sbostic break; 13451151Sbostic case 'L': /* Create lfs */ 13551151Sbostic lfs = 1; 13651151Sbostic break; 13751151Sbostic case 'N': 13851151Sbostic Nflag++; 13951151Sbostic break; 14051151Sbostic case 'S': 14151151Sbostic if ((sectorsize = atoi(optarg)) <= 0) 14251151Sbostic fatal("%s: bad sector size", optarg); 14351151Sbostic break; 14451151Sbostic #ifdef COMPAT 14551151Sbostic case 'T': 14651151Sbostic disktype = optarg; 14751151Sbostic break; 14851151Sbostic #endif 14951151Sbostic case 'a': 15051151Sbostic if ((maxcontig = atoi(optarg)) <= 0) 15151151Sbostic fatal("%s: bad max contiguous blocks\n", 15251151Sbostic optarg); 15351151Sbostic break; 15451151Sbostic case 'b': /* used for LFS */ 155*57202Smargo if ((bsize = atoi(optarg)) < LFS_MINBLOCKSIZE) 15651151Sbostic fatal("%s: bad block size", optarg); 15751151Sbostic break; 15851151Sbostic case 'c': 15951151Sbostic if ((cpg = atoi(optarg)) <= 0) 16051151Sbostic fatal("%s: bad cylinders/group", optarg); 16151151Sbostic cpgflg++; 16251151Sbostic break; 16351151Sbostic case 'd': 16451151Sbostic if ((rotdelay = atoi(optarg)) < 0) 16551151Sbostic fatal("%s: bad rotational delay\n", optarg); 16651151Sbostic break; 16751151Sbostic case 'e': 16851151Sbostic if ((maxbpg = atoi(optarg)) <= 0) 16951151Sbostic fatal("%s: bad blocks per file in a cyl group\n", 17051151Sbostic optarg); 17151151Sbostic break; 17251151Sbostic case 'f': 17351151Sbostic if ((fsize = atoi(optarg)) <= 0) 17451151Sbostic fatal("%s: bad frag size", optarg); 17551151Sbostic break; 17651151Sbostic case 'i': 17751151Sbostic if ((density = atoi(optarg)) <= 0) 17851151Sbostic fatal("%s: bad bytes per inode\n", optarg); 17951151Sbostic break; 18051151Sbostic case 'k': 18151151Sbostic if ((trackskew = atoi(optarg)) < 0) 18251151Sbostic fatal("%s: bad track skew", optarg); 18351151Sbostic break; 18451151Sbostic case 'l': 18551151Sbostic if ((interleave = atoi(optarg)) <= 0) 18651151Sbostic fatal("%s: bad interleave", optarg); 18751151Sbostic break; 18851151Sbostic case 'm': /* used for LFS */ 18951151Sbostic if ((minfree = atoi(optarg)) < 0 || minfree > 99) 19051151Sbostic fatal("%s: bad free space %%\n", optarg); 19151151Sbostic break; 19251151Sbostic case 'n': 19351151Sbostic if ((nrpos = atoi(optarg)) <= 0) 19451151Sbostic fatal("%s: bad rotational layout count\n", 19551151Sbostic optarg); 19651151Sbostic break; 19751151Sbostic case 'o': 19851151Sbostic if (strcmp(optarg, "space") == 0) 19951151Sbostic opt = FS_OPTSPACE; 20051151Sbostic else if (strcmp(optarg, "time") == 0) 20151151Sbostic opt = FS_OPTTIME; 20251151Sbostic else 20351151Sbostic fatal("%s: bad optimization preference %s", 20451151Sbostic optarg, "(options are `space' or `time')"); 20551151Sbostic break; 20651151Sbostic case 'p': 20751151Sbostic if ((trackspares = atoi(optarg)) < 0) 20851151Sbostic fatal("%s: bad spare sectors per track", 20951151Sbostic optarg); 21051151Sbostic break; 21151151Sbostic case 'r': 21251151Sbostic if ((rpm = atoi(optarg)) <= 0) 21351151Sbostic fatal("%s: bad revs/minute\n", optarg); 21451151Sbostic break; 21551151Sbostic case 's': /* used for LFS */ 21651151Sbostic if ((fssize = atoi(optarg)) <= 0) 21751151Sbostic fatal("%s: bad file system size", optarg); 21851151Sbostic break; 21951151Sbostic case 't': 22051151Sbostic if ((ntracks = atoi(optarg)) <= 0) 22151151Sbostic fatal("%s: bad total tracks", optarg); 22251151Sbostic break; 22351151Sbostic case 'u': 22451151Sbostic if ((nsectors = atoi(optarg)) <= 0) 22551151Sbostic fatal("%s: bad sectors/track", optarg); 22651151Sbostic break; 22751151Sbostic case 'x': 22851151Sbostic if ((cylspares = atoi(optarg)) < 0) 22951151Sbostic fatal("%s: bad spare sectors per cylinder", 23051151Sbostic optarg); 23151151Sbostic break; 23251151Sbostic case '?': 23351151Sbostic default: 23451151Sbostic usage(); 23551151Sbostic } 23651151Sbostic argc -= optind; 23751151Sbostic argv += optind; 23851151Sbostic 23951151Sbostic if (argc != 2 && (mfs || argc != 1)) 24051151Sbostic usage(); 24151151Sbostic 24251151Sbostic /* 24351151Sbostic * If the -N flag isn't specified, open the output file. If no path 24451151Sbostic * prefix, try /dev/r%s and then /dev/%s. 24551151Sbostic */ 24651151Sbostic special = argv[0]; 24751151Sbostic if (index(special, '/') == NULL) { 24851151Sbostic (void)sprintf(device, "%sr%s", _PATH_DEV, special); 24951151Sbostic if (stat(device, &st) == -1) 25051151Sbostic (void)sprintf(device, "%s%s", _PATH_DEV, special); 25151151Sbostic special = device; 25251151Sbostic } 25351151Sbostic if (!Nflag) { 25451151Sbostic fso = open(special, 25551151Sbostic (debug ? O_CREAT : 0) | O_WRONLY, DEFFILEMODE); 25651151Sbostic if (fso < 0) 25751151Sbostic fatal("%s: %s", special, strerror(errno)); 25851151Sbostic } else 25951151Sbostic fso = -1; 26051151Sbostic 26151151Sbostic /* Open the input file. */ 26251151Sbostic fsi = open(special, O_RDONLY); 26351151Sbostic if (fsi < 0) 26451151Sbostic fatal("%s: %s", special, strerror(errno)); 26551151Sbostic if (fstat(fsi, &st) < 0) 26651151Sbostic fatal("%s: %s", special, strerror(errno)); 26751151Sbostic 26851865Sbostic if (!debug && !mfs && !S_ISCHR(st.st_mode)) 26951151Sbostic (void)printf("%s: %s: not a character-special device\n", 27051151Sbostic progname, special); 27151151Sbostic cp = index(argv[0], '\0') - 1; 27251151Sbostic if (!debug && (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))) 27351151Sbostic fatal("%s: can't figure out file system partition", argv[0]); 27451151Sbostic 27551151Sbostic #ifdef COMPAT 27651151Sbostic if (!mfs && disktype == NULL) 27751151Sbostic disktype = argv[1]; 27851151Sbostic #endif 27951151Sbostic if (debug) 28051151Sbostic lp = debug_readlabel(fsi); 28151151Sbostic else 28251151Sbostic lp = getdisklabel(special, fsi); 28351151Sbostic 28451151Sbostic if (isdigit(*cp)) 28551151Sbostic pp = &lp->d_partitions[0]; 28651151Sbostic else 28751151Sbostic pp = &lp->d_partitions[*cp - 'a']; 28851151Sbostic if (pp->p_size == 0) 28951151Sbostic fatal("%s: `%c' partition is unavailable", argv[0], *cp); 29051151Sbostic 29151151Sbostic /* If we're making a LFS, we break out here */ 29252100Sbostic exit(make_lfs(fso, lp, pp, minfree, bsize, segsize)); 29351151Sbostic } 29451151Sbostic 29551151Sbostic #ifdef COMPAT 29651151Sbostic char lmsg[] = "%s: can't read disk label; disk type must be specified"; 29751151Sbostic #else 29851151Sbostic char lmsg[] = "%s: can't read disk label"; 29951151Sbostic #endif 30051151Sbostic 30151151Sbostic static struct disklabel * 30251151Sbostic getdisklabel(s, fd) 30351151Sbostic char *s; 30451151Sbostic int fd; 30551151Sbostic { 30651151Sbostic static struct disklabel lab; 30751151Sbostic 30851151Sbostic if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { 30951151Sbostic #ifdef COMPAT 31051151Sbostic if (disktype) { 31151151Sbostic struct disklabel *lp, *getdiskbyname(); 31251151Sbostic 31351151Sbostic unlabeled++; 31451151Sbostic lp = getdiskbyname(disktype); 31551151Sbostic if (lp == NULL) 31651151Sbostic fatal("%s: unknown disk type", disktype); 31751151Sbostic return (lp); 31851151Sbostic } 31951151Sbostic #endif 32051151Sbostic (void)fprintf(stderr, 32151151Sbostic "%s: ioctl (GDINFO): %s\n", progname, strerror(errno)); 32251151Sbostic fatal(lmsg, s); 32351151Sbostic } 32451151Sbostic return (&lab); 32551151Sbostic } 32651151Sbostic 32751151Sbostic 32851151Sbostic static struct disklabel * 32951151Sbostic debug_readlabel(fd) 33051151Sbostic int fd; 33151151Sbostic { 33251151Sbostic static struct disklabel lab; 33351151Sbostic int n; 33451151Sbostic 33551151Sbostic if ((n = read(fd, &lab, sizeof(struct disklabel))) < 0) 33651151Sbostic fatal("unable to read disk label: %s", strerror(errno)); 33751151Sbostic else if (n < sizeof(struct disklabel)) 33851151Sbostic fatal("short read of disklabel: %d of %d bytes", n, 33951151Sbostic sizeof(struct disklabel)); 34051151Sbostic return(&lab); 34151151Sbostic } 34251151Sbostic 34351151Sbostic static void 34451151Sbostic rewritelabel(s, fd, lp) 34551151Sbostic char *s; 34651151Sbostic int fd; 34751151Sbostic register struct disklabel *lp; 34851151Sbostic { 34951151Sbostic #ifdef COMPAT 35051151Sbostic if (unlabeled) 35151151Sbostic return; 35251151Sbostic #endif 35351151Sbostic lp->d_checksum = 0; 35451151Sbostic lp->d_checksum = dkcksum(lp); 35551151Sbostic if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) { 35651151Sbostic (void)fprintf(stderr, 35751151Sbostic "%s: ioctl (WDINFO): %s\n", progname, strerror(errno)); 35851151Sbostic fatal("%s: can't rewrite disk label", s); 35951151Sbostic } 36051151Sbostic #if vax 36151151Sbostic if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) { 36251151Sbostic register i; 36351151Sbostic int cfd; 36451151Sbostic daddr_t alt; 36551151Sbostic char specname[64]; 36651151Sbostic char blk[1024]; 36751151Sbostic char *cp; 36851151Sbostic 36951151Sbostic /* 37051151Sbostic * Make name for 'c' partition. 37151151Sbostic */ 37251151Sbostic strcpy(specname, s); 37351151Sbostic cp = specname + strlen(specname) - 1; 37451151Sbostic if (!isdigit(*cp)) 37551151Sbostic *cp = 'c'; 37651151Sbostic cfd = open(specname, O_WRONLY); 37751151Sbostic if (cfd < 0) 37851151Sbostic fatal("%s: %s", specname, strerror(errno)); 37951151Sbostic bzero(blk, sizeof(blk)); 38051151Sbostic *(struct disklabel *)(blk + LABELOFFSET) = *lp; 38151151Sbostic alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors; 38251151Sbostic for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) { 38351151Sbostic if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, 38451151Sbostic L_SET) == -1) 38551151Sbostic fatal("lseek to badsector area: %s", 38651151Sbostic strerror(errno)); 38751151Sbostic if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) 38851151Sbostic fprintf(stderr, 38951151Sbostic "%s: alternate label %d write: %s\n", 39051151Sbostic progname, i/2, strerror(errno)); 39151151Sbostic } 39251151Sbostic close(cfd); 39351151Sbostic } 39451151Sbostic #endif 39551151Sbostic } 39651151Sbostic 39751151Sbostic void 39851151Sbostic usage() 39951151Sbostic { 40051151Sbostic if (mfs) { 40151151Sbostic fprintf(stderr, 40251151Sbostic "usage: mfs [ -fsoptions ] special-device mount-point\n"); 40351151Sbostic } else 40451151Sbostic fprintf(stderr, 40551151Sbostic "usage: newfs [ -fsoptions ] special-device%s\n", 40651151Sbostic #ifdef COMPAT 40751151Sbostic " [device-type]"); 40851151Sbostic #else 40951151Sbostic ""); 41051151Sbostic #endif 41151151Sbostic fprintf(stderr, "where fsoptions are:\n"); 41251151Sbostic fprintf(stderr, "\t-B LFS segment size\n"); 41351151Sbostic fprintf(stderr, "\t-D debug\n"); 41451151Sbostic fprintf(stderr, "\t-F mount flags\n"); 41551151Sbostic fprintf(stderr, "\t-L create LFS file system\n"); 41651151Sbostic fprintf(stderr, 41751151Sbostic "\t-N do not create file system, just print out parameters\n"); 41851151Sbostic fprintf(stderr, "\t-S sector size\n"); 41951151Sbostic #ifdef COMPAT 42051151Sbostic fprintf(stderr, "\t-T disktype\n"); 42151151Sbostic #endif 42251151Sbostic fprintf(stderr, "\t-a maximum contiguous blocks\n"); 42351151Sbostic fprintf(stderr, "\t-b block size\n"); 42451151Sbostic fprintf(stderr, "\t-c cylinders/group\n"); 42551151Sbostic fprintf(stderr, "\t-d rotational delay between contiguous blocks\n"); 42651151Sbostic fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n"); 42751151Sbostic fprintf(stderr, "\t-f frag size\n"); 42851151Sbostic fprintf(stderr, "\t-i number of bytes per inode\n"); 42951151Sbostic fprintf(stderr, "\t-k sector 0 skew, per track\n"); 43051151Sbostic fprintf(stderr, "\t-l hardware sector interleave\n"); 43151151Sbostic fprintf(stderr, "\t-m minimum free space %%\n"); 43251151Sbostic fprintf(stderr, "\t-n number of distinguished rotational positions\n"); 43351151Sbostic fprintf(stderr, "\t-o optimization preference (`space' or `time')\n"); 43451151Sbostic fprintf(stderr, "\t-p spare sectors per track\n"); 43551151Sbostic fprintf(stderr, "\t-r revolutions/minute\n"); 43651151Sbostic fprintf(stderr, "\t-s file system size (sectors)\n"); 43751151Sbostic fprintf(stderr, "\t-t tracks/cylinder\n"); 43851151Sbostic fprintf(stderr, "\t-u sectors/track\n"); 43951151Sbostic fprintf(stderr, "\t-x spare sectors per cylinder\n"); 44051151Sbostic exit(1); 44151151Sbostic } 442