#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;
}
}
*/原文:http://990487026.blog.51cto.com/10133282/1937255