⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 format.c

📁 操作系统源代码
💻 C
字号:
/*	format 1.1 - format PC floppy disk		Author: Kees J. Bot *								5 Mar 1994 */#define nil 0#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <time.h>#include <errno.h>#include <limits.h>#include <ibm/diskparm.h>#include <minix/minlib.h>/* Constants. */#define SECTOR_SIZE	512#define NR_HEADS	  2#define MAX_SECTORS	 18	/* 1.44Mb is the largest. *//* Name error in <ibm/diskparm.h>, left over from the days floppies were * single sided. */#define sectors_per_track	sectors_per_cylinder/* From floppy device number to drive/type/format-bit and back.  See fd(4). */#define isfloppy(dev)		(((dev) & 0xFF00) == 0x0200)#define fl_drive(dev)		(((dev) & 0x0003) >> 0)#define fl_type(dev)		(((dev) & 0x007C) >> 2)#define fl_format(dev)		(((dev) & 0x0080) >> 7)#define fl_makedev(drive, type, fmt)	\	((dev_t) (0x0200 | ((fmt) << 7) | ((type) << 2) | ((drive) << 0)))/* Recognize floppy types. */#define NR_TYPES		7	/* # non-auto types */#define isflauto(type)		((type) == 0)#define isfltyped(type)		((unsigned) ((type) - 1) < NR_TYPES)#define isflpart(type)		((unsigned) (type) >= 28)/* Formatting parameters per type.  (Most of these parameters have no use * for formatting, disk_parameter_s probably matches a BIOS parameter table.) */typedef struct disk_parameter_s	fmt_params_t;typedef struct type_parameters {	unsigned		media_size;	unsigned		drive_size;	fmt_params_t		fmt_params;} type_parameters_t;#define DC	0	/* Don't care. */type_parameters_t parameters[NR_TYPES] = {	/* mediasize       s1     off   sec/cyl  dlen       fill    start */	/*       drivesize     s2   sizecode  gap    fmtgap     settle    */  /* pc */ {  360,  360, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},  /* at */ { 1200, 1200, { DC, DC, DC, 2, 15, DC, DC, 0x54, 0xF6, DC, DC }},  /* qd */ {  360,  720, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},  /* ps */ {  720,  720, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},  /* pat */{  360, 1200, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},  /* qh */ {  720, 1200, { DC, DC, DC, 2,  9, DC, DC, 0x50, 0xF6, DC, DC }},  /* PS */ { 1440, 1440, { DC, DC, DC, 2, 18, DC, DC, 0x54, 0xF6, DC, DC }},};/* Per sector ID to be sent to the controller by the driver. */typedef struct sector_id {	unsigned char	cyl;	unsigned char	head;	unsigned char	sector;	unsigned char	sector_size_code;} sector_id_t;/* Data to be "written" to the driver to format a track.  (lseek to the track * first.)  The first sector contains sector ID's, the second format params. */typedef struct track_data {	sector_id_t	sec_ids[SECTOR_SIZE / sizeof(sector_id_t)];	fmt_params_t	fmt_params;	char		padding[SECTOR_SIZE - sizeof(fmt_params_t)];} track_data_t;void report(const char *label){	fprintf(stderr, "format: %s: %s\n", label, strerror(errno));}void fatal(const char *label){	report(label);	exit(1);}void format_track(int ffd, unsigned type, unsigned cyl, unsigned head)/* Format a single track on a floppy. */{	type_parameters_t *tparams= &parameters[type - 1];	track_data_t track_data;	off_t track_pos;	unsigned sector;	unsigned nr_sectors= tparams->fmt_params.sectors_per_track;	sector_id_t *sid;	memset(&track_data, 0, sizeof(track_data));	/* Set the sector id's.  (Note that sectors count from 1.) */	for (sector= 0; sector <= nr_sectors; sector++) {		sid= &track_data.sec_ids[sector];		sid->cyl= cyl;		sid->head= head;		sid->sector= sector + 1;		sid->sector_size_code= tparams->fmt_params.sector_size_code;	}	/* Format parameters. */	track_data.fmt_params= tparams->fmt_params;	/* Seek to the right track. */	track_pos= (off_t) (cyl * NR_HEADS + head) * nr_sectors * SECTOR_SIZE;	if (lseek(ffd, track_pos, SEEK_SET) == -1) {		fprintf(stderr,		"format: seeking to cyl %u, head %u (pos %ld) failed: %s\n",			cyl, head, track_pos, strerror(errno));		exit(1);	}	/* Format track. */	if (write(ffd, &track_data, sizeof(track_data)) < 0) {		fprintf(stderr,			"format: formatting cyl %d, head %d failed: %s\n",			cyl, head, strerror(errno));		exit(1);	}}void verify_track(int vfd, unsigned type, unsigned cyl, unsigned head)/* Verify a track by reading it.  On error read sector by sector. */{	type_parameters_t *tparams= &parameters[type - 1];	off_t track_pos;	unsigned sector;	unsigned nr_sectors= tparams->fmt_params.sectors_per_track;	size_t track_bytes;	static char buf[MAX_SECTORS * SECTOR_SIZE];	static unsigned bad_count;	/* Seek to the right track. */	track_pos= (off_t) (cyl * NR_HEADS + head) * nr_sectors * SECTOR_SIZE;	if (lseek(vfd, track_pos, SEEK_SET) == -1) {		fprintf(stderr,		"format: seeking to cyl %u, head %u (pos %ld) failed: %s\n",			cyl, head, track_pos, strerror(errno));		exit(1);	}	/* Read the track whole. */	track_bytes= nr_sectors * SECTOR_SIZE;	if (read(vfd, buf, track_bytes) == track_bytes) return;	/* An error occurred, retry sector by sector. */	for (sector= 0; sector < nr_sectors; sector++) {		if (lseek(vfd, track_pos, SEEK_SET) == -1) {			fprintf(stderr,	"format: seeking to cyl %u, head %u, sector %u (pos %ld) failed: %s\n",				cyl, head, sector, track_pos, strerror(errno));			exit(1);		}		switch (read(vfd, buf, SECTOR_SIZE)) {		case -1:			fprintf(stderr,		"format: bad sector at cyl %u, head %u, sector %u (pos %ld)\n",				cyl, head, sector, track_pos);			bad_count++;			break;		case SECTOR_SIZE:			/* Fine. */			break;		default:			fprintf(stderr, "format: short read at pos %ld\n",				track_pos);			bad_count++;		}		track_pos+= SECTOR_SIZE;		if (bad_count >= nr_sectors) {	fprintf(stderr, "format: too many bad sectors, floppy unusable\n");			exit(1);		}	}}void format_device(unsigned drive, unsigned type, int verify){	int ffd, vfd;	char *fmt_dev, *ver_dev;	struct stat st;	unsigned cyl, head;	unsigned nr_cyls;	type_parameters_t *tparams= &parameters[type - 1];	int verbose= isatty(1);	fmt_dev= tmpnam(nil);	if (mknod(fmt_dev, S_IFCHR | 0700, fl_makedev(drive, type, 1)) < 0) {		fprintf(stderr, "format: making format device failed: %s\n",			strerror(errno));		exit(1);	}	if ((ffd= open(fmt_dev, O_WRONLY)) < 0 || fstat(ffd, &st) < 0) {		report(fmt_dev);		(void) unlink(fmt_dev);		exit(1);	}	(void) unlink(fmt_dev);	if (st.st_rdev != fl_makedev(drive, type, 1)) {		/* Someone is trying to trick me. */		exit(1);	}	if (verify) {		ver_dev= tmpnam(nil);		if (mknod(ver_dev, S_IFCHR | 0700, fl_makedev(drive, type, 0))									< 0) {			fprintf(stderr,				"format: making verify device failed: %s\n",				strerror(errno));			exit(1);		}		if ((vfd= open(ver_dev, O_RDONLY)) < 0) {			report(ver_dev);			(void) unlink(ver_dev);			exit(1);		}		(void) unlink(ver_dev);	}	nr_cyls= tparams->media_size * (1024 / SECTOR_SIZE) / NR_HEADS				/ tparams->fmt_params.sectors_per_track;	if (verbose) {		printf("Formatting a %uk diskette in a %uk drive\n",			tparams->media_size, tparams->drive_size);	}	for (cyl= 0; cyl < nr_cyls; cyl++) {		for (head= 0; head < NR_HEADS; head++) {			if (verbose) {				printf(" Cyl. %2u, Head %u\r", cyl, head);				fflush(stdout);			}#if __minix_vmd			/* After formatting a track we are too late to format			 * the next track.  So we can sleep at most 1/6 sec to			 * allow the above printf to get displayed before we			 * lock Minix into the floppy driver again.			 */			usleep(50000);	/* 1/20 sec will do. */#endif			format_track(ffd, type, cyl, head);			if (verify) verify_track(vfd, type, cyl, head);		}	}	if (verbose) fputc('\n', stdout);}void usage(void){	fprintf(stderr,		"Usage: format [-v] <device> [<media size> [<drive size>]]\n");	exit(1);}int main(int argc, char **argv){	char *device;	unsigned drive;	unsigned type;	unsigned media_size;	unsigned drive_size;	int verify= 0;	struct stat st;	FILE *mfp;	char special[PATH_MAX + 1], mounted_on[PATH_MAX + 1];	char version[10], rw_flag[10];	/* Option -v. */	while (argc > 1 && argv[1][0] == '-') {		char *p;		for (p= argv[1]; *p == '-' || *p == 'v'; p++) {			if (*p == 'v') verify= 1;		}		if (*p != 0) usage();		argc--;		argv++;		if (strcmp(argv[0], "--") == 0) break;	}	if (argc < 2 || argc > 4) usage();	/* Check if the caller has read-write permission.  Use the access()	 * call to check with the real uid & gid.  This program is usually	 * set-uid root.	 */	device= argv[1];	if (access(device, R_OK|W_OK) < 0 || stat(device, &st) < 0)		fatal(device);	if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))						|| !isfloppy(st.st_rdev)) {		fprintf(stderr, "format: %s: not a floppy device\n", device);		exit(1);	}	drive= fl_drive(st.st_rdev);	type= fl_type(st.st_rdev);	/* The drive should not be mounted. */	if (load_mtab("mkfs") < 0) return;	while (get_mtab_entry(special, mounted_on, version, rw_flag) == 0) {		if (stat(special, &st) >= 0 && isfloppy(st.st_rdev)					&& fl_drive(st.st_rdev) == drive) {			fprintf(stderr, "format: %s is mounted on %s\n",				device, mounted_on);			exit(1);		}	}	if (isflauto(type)) {		/* Auto type 0 requires size(s). */		unsigned long lmedia, ldrive;		char *end;		if (argc < 3) {			fprintf(stderr,			"format: no size specified for auto floppy device %s\n",				device);			usage();		}		lmedia= strtoul(argv[2], &end, 10);		if (end == argv[2] || *end != 0 || lmedia > 20 * 1024)			usage();		if (argc == 4) {			ldrive= strtoul(argv[3], &end, 10);			if (end == argv[3] || *end != 0 || ldrive > 20 * 1024)				usage();		} else {			ldrive= lmedia;		}		/* Silently correct wrong ordered sizes. */		if (lmedia > ldrive) {			media_size= ldrive;			drive_size= lmedia;		} else {			media_size= lmedia;			drive_size= ldrive;		}		/* A 1.44M drive can do 720k diskettes with no extra tricks.		 * Diddle with the 720k params so it is found.		 */		if (media_size == 720 && drive_size == 1440)			parameters[4 - 1].drive_size= 1440;		/* Translate the auto type to a known type. */		for (type= 1; type <= NR_TYPES; type++) {			if (parameters[type - 1].media_size == media_size				&& parameters[type - 1].drive_size == drive_size			) break;		}		if (!isfltyped(type)) {			fprintf(stderr,			"format: can't format a %uk floppy in a %uk drive\n",				media_size, drive_size);			exit(1);		}	} else	if (isfltyped(type)) {		/* No sizes needed for a non-auto type. */		if (argc > 2) {			fprintf(stderr,	"format: no sizes need to be specified for non-auto floppy device %s\n",				device);			usage();		}	} else	if (isflpart(type)) {		fprintf(stderr,			"format: floppy partition %s can't be formatted\n",			device);		exit(1);	} else {		fprintf(stderr,			"format: %s: can't format strange type %d\n",			device, type);	}	format_device(drive, type, verify);	exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -