* archival/bunzip2.c (bunzip2_main): Do not remove files if writing to standard
[oweals/busybox.git] / coreutils / dd.c
index 1618dd102a81c50a8442691136ff169496c80936..09e6cccc72ff9c7be988acc4d5869fc5e16aac55 100644 (file)
@@ -3,7 +3,7 @@
  * Mini dd implementation for busybox
  *
  *
- * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
+ * Copyright (C) 2000,2001  Matt Kraai
  *
  * 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
@@ -22,6 +22,7 @@
  */
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -45,12 +46,11 @@ static const struct suffix_mult dd_suffixes[] = {
 
 int dd_main(int argc, char **argv)
 {
-       int i, ifd, ofd, oflag, sync = FALSE, trunc = TRUE;
+       int i, ifd, ofd, oflag, sync_flag = FALSE, trunc = TRUE;
        size_t in_full = 0, in_part = 0, out_full = 0, out_part = 0;
        size_t bs = 512, count = -1;
        ssize_t n;
        off_t seek = 0, skip = 0;
-       FILE *statusfp;
        char *infile = NULL, *outfile = NULL, *buf;
 
        for (i = 1; i < argc; i++) {
@@ -73,7 +73,7 @@ int dd_main(int argc, char **argv)
                                        trunc = FALSE;
                                        buf += 7;
                                } else if (strncmp("sync", buf, 4) == 0) {
-                                       sync = TRUE;
+                                       sync_flag = TRUE;
                                        buf += 4;
                                } else {
                                        error_msg_and_die("invalid conversion `%s'", argv[i]+5);
@@ -107,15 +107,17 @@ int dd_main(int argc, char **argv)
                        perror_msg_and_die("%s", outfile);
 
                if (seek && trunc) {
-                       if (ftruncate(ofd, seek * bs) < 0)
-                               perror_msg_and_die("%s", outfile);
-               }
+                       if (ftruncate(ofd, seek * bs) < 0) {
+                               struct stat st;
 
-               statusfp = stdout;
+                               if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
+                                               S_ISDIR (st.st_mode))
+                                       perror_msg_and_die("%s", outfile);
+                       }
+               }
        } else {
                ofd = STDOUT_FILENO;
                outfile = "standard output";
-               statusfp = stderr;
        }
 
        if (skip) {
@@ -138,7 +140,7 @@ int dd_main(int argc, char **argv)
                        in_full++;
                else
                        in_part++;
-               if (sync) {
+               if (sync_flag) {
                        memset(buf + n, '\0', bs - n);
                        n = bs;
                }
@@ -151,8 +153,14 @@ int dd_main(int argc, char **argv)
                        out_part++;
        }
 
-       fprintf(statusfp, "%d+%d records in\n", in_full, in_part);
-       fprintf(statusfp, "%d+%d records out\n", out_full, out_part);
+       if (close (ifd) < 0)
+               perror_msg_and_die("%s", infile);
+
+       if (close (ofd) < 0)
+               perror_msg_and_die("%s", outfile);
+
+       fprintf(stderr, "%ld+%ld records in\n", (long)in_full, (long)in_part);
+       fprintf(stderr, "%ld+%ld records out\n", (long)out_full, (long)out_part);
 
        return EXIT_SUCCESS;
 }