首页 > 代码库 > Linux dd 源程序

Linux dd 源程序



#include "stdio.h"
#include "stdlib.h"
#include "sys/stat.h"
#include "sys/types.h"
#include "fcntl.h"

#define BLOCK_SIZE 512
#define BUF_SIZE   1024
#define TOTAL_BUF  (BUF_SIZE<<1)

typedef struct 
{
	char data[BUF_SIZE*2+1];
	int base,top;
	int length;
}buf_queue;

void do_dd(int infilefd ,int outfilefd ,int iperbytes ,int operbytes ,int cperbytes ,int totalblocks);
static inline int buf_empty(buf_queue *buf);
static inline int buf_length(buf_queue *buf);

int read2buf(int fd,buf_queue *buf,int size);
int writefrombuf(int fd,buf_queue *buf,int size);

int main(int argc,char **argv)
{
	int i;
	int iperbytes=BLOCK_SIZE,operbytes=BLOCK_SIZE,cperbytes=0;
	int totalblocks = -1,seekblocks=0,skipblocks=0;
	clock_t begin,end;
	off_t fbegin,fend;
	int noxfer=0;
	int infilefd,outfilefd;
	char *infile=NULL,*outfile=NULL,*iflags=NULL,*oflags=NULL;
	for(i=1;i<argc ;i++)
	{
		if(!strncmp(argv[i],"bs",strlen("bs")))
		{
			iperbytes = operbytes = atoi(argv[i]+strlen("bs")+1);
		}else if (!strncmp(argv[i],"cbs",strlen("cbs")))
		{
			cperbytes = atoi(argv[i]+strlen("cbs")+1);
		}else if (!strncmp(argv[i],"conv"))
		{
		}else if (!strncmp(argv[i],"count",strlen("count")))
		{
			totalblocks = atoi(argv[i]+strlen("count")+1);
		}else if (!strncmp(argv[i],"ibs",strlen("ibs")))
		{
			iperbytes = atoi(argv[i]+strlen("ibs")+1);
		}else if (!strncmp(argv[i],"obs",strlen("obs")))
		{
			operbytes = atoi(argv[i]+strlen("obs")+1);
		}else if (!strncmp(argv[i],"if",strlen("if")))
		{
			infile = argv[i]+strlen("if")+1;
		}else if (!strncmp(argv[i],"of",strlen("of")))
		{
			outfile = argv[i]+strlen("of")+1;
		}else if (!strncmp(argv[i],"iflag",strlen("iflag")))
		{
			iflags = argv[i]+strlen("iflag")+1;
		}else if (!strncmp(argv[i],"oflag",strlen("oflag")))
		{
			oflags = argv[i]+strlen("oflag")+1;
		}
		else if (!strncmp(argv[i],"seek",strlen("seek")))
		{
			seekblocks = atoi(argv[i] + strlen("seek")+1);
		}else if (!strncmp(argv[i],"skip",strlen("skip")))
		{
			skipblocks = atoi(argv[i] + strlen("skip")+1);
		}else if (!strncmp(argv[i],"status",strlen("status")))
		{
			noxfer =!strncmp(argv[i]+strlen("status")+1,"noxfer",strlen("noxfer"));
		}
	}
	
	
	if(infile)
	{
		if((infilefd = open(infile,O_RDONLY))== -1)
		{
			perror("open infile error : ");
			return -1;
		}
	}else
	{
		infilefd = fileno(stdin);
	}
	lseek(infilefd,skipblocks*BLOCK_SIZE,SEEK_SET);
	
	if(outfile)
	{
		if(seekblocks!=0)
		{
			outfilefd = open(outfile, O_APPEND | O_WRONLY);
		}else
		{
			outfilefd = open(outfile, O_CREAT|O_WRONLY|O_TRUNC,00660);
		}
		if(outfilefd == -1)
		{
			perror("open outfile error : ");
			close(infilefd);
			return -1;
		}
	}
	else
	{
		outfilefd = fileno(stdout);
	}
	lseek(outfilefd,seekblocks*BLOCK_SIZE,SEEK_SET);
	do_dd(infilefd,outfilefd,iperbytes,operbytes,cperbytes,totalblocks);
}

