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

📄 dd.c

📁 一个类linux的dos下开发的操作系统.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
- dd_write() should do the Right Thing when write
	ends in the middle of a block

>>>- testing
	Turbo C 2.0, Turbo C 3.0, DJGPP
	486 system, Pentium system
	plain DOS, DOS w/ SMARTDRV, Windows DOS box
	1.44 meg disks, 1.68 meg disks
	random things: initial offset, whole middle blocks, terminal offset
>>>- faster?

later:
- need zero-fill if reading beyond end of disk?
- support hard drive (entire drive and partitions)
*****************************************************************************/
#include <stdlib.h> /* atol(), malloc(), free() */
#include <string.h> /* NULL, movedata(), memset(), strlen(), memicmp() */
#include <ctype.h> /* isalpha(), toupper(), tolower() */
#include <stdio.h> /* printf() */
#include <fcntl.h> /* O_nnn */
#include <bios.h> /* _DISK_..., biosdisk() */
#include <dos.h> /* union REGS, int86(), peek(), poke(), pokeb() */
#include <io.h> /* open(), lseek(), tell(), read(), write(), close() */

#if defined(__DJGPP__)
#include <unistd.h> /* all of the io.h functions except tell() */
#include <sys/farptr.h> /* _far...() */
#include <dpmi.h> /* __dpmi... */
#include <go32.h> /* _dos_ds */

/* the nice thing about standards is... */
#define	to_linear(S,O)	(((unsigned long)(S) << 4) + O)
#define	peek(S,O)	_farpeekw(_dos_ds, to_linear(S,O))
#define	poke(S,O,V)	_farpokew(_dos_ds, to_linear(S,O), V)
#define	pokeb(S,O,V)	_farpokeb(_dos_ds, to_linear(S,O), V)
#define	my_movedata(SS,SO,DS,DO,C) 				\
			movedata(_dos_ds, to_linear(SS,SO),	\
				_dos_ds, to_linear(DS,DO), C)
#define	dos_int(N,R)	__dpmi_int(N,R)

typedef __dpmi_regs regs_t;

#elif defined(__TURBOC__)
#define	my_movedata(SS,SO,DS,DO,C)	\
			movedata(SS,SO,DS,DO,C)
#define	dos_int(N,R)	int86(N,R,R)

typedef union REGS regs_t;

#else
#error Not DJGPP, not Turbo C. Sorry.
#endif

#if 0
#define	DEBUG(X)	X
#else
#define	DEBUG(X)
#endif

#define	BUFLEN	8192

#define	false	0
#define	true	1

typedef unsigned char	bool;

typedef struct
{
	unsigned is_device : 1;
	unsigned needs_fill : 1;
	unsigned needs_flush : 1;
	unsigned long size;
/* read/write position */
	unsigned short curr_blk, curr_off;
/* block buffer */
	unsigned short buf_size;/* max number of bytes in buffer */
	unsigned char *buf;	/* base address of buffer */
/* used if input/output is a regular file */
	int handle;
/* use if input/output is a block device */
	unsigned char int13_dev;
	unsigned short cyls, sects, heads, bps;
} file_t;

static const char *_usage =
"\n"
"dd for DOS, version 0.3     http://www.execpc.com/~geezer/os\n"
"Performs low-level byte-wise copying between files and floppies.\n"
"Usage:\n"
"          dd count=... skip=... seek=... if=... of=... probe\n"
"count=number of bytes to copy           (default: size of input)\n"
"skip =number of input bytes to skip     (default: 0)\n"
"seek =number of output bytes to skip    (default: 0)\n"
"if   =input file or drive\n"
"of   =output file or drive\n"
"  Examples:\n"
"    dd count=512 if=boot.bin of=a:      (install bootloader)\n"
"    dd  skip=512 if=boot.bin of=a:\\loader.bin\n"
"    dd skip=18K count=18K if=a: of=d:t1 (copy 2nd track of 1.44M disk)\n"
"    dd count=5k if=a: of=c:save         (backup boot sector and 1st FAT)\n"
"    dd skip=100 count=100 if=foo of=bar (pick out second 100 bytes of file)\n"
"    dd if=image of=b:                   (RAWRITE)\n"
"    dd if=a: of=c:\\tmp\\image.bin        (RAWREAD, DSKIMG)\n"
"    dd if=a: of=b:                      (DISKCOPY)\n"
"Use 'probe' for unusual floppy sizes such as 1.68 meg\n";

