summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1995-12-22 05:30:48 +0000
committerJim Meyering <jim@meyering.net>1995-12-22 05:30:48 +0000
commit654ad9e596595ecb17fabe34fe9595a765b6adee (patch)
treef5620787bdf81cd266f7f1bd009b907397afc1ae /src
parent8cff7ef2b9ff9ee57fedbb21af1a7fe92afa9dbb (diff)
downloadcoreutils-654ad9e596595ecb17fabe34fe9595a765b6adee.tar.xz
(main): Accept new option, --sparse={never,auto,always},
to control creation of sparse files. (copy_reg): Set local, make_holes, from global flag_sparse. Include argmatch.h.
Diffstat (limited to 'src')
-rw-r--r--src/cp.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/src/cp.c b/src/cp.c
index 553e93bf8..84385b641 100644
--- 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. */