#include <stdio.h>

main(argc, argv)
	char *argv[];
{
	register char *buf;
	register int nbuf, got, now;
	int fd;
	long bytes;
	int reads, writes;
	int status;
	extern char *malloc();

	if(argc <= 1 || (nbuf = atoi(argv[1])) <= 0) {
		fprintf(stderr, "Usage: %s nbytes [ inputfile ]\n\
Read from file (default standard input), write to standard output\n\
in blocks of `nbytes' bytes each.  Like `dd obs=nbytes' but much faster\n",
		argv[0]);
		exit(1);
	}

	if(argc > 2) {
		if((fd = open(argv[2], 0)) < 0) {
			fprintf(stderr, "%s: cannot open input file %s: ",
				argv[0], argv[2]);
			exit(2);
		}
	} else {
		fd = 0;
	}

	if((buf = malloc(nbuf)) == NULL) {
		fprintf(stderr, "%s: cannot allocate %d bytes for I/O buffer: ",
			argv[0], nbuf);
		perror("");
		exit(3);
	}

	status = 0;
	reads = writes = 0;
	bytes = 0;

	got = 0;
	while((now = read(fd, &buf[got], nbuf - got)) > 0) {
		got += now;
		reads++;
		bytes += now;
		if(got == nbuf) {
			if((now = write(1, buf, nbuf)) != nbuf) {
				fprintf(stderr, "%s: error writing %d bytes (wrote %d)",
					argv[0], got, now);
				perror("");
				status = 4;
				goto done;
			}
			writes++;
			got = 0;
		}
	}
	if(now < 0) {
		fprintf(stderr, "%s: error reading %s: ", argv[0],
			fd == 0 ? "stdin" : argv[2]);
		perror("");
		status = 5;
	} else if(got > 0) {
		if((now = write(1, buf, got)) != got) {
			fprintf(stderr, "%s: error writing %d bytes (wrote %d): ",
				argv[0], got, now);
			perror("");
			status = 6;
		} else
			writes++;
	}
  done:
	fprintf(stderr, "%d bytes copied, %d input, %d output blocks\n",
		bytes, reads, writes);
	exit(status);
}
