Patch from Matt Kraai to fix an infinate loop with ls -aR
[oweals/busybox.git] / coreutils / dd.c
index bc01eedbfaab9e4dfc5df26387ac05ae3dcdc3b9..6868a913e811aa5e1b198eca2f80fa167e2419f4 100644 (file)
@@ -1,13 +1,14 @@
+/* vi: set sw=4 ts=4: */
 /*
  * Mini dd implementation for busybox
  *
- * Copyright (C) 1999 by Lineo, inc.
+ * 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.
+ * 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.
  *
@@ -28,7 +29,7 @@
  */
 
 
-#include "internal.h"
+#include "busybox.h"
 #include <features.h>
 #include <stdio.h>
 #include <fcntl.h>
 typedef unsigned long long int uintmax_t;
 #endif
 
-static const char dd_usage[] =
-"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"
-"\tbs=n\tread and write N BYTES at a time\n"
-"\tcount=n\tcopy only n input blocks\n"
-//"\tskip=n\tskip n input blocks\n"
-"\n"
-"BYTES may be suffixed by w (x2), k (x1024), b (x512), or m (x1024^2).\n";
-
-
-
-extern int dd_main (int argc, char **argv)
+extern int dd_main(int argc, char **argv)
 {
-    const char *inFile = NULL;
-    const char *outFile = NULL;
-    char *cp;
-    int inFd;
-    int outFd;
-    int inCc = 0;
-    int outCc;
-    size_t blockSize = 512;
-    //uintmax_t skipBlocks = 0;
-    uintmax_t count = (uintmax_t)-1;
-    uintmax_t intotal;
-    uintmax_t outTotal;
-    unsigned char *buf;
+       char *inFile = NULL;
+       char *outFile = NULL;
+       int inFd;
+       int outFd;
+       int inCc = 0;
+       int outCc;
+       int trunc=TRUE;
+       long blockSize = 512;
+       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;
+       uintmax_t readSize;
+       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 = getNum ((strchr(*argv, '='))+1);
-           if (count <= 0) {
-               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 %s\n", *argv);
-               goto usage;
-           }
-       }
-#if 0
-       else if (strncmp(*argv, "skip", 4) == 0) {
-           skipBlocks = atoi( *argv); 
-           if (skipBlocks <= 0) {
-               fprintf (stderr, "Bad skip value %d\n", skipBlocks);
-               goto usage;
-           }
-
-       }
-#endif
-       else {
-           goto usage;
-       }
        argc--;
        argv++;
-    }
 
-    buf = malloc (blockSize);
-    if (buf == NULL) {
-       fprintf (stderr, "Cannot allocate buffer\n");
-       exit( FALSE);
-    }
+       /* 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 = getNum((strchr(*argv, '=')) + 1);
+                       if (count < 0) {
+                               errorMsg("Bad count value %s\n", *argv);
+                               goto usage;
+                       }
+               } else if (strncmp(*argv, "bs", 2) == 0) {
+                       blockSize = getNum((strchr(*argv, '=')) + 1);
+                       if (blockSize <= 0) {
+                               errorMsg("Bad block size value %s\n", *argv);
+                               goto usage;
+                       }
+               } else if (strncmp(*argv, "skip", 4) == 0) {
+                       skipBlocks = getNum((strchr(*argv, '=')) + 1);
+                       if (skipBlocks <= 0) {
+                               errorMsg("Bad skip value %s\n", *argv);
+                               goto usage;
+                       }
+
+               } else if (strncmp(*argv, "seek", 4) == 0) {
+                       seekBlocks = getNum((strchr(*argv, '=')) + 1);
+                       if (seekBlocks <= 0) {
+                               errorMsg("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;
+               } else {
+                       goto usage;
+               }
+               argc--;
+               argv++;
+       }
 
-    intotal = 0;
-    outTotal = 0;
+       if (inFile == NULL)
+               inFd = fileno(stdin);
+       else
+               inFd = open(inFile, 0);
 
-    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... */
 
-    if (inFd < 0) {
-       perror (inFile);
-       free (buf);
-       exit( FALSE);
-    }
+               /* free(buf); */
+               fatalPerror("%s", inFile);
+       }
 
-    if (outFile == NULL)
-       outFd = fileno(stdout);
-    else
-       outFd = creat (outFile, 0666);
+       if (outFile == NULL)
+               outFd = fileno(stdout);
+       else
+               outFd = open(outFile, O_WRONLY | O_CREAT, 0666);
 
-    if (outFd < 0) {
-       perror (outFile);
-       close (inFd);
-       free (buf);
-       exit( FALSE);
-    }
+       if (outFd < 0) {
+               /* Note that we are not freeing buf or closing
+                * files here to save a few bytes. This exits
+                * here anyways... */
 
-    //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;
+               /* close(inFd);
+                  free(buf); */
+               fatalPerror("%s", outFile);
        }
-       intotal += inCc;
-       cp = buf;
 
-       while (intotal > outTotal) {
-           if (outTotal + inCc > count * blockSize)
-               inCc = count * blockSize - outTotal;
-           outCc = write (outFd, cp, inCc);
-           if (outCc < 0) {
-               perror (outFile);
-               goto cleanup;
-           } else if (outCc == 0) {
-               goto cleanup;
-           }
-
-           inCc -= outCc;
-           cp += outCc;
-           outTotal += outCc;
+       lseek(inFd, (off_t) (skipBlocks * blockSize), SEEK_SET);
+       lseek(outFd, (off_t) (seekBlocks * blockSize), SEEK_SET);
+       totalSize=count*blockSize;
+       while ((readSize = totalSize - inTotal) > 0) {
+               if (readSize > BUFSIZ)
+                       readSize=BUFSIZ;
+               inCc = fullRead(inFd, buf, readSize);
+               inTotal += inCc;
+               if ((outCc = fullWrite(outFd, buf, inCc)) < 1)
+                       break;
+               outTotal += outCc;
+        }
+       if (trunc == TRUE) {
+               ftruncate(outFd, lseek(outFd, 0, SEEK_CUR));
        }
-    }
-
-    if (inCc < 0)
-       perror (inFile);
-
-  cleanup:
-    close (inFd);
-    close (outFd);
-    free (buf);
+       /* 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);
-    exit( TRUE);
+       printf("%ld+%d records in\n", (long) (inTotal / blockSize),
+                  (inTotal % blockSize) != 0);
+       printf("%ld+%d records out\n", (long) (outTotal / blockSize),
+                  (outTotal % blockSize) != 0);
+       exit(TRUE);
   usage:
 
-    usage( dd_usage);
+       usage(dd_usage);
 }
-
-