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