]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
(main): Accept new option, --sparse={never,auto,always},
authorJim Meyering <jim@meyering.net>
Fri, 22 Dec 1995 05:30:48 +0000 (05:30 +0000)
committerJim Meyering <jim@meyering.net>
Fri, 22 Dec 1995 05:30:48 +0000 (05:30 +0000)
to control creation of sparse files.
(copy_reg): Set local, make_holes, from global flag_sparse.
Include argmatch.h.

src/cp.c

index 553e93bf858af7a3bac9f0bfd54a290f6cda3a16..84385b641693e4c71d1aa8441ca6c37039a351d8 100644 (file)
--- a/src/cp.c
+++ b/src/cp.c
@@ -27,6 +27,7 @@
 #include "cp.h"
 #include "backupfile.h"
 #include "version.h"
+#include "argmatch.h"
 
 #ifndef _POSIX_VERSION
 uid_t geteuid ();
@@ -42,6 +43,25 @@ struct dir_attr
   struct dir_attr *next;
 };
 
+/* Control creation of sparse files (files with holes).  */
+enum Sparse_type
+{
+  /* Never create holes in DEST.  */
+  SPARSE_NEVER,
+
+  /* This is the default.  Use a crude (and sometimes inaccurate)
+     heuristic to determine if SOURCE has holes.  If so, try to create
+     holes in DEST.  */
+  SPARSE_AUTO,
+
+  /* For every sufficiently long sequence of bytes in SOURCE, try to
+     create a corresponding hole in DEST.  There is a performance penalty
+     here because CP has to search for holes in SRC.  But if the holes are
+     big enough, that penalty can be offset by the decrease in the amount
+     of data written to disk.   */
+  SPARSE_ALWAYS
+};
+
 int stat ();
 int lstat ();
 
@@ -121,6 +141,19 @@ static int flag_update = 0;
 /* If nonzero, display the names of the files before copying them. */
 static int flag_verbose = 0;
 
+static char const *const sparse_type_string[] =
+{
+  "never", "auto", "always", 0
+};
+
+static enum Sparse_type const sparse_type[] =
+{
+  SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS
+};
+
+/* Control creation of sparse files.  */
+static int flag_sparse = SPARSE_AUTO;
+
 /* The error code to return to the system. */
 static int exit_status = 0;
 
@@ -141,6 +174,7 @@ static struct option const long_opts[] =
   {"archive", no_argument, NULL, 'a'},
   {"backup", no_argument, NULL, 'b'},
   {"force", no_argument, NULL, 'f'},
+  {"sparse", required_argument, NULL, 2},
   {"interactive", no_argument, NULL, 'i'},
   {"link", no_argument, NULL, 'l'},
   {"no-dereference", no_argument, &flag_dereference, 0},
@@ -189,6 +223,21 @@ main (int argc, char **argv)
        case 0:
          break;
 
+       case 2:
+         {
+           int i;
+
+           /* --sparse={never,auto,always}  */
+           i = argmatch (optarg, sparse_type_string);
+           if (i < 0)
+             {
+               invalid_arg (_("sparse type"), optarg, i);
+               usage (2, NULL);
+             }
+           flag_sparse = sparse_type[i];
+         }
+         break;
+
        case 'a':               /* Like -dpR. */
          flag_dereference = 0;
          flag_preserve = 1;
@@ -1110,7 +1159,7 @@ copy_reg (char *src_path, char *dst_path)
   int return_val = 0;
   long n_read_total = 0;
   int last_write_made_hole = 0;
-  int make_holes = 0;
+  int make_holes = (flag_sparse == SPARSE_ALWAYS);
 
   source_desc = open (src_path, O_RDONLY);
   if (source_desc < 0)
@@ -1142,7 +1191,7 @@ copy_reg (char *src_path, char *dst_path)
   buf_size = ST_BLKSIZE (sb);
 
 #ifdef HAVE_ST_BLOCKS
-  if (S_ISREG (sb.st_mode))
+  if (flag_sparse == SPARSE_AUTO && S_ISREG (sb.st_mode))
     {
       /* Find out whether the file contains any sparse blocks. */