static bool _probe_floppy, _changed_fpt;
static unsigned short _old_fpt_seg, _old_fpt_off;
/*////////////////////////////////////////////////////////////////////////////
	PROBING DISK GEOMETRY
////////////////////////////////////////////////////////////////////////////*/
/*****************************************************************************
*****************************************************************************/
static void new_fpt(void)
{
	unsigned short new_fpt_seg;
	regs_t regs;

	if(_changed_fpt)
		return;
/* save old FPT */
	_old_fpt_off = peek(0, 0x1E * 4 + 0);
	_old_fpt_seg = peek(0, 0x1E * 4 + 2);
/* alloc 1 paragraph (16 bytes) DOS memory */
	regs.h.ah = 0x48;
	regs.x.bx = 1;
	dos_int(0x21, &regs);
	new_fpt_seg = regs.x.ax;
/* copy old FPT to new */
	my_movedata(_old_fpt_seg, _old_fpt_off,
		new_fpt_seg, 0,
		11);
/* set sectors-per-track to inflated value */
	pokeb(new_fpt_seg, 4, 96);
/* install new FPT */
	poke(0, 0x1E * 4 + 0, 0);
	poke(0, 0x1E * 4 + 2, new_fpt_seg);
	_changed_fpt = true;
}
/*****************************************************************************
*****************************************************************************/
static void old_fpt(void)
{
	if(!_changed_fpt)
		return;
	poke(0, 0x1E * 4 + 0, _old_fpt_off);
	poke(0, 0x1E * 4 + 2, _old_fpt_seg);
}
/*****************************************************************************
*****************************************************************************/
static int dd_get_geom(file_t *file)
{
	unsigned short temp;
	union REGS regs;

/* first do INT 13h AH=08h to get number of drives */
	regs.h.ah = 0x08;
	if(file->int13_dev >= 0x80)
		regs.h.dl = 0x80;
	else
		regs.h.dl = 0;
	int86(0x13, &regs, &regs);
	if(regs.x.cflag)
	{
		printf("error getting drive count in dd_get_geom\n");
		return -1;
	}
	if((file->int13_dev & 0x7F) >= regs.h.dl)
	{
		printf("error: no such drive in dd_get_geom\n");
		return -1;
	}
	temp = regs.h.cl;
	temp <<= 2;
	temp |= regs.h.ch;

	file->bps = 512;
	file->cyls = temp + 1;
	file->heads = regs.h.dh + 1;
/* hard disk: use the sectors-per-track returned by INT 13h AH=08h */
	if(file->int13_dev >= 0x80)
		file->sects = regs.h.cl & 0x3F;
/* floppy disk, no probe: use sectors-per-track returned by INT 13h AH=08h */
	else if(!_probe_floppy)
		file->sects = regs.h.cl & 0x3F;
/* floppy disk, probed geometry. Use this for non-standard floppy sizes
like 1.68 meg (21 sectors per track), since INT 13h AH=08h is unreliable
in this case. */
	else
	{
		unsigned short sects, delta, old_err;
/* NOTE: 'try' is a C++ reserved word */
		unsigned char try, buffer[512];

/* install new floppy parameter table */
		new_fpt();
		printf("probing floppy geometry; please wait...\n");
AGAIN:
		delta = sects = 16;
		do
		{
			delta >>= 1;
			DEBUG(printf("sects=%d, delta=%d\n", sects, delta);)
			old_err = 0;
/* The floppy drive is easily confused by this probing.
Try each read up to 3 times before giving up. */
			for(try = 3; try != 0; try--)
			{
/* *** WARNING, WARNING -- biosdisk() doesn't return what
Turbo C online help says it returns. It returns the INT 13h
error value only, not the number of sectors moved. */
				temp = biosdisk(_DISK_READ, file->int13_dev,
					0/*head*/, 0/*track*/,
					sects, 1/*nsects*/, buffer);
				if(temp == 6)
				{
					DEBUG(printf("disk change, "
						"restarting...\n");)
					goto AGAIN;
				}
				else if(temp == 0)
				{
					sects += delta;
					break;
				}
				DEBUG(printf("\terror 0x%X\n", temp);)
				(void)biosdisk(_DISK_RESET, file->int13_dev,
					0, 0, 0, 0, 0);
/* don't decrement sects more than once */
				if(old_err == 0)
					sects -= delta;
				old_err = temp;
			}
		} while(delta != 0);
/* no, do this when the program exits
		old_fpt(); */
		(void)biosdisk(_DISK_RESET, file->int13_dev, 0, 0, 0, 0, 0);
		if(temp != 0)
			sects--;

		file->sects = sects;
	}
	printf("CHS=%u:%u:%u\n", file->cyls, file->heads, file->sects);
	return 0;
}
/*****************************************************************************
*****************************************************************************/
static int dd_rwdisk(file_t *file, int cmd, unsigned long lba,
		unsigned short nsects, unsigned char *buf)
{
	unsigned short cyl, head, sect;
	unsigned char try;
	int err;

	if(nsects == 0)
		return 0;
	if(lba * file->bps >= file->size)
	{
		printf("error: access beyond end of disk in dd_rwdisk\n");
		return -1;
	}
/* convert to CHS */
	sect = lba % file->sects + 1;
	lba /= file->sects;
	head = lba % file->heads;
	cyl = lba / file->heads;
	for(try = 3; try != 0; try--)
	{
		DEBUG(printf("dd_rwdisk: CHS=%u:%u:%u\n", cyl, head, sect);)
		err = biosdisk(cmd, file->int13_dev, head, cyl, sect,
			nsects, buf);
		if(err == 0 || err == 0x11)
			return 0;
		DEBUG(printf("disk error 0x%X in dd_rwdisk\n", err);)
	}
	printf("disk error 0x%X in dd_rwdisk\n", err);
	return -1;
}
/*////////////////////////////////////////////////////////////////////////////
	INPUT
////////////////////////////////////////////////////////////////////////////*/
/*****************************************************************************
*****************************************************************************/
static int dd_fill(file_t *file)
{
	int temp;

	if(!file->needs_fill)

⌨️ 快捷键说明

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