2021-10-11 18:20:23 -03:00

486 lines
11 KiB
C

#ident "@(#)newfs.c 1.1 92/07/30 SMI" /* from UCB 5.2 9/11/85 */
/*
* newfs: friendly front end to mkfs
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <ufs/fs.h>
#include <sys/dir.h>
#include <stdio.h>
#include <disktab.h>
#include <sys/ioctl.h>
#include <sun/dklabel.h>
#include <sun/dkio.h>
struct disktab *getdiskbydev();
#define EPATH "PATH=/bin:/usr/bin:/usr/etc:"
int Nflag; /* run mkfs without writing file system */
int verbose; /* show mkfs line before exec */
int fssize; /* file system size */
int fsize; /* fragment size */
int bsize; /* block size */
int ntracks; /* # tracks/cylinder */
int nsectors; /* # sectors/track */
int cpg; /* cylinders/cylinder group */
int minfree = -1; /* free space threshold */
int opt; /* optimization preference (space or time) */
int rpm; /* revolutions/minute of drive */
int nrpos = 8; /* # of distinguished rotational positions */
/* 8 is the historical default */
int density; /* number of bytes per inode */
int apc; /* alternates per cylinder */
int rot = -1; /* rotational delay (msecs) */
int maxcontig = -1; /* maximum number of contig blocks */
char device[MAXPATHLEN];
char cmd[BUFSIZ];
extern char *index();
extern char *strcpy();
extern char *strcat();
extern char *sprintf();
extern char *getenv();
extern char *malloc();
extern void exit();
main(argc, argv)
char *argv[];
{
static char *nmiss = "-n: missing # of rotational positions\n";
static char *nmiss2 = "%s: bad # of rotational positions\n";
static char *amiss = "-a: missing # of alternates per cyl";
static char *omiss = "-o: missing optimization preference";
static char *badop = "%s: bad optimization preference %s";
char *cp, *special;
register struct disktab *dp;
register struct partition *pp;
struct stat st;
struct dk_info dkinfo;
int fd, status, cacheing_drive;
argc--, argv++;
while (argc > 0 && argv[0][0] == '-') {
for (cp = &argv[0][1]; *cp; cp++)
switch (*cp) {
case 'v':
verbose++;
break;
case 'N':
Nflag++;
break;
case 's':
if (argc < 1)
fatal("-s: missing file system size");
argc--, argv++;
fssize = atoi(*argv);
if (fssize < 0)
fatal("%s: bad file system size",
*argv);
goto next;
case 'C':
if (argc < 1)
fatal("-C: missing maxcontig");
argc--, argv++;
maxcontig = atoi(*argv);
if (maxcontig <= 0)
fatal("%s: bad maxcontig", *argv);
goto next;
case 'd':
if (argc < 1)
fatal("-d: missing rotational delay");
argc--, argv++;
rot = atoi(*argv);
if (rot < 0)
fatal("%s: bad rotational delay",
*argv);
goto next;
case 't':
if (argc < 1)
fatal("-t: missing track total");
argc--, argv++;
ntracks = atoi(*argv);
if (ntracks < 0)
fatal("%s: bad total tracks", *argv);
goto next;
case 'o':
if (argc < 1)
fatal(omiss);
argc--, argv++;
if (strcmp(*argv, "space") == 0)
opt = FS_OPTSPACE;
else if (strcmp(*argv, "time") == 0)
opt = FS_OPTTIME;
else
fatal(badop, *argv,
"(options are `space' or `time')");
goto next;
case 'a':
if (argc < 1)
fatal(amiss);
argc--, argv++;
apc = atoi(*argv);
if (apc < 0)
fatal("%s: bad altenates per cyl ",
*argv);
goto next;
case 'b':
if (argc < 1)
fatal("-b: missing block size");
argc--, argv++;
bsize = atoi(*argv);
if (bsize < 0 || bsize < MINBSIZE)
fatal("%s: bad block size", *argv);
goto next;
case 'f':
if (argc < 1)
fatal("-f: missing frag size");
argc--, argv++;
fsize = atoi(*argv);
if (fsize < 0)
fatal("%s: bad frag size", *argv);
goto next;
case 'c':
if (argc < 1)
fatal("-c: missing cylinders/group");
argc--, argv++;
cpg = atoi(*argv);
if (cpg < 0)
fatal("%s: bad cylinders/group", *argv);
goto next;
case 'm':
if (argc < 1)
fatal("-m: missing free space %%\n");
argc--, argv++;
minfree = atoi(*argv);
if (minfree < 0 || minfree > 99)
fatal("%s: bad free space %%\n",
*argv);
goto next;
case 'n':
if (argc < 1)
fatal(nmiss);
argc--, argv++;
nrpos = atoi(*argv);
if (nrpos < 0)
fatal(nmiss2, *argv);
goto next;
case 'r':
if (argc < 1)
fatal("-r: missing revs/minute\n");
argc--, argv++;
rpm = atoi(*argv);
if (rpm < 0)
fatal("%s: bad revs/minute\n", *argv);
goto next;
case 'i':
if (argc < 1)
fatal("-i: missing bytes per inode\n");
argc--, argv++;
density = atoi(*argv);
if (density < 0)
fatal("%s: bad bytes per inode\n",
*argv);
goto next;
default:
fatal("-%c: unknown flag", *cp);
}
next:
argc--, argv++;
}
if (argc < 1) {
fprintf(stderr, "usage: newfs [ -v ] [ mkfs-options ] %s\n",
"raw-special-device");
fprintf(stderr, "where mkfs-options are:\n");
fprintf(stderr, "\t-N do not create file system, %s\n",
"just print out parameters");
fprintf(stderr, "\t-s file system size (sectors)\n");
fprintf(stderr, "\t-b block size\n");
fprintf(stderr, "\t-f frag size\n");
fprintf(stderr, "\t-t tracks/cylinder\n");
fprintf(stderr, "\t-c cylinders/group\n");
fprintf(stderr, "\t-m minimum free space %%\n");
fprintf(stderr, "\t-o optimization preference %s\n",
"(`space' or `time')");
fprintf(stderr, "\t-r revolutions/minute\n");
fprintf(stderr, "\t-i number of bytes per inode\n");
fprintf(stderr, "\t-a number of alternates per cylinder\n");
fprintf(stderr, "\t-C maxcontig\n");
fprintf(stderr, "\t-d rotational delay\n");
fprintf(stderr, "\t-n number of rotational positions\n");
exit(1);
}
special = argv[0];
again:
if (stat(special, &st) < 0) {
if (*special != '/') {
if (*special == 'r')
special++;
special = sprintf(device, "/dev/r%s", special);
goto again;
}
fprintf(stderr, "newfs: "); perror(special);
exit(2);
}
if ((st.st_mode & S_IFMT) != S_IFCHR)
fatal("%s: not a raw disk device", special);
dp = getdiskbydev(special);
if (dp == 0)
fatal("%s: unknown disk information", argv[1]);
cp = index(argv[0], '\0') - 1;
if (cp == 0 || *cp < 'a' || *cp > 'h')
fatal("%s: can't figure out file system partition", argv[0]);
pp = &dp->d_partitions[*cp - 'a'];
if (fssize == 0) {
fssize = pp->p_size;
if (fssize < 0)
fatal("%s: no default size for `%c' partition",
argv[1], *cp);
}
if (nsectors == 0) {
nsectors = dp->d_nsectors;
if (nsectors < 0)
fatal("%s: no default #sectors/track", argv[1]);
}
if (ntracks == 0) {
ntracks = dp->d_ntracks;
if (ntracks < 0)
fatal("%s: no default #tracks", argv[1]);
}
if (bsize == 0) {
bsize = pp->p_bsize;
if (bsize < 0)
fatal("%s: no default block size for `%c' partition",
argv[1], *cp);
}
if (fsize == 0) {
fsize = pp->p_fsize;
if (fsize < 0)
fatal("%s: no default frag size for `%c' partition",
argv[1], *cp);
}
if (rpm == 0) {
rpm = dp->d_rpm;
if (rpm < 0)
fatal("%s: no default revolutions/minute value",
argv[1]);
}
if ((fd = open(special, 2)) == -1)
fatal("can't open %s", special);
/*
* Best default depends on controller type.
*
* The controller should tell us (via some
* ioctl) what rotdelay and maxcontig it might
* prefer.
*
* For both rotdelay and maxcontig we need to infer
* from both controller type and, in the SCSI case,
* additional ioctl information, whether it might
* be a good idea to set rotdelay to zero and
* maxcontig to a reasonably large default value
* (in the absence of a command argument overriding
* either).
*/
cacheing_drive = 0;
if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) {
switch (dkinfo.dki_ctype) {
case DKC_MD21:
case DKC_SCSI_CCS:
if (scsidisk_has_cache(fd) == 0) {
break;
}
/* FALLTHROUGH */
case DKC_XD7053:
case DKC_SUN_IPI1:
case DKC_CDC_9057:
case DKC_FJ_M1060:
cacheing_drive = 1;
break;
}
}
if (rot == -1 && cacheing_drive) {
rot = 0;
}
if (maxcontig == -1 && cacheing_drive) {
/*
* As long as maxphys is commonly 56K
* we need to use 7. If we grow it to
* 124K on all our machines, we can grow
* maxcontig to 15.
*/
maxcontig = 7;
}
close(fd);
/* XXX - following defaults are both here and in mkfs */
if (density <= 0)
density = 2048;
if (cpg == 0)
cpg = 16;
if (minfree < 0)
minfree = 10;
if (minfree < 10 && opt != FS_OPTSPACE) {
fprintf(stderr, "setting optimization for space ");
fprintf(stderr, "with minfree less than 10%\n");
opt = FS_OPTSPACE;
}
/*
* If alternates-per-cylinder is ever implemented:
* need to get apc from dp->d_apc if no -a switch???
*/
(void) sprintf(cmd,
"mkfs %s%s %d %d %d %d %d %d %d %d %d %s %d %d %d %d",
Nflag ? "-N " : " ", special,
fssize, nsectors, ntracks, bsize, fsize, cpg, minfree, rpm/60,
density, opt == FS_OPTSPACE ? "s" : "t", apc, rot, nrpos,
maxcontig);
if (verbose)
printf("%s\n", cmd);
exenv();
if (status = system(cmd))
exit(status >> 8);
if (Nflag)
exit(0);
(void)sprintf(cmd, "fsirand %s", special);
if (status = system(cmd))
printf("%s: failed, status = %d\n", cmd, status);
exit(0);
/* NOTREACHED */
}
exenv()
{
char *epath; /* executable file path */
char *cpath; /* current path */
if ((cpath = getenv("PATH")) == NULL) {
fprintf(stderr, "newfs: no entry in env\n");
}
if ((epath = malloc((unsigned)strlen(EPATH)+strlen(cpath)+1)) == NULL) {
fprintf(stderr, "newfs: malloc failed\n");
exit(1);
}
strcpy(epath, EPATH);
strcat(epath, cpath);
if (putenv(epath) < 0) {
fprintf(stderr, "newfs: putenv failed\n");
exit(1);
}
}
/*VARARGS*/
fatal(fmt, arg1, arg2)
char *fmt;
{
fprintf(stderr, "newfs: ");
fprintf(stderr, fmt, arg1, arg2);
putc('\n', stderr);
exit(10);
}
struct disktab *
getdiskbydev(disk)
char *disk;
{
static struct disktab d;
struct dk_geom g;
struct dk_map m;
int fd, part;
part = disk[strlen(disk)-1] - 'a';
if ((fd = open(disk, 0)) < 0) {
perror(disk);
exit(1);
}
if (ioctl(fd, DKIOCGGEOM, &g) < 0) {
perror("geom ioctl");
exit(1);
}
d.d_secsize = 512;
d.d_ntracks = g.dkg_nhead;
d.d_nsectors = g.dkg_nsect;
d.d_ncylinders = g.dkg_ncyl;
d.d_rpm = g.dkg_rpm;
if (d.d_rpm <= 0)
d.d_rpm = 3600;
d.d_apc = g.dkg_apc;
if (ioctl(fd, DKIOCGPART, &m) < 0) {
perror("part ioctl");
exit(1);
}
close(fd);
d.d_partitions[part].p_size = m.dkl_nblk;
d.d_partitions[part].p_bsize = 8192;
d.d_partitions[part].p_fsize = 1024;
return (&d);
}
#include <scsi/scsi.h>
#define MSDSIZE (MODE_HEADER_LENGTH + sizeof (struct block_descriptor) + 32)
static int
modesense(localbuf, length, param, fd)
char *localbuf;
int length, param, fd;
{
auto struct dk_cmd cmdblk;
bzero(localbuf, length);
bzero((char *)&cmdblk, sizeof (cmdblk));
cmdblk.dkc_bufaddr = localbuf;
cmdblk.dkc_buflen = length;
cmdblk.dkc_blkno = param;
cmdblk.dkc_cmd = SCMD_MODE_SENSE;
cmdblk.dkc_flags = DK_ISOLATE|DK_SILENT;
return (ioctl(fd, DKIOCSCMD, (char *) &cmdblk));
}
int
scsidisk_has_cache(fd)
int fd;
{
struct mode_header *mh;
struct mode_page *mp;
auto char buf[MSDSIZE];
static int page_codes[] = { 0x8, 0x38, -1 };
int i;
mh = (struct mode_header *) buf;
for (i = 0; page_codes[i] != -1; i++) {
(void) bzero (buf, MSDSIZE);
if (modesense(buf, MSDSIZE, page_codes[i], fd) == 0) {
mp = MODE_PAGE_ADDR(mh, struct mode_page);
if (mp && mp->code && mp->length) {
return (1);
}
}
}
return (0);
}