void do_dd(int infilefd ,int outfilefd ,int iperbytes ,int operbytes ,int cperbytes ,int totalblocks)
{
	buf_queue *buf;
	int readbytes = 0,writebytes =0;
	if( (iperbytes > (BUF_SIZE*2)) && (operbytes > (BUF_SIZE * 2)))
		iperbytes = operbytes = BUF_SIZE*2;
	else
	{
		if(iperbytes > BUF_SIZE)
			iperbytes = BUF_SIZE;
		if(operbytes > BUF_SIZE)
			operbytes = BUF_SIZE;
	}
	if((buf = (buf_queue* )malloc(sizeof(buf_queue)))==NULL)
		perror("malloc memory failed :");
	buf->base=buf->top=0;
	buf->length =0;
	readbytes = iperbytes;
	writebytes = operbytes;
	while(readbytes == iperbytes )
	{
		while((buf_empty(buf) >= iperbytes) && (readbytes == iperbytes) )
		{
			readbytes = read2buf(infilefd,buf,iperbytes);
		}
		while( buf_length(buf) >= operbytes && (writebytes == operbytes)) 
		{
			writefrombuf(outfilefd,buf,operbytes);
		}
	}
	writefrombuf(outfilefd,buf,buf_length(buf));	
}

inline int buf_empty(buf_queue *buf)
{
	return TOTAL_BUF-buf->length;
}

inline int buf_length(buf_queue *buf)
{
	return buf->length;
}

//read data into top and need the stuation is size < buf_empty;
int read2buf(int fd,buf_queue *buf,int size)
{
	int readbytes,totalread = 0,toread;
	if(size > (TOTAL_BUF-buf->top))
		toread = TOTAL_BUF - buf->top;
	else
		toread = size;
	while(toread)
	{
		if((readbytes = read(fd,buf->data+buf->top,toread)) == -1)
		{
			perror("read file error : ");
			return -1;
		}
		totalread += readbytes;
		buf->length +=readbytes;
		buf->top = (buf->top + readbytes) % TOTAL_BUF;
		if(readbytes != toread)
			return totalread;
		toread = size - toread;
		size = toread;
	}
	return totalread;
}

//read data into top and need the stuation is size < buf_empty;
int writefrombuf(int fd,buf_queue *buf,int size)
{
	int writebytes,totalwrite = 0,towrite;
	
	if(size > (TOTAL_BUF-buf->base))
		towrite = TOTAL_BUF - buf->base;
	else
		towrite = size;
	while(towrite)
	{
		if((writebytes = write(fd,buf->data+buf->base,towrite)) == -1)
		{
			perror("write error ");
			return -1;
		}
		totalwrite += writebytes;
		buf->length-=writebytes;
		buf->base = (buf->base + writebytes) % TOTAL_BUF;
		if(writebytes != towrite)
			return totalwrite;
		towrite = size - towrite;
		size = towrite;
	}
	return totalwrite;
}

/*
//read data into top and need the stuation is size < buf_empty;
int read2buf(int fd,char *buf,char *base,char *top,int size)
{
	int toread = 0,readbytes = 0;
	if(top > base)
	{
		toread = buf + BUF_SIZE - top
		if(size <= toread)
		{
			toread = size;
			readbytes = read(fd,top,toread);
			top = top + ((top - buf + readbytes) % BUF_SIZE)
			return readbytes;
		}else
		{
			readbytes = read(fd,top,toread);
			top = top + ((top - buf + readbytes) % BUF_SIZE)
			if(readbytes != toread)
				return readbytes;
			else
			{
				toread = size-toread;
				readbytes = read(fd,top,toread);
				top = top + ((top - buf + readbytes) % BUF_SIZE)
				return size-(toread - size)
			}
		}
	}
	else
	{
		readbytes = read(fd,top,size);
		top = top + ((top - buf + readbytes) % BUF_SIZE)
		return readbytes;
	}
}
*/


Linux dd 源程序