2.9BSD/usr/src/ucb/bad144.c

Compare this file to the similar file:
Show the results in this format:

/*
 * bad144
 *
 * This program prints and/or initializes a bad block record for a pack,
 * in the format used by the DEC standard 144.
 *
 * BUGS:
 *	Only reads/writes the first of the bad block record (sector 0
 *	of the last track of the disk); in fact, there are copies
 *	of the information in the first 5 even numbered sectors of this
 *	track, but UNIX uses only the first, and we don't bother with the
 *	others.
 *
 * It is preferable to write the bad information with a standard formatter,
 * but this program will do in a pinch, e.g. if the bad information is
 * accidentally wiped out this is a much faster way of restoring it than
 * reformatting.  To add a new bad sector the formatter must be used in
 * general since UNIX doesn't have on-line formatters to write the BSE
 * error in the header.
 */
#include <whoami.h>
#ifndef	BADSECT
#define BADSECT
#endif
#include <sys/types.h>
#include <sys/dkbad.h>
#include <stdio.h>

struct diskinfo {
	char	*di_type;	/* type name of disk */
	daddr_t	di_size;	/* size of entire volume in sectors */
	int	di_nsect;	/* sectors per track */
	int	di_ntrak;	/* tracks per cylinder */
} diskinfo[] = {
	"rk06",		22*3*411L,	22,	3,
	"rk07",		22*3*815L,	22,	3,
	"rm02",		32*5*823L,	32,	5,
	"rm03",		32*5*823L,	32,	5,
	"rm05",		32*19*823L,	32,	19,
	"rp06",		22*19*815L,	22,	19,
	"rm80",		31*14*559L,	31,	14,
	"rp05",		22*19*411L,	22,	19,
	"rp07",		50*32*630L,	50,	32,
	0,
};
union {
	struct	dkbad bad;
	char	buf[512];
} dkbad;
long tell();
long atol();

main(argc, argv)
	int argc;
	char **argv;
{
	register struct diskinfo *di;
	register struct bt_b *bt;
	char name[BUFSIZ];
	int i, f, errs;
	daddr_t bad;
	int toomany = 0;

	argc--, argv++;
	if (argc < 2) {
		fprintf(stderr, "usage: bad type disk [ snum [ bn ... ] ]\n");
		fprintf(stderr, "e.g.: bad rk07 hk0\n");
		exit(1);
	}
	for (di = diskinfo; di->di_type; di++)
		if (!strcmp(di->di_type, argv[0]))
			goto found;
	fprintf(stderr, "%s: not a known disk type\n", argv[0]);
	fprintf(stderr, "known types:");
	for (di = diskinfo; di->di_type; di++)
		fprintf(stderr, " %s", di->di_type);
	fprintf(stderr, "\n");
	exit(1);
found:
	sprintf(name, "/dev/r%sh", argv[1]);
	argc -= 2;
	argv += 2;
	if (argc == 0) {
		f = open(name, 0);
		if (f < 0) {
			perror(name);
			exit(1);
		}
		lseek(f, 512 * (di->di_size - di->di_nsect), 0);
		printf("bad block information at 0x%X in %s:\n",
		    tell(f), name);
		if (read(f, &dkbad, 512) != 512) {
			fprintf(stderr, "%s: can't read bad block info (wrong type disk?)\n", name);
			exit(1);
		}
		printf("cartridge serial number: %D(10)\n", dkbad.bad.bt_csn);
		switch (dkbad.bad.bt_flag) {
		case -1:
			printf("alignment cartridge\n");
			break;
		case 0:
			break;
		default:
			printf("bt_flag=%x(16)?\n", dkbad.bad.bt_flag);
			break;
		}
		bt = dkbad.bad.bt_bad;
		for (i = 0; i < 126; i++) {
			bad = ((daddr_t)bt->bt_cyl<<16) + bt->bt_trksec;
			if (bad < 0)
				break;
			if (!toomany && i >= MAXBAD) {
				toomany++;
	printf("More bad sectors than system supports.\n");
	printf("The remainder are not being replaced automatically...\n");
			}
			printf("sn=%D, cn=%d, tn=%d, sn=%d\n",
			    ((daddr_t)bt->bt_cyl*di->di_ntrak + (bt->bt_trksec>>8)) *
				di->di_nsect + (bt->bt_trksec&0xff),
			    bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
			bt++;
		}
		exit (0);
	}
	f = open(name, 1);
	if (f < 0) {
		perror(name);
		exit(1);
	}
	dkbad.bad.bt_csn = atol(*argv++);
	argc--;
	dkbad.bad.bt_mbz = 0;
	if (argc > 2 * di->di_nsect || argc > MAXBAD) {
		printf("bad: too many bad sectors specified\n");
		if (argc > MAXBAD)
		 printf("system is currently configured for only %d\n", MAXBAD);
		else
			printf("limited to %d (only 2 tracks of sectors)\n",
			    2 * di->di_nsect);
		if (2 * di->di_nsect > 126)
			printf("limited to 126 by information format\n");
		exit(1);
	}
	errs = 0;
	i = 0;
	while (argc > 0) {
		long sn = atol(*argv++);
		argc--;
		if (sn < 0 || sn >= di->di_size) {
			printf("%d: out of range [0,%d) for %s\n",
			    sn, di->di_size, di->di_type);
			errs++;
		}
		dkbad.bad.bt_bad[i].bt_cyl = sn / (di->di_nsect*di->di_ntrak);
		sn %= (di->di_nsect*di->di_ntrak);
		dkbad.bad.bt_bad[i].bt_trksec =
		    ((sn/di->di_nsect) << 8) + (sn%di->di_nsect);
		i++;
	}
	while (i < 126) {
		dkbad.bad.bt_bad[i].bt_trksec = -1;
		dkbad.bad.bt_bad[i].bt_cyl = -1;
		i++;
	}
	if (errs)
		exit(1);
	lseek(f, 512 * (di->di_size - di->di_nsect), 0);
	if (write(f, (caddr_t)&dkbad, 512) != 512) {
		perror(name);
		exit(1);
	}
	exit(0);
}