work in progress...
[oweals/busybox.git] / dd.c
diff --git a/dd.c b/dd.c
index 33c45940ec7b7ab2a58fca523b100fc8c9d67949..bc01eedbfaab9e4dfc5df26387ac05ae3dcdc3b9 100644 (file)
--- a/dd.c
+++ b/dd.c
 
 
 #include "internal.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
 
 static const char dd_usage[] =
-"dd [if=name] [of=name] [bs=n] [count=n]\n"
+"dd [if=name] [of=name] [bs=n] [count=n]\n\n"
 "Copy a file, converting and formatting according to options\n\n"
 "\tif=FILE\tread from FILE instead of stdin\n"
 "\tof=FILE\twrite to FILE instead of stout\n"
@@ -42,77 +48,26 @@ static const char dd_usage[] =
 "\tcount=n\tcopy only n input blocks\n"
 //"\tskip=n\tskip n input blocks\n"
 "\n"
-"BYTES may be suffixed: by k for x1024, b for x512, and w for x2.\n";
-
-
-
-
-/*
- * Read a number with a possible multiplier.
- * Returns -1 if the number format is illegal.
- */
-static long getNum (const char *cp)
-{
-    long value;
-
-    if (!isDecimal (*cp))
-       return -1;
-
-    value = 0;
-
-    while (isDecimal (*cp))
-       value = value * 10 + *cp++ - '0';
-
-    switch (*cp++) {
-    case 'k':
-       value *= 1024;
-       break;
+"BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n";
 
-    case 'b':
-       value *= 512;
-       break;
-
-    case 'w':
-       value *= 2;
-       break;
-
-    case '\0':
-       return value;
-
-    default:
-       return -1;
-    }
-
-    if (*cp)
-       return -1;
-
-    return value;
-}
 
 
 extern int dd_main (int argc, char **argv)
 {
-    const char *inFile;
-    const char *outFile;
+    const char *inFile = NULL;
+    const char *outFile = NULL;
     char *cp;
     int inFd;
     int outFd;
     int inCc = 0;
     int outCc;
-    int skipBlocks;
-    int blockSize;
-    long count;
-    long intotal;
-    long outTotal;
+    size_t blockSize = 512;
+    //uintmax_t skipBlocks = 0;
+    uintmax_t count = (uintmax_t)-1;
+    uintmax_t intotal;
+    uintmax_t outTotal;
     unsigned char *buf;
 
-    inFile = NULL;
-    outFile = NULL;
-    blockSize = 512;
-    skipBlocks = 0;
-    count = 1;
-
-
     argc--;
     argv++;
 
@@ -125,14 +80,14 @@ extern int dd_main (int argc, char **argv)
        else if (strncmp("count", *argv, 5) == 0) {
            count = getNum ((strchr(*argv, '='))+1);
            if (count <= 0) {
-               fprintf (stderr, "Bad count value %ld\n", count);
+               fprintf (stderr, "Bad count value %s\n", *argv);
                goto usage;
            }
        }
        else if (strncmp(*argv, "bs", 2) == 0) {
            blockSize = getNum ((strchr(*argv, '='))+1);
            if (blockSize <= 0) {
-               fprintf (stderr, "Bad block size value %d\n", blockSize);
+               fprintf (stderr, "Bad block size value %s\n", *argv);
                goto usage;
            }
        }
@@ -152,8 +107,6 @@ extern int dd_main (int argc, char **argv)
        argc--;
        argv++;
     }
-    if ( inFile == NULL || outFile == NULL)
-       goto usage;
 
     buf = malloc (blockSize);
     if (buf == NULL) {
@@ -165,7 +118,7 @@ extern int dd_main (int argc, char **argv)
     outTotal = 0;
 
     if (inFile == NULL)
-       inFd = STDIN;
+       inFd = fileno(stdin);
     else
        inFd = open (inFile, 0);
 
@@ -176,7 +129,7 @@ extern int dd_main (int argc, char **argv)
     }
 
     if (outFile == NULL)
-       outFd = STDOUT;
+       outFd = fileno(stdout);
     else
        outFd = creat (outFile, 0666);
 
@@ -188,11 +141,17 @@ extern int dd_main (int argc, char **argv)
     }
 
     //lseek(inFd, skipBlocks*blockSize, SEEK_SET);
+    //
+    //TODO: Convert to using fullRead & fullWrite
+    // from utilitity.c
+    //  -Erik
     while (outTotal < count * blockSize) {
        inCc = read (inFd, buf, blockSize);
        if (inCc < 0) {
            perror (inFile);
            goto cleanup;
+       } else if (inCc == 0) {
+           goto cleanup;
        }
        intotal += inCc;
        cp = buf;
@@ -204,6 +163,8 @@ extern int dd_main (int argc, char **argv)
            if (outCc < 0) {
                perror (outFile);
                goto cleanup;
+           } else if (outCc == 0) {
+               goto cleanup;
            }
 
            inCc -= outCc;
@@ -220,15 +181,14 @@ extern int dd_main (int argc, char **argv)
     close (outFd);
     free (buf);
 
-    printf ("%ld+%d records in\n", intotal / blockSize,
+    printf ("%ld+%d records in\n", (long)(intotal / blockSize),
            (intotal % blockSize) != 0);
-    printf ("%ld+%d records out\n", outTotal / blockSize,
+    printf ("%ld+%d records out\n", (long)(outTotal / blockSize),
            (outTotal % blockSize) != 0);
     exit( TRUE);
   usage:
 
-    fprintf (stderr, "%s", dd_usage);
-    exit( FALSE);
+    usage( dd_usage);
 }