Example #1
0
static void ledumpall(void)
{
    (void)printf("getsb: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) sb1, (uint64_t) sb2,
		 (uint64_t) getsb(buf, 0), (uint64_t) getsb(buf, 8));
    (void)printf("getub: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) ub1, (uint64_t) ub2,
		 (uint64_t) getub(buf, 0), (uint64_t) getub(buf, 8));
    (void)printf("getles16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) sw1, (uint64_t) sw2,
		 (uint64_t) getles16(buf, 0), (uint64_t) getles16(buf, 8));
    (void)printf("getleu16: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) uw1, (uint64_t) uw2,
		 (uint64_t) getleu16(buf, 0), (uint64_t) getleu16(buf, 8));
    (void)printf("getles32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) sl1, (uint64_t) sl2,
		 (uint64_t) getles32(buf, 0), (uint64_t) getles32(buf, 8));
    (void)printf("getleu32: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) ul1, (uint64_t) ul2,
		 (uint64_t) getleu32(buf, 0), (uint64_t) getleu32(buf, 8));
    (void)printf("getles64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) sL1, (uint64_t) sL2,
		 (uint64_t) getles64(buf, 0), (uint64_t) getles64(buf, 8));
    (void)printf("getleu64: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 "\n",
		 (uint64_t) uL1, (uint64_t) uL2,
		 (uint64_t) getleu64(buf, 0), (uint64_t) getleu64(buf, 8));
    (void)printf("getlef32: %f %f\n", f1, getlef32((const char *)buf, 24));
    (void)printf("getled64: %.16f %.16f\n", d1, getled64((const char *)buf, 16));
}
Example #2
0
static void display_superstar2_svinfo(unsigned char *buf, size_t data_len)
{
    int i;

    if (data_len != 67)
	return;

    for (i = 0; i < 12; i++) {
	/* get info for one channel/satellite */
	int off = i * 5 + 5;
	unsigned char fl, p**n, ss;
	char el;
	unsigned short az;

	if ((p**n = (unsigned char)getub(buf, off) & 0x1f) == 0)
	    p**n = ((unsigned char)getub(buf, off + 3) >> 1) + 87;

	ss = (unsigned char)getub(buf, off + 4);
	el = (char)getsb(buf, off + 1);
	az = (unsigned short)(getub(buf, off + 2) +
			      ((getub(buf, off + 3) & 0x1) << 1));
	fl = (unsigned char)getub(buf, off) & 0xe0;
	(void)wmove(satwin, i + 2, 4);
	(void)wprintw(satwin, "%3u %3d %2d  %02d %02x %c",
		      p**n, az, el, ss, fl,
		      ((fl & 0x60) == 0x60) ? 'Y' : ' ');
    }
    (void)wnoutrefresh(satwin);
    return;
}
Example #3
0
static void display_nav_svinfo(unsigned char *buf, size_t data_len)
{
    int i, nchan;

    if (data_len < 152)
	return;

    nchan = (int)getub(buf, 4);
    if (nchan > 16)
	nchan = 16;

    for (i = 0; i < nchan; i++) {
	int off = 8 + 12 * i;
	unsigned char ss, prn;
	char el;
	short az;
	unsigned short fl;

	prn = (unsigned char)getub(buf, off + 1);
	fl = (unsigned short)getleu16(buf, off + 2);
	ss = (unsigned char)getub(buf, off + 4);
	el = (char)getsb(buf, off + 5);
	az = (short)getles16(buf, off + 6);
	(void)wmove(satwin, (int)(i + 2), 4);
	(void)wprintw(satwin, "%3d %3d %3d  %2d %04x %c",
		      prn, az, el, ss, fl, (fl & UBX_SAT_USED) ? 'Y' : ' ');
    }
    (void)wnoutrefresh(satwin);
    return;
}
Example #4
0
/*@ -duplicatequals +ignorequals @*/
int main(int argc, char *argv[])
{
    bool failures = false;
    bool quiet = (argc > 1) && (strcmp(argv[1], "--quiet") == 0);

    /*@ -observertrans -usereleased @*/
    struct unsigned_test *up, unsigned_tests[] = {
	/* tests using the big buffer */
	{buf, 0,  1,  0,    false, "first bit of first byte"},
	{buf, 0,  8,  0x01, false, "first 8 bits"},
	{buf, 32, 7,  0x02, false, "first seven bits of fifth byte (0x05)"},
	{buf, 56, 12, 0x8f, false, "12 bits crossing 7th to 8th bytes (0x08ff)"},
	{buf, 78, 4,  0xb, false, "4 bits crossing 8th to 9th byte (0xfefd)"},
	{buf, 0,  1,  0,    true,  "first bit of first byte"},
	{buf, 0,  8,  0x80, true,  "first 8 bits"},
	{buf, 32, 7,  0x20, true, "first seven bits of fifth byte (0x05)"},
	{buf, 56, 12, 0xf10,true, "12 bits crossing 7th to 8th bytes (0x08ff)"},
	{buf, 78, 4,  0xd,  true, "4 bits crossing 8th to 9th byte (0xfefd)"},
	/* sporadic tests based on found bugs */
	{(unsigned char *)"\x19\x23\f6",
	 7, 2, 2, false, "2 bits crossing 1st to 2nd byte (0x1923)"},
    };

    unsigned char *sp;

    memcpy(buf, "\x01\x02\x03\x04\x05\x06\x07\x08", 8);
    memcpy(buf + 8, "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8", 8);
    memcpy(buf + 16, "\x40\x09\x21\xfb\x54\x44\x2d\x18", 8);
    memcpy(buf + 24, "\x40\x49\x0f\xdb", 4);
    /*@ +observertrans +usereleased @*/

    /*@-type@*/
    sb1 = getsb(buf, 0);
    sb2 = getsb(buf, 8);
    ub1 = getub(buf, 0);
    ub2 = getub(buf, 8);
    sw1 = getbes16(buf, 0);
    sw2 = getbes16(buf, 8);
    uw1 = getbeu16(buf, 0);
    uw2 = getbeu16(buf, 8);
    sl1 = getbes32(buf, 0);
    sl2 = getbes32(buf, 8);
    ul1 = getbeu32(buf, 0);
    ul2 = getbeu32(buf, 8);
    sL1 = getbes64(buf, 0);
    sL2 = getbes64(buf, 8);
    uL1 = getbeu64(buf, 0);
    uL2 = getbeu64(buf, 8);
    f1 = getbef32((const char *)buf, 24);
    d1 = getbed64((const char *)buf, 16);
    sb1 = getsb(buf, 0);
    sb2 = getsb(buf, 8);
    ub1 = getub(buf, 0);
    ub2 = getub(buf, 8);
    sw1 = getles16(buf, 0);
    sw2 = getles16(buf, 8);
    uw1 = getleu16(buf, 0);
    uw2 = getleu16(buf, 8);
    sl1 = getles32(buf, 0);
    sl2 = getles32(buf, 8);
    ul1 = getleu32(buf, 0);
    ul2 = getleu32(buf, 8);
    sL1 = getles64(buf, 0);
    sL2 = getles64(buf, 8);
    uL1 = getleu64(buf, 0);
    uL2 = getleu64(buf, 8);
    f1 = getlef32((const char *)buf, 24);
    d1 = getled64((const char *)buf, 16);
    /*@+type@*/

    if (!quiet) {
	(void)fputs("Test data:", stdout);
	for (sp = buf; sp < buf + 28; sp++)
	    (void)printf(" %02x", *sp);
	(void)putc('\n', stdout);

	/* big-endian test */
	printf("Big-endian:\n");
	bedumpall();

	/* little-endian test */
	printf("Little-endian:\n");
	ledumpall();
    }

    if (sb1 != 1)  printf("getsb(buf, 0) FAILED\n");
    if (sb2 != -1) printf("getsb(buf, 8) FAILED\n");
    if (ub1 != 1)  printf("getub(buf, 0) FAILED\n");
    if (ub2 != 0xff) printf("getub(buf, 8) FAILED\n");

    (void)printf("Testing bitfield extraction\n");
    for (up = unsigned_tests;
	 up <
	 unsigned_tests + sizeof(unsigned_tests) / sizeof(unsigned_tests[0]);
	 up++) {
	uint64_t res = ubits((unsigned char *)buf, up->start, up->width, up->le);
	bool success = (res == up->expected);
	if (!success)
	    failures = true;
	if (!success || !quiet)
	    (void)printf("ubits(%s, %d, %d, %s) %s should be %" PRIx64 ", is %" PRIx64 ": %s\n",
			 hexdump(buf, strlen((char *)buf)),
			 up->start, up->width, up->le ? "true" : "false",
			 up->description, up->expected, res,
			 success ? "succeeded" : "FAILED");
    }

    exit(failures ? EXIT_FAILURE : EXIT_SUCCESS);
}
Example #5
0
int
main(int argc, char *argv[])
{
	char *special, *name, *mountpoint = NULL;
	struct stat64 st;
	int i, mountfd;
	int Aflag = 0;
	char *chg[2];
	int	opt;
	struct fiotune fiotune;


	if (argc < 3)
		usage();
	special = argv[argc - 1];

	/*
	 * For performance, don't search mnttab unless necessary
	 */

	if (stat64(special, &st) >= 0) {
		/*
		 * If mounted directory, search mnttab for special
		 */
		if ((st.st_mode & S_IFMT) == S_IFDIR) {
			if (st.st_ino == UFSROOTINO)
				searchmnttab(&special, &mountpoint);
		/*
		 * If mounted device, search mnttab for mountpoint
		 */
		} else if ((st.st_mode & S_IFMT) == S_IFBLK ||
			    (st.st_mode & S_IFMT) == S_IFCHR) {
				if (ustat(st.st_rdev, &ustatarea) >= 0)
					searchmnttab(&special, &mountpoint);
		}
	}
	/*
	 * Doesn't appear to be mounted; take ``unmounted'' path
	 */
	if (mountpoint == NULL)
		searchvfstab(&special);

	if ((special = getfullrawname(special)) == NULL) {
		fprintf(stderr, "tunefs: malloc failed\n");
		exit(32);
	}

	if (*special == '\0') {
		fprintf(stderr, "tunefs: Could not find raw device for %s\n",
		    argv[argc -1]);
		exit(32);
	}

	if (stat64(special, &st) < 0) {
		fprintf(stderr, "tunefs: "); perror(special);
		exit(31+1);
	}

	/*
	 * If a mountpoint has been found then we will ioctl() the file
	 * system instead of writing to the file system's device
	 */
	/* ustat() ok because max number of UFS inodes can fit in ino_t */
	if (ustat(st.st_rdev, &ustatarea) >= 0) {
		if (mountpoint == NULL) {
			printf("%s is mounted, can't tunefs\n", special);
			exit(32);
		}
	} else
		mountpoint = NULL;

	if ((st.st_mode & S_IFMT) != S_IFBLK &&
	    (st.st_mode & S_IFMT) != S_IFCHR)
		fatal("%s: not a block or character device", special);
	getsb(&sblock, special);
	while ((opt = getopt(argc, argv, "o:m:e:d:a:AV")) != EOF) {
		switch (opt) {

		case 'A':
			Aflag++;
			continue;

		case 'a':
			name = "maximum contiguous block count";
			if (!isnumber(optarg))
				fatal("%s: %s must be >= 1", *argv, name);
			i = atoi(optarg);
			if (i < 1)
				fatal("%s: %s must be >= 1", *argv, name);
			fprintf(stdout, "%s changes from %d to %d\n",
				name, sblock.fs_maxcontig, i);
			sblock.fs_maxcontig = i;
			continue;

		case 'd':
			sblock.fs_rotdelay = 0;
			continue;

		case 'e':
			name =
			    "maximum blocks per file in a cylinder group";
			if (!isnumber(optarg))
				fatal("%s: %s must be >= 1", *argv, name);
			i = atoi(optarg);
			if (i < 1)
				fatal("%s: %s must be >= 1", *argv, name);
			fprintf(stdout, "%s changes from %d to %d\n",
				name, sblock.fs_maxbpg, i);
			sblock.fs_maxbpg = i;
			continue;

		case 'm':
			name = "minimum percentage of free space";
			if (!isnumber(optarg))
				fatal("%s: bad %s", *argv, name);
			i = atoi(optarg);
			if (i < 0 || i > 99)
				fatal("%s: bad %s", *argv, name);
			fprintf(stdout,
				"%s changes from %d%% to %d%%\n",
				name, sblock.fs_minfree, i);
			sblock.fs_minfree = i;
			continue;

		case 'o':
			name = "optimization preference";
			chg[FS_OPTSPACE] = "space";
			chg[FS_OPTTIME] = "time";
			if (strcmp(optarg, chg[FS_OPTSPACE]) == 0)
				i = FS_OPTSPACE;
			else if (strcmp(optarg, chg[FS_OPTTIME]) == 0)
				i = FS_OPTTIME;
			else
			fatal("%s: bad %s (options are `space' or `time')",
					optarg, name);
			if (sblock.fs_optim == i) {
				fprintf(stdout,
					"%s remains unchanged as %s\n",
					name, chg[i]);
				continue;
			}
			fprintf(stdout,
				"%s changes from %s to %s\n",
				name, chg[sblock.fs_optim], chg[i]);
			sblock.fs_optim = i;
			continue;

		case 'V':
			{
				char	*opt_text;
				int	opt_count;

				(void) fprintf(stdout, "tunefs -F ufs ");
				for (opt_count = 1; opt_count < argc;
				    opt_count++) {
					opt_text = argv[opt_count];
					if (opt_text)
						(void) fprintf(stdout, " %s ",
						    opt_text);
				}
				(void) fprintf(stdout, "\n");
			}
			break;

		default:
			usage();
		}
	}
	if ((argc - optind) != 1)
		usage();
	if (mountpoint) {
		mountfd = open(mountpoint, O_RDONLY);
		if (mountfd == -1) {
			perror(mountpoint);
			fprintf(stderr,
				"tunefs: can't tune %s\n", mountpoint);
			exit(32);
		}
		fiotune.maxcontig = sblock.fs_maxcontig;
		fiotune.rotdelay = sblock.fs_rotdelay;
		fiotune.maxbpg = sblock.fs_maxbpg;
		fiotune.minfree = sblock.fs_minfree;
		fiotune.optim = sblock.fs_optim;
		if (ioctl(mountfd, _FIOTUNE, &fiotune) == -1) {
			perror(mountpoint);
			fprintf(stderr,
				"tunefs: can't tune %s\n", mountpoint);
			exit(32);
		}
		close(mountfd);
	} else {
		bwrite((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE);

		if (Aflag)
			for (i = 0; i < sblock.fs_ncg; i++)
				bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
				    (char *)&sblock, SBSIZE);
	}

	close(fi);
	return (0);
}
Example #6
0
int
main(int argc, char **argv)
{
	char *cp, *special;
	const char *name, *action;
	struct stat st;
	int i;
	int Aflag = 0, active = 0;
	struct fstab *fs;
	const char *chg[2];
	char device[MAXPATHLEN];
	struct ufs_args args;
	struct statfs stfs;

	argc--, argv++;
	if (argc < 2)
		usage();
	special = argv[argc - 1];
	fs = getfsfile(special);
	if (fs) {
		if (statfs(special, &stfs) == 0 &&
		    strcmp(special, stfs.f_mntonname) == 0) {
			active = 1;
		}
		special = fs->fs_spec;
	}
again:
	if (stat(special, &st) < 0) {
		if (*special != '/') {
			if (*special == 'r')
				special++;
			snprintf(device, sizeof(device), "%s%s",
				 _PATH_DEV, special);
			special = device;
			goto again;
		}
		err(1, "%s", special);
	}
	if (fs == NULL && (st.st_mode & S_IFMT) == S_IFDIR)
		errx(10, "%s: unknown file system", special);
	getsb(&sblock, special);
	for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
		for (cp = &argv[0][1]; *cp; cp++)
			switch (*cp) {

			case 'A':
				Aflag++;
				continue;

			case 'p':
				printfs();
				exit(0);

			case 'a':
				name = "maximum contiguous block count";
				if (argc < 1)
					errx(10, "-a: missing %s", name);
				argc--, argv++;
				i = atoi(*argv);
				if (i < 1)
					errx(10, "%s must be >= 1 (was %s)",
					    name, *argv);
				warnx("%s changes from %d to %d",
				    name, sblock.fs_maxcontig, i);
				sblock.fs_maxcontig = i;
				continue;

			case 'd':
				name =
				   "rotational delay between contiguous blocks";
				if (argc < 1)
					errx(10, "-d: missing %s", name);
				argc--, argv++;
				i = atoi(*argv);
				warnx("%s changes from %dms to %dms",
				    name, sblock.fs_rotdelay, i);
				sblock.fs_rotdelay = i;
				continue;

			case 'e':
				name =
				  "maximum blocks per file in a cylinder group";
				if (argc < 1)
					errx(10, "-e: missing %s", name);
				argc--, argv++;
				i = atoi(*argv);
				if (i < 1)
					errx(10, "%s must be >= 1 (was %s)",
					    name, *argv);
				warnx("%s changes from %d to %d",
				    name, sblock.fs_maxbpg, i);
				sblock.fs_maxbpg = i;
				continue;

			case 'f':
				name = "average file size";
				if (argc < 1)
					errx(10, "-a: missing %s", name);
				argc--, argv++;
				i = atoi(*argv);
				if (i < 1)
					errx(10, "%s must be >= 1 (was %s)", name, *argv);
				if (sblock.fs_avgfilesize == i) {
					warnx("%s remains unchanged as %d",
						name, i);
				} else {
					warnx("%s changes from %d to %d",
						name, sblock.fs_avgfilesize, i);
					sblock.fs_avgfilesize = i;
				}
				break;

			case 'm':
				name = "minimum percentage of free space";
				if (argc < 1)
					errx(10, "-m: missing %s", name);
				argc--, argv++;
				i = atoi(*argv);
				if (i < 0 || i > 99)
					errx(10, "bad %s (%s)", name, *argv);
				warnx("%s changes from %d%% to %d%%",
				    name, sblock.fs_minfree, i);
				sblock.fs_minfree = i;
				if (i >= MINFREE &&
				    sblock.fs_optim == FS_OPTSPACE)
					warnx(OPTWARN, "time", ">=", MINFREE);
				if (i < MINFREE &&
				    sblock.fs_optim == FS_OPTTIME)
					warnx(OPTWARN, "space", "<", MINFREE);
				continue;

			case 'n':
 				name = "soft updates";
 				if (argc < 1)
 					errx(10, "-n: missing %s", name);
 				argc--, argv++;
 				if (strcmp(*argv, "enable") == 0) {
 					sblock.fs_flags |= FS_DOSOFTDEP;
 					action = "set";
 				} else if (strcmp(*argv, "disable") == 0) {
 					sblock.fs_flags &= ~FS_DOSOFTDEP;
 					action = "cleared";
 				} else {
 					errx(10, "bad %s (options are %s)",
 					    name, "`enable' or `disable'");
 				}
 				warnx("%s %s", name, action);
 				continue;
 
			case 'o':
				name = "optimization preference";
				if (argc < 1)
					errx(10, "-o: missing %s", name);
				argc--, argv++;
				chg[FS_OPTSPACE] = "space";
				chg[FS_OPTTIME] = "time";
				if (strcmp(*argv, chg[FS_OPTSPACE]) == 0)
					i = FS_OPTSPACE;
				else if (strcmp(*argv, chg[FS_OPTTIME]) == 0)
					i = FS_OPTTIME;
				else
					errx(10, "bad %s (options are `space' or `time')",
					    name);
				if (sblock.fs_optim == i) {
					warnx("%s remains unchanged as %s",
					    name, chg[i]);
					continue;
				}
				warnx("%s changes from %s to %s",
				    name, chg[sblock.fs_optim], chg[i]);
				sblock.fs_optim = i;
				if (sblock.fs_minfree >= MINFREE &&
				    i == FS_OPTSPACE)
					warnx(OPTWARN, "time", ">=", MINFREE);
				if (sblock.fs_minfree < MINFREE &&
				    i == FS_OPTTIME)
					warnx(OPTWARN, "space", "<", MINFREE);
				continue;

			case 's':
				name = "expected number of files per directory";
				if (argc < 1)
					errx(10, "-a: missing %s", name);
				argc--, argv++;
				i = atoi(*argv);
				if (i < 1)
					errx(10, "%s must be >= 1 (was %s)", name, *argv);
				if (sblock.fs_avgfpdir == i) {
					warnx("%s remains unchanged as %d",
						name, i);
				} else {
					warnx("%s changes from %d to %d",
						name, sblock.fs_avgfpdir, i);
					sblock.fs_avgfpdir = i;
				}
				break;

			default:
				usage();
			}
	}
	if (argc != 1)
		usage();
	putsb(&sblock, special, Aflag);
	if (active) {
		bzero(&args, sizeof(args));
		if (mount("ufs", fs->fs_file,
		    stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0)
			err(9, "%s: reload", special);
		warnx("file system reloaded");
	}
	exit(0);
}
Example #7
0
int
main(int argc, char *argv[])
{
#define	OPTSTRING	"AFNe:g:h:m:o:"
    int		i, ch, Aflag, Fflag, Nflag, openflags;
    char		*special;
    const char	*chg[2];
    int		maxbpg, minfree, optim;
    int		avgfilesize, avgfpdir;

    Aflag = Fflag = Nflag = 0;
    maxbpg = minfree = optim = -1;
    avgfilesize = avgfpdir = -1;
    chg[FS_OPTSPACE] = "space";
    chg[FS_OPTTIME] = "time";

    while ((ch = getopt(argc, argv, OPTSTRING)) != -1) {
        switch (ch) {

        case 'A':
            Aflag++;
            break;

        case 'F':
            Fflag++;
            break;

        case 'N':
            Nflag++;
            break;

        case 'e':
            maxbpg = getnum(optarg,
                            "maximum blocks per file in a cylinder group",
                            1, INT_MAX);
            break;

        case 'g':
            avgfilesize = getnum(optarg,
                                 "average file size", 1, INT_MAX);
            break;

        case 'h':
            avgfpdir = getnum(optarg,
                              "expected number of files per directory",
                              1, INT_MAX);
            break;

        case 'm':
            minfree = getnum(optarg,
                             "minimum percentage of free space", 0, 99);
            break;

        case 'o':
            if (strcmp(optarg, chg[FS_OPTSPACE]) == 0)
                optim = FS_OPTSPACE;
            else if (strcmp(optarg, chg[FS_OPTTIME]) == 0)
                optim = FS_OPTTIME;
            else
                errx(10,
                     "bad %s (options are `space' or `time')",
                     "optimization preference");
            break;

        default:
            usage();
        }
    }
    argc -= optind;
    argv += optind;
    if (argc != 1)
        usage();

    special = argv[0];
    openflags = Nflag ? O_RDONLY : O_RDWR;
#ifndef _LINUX_PORT
    if (Fflag)
        fi = open(special, openflags);
    else
        fi = openpartition(special, openflags, &special);
#else
    fi = open(special, openflags);
#endif /* _LINUX_PORT */
    if (fi == -1)
        err(1, "%s", special);
    getsb(&sblock, special);

#define CHANGEVAL(old, new, type, suffix) do				\
	if ((new) != -1) {						\
		if ((new) == (old))					\
			warnx("%s remains unchanged at %d%s",		\
			    (type), (old), (suffix));			\
		else {							\
			warnx("%s changes from %d%s to %d%s",		\
			    (type), (old), (suffix), (new), (suffix));	\
			(old) = (new);					\
		}							\
	} while (/* CONSTCOND */0)

    warnx("tuning %s", special);
    CHANGEVAL(sblock.fs_maxbpg, maxbpg,
              "maximum blocks per file in a cylinder group", "");
    CHANGEVAL(sblock.fs_minfree, minfree,
              "minimum percentage of free space", "%");
    if (minfree != -1) {
        if (minfree >= MINFREE &&
                sblock.fs_optim == FS_OPTSPACE)
            warnx(OPTWARN, "time", ">=", MINFREE);
        if (minfree < MINFREE &&
                sblock.fs_optim == FS_OPTTIME)
            warnx(OPTWARN, "space", "<", MINFREE);
    }
    if (optim != -1) {
        if (sblock.fs_optim == optim) {
            warnx("%s remains unchanged as %s",
                  "optimization preference",
                  chg[optim]);
        } else {
            warnx("%s changes from %s to %s",
                  "optimization preference",
                  chg[sblock.fs_optim], chg[optim]);
            sblock.fs_optim = optim;
            if (sblock.fs_minfree >= MINFREE &&
                    optim == FS_OPTSPACE)
                warnx(OPTWARN, "time", ">=", MINFREE);
            if (sblock.fs_minfree < MINFREE &&
                    optim == FS_OPTTIME)
                warnx(OPTWARN, "space", "<", MINFREE);
        }
    }
    CHANGEVAL(sblock.fs_avgfilesize, avgfilesize,
              "average file size", "");
    CHANGEVAL(sblock.fs_avgfpdir, avgfpdir,
              "expected number of files per directory", "");

    if (Nflag) {
        fprintf(stdout, "tunefs: current settings of %s\n", special);
        fprintf(stdout, "\tmaximum contiguous block count %d\n",
                sblock.fs_maxcontig);
        fprintf(stdout,
                "\tmaximum blocks per file in a cylinder group %d\n",
                sblock.fs_maxbpg);
        fprintf(stdout, "\tminimum percentage of free space %d%%\n",
                sblock.fs_minfree);
        fprintf(stdout, "\toptimization preference: %s\n",
                chg[sblock.fs_optim]);
        fprintf(stdout, "\taverage file size: %d\n",
                sblock.fs_avgfilesize);
        fprintf(stdout,
                "\texpected number of files per directory: %d\n",
                sblock.fs_avgfpdir);
        fprintf(stdout, "tunefs: no changes made\n");
        exit(0);
    }

    memcpy(buf, (char *)&sblock, SBLOCKSIZE);
    bwrite(sblockloc, buf, SBLOCKSIZE, special);
    if (Aflag)
        for (i = 0; i < sblock.fs_ncg; i++)
            bwrite(fsbtodb(&sblock, cgsblock(&sblock, i)),
                   buf, SBLOCKSIZE, special);
    close(fi);
    exit(0);
}