182 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* vi: set sw=4 ts=4: */
 | 
						|
/*
 | 
						|
 * Mini dd implementation for busybox
 | 
						|
 *
 | 
						|
 * Copyright (C) 1999, 2000 by Lineo, inc.
 | 
						|
 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
 | 
						|
 *
 | 
						|
 * Based in part on code taken from sash. 
 | 
						|
 *   Copyright (c) 1999 by David I. Bell
 | 
						|
 *   Permission is granted to use, distribute, or modify this source,
 | 
						|
 *   provided that this copyright notice remains intact.
 | 
						|
 *
 | 
						|
 * Permission to distribute this code under the GPL has been granted.
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License as published by
 | 
						|
 * the Free Software Foundation; either version 2 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 | 
						|
 * General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
#include "busybox.h"
 | 
						|
#include <features.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <errno.h>
 | 
						|
#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1)
 | 
						|
#include <inttypes.h>
 | 
						|
#else
 | 
						|
typedef unsigned long long int uintmax_t;
 | 
						|
#endif
 | 
						|
 | 
						|
extern int dd_main(int argc, char **argv)
 | 
						|
{
 | 
						|
	char *inFile = NULL;
 | 
						|
	char *outFile = NULL;
 | 
						|
	int inFd;
 | 
						|
	int outFd;
 | 
						|
	int inCc = 0;
 | 
						|
	int outCc;
 | 
						|
	int trunc=TRUE;
 | 
						|
	int sync=FALSE;
 | 
						|
	long blockSize = 512,ibs;
 | 
						|
	uintmax_t skipBlocks = 0;
 | 
						|
	uintmax_t seekBlocks = 0;
 | 
						|
	uintmax_t count = (uintmax_t) - 1;
 | 
						|
	uintmax_t inTotal = 0;
 | 
						|
	uintmax_t outTotal = 0;
 | 
						|
	uintmax_t totalSize;
 | 
						|
 | 
						|
	unsigned char buf[BUFSIZ];
 | 
						|
	char *keyword = NULL;
 | 
						|
 | 
						|
	argc--;
 | 
						|
	argv++;
 | 
						|
 | 
						|
	/* Parse any options */
 | 
						|
	while (argc) {
 | 
						|
		if (inFile == NULL && (strncmp(*argv, "if", 2) == 0))
 | 
						|
			inFile = ((strchr(*argv, '=')) + 1);
 | 
						|
		else if (outFile == NULL && (strncmp(*argv, "of", 2) == 0))
 | 
						|
			outFile = ((strchr(*argv, '=')) + 1);
 | 
						|
		else if (strncmp("count", *argv, 5) == 0) {
 | 
						|
			count = atoi_w_units((strchr(*argv, '=')) + 1);
 | 
						|
			if (count < 0) {
 | 
						|
				error_msg("Bad count value %s\n", *argv);
 | 
						|
				goto usage;
 | 
						|
			}
 | 
						|
		} else if (strncmp(*argv, "bs", 2) == 0) {
 | 
						|
			blockSize = atoi_w_units((strchr(*argv, '=')) + 1);
 | 
						|
			if (blockSize <= 0) {
 | 
						|
				error_msg("Bad block size value %s\n", *argv);
 | 
						|
				goto usage;
 | 
						|
			}
 | 
						|
		} else if (strncmp(*argv, "skip", 4) == 0) {
 | 
						|
			skipBlocks = atoi_w_units((strchr(*argv, '=')) + 1);
 | 
						|
			if (skipBlocks <= 0) {
 | 
						|
				error_msg("Bad skip value %s\n", *argv);
 | 
						|
				goto usage;
 | 
						|
			}
 | 
						|
 | 
						|
		} else if (strncmp(*argv, "seek", 4) == 0) {
 | 
						|
			seekBlocks = atoi_w_units((strchr(*argv, '=')) + 1);
 | 
						|
			if (seekBlocks <= 0) {
 | 
						|
				error_msg("Bad seek value %s\n", *argv);
 | 
						|
				goto usage;
 | 
						|
			}
 | 
						|
		} else if (strncmp(*argv, "conv", 4) == 0) {
 | 
						|
			keyword = (strchr(*argv, '=') + 1);
 | 
						|
                	if (strcmp(keyword, "notrunc") == 0) 
 | 
						|
				trunc=FALSE;
 | 
						|
			if (strcmp(keyword, "sync") == 0) 
 | 
						|
				sync=TRUE;
 | 
						|
		} else {
 | 
						|
			goto usage;
 | 
						|
		}
 | 
						|
		argc--;
 | 
						|
		argv++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (inFile == NULL)
 | 
						|
		inFd = fileno(stdin);
 | 
						|
	else
 | 
						|
		inFd = open(inFile, 0);
 | 
						|
 | 
						|
	if (inFd < 0) {
 | 
						|
		/* Note that we are not freeing buf or closing
 | 
						|
		 * files here to save a few bytes. This exits
 | 
						|
		 * here anyways... */
 | 
						|
 | 
						|
		/* free(buf); */
 | 
						|
		perror_msg_and_die("%s", inFile);
 | 
						|
	}
 | 
						|
 | 
						|
	if (outFile == NULL)
 | 
						|
		outFd = fileno(stdout);
 | 
						|
	else
 | 
						|
		outFd = open(outFile, O_WRONLY | O_CREAT, 0666);
 | 
						|
 | 
						|
	if (outFd < 0) {
 | 
						|
		/* Note that we are not freeing buf or closing
 | 
						|
		 * files here to save a few bytes. This exits
 | 
						|
		 * here anyways... */
 | 
						|
 | 
						|
		/* close(inFd);
 | 
						|
		   free(buf); */
 | 
						|
		perror_msg_and_die("%s", outFile);
 | 
						|
	}
 | 
						|
 | 
						|
	lseek(inFd, (off_t) (skipBlocks * blockSize), SEEK_SET);
 | 
						|
	lseek(outFd, (off_t) (seekBlocks * blockSize), SEEK_SET);
 | 
						|
	totalSize=count*blockSize;
 | 
						|
 | 
						|
	ibs=blockSize;
 | 
						|
	if (ibs > BUFSIZ)
 | 
						|
		ibs=BUFSIZ;
 | 
						|
			
 | 
						|
	while (totalSize > outTotal) {
 | 
						|
		inCc = full_read(inFd, buf, ibs);
 | 
						|
		inTotal += inCc;
 | 
						|
		if ( (sync==TRUE) && (inCc>0) )
 | 
						|
			while (inCc<ibs)
 | 
						|
				buf[inCc++]='\0';
 | 
						|
 | 
						|
		if ((outCc = full_write(outFd, buf, inCc)) < 1){
 | 
						|
			if (outCc < 0 ){
 | 
						|
				perror("Error during write");
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		outTotal += outCc;
 | 
						|
        }
 | 
						|
	if (trunc == TRUE) {
 | 
						|
		ftruncate(outFd, lseek(outFd, 0, SEEK_CUR));
 | 
						|
	}
 | 
						|
	/* Note that we are not freeing memory or closing
 | 
						|
	 * files here, to save a few bytes. */
 | 
						|
#ifdef BB_FEATURE_CLEAN_UP
 | 
						|
	close(inFd);
 | 
						|
	close(outFd);
 | 
						|
#endif
 | 
						|
 | 
						|
	printf("%ld+%d records in\n", (long) (inTotal / blockSize),
 | 
						|
		   (inTotal % blockSize) != 0);
 | 
						|
	printf("%ld+%d records out\n", (long) (outTotal / blockSize),
 | 
						|
		   (outTotal % blockSize) != 0);
 | 
						|
	return EXIT_SUCCESS;
 | 
						|
  usage:
 | 
						|
 | 
						|
	usage(dd_usage);
 | 
						|
}
